Files
pengcheng-exam-teacher/src/permission.ts
2025-08-15 15:33:15 +08:00

154 lines
5.5 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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'
import { useAppStoreWithOut } from '@/store/modules/app'
import { CACHE_KEY, useCache } from '@/hooks/web/useCache'
const { wsCache } = useCache()
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 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: '/dashboard' }) // 已登录时访问登录页,重定向到首页
} else {
// 获取所有字典
const dictStore = useDictStoreWithOut()
const userStore = useUserStoreWithOut()
const permissionStore = usePermissionStoreWithOut()
const appStore = useAppStoreWithOut()
// 根据路由自动切换布局 - 只有当前路径是dashboard时才使用dashboard布局
if (to.path === '/dashboard' || to.path === '/') {
appStore.setLayout('dashboard')
appStore.setFixedHeader(true) // 设置header固定
} else {
// 获取当前保存的布局设置如果不是dashboard就恢复到之前的设置
const currentLayout = appStore.getLayout
if (currentLayout === 'dashboard') {
// 恢复到默认布局或从缓存中获取之前的布局
const cachedLayout = wsCache.get(CACHE_KEY.LAYOUT) || 'classic'
appStore.setLayout(cachedLayout === 'dashboard' ? 'classic' : cachedLayout)
appStore.setFixedHeader(true) // 保持header固定
}
}
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 { paramsObject: query } = parseURL(redirect)
// 如果重定向路径是根路径或不存在的路径,改为首页
const finalRedirect = (redirect === '/' || redirect === '/index') ? '/dashboard' : redirect
console.log('Permission guard - first time setting user, redirecting to:', finalRedirect) // 调试日志
const nextData = to.path === finalRedirect ? { ...to, replace: true } : { path: finalRedirect, query }
next(nextData)
} else {
// 即使用户信息已设置,也要检查是否需要重定向到首页
if (to.path === '/' || (to.path === '/login' && from.query.redirect)) {
// 从登录页跳转过来,或者访问根路径,重定向到首页
console.log('Permission guard - redirecting to dashboard from:', to.path) // 调试日志
next({ path: '/dashboard', replace: true })
} else {
console.log('Permission guard - allowing navigation to:', to.path) // 调试日志
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()
// 路由切换后的布局处理
const appStore = useAppStoreWithOut()
if (to.path === '/dashboard' || to.path === '/') {
appStore.setLayout('dashboard')
appStore.setFixedHeader(true) // 设置header固定
} else {
const currentLayout = appStore.getLayout
if (currentLayout === 'dashboard') {
// 恢复到默认布局
appStore.setLayout('classic')
appStore.setFixedHeader(true) // 保持header固定
}
}
})