index.ts 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. import { createRouter, createWebHashHistory, createWebHistory } from "vue-router";
  2. import { useUserStore } from "@/stores/modules/user";
  3. import { useAuthStore } from "@/stores/modules/auth";
  4. import { LOGIN_URL, ROUTER_WHITE_LIST } from "@/config";
  5. import { initDynamicRouter } from "@/routers/modules/dynamicRouter";
  6. import { staticRouter, errorRouter } from "@/routers/modules/staticRouter";
  7. import NProgress from "@/config/nprogress";
  8. const mode = import.meta.env.VITE_ROUTER_MODE;
  9. const routerMode = {
  10. hash: () => createWebHashHistory(),
  11. history: () => createWebHistory()
  12. };
  13. /**
  14. * @description 📚 路由参数配置简介
  15. * @param path ==> 路由菜单访问路径
  16. * @param name ==> 路由 name (对应页面组件 name, 可用作 KeepAlive 缓存标识 && 按钮权限筛选)
  17. * @param redirect ==> 路由重定向地址
  18. * @param component ==> 视图文件路径
  19. * @param meta ==> 路由菜单元信息
  20. * @param meta.icon ==> 菜单和面包屑对应的图标
  21. * @param meta.title ==> 路由标题 (用作 document.title || 菜单的名称)
  22. * @param meta.activeMenu ==> 当前路由为详情页时,需要高亮的菜单
  23. * @param meta.isLink ==> 路由外链时填写的访问地址
  24. * @param meta.isHide ==> 是否在菜单中隐藏 (通常列表详情页需要隐藏)
  25. * @param meta.isFull ==> 菜单是否全屏 (示例:数据大屏页面)
  26. * @param meta.isAffix ==> 菜单是否固定在标签页中 (首页通常是固定项)
  27. * @param meta.isKeepAlive ==> 当前路由是否缓存
  28. * */
  29. const router = createRouter({
  30. history: routerMode[mode](),
  31. routes: [...staticRouter, ...errorRouter],
  32. strict: false,
  33. scrollBehavior: () => ({ left: 0, top: 0 })
  34. });
  35. /**
  36. * @description 路由拦截 beforeEach
  37. * */
  38. router.beforeEach(async (to, from, next) => {
  39. const userStore = useUserStore();
  40. const authStore = useAuthStore();
  41. // 1.NProgress 开始
  42. NProgress.start();
  43. // 检查 to 对象是否存在
  44. if (!to || !to.path) {
  45. NProgress.done();
  46. return next();
  47. }
  48. // 2.动态设置标题
  49. const title = import.meta.env.VITE_GLOB_APP_TITLE;
  50. document.title = to.meta?.title ? `${to.meta.title} - ${title}` : title;
  51. // 3.判断是访问登陆页,有 Token 就在当前页面,没有 Token 重置路由到登陆页
  52. if (to.path.toLocaleLowerCase() === LOGIN_URL) {
  53. if (userStore.token && from && from.fullPath) return next(from.fullPath);
  54. resetRouter();
  55. return next();
  56. }
  57. // 4.判断访问页面是否在路由白名单地址(静态路由)中,如果存在直接放行
  58. if (ROUTER_WHITE_LIST.includes(to.path)) return next();
  59. // 5.判断是否有 Token,没有重定向到 login 页面
  60. if (!userStore.token) return next({ path: LOGIN_URL, replace: true });
  61. // 6.如果没有菜单列表,就重新请求菜单列表并添加动态路由
  62. if (!authStore.authMenuListGet.length) {
  63. await initDynamicRouter();
  64. return next({ ...to, replace: true });
  65. }
  66. // 7.存储 routerName 做按钮权限筛选
  67. authStore.setRouteName(to.name as string);
  68. // 8.正常访问页面
  69. next();
  70. });
  71. /**
  72. * @description 重置路由
  73. * */
  74. export const resetRouter = () => {
  75. const authStore = useAuthStore();
  76. authStore.flatMenuListGet.forEach(route => {
  77. const { name } = route;
  78. if (name && router.hasRoute(name)) router.removeRoute(name);
  79. });
  80. };
  81. /**
  82. * @description 路由跳转错误
  83. * */
  84. router.onError(error => {
  85. NProgress.done();
  86. console.warn("路由错误", error.message);
  87. });
  88. /**
  89. * @description 路由跳转结束
  90. * */
  91. router.afterEach(() => {
  92. NProgress.done();
  93. });
  94. export default router;