SEC_Warehouse/src/pages/login/index.tsx

102 lines
3.9 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { useState } from 'react'
import { View, Text } from '@tarojs/components'
import { useDidShow } from '@tarojs/taro'
import { useAppDispatch, useAppSelector } from '@/store/hooks'
import { setAuth } from '@/store/authSlice'
import { performWxLogin, completeUserInfoLogin, getLoginSubState } from './wxLoginFlow'
import { useToast } from '@/hooks/useToast'
import { ROUTES } from '@/constants/routes'
import { reLaunch } from '@/utils/navigation'
import { storage } from '@/utils/storage'
import { WX_OPENID_STORAGE_KEY } from '@/constants/auth'
import styles from './index.module.scss'
export default function Login() {
const dispatch = useAppDispatch()
const toast = useToast()
const token = useAppSelector((s) => s.auth.token)
const [loading, setLoading] = useState(false)
// 注册中间态:needUserInfo(待用户资料授权)→ null(初始/完成)
const [needAuth, setNeedAuth] = useState(false)
const [openId, setOpenId] = useState('')
// 已有 token 直接进首页(本期不做 checkLogin 校验,spec D5)
useDidShow(() => {
if (token && !loading) reLaunch(ROUTES.HOME)
})
// 完整登录态校验与落地;未完成时推进授权态
const applyResult = async (result: Awaited<ReturnType<typeof performWxLogin>>) => {
const state = getLoginSubState(result)
if (state !== 'complete') {
console.log('[login-page] 注册未完成,推进到', state)
if (state === 'noMobile') {
// 手机号授权暂缓(后端字段未定):提示并保持当前态,等后端确认后接续
throw new Error('后端要求绑定手机号,该流程暂未开通')
}
// openId 兜底链:响应 openId → 本地缓存(needUserInfo 首次已写入)→ 当前 state
const openIdNext =
result.openId ?? storage.get<string>(WX_OPENID_STORAGE_KEY) ?? openId
if (!openIdNext) throw new Error('响应缺少 openId,无法继续授权')
setOpenId(openIdNext)
setNeedAuth(true)
setLoading(false)
return
}
if (!result.code || !result.userInfo) throw new Error('登录响应缺少凭证')
console.log('[login-page] 登录完成,token 已落地')
setNeedAuth(false)
dispatch(setAuth({ token: result.code, userInfo: result.userInfo }))
await reLaunch(ROUTES.HOME)
}
const handleWxLogin = async () => {
if (loading) return
setLoading(true)
try {
applyResult(await performWxLogin())
} catch (e) {
// code 失效/已用等场景:toast 后端 Message,用户重按按钮重新 Taro.login(code 一次性,重试安全)
console.error('[login-page] performWxLogin 失败', e)
toast.error(e instanceof Error && e.message ? e.message : '登录失败')
setLoading(false)
}
}
// needUserInfo:getUserInfo 授权用户资料(后端文档约定的授权接口)
const handleAuthUserInfo = async () => {
if (loading || !openId) return
setLoading(true)
try {
applyResult(await completeUserInfoLogin(openId))
} catch (e) {
// 授权失败/取消:保留待授权态,用户可重试
console.error('[login-page] completeUserInfoLogin 失败', e)
toast.error(e instanceof Error && e.message ? e.message : '授权失败')
setLoading(false)
}
}
return (
<View className={styles.page}>
<View className={styles.hero}>
<View className={styles.logo}>
<Text className={styles.logoText}>智</Text>
</View>
<Text className={styles.productName}>智慧养老</Text>
<Text className={styles.slogan}>一起守护家人</Text>
</View>
<View className={styles.form}>
<View
className={styles.submit}
onClick={needAuth ? handleAuthUserInfo : handleWxLogin}
>
<Text className={styles.submitText}>
{loading ? '登录中...' : needAuth ? '授权用户信息,继续' : '微信一键登录'}
</Text>
</View>
</View>
</View>
)
}