| import { useEffect, useState } from 'react'; |
| import { LockOutlined, MailOutlined, NumberOutlined, UserOutlined } from '@ant-design/icons'; |
| import {Button, Checkbox, Form, Input, Space} from 'antd'; |
| import { NavLink } from 'react-router'; |
| import authApi from "../../api/authApi.ts"; |
| |
| interface FormValues { |
| name: string; |
| email: string; |
| verifyCode: string; |
| password: string; |
| confirmPassword: string; |
| agreement: boolean; |
| } |
| |
| function Register() { |
| const [countdown, setCountdown] = useState(0); |
| const [form] = Form.useForm<FormValues>(); |
| const emailValue = Form.useWatch('email', form) |
| |
| // |
| function isValidEmail(email: string): boolean { |
| const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; |
| |
| return emailRegex.test(email); |
| } |
| |
| const sendVerificationCode = () => { |
| // 如果邮箱校验不通过,则触发表单校验提示,并中断 |
| if (!isValidEmail(emailValue)) { |
| form.validateFields(['email']); |
| return; |
| } |
| |
| // 发起 POST 请求到后端 /sendVerification |
| authApi.sendVerificationCode(emailValue).catch() |
| setCountdown(60); |
| }; |
| |
| // 发送表单倒计时 |
| useEffect(() => { |
| if (countdown > 0) { |
| const timer = setTimeout(() => { |
| setCountdown(prev => prev - 1); |
| }, 1000); |
| |
| return () => clearTimeout(timer); |
| } |
| }, [countdown]); |
| |
| |
| // 表单提交 |
| const onFinish = (values: FormValues) => { |
| console.log('注册成功:', values); |
| }; |
| |
| return ( |
| <Form |
| form={form} |
| style={{ maxWidth: 360 }} |
| onFinish={onFinish} |
| scrollToFirstError |
| > |
| <h2>注册</h2> |
| |
| <Form.Item |
| name="name" |
| rules={[{ required: true, message: '请输入用户名' }]} |
| > |
| <Input prefix={<UserOutlined />} placeholder="请输入用户名" /> |
| </Form.Item> |
| |
| <Form.Item |
| name="email" |
| |
| rules={[{ required: true, message: '请输入邮箱' }, { type: 'email', message: '邮箱格式错误' }]} |
| > |
| <Input |
| prefix={<MailOutlined />} |
| placeholder="请输入邮箱" |
| /> |
| </Form.Item> |
| |
| <Form.Item |
| name="verifyCode" |
| rules={[{ required: true, message: '请填写验证码' }]} |
| > |
| <Space direction="horizontal" size="small"> |
| <Input |
| prefix={<NumberOutlined />} |
| placeholder="请输入验证码" |
| style={{ flex: 1 }} |
| /> |
| <Button |
| disabled={countdown > 0} |
| onClick={sendVerificationCode} |
| color="primary" |
| style={{ width: 120 }} |
| > |
| {countdown > 0 ? `${countdown}s后重试` : '发送验证码'} |
| </Button> |
| </Space> |
| </Form.Item> |
| |
| <Form.Item |
| name="password" |
| rules={[ |
| { required: true, message: '请输入密码' }, |
| { min: 6, message: '密码长度至少为6位' }, |
| ]} |
| > |
| <Input.Password |
| prefix={<LockOutlined />} |
| placeholder="请输入密码" |
| /> |
| </Form.Item> |
| |
| <Form.Item |
| name="confirmPassword" |
| dependencies={['password']} |
| rules={[ |
| { required: true, message: '请确认密码' }, |
| ({ getFieldValue }) => ({ |
| validator(_, value) { |
| if (!value || getFieldValue('password') === value) { |
| return Promise.resolve(); |
| } |
| return Promise.reject('两次输入的密码不一致'); |
| }, |
| }), |
| ]} |
| > |
| <Input.Password |
| prefix={<LockOutlined />} |
| placeholder="请确认密码" |
| /> |
| </Form.Item> |
| |
| <Form.Item |
| name="agreement" |
| valuePropName="checked" |
| rules={[ |
| { |
| validator: (_, value) => |
| value ? Promise.resolve() : Promise.reject('请阅读并同意用户协议'), |
| }, |
| ]} |
| > |
| <Checkbox>我已阅读并同意用户协议:<a>《创驿平台用户协议》</a></Checkbox> |
| </Form.Item> |
| |
| <Form.Item> |
| <Button |
| type="primary" |
| htmlType="submit" |
| style={{ width: '100%' }} |
| > |
| 注册 |
| </Button> |
| 或 <NavLink to='/login'>返回登录</NavLink> |
| </Form.Item> |
| </Form> |
| ); |
| } |
| |
| export default Register; |