ai-admin/docs/菜单权限分析报告.md

201 lines
5.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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