fix:完善相关页面

This commit is contained in:
liangdong
2025-12-30 19:08:31 +08:00
parent fa4de6f71f
commit bfb6a1e500
22 changed files with 1886 additions and 23 deletions

View File

@@ -1,16 +1,204 @@
import { createWebHistory, createRouter } from 'vue-router'
import { createWebHistory, createRouter, type RouteRecordRaw } from 'vue-router'
import { useUserStore } from '@/store'
import { getRouteMenus } from '@/api'
import useTokenRefresh from '@/hooks/useTokenRefresh'
import Login from '@/pages/Login/index.vue';
import HomeView from '@/pages/Layout/index.vue';
const routes = [
{ path: '/', component: HomeView },
{ path: '/login', component: Login },
const baseUrl = import.meta.env.VITE_APP_BASE_API || '';
// 基础路由(不需要权限验证)
const constantRoutes: RouteRecordRaw[] = [
{
path: '/login',
name: 'Login',
component: Login,
meta: {
title: '登录',
requiresAuth: false
}
},
]
// 动态路由(需要权限验证)
const asyncRoutes: RouteRecordRaw[] = [
{
path: '/',
name: 'Layout',
component: HomeView,
redirect: '/home',
meta: {
requiresAuth: true,
},
children: [] as RouteRecordRaw[],
},
]
const router = createRouter({
history: createWebHistory(),
routes,
routes: [...constantRoutes, ...asyncRoutes],
})
// 白名单路由(不需要登录即可访问)
const whiteList = ['/login']
// 1. 预先加载所有可能的页面组件
// 这里的路径模式要覆盖到你所有的业务组件
const modules = import.meta.glob('@/pages/**/*.vue')
const loadComponent = (componentPath: string) => {
if (!componentPath) return null
// 统一路径格式处理
let fullPath = ''
if (componentPath.startsWith('@/')) {
fullPath = componentPath
} else if (componentPath.includes('/')) {
// 补全路径,确保以 @/pages 开头
fullPath = componentPath.startsWith('pages/') ? `@/${componentPath}` : `@/pages/${componentPath}`
} else {
// 补全 index.vue
fullPath = `@/pages/${componentPath}/index.vue`
}
// 重点:将 @/ 转换为 /src/,因为 glob 默认生成的 key 是相对于项目根目录的
const key = fullPath.replace('@/', '/src/')
// 从 modules 中查找对应的导入函数
if (modules[key]) {
return modules[key]
} else {
console.error(`未找到组件文件: ${key}. 请检查路径或大小写。`)
return null
}
}
// 将后端返回的路由数据转换为 Vue Router 路由
const transformRoutes = (routes: any[]): RouteRecordRaw[] => {
return routes.map((route) => {
const component = route.component ? loadComponent(route.component) : undefined
// 构建基础路由对象
const routeRecord: any = {
path: route.path,
name: route.name || route.path,
meta: {
title: route.meta?.title || route.title || route.name,
icon: route.meta?.icon || route.icon,
requiresAuth: route.meta?.requiresAuth !== false, // 默认需要权限
roles: route.meta?.roles || route.roles,
...route.meta,
},
}
// 如果有组件,添加组件属性
if (component) {
routeRecord.component = component
}
// 处理子路由
if (route.children && route.children.length > 0) {
routeRecord.children = transformRoutes(route.children)
}
return routeRecord as RouteRecordRaw
})
}
// 添加动态路由
const addDynamicRoutes = async () => {
const userStore = useUserStore()
// 如果路由已加载,直接返回
if (userStore.isRoutesLoaded) {
return
}
try {
// 从后端获取路由菜单数据
const response = await getRouteMenus()
if (response.code === 0 && response.data) {
// 转换路由数据
const dynamicRoutes = transformRoutes(Array.isArray(response.data) ? response.data : [response.data])
// 将动态路由添加到 Layout 的 children 中
const layoutRoute = router.getRoutes().find(route => route.name === 'Layout')
console.log('Layout route:', layoutRoute,dynamicRoutes)
if (layoutRoute) {
dynamicRoutes.forEach(route => {
router.addRoute('Layout', route)
})
} else {
// 如果找不到 Layout 路由,直接添加到根路由
dynamicRoutes.forEach(route => {
router.addRoute(route)
})
}
// 保存路由数据到 store
userStore.setRoutes(response.data)
// 标记路由已加载
userStore.isRoutesLoaded = true
}
} catch (error) {
console.error('Failed to load routes:', error)
// 如果获取路由失败,清除用户数据并跳转到登录页
userStore.clearUserData()
router.push('/login')
}
}
// 路由导航守卫
router.beforeEach(async (to, _from, next) => {
const userStore = useUserStore()
const { getAccessToken } = useTokenRefresh(baseUrl)
// 获取 token
const token = getAccessToken() || userStore.token
// 如果已登录,更新 store 中的 token
if (token) {
userStore.setToken(token)
}
// 判断是否在白名单中
if (whiteList.includes(to.path)) {
// 如果在白名单中且已登录,重定向到首页
if (token) {
next('/')
} else {
next()
}
return
}
// 需要登录验证
if (!token) {
// 未登录,重定向到登录页
next({
path: '/login',
query: { redirect: to.fullPath }, // 保存当前路径,登录后可以跳转回来
})
return
}
// 已登录,检查路由是否已加载
if (!userStore.isRoutesLoaded) {
try {
// 加载动态路由
await addDynamicRoutes()
// 路由加载完成后,重新导航到目标路由
next({ ...to, replace: true })
} catch (error) {
console.error('Route loading error:', error)
next('/login')
}
} else {
// 路由已加载,直接放行
next()
}
})
export default router