permission.ts 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. import type { NavigationGuardNext, RouteLocationNormalized, RouteRecordRaw } from "vue-router";
  2. import NProgress from "@/utils/nprogress";
  3. import { Auth } from "@/utils/auth";
  4. import router from "@/router";
  5. import { usePermissionStore, useUserStore, useEnterpriseStore } from "@/store";
  6. export function setupPermission() {
  7. // 白名单路由
  8. const whiteList = ["/login"];
  9. router.beforeEach(async (to, from, next) => {
  10. NProgress.start();
  11. try {
  12. const isLoggedIn = Auth.isLoggedIn();
  13. if (isLoggedIn) {
  14. // 如果已登录但访问登录页,重定向到首页
  15. if (to.path === "/login") {
  16. next({ path: "/" });
  17. return;
  18. }
  19. // 处理已登录用户的路由访问
  20. await handleAuthenticatedUser(to, from, next);
  21. } else {
  22. // 未登录用户的处理
  23. if (whiteList.includes(to.path)) {
  24. next();
  25. } else {
  26. next(`/login?redirect=${encodeURIComponent(to.fullPath)}`);
  27. NProgress.done();
  28. }
  29. }
  30. } catch (error) {
  31. // 错误处理:重置状态并跳转登录(保留 redirect 与未登录分支一致)
  32. console.error("Route guard error:", error);
  33. await useUserStore().resetAllState();
  34. next(`/login?redirect=${encodeURIComponent(to.fullPath)}`);
  35. NProgress.done();
  36. }
  37. });
  38. // 后置守卫,确保进度条关闭
  39. router.afterEach(() => {
  40. NProgress.done();
  41. });
  42. }
  43. /**
  44. * 处理已登录用户的路由访问
  45. */
  46. async function handleAuthenticatedUser(
  47. to: RouteLocationNormalized,
  48. from: RouteLocationNormalized,
  49. next: NavigationGuardNext
  50. ) {
  51. const permissionStore = usePermissionStore();
  52. const userStore = useUserStore();
  53. const enterpriseStore = useEnterpriseStore();
  54. try {
  55. // 检查路由是否已生成
  56. if (!permissionStore.isRouteGenerated) {
  57. // 如果用户信息为空,获取用户信息
  58. if (!userStore.basicInfo?.roles?.length) {
  59. await userStore.getUserInfo();
  60. }
  61. // 如果是租户用户,获取企业列表
  62. if (!userStore.is_platform_user) {
  63. await enterpriseStore.loadEnterpriseList();
  64. }
  65. const dynamicRoutes = await permissionStore.generateRoutes();
  66. // 添加路由到路由器
  67. dynamicRoutes.forEach((route: RouteRecordRaw) => {
  68. router.addRoute('/', route);
  69. });
  70. // 路由生成完成后,重新导航到目标路由
  71. next({ ...to, replace: true });
  72. return;
  73. }
  74. // 路由已加载,检查路由是否存在
  75. if (to.matched.length === 0) {
  76. next("/404");
  77. return;
  78. }
  79. // 动态设置页面标题(仅做简单净化,避免 query 注入标签/过长字符串影响标签栏展示)
  80. const rawTitle = (to.params.title as string) || (to.query.title as string);
  81. if (rawTitle && typeof rawTitle === "string") {
  82. const safe = rawTitle.replace(/[<>]/g, "").trim().slice(0, 64);
  83. if (safe) {
  84. to.meta.title = safe;
  85. }
  86. }
  87. next();
  88. } catch (error) {
  89. console.error("❌ Route guard error:", error);
  90. await useUserStore().resetAllState();
  91. next(`/login?redirect=${encodeURIComponent(to.fullPath)}`);
  92. NProgress.done();
  93. }
  94. }