align(用户菜单授权): 创建/编辑用户菜单权限补齐前端客户端(app)菜单并按类型分区落库

用户管理菜单权限此前只含后台 admin(单类型):前端授权树/回显仅拉 menuType=admin,
后端 replaceDirectPermissions 也固定用 ADMIN 作用域写。现改为同时覆盖 后台(admin)+前端客户端(app):
- 前端 user-menu-auth 节点携带 type,api 并行拉取 admin/app 两类可授权树与已授权 id 合并去重,树内两类根并存(账号与权限/视频/前端工具/运营工具/后勤工具等)
- 后端 PermissionMenuService 新增 resolveMenuTypes(按 id 解析类型);AdminUserService create/update 把勾选 id 拆 admin/app 分区整树替换(internal 不纳入)
- 前端 1556 测试全绿 + build 通过;后端单测(AdminUserServiceTest/PermissionMenuServiceTest/Controller/PermissionMenuResolveTypeTest) EXIT 0
- 本地 E2E:创建用户写入 admin=7+app=3 → 按类型回读 admin[7]/app[3],删除正常
This commit is contained in:
2026-09-06 15:32:43 +08:00
parent 8034d916bc
commit 898fae4cb3
7 changed files with 184 additions and 19 deletions
@@ -230,11 +230,38 @@ public class AdminUserService {
}
}
/**
* 用户管理授权树现在同时展示并勾选 后台(admin) + 前端客户端(app) 菜单:
* 把勾选 id 按类型拆分后分区整树替换(internal 类型不在树里,出现即按无效处理)。
*/
private void replaceDirectPermissions(AdminUserEntity operator, Long userId, List<Long> columnIds) {
List<Long> raw = columnIds == null ? List.of() : columnIds;
Map<Long, String> typeById = permissionMenuService.resolveMenuTypes(raw);
List<Long> adminIds = new ArrayList<>();
List<Long> appIds = new ArrayList<>();
for (Long id : raw) {
if (id == null) {
continue;
}
String type = typeById.getOrDefault(id, "");
if (PermissionMenuService.MENU_TYPE_ADMIN.equals(type)) {
adminIds.add(id);
} else if (PermissionMenuService.MENU_TYPE_APP.equals(type)) {
appIds.add(id);
} else {
throw new BusinessException("存在无效或不属于当前类型的菜单权限项");
}
}
replaceDirectPermissionsByType(operator, userId, adminIds, PermissionMenuService.MENU_TYPE_ADMIN);
replaceDirectPermissionsByType(operator, userId, appIds, PermissionMenuService.MENU_TYPE_APP);
}
private void replaceDirectPermissionsByType(AdminUserEntity operator, Long userId, List<Long> columnIds,
String menuType) {
UserColumnPermissionUpdateRequest permissionRequest = new UserColumnPermissionUpdateRequest();
permissionRequest.setColumnIds(columnIds == null ? List.of() : columnIds);
permissionRequest.setColumnIds(columnIds);
permissionMenuService.updateUserColumnPermissions(
operator, userId, permissionRequest, PermissionMenuService.MENU_TYPE_APP);
operator, userId, permissionRequest, menuType);
}
public void deleteUser(AdminUserEntity currentUser, Long uid) {
@@ -61,6 +61,25 @@ public class PermissionMenuService {
return toItemVos(menus, menus);
}
/**
* 按菜单(column) id 解析所属类型;未知/无效 id 不在返回中。供用户创建/编辑把
* 勾选的 后台(admin)+客户端(app) 菜单 id 拆分后分别落库。
*/
public Map<Long, String> resolveMenuTypes(List<Long> columnIds) {
List<Long> ids = normalizeColumnIds(columnIds);
if (ids.isEmpty()) {
return Map.of();
}
List<PermissionMenuEntity> rows = permissionMenuMapper.selectBatchIds(ids);
Map<Long, String> typeById = new HashMap<>();
for (PermissionMenuEntity row : rows) {
if (row != null && row.getId() != null) {
typeById.put(row.getId(), row.getMenuType() == null ? "" : row.getMenuType());
}
}
return typeById;
}
@Transactional
public PermissionMenuItemVo create(PermissionMenuCreateRequest request) {
return create(null, request);