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

147 lines
4.7 KiB
TypeScript

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

import router from './router'
import type { RouteRecordRaw } from 'vue-router'
import { isRelogin } from '@/config/axios/service'
import { getAccessToken } from '@/utils/auth'
import { useTitle } from '@/hooks/web/useTitle'
import { useNProgress } from '@/hooks/web/useNProgress'
import { usePageLoading } from '@/hooks/web/usePageLoading'
import { useDictStoreWithOut } from '@/store/modules/dict'
import { useUserStoreWithOut } from '@/store/modules/user'
import { usePermissionStoreWithOut } from '@/store/modules/permission'
const { start, done } = useNProgress()
const { loadStart, loadDone } = usePageLoading()
const parseURL = (
url: string | null | undefined
): { basePath: string; paramsObject: { [key: string]: string } } => {
// 如果输入为 null 或 undefined返回空字符串和空对象
if (url == null) {
return { basePath: '', paramsObject: {} }
}
// 找到问号 (?) 的位置,它之前是基础路径,之后是查询参数
const questionMarkIndex = url.indexOf('?')
let basePath = url
const paramsObject: { [key: string]: string } = {}
// 如果找到了问号,说明有查询参数
if (questionMarkIndex !== -1) {
// 获取 basePath
basePath = url.substring(0, questionMarkIndex)
// 从 URL 中获取查询字符串部分
const queryString = url.substring(questionMarkIndex + 1)
// 使用 URLSearchParams 遍历参数
const searchParams = new URLSearchParams(queryString)
searchParams.forEach((value, key) => {
// 封装进 paramsObject 对象
paramsObject[key] = value
})
}
// 返回 basePath 和 paramsObject
return { basePath, paramsObject }
}
const resolveChildPath = (parentPath: string, childPath: string) => {
if (!childPath) return parentPath
if (childPath.startsWith('/')) return childPath
const p = parentPath.endsWith('/') ? parentPath.slice(0, -1) : parentPath
return `${p}/${childPath}`.replace(/\/+/g, '/')
}
const resolveFirstMenuPath = (routes: any[], parentPath = ''): string | undefined => {
for (const r of routes ?? []) {
if (!r) continue
if (typeof r?.path === 'string' && r.path.includes(':path(.*)*')) continue
if (r?.meta?.hidden === true) continue
if (typeof r.redirect === 'string' && r.redirect.trim()) {
const redirect = r.redirect.trim()
if (redirect !== '/') return redirect
}
const currentPath = parentPath ? resolveChildPath(parentPath, String(r.path ?? '')) : String(r.path ?? '')
const childPath = resolveFirstMenuPath(r.children, currentPath)
if (childPath) return childPath
if (currentPath) return currentPath
}
return undefined
}
// 路由不重定向白名单
const whiteList = [
'/login',
'/social-login',
'/auth-redirect',
'/bind',
'/register',
'/oauthLogin/gitee'
]
// 路由加载前
router.beforeEach(async (to, from, next) => {
start()
loadStart()
if (getAccessToken()) {
if (to.path === '/login') {
next({ path: '/' })
} else {
// 获取所有字典
const dictStore = useDictStoreWithOut()
const userStore = useUserStoreWithOut()
const permissionStore = usePermissionStoreWithOut()
if (!dictStore.getIsSetDict) {
await dictStore.setDictMap()
}
if (!userStore.getIsSetUser) {
isRelogin.show = true
await userStore.setUserInfoAction()
isRelogin.show = false
// 后端过滤菜单
await permissionStore.generateRoutes()
permissionStore.getAddRouters.forEach((route) => {
router.addRoute(route as unknown as RouteRecordRaw) // 动态添加可访问路由表
})
const redirectPath = from.query.redirect || to.path
const redirect = decodeURIComponent(redirectPath as string)
const { basePath, paramsObject: query } = parseURL(redirect)
let targetPath = redirect
let targetQuery = query
if (basePath === '/' || basePath === '') {
targetPath = resolveFirstMenuPath(permissionStore.addRouters) ?? '/empty'
targetQuery = {}
}
const nextData = to.path === targetPath ? { ...to, replace: true } : { path: targetPath, query: targetQuery }
next(nextData)
} else {
if (to.path === '/') {
const firstMenuPath = resolveFirstMenuPath(permissionStore.addRouters) ?? '/empty'
if (firstMenuPath === '/') {
next()
} else {
next({ path: firstMenuPath, replace: true })
}
return
}
next()
}
}
} else {
if (whiteList.indexOf(to.path) !== -1) {
next()
} else {
next(`/login?redirect=${to.fullPath}`) // 否则全部重定向到登录页
}
}
})
router.afterEach((to) => {
useTitle(to?.meta?.title as string)
done() // 结束Progress
loadDone()
})