index.ts 4.1 KB

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