import { createContext, useContext, useState, useEffect, type ReactNode } from 'react' import type { User, MenuItem, UserOrgInfo } from '@/types' import { apiClient } from '@/services/api' interface AuthContextType { user: User | null token: string | null isAuthenticated: boolean isLoading: boolean login: (account: string, password: string) => Promise loginWithToken: (token: string) => void logout: () => void currentOrg: { id: number; name: string } | null userOrgs: UserOrgInfo[] userMenus: MenuItem[] switchOrg: (orgId: number) => Promise refreshMenus: () => Promise } const AuthContext = createContext(undefined) export function AuthProvider({ children }: { children: ReactNode }) { const [user, setUser] = useState(null) const [token, setToken] = useState(null) const [isLoading, setIsLoading] = useState(true) const [currentOrg, setCurrentOrg] = useState<{ id: number; name: string } | null>(null) const [userOrgs, setUserOrgs] = useState([]) const [userMenus, setUserMenus] = useState([]) useEffect(() => { const storedToken = localStorage.getItem('token') const storedUser = localStorage.getItem('user') if (storedToken) { setToken(storedToken) } if (storedUser) { try { setUser(JSON.parse(storedUser)) } catch { localStorage.removeItem('user') } } const savedOrg = localStorage.getItem('currentOrg') if (savedOrg) { try { setCurrentOrg(JSON.parse(savedOrg)) } catch {} } setIsLoading(false) }, []) const refreshMenus = async () => { try { const data = await apiClient.getCurrentMenus() setUserMenus(data.list || []) } catch (e) { console.error('Failed to fetch menus:', e) } } const loadUserContext = async () => { try { const orgsData = await apiClient.getUserOrgs() const orgs = orgsData.list || [] setUserOrgs(orgs) if (orgs.length > 0) { const storedOrg = localStorage.getItem('currentOrg') let selectedOrg = orgs[0] if (storedOrg) { try { const parsed = JSON.parse(storedOrg) const found = orgs.find((o: UserOrgInfo) => o.orgId === parsed.id) if (found) selectedOrg = found } catch {} } setCurrentOrg({ id: selectedOrg.orgId, name: selectedOrg.orgName }) localStorage.setItem('currentOrg', JSON.stringify({ id: selectedOrg.orgId, name: selectedOrg.orgName })) } await refreshMenus() } catch (e) { console.error('Failed to load user context:', e) await refreshMenus() } } const switchOrgFn = async (orgId: number) => { try { const data = await apiClient.switchOrg(orgId) if (data.token) { localStorage.setItem('token', data.token) setToken(data.token) try { const payload = JSON.parse(atob(data.token.split('.')[1])) const userData: User = { id: payload.userId || 0, username: payload.username || '', email: '', role: payload.role || 'user', createdAt: new Date().toISOString(), updatedAt: new Date().toISOString(), } setUser(userData) localStorage.setItem('user', JSON.stringify(userData)) } catch {} const org = userOrgs.find((o: UserOrgInfo) => o.orgId === orgId) if (org) { setCurrentOrg({ id: org.orgId, name: org.orgName }) localStorage.setItem('currentOrg', JSON.stringify({ id: org.orgId, name: org.orgName })) } await refreshMenus() } } catch (e) { console.error('Failed to switch org:', e) throw e } } useEffect(() => { if (token && !isLoading) { loadUserContext() } }, [token, isLoading]) const login = async (account: string, password: string) => { try { const response = await apiClient.login({ account, password }) if (response.success && response.token) { setToken(response.token) // 解析 JWT 获取用户信息 try { const payload = JSON.parse(atob(response.token.split('.')[1])) const userData: User = { id: payload.userId || 0, username: payload.username || account, email: '', role: payload.role || 'user', createdAt: new Date().toISOString(), updatedAt: new Date().toISOString(), } setUser(userData) localStorage.setItem('user', JSON.stringify(userData)) } catch { const userData: User = { id: 0, username: account, email: '', createdAt: new Date().toISOString(), updatedAt: new Date().toISOString(), } setUser(userData) localStorage.setItem('user', JSON.stringify(userData)) } } } catch (error) { throw error } } const loginWithToken = (ssoToken: string) => { localStorage.setItem('token', ssoToken) setToken(ssoToken) // 解析 JWT 获取用户信息 try { const payload = JSON.parse(atob(ssoToken.split('.')[1])) const userData: User = { id: payload.userId || 0, username: payload.username || '', email: payload.email || '', role: payload.role || 'user', createdAt: new Date().toISOString(), updatedAt: new Date().toISOString(), } setUser(userData) localStorage.setItem('user', JSON.stringify(userData)) } catch { // JWT 解析失败,使用占位数据 const userData: User = { id: 0, username: 'SSO User', email: '', createdAt: new Date().toISOString(), updatedAt: new Date().toISOString(), } setUser(userData) localStorage.setItem('user', JSON.stringify(userData)) } } const logout = () => { apiClient.logout() setToken(null) setUser(null) setCurrentOrg(null) setUserOrgs([]) setUserMenus([]) localStorage.removeItem('user') localStorage.removeItem('currentOrg') } const value: AuthContextType = { user, token, isAuthenticated: !!token, isLoading, login, loginWithToken, logout, currentOrg, userOrgs, userMenus, switchOrg: switchOrgFn, refreshMenus, } return {children} } export function useAuth() { const context = useContext(AuthContext) if (context === undefined) { throw new Error('useAuth must be used within an AuthProvider') } return context }