From db7dbcc97e85772350605d45f0d41e3e70d84b55 Mon Sep 17 00:00:00 2001 From: cuijiawang Date: Sat, 20 Sep 2025 18:14:51 +0800 Subject: [PATCH] =?UTF-8?q?=E8=8F=9C=E5=8D=95=E5=A2=9E=E5=88=A0=E6=94=B9?= =?UTF-8?q?=E6=9F=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../menu/service/impl/SysMenuServiceImpl.java | 100 +++++++++++++----- .../system/role/mapper/SysRoleMapper.java | 6 ++ .../agileboot/system/menu/dto/MenuQuery.java | 15 ++- 3 files changed, 92 insertions(+), 29 deletions(-) diff --git a/agileboot-system/agileboot-system-base/src/main/java/com/agileboot/system/menu/service/impl/SysMenuServiceImpl.java b/agileboot-system/agileboot-system-base/src/main/java/com/agileboot/system/menu/service/impl/SysMenuServiceImpl.java index c8d432b..7120bbd 100644 --- a/agileboot-system/agileboot-system-base/src/main/java/com/agileboot/system/menu/service/impl/SysMenuServiceImpl.java +++ b/agileboot-system/agileboot-system-base/src/main/java/com/agileboot/system/menu/service/impl/SysMenuServiceImpl.java @@ -1,5 +1,6 @@ package com.agileboot.system.menu.service.impl; +import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.lang.tree.Tree; import cn.hutool.core.lang.tree.TreeNodeConfig; @@ -15,6 +16,9 @@ import com.agileboot.system.menu.entity.SysMenu; import com.agileboot.system.menu.mapper.SysMenuMapper; import com.agileboot.system.menu.service.ISysMenuService; import com.agileboot.system.menu.vo.RouterVO; +import com.agileboot.system.role.mapper.SysRoleMapper; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import lombok.RequiredArgsConstructor; import org.springframework.beans.BeanUtils; @@ -35,14 +39,11 @@ import java.util.stream.Collectors; @RequiredArgsConstructor public class SysMenuServiceImpl extends ServiceImpl implements ISysMenuService { + private final SysRoleMapper roleMapper; @Override public List getMenuList(MenuQuery query) { - Boolean isButton = query.getIsButton(); - List list = super.lambdaQuery() - .eq(isButton != null, SysMenu::getIsButton, isButton) - .orderByDesc(SysMenu::getParentId) - .list(); + List list = super.list(query.toQueryWrapper()); return list.stream().map(MenuDTO::new) .sorted(Comparator.comparing(MenuDTO::getRank, Comparator.nullsLast(Integer::compareTo))) .collect(Collectors.toList()); @@ -71,33 +72,34 @@ public class SysMenuServiceImpl extends ServiceImpl impl BeanUtils.copyProperties(addCommand, entity, "menuId"); String metaInfo = JacksonUtil.to(addCommand.getMeta()); entity.setMetaInfo(metaInfo); - // 校验菜单名称是否唯一 - boolean exists = super.lambdaQuery() - .eq(SysMenu::getMenuName, addCommand.getMenuName()) - .eq(addCommand.getParentId() != null, SysMenu::getParentId, addCommand.getParentId()) - .exists(); - if (exists) throw new BizException(ErrorCode.Business.MENU_NAME_IS_NOT_UNIQUE); - SysMenu parentMenu = super.getById(addCommand.getParentId()); - // Iframe和外链跳转类型 不允许添加按钮 - if (parentMenu != null && parentMenu.getIsButton() && ( - Objects.equals(parentMenu.getMenuType(), MenuTypeEnum.IFRAME.getValue()) - || Objects.equals(parentMenu.getMenuType(), MenuTypeEnum.OUTSIDE_LINK_REDIRECT.getValue()) - )) { - throw new BizException(ErrorCode.Business.MENU_NOT_ALLOWED_TO_CREATE_BUTTON_ON_IFRAME_OR_OUT_LINK); - } - // 只允许在目录菜单类型底下 添加子菜单 - if (parentMenu != null && !parentMenu.getIsButton() && ( - !Objects.equals(parentMenu.getMenuType(), MenuTypeEnum.CATALOG.getValue()) - )) { - throw new BizException(ErrorCode.Business.MENU_ONLY_ALLOWED_TO_CREATE_SUB_MENU_IN_CATALOG); - } + this.checkMenuNameUnique(entity.getMenuName(), entity.getMenuId(), entity.getParentId()); + this.checkAddButtonInIframeOrOutLink(entity.getIsButton(), entity.getParentId()); + this.checkAddMenuNotInCatalog(entity.getIsButton(), entity.getParentId()); + super.save(entity); } @Override - public void updateMenu(UpdateMenuDTO updateCommand) { + public void updateMenu(UpdateMenuDTO dto) { + Long menuId = dto.getMenuId(); + SysMenu byId = super.getById(menuId); + if (byId == null) { + throw new BizException(ErrorCode.Business.COMMON_OBJECT_NOT_FOUND, menuId, "菜单"); + } + if (!Objects.equals(byId.getMenuType(), dto.getMenuType()) && !byId.getIsButton()) { + throw new BizException(ErrorCode.Business.MENU_CAN_NOT_CHANGE_MENU_TYPE); + } + BeanUtil.copyProperties(dto, byId, "menuId"); + String metaInfo = JacksonUtil.to(dto.getMeta()); + byId.setMetaInfo(metaInfo); + this.checkMenuNameUnique(byId.getMenuName(), byId.getMenuId(), byId.getParentId()); + this.checkAddButtonInIframeOrOutLink(byId.getIsButton(), byId.getParentId()); + this.checkAddMenuNotInCatalog(byId.getIsButton(), byId.getParentId()); + this.checkParentIdConflict(byId.getMenuId(), byId.getParentId()); + + super.updateById(byId); } @Override @@ -107,7 +109,7 @@ public class SysMenuServiceImpl extends ServiceImpl impl throw new BizException(ErrorCode.Business.MENU_EXIST_CHILD_MENU_NOT_ALLOW_DELETE); } // 查询菜单是否存在角色 - if (super.lambdaQuery().eq(SysMenu::getMenuId, menuId).exists()) { + if (roleMapper.isMenuAssignToRoles(menuId)) { throw new BizException(ErrorCode.Business.MENU_ALREADY_ASSIGN_TO_ROLE_NOT_ALLOW_DELETE); } super.removeById(menuId); @@ -135,7 +137,7 @@ public class SysMenuServiceImpl extends ServiceImpl impl // 传给前端的路由排除掉按钮和停用的菜单 List noButtonMenus = allMenus.stream() .filter(menu -> !menu.getIsButton()) - .filter(menu-> StatusEnum.ENABLE.getValue().equals(menu.getStatus())) + .filter(menu -> StatusEnum.ENABLE.getValue().equals(menu.getStatus())) .collect(Collectors.toList()); TreeNodeConfig config = new TreeNodeConfig(); @@ -191,4 +193,46 @@ public class SysMenuServiceImpl extends ServiceImpl impl }); } + private void checkMenuNameUnique(String menuName, Long menuId, Long parentId) { + LambdaQueryWrapper queryWrapper = Wrappers.lambdaQuery(SysMenu.class) + .eq(SysMenu::getMenuName, menuName) + .ne(menuId != null, SysMenu::getMenuId, menuId) + .eq(parentId != null, SysMenu::getParentId, parentId); + if (this.baseMapper.exists(queryWrapper)) { + throw new BizException(ErrorCode.Business.MENU_NAME_IS_NOT_UNIQUE, menuName); + } + } + + private void checkParentIdConflict(Long menuId, Long parentId) { + if (menuId.equals(parentId)) { + throw new BizException(ErrorCode.Business.MENU_PARENT_ID_NOT_ALLOW_SELF); + } + } + + /** + * Iframe和外链跳转类型 不允许添加按钮 + */ + private void checkAddButtonInIframeOrOutLink(Boolean isButton, Long parentId) { + SysMenu parentMenu = super.getById(parentId); + + if (parentMenu != null && isButton + && (Objects.equals(parentMenu.getMenuType(), MenuTypeEnum.IFRAME.getValue()) + || Objects.equals(parentMenu.getMenuType(), MenuTypeEnum.OUTSIDE_LINK_REDIRECT.getValue()) + )) { + throw new BizException(ErrorCode.Business.MENU_NOT_ALLOWED_TO_CREATE_BUTTON_ON_IFRAME_OR_OUT_LINK); + } + } + + /** + * 只允许在目录菜单类型底下 添加子菜单 + */ + private void checkAddMenuNotInCatalog(Boolean isButton, Long parentId) { + SysMenu parentMenu = super.getById(parentId); + + if (parentMenu != null && !isButton + && (!Objects.equals(parentMenu.getMenuType(), MenuTypeEnum.CATALOG.getValue()) + )) { + throw new BizException(ErrorCode.Business.MENU_ONLY_ALLOWED_TO_CREATE_SUB_MENU_IN_CATALOG); + } + } } diff --git a/agileboot-system/agileboot-system-base/src/main/java/com/agileboot/system/role/mapper/SysRoleMapper.java b/agileboot-system/agileboot-system-base/src/main/java/com/agileboot/system/role/mapper/SysRoleMapper.java index 5c90a4a..bbd5649 100644 --- a/agileboot-system/agileboot-system-base/src/main/java/com/agileboot/system/role/mapper/SysRoleMapper.java +++ b/agileboot-system/agileboot-system-base/src/main/java/com/agileboot/system/role/mapper/SysRoleMapper.java @@ -2,7 +2,13 @@ package com.agileboot.system.role.mapper; import com.agileboot.system.role.entity.SysRole; import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.apache.ibatis.annotations.Select; public interface SysRoleMapper extends BaseMapper { + /** + * 判断菜单是否被角色分配 + */ + @Select("SELECT COUNT(1) != 0 FROM sys_role_menu WHERE menu_id = #{menuId}") + boolean isMenuAssignToRoles(Long menuId); } diff --git a/wol-domain/src/main/java/com/agileboot/system/menu/dto/MenuQuery.java b/wol-domain/src/main/java/com/agileboot/system/menu/dto/MenuQuery.java index 85898f1..8cb7e7e 100644 --- a/wol-domain/src/main/java/com/agileboot/system/menu/dto/MenuQuery.java +++ b/wol-domain/src/main/java/com/agileboot/system/menu/dto/MenuQuery.java @@ -1,15 +1,28 @@ package com.agileboot.system.menu.dto; +import com.agileboot.common.mybatis.core.page.PageQuery; +import com.agileboot.system.menu.entity.SysMenu; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; import lombok.Data; +import lombok.EqualsAndHashCode; /** * @author valarchie */ +@EqualsAndHashCode(callSuper = true) @Data -public class MenuQuery { +public class MenuQuery extends PageQuery { // 直接交给前端筛选 // private String menuName; // private Boolean isVisible; // private Integer status; private Boolean isButton; + + @Override + public LambdaQueryWrapper toQueryWrapper() { + return Wrappers.lambdaQuery(SysMenu.class) + .eq(isButton != null, SysMenu::getIsButton, isButton) + .orderByDesc(SysMenu::getParentId); + } }