| import { MailOutlined, LockOutlined } from '@ant-design/icons'; |
| import { Button, Form, Input, message, Row, Col, Modal } from 'antd'; |
| import { NavLink, useNavigate } from 'react-router'; |
| import { useState, useEffect } from 'react'; |
| import { useForm } from 'antd/es/form/Form'; |
| import authApi from '../../api/authApi'; |
| |
| // 定义表单值的类型 |
| interface FormValues { |
| email: string; |
| code: string; |
| password: string; |
| confirmPassword: string; |
| } |
| |
| |
| function Forget() { |
| const [countdown, setCountdown] = useState(0); |
| const [emailSent, setEmailSent] = useState(false); // 是否已发送验证码 |
| const [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@]+$/; |
| console.log(emailRegex.test(email)) |
| console.log(email) |
| return emailRegex.test(email); |
| } |
| |
| // 发送验证码 |
| const sendResetCode = async () => { |
| if (!isValidEmail(emailValue)) { |
| form.validateFields(['email']); |
| return; |
| } |
| |
| await authApi.sendResetCode(emailValue).then(() => { |
| setEmailSent(true); |
| setCountdown(60); |
| }).catch((error) => { |
| messageApi.error(error?.message || '验证码发送失败'); |
| }); |
| }; |
| |
| const [modal, modalContext] = Modal.useModal(); |
| |
| const countDownNav = (onOk: () => void) => { |
| let secondsToGo = 5; |
| const instance = modal.success({ |
| title: '重置成功', |
| content: `系统将在 ${secondsToGo} 后跳转到登陆页面.`, |
| okText: "立即跳转", |
| onOk |
| }); |
| |
| const timer = setInterval(() => { |
| secondsToGo -= 1; |
| instance.update({ |
| content: `将在 ${secondsToGo} 后回到登陆页面.`, |
| }); |
| }, 1000); |
| |
| setTimeout(() => { |
| clearInterval(timer); |
| instance.destroy(); |
| }, secondsToGo * 1000); |
| }; |
| // 倒计时发送 |
| useEffect(() => { |
| let countdownTimer = null; |
| |
| if (countdown > 0) { |
| countdownTimer = setTimeout(() => { |
| setCountdown(prev => prev - 1); |
| }, 1000); |
| } |
| |
| return () => { |
| if (countdownTimer) { |
| clearTimeout(countdownTimer); |
| } |
| }; |
| }, [countdown]); |
| |
| // 重新发送验证码 |
| const resendCode = () => { |
| if (countdown > 0) return; |
| setCountdown(60); |
| sendResetCode(); // 重新发送验证码 |
| }; |
| |
| // 表单提交处理 |
| const onFinish = (values: FormValues) => { |
| if (!emailSent) { |
| sendResetCode(); |
| } else { |
| console.log(values); |
| authApi.resetPassword({ |
| email: values.email, |
| code: values.code, |
| newPassword: values.password, |
| }).then((response) => { |
| if (response.data.code == 0) { |
| countDownNav(() => nav('/login')) |
| } else { |
| messageApi.error(response.data.message); |
| } |
| }) |
| } |
| }; |
| |
| return ( |
| <> |
| <Form |
| form={form} |
| name="forget" |
| initialValues={{ remember: false }} |
| onFinish={onFinish} |
| > |
| {contextHolder} |
| <h2>重置密码</h2> |
| <p>请输入您注册时使用的邮箱地址</p> |
| |
| <Form.Item |
| name="email" |
| rules={[ |
| { required: true, message: '请输入您的邮箱!' }, |
| { type: 'email', message: '请输入正确的邮箱格式' } |
| ]} |
| > |
| <Input prefix={<MailOutlined />} placeholder="注册邮箱" /> |
| </Form.Item> |
| |
| {emailSent && ( |
| <> |
| <Form.Item |
| name="code" |
| rules={[{ required: true, message: '请输入验证码!' }]} |
| > |
| <Row gutter={8}> |
| <Col span={16}> |
| <Input placeholder="验证码" /> |
| </Col> |
| <Col span={8}> |
| <Button |
| disabled={countdown > 0} |
| onClick={resendCode} |
| style={{ width: '100%' }} |
| > |
| {countdown > 0 ? `${countdown}s后重试` : '重新发送'} |
| </Button> |
| </Col> |
| </Row> |
| </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(new Error('两次输入的密码不一致!')); |
| }, |
| }), |
| ]} |
| > |
| <Input.Password prefix={<LockOutlined />} placeholder="确认新密码" /> |
| </Form.Item> |
| </> |
| )} |
| |
| <Form.Item> |
| <Button block type="primary" htmlType="submit"> |
| {emailSent ? '确认重置' : '获取验证码'} |
| </Button> |
| 或 <NavLink to='/login'>返回登录</NavLink> |
| </Form.Item> |
| </Form> |
| {modalContext} |
| </> |
| ); |
| } |
| |
| export default Forget; |