diff --git a/src/passport/login.tsx b/src/passport/login.tsx index 3d9bc82..179b470 100644 --- a/src/passport/login.tsx +++ b/src/passport/login.tsx @@ -105,14 +105,17 @@ async function fetchUserInfo(token: string) { const Login = () => { const [isAgree, setIsAgree] = useState(false) const [loading, setLoading] = useState(false) + const [phoneAuthPending, setPhoneAuthPending] = useState(false) const [phoneAuthCooling, setPhoneAuthCooling] = useState(isPhoneAuthCoolingDown()) const [showContent, setShowContent] = useState(false) const phoneAuthInFlightRef = useRef(false) + const phoneAuthPendingRef = useRef(false) const phoneAuthTimerRef = useRef | null>(null) + const phoneAuthPendingTimerRef = useRef | null>(null) const router = Taro.getCurrentInstance().router const isWeapp = IS_WEAPP - const canUsePhoneAuth = isAgree && !loading && !phoneAuthCooling + const canUsePhoneAuth = isAgree && !loading && !phoneAuthPending && !phoneAuthCooling /** 页面加载动画 */ useEffect(() => { @@ -125,6 +128,10 @@ const Login = () => { clearTimeout(phoneAuthTimerRef.current) phoneAuthTimerRef.current = null } + if (phoneAuthPendingTimerRef.current) { + clearTimeout(phoneAuthPendingTimerRef.current) + phoneAuthPendingTimerRef.current = null + } } }, []) @@ -138,6 +145,49 @@ const Login = () => { }, remaining) } + const clearPhoneAuthPending = () => { + phoneAuthPendingRef.current = false + setPhoneAuthPending(false) + if (phoneAuthPendingTimerRef.current) { + clearTimeout(phoneAuthPendingTimerRef.current) + phoneAuthPendingTimerRef.current = null + } + } + + const startPhoneAuthPending = () => { + phoneAuthPendingRef.current = true + setPhoneAuthPending(true) + markPhoneAuthCalled() + startPhoneAuthCooldown() + if (phoneAuthPendingTimerRef.current) clearTimeout(phoneAuthPendingTimerRef.current) + phoneAuthPendingTimerRef.current = setTimeout(() => { + clearPhoneAuthPending() + Taro.showModal({ + title: '手机号授权超时', + content: '微信手机号授权暂时无响应,请稍后重试或改用短信验证码登录。', + confirmText: '短信登录', + cancelText: '稍后重试', + confirmColor: '#07c160', + success: (res) => { + if (res.confirm) goSmsLogin() + }, + }) + }, 12000) + } + + const handlePhoneAuthTap = () => { + if (!isAgree) { + Taro.showToast({ title: '请先勾选同意协议', icon: 'none' }) + return + } + if (loading || phoneAuthInFlightRef.current || phoneAuthPendingRef.current || isPhoneAuthCoolingDown()) { + startPhoneAuthCooldown() + Taro.showToast({ title: '请稍后再试', icon: 'none' }) + return + } + startPhoneAuthPending() + } + /** 解析 redirect 参数 */ const redirectUrl = (() => { const raw = (router?.params as Record | undefined)?.redirect @@ -226,18 +276,19 @@ const Login = () => { /** 手机号快捷登录 */ const handleGetPhoneNumber = async ({ detail }: GetPhoneNumberEvent) => { + clearPhoneAuthPending() + if (!isAgree) { Taro.showToast({ title: '请先勾选同意协议', icon: 'none' }) return } - if (loading || phoneAuthInFlightRef.current || isPhoneAuthCoolingDown()) { + if (loading || phoneAuthInFlightRef.current) { startPhoneAuthCooldown() Taro.showToast({ title: '请稍后再试', icon: 'none' }) return } phoneAuthInFlightRef.current = true - markPhoneAuthCalled() startPhoneAuthCooldown() const { code: phoneCode, encryptedData, iv, errMsg } = detail || {} @@ -312,6 +363,7 @@ const Login = () => { Taro.showToast({ title: e?.message || '登录失败', icon: 'none' }) } finally { phoneAuthInFlightRef.current = false + clearPhoneAuthPending() setLoading(false) } } @@ -351,14 +403,15 @@ const Login = () => { color: '#ffffff', fontWeight: '600', textAlign: 'center', - opacity: (!isAgree || loading) ? 0.5 : 1, + opacity: canUsePhoneAuth ? 1 : 0.5, margin: 0, padding: 0, }} openType={canUsePhoneAuth ? 'getPhoneNumber' : undefined} + onClick={handlePhoneAuthTap} onGetPhoneNumber={handleGetPhoneNumber} disabled={!canUsePhoneAuth} - loading={loading} + loading={loading || phoneAuthPending} > 手机号快捷登录 diff --git a/src/utils/phoneAuth.ts b/src/utils/phoneAuth.ts index af0dec0..bb201fa 100644 --- a/src/utils/phoneAuth.ts +++ b/src/utils/phoneAuth.ts @@ -11,7 +11,7 @@ let lastPhoneAuthTime = 0 /** 冷却期(ms),在此期间不允许再次触发 getPhoneNumber */ -const PHONE_AUTH_COOLDOWN = 3000 +const PHONE_AUTH_COOLDOWN = 8000 /** * 检查当前是否在冷却期内。