Files
QQuiz/frontend/src/pages/Register.jsx
handsomezhuzhu c5ecbeaec2 🎉 Initial commit: QQuiz - 智能刷题与题库管理平台
## 功能特性

 **核心功能**
- 多文件上传与智能去重(基于 content_hash)
- 异步文档解析(支持 TXT/PDF/DOCX/XLSX)
- AI 智能题目提取与评分(OpenAI/Anthropic/Qwen)
- 断点续做与进度管理
- 自动错题本收集

 **技术栈**
- Backend: FastAPI + SQLAlchemy 2.0 + PostgreSQL
- Frontend: React 18 + Vite + Tailwind CSS
- Deployment: Docker Compose

 **项目结构**
- 53 个文件
- 完整的前后端分离架构
- Docker/源码双模部署支持

🚀 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-01 12:39:46 +08:00

160 lines
4.8 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* Register Page
*/
import React, { useState } from 'react'
import { Link, useNavigate } from 'react-router-dom'
import { useAuth } from '../context/AuthContext'
import { BookOpen } from 'lucide-react'
export const Register = () => {
const navigate = useNavigate()
const { register } = useAuth()
const [formData, setFormData] = useState({
username: '',
password: '',
confirmPassword: ''
})
const [loading, setLoading] = useState(false)
const [error, setError] = useState('')
const handleSubmit = async (e) => {
e.preventDefault()
setError('')
// Validate
if (formData.password !== formData.confirmPassword) {
setError('两次输入的密码不一致')
return
}
if (formData.password.length < 6) {
setError('密码至少需要 6 位')
return
}
setLoading(true)
try {
const success = await register(formData.username, formData.password)
if (success) {
navigate('/login')
}
} finally {
setLoading(false)
}
}
const handleChange = (e) => {
setFormData({
...formData,
[e.target.name]: e.target.value
})
setError('')
}
return (
<div className="min-h-screen bg-gradient-to-br from-primary-50 to-primary-100 flex items-center justify-center p-4">
<div className="max-w-md w-full">
{/* Logo and Title */}
<div className="text-center mb-8">
<div className="flex justify-center mb-4">
<div className="bg-primary-600 p-3 rounded-2xl">
<BookOpen className="h-10 w-10 text-white" />
</div>
</div>
<h1 className="text-3xl font-bold text-gray-900">QQuiz</h1>
<p className="text-gray-600 mt-2">智能刷题与题库管理平台</p>
</div>
{/* Register Form */}
<div className="bg-white rounded-2xl shadow-xl p-8">
<h2 className="text-2xl font-bold text-gray-900 mb-6">注册</h2>
<form onSubmit={handleSubmit} className="space-y-6">
{/* Error Message */}
{error && (
<div className="bg-red-50 text-red-600 px-4 py-3 rounded-lg text-sm">
{error}
</div>
)}
{/* Username */}
<div>
<label className="block text-sm font-medium text-gray-700 mb-2">
用户名
</label>
<input
type="text"
name="username"
value={formData.username}
onChange={handleChange}
required
minLength={3}
maxLength={50}
className="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-primary-500 focus:border-transparent"
placeholder="3-50 位字符"
/>
</div>
{/* Password */}
<div>
<label className="block text-sm font-medium text-gray-700 mb-2">
密码
</label>
<input
type="password"
name="password"
value={formData.password}
onChange={handleChange}
required
minLength={6}
className="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-primary-500 focus:border-transparent"
placeholder="至少 6 位"
/>
</div>
{/* Confirm Password */}
<div>
<label className="block text-sm font-medium text-gray-700 mb-2">
确认密码
</label>
<input
type="password"
name="confirmPassword"
value={formData.confirmPassword}
onChange={handleChange}
required
minLength={6}
className="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-primary-500 focus:border-transparent"
placeholder="再次输入密码"
/>
</div>
{/* Submit Button */}
<button
type="submit"
disabled={loading}
className="w-full bg-primary-600 text-white py-3 rounded-lg font-medium hover:bg-primary-700 transition-colors disabled:opacity-50 disabled:cursor-not-allowed"
>
{loading ? '注册中...' : '注册'}
</button>
</form>
{/* Login Link */}
<div className="mt-6 text-center">
<p className="text-gray-600">
已有账号{' '}
<Link to="/login" className="text-primary-600 font-medium hover:text-primary-700">
立即登录
</Link>
</p>
</div>
</div>
</div>
</div>
)
}
export default Register