feat(权限): 实现基于角色的路由权限控制

- 新增路由元信息类型定义 (requiresAuth, roles, title)
- 实现路由守卫中的角色权限校验逻辑
- 新增 403 禁止访问页面
- 提取权限校验函数 checkRoutePermission,提高可测试性
- 修复 JSON.parse 异常处理,增强健壮性
- 优化页面标题动态设置

测试优化:
- 重构 global-setup.ts,支持 JAR 文件启动后端服务
- 优化测试用例等待逻辑,减少硬编码延迟
- 简化 playwright 配置,移除多浏览器支持
- 新增路由权限守卫单元测试

关联需求:权限系统完善
This commit is contained in:
张翔
2026-04-08 15:29:03 +08:00
parent 9b2c8a47a4
commit 7420afa380
23 changed files with 933 additions and 349 deletions
@@ -17,6 +17,9 @@
active-text-color="#409eff"
router
>
<div v-if="menuTree.length === 0" style="padding: 20px; text-align: center; color: #999;">
菜单加载中...
</div>
<menu-item
v-for="menu in menuTree"
:key="menu.id"
@@ -75,7 +78,9 @@ const username = ref(localStorage.getItem('username') || 'Admin')
const permissionStore = usePermissionStore()
const activeMenu = computed(() => route.path)
const menuTree = computed(() => permissionStore.menus)
const menuTree = computed(() => {
return permissionStore.menus
})
const handleCommand = (command: string) => {
if (command === 'profile') {
@@ -87,12 +92,21 @@ const handleCommand = (command: string) => {
}
}
onMounted(() => {
onMounted(async () => {
const token = localStorage.getItem('token')
if (!token) {
router.push('/login')
} else if (!permissionStore.loaded) {
permissionStore.initFromStorage()
if (!permissionStore.loaded || permissionStore.menus.length === 0) {
try {
await permissionStore.fetchUserMenus()
} catch (error) {
console.error('获取用户菜单失败:', error)
}
}
}
})
</script>