5.1 KiB
5.1 KiB
菜单权限功能前后端对接分析报告
分析时间
2025-08-26
项目概述
- 后端: Spring Boot + MyBatis-Plus + JWT
- 前端: Vue 3 + TypeScript + Element Plus + Pinia
后端菜单权限现状
✅ 已实现的功能
-
数据库设计完整
sys_menu: 菜单表,包含层级结构sys_role_menu: 角色菜单关联表sys_user_role: 用户角色关联表
-
接口权限控制
- 使用
@PreAuthorize注解控制接口访问权限 - JWT token 身份验证机制
- 使用
-
菜单管理接口完整
GET /menus/tree: 查询完整菜单树(管理用)GET /menus/user-tree: 查询用户菜单树(权限过滤)- 完整的 CRUD 操作接口
-
权限查询方法
getUserPermissions(userId): 获取用户权限列表getUserMenuTree(userId): 获取用户可访问的菜单树
⚠️ 存在的问题
-
用户ID获取方式
// 当前硬编码为1L,需要从JWT获取真实用户ID List<SysMenu> result = menuService.getUserMenuTree(1L); -
权限验证机制
- 后端有权限控制,但前端路由未集成权限验证
前端菜单权限现状
✅ 已实现的功能
-
用户状态管理
- Pinia store 管理用户信息、权限、角色
- JWT token 持久化存储
-
基础路由守卫
- 登录状态验证
- 基础的路由重定向
-
菜单 API 接口
- 已定义完整的菜单相关 API 方法
- TypeScript 类型定义完整
❌ 缺失的功能
-
动态菜单渲染
- 当前侧边栏菜单是静态硬编码的
- 没有基于权限的动态菜单生成
-
菜单权限控制
- 没有菜单 store 管理菜单状态
- 没有基于用户权限的菜单过滤
-
动态路由生成
- 路由配置是静态的
- 没有根据用户权限动态生成路由
前后端对接可行性分析
✅ 对接优势
-
API 接口完备
- 后端提供
/menus/user-tree接口获取用户菜单 - 前端已有对应的
getUserMenuTree()方法
- 后端提供
-
数据结构兼容
// 前端 Menu 类型与后端 SysMenu 实体匹配度高 interface Menu { id: number menuName: string parentId: number path: string component: string menuType: string // M=目录, C=菜单, F=按钮 permission: string icon: string visible: number status: number children?: Menu[] } -
权限体系完整
- 后端:基于角色的权限控制(RBAC)
- 前端:用户 store 已存储权限和角色信息
⚠️ 对接挑战
-
菜单类型映射
- 需要将后端菜单类型(M/C/F)映射到前端路由类型
-
动态组件加载
- 需要将后端 component 路径转换为前端组件导入
-
权限指令实现
- 需要实现 v-permission 等权限指令用于按钮级权限控制
实现方案建议
1. 后端优化 (高优先级)
// 修改 SysMenuController.getUserMenuTree()
@GetMapping("/user-tree")
@Operation(summary = "查询用户菜单树")
public Result<List<SysMenu>> getUserMenuTree() {
Long userId = SecurityUtils.getCurrentUserId(); // 从JWT获取用户ID
List<SysMenu> result = menuService.getUserMenuTree(userId);
return Result.success(result);
}
2. 前端菜单 Store 实现 (高优先级)
// 新增 src/stores/menu.ts
export const useMenuStore = defineStore('menu', () => {
const menuTree = ref<Menu[]>([])
const flatMenus = ref<Menu[]>([])
const loadUserMenus = async () => {
const response = await getUserMenuTree()
menuTree.value = response.data
flatMenus.value = flattenMenus(response.data)
}
return { menuTree, flatMenus, loadUserMenus }
})
3. 动态菜单组件 (中优先级)
<!-- 新增 src/components/DynamicMenu.vue -->
<template>
<el-menu>
<template v-for="menu in menuTree" :key="menu.id">
<DynamicMenuItem :menu="menu" />
</template>
</el-menu>
</template>
4. 权限指令实现 (中优先级)
// 新增 src/directives/permission.ts
app.directive('permission', {
mounted(el, binding) {
const { hasPermission } = useUserStore()
if (!hasPermission(binding.value)) {
el.remove()
}
}
})
结论
前后端菜单权限功能具备良好的对接基础:
✅ 可以立即对接的部分:
- API 接口调用
- 基础权限验证
- 菜单数据获取
⚠️ 需要开发的关键功能:
- 动态菜单渲染组件
- 菜单状态管理 Store
- 权限指令和按钮级权限控制
📈 实现难度评估:
- 后端调整:简单 (主要是用户ID获取)
- 前端菜单Store:中等 (状态管理和数据处理)
- 动态菜单组件:中等 (递归组件渲染)
- 权限指令:简单 (基础指令实现)
建议实施顺序:
- 修复后端用户ID获取逻辑
- 实现前端菜单 Store
- 创建动态菜单组件
- 集成到布局组件中
- 实现权限指令用于按钮控制
整体评估:前后端对接可行性较高,主要工作集中在前端动态菜单实现上。