轻松聘
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

62 lines
2.1 KiB

import { useCallback, useState } from 'react';
import {
getPasswordRuleMessage,
resetPassword,
validatePassword,
validatePasswordConfirm,
type LoginResult,
} from '../api';
import type { PasswordResetPayload } from '../types';
export interface UsePasswordResetReturn {
/** 重置 / 首次设置密码,成功返回登录结果(后端直接下发登录态) */
reset: (payload: PasswordResetPayload) => Promise<LoginResult>;
/** 提交进行中 */
loading: boolean;
/** 失败原因(用于页面提示) */
error: Error | null;
/**
* 新密码规则校验:返回中文提示,null 表示通过。
* 规则本身在 API 层计算,页面只渲染结果,不写判断逻辑。
*/
checkPassword: (password: string, confirm: string) => string | null;
}
/**
* 重置 / 首次设置登录密码。
*
* 覆盖两个场景:忘记密码(老用户改密)、首次设置密码(登录即注册的用户天生无密码)。
* 两条路径共用同一流程与接口,页面按来源只改文案。
* 发送验证码走独立的 useSmsCode。
*/
export function usePasswordReset(): UsePasswordResetReturn {
const [loading, setLoading] = useState(false);
const [error, setError] = useState<Error | null>(null);
const reset = useCallback(async (payload: PasswordResetPayload) => {
setLoading(true);
setError(null);
try {
return await resetPassword(payload);
} catch (e) {
const err = e instanceof Error ? e : new Error('密码设置失败,请稍后重试');
setError(err);
throw err;
} finally {
setLoading(false);
}
}, []);
const checkPassword = useCallback((password: string, confirm: string) => {
const ruleError = validatePassword(password);
if (ruleError) return getPasswordRuleMessage(ruleError);
// 确认框还没开始输入时不提示不一致,避免用户刚敲第一个字符就被报错
if (confirm.length > 0) {
const confirmError = validatePasswordConfirm(password, confirm);
if (confirmError) return getPasswordRuleMessage(confirmError);
}
return null;
}, []);
return { reset, loading, error, checkPassword };
}