import { useState } from "react"; import { useQuery } from "@tanstack/react-query"; import { MailCheck } from "lucide-react"; import { Link, useNavigate } from "react-router-dom"; import { fetchAuthCapabilities, forgotPassword, resetPassword } from "../api/auth"; import { mapApiErrorMessage } from "../api/errorMessages"; import { isApiError } from "../api/types"; import { AuthPanel } from "../components/auth/AuthPanel"; import { Button } from "../components/ui/button"; import { Input } from "../components/ui/input"; import { Label } from "../components/ui/label"; import { PasswordInput } from "../components/ui/password-input"; const PASSWORD_REQUIREMENTS = [ "至少 12 位", "包含大写字母、小写字母和数字", "不要使用公司名、常见顺序或过于简单的组合", ]; export function ForgotPasswordPage() { const navigate = useNavigate(); const [email, setEmail] = useState(""); const [code, setCode] = useState(""); const [newPassword, setNewPassword] = useState(""); const [confirmPassword, setConfirmPassword] = useState(""); const [codeRequested, setCodeRequested] = useState(false); const [submittingCode, setSubmittingCode] = useState(false); const [submittingReset, setSubmittingReset] = useState(false); const [message, setMessage] = useState(""); const [error, setError] = useState(""); const authCapabilitiesQuery = useQuery({ queryKey: ["auth", "capabilities"], queryFn: () => fetchAuthCapabilities(), staleTime: 60_000, }); const emailDeliveryReady = authCapabilitiesQuery.data?.emailDelivery?.ready === true; const emailDeliveryChecking = authCapabilitiesQuery.isLoading; const emailDeliveryUnavailable = authCapabilitiesQuery.isSuccess && !emailDeliveryReady; const emailDeliveryUnknown = authCapabilitiesQuery.isError; async function handleRequestCode(event: React.FormEvent) { event.preventDefault(); setError(""); setMessage(""); const normalizedEmail = email.trim(); if (!normalizedEmail) { setError("请输入邮箱。"); return; } if (!emailDeliveryReady) { setError( emailDeliveryChecking ? "正在检查邮件服务,请稍后再试。" : "邮件验证码暂不可用,请联系管理员处理。", ); return; } setSubmittingCode(true); try { await forgotPassword({ email: normalizedEmail }); setCodeRequested(true); setMessage("如账号可用,验证码将发送到企业邮箱;10 分钟内有效,请同时查看免提醒邮件。"); } catch (err) { if (isApiError(err)) { setError(mapApiErrorMessage(err.code, err.details, err.message)); } else { setError("请求验证码失败,请稍后重试或联系管理员。"); } } finally { setSubmittingCode(false); } } async function handleResetPassword(event: React.FormEvent) { event.preventDefault(); setError(""); const normalizedEmail = email.trim(); const normalizedCode = code.trim(); if (!normalizedEmail) { setError("请输入邮箱。"); return; } if (normalizedCode.length !== 6) { setError("请输入 6 位验证码。"); return; } if (newPassword !== confirmPassword) { setError("两次输入的新密码不一致,请确认后再提交。"); return; } setSubmittingReset(true); try { await resetPassword({ email: normalizedEmail, code: normalizedCode, newPassword, }); setMessage("密码已重置,请使用新密码登录。"); navigate("/login", { replace: true }); } catch (err) { if (isApiError(err)) { setError(mapApiErrorMessage(err.code, err.details, err.message)); } else { setError("重置密码失败,请稍后重试或联系管理员。"); } } finally { setSubmittingReset(false); } } return ( 返回登录 )} >
1 输入账号绑定的企业邮箱,系统发送 6 位验证码。
2 填写验证码和新密码;验证码 10 分钟内有效。
setEmail(event.target.value)} placeholder="请输入账号邮箱" type="email" value={email} />
{!emailDeliveryReady ? (
) : null}
{codeRequested ? (
setCode(event.target.value.replace(/\D/g, "").slice(0, 6))} placeholder="6 位验证码" value={code} />
setNewPassword(event.target.value)} placeholder="至少 12 位,建议包含大小写/数字" value={newPassword} />

密码要求:{PASSWORD_REQUIREMENTS.join(";")}。

setConfirmPassword(event.target.value)} placeholder="再次输入新密码" value={confirmPassword} />
) : null} {message ? (
{message}
) : null} {error ? (
{error}
) : null}
); }