import { useState } from 'react'; import { Link, Navigate, useNavigate } from 'react-router-dom'; import { PasswordInput } from '@/features/auth/components/PasswordInput'; import { Toast } from '@/features/auth/components/Toast'; import { VerificationCodeButton } from '@/features/auth/components/VerificationCodeButton'; import { confirmPasswordReset, verifyPasswordResetCode } from '@/lib/api/auth'; import { ImApiError } from '@/lib/api/client'; import { useSessionStore } from '@/stores/session'; const PHONE_RE = /^\d{11}$/; export function ResetPasswordPage() { const navigate = useNavigate(); const tenant = useSessionStore((s) => s.tenant); const [phone, setPhone] = useState(''); const [code, setCode] = useState(''); const [password, setPassword] = useState(''); const [confirm, setConfirm] = useState(''); const [challengeId, setChallengeId] = useState(''); const [error, setError] = useState(''); const [submitting, setSubmitting] = useState(false); const [toast, setToast] = useState(''); if (!tenant) return ; const submit = async (e: React.FormEvent) => { e.preventDefault(); if (!PHONE_RE.test(phone)) return setError('请输入 11 位手机号'); if (!challengeId || !/^\d{6}$/.test(code)) return setError('请先获取并输入 6 位验证码'); // Matches Register's rule (>= 8, no upper bound -- the backend's checkPasswordPolicy only // enforces a minimum length). if (password.length < 8) return setError('密码至少 8 位,需包含字母和数字'); if (password !== confirm) return setError('两次输入的密码不一致'); setSubmitting(true); setError(''); try { const verified = await verifyPasswordResetCode(challengeId, code); await confirmPasswordReset(verified.reset_token, password); setToast('密码修改成功,请重新登录'); window.setTimeout(() => navigate('/login'), 1200); } catch (err) { setError(err instanceof ImApiError ? err.message : '验证码错误或已过期'); setSubmitting(false); } }; return (
arrow_back_ios_new 返回登录

重置密码

通过已绑定的手机号验证身份。未绑定手机号的账号请联系企业管理员重置。

{error ? (
{error}
) : null}
setCode(e.target.value.replace(/\D/g, '').slice(0, 6))} placeholder="短信验证码" inputMode="numeric" className="h-[50px] flex-1 rounded-lg bg-surface-input px-3.5 text-[15px] outline-none" />
setToast('')} />
); }