import { clearCredentials, selectCurrentToken, selectCurrentUser, setCredentials } from '@/features/auth/authSlice'; import { EVENT_TYPES, eventEmitter } from '@/lib/event-util'; import { fetchApi, refreshAuthToken } from '@/lib/server-api-util'; import { store } from '@/store'; import { User } from '@/types/user'; import * as SecureStore from 'expo-secure-store'; import React, { createContext, ReactNode, useContext, useEffect } from 'react'; import { Platform } from 'react-native'; import { useDispatch, useSelector } from 'react-redux'; interface AuthContextType { user: User | null; login: (user: User, jwt: string) => void; logout: () => void; jwt: string | null; isGuester: () => Promise; isFormalUser: (userMessage: User | null) => boolean; } const AuthContext = createContext(undefined); export const AuthProvider: React.FC<{ children: ReactNode }> = ({ children }) => { const dispatch = useDispatch(); const user = useSelector(selectCurrentUser); const jwt = useSelector(selectCurrentToken); useEffect(() => { // 检查 Redux store 中是否已有 token const refreshTokenAction = async () => { let token = store.getState().auth.token; if (Platform.OS === 'web') { token = localStorage.getItem('token') || ""; } else { await SecureStore.getItemAsync('token').then((token) => { token = token || ""; }) } if (token) { // 验证当前 token 是否有效 fetchApi('/user/identity-check', {}, false) .catch(async (error) => { // console.error("JWT validation failed, attempting to refresh token..."); try { // 尝试刷新 token await refreshAuthToken("Token expired"); // console.log("Token refreshed successfully"); // Token 刷新成功,不需要做其他操作 } catch (refreshError) { // 刷新 token 失败,才进行登出操作 // console.error("Token refresh failed, logging out", refreshError); logout(); } }); } else { try { // 尝试刷新 token await refreshAuthToken("Token expired"); // console.log("Token refreshed successfully"); // Token 刷新成功,不需要做其他操作 } catch (refreshError) { // 刷新 token 失败,才进行登出操作 // console.error("Token refresh failed, logging out", refreshError); logout(); } } } refreshTokenAction(); }, [dispatch]); const login = (newUser: User, newJwt: string) => { // 更新 Redux store dispatch(setCredentials({ user: newUser, token: newJwt })); // 判断运行环境是web则存在localstorage或者expo-secure-store中 if (Platform.OS === 'web') { localStorage.setItem('user', JSON.stringify(newUser)); localStorage.setItem('token', newJwt); } else { SecureStore.setItemAsync('user', JSON.stringify(newUser)); SecureStore.setItemAsync('token', newJwt); } // 触发事件通知 eventEmitter.emit(EVENT_TYPES.USER_INFO_UPDATED, newUser); }; const logout = () => { // 清除 Redux store 中的认证信息 dispatch(clearCredentials()); if (Platform.OS === 'web') { localStorage.setItem('user', ""); localStorage.setItem('token', ""); } else { SecureStore.setItemAsync('user', ""); SecureStore.setItemAsync('token', ""); } // 触发事件通知 eventEmitter.emit(EVENT_TYPES.USER_INFO_UPDATED, null); }; // 判断是否是游客身份 const isGuester = async () => { // 调用接口判断是否是游客 try { await fetchApi(`/iam/identity-check`, { method: 'POST', }, false); user?.email === "" return false } catch (error) { return true; } } // 判断是否是正式用户 手机号注册和email注册都为正式用户 const isFormalUser = (userMessage: User | null) => { if (userMessage?.account) { if (userMessage?.account?.includes("@")) { return true } else if (/^1[3-9]\d{9}$/.test(userMessage?.account)) { return true } else { return false } } // 没有用户信息 return false } return ( {children} ); }; export const useAuth = () => { const context = useContext(AuthContext); if (context === undefined) { throw new Error('useAuth must be used within an AuthProvider'); } return context; };