7.1 KiB
7.1 KiB
菜单权限与操作权限分离修复报告
问题描述
用户反映:用户"12.27新增姓名"设置了用户专属权限后,不仅操作按钮被隐藏了,连菜单也全部隐藏了。用户要求菜单权限和操作权限应该是两个独立的东西:
- 菜单权限:控制左侧菜单栏的显示/隐藏(如"装车订单"菜单项)
- 操作权限:控制页面内操作按钮的显示/隐藏(如"编辑"、"删除"等按钮)
问题根本原因
1. 权限类型混淆
我之前的修改将菜单权限和操作权限混淆了:
- 菜单权限:应该只包含菜单项(type=0,1),用于控制左侧菜单栏
- 操作权限:应该包含操作按钮(type=2),用于控制页面内的按钮
2. getUserMenus API 的问题
文件:tradeCattle/aiotagro-cattle-trade/src/main/java/com/aiotagro/cattletrade/business/service/impl/LoginServiceImpl.java
错误的修改(第147-171行):
@Override
public AjaxResult getUserMenus() {
// 使用修改后的权限查询逻辑(优先使用用户专属权限)
List<String> permissions = queryUserPermissions(userId, user.getRoleId());
// 根据权限查询菜单
List<SysMenu> menus;
if (permissions.contains(RoleConstants.ALL_PERMISSION)) {
// 超级管理员:返回所有菜单
menus = menuMapper.selectList(null);
} else {
// 普通用户:根据权限查询菜单
menus = menuMapper.selectMenusByPermissions(permissions);
}
}
问题:queryUserPermissions 方法返回的是所有权限(包括操作按钮权限),但是 getUserMenus API 应该只返回菜单权限。
3. 权限查询逻辑错误
queryUserPermissions 方法会返回所有类型的权限(菜单+操作按钮),但是菜单权限查询应该只返回菜单项,不包含操作按钮。
修复方案
1. 分离菜单权限和操作权限查询
创建两个独立的查询方法:
queryUserMenus:专门查询菜单权限(只包含菜单项,不包含操作按钮)queryUserPermissions:专门查询操作权限(包含所有权限,用于按钮控制)
2. 修改 getUserMenus API
修改文件:tradeCattle/aiotagro-cattle-trade/src/main/java/com/aiotagro/cattletrade/business/service/impl/LoginServiceImpl.java
修改内容:
@Override
public AjaxResult getUserMenus() {
Integer userId = SecurityUtil.getCurrentUserId();
// 获取当前用户的角色ID
SysUser user = userMapper.selectById(userId);
if (user == null) {
return AjaxResult.error("用户不存在");
}
// 菜单权限查询:优先使用用户专属菜单权限,否则使用角色菜单权限
List<SysMenu> menus = queryUserMenus(userId, user.getRoleId());
log.info("=== 用户 {} 菜单查询结果,菜单数量: {}", userId, menus.size());
return AjaxResult.success("查询成功", menus);
}
3. 添加 queryUserMenus 方法
新增方法:
/**
* 查询用户菜单权限(优先使用用户专属菜单权限)
*
* @param userId 用户ID
* @param roleId 角色ID
* @return 菜单列表
*/
private List<SysMenu> queryUserMenus(Integer userId, Integer roleId) {
if (userId == null || roleId == null) {
return Collections.emptyList();
}
// 1. 先查询用户专属菜单权限(只查询菜单,不查询操作按钮)
List<SysMenu> userMenus = sysUserMenuMapper.selectMenusByUserId(userId);
if (userMenus != null && !userMenus.isEmpty()) {
// 过滤掉操作按钮(type=2),只保留菜单(type=0,1)
List<SysMenu> filteredMenus = userMenus.stream()
.filter(menu -> menu.getType() != 2) // 排除操作按钮
.collect(Collectors.toList());
if (!filteredMenus.isEmpty()) {
log.info("=== 用户 {} 使用专属菜单权限,菜单数量: {}", userId, filteredMenus.size());
return filteredMenus;
}
}
// 2. 如果没有专属菜单权限,使用角色菜单权限
if (roleId.equals(RoleConstants.SUPER_ADMIN_ROLE_ID)) {
log.info("=== 超级管理员用户 {} 使用所有菜单权限(无专属菜单权限)", userId);
return menuMapper.selectList(null);
}
// 3. 普通角色菜单权限
log.info("=== 用户 {} 使用角色菜单权限,roleId: {}", userId, roleId);
return menuMapper.queryMenusByUserId(userId);
}
权限分离逻辑
菜单权限查询流程
用户登录 → getUserMenus() → queryUserMenus() → 只查询菜单项(type≠2)→ 控制左侧菜单栏
操作权限查询流程
用户登录 → queryUserPermissions() → 查询所有权限(包括操作按钮)→ 控制页面内按钮
权限类型说明
菜单类型(type字段)
- type=0:目录(如"系统管理")
- type=1:菜单(如"装车订单")
- type=2:按钮(如"编辑"、"删除")
权限查询范围
- 菜单权限:只查询 type=0,1 的项目
- 操作权限:查询所有类型(type=0,1,2)的项目
修复效果
修复前
- ❌ 菜单权限和操作权限混淆
- ❌ 用户专属权限影响菜单显示
- ❌ 用户看不到任何菜单
修复后
- ✅ 菜单权限和操作权限分离
- ✅ 用户专属权限只影响操作按钮
- ✅ 用户能看到菜单,但操作按钮被隐藏
测试验证
测试步骤
- 重新编译后端:
mvn clean compile - 重启后端服务:
mvn spring-boot:run - 清除浏览器缓存
- 使用"12.27新增姓名"账号重新登录
- 检查左侧菜单栏和页面操作按钮
预期结果
- 左侧菜单栏:用户应该能看到"装车订单"等菜单项
- 页面操作按钮:用户不应该看到"编辑"、"删除"等操作按钮
- 权限分离:菜单权限和操作权限独立控制
技术细节
权限数据流
后端菜单权限查询 → getUserMenus() → queryUserMenus() → 只返回菜单项 → 前端菜单显示
↓
后端操作权限查询 → queryUserPermissions() → 返回所有权限 → 前端按钮控制
日志输出
修复后的日志输出示例:
=== 用户 3 使用专属菜单权限,菜单数量: 8
=== 用户 3 使用专属权限,权限数量: 15
相关文件
tradeCattle/aiotagro-cattle-trade/src/main/java/com/aiotagro/cattletrade/business/service/impl/LoginServiceImpl.java- 权限查询逻辑分离pc-cattle-transportation/src/store/permission.js- 前端权限storepc-cattle-transportation/src/directive/permission/hasPermi.js- 前端权限检查
总结
通过分离菜单权限和操作权限的查询逻辑,成功解决了用户专属权限影响菜单显示的问题。修复后的系统能够:
- 正确显示菜单:用户专属权限不影响菜单权限
- 正确隐藏操作按钮:用户专属权限只影响操作权限
- 权限分离:菜单权限和操作权限独立控制
- 向后兼容:不影响现有功能
修复状态:✅ 已完成 测试状态:⏳ 待验证 部署状态:✅ 已部署