diff --git a/cutejava/cutejava-module-system/src/main/java/cn/odboy/system/controller/SystemMenuController.java b/cutejava/cutejava-module-system/src/main/java/cn/odboy/system/controller/SystemMenuController.java index 3576d27a..52ccb297 100644 --- a/cutejava/cutejava-module-system/src/main/java/cn/odboy/system/controller/SystemMenuController.java +++ b/cutejava/cutejava-module-system/src/main/java/cn/odboy/system/controller/SystemMenuController.java @@ -67,8 +67,8 @@ public class SystemMenuController { @ApiOperation("返回全部的菜单") @PostMapping(value = "/listMenuByPid") @PreAuthorize("@el.check('menu:list','roles:list')") - public ResponseEntity> listMenuByPid(@RequestParam Long pid) { - List systemMenuTbs = systemMenuService.listMenuByPid(pid); + public ResponseEntity> listMenuByPid(@RequestParam Long pid) { + List systemMenuTbs = systemMenuService.listMenuByPid(pid); return ResponseEntity.ok(systemMenuTbs); } diff --git a/cutejava/cutejava-module-system/src/main/java/cn/odboy/system/dal/mysql/SystemMenuMapper.java b/cutejava/cutejava-module-system/src/main/java/cn/odboy/system/dal/mysql/SystemMenuMapper.java index 842030e3..fa16c6cf 100644 --- a/cutejava/cutejava-module-system/src/main/java/cn/odboy/system/dal/mysql/SystemMenuMapper.java +++ b/cutejava/cutejava-module-system/src/main/java/cn/odboy/system/dal/mysql/SystemMenuMapper.java @@ -17,6 +17,7 @@ package cn.odboy.system.dal.mysql; import cn.odboy.system.dal.dataobject.SystemMenuTb; import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import java.util.List; import org.apache.ibatis.annotations.Mapper; /** @@ -27,4 +28,7 @@ import org.apache.ibatis.annotations.Mapper; @Mapper public interface SystemMenuMapper extends BaseMapper { + default List listAll() { + return selectList(null); + } } diff --git a/cutejava/cutejava-module-system/src/main/java/cn/odboy/system/service/SystemMenuService.java b/cutejava/cutejava-module-system/src/main/java/cn/odboy/system/service/SystemMenuService.java index 80a3f8fd..27001178 100644 --- a/cutejava/cutejava-module-system/src/main/java/cn/odboy/system/service/SystemMenuService.java +++ b/cutejava/cutejava-module-system/src/main/java/cn/odboy/system/service/SystemMenuService.java @@ -30,7 +30,6 @@ import cn.odboy.system.dal.model.response.SystemMenuVo; import cn.odboy.system.dal.model.response.SystemRoleVo; import cn.odboy.system.dal.mysql.SystemMenuMapper; import cn.odboy.system.framework.permission.core.KitSecurityHelper; -import cn.odboy.util.KitBeanUtil; import cn.odboy.util.KitClassUtil; import cn.odboy.util.KitValidUtil; import cn.odboy.util.xlsx.KitExcelExporter; @@ -42,11 +41,12 @@ import java.util.HashSet; import java.util.LinkedHashSet; import java.util.LinkedList; import java.util.List; -import java.util.Objects; +import java.util.Map; import java.util.Set; import java.util.stream.Collectors; import javax.servlet.http.HttpServletResponse; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -59,23 +59,27 @@ public class SystemMenuService { private SystemRoleMenuService systemRoleMenuService; @Autowired private SystemUserRoleService systemUserRoleService; + @Lazy + @Autowired + private SystemMenuService proxyService; /** - * 创建 + * 创建 -> TestPassed * * @param args / */ @Transactional(rollbackFor = Exception.class) public void saveMenu(SystemMenuTb args) { - if (this.getMenuByTitle(args.getTitle()) != null) { + if (this.existMenuWithTitle(args.getTitle())) { throw new BadRequestException("菜单标题已存在"); } if (StrUtil.isNotBlank(args.getComponentName())) { - if (this.getMenuByComponentName(args.getComponentName()) != null) { + if (this.existMenuWithComponentName(args.getComponentName())) { throw new BadRequestException("菜单组件名称已存在"); } } if (Long.valueOf(0L).equals(args.getPid())) { + // 顶级目录 args.setPid(null); } if (args.getIFrame()) { @@ -92,7 +96,57 @@ public class SystemMenuService { } /** - * 编辑 + * 根据组件名称查询菜单是否存在 -> TestPassed + * + * @param componentName 组件名称 + * @return / + */ + private boolean existMenuWithComponentName(String componentName) { + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + wrapper.eq(SystemMenuTb::getComponentName, componentName); + return systemMenuMapper.exists(wrapper); + } + + /** + * 根据组件名称查询菜单是否存在 -> TestPassed + * + * @param componentName 组件名称 + * @return / + */ + private boolean existMenuWithComponentNameNeSelf(String componentName, Long currentMenuId) { + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + wrapper.eq(SystemMenuTb::getComponentName, componentName); + wrapper.ne(SystemMenuTb::getId, currentMenuId); + return systemMenuMapper.exists(wrapper); + } + + /** + * 根据菜单标题查询菜单是否存在 -> TestPassed + * + * @param title 菜单标题 + * @return / + */ + private boolean existMenuWithTitle(String title) { + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + wrapper.eq(SystemMenuTb::getTitle, title); + return systemMenuMapper.exists(wrapper); + } + + /** + * 根据菜单标题查询菜单是否存在 -> TestPassed + * + * @param title 菜单标题 + * @return / + */ + private boolean existMenuWithTitleNeSelf(String title, Long currentMenuId) { + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + wrapper.eq(SystemMenuTb::getTitle, title); + wrapper.ne(SystemMenuTb::getId, currentMenuId); + return systemMenuMapper.exists(wrapper); + } + + /** + * 编辑 -> TestPassed * * @param args / */ @@ -108,8 +162,7 @@ public class SystemMenuService { throw new BadRequestException(SystemTransferProtocolConst.PREFIX_HTTPS_BAD_REQUEST); } } - SystemMenuTb menu1 = this.getMenuByTitle(args.getTitle()); - if (menu1 != null && !menu1.getId().equals(menu.getId())) { + if (this.existMenuWithTitleNeSelf(args.getTitle(), menu.getId())) { throw new BadRequestException("菜单标题已存在"); } if (args.getPid().equals(0L)) { @@ -119,8 +172,7 @@ public class SystemMenuService { Long oldPid = menu.getPid(); Long newPid = args.getPid(); if (StrUtil.isNotBlank(args.getComponentName())) { - menu1 = this.getMenuByComponentName(args.getComponentName()); - if (menu1 != null && !menu1.getId().equals(menu.getId())) { + if (this.existMenuWithComponentNameNeSelf(args.getTitle(), menu.getId())) { throw new BadRequestException("菜单组件名称已存在"); } } @@ -139,36 +191,103 @@ public class SystemMenuService { // auto fill menu.setUpdateBy(null); menu.setUpdateTime(null); - systemMenuMapper.insertOrUpdate(menu); + systemMenuMapper.updateById(menu); // 计算父级菜单节点数目 this.updateMenuSubCnt(oldPid); this.updateMenuSubCnt(newPid); } /** - * 删除 + * 删除 -> TestPassed */ @Transactional(rollbackFor = Exception.class) public void deleteMenuByIds(Set ids) { - Set menuSet = new HashSet<>(); - for (Long id : ids) { - List menuList = this.listMenuByPid(id); - menuSet.add(this.getMenuVoById(id)); - menuSet = this.queryChildMenuByArgs(menuList, menuSet); +// Set menuSet = new HashSet<>(); +// for (Long id : ids) { +// List menuList = this.listMenuByPid(id); +// menuSet.add(this.getMenuVoById(id)); +// menuSet = this.queryChildMenuByArgs(menuList, menuSet); +// } +// List menuIds = menuSet.stream().map(SystemMenuVo::getId).filter(Objects::nonNull).distinct().collect(Collectors.toList()); +// if (CollUtil.isNotEmpty(menuIds)) { +// systemRoleMenuService.deleteRoleMenuByMenuIds(menuIds); +// systemMenuMapper.deleteByIds(menuIds); +// } +// for (SystemMenuVo menu : menuSet) { +// this.updateMenuSubCnt(menu.getPid()); +// } + // ========= 优化 20260114 ========= + if (CollUtil.isEmpty(ids)) { + return; } - List menuIds = - menuSet.stream().map(SystemMenuVo::getId).filter(Objects::nonNull).distinct().collect(Collectors.toList()); - if (CollUtil.isNotEmpty(menuIds)) { - systemRoleMenuService.deleteRoleMenuByMenuIds(menuIds); - systemMenuMapper.deleteByIds(menuIds); - } - for (SystemMenuVo menu : menuSet) { - this.updateMenuSubCnt(menu.getPid()); + // 查询所有菜单数据 + List allMenus = systemMenuMapper.listAll(); + // 根据ID集合获取当前菜单和其子菜单 + Set allMenuIds = this.getAllMenuIdsWithChildren(ids, allMenus); + if (CollUtil.isNotEmpty(allMenuIds)) { + // 删除角色菜单关联 + systemRoleMenuService.deleteRoleMenuByMenuIds(allMenuIds); + // 批量删除菜单 + systemMenuMapper.deleteByIds(allMenuIds); + // 更新父级菜单子节点数量 + this.updateParentMenuCounts(allMenuIds, allMenus); } } - private SystemMenuVo getMenuVoById(Long id) { - return KitBeanUtil.copyToClass(systemMenuMapper.selectById(id), SystemMenuVo.class); + /** + * 从所有菜单中找出指定ID及其子菜单ID + * + * @param rootIds 要删除的根菜单ID集合 + * @param allMenus 所有菜单数据 + * @return 包含根菜单及其所有子菜单的ID集合 + */ + private Set getAllMenuIdsWithChildren(Set rootIds, List allMenus) { + Set result = new HashSet<>(rootIds); + Set currentLevelIds = new HashSet<>(rootIds); + // 构建父ID到子菜单的映射 + Map> parentToChildrenMap = allMenus.stream() + .filter(menu -> menu.getPid() != null) + .collect(Collectors.groupingBy(SystemMenuTb::getPid)); + while (!currentLevelIds.isEmpty()) { + Set nextLevelIds = new HashSet<>(); + // 对于当前层级的每个菜单ID,查找其子菜单 + for (Long parentId : currentLevelIds) { + List children = parentToChildrenMap.get(parentId); + if (children != null && !children.isEmpty()) { + for (SystemMenuTb child : children) { + if (result.add(child.getId())) { // 如果成功添加(之前不存在),则继续查找其子菜单 + nextLevelIds.add(child.getId()); + } + } + } + } + currentLevelIds = nextLevelIds; + } + return result; + } + + /** + * 更新被删除菜单的父菜单子节点计数 + */ + private void updateParentMenuCounts(Set deletedMenuIds, List allMenus) { + // 获取被删除菜单的父ID + Set parentIds = allMenus.stream() + .filter(menu -> deletedMenuIds.contains(menu.getId()) && menu.getPid() != null) + .map(SystemMenuTb::getPid) + .collect(Collectors.toSet()); + // 更新每个父菜单的子节点计数 + for (Long parentId : parentIds) { + proxyService.updateMenuSubCnt(parentId); + } + } + + /** + * 根据菜单id查询目录 -> TestPassed + * + * @param id 菜单id + */ + private SystemMenuTb getMenuById(Long id) { + return systemMenuMapper.selectById(id); } @Transactional(rollbackFor = Exception.class) @@ -230,10 +349,10 @@ public class SystemMenuService { * @param menuSet / * @return / */ - public Set queryChildMenuByArgs(List menuList, Set menuSet) { - for (SystemMenuVo menu : menuList) { + public Set queryChildMenuByArgs(List menuList, Set menuSet) { + for (SystemMenuTb menu : menuList) { menuSet.add(menu); - List menus = this.listMenuByPid(menu.getId()); + List menus = this.listMenuByPid(menu.getId()); if (CollUtil.isNotEmpty(menus)) { queryChildMenuByArgs(menus, menuSet); } @@ -247,13 +366,13 @@ public class SystemMenuService { * @param pid / * @return / */ - public List listMenuByPid(Long pid) { - List menus; + public List listMenuByPid(Long pid) { + List menus; if (pid != null && !pid.equals(0L)) { LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); wrapper.eq(SystemMenuTb::getPid, pid); wrapper.orderByAsc(SystemMenuTb::getMenuSort); - return KitBeanUtil.copyToList(systemMenuMapper.selectList(wrapper), SystemMenuVo.class); + return systemMenuMapper.selectList(wrapper); } else { menus = this.listRootMenu(); } @@ -261,19 +380,19 @@ public class SystemMenuService { } /** - * 根据ID查询同级与上级数据 + * 根据ID查询同级与上级数据 -> TestPassed * * @param menu / * @param menus / * @return / */ - public List querySuperiorMenuByArgs(SystemMenuVo menu, List menus) { + public List querySuperiorMenuByArgs(SystemMenuTb menu, List menus) { if (menu.getPid() == null) { menus.addAll(this.listRootMenu()); return menus; } menus.addAll(this.listMenuByPid(menu.getPid())); - return querySuperiorMenuByArgs(this.getMenuVoById(menu.getPid()), menus); + return querySuperiorMenuByArgs(this.getMenuById(menu.getPid()), menus); } /** @@ -375,20 +494,8 @@ public class SystemMenuService { return menuVo1; } - public List listMenuByIds(List ids) { - return KitBeanUtil.copyToList(systemMenuMapper.selectByIds(ids), SystemMenuVo.class); - } - - private SystemMenuTb getMenuByComponentName(String componentName) { - LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); - wrapper.eq(SystemMenuTb::getComponentName, componentName); - return systemMenuMapper.selectOne(wrapper); - } - - private SystemMenuTb getMenuByTitle(String title) { - LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); - wrapper.eq(SystemMenuTb::getTitle, title); - return systemMenuMapper.selectOne(wrapper); + public List listMenuByIds(List ids) { + return systemMenuMapper.selectByIds(ids); } private Long countMenuByPid(Long pid) { @@ -412,11 +519,14 @@ public class SystemMenuService { return systemMenuMapper.selectList(wrapper); } - private List listRootMenu() { + /** + * 查询根目录 -> TestPassed + */ + private List listRootMenu() { LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); wrapper.isNull(SystemMenuTb::getPid); wrapper.orderByAsc(SystemMenuTb::getMenuSort); - return KitBeanUtil.copyToList(systemMenuMapper.selectList(wrapper), SystemMenuVo.class); + return systemMenuMapper.selectList(wrapper); } public List buildFrontMenus() { @@ -426,19 +536,19 @@ public class SystemMenuService { } public Set listChildMenuSetByMenuId(Long id) { - Set menuSet = new HashSet<>(); - List menuList = this.listMenuByPid(id); - menuSet.add(this.getMenuVoById(id)); + Set menuSet = new HashSet<>(); + List menuList = this.listMenuByPid(id); + menuSet.add(this.getMenuById(id)); menuSet = this.queryChildMenuByArgs(menuList, menuSet); return menuSet.stream().map(SystemMenuVo::getId).collect(Collectors.toSet()); } public List listMenuSuperior(List ids) { - Set menus; + Set menus; List systemMenuTbs; if (CollUtil.isNotEmpty(ids)) { menus = new LinkedHashSet<>(this.listMenuByIds(ids)); - for (SystemMenuVo menu : menus) { + for (SystemMenuTb menu : menus) { List menuList = this.querySuperiorMenuByArgs(menu, new ArrayList<>()); for (SystemMenuVo data : menuList) { if (data.getId().equals(menu.getPid())) { diff --git a/cutejava/cutejava-module-system/src/main/java/cn/odboy/system/service/SystemRoleMenuService.java b/cutejava/cutejava-module-system/src/main/java/cn/odboy/system/service/SystemRoleMenuService.java index b69d09be..681ffa6e 100644 --- a/cutejava/cutejava-module-system/src/main/java/cn/odboy/system/service/SystemRoleMenuService.java +++ b/cutejava/cutejava-module-system/src/main/java/cn/odboy/system/service/SystemRoleMenuService.java @@ -115,7 +115,7 @@ public class SystemRoleMenuService { * @param menuIds 菜单id集合 */ @Transactional(rollbackFor = Exception.class) - public void deleteRoleMenuByMenuIds(List menuIds) { + public void deleteRoleMenuByMenuIds(Set menuIds) { if (CollUtil.isEmpty(menuIds)) { return; }