- 移除 UserContext 和 useUser 中的 loginByOpenId 调用及相关降级逻辑 - 无本地 token 时保持未登录状态,不再自动触发静默登录 - 清理无用导入 TenantId 和 loginByOpenId - 订单列表页增加登录校验,未登录用户跳转登录页并阻止渲染订单 - 商城首页价格改为 Price 组件,未登录游客显示登录遮罩,单位仅登录后可见
111 lines
3.1 KiB
TypeScript
111 lines
3.1 KiB
TypeScript
import React, { createContext, useContext, useState, useEffect, type ReactNode } from 'react'
|
||
import Taro from '@tarojs/taro'
|
||
import type { User } from '@/api/system/user/model'
|
||
import { getUserInfo } from '@/api/layout'
|
||
import { saveStorageByLoginUser, clearStorageByLoginUser } from '@/utils/server'
|
||
|
||
interface UserContextType {
|
||
user: User | null
|
||
isLoggedIn: boolean
|
||
loading: boolean
|
||
loginUser: (token: string, userInfo: User) => void
|
||
logoutUser: () => void
|
||
refreshUser: () => Promise<User | null>
|
||
syncFromStorage: () => boolean
|
||
}
|
||
|
||
const UserContext = createContext<UserContextType | undefined>(undefined)
|
||
|
||
export const UserProvider: React.FC<{ children: ReactNode }> = ({ children }) => {
|
||
const [user, setUser] = useState<User | null>(null)
|
||
const [loading, setLoading] = useState(true)
|
||
|
||
useEffect(() => {
|
||
const init = async () => {
|
||
const token = Taro.getStorageSync('access_token')
|
||
const userData = Taro.getStorageSync('User')
|
||
|
||
// 情况1: 有本地token和用户数据,直接使用
|
||
if (token && userData) {
|
||
const parsed = typeof userData === 'string' ? JSON.parse(userData) : userData
|
||
setUser(parsed as User)
|
||
setLoading(false)
|
||
return
|
||
}
|
||
|
||
// 情况2: 有token但没有用户数据,尝试从接口获取
|
||
if (token) {
|
||
try {
|
||
const userInfo = await getUserInfo()
|
||
setUser(userInfo)
|
||
setLoading(false)
|
||
return
|
||
} catch {
|
||
// token无效,清除
|
||
clearStorageByLoginUser()
|
||
}
|
||
}
|
||
|
||
// 无本地token,保持未登录状态(已禁用静默登录)
|
||
setLoading(false)
|
||
}
|
||
init()
|
||
}, [])
|
||
|
||
const loginUser = (token: string, userInfo: User) => {
|
||
saveStorageByLoginUser(token, userInfo)
|
||
setUser(userInfo)
|
||
}
|
||
|
||
const logoutUser = () => {
|
||
clearStorageByLoginUser()
|
||
setUser(null)
|
||
}
|
||
|
||
/** 从 storage 快速同步用户状态(无需网络请求),供页面 useDidShow 调用 */
|
||
const syncFromStorage = (): boolean => {
|
||
const token = Taro.getStorageSync('access_token')
|
||
const userData = Taro.getStorageSync('User')
|
||
if (token && userData) {
|
||
const parsed = typeof userData === 'string' ? JSON.parse(userData) : userData
|
||
setUser(parsed as User)
|
||
return true
|
||
}
|
||
if (!token) {
|
||
setUser(null)
|
||
}
|
||
return false
|
||
}
|
||
|
||
const refreshUser = async (): Promise<User | null> => {
|
||
if (!Taro.getStorageSync('access_token')) return null
|
||
try {
|
||
const userInfo = await getUserInfo()
|
||
const token = Taro.getStorageSync('access_token')
|
||
if (token) {
|
||
saveStorageByLoginUser(token, userInfo)
|
||
}
|
||
setUser(userInfo)
|
||
return userInfo
|
||
} catch {
|
||
return null
|
||
}
|
||
}
|
||
|
||
return (
|
||
<UserContext.Provider
|
||
value={{ user, isLoggedIn: !!user, loading, loginUser, logoutUser, refreshUser, syncFromStorage }}
|
||
>
|
||
{children}
|
||
</UserContext.Provider>
|
||
)
|
||
}
|
||
|
||
export const useUserContext = (): UserContextType => {
|
||
const context = useContext(UserContext)
|
||
if (!context) {
|
||
throw new Error('useUserContext must be used within UserProvider')
|
||
}
|
||
return context
|
||
}
|