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.

232 lines
6.3 KiB

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 { createRouter, createWebHistory } from 'vue-router'
import Layout from '@/layout/index.vue'
import { useUserStore } from '@/stores/user'
// 进度条
import NProgress from 'nprogress'
import 'nprogress/nprogress.css'
// 基础路由(不需要权限)
export const constantRoutes = [
{
path: '/login',
name: 'login',
component: () => import('@/views/Login/index.vue'),
meta: { title: '登录' },
},
]
// 动态路由配置(需要权限)
export const asyncRoutes = [
{
path: 'SystemManage',
meta: { title: '系统管理', permissions: ['system'] },
redirect: `/SystemManage/UserManage`,
name: 'SystemManage',
children: [
{
path: 'UserManage',
name: 'UserManage',
component: () => import('@/views/UserManage/index.vue'),
meta: { title: '用户管理', permissions: ['user_management'] },
},
{
path: 'RoleManage',
name: 'RoleManage',
component: () => import('@/views/RoleManage/index.vue'),
meta: { title: '角色管理', permissions: ['role_management'] },
},
{
path: 'AuthManage',
name: 'AuthManage',
component: () => import('@/views/AuthManage/index.vue'),
meta: { title: '权限管理', permissions: ['permission_management'] },
},
],
},
{
path: 'ModelManage',
name: 'ModelManage',
component: () => import('@/views/ModelManage/index.vue'),
meta: { title: '模版管理', permissions: ['template'] },
},
{
path: 'ComboManage',
name: 'ComboManage',
component: () => import('@/views/ComboManage/index.vue'),
meta: { title: '套餐管理', permissions: ['membership_plan'] },
},
{
path: 'GenerateRecord',
name: 'GenerateRecord',
component: () => import('@/views/GenerateRecord/index.vue'),
meta: { title: '生成记录', permissions: ['generate_record'] },
},
{
path: 'OrderManage',
name: 'OrderManage',
component: () => import('@/views/OrderManage/index.vue'),
meta: { title: '订单管理', permissions: ['order_management'] },
},
{
path: 'NoPermission',
name: 'NoPermission',
component: () => import('@/views/NoPermission/index.vue'),
meta: { title: 'NoPermission', hide: true },
}
]
// 检查用户权限
function hasPermission(permissions, userPermissions) {
if (!permissions || permissions.length === 0) return true
if (useUserStore().userInfo?.isAdmin) return true
if (!userPermissions || userPermissions.length === 0) return false
return permissions.some(permission =>
userPermissions.some(userPerm => userPerm.code === permission)
)
}
// 过滤有权限的路由
function filterAsyncRoutes(routes, userPermissions) {
const filteredRoutes = []
routes.forEach(route => {
const temp = { ...route }
if (hasPermission(temp.meta?.permissions, userPermissions)) {
if (temp.children) {
temp.children = filterAsyncRoutes(temp.children, userPermissions)
}
filteredRoutes.push(temp)
}
})
if (filteredRoutes.length > 0) {
filteredRoutes.sort((a, b) => {
if (a.path === 'NoPermission') {
return 1
}
})
}
return filteredRoutes
}
// 生成动态路由
export function generateRoutes(userPermissions) {
const accessedRoutes = filterAsyncRoutes(asyncRoutes, userPermissions)
// 如果有可访问的路由,创建主布局路由
// console.log('accessedRoutes', accessedRoutes)
if (accessedRoutes.length > 0) {
const mainRoute = {
path: '/',
component: Layout,
name: 'index',
redirect: accessedRoutes[0].redirect || `/${accessedRoutes[0].path}`, // 重定向到第一个有权限的路由
children: accessedRoutes,
}
useUserStore().setRouterList(accessedRoutes || [])
return [mainRoute, ...constantRoutes]
}
return constantRoutes
}
export const routes = constantRoutes
const router = createRouter({
history: createWebHistory(import.meta.env.BASE_URL),
routes,
})
console.log('routerinit')
// 白名单
const whiteList = ['/login']
// 标记是否已添加动态路由
let hasAddRoutes = false
function flatten(arr) {
const res = []
arr.forEach(item => {
const { children, ...rest } = item
res.push(rest) // 当前节点
if (children && children.length > 0) {
res.push(...flatten(children)) // 递归子节点
}
})
return res
}
// 全局前置导航守卫
router.beforeEach(async (to, from, next) => {
// 开启进度条
NProgress.start()
// 如果没有 token并且不在白名单中则重定向到登录
if (!useUserStore().token && !whiteList.includes(to.path)) {
return next('/login')
}
// 如果有 token 但还没有添加动态路由
if (useUserStore().token && !hasAddRoutes) {
try {
// 获取用户权限
const userPermissions = flatten(useUserStore().userInfo?.menus || [])
// 生成有权限的路由
const accessRoutes = generateRoutes(userPermissions)
// 清除现有路由
router.getRoutes().forEach(route => {
if (route.name && route.name !== 'login') {
router.removeRoute(route.name)
}
})
// 添加新的动态路由
accessRoutes.forEach(route => {
router.addRoute(route)
})
hasAddRoutes = true
// 如果当前访问的是根路径,重定向到第一个有权限的页面
if (to.path === '/') {
const firstRoute = accessRoutes.find(route => route.path === '/')
if (firstRoute && firstRoute.children && firstRoute.children.length > 0) {
return next(`/${firstRoute.children[0].path}`)
}
}
// 重新导航到目标路由
return next({ ...to, replace: true })
} catch (error) {
console.error('生成路由失败:', error)
// 清除用户信息并重定向到登录
useUserStore().logout()
return next('/login')
}
}
next()
})
// 全局后置导航守卫
router.afterEach((to) => {
document.title = `${to.meta.title || ''}-智能电梯图纸生成后台`
// 关闭进度条
NProgress.done()
})
// 重置路由(用于退出登录时)
export function resetRouter() {
hasAddRoutes = false
// 清除动态添加的路由
router.getRoutes().forEach(route => {
if (route.name && route.name !== 'login') {
router.removeRoute(route.name)
}
})
}
export default router