Files
1818uniapp-admin/src/router/index.js

283 lines
7.6 KiB
JavaScript
Raw Normal View History

import { createRouter, createWebHistory } from 'vue-router'
import NProgress from 'nprogress'
import 'nprogress/nprogress.css'
import { getToken } from '@/utils/auth'
import { useUserStore } from '@/store/modules/user'
NProgress.configure({ showSpinner: false })
// 静态路由
export const constantRoutes = [
{
path: '/',
component: () => import('@/layouts/BasicLayout.vue'),
redirect: '/dashboard',
meta: { title: '首页', icon: 'DashboardOutlined' },
children: [
{
path: 'dashboard',
name: 'Dashboard',
component: () => import('@/views/dashboard/index.vue'),
meta: { title: '控制台', icon: 'DashboardOutlined' }
}
]
},
{
path: '/login',
name: 'Login',
component: () => import('@/views/login/index.vue'),
meta: { title: '登录', hidden: true }
},
{
path: '/403',
name: '403',
component: () => import('@/views/error/403.vue'),
meta: { title: '无权限', hidden: true }
},
{
path: '/404',
name: '404',
component: () => import('@/views/error/404.vue'),
meta: { title: '页面不存在', hidden: true }
}
]
// 动态路由(根据权限加载)
export const asyncRoutes = [
{
path: '/user',
component: () => import('@/layouts/BasicLayout.vue'),
redirect: '/user/list',
meta: { title: '用户管理', icon: 'TeamOutlined' },
children: [
{
path: 'list',
name: 'UserList',
component: () => import('@/views/user/list.vue'),
meta: { title: '用户列表', icon: 'UnorderedListOutlined' }
}
]
},
{
path: '/order',
component: () => import('@/layouts/BasicLayout.vue'),
redirect: '/order/list',
meta: { title: '订单管理', icon: 'ShoppingOutlined' },
children: [
{
path: 'list',
name: 'OrderList',
component: () => import('@/views/order/list.vue'),
meta: { title: '订单列表', icon: 'UnorderedListOutlined' }
}
]
},
{
path: '/work',
component: () => import('@/layouts/BasicLayout.vue'),
redirect: '/work/list',
meta: { title: '作品管理', icon: 'PictureOutlined' },
children: [
{
path: 'list',
name: 'WorkList',
component: () => import('@/views/work/list.vue'),
meta: { title: '作品列表', icon: 'FileImageOutlined' }
},
{
path: 'audit',
name: 'WorkAudit',
component: () => import('@/views/work/audit.vue'),
meta: { title: '作品审核', icon: 'AuditOutlined' }
},
{
path: 'category',
name: 'WorkCategory',
component: () => import('@/views/work/category.vue'),
meta: { title: '分类管理', icon: 'AppstoreOutlined' }
}
]
},
{
path: '/ai',
component: () => import('@/layouts/BasicLayout.vue'),
redirect: '/ai/provider',
meta: { title: 'AI管理', icon: 'RobotOutlined' },
children: [
{
path: 'provider',
name: 'AiProvider',
component: () => import('@/views/ai/provider.vue'),
meta: { title: 'AI厂商', icon: 'CloudServerOutlined' }
},
{
path: 'model',
name: 'AiModel',
component: () => import('@/views/ai/model.vue'),
meta: { title: 'AI模型', icon: 'ApiOutlined' }
},
{
path: 'task',
name: 'AiTask',
component: () => import('@/views/ai/task.vue'),
meta: { title: 'AI任务', icon: 'ScheduleOutlined' }
},
{
path: 'debug',
name: 'AiDebug',
component: () => import('@/views/ai/debug.vue'),
meta: { title: 'AI调试', icon: 'BugOutlined' }
}
]
},
{
path: '/config',
component: () => import('@/layouts/BasicLayout.vue'),
redirect: '/config/reward',
meta: { title: '系统配置', icon: 'SettingOutlined' },
children: [
{
path: 'reward',
name: 'RewardConfig',
component: () => import('@/views/config/reward.vue'),
meta: { title: '奖励配置', icon: 'GiftOutlined' }
},
{
path: 'redeem',
name: 'RedeemConfig',
component: () => import('@/views/config/redeem.vue'),
meta: { title: '兑换码管理', icon: 'KeyOutlined' }
},
{
path: 'vip',
name: 'VipConfig',
component: () => import('@/views/config/vip.vue'),
meta: { title: 'VIP套餐', icon: 'CrownOutlined' }
},
{
path: 'points',
name: 'PointsConfig',
component: () => import('@/views/config/points.vue'),
meta: { title: '积分套餐', icon: 'StarOutlined' }
},
{
path: 'banner',
name: 'BannerConfig',
component: () => import('@/views/config/banner.vue'),
meta: { title: 'Banner管理', icon: 'FileImageOutlined' }
},
{
path: 'notice',
name: 'NoticeConfig',
component: () => import('@/views/config/notice.vue'),
meta: { title: '公告管理', icon: 'NotificationOutlined' }
}
]
},
{
path: '/system',
component: () => import('@/layouts/BasicLayout.vue'),
redirect: '/system/admin',
meta: { title: '系统管理', icon: 'ToolOutlined' },
children: [
{
path: 'admin',
name: 'AdminList',
component: () => import('@/views/system/admin.vue'),
meta: { title: '管理员管理', icon: 'UserOutlined' }
},
{
path: 'role',
name: 'RoleList',
component: () => import('@/views/system/role.vue'),
meta: { title: '角色管理', icon: 'SafetyOutlined' }
},
{
path: 'permission',
name: 'PermissionList',
component: () => import('@/views/system/permission.vue'),
meta: { title: '权限管理', icon: 'KeyOutlined' }
}
]
},
{ path: '/:pathMatch(.*)*', name: 'NotFound', redirect: '/404', meta: { hidden: true } }
]
const router = createRouter({
history: createWebHistory(),
routes: constantRoutes
})
// 白名单
const whiteList = ['/login', '/403', '/404']
// 标记是否已添加动态路由
let dynamicRoutesAdded = false
// 添加动态路由
function addDynamicRoutes() {
if (dynamicRoutesAdded) return
asyncRoutes.forEach(route => router.addRoute(route))
dynamicRoutesAdded = true
}
// 重置路由(登出时调用)
export function resetRouter() {
dynamicRoutesAdded = false
// 移除动态添加的路由
asyncRoutes.forEach(route => {
if (route.name && router.hasRoute(route.name)) {
router.removeRoute(route.name)
}
})
}
// 路由守卫
router.beforeEach(async (to, _from, next) => {
NProgress.start()
const token = getToken()
if (token) {
if (to.path === '/login') {
next({ path: '/' })
} else {
// 确保动态路由已添加
addDynamicRoutes()
const userStore = useUserStore()
// 确保用户信息已获取(包含权限和角色)
if (!userStore.userInfo || !userStore.roles.length) {
try {
await userStore.getUserInfo()
} catch (error) {
console.error('获取用户信息失败', error)
// Token可能已失效跳转登录
userStore.resetState()
next(`/login?redirect=${to.path}`)
return
}
}
// 检查路由是否存在
if (router.hasRoute(to.name) || to.matched.length > 0) {
next()
} else {
// 路由刚添加,需要重新导航
next({ ...to, replace: true })
}
}
} else {
if (whiteList.includes(to.path)) {
next()
} else {
next(`/login?redirect=${to.path}`)
}
}
})
router.afterEach(() => {
NProgress.done()
})
export default router