import Loader from "@/components/loader"; import React, {createContext, useEffect, useReducer} from "react"; import {auth, getUserInfo} from "@/service/api/user.ts"; import {getAuthToken, setAuthToken} from "@/hooks/useAuth.ts"; import {getRoleByUsername} from "@/contexts/auth/role.ts"; const AuthContext = createContext(null) const initialState: AuthProps = { isLoggedIn: false, isInitialized: false, user: null }; const authReducer = (state: AuthProps, action: { action?: string, payload: Partial }) => { return { ...state, ...action.payload, } } const UserRoleStorageKey = 'user-current-role'; function getCurrentRole(username: string) { return (localStorage.getItem(UserRoleStorageKey) || getRoleByUsername(username)) as UserRole } export function setCurrentRole(role: UserRole) { localStorage.setItem(UserRoleStorageKey, role) } function removeRoleStorage() { localStorage.removeItem(UserRoleStorageKey) } function getInitUserData(user: UserProfile) { const {roles} = user; const role = !roles || roles.length === 0 ? 'staff' : ( roles.includes('root') ? 'root' : ( roles.includes('fo') ? 'fo' : 'ro' ) ) as UserRole return { ...user, origin_role: role, role: role == 'root' ? (getCurrentRole(user.username) || role) : role } } export const AuthProvider = ({children}: { children: React.ReactNode }) => { const [state, dispatch] = useReducer(authReducer, initialState); // MOCK INIT DATA const refreshUserInfo = async ()=>{ const user = await getUserInfo(); dispatch({ action: 'refresh', payload: { isLoggedIn: !!user, user: getInitUserData(user) } }) } const init = async () => { const token = getAuthToken(); if (!token) { dispatch({ payload: { isInitialized: true, } }) return 'initialized' } getUserInfo().then(user => { dispatch({ action: 'init', payload: { isInitialized: true, isLoggedIn: !!user, user: getInitUserData(user) } }) }).finally(() => { dispatch({ payload: { isInitialized: true, } }) }) return 'initialized' } // 登录 const login = async (code: string, state: string) => { const user = await auth(code, state) // 保存token setAuthToken(user.token, user.expiration_time ? (new Date(user.expiration_time)).getTime() : -1); // dispatch({ action: 'login', payload: { isLoggedIn: true, user: getInitUserData(user) } }) } // 登出 const logout = async () => { setTimeout(() => { const a = document.createElement('a') a.setAttribute('href', 'https://portal.chuhai.edu.hk/signout') a.setAttribute('target', '_blank') a.click() }, 0) setAuthToken(null) removeRoleStorage() dispatch({ action: 'logout', payload: { isLoggedIn: false, user: null } }) } const mockLogin = async () => { console.log('mock login') } const updateUser = async (user: Partial) => { dispatch({ action: 'updateUser', payload: { user: { ...state.user, ...user } as never, } }) }; useEffect(() => { init().then(console.log) }, []) // 判断是否已经初始化 if (state.isInitialized !== undefined && !state.isInitialized) { return ; } return ({children}) } export default AuthContext