v0.1.0
This commit is contained in:
210
src/pages/Register.jsx
Normal file
210
src/pages/Register.jsx
Normal file
@ -0,0 +1,210 @@
|
||||
import React, { useState } from 'react'
|
||||
import { Link, Navigate } from 'react-router-dom'
|
||||
import { useAuth } from '../contexts/AuthContext'
|
||||
import {
|
||||
Container,
|
||||
Paper,
|
||||
TextField,
|
||||
Button,
|
||||
Typography,
|
||||
Box,
|
||||
Alert,
|
||||
InputAdornment,
|
||||
IconButton
|
||||
} from '@mui/material'
|
||||
import { Visibility, VisibilityOff, PersonAdd as RegisterIcon } from '@mui/icons-material'
|
||||
|
||||
const Register = () => {
|
||||
const { register, user } = useAuth()
|
||||
const [formData, setFormData] = useState({
|
||||
username: '',
|
||||
email: '',
|
||||
password: '',
|
||||
confirmPassword: ''
|
||||
})
|
||||
const [showPassword, setShowPassword] = useState(false)
|
||||
const [showConfirmPassword, setShowConfirmPassword] = useState(false)
|
||||
const [error, setError] = useState('')
|
||||
const [loading, setLoading] = useState(false)
|
||||
|
||||
if (user) {
|
||||
return <Navigate to="/dashboard" replace />
|
||||
}
|
||||
|
||||
const handleChange = (e) => {
|
||||
setFormData({
|
||||
...formData,
|
||||
[e.target.name]: e.target.value
|
||||
})
|
||||
}
|
||||
|
||||
const validateForm = () => {
|
||||
if (formData.password !== formData.confirmPassword) {
|
||||
setError('两次输入的密码不一致')
|
||||
return false
|
||||
}
|
||||
if (formData.password.length < 6) {
|
||||
setError('密码长度至少6位')
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
const handleSubmit = async (e) => {
|
||||
e.preventDefault()
|
||||
setError('')
|
||||
|
||||
if (!validateForm()) {
|
||||
return
|
||||
}
|
||||
|
||||
setLoading(true)
|
||||
|
||||
const { confirmPassword, ...userData } = formData
|
||||
const result = await register(userData)
|
||||
if (!result.success) {
|
||||
setError(result.message)
|
||||
}
|
||||
setLoading(false)
|
||||
}
|
||||
|
||||
return (
|
||||
<Container maxWidth="sm">
|
||||
<Box
|
||||
sx={{
|
||||
minHeight: '100vh',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center'
|
||||
}}
|
||||
>
|
||||
<Paper
|
||||
elevation={3}
|
||||
sx={{
|
||||
p: 4,
|
||||
width: '100%',
|
||||
maxWidth: 400
|
||||
}}
|
||||
>
|
||||
<Box textAlign="center" mb={3}>
|
||||
<RegisterIcon sx={{ fontSize: 48, color: 'primary.main', mb: 2 }} />
|
||||
<Typography variant="h4" component="h1" gutterBottom>
|
||||
注册
|
||||
</Typography>
|
||||
<Typography variant="body2" color="text.secondary">
|
||||
创建您的账户
|
||||
</Typography>
|
||||
</Box>
|
||||
|
||||
{error && (
|
||||
<Alert severity="error" sx={{ mb: 2 }}>
|
||||
{error}
|
||||
</Alert>
|
||||
)}
|
||||
|
||||
<form onSubmit={handleSubmit}>
|
||||
<TextField
|
||||
fullWidth
|
||||
label="用户名"
|
||||
name="username"
|
||||
value={formData.username}
|
||||
onChange={handleChange}
|
||||
margin="normal"
|
||||
required
|
||||
autoComplete="username"
|
||||
/>
|
||||
|
||||
<TextField
|
||||
fullWidth
|
||||
label="邮箱"
|
||||
name="email"
|
||||
type="email"
|
||||
value={formData.email}
|
||||
onChange={handleChange}
|
||||
margin="normal"
|
||||
required
|
||||
autoComplete="email"
|
||||
/>
|
||||
|
||||
<TextField
|
||||
fullWidth
|
||||
label="密码"
|
||||
name="password"
|
||||
type={showPassword ? 'text' : 'password'}
|
||||
value={formData.password}
|
||||
onChange={handleChange}
|
||||
margin="normal"
|
||||
required
|
||||
autoComplete="new-password"
|
||||
InputProps={{
|
||||
endAdornment: (
|
||||
<InputAdornment position="end">
|
||||
<IconButton
|
||||
onClick={() => setShowPassword(!showPassword)}
|
||||
edge="end"
|
||||
>
|
||||
{showPassword ? <VisibilityOff /> : <Visibility />}
|
||||
</IconButton>
|
||||
</InputAdornment>
|
||||
)
|
||||
}}
|
||||
/>
|
||||
|
||||
<TextField
|
||||
fullWidth
|
||||
label="确认密码"
|
||||
name="confirmPassword"
|
||||
type={showConfirmPassword ? 'text' : 'password'}
|
||||
value={formData.confirmPassword}
|
||||
onChange={handleChange}
|
||||
margin="normal"
|
||||
required
|
||||
autoComplete="new-password"
|
||||
InputProps={{
|
||||
endAdornment: (
|
||||
<InputAdornment position="end">
|
||||
<IconButton
|
||||
onClick={() => setShowConfirmPassword(!showConfirmPassword)}
|
||||
edge="end"
|
||||
>
|
||||
{showConfirmPassword ? <VisibilityOff /> : <Visibility />}
|
||||
</IconButton>
|
||||
</InputAdornment>
|
||||
)
|
||||
}}
|
||||
/>
|
||||
|
||||
<Button
|
||||
type="submit"
|
||||
fullWidth
|
||||
variant="contained"
|
||||
size="large"
|
||||
disabled={loading}
|
||||
sx={{ mt: 3, mb: 2 }}
|
||||
>
|
||||
{loading ? '注册中...' : '注册'}
|
||||
</Button>
|
||||
|
||||
<Box textAlign="center">
|
||||
<Typography variant="body2">
|
||||
已有账户?{' '}
|
||||
<Link to="/login" style={{ textDecoration: 'none' }}>
|
||||
<Typography
|
||||
component="span"
|
||||
variant="body2"
|
||||
color="primary"
|
||||
sx={{ cursor: 'pointer' }}
|
||||
>
|
||||
立即登录
|
||||
</Typography>
|
||||
</Link>
|
||||
</Typography>
|
||||
</Box>
|
||||
</form>
|
||||
</Paper>
|
||||
</Box>
|
||||
</Container>
|
||||
)
|
||||
}
|
||||
|
||||
export default Register
|
Reference in New Issue
Block a user