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