Files
cpms_operation_platform/src/hooks/useAuth.ts
T

94 lines
2.3 KiB
TypeScript
Raw Normal View History

2026-07-14 10:31:17 +08:00
// src/hooks/useAuth.ts
import { useState } from './useState';
import { watch } from 'vue';
2026-07-23 11:27:33 +08:00
import { useMenuStore } from '@/stores/menuStore';
import { usePermissionStore } from '@/stores/permissionStore';
import router, { WHITE_LIST } from '@/router';
2026-07-14 10:31:17 +08:00
const TOKEN_KEY = 'MY_APP_AUTH_TOKEN';
function createAuth() {
const [token, setToken] = useState<string | null>(window.localStorage.getItem(TOKEN_KEY));
watch(token, (newToken) => {
if (newToken) {
window.localStorage.setItem(TOKEN_KEY, newToken);
} else {
window.localStorage.removeItem(TOKEN_KEY);
}
});
2026-07-23 11:27:33 +08:00
const isLoggedIn = () => !!token.value;
/**
* 登录:保存 token → 拉取菜单+权限 → 动态注册路由 → 跳转首页
*/
const login = async (newToken: string) => {
2026-07-14 10:31:17 +08:00
setToken(newToken);
2026-07-23 11:27:33 +08:00
const { loadMenu, homePath } = useMenuStore();
const { loadPermissions } = usePermissionStore();
// 并行拉取菜单和权限
await Promise.all([loadMenu(), loadPermissions()]);
// 跳转到首页(动态路由已注册完成)
router.push(homePath.value);
2026-07-14 10:31:17 +08:00
};
2026-07-23 11:27:33 +08:00
/**
* 退出:清除 token → 清除菜单+权限 → 清除动态路由 → 跳转登录页
*/
2026-07-14 10:31:17 +08:00
const logout = () => {
setToken(null);
2026-07-23 11:27:33 +08:00
const { clearMenu } = useMenuStore();
const { clearPermissions } = usePermissionStore();
clearMenu();
clearPermissions();
router.push('/login');
2026-07-14 10:31:17 +08:00
};
return {
token,
2026-07-23 11:27:33 +08:00
isLoggedIn,
2026-07-14 10:31:17 +08:00
login,
logout,
};
}
export const auth = createAuth();
2026-07-23 11:27:33 +08:00
/**
* 路由守卫逻辑(由 router/guard.ts 使用)
* 判断逻辑:
* 1. 白名单路径 → 直接放行
* 2. 已登录但菜单未加载 → 加载菜单后放行
* 3. 已登录且菜单已加载 → 直接放行
* 4. 未登录 → 跳转 /login
*/
export async function handleRouteGuard(
toPath: string,
): Promise<{ allow: boolean; redirect?: string }> {
// 白名单直接放行
if (WHITE_LIST.includes(toPath) || toPath.match(/^\/:pathMatch/)) {
return { allow: true };
}
// 未登录
if (!auth.isLoggedIn()) {
return { allow: false, redirect: '/login' };
}
// 已登录但菜单未加载 → 先加载
const { loadMenu, loaded } = useMenuStore();
if (!loaded.value) {
const { loadPermissions } = usePermissionStore();
await Promise.all([loadMenu(), loadPermissions()]);
}
return { allow: true };
}