Files
vue3-element-admin/src/router/guards/permission.ts

97 lines
2.7 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import type { RouteRecordRaw } from "vue-router";
import NProgress from "@/plugins/nprogress";
import router from "@/router";
import { usePermissionStore, useUserStore } from "@/stores";
import { useTenantStoreHook } from "@/stores/tenant";
import { isTenantEnabled } from "@/utils/tenant";
/**
* 路由权限守卫
*
* 处理登录验证、动态路由生成、404检测等
*/
export function setupPermissionGuard() {
// 白名单支持前缀匹配:/f 命中所有公开表单分享页 /f/:formKey
const whiteList = ["/login", "/f"];
router.beforeEach(async (to, _from) => {
NProgress.start();
try {
const isLoggedIn = useUserStore().isLoggedIn();
// 未登录处理
if (!isLoggedIn) {
const isWhiteListed = whiteList.some(
(path) => to.path === path || to.path.startsWith(`${path}/`)
);
if (isWhiteListed) {
return;
}
NProgress.done();
return `/login?redirect=${encodeURIComponent(to.fullPath)}`;
}
// 已登录访问登录页,重定向到首页
if (to.path === "/login") {
return { path: "/" };
}
const permissionStore = usePermissionStore();
const userStore = useUserStore();
// 动态路由生成
if (!permissionStore.isRouteGenerated) {
if (!userStore.userInfo?.roles?.length) {
await userStore.getUserInfo();
}
// 加载用户租户列表(VITE_TENANT_ENABLED=true 时生效)
await initTenantContext();
const dynamicRoutes = await permissionStore.generateRoutes();
dynamicRoutes.forEach((route: RouteRecordRaw) => {
router.addRoute(route);
});
return { ...to, replace: true };
}
// 路由 404 检查
if (to.matched.length === 0) {
// 从登录页跳转且目标路径无效,回退首页(避免不同用户权限不同导致的 404)
if (_from.path === "/login") {
return { path: "/", replace: true };
}
return "/404";
}
// 动态标题
const title = (to.params.title as string) || (to.query.title as string);
if (title) {
to.meta.title = title;
}
} catch (error) {
console.error("Route guard error:", error);
await useUserStore().resetAllState();
NProgress.done();
return "/login";
}
});
router.afterEach(() => {
NProgress.done();
});
}
/** 初始化多租户上下文,未启用或失败时静默跳过 */
async function initTenantContext(): Promise<void> {
if (!isTenantEnabled()) return;
try {
await useTenantStoreHook().loadTenant();
} catch {
// 静默失败,不影响主流程
}
}