|
|
|
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}`)
|
|
|
|
}
|
|
|
|
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
|
|
|
|
})
|
|
|
|
}
|