blob: 0023b71373c3167cbd622f125b9ba7689622563e [file] [log] [blame]
import { useEffect, useState } from 'react';
import { LockOutlined, MailOutlined, NumberOutlined, UserOutlined } from '@ant-design/icons';
import { Button, Checkbox, Form, Input, message, Space } from 'antd';
import { NavLink, useNavigate } from 'react-router';
import authApi from "../../api/authApi";
import type { RejisterRequest } from "../../api/type";
import type { AxiosResponse } from 'axios';
// 定义表单字段的类型
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);
const [messageApi, contextHolder] = message.useMessage();
const nav = useNavigate(); // 用于页面跳转
// 校验邮箱格式
function isValidEmail(email: string): boolean {
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
return emailRegex.test(email);
}
// 发送验证码
const sendVerificationCode = () => {
if (!isValidEmail(emailValue)) {
form.validateFields(['email']);
return;
}
authApi.sendVerificationCode(emailValue).then(() => {
setCountdown(60); // 开始倒计时
}).catch((error) => {
messageApi.error(error?.message || '验证码发送失败');
});
};
// 倒计时处理
useEffect(() => {
if (countdown === 0) return;
const timer = setInterval(() => {
setCountdown(prev => {
if (prev === 1) clearInterval(timer); // 倒计时结束
return prev - 1;
});
}, 1000);
return () => clearInterval(timer);
}, [countdown]);
// 表单提交
const onFinish = (values: FormValues) => {
const registerRequest: RejisterRequest = {
username: values.name,
email: values.email,
verificationCode: values.verifyCode,
password: values.password,
};
authApi.register(registerRequest).then((response: AxiosResponse) => {
if (response.data.code === 200) {
messageApi.success("注册成功");
form.resetFields(); // 清空表单
setTimeout(() => {
nav('/login'); // 注册成功后跳转到登录页面
}, 1500);
} else {
messageApi.error(response.data.message);
}
}).catch((error) => {
messageApi.error(error?.message || '注册失败,请重试');
});
};
return (
<Form
form={form}
style={{ maxWidth: 360 }}
onFinish={onFinish}
scrollToFirstError
>
<h2>注册</h2>
{contextHolder}
<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;