// src/hooks/useAuth.ts import { notification } from 'ant-design-vue'; import { useState } from './useState'; import { useEffect } from './useEffect'; import { useMenuStore } from '@/stores/menuStore'; import { usePermissionStore } from '@/stores/permissionStore'; import { useTabsStore } from '@/stores/tabsStore'; import { useUserStore } from '@/stores/userStore'; import { clearAuthDataCache } from '@/api/authCache'; import { logout as logoutApi } from '@/api/login'; import router from '@/router'; const TOKEN_KEY = 'MY_APP_AUTH_TOKEN'; let isForceLoggingOut = false; function createAuth() { const [token, setToken] = useState(window.localStorage.getItem(TOKEN_KEY)); useEffect(() => { const newToken = token.value; if (newToken) { window.localStorage.setItem(TOKEN_KEY, newToken); } else { window.localStorage.removeItem(TOKEN_KEY); } }, [token]); const isLoggedIn = () => !!token.value; const clearSession = () => { setToken(null); const { clearUser } = useUserStore(); const { clearMenu } = useMenuStore(); const { clearPermissions } = usePermissionStore(); const { clearTabs } = useTabsStore(); clearUser(); clearTabs(); clearMenu(); clearPermissions(); clearAuthDataCache(); }; /** * 登录:保存 token → 拉取菜单+权限 → 动态注册路由 → 跳转首页 */ const login = async (newToken: string, targetPath?: string) => { isForceLoggingOut = false; setToken(newToken); const { loadMenu, homePath, isRoutePathAvailable } = useMenuStore(); const { loadPermissions } = usePermissionStore(); // 并行拉取菜单和权限 await Promise.all([loadMenu(), loadPermissions()]); // 权限获取失败时会清空会话,此时不再跳转首页 if (!isLoggedIn()) return; const nextPath = targetPath && isRoutePathAvailable(targetPath) ? targetPath : homePath.value || '/404'; // 动态路由注册完成后,再跳转到有效目标页 router.push(nextPath); }; /** * 退出:调用登出接口 → 清除 token → 清除菜单+权限 → 清除动态路由 → 跳转登录页 */ const logout = async () => { try { await logoutApi(); } catch { // 即使接口失败也要继续清除本地会话 } clearSession(); router.push('/login'); }; return { token, isLoggedIn, login, logout, clearSession, }; } export const auth = createAuth(); /** * 强制重新登录:提示错误 → 清空会话 → 跳转登录页 * 用于权限获取失败、登录态失效等需要彻底重置会话的场景 */ export function forceReLogin(msg = '账户权限获取失败,请重新登录') { if (isForceLoggingOut) return; isForceLoggingOut = true; notification.error({ message: '提示', description: msg, duration: 2600, }); auth.clearSession(); router.push('/login'); }