1
0

guard.ts 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. import { generatorMenus, generatorRoutes } from '@vben-core/helpers';
  2. import { preferences } from '@vben-core/preferences';
  3. import { useAccessStore } from '@vben-core/stores';
  4. import type { RouteLocationNormalized, Router } from 'vue-router';
  5. import { LOGIN_PATH } from '@vben/constants';
  6. import { $t } from '@vben/locales';
  7. import { startProgress, stopProgress } from '@vben/utils';
  8. import { useTitle } from '@vueuse/core';
  9. import { dynamicRoutes } from '@/router/routes';
  10. /**
  11. * 通用守卫配置
  12. * @param router
  13. */
  14. function setupCommonGuard(router: Router) {
  15. // 记录已经加载的页面
  16. const loadedPaths = new Set<string>();
  17. router.beforeEach(async (to) => {
  18. // 页面加载进度条
  19. if (preferences.transition.progress) {
  20. startProgress();
  21. }
  22. to.meta.loaded = loadedPaths.has(to.path);
  23. return true;
  24. });
  25. router.afterEach((to) => {
  26. // 记录页面是否加载,如果已经加载,后续的页面切换动画等效果不在重复执行
  27. loadedPaths.add(to.path);
  28. // 关闭页面加载进度条
  29. if (preferences.transition.progress) {
  30. stopProgress();
  31. }
  32. // 动态修改标题
  33. if (preferences.app.dynamicTitle) {
  34. const { title } = to.meta;
  35. useTitle(`${$t(title)} - ${preferences.app.name}`);
  36. }
  37. });
  38. }
  39. /**
  40. * 权限访问守卫配置
  41. * @param router
  42. */
  43. function setupAccessGuard(router: Router) {
  44. router.beforeEach(async (to, from) => {
  45. const accessStore = useAccessStore();
  46. const accessToken = accessStore.getAccessToken;
  47. // accessToken 检查
  48. if (!accessToken) {
  49. if (to.path === '/') {
  50. return loginPageMeta(to);
  51. }
  52. // 明确声明忽略权限访问权限,则可以访问
  53. if (to.meta.ignoreAccess) {
  54. return true;
  55. }
  56. // 没有访问权限,跳转登录页面
  57. if (to.fullPath !== LOGIN_PATH) {
  58. return loginPageMeta(to);
  59. }
  60. return to;
  61. }
  62. const accessRoutes = accessStore.getAccessRoutes;
  63. // 是否已经生成过动态路由
  64. if (accessRoutes && accessRoutes.length > 0) {
  65. return true;
  66. }
  67. // 生成路由表
  68. // 当前登录用户拥有的角色标识列表
  69. const userRoles = accessStore.getUserRoles;
  70. const routes = await generatorRoutes(dynamicRoutes, userRoles);
  71. // 动态添加到router实例内
  72. routes.forEach((route) => router.addRoute(route));
  73. const menus = await generatorMenus(routes, router);
  74. // 保存菜单信息和路由信息
  75. accessStore.setAccessMenus(menus);
  76. accessStore.setAccessRoutes(routes);
  77. const redirectPath = (from.query.redirect ?? to.path) as string;
  78. return {
  79. path: decodeURIComponent(redirectPath),
  80. replace: true,
  81. };
  82. });
  83. }
  84. /**
  85. * 登录页面信息
  86. * @param to
  87. */
  88. function loginPageMeta(to: RouteLocationNormalized) {
  89. return {
  90. path: LOGIN_PATH,
  91. // 如不需要,直接删除 query
  92. query: { redirect: encodeURIComponent(to.fullPath) },
  93. // 携带当前跳转的页面,登录后重新跳转该页面
  94. replace: true,
  95. };
  96. }
  97. /**
  98. * 项目守卫配置
  99. * @param router
  100. */
  101. function createRouterGuard(router: Router) {
  102. /** 通用 */
  103. setupCommonGuard(router);
  104. /** 权限访问 */
  105. setupAccessGuard(router);
  106. }
  107. export { createRouterGuard };