import { create } from 'zustand'; import { getAccessToken, setToken, removeToken } from '@/utils/token'; import { scheduleProactiveRefresh, clearProactiveRefresh } from '@/utils/request'; import { loginApi, logoutApi, getAuthPermissionInfoApi } from '@/api/auth'; import type { UserInfo, MenuRecord, LoginParams } from '@/types/auth'; import { convertBackendMenus } from '@/utils/menuConverter'; import { addDynamicRoutes, resetDynamicRoutes } from '@/router'; interface AuthState { token: string | null; userInfo: UserInfo | null; roles: string[]; permissions: string[]; menus: MenuRecord[]; login: (params: LoginParams, remember?: boolean) => Promise; logout: () => Promise; fetchPermissionInfo: () => Promise; hasPermission: (code: string) => boolean; reset: () => void; } export const useAuthStore = create()((set, get) => ({ token: getAccessToken(), userInfo: null, roles: [], permissions: [], menus: [], login: async (params, remember = true) => { const { data } = await loginApi(params); setToken(data.accessToken, data.refreshToken, remember, data.expiresTime); set({ token: data.accessToken }); scheduleProactiveRefresh(); await get().fetchPermissionInfo(); }, logout: async () => { try { await logoutApi(); } finally { get().reset(); } }, fetchPermissionInfo: async () => { const resp = await getAuthPermissionInfoApi(); if (!resp || !resp.data) { throw new Error('Failed to fetch permission info: empty response'); } const { data } = resp; const menus = convertBackendMenus(data.menus ?? []); const mergedMenus = addDynamicRoutes(menus); set({ userInfo: data.user, roles: data.roles ?? [], permissions: data.permissions ?? [], menus: mergedMenus, }); }, hasPermission: (code) => { const perms = get().permissions; return perms.includes('*:*:*') || perms.includes(code); }, reset: () => { clearProactiveRefresh(); resetDynamicRoutes(); removeToken(); set({ token: null, userInfo: null, roles: [], permissions: [], menus: [], }); }, }));