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.
148 lines
4.0 KiB
148 lines
4.0 KiB
/* eslint-disable @typescript-eslint/require-await */ |
|
import type { RouteLocationNormalized, Router } from 'vue-router' |
|
import { Modal, notification } from 'ant-design-vue' |
|
import { unref } from 'vue' |
|
import nProgress from 'nprogress' |
|
import { createPermissionGuard } from './permissionGuard' |
|
import { createStateGuard } from './stateGuard' |
|
import { createParamMenuGuard } from './paramMenuGuard' |
|
import { useAppStoreWithOut } from '@/store/modules/app' |
|
import { useUserStoreWithOut } from '@/store/modules/user' |
|
import { useTransitionSetting } from '@/hooks/setting/useTransitionSetting' |
|
import { AxiosCanceler } from '@/utils/http/axios/axiosCancel' |
|
import { warn } from '@/utils/log' |
|
import { setRouteChange } from '@/logics/mitt/routeChange' |
|
import projectSetting from '@/settings/projectSetting' |
|
|
|
// Don't change the order of creation |
|
export function setupRouterGuard(router: Router) { |
|
createPageGuard(router) |
|
createPageLoadingGuard(router) |
|
createHttpGuard(router) |
|
createScrollGuard(router) |
|
createMessageGuard(router) |
|
createProgressGuard(router) |
|
createPermissionGuard(router) |
|
createParamMenuGuard(router) // must after createPermissionGuard (menu has been built.) |
|
createStateGuard(router) |
|
} |
|
|
|
/** |
|
* Hooks for handling page state |
|
*/ |
|
function createPageGuard(router: Router) { |
|
const loadedPageMap = new Map<string, boolean>() |
|
|
|
router.beforeEach(async (to) => { |
|
// The page has already been loaded, it will be faster to open it again, you don’t need to do loading and other processing |
|
to.meta.loaded = !!loadedPageMap.get(to.path) |
|
// Notify routing changes |
|
setRouteChange(to) |
|
|
|
return true |
|
}) |
|
|
|
router.afterEach((to) => { |
|
loadedPageMap.set(to.path, true) |
|
}) |
|
} |
|
|
|
// Used to handle page loading status |
|
function createPageLoadingGuard(router: Router) { |
|
const userStore = useUserStoreWithOut() |
|
const appStore = useAppStoreWithOut() |
|
const { getOpenPageLoading } = useTransitionSetting() |
|
router.beforeEach(async (to) => { |
|
if (!userStore.getAccessToken) |
|
return true |
|
|
|
if (to.meta.loaded) |
|
return true |
|
|
|
if (unref(getOpenPageLoading)) { |
|
appStore.setPageLoadingAction(true) |
|
return true |
|
} |
|
|
|
return true |
|
}) |
|
router.afterEach(async () => { |
|
if (unref(getOpenPageLoading)) { |
|
// TODO Looking for a better way |
|
// The timer simulates the loading time to prevent flashing too fast, |
|
setTimeout(() => { |
|
appStore.setPageLoading(false) |
|
}, 220) |
|
} |
|
return true |
|
}) |
|
} |
|
|
|
/** |
|
* The interface used to close the current page to complete the request when the route is switched |
|
* @param router |
|
*/ |
|
function createHttpGuard(router: Router) { |
|
const { removeAllHttpPending } = projectSetting |
|
let axiosCanceler: Nullable<AxiosCanceler> |
|
if (removeAllHttpPending) |
|
axiosCanceler = new AxiosCanceler() |
|
|
|
router.beforeEach(async () => { |
|
// Switching the route will delete the previous request |
|
axiosCanceler?.removeAllPending() |
|
return true |
|
}) |
|
} |
|
|
|
// Routing switch back to the top |
|
function createScrollGuard(router: Router) { |
|
const isHash = (href: string) => { |
|
return href.startsWith('#') |
|
} |
|
|
|
const body = document.body |
|
|
|
router.afterEach(async (to) => { |
|
// scroll top |
|
isHash((to as RouteLocationNormalized & { href: string })?.href) && body.scrollTo(0, 0) |
|
return true |
|
}) |
|
} |
|
|
|
/** |
|
* Used to close the message instance when the route is switched |
|
* @param router |
|
*/ |
|
export function createMessageGuard(router: Router) { |
|
const { closeMessageOnSwitch } = projectSetting |
|
|
|
router.beforeEach(async () => { |
|
try { |
|
if (closeMessageOnSwitch) { |
|
Modal.destroyAll() |
|
notification.destroy() |
|
} |
|
} |
|
catch (error) { |
|
warn(`message guard error:${error as any}`) |
|
} |
|
return true |
|
}) |
|
} |
|
|
|
export function createProgressGuard(router: Router) { |
|
const { getOpenNProgress } = useTransitionSetting() |
|
router.beforeEach(async (to) => { |
|
if (to.meta.loaded) |
|
return true |
|
|
|
unref(getOpenNProgress) && nProgress.start() |
|
return true |
|
}) |
|
|
|
router.afterEach(async () => { |
|
unref(getOpenNProgress) && nProgress.done() |
|
return true |
|
}) |
|
}
|
|
|