Files
cpms_operation_platform/src/hooks/useAuth.ts
T
2026-08-07 11:26:49 +08:00

109 lines
2.9 KiB
TypeScript

// 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<string | null>(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');
}