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

5.1 KiB
Raw Blame History

菜单权限功能前后端对接分析报告

分析时间

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获取方式

    // 当前硬编码为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. 数据结构兼容

    // 前端 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. 后端优化 (高优先级)

// 修改 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中等 (状态管理和数据处理)
  • 动态菜单组件:中等 (递归组件渲染)
  • 权限指令:简单 (基础指令实现)

建议实施顺序

  1. 修复后端用户ID获取逻辑
  2. 实现前端菜单 Store
  3. 创建动态菜单组件
  4. 集成到布局组件中
  5. 实现权限指令用于按钮控制

整体评估:前后端对接可行性较高,主要工作集中在前端动态菜单实现上。