import { createRouter, createWebHistory } from 'vue-router' import { useUserStore } from '@/stores/user-store' import { getToken } from '@/utils/auth' const router = createRouter({ history: createWebHistory(), routes: [ { path: '/login', name: 'Login', component: () => import('@/views/login/index.vue'), meta: { hidden: true } }, { path: '/profile', component: () => import('@/components/Layout/index.vue'), meta: { hidden: true }, children: [ { path: '', name: 'Profile', component: () => import('@/views/profile/index.vue'), meta: { title: '个人中心' } } ] }, { path: '/:pathMatch(.*)*', name: 'NotFound', component: () => import('@/views/error/404.vue'), meta: { hidden: true } }, { path: '/', component: () => import('@/components/Layout/index.vue'), redirect: '/dashboard', children: [ { path: 'dashboard', name: 'Dashboard', component: () => import('@/views/dashboard/index.vue'), meta: { title: '首页', icon: 'HomeFilled' } } ] }, { path: '/workbench', component: () => import('@/components/Layout/index.vue'), meta: { title: '工作台', icon: 'Monitor' }, children: [ { path: '', name: 'Workbench', component: () => import('@/views/workbench/index.vue'), meta: { title: '智能工作台', icon: 'Monitor' } } ] }, { path: '/analysis', component: () => import('@/components/Layout/index.vue'), redirect: '/analysis/flow', meta: { title: '数据看板', icon: 'TrendCharts' }, children: [ { path: 'flow', name: 'FlowAnalysis', component: () => import('@/views/analysis/index.vue'), meta: { title: '流程分析看板', icon: 'TrendCharts' } } ] }, { path: '/system', component: () => import('@/components/Layout/index.vue'), redirect: '/system/user', meta: { title: '系统管理', icon: 'Setting' }, children: [ { path: 'user', name: 'User', component: () => import('@/views/system/user/index.vue'), meta: { title: '用户管理', icon: 'UserFilled' } }, { path: 'role', name: 'Role', component: () => import('@/views/system/role/index.vue'), meta: { title: '审批角色', icon: 'User' } }, ] }, { path: '/flow', component: () => import('@/components/Layout/index.vue'), redirect: '/flow/definition', meta: { title: '流程管理', icon: 'Connection' }, children: [ { path: 'designer', name: 'FlowDesigner', component: () => import('@/views/flow/designer/index.vue'), meta: { title: '流程设计器', icon: 'EditPen' } }, { path: 'definition', name: 'FlowDefinition', component: () => import('@/views/flow/definition/index.vue'), meta: { title: '流程管理', icon: 'Document' } } ] }, { path: '/approval', component: () => import('@/components/Layout/index.vue'), redirect: '/approval/todo', meta: { title: '审批中心', icon: 'Stamp' }, children: [ { path: 'todo', name: 'Todo', component: () => import('@/views/flow/task/todo.vue'), meta: { title: '我的待办', icon: 'Bell' } }, { path: 'handled', name: 'Handled', component: () => import('@/views/flow/task/handled.vue'), meta: { title: '我的已办', icon: 'CircleCheck' } }, { path: 'cc', name: 'Cc', component: () => import('@/views/flow/task/cc.vue'), meta: { title: '我的抄送', icon: 'Message' } }, { path: 'mine', name: 'MyInstance', component: () => import('@/views/flow/instance/mine.vue'), meta: { title: '我的流程', icon: 'List' } }, { path: 'execute', name: 'FlowExecute', component: () => import('@/views/flow/execute/index.vue'), meta: { title: '流程执行', icon: 'Pointer' } }, { path: 'all', name: 'AllInstance', component: () => import('@/views/flow/instance/all.vue'), meta: { title: '流程明细', icon: 'Document' } } ] } ] }) const publicPaths = new Set(['/login']) // 按员工类型限制的路径 const permissionPaths: Record> = { common_user: new Set(['/', '/dashboard', '/login', '/profile', '/approval/todo', '/approval/handled', '/approval/mine', '/approval/execute', '/approval/cc']), dept_manager: new Set(['/', '/dashboard', '/login', '/profile', '/system/user', '/system/role', '/approval/todo', '/approval/handled', '/approval/mine', '/approval/execute', '/approval/cc']), flow_manager: new Set(['/', '/dashboard', '/login', '/profile', '/flow/designer', '/flow/definition', '/flow/instance/all', '/approval/todo', '/approval/handled', '/approval/mine', '/approval/execute', '/approval/cc', '/analysis']), super_admin: new Set(['/', '/dashboard', '/login', '/profile', '/system/user', '/system/role', '/flow/designer', '/flow/definition', '/flow/instance/all', '/approval/todo', '/approval/handled', '/approval/mine', '/approval/execute', '/approval/cc', '/analysis']) } function isPathAllowed(allowedSet: Set, path: string): boolean { if (allowedSet.has(path)) return true // 允许子路径,但父路径必须以 / 结尾或精确匹配 for (const allowed of allowedSet) { if (allowed !== '/' && path.startsWith(allowed + '/')) { return true } } return false } // 防止快速切换 tab 时并发多次拉取用户信息 let fetchingUserInfo: Promise | null = null router.beforeEach(async (to, from, next) => { const token = getToken() // 404、登录页等公开页面直接放行 if (publicPaths.has(to.path) || to.name === 'NotFound') { next() return } if (token) { const userStore = useUserStore() if (!userStore.userInfo) { try { if (!fetchingUserInfo) { fetchingUserInfo = userStore.fetchUserInfo().catch(async (err) => { await userStore.logoutAction() throw err }) } await fetchingUserInfo } catch { next(`/login?redirect=${to.path}`) return } finally { fetchingUserInfo = null } } // 按 employeeType 限制 const employeeType = userStore.userInfo?.employeeType || 'common_user' const allowedPaths = permissionPaths[employeeType] || permissionPaths['common_user'] if (!isPathAllowed(allowedPaths, to.path)) { next('/dashboard') return } next() } else { next(`/login?redirect=${to.path}`) } }) export default router