Files
vue3-element-admin/src/router/guards.ts
Ray.Hao 3ccbdb7c06 chore: 递增版本号并标记停更版本
- 版本号: 中段递增、末段归零

- README: laravel 与 spring-boot-3 更新状态改为 ❌️
2026-09-25 19:56:52 +08:00

99 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 {
// 静默失败,不影响主流程
}
}