blob: 08edc701927a3c38eb8e5331853c672aedb41ee7 [file] [log] [blame]
22301014bc4616f2025-06-03 16:59:44 +08001import { useEffect, useState } from 'react';
2import { LockOutlined, MailOutlined, NumberOutlined, UserOutlined } from '@ant-design/icons';
2230102371ee1c92025-06-05 16:18:32 +08003import {Button, Checkbox, Form, Input, Space} from 'antd';
22301014bc4616f2025-06-03 16:59:44 +08004import { NavLink } from 'react-router';
2230102371ee1c92025-06-05 16:18:32 +08005import authApi from "../../api/authApi.ts";
22301014bc4616f2025-06-03 16:59:44 +08006
7interface FormValues {
8 name: string;
9 email: string;
10 verifyCode: string;
11 password: string;
12 confirmPassword: string;
13 agreement: boolean;
14}
15
16function Register() {
17 const [countdown, setCountdown] = useState(0);
18 const [form] = Form.useForm<FormValues>();
223010146abadd72025-06-05 14:21:13 +080019 const emailValue = Form.useWatch('email', form)
20
21 //
22 function isValidEmail(email: string): boolean {
23 const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
24
25 return emailRegex.test(email);
26 }
22301014bc4616f2025-06-03 16:59:44 +080027
28 const sendVerificationCode = () => {
2230102371ee1c92025-06-05 16:18:32 +080029 // 如果邮箱校验不通过,则触发表单校验提示,并中断
223010146abadd72025-06-05 14:21:13 +080030 if (!isValidEmail(emailValue)) {
2230102371ee1c92025-06-05 16:18:32 +080031 form.validateFields(['email']);
223010146abadd72025-06-05 14:21:13 +080032 return;
33 }
2230102371ee1c92025-06-05 16:18:32 +080034
35 // 发起 POST 请求到后端 /sendVerification
36 authApi.sendVerificationCode(emailValue).catch()
37 setCountdown(60);
38 };
22301014bc4616f2025-06-03 16:59:44 +080039
40 // 发送表单倒计时
41 useEffect(() => {
42 if (countdown > 0) {
43 const timer = setTimeout(() => {
44 setCountdown(prev => prev - 1);
45 }, 1000);
46
47 return () => clearTimeout(timer);
48 }
49 }, [countdown]);
50
51
52 // 表单提交
53 const onFinish = (values: FormValues) => {
54 console.log('注册成功:', values);
55 };
56
57 return (
58 <Form
59 form={form}
60 style={{ maxWidth: 360 }}
61 onFinish={onFinish}
62 scrollToFirstError
63 >
64 <h2>注册</h2>
65
66 <Form.Item
67 name="name"
68 rules={[{ required: true, message: '请输入用户名' }]}
69 >
70 <Input prefix={<UserOutlined />} placeholder="请输入用户名" />
71 </Form.Item>
72
73 <Form.Item
74 name="email"
75
76 rules={[{ required: true, message: '请输入邮箱' }, { type: 'email', message: '邮箱格式错误' }]}
77 >
78 <Input
79 prefix={<MailOutlined />}
80 placeholder="请输入邮箱"
81 />
82 </Form.Item>
83
84 <Form.Item
85 name="verifyCode"
86 rules={[{ required: true, message: '请填写验证码' }]}
87 >
88 <Space direction="horizontal" size="small">
89 <Input
90 prefix={<NumberOutlined />}
91 placeholder="请输入验证码"
92 style={{ flex: 1 }}
93 />
94 <Button
223010146abadd72025-06-05 14:21:13 +080095 disabled={countdown > 0}
22301014bc4616f2025-06-03 16:59:44 +080096 onClick={sendVerificationCode}
223010146abadd72025-06-05 14:21:13 +080097 color="primary"
22301014bc4616f2025-06-03 16:59:44 +080098 style={{ width: 120 }}
99 >
100 {countdown > 0 ? `${countdown}s后重试` : '发送验证码'}
101 </Button>
102 </Space>
103 </Form.Item>
104
105 <Form.Item
106 name="password"
107 rules={[
108 { required: true, message: '请输入密码' },
109 { min: 6, message: '密码长度至少为6位' },
110 ]}
111 >
112 <Input.Password
113 prefix={<LockOutlined />}
114 placeholder="请输入密码"
115 />
116 </Form.Item>
117
118 <Form.Item
119 name="confirmPassword"
120 dependencies={['password']}
121 rules={[
122 { required: true, message: '请确认密码' },
123 ({ getFieldValue }) => ({
124 validator(_, value) {
125 if (!value || getFieldValue('password') === value) {
126 return Promise.resolve();
127 }
128 return Promise.reject('两次输入的密码不一致');
129 },
130 }),
131 ]}
132 >
133 <Input.Password
134 prefix={<LockOutlined />}
135 placeholder="请确认密码"
136 />
137 </Form.Item>
138
139 <Form.Item
140 name="agreement"
141 valuePropName="checked"
142 rules={[
143 {
144 validator: (_, value) =>
145 value ? Promise.resolve() : Promise.reject('请阅读并同意用户协议'),
146 },
147 ]}
148 >
149 <Checkbox>我已阅读并同意用户协议:<a>《创驿平台用户协议》</a></Checkbox>
150 </Form.Item>
151
152 <Form.Item>
153 <Button
154 type="primary"
155 htmlType="submit"
156 style={{ width: '100%' }}
157 >
158 注册
159 </Button>
160 <NavLink to='/login'>返回登录</NavLink>
161 </Form.Item>
162 </Form>
163 );
164}
165
166export default Register;