You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

172 lines
4.8 KiB

  1. import { getConfig } from "@/config";
  2. import { toRouteType } from "./types";
  3. import NProgress from "@/utils/progress";
  4. import { findIndex } from "lodash-unified";
  5. import { transformI18n } from "@/plugins/i18n";
  6. import { sessionKey, type DataInfo } from "@/utils/auth";
  7. import { useMultiTagsStoreHook } from "@/store/modules/multiTags";
  8. import { usePermissionStoreHook } from "@/store/modules/permission";
  9. import {
  10. Router,
  11. createRouter,
  12. RouteRecordRaw,
  13. RouteComponent
  14. } from "vue-router";
  15. import {
  16. ascending,
  17. initRouter,
  18. isOneOfArray,
  19. getHistoryMode,
  20. findRouteByPath,
  21. handleAliveRoute,
  22. formatTwoStageRoutes,
  23. formatFlatteningRoutes
  24. } from "./utils";
  25. import {
  26. buildHierarchyTree,
  27. openLink,
  28. isUrl,
  29. storageSession
  30. } from "@pureadmin/utils";
  31. import homeRouter from "./modules/home";
  32. import errorRouter from "./modules/error";
  33. import remainingRouter from "./modules/remaining";
  34. /** 原始静态路由(未做任何处理) */
  35. const routes = [homeRouter, errorRouter];
  36. /** 导出处理后的静态路由(三级及以上的路由全部拍成二级) */
  37. export const constantRoutes: Array<RouteRecordRaw> = formatTwoStageRoutes(
  38. formatFlatteningRoutes(buildHierarchyTree(ascending(routes)))
  39. );
  40. /** 用于渲染菜单,保持原始层级 */
  41. export const constantMenus: Array<RouteComponent> = ascending(routes).concat(
  42. ...remainingRouter
  43. );
  44. /** 不参与菜单的路由 */
  45. export const remainingPaths = Object.keys(remainingRouter).map(v => {
  46. return remainingRouter[v].path;
  47. });
  48. /** 创建路由实例 */
  49. export const router: Router = createRouter({
  50. history: getHistoryMode(),
  51. routes: constantRoutes.concat(...(remainingRouter as any)),
  52. strict: true,
  53. scrollBehavior(to, from, savedPosition) {
  54. return new Promise(resolve => {
  55. if (savedPosition) {
  56. return savedPosition;
  57. } else {
  58. if (from.meta.saveSrollTop) {
  59. const top: number =
  60. document.documentElement.scrollTop || document.body.scrollTop;
  61. resolve({ left: 0, top });
  62. }
  63. }
  64. });
  65. }
  66. });
  67. /** 重置路由 */
  68. export function resetRouter() {
  69. router.getRoutes().forEach(route => {
  70. const { name, meta } = route;
  71. if (name && router.hasRoute(name) && meta?.backstage) {
  72. router.removeRoute(name);
  73. router.options.routes = formatTwoStageRoutes(
  74. formatFlatteningRoutes(buildHierarchyTree(ascending(routes)))
  75. );
  76. }
  77. });
  78. usePermissionStoreHook().clearAllCachePage();
  79. }
  80. /** 路由白名单 */
  81. const whiteList = ["/login"];
  82. router.beforeEach((to: toRouteType, _from, next) => {
  83. if (to.meta?.keepAlive) {
  84. const newMatched = to.matched;
  85. handleAliveRoute(newMatched, "add");
  86. // 页面整体刷新和点击标签页刷新
  87. if (_from.name === undefined || _from.name === "Redirect") {
  88. handleAliveRoute(newMatched);
  89. }
  90. }
  91. const userInfo = storageSession.getItem<DataInfo<number>>(sessionKey);
  92. NProgress.start();
  93. const externalLink = isUrl(to?.name as string);
  94. if (!externalLink) {
  95. to.matched.some(item => {
  96. if (!item.meta.title) return "";
  97. const Title = getConfig().Title;
  98. if (Title)
  99. document.title = `${transformI18n(item.meta.title)} | ${Title}`;
  100. else document.title = transformI18n(item.meta.title);
  101. });
  102. }
  103. if (userInfo) {
  104. // 无权限跳转403页面
  105. if (to.meta?.roles && !isOneOfArray(to.meta?.roles, userInfo?.roles)) {
  106. next({ path: "/error/403" });
  107. }
  108. if (_from?.name) {
  109. // name为超链接
  110. if (externalLink) {
  111. openLink(to?.name as string);
  112. NProgress.done();
  113. } else {
  114. next();
  115. }
  116. } else {
  117. // 刷新
  118. if (
  119. usePermissionStoreHook().wholeMenus.length === 0 &&
  120. to.path !== "/login"
  121. )
  122. initRouter().then((router: Router) => {
  123. if (!useMultiTagsStoreHook().getMultiTagsCache) {
  124. const { path } = to;
  125. const index = findIndex(remainingRouter, v => {
  126. return v.path == path;
  127. });
  128. const routes: any =
  129. index === -1
  130. ? router.options.routes[0].children
  131. : router.options.routes;
  132. const route = findRouteByPath(path, routes);
  133. // query、params模式路由传参数的标签页不在此处处理
  134. if (route && route.meta?.title) {
  135. useMultiTagsStoreHook().handleTags("push", {
  136. path: route.path,
  137. name: route.name,
  138. meta: route.meta
  139. });
  140. }
  141. }
  142. router.push(to.fullPath);
  143. });
  144. next();
  145. }
  146. } else {
  147. if (to.path !== "/login") {
  148. if (whiteList.indexOf(to.path) !== -1) {
  149. next();
  150. } else {
  151. next({ path: "/login" });
  152. }
  153. } else {
  154. next();
  155. }
  156. }
  157. });
  158. router.afterEach(() => {
  159. NProgress.done();
  160. });
  161. export default router;