index.ts 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. import type { Router, RouteLocationNormalized } from 'vue-router';
  2. import { useAppStoreWithOut } from '/@/store/modules/app';
  3. import { useUserStoreWithOut } from '/@/store/modules/user';
  4. import { useVentStore } from '/@/store/modules/vent';
  5. import { useTransitionSetting } from '/@/hooks/setting/useTransitionSetting';
  6. import { AxiosCanceler } from '/@/utils/http/axios/axiosCancel';
  7. import { Modal, notification } from 'ant-design-vue';
  8. import { warn } from '/@/utils/log';
  9. import { unref } from 'vue';
  10. import { setRouteChange } from '/@/logics/mitt/routeChange';
  11. import { createPermissionGuard } from './permissionGuard';
  12. import { createStateGuard } from './stateGuard';
  13. import nProgress from 'nprogress';
  14. import projectSetting from '/@/settings/projectSetting';
  15. import { createParamMenuGuard } from './paramMenuGuard';
  16. import { RootRoute } from '/@/router/routes';
  17. import { useGlobSetting } from '/@/hooks/setting';
  18. import { PageEnum } from '/@/enums/pageEnum';
  19. import { unmountMicroApps } from '/@/qiankun';
  20. // Don't change the order of creation
  21. export function setupRouterGuard(router: Router) {
  22. createPageGuard(router);
  23. createPageLoadingGuard(router);
  24. createHttpGuard(router);
  25. createScrollGuard(router);
  26. createMessageGuard(router);
  27. createProgressGuard(router);
  28. createPermissionGuard(router);
  29. createParamMenuGuard(router); // must after createPermissionGuard (menu has been built.)
  30. createStateGuard(router);
  31. }
  32. const glob = useGlobSetting();
  33. RootRoute.redirect = glob.homePath || PageEnum.BASE_HOME;
  34. /**
  35. * Hooks for handling page state
  36. */
  37. function createPageGuard(router: Router) {
  38. const loadedPageMap = new Map<string, boolean>();
  39. router.beforeEach(async (to, from) => {
  40. if (from.path.startsWith('/micro-') && !to.path.startsWith('/micro-')) {
  41. unmountMicroApps(['/' + from.path.split('/')[1]]);
  42. } else if (from.path.startsWith('/micro-') && to.path.startsWith('/micro-') && from.path.split('/')[1] != to.path.split('/')[1]) {
  43. unmountMicroApps(['/' + from.path.split('/')[1]]);
  44. }
  45. // The page has already been loaded, it will be faster to open it again, you don’t need to do loading and other processing
  46. to.meta.loaded = !!loadedPageMap.get(to.path);
  47. // Notify routing changes
  48. setRouteChange(to);
  49. return true;
  50. });
  51. router.afterEach((to) => {
  52. loadedPageMap.set(to.path, true);
  53. });
  54. }
  55. // Used to handle page loading status
  56. function createPageLoadingGuard(router: Router) {
  57. const ventStore = useVentStore();
  58. const userStore = useUserStoreWithOut();
  59. const appStore = useAppStoreWithOut();
  60. const { getOpenPageLoading } = useTransitionSetting();
  61. router.beforeEach(async (to, from) => {
  62. if (!userStore.getToken) {
  63. return true;
  64. }
  65. if (to.meta.loaded) {
  66. return true;
  67. }
  68. if (!ventStore.allTableHeaderColumns) {
  69. await ventStore.setAllTableHeaderColumns();
  70. }
  71. if (unref(getOpenPageLoading)) {
  72. appStore.setPageLoadingAction(true);
  73. return true;
  74. }
  75. return true;
  76. });
  77. router.afterEach(async (to, from) => {
  78. if (unref(getOpenPageLoading)) {
  79. // TODO Looking for a better way
  80. // The timer simulates the loading time to prevent flashing too fast,
  81. setTimeout(() => {
  82. appStore.setPageLoading(false);
  83. }, 220);
  84. }
  85. return true;
  86. });
  87. }
  88. /**
  89. * The interface used to close the current page to complete the request when the route is switched
  90. * @param router
  91. */
  92. function createHttpGuard(router: Router) {
  93. const { removeAllHttpPending } = projectSetting;
  94. let axiosCanceler: Nullable<AxiosCanceler>;
  95. if (removeAllHttpPending) {
  96. axiosCanceler = new AxiosCanceler();
  97. }
  98. router.beforeEach(async () => {
  99. // Switching the route will delete the previous request
  100. axiosCanceler?.removeAllPending();
  101. return true;
  102. });
  103. }
  104. // Routing switch back to the top
  105. function createScrollGuard(router: Router) {
  106. const isHash = (href: string) => {
  107. return /^#/.test(href);
  108. };
  109. const body = document.body;
  110. router.afterEach(async (to) => {
  111. // scroll top
  112. isHash((to as RouteLocationNormalized & { href: string })?.href) && body.scrollTo(0, 0);
  113. return true;
  114. });
  115. }
  116. /**
  117. * Used to close the message instance when the route is switched
  118. * @param router
  119. */
  120. export function createMessageGuard(router: Router) {
  121. const { closeMessageOnSwitch } = projectSetting;
  122. router.beforeEach(async () => {
  123. try {
  124. if (closeMessageOnSwitch) {
  125. Modal.destroyAll();
  126. notification.destroy();
  127. }
  128. } catch (error) {
  129. warn('message guard error:' + error);
  130. }
  131. return true;
  132. });
  133. }
  134. export function createProgressGuard(router: Router) {
  135. const { getOpenNProgress } = useTransitionSetting();
  136. router.beforeEach(async (to) => {
  137. if (to.meta.loaded) {
  138. return true;
  139. }
  140. unref(getOpenNProgress) && nProgress.start();
  141. return true;
  142. });
  143. router.afterEach(async () => {
  144. unref(getOpenNProgress) && nProgress.done();
  145. return true;
  146. });
  147. }