| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150 |
- import React, { useEffect, useState } from 'react';
- import { API, getLogo, showError, showInfo, showSuccess, getSystemName } from '../../helpers';
- import Turnstile from 'react-turnstile';
- import { Button, Card, Form, Typography } from '@douyinfe/semi-ui';
- import { IconMail } from '@douyinfe/semi-icons';
- import { Link } from 'react-router-dom';
- import { useTranslation } from 'react-i18next';
- const { Text, Title } = Typography;
- const PasswordResetForm = () => {
- const { t } = useTranslation();
- const [inputs, setInputs] = useState({
- email: '',
- });
- const { email } = inputs;
- const [loading, setLoading] = useState(false);
- const [turnstileEnabled, setTurnstileEnabled] = useState(false);
- const [turnstileSiteKey, setTurnstileSiteKey] = useState('');
- const [turnstileToken, setTurnstileToken] = useState('');
- const [disableButton, setDisableButton] = useState(false);
- const [countdown, setCountdown] = useState(30);
- const logo = getLogo();
- const systemName = getSystemName();
- useEffect(() => {
- let status = localStorage.getItem('status');
- if (status) {
- status = JSON.parse(status);
- if (status.turnstile_check) {
- setTurnstileEnabled(true);
- setTurnstileSiteKey(status.turnstile_site_key);
- }
- }
- }, []);
- useEffect(() => {
- let countdownInterval = null;
- if (disableButton && countdown > 0) {
- countdownInterval = setInterval(() => {
- setCountdown(countdown - 1);
- }, 1000);
- } else if (countdown === 0) {
- setDisableButton(false);
- setCountdown(30);
- }
- return () => clearInterval(countdownInterval);
- }, [disableButton, countdown]);
- function handleChange(value) {
- setInputs((inputs) => ({ ...inputs, email: value }));
- }
- async function handleSubmit(e) {
- if (!email) {
- showError(t('请输入邮箱地址'));
- return;
- }
- if (turnstileEnabled && turnstileToken === '') {
- showInfo(t('请稍后几秒重试,Turnstile 正在检查用户环境!'));
- return;
- }
- setDisableButton(true);
- setLoading(true);
- const res = await API.get(
- `/api/reset_password?email=${email}&turnstile=${turnstileToken}`,
- );
- const { success, message } = res.data;
- if (success) {
- showSuccess(t('重置邮件发送成功,请检查邮箱!'));
- setInputs({ ...inputs, email: '' });
- } else {
- showError(message);
- }
- setLoading(false);
- }
- return (
- <div className="relative overflow-hidden bg-gray-100 flex items-center justify-center py-12 px-4 sm:px-6 lg:px-8">
- {/* 背景模糊晕染球 */}
- <div className="blur-ball blur-ball-indigo" style={{ top: '-80px', right: '-80px', transform: 'none' }} />
- <div className="blur-ball blur-ball-teal" style={{ top: '50%', left: '-120px' }} />
- <div className="w-full max-w-sm mt-[64px]">
- <div className="flex flex-col items-center">
- <div className="w-full max-w-md">
- <div className="flex items-center justify-center mb-6 gap-2">
- <img src={logo} alt="Logo" className="h-10 rounded-full" />
- <Title heading={3} className='!text-gray-800'>{systemName}</Title>
- </div>
- <Card className="shadow-xl border-0 !rounded-2xl overflow-hidden">
- <div className="flex justify-center pt-6 pb-2">
- <Title heading={3} className="text-gray-800 dark:text-gray-200">{t('密码重置')}</Title>
- </div>
- <div className="px-2 py-8">
- <Form className="space-y-3">
- <Form.Input
- field="email"
- label={t('邮箱')}
- placeholder={t('请输入您的邮箱地址')}
- name="email"
- size="large"
- className="!rounded-md"
- value={email}
- onChange={handleChange}
- prefix={<IconMail />}
- />
- <div className="space-y-2 pt-2">
- <Button
- theme="solid"
- className="w-full !rounded-full"
- type="primary"
- htmlType="submit"
- size="large"
- onClick={handleSubmit}
- loading={loading}
- disabled={disableButton}
- >
- {disableButton ? `${t('重试')} (${countdown})` : t('提交')}
- </Button>
- </div>
- </Form>
- <div className="mt-6 text-center text-sm">
- <Text>{t('想起来了?')} <Link to="/login" className="text-blue-600 hover:text-blue-800 font-medium">{t('登录')}</Link></Text>
- </div>
- </div>
- </Card>
- {turnstileEnabled && (
- <div className="flex justify-center mt-6">
- <Turnstile
- sitekey={turnstileSiteKey}
- onVerify={(token) => {
- setTurnstileToken(token);
- }}
- />
- </div>
- )}
- </div>
- </div>
- </div>
- </div>
- );
- };
- export default PasswordResetForm;
|