Files
MedicineManagerSystem/frontend/src/router/index.js
KiriAky 107 258bae75b2 添加后端基础架构和API功能
- 配置.env文件支持环境变量管理
- 集成MyBatis Plus ORM框架并配置数据库连接
- 实现JWT认证和Spring Security安全配置
- 添加全局异常处理机制和统一响应结果封装
- 配置CORS跨域资源共享支持
- 实现用户认证API包括登录、注册、刷新token功能
- 开发完整的药品管理系统包含分类、药品、库存管理
- 实现出入库管理功能包括供应商、客户管理
- 添加角色权限管理和菜单配置
- 实现仪表盘统计和过期预警功能
- 配置分页查询和数据验证功能
```
2026-07-06 20:04:44 +08:00

116 lines
3.2 KiB
JavaScript

import { createRouter, createWebHistory } from 'vue-router'
import { useUserStore } from '@/stores/user'
import MainLayout from '@/layout/MainLayout.vue'
// 静态路由(无需权限)
const constantRoutes = [
{
path: '/login',
name: 'Login',
component: () => import('@/views/login/LoginView.vue'),
meta: { title: '登录', noAuth: true },
},
{
path: '/register',
name: 'Register',
component: () => import('@/views/login/RegisterView.vue'),
meta: { title: '注册', noAuth: true },
},
{
path: '/',
name: 'MainLayout',
component: MainLayout,
redirect: '/dashboard',
children: [
{
path: 'dashboard',
name: 'Dashboard',
component: () => import('@/views/dashboard/DashboardView.vue'),
meta: { title: '仪表盘', icon: 'Odometer' },
},
],
},
{
path: '/:pathMatch(.*)*',
redirect: '/dashboard',
},
]
const router = createRouter({
history: createWebHistory(),
routes: constantRoutes,
})
// 动态路由映射(后端菜单 component 路径 → 页面组件)
export const componentMap = {
'views/medicine/MedicineList': () => import('@/views/medicine/MedicineList.vue'),
'views/category/CategoryList': () => import('@/views/category/CategoryList.vue'),
'views/supplier/SupplierList': () => import('@/views/supplier/SupplierList.vue'),
'views/customer/CustomerList': () => import('@/views/customer/CustomerList.vue'),
'views/stock/StockList': () => import('@/views/stock/StockList.vue'),
'views/stockIn/StockInList': () => import('@/views/stockIn/StockInList.vue'),
'views/stockIn/StockInForm': () => import('@/views/stockIn/StockInForm.vue'),
'views/stockOut/StockOutList': () => import('@/views/stockOut/StockOutList.vue'),
'views/stockOut/StockOutForm': () => import('@/views/stockOut/StockOutForm.vue'),
'views/user/UserList': () => import('@/views/user/UserList.vue'),
'views/role/RoleList': () => import('@/views/role/RoleList.vue'),
'views/menu/MenuList': () => import('@/views/menu/MenuList.vue'),
}
// 根据后端菜单数据生成路由
function generateRoutes(menus) {
const routes = []
menus.forEach((menu) => {
if (menu.type === 2 && menu.path && menu.component) {
routes.push({
path: menu.path.toLowerCase(),
name: menu.name,
component: componentMap[menu.component] || null,
meta: { title: menu.name, icon: menu.icon },
})
}
if (menu.children?.length) {
routes.push(...generateRoutes(menu.children))
}
})
return routes
}
let isMenusLoaded = false
router.beforeEach(async (to, _from, next) => {
const userStore = useUserStore()
if (to.meta.noAuth) {
next()
return
}
if (!userStore.token) {
next('/login')
return
}
// 动态注册菜单路由(仅首次)
if (!isMenusLoaded) {
try {
const menus = await userStore.getMenus()
if (menus.length) {
const dynamicRoutes = generateRoutes(menus)
dynamicRoutes.forEach((route) => {
router.addRoute('MainLayout', route)
})
}
} catch {
// 后端未启动,跳过
}
isMenusLoaded = true
next({ ...to, replace: true })
return
}
next()
})
export default router