blob: c4fb06d4b90e1b85be23689275d2ca5605857109 [file] [log] [blame]
ybtda5978b2025-05-31 15:58:05 +08001// src/features/auth/pages/RegisterPage.jsx
2import React, { useState } from 'react';
3import { useNavigate, Link } from 'react-router-dom';
4import { Form, Input, Button, Card, Typography, Divider, message } from 'antd';
5import { UserOutlined, LockOutlined, MailOutlined } from '@ant-design/icons';
6import { useAuth } from '../contexts/AuthContext'; // 使用新的 AuthContext
7
8const { Title, Text } = Typography;
9
10const RegisterPage = () => {
11 const [loading, setLoading] = useState(false);
12 const navigate = useNavigate();
13 const { register, isAuthenticated, user } = useAuth(); // 从 Context 获取 register 方法
14
15 React.useEffect(() => {
16 if (isAuthenticated && user) {
17 navigate('/'); // 如果已登录,跳转到首页
18 }
19 }, [isAuthenticated, user, navigate]);
20
21 const onFinish = async (values) => {
22 setLoading(true);
23 try {
24 // 从表单值中移除 'confirm' 字段,因为它不需要发送到后端
25 const { confirm, ...registrationData } = values;
26 await register(registrationData); // 使用 context 中的 register 方法
27 message.success('注册成功!将跳转到登录页...');
28 setTimeout(() => {
29 navigate('/login');
30 }, 1500); // 延迟跳转,让用户看到成功消息
31 } catch (error) {
32 // 错误消息由 AuthContext 中的 register 方法处理或 request 拦截器处理
33 console.error('Registration page error:', error);
34 // message.error(error.message || '注册失败,请重试'); // 如果 Context 未处理错误提示
35 } finally {
36 setLoading(false);
37 }
38 };
39
40 return (
41 <div className="flex justify-center items-center min-h-screen bg-slate-100 p-4">
42 <Card className="w-full max-w-md shadow-lg rounded-lg">
43 <div className="text-center mb-8">
44 <Title level={2} className="!mb-2 text-slate-700">创建您的账户</Title>
45 <Text type="secondary">加入我们的PT社区</Text>
46 </div>
47
48 <Form
49 name="register_form"
50 onFinish={onFinish}
51 size="large"
52 layout="vertical"
53 className="space-y-4" // 调整表单项间距
54 >
55 <Form.Item
56 name="username"
57 rules={[
58 { required: true, message: '请输入您的用户名!' },
59 { min: 3, message: '用户名至少需要3个字符' },
60 { max: 20, message: '用户名不能超过20个字符' },
61 { pattern: /^[a-zA-Z0-9_]+$/, message: '用户名只能包含字母、数字和下划线' }
62 ]}
63 hasFeedback // 显示校验状态图标
64 >
65 <Input prefix={<UserOutlined />} placeholder="用户名" />
66 </Form.Item>
67
68 <Form.Item
69 name="email"
70 rules={[
71 { required: true, message: '请输入您的邮箱地址!' },
72 { type: 'email', message: '请输入一个有效的邮箱地址!' }
73 ]}
74 hasFeedback
75 >
76 <Input prefix={<MailOutlined />} placeholder="邮箱" />
77 </Form.Item>
78
79 <Form.Item
80 name="password"
81 rules={[
82 { required: true, message: '请输入您的密码!' },
83 { min: 6, message: '密码至少需要6个字符' }
84 // 可以添加更复杂的密码强度校验规则
85 ]}
86 hasFeedback
87 >
88 <Input.Password prefix={<LockOutlined />} placeholder="密码" />
89 </Form.Item>
90
91 <Form.Item
92 name="confirm"
93 dependencies={['password']}
94 hasFeedback
95 rules={[
96 { required: true, message: '请再次输入您的密码!' },
97 ({ getFieldValue }) => ({
98 validator(_, value) {
99 if (!value || getFieldValue('password') === value) {
100 return Promise.resolve();
101 }
102 return Promise.reject(new Error('两次输入的密码不一致!'));
103 },
104 }),
105 ]}
106 >
107 <Input.Password prefix={<LockOutlined />} placeholder="确认密码" />
108 </Form.Item>
109
110 <Form.Item className="!mt-6"> {/* 增加注册按钮的上边距 */}
111 <Button type="primary" htmlType="submit" className="w-full !text-base" loading={loading}>
112
113 </Button>
114 </Form.Item>
115
116 <Divider plain><span className="text-slate-500">或</span></Divider>
117
118 <div className="text-center">
119 <Text type="secondary" className="mr-1">已经有账户了?</Text>
120 <Link to="/login" className="font-medium text-blue-600 hover:text-blue-700 hover:underline">
121 前往登录
122 </Link>
123 </div>
124 </Form>
125 </Card>
126 </div>
127 );
128};
129
130export default RegisterPage;