diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysMenuController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysMenuController.java index eaaebd3e..eecf3cc9 100644 --- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysMenuController.java +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysMenuController.java @@ -93,6 +93,10 @@ public class SysMenuController extends BaseController { return error("新增菜单'" + menu.getMenuName() + "'失败,地址必须以http(s)://开头"); } + else if (!menuService.checkRouteConfigUnique(menu)) + { + return error("新增菜单'" + menu.getMenuName() + "'失败,路由名称或地址已存在"); + } menu.setCreateBy(getUsername()); return toAjax(menuService.insertMenu(menu)); } @@ -117,6 +121,10 @@ public class SysMenuController extends BaseController { return error("修改菜单'" + menu.getMenuName() + "'失败,上级菜单不能选择自己"); } + else if (!menuService.checkRouteConfigUnique(menu)) + { + return error("修改菜单'" + menu.getMenuName() + "'失败,路由名称或地址已存在"); + } menu.setUpdateBy(getUsername()); return toAjax(menuService.updateMenu(menu)); } diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysMenuMapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysMenuMapper.java index f3e2eb9e..387931e0 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysMenuMapper.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysMenuMapper.java @@ -122,4 +122,13 @@ public interface SysMenuMapper * @return 结果 */ public SysMenu checkMenuNameUnique(@Param("menuName") String menuName, @Param("parentId") Long parentId); + + /** + * 根据路由路径或名称查询菜单信息(用于唯一性校验) + * + * @param path 路由地址 + * @param routeName 路由名称 + * @return 匹配的菜单列表 + */ + public List selectMenusByPathOrRouteName(@Param("path") String path, @Param("routeName") String routeName); } diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysMenuService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysMenuService.java index 134b9ebd..422e620d 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysMenuService.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysMenuService.java @@ -141,4 +141,12 @@ public interface ISysMenuService * @return 结果 */ public boolean checkMenuNameUnique(SysMenu menu); + + /** + * 校验路由组合是否唯一 + * + * @param menu 菜单信息 + * @return 结果 + */ + public boolean checkRouteConfigUnique(SysMenu menu); } diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysMenuServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysMenuServiceImpl.java index 897e9803..16466c97 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysMenuServiceImpl.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysMenuServiceImpl.java @@ -8,6 +8,8 @@ import java.util.LinkedList; import java.util.List; import java.util.Set; import java.util.stream.Collectors; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import com.ruoyi.common.constant.Constants; @@ -32,8 +34,12 @@ import com.ruoyi.system.service.ISysMenuService; @Service public class SysMenuServiceImpl implements ISysMenuService { + private static final Logger log = LoggerFactory.getLogger(SysMenuServiceImpl.class); + public static final String PREMISSION_STRING = "perms[\"{0}\"]"; + public static final Long MENU_ROOT_ID = 0L; + @Autowired private SysMenuMapper menuMapper; @@ -138,7 +144,7 @@ public class SysMenuServiceImpl implements ISysMenuService { menus = menuMapper.selectMenuTreeByUserId(userId); } - return getChildPerms(menus, 0); + return getChildPerms(menus, MENU_ROOT_ID); } /** @@ -193,7 +199,7 @@ public class SysMenuServiceImpl implements ISysMenuService childrenList.add(children); router.setChildren(childrenList); } - else if (menu.getParentId().intValue() == 0 && isInnerLink(menu)) + else if (menu.getParentId().intValue() == MENU_ROOT_ID && isInnerLink(menu)) { router.setMeta(new MetaVo(menu.getMenuName(), menu.getIcon())); router.setPath("/"); @@ -345,6 +351,47 @@ public class SysMenuServiceImpl implements ISysMenuService return UserConstants.UNIQUE; } + /** + * 校验路由名称是否唯一 + * + * @param menu 菜单信息 + * @return 结果 + */ + @Override + public boolean checkRouteConfigUnique(SysMenu menu) + { + Long menuId = StringUtils.isNull(menu.getMenuId()) ? -1L : menu.getMenuId(); + Long parentId = menu.getParentId(); + String path = menu.getPath(); + String routeName = StringUtils.isEmpty(menu.getRouteName()) ? path : menu.getRouteName(); + List sysMenuList = menuMapper.selectMenusByPathOrRouteName(path, routeName); + for (SysMenu sysMenu : sysMenuList) + { + if (sysMenu.getMenuId().longValue() != menuId.longValue()) + { + Long dbParentId = sysMenu.getParentId(); + String dbPath = sysMenu.getPath(); + String dbRouteName = StringUtils.isEmpty(sysMenu.getRouteName()) ? dbPath : sysMenu.getRouteName(); + if (StringUtils.equalsAnyIgnoreCase(path, dbPath) && parentId.longValue() == dbParentId.longValue()) + { + log.warn("[同级路由冲突] 同级下已存在相同路由路径 '{}',冲突菜单:{}", dbPath, sysMenu.getMenuName()); + return UserConstants.NOT_UNIQUE; + } + else if (StringUtils.equalsAnyIgnoreCase(path, dbPath) && parentId.longValue() == MENU_ROOT_ID) + { + log.warn("[根目录路由冲突] 根目录下路由 '{}' 必须唯一,已被菜单 '{}' 占用", path, sysMenu.getMenuName()); + return UserConstants.NOT_UNIQUE; + } + else if (StringUtils.equalsAnyIgnoreCase(routeName, dbRouteName)) + { + log.warn("[路由名称冲突] 路由名称 '{}' 需全局唯一,已被菜单 '{}' 使用", routeName, sysMenu.getMenuName()); + return UserConstants.NOT_UNIQUE; + } + } + } + return UserConstants.UNIQUE; + } + /** * 获取路由名称 * @@ -384,12 +431,12 @@ public class SysMenuServiceImpl implements ISysMenuService { String routerPath = menu.getPath(); // 内链打开外网方式 - if (menu.getParentId().intValue() != 0 && isInnerLink(menu)) + if (menu.getParentId().intValue() != MENU_ROOT_ID && isInnerLink(menu)) { routerPath = innerLinkReplaceEach(routerPath); } // 非外链并且是一级目录(类型为目录) - if (0 == menu.getParentId().intValue() && UserConstants.TYPE_DIR.equals(menu.getMenuType()) + if (MENU_ROOT_ID == menu.getParentId().intValue() && UserConstants.TYPE_DIR.equals(menu.getMenuType()) && UserConstants.NO_FRAME.equals(menu.getIsFrame())) { routerPath = "/" + menu.getPath(); @@ -415,7 +462,7 @@ public class SysMenuServiceImpl implements ISysMenuService { component = menu.getComponent(); } - else if (StringUtils.isEmpty(menu.getComponent()) && menu.getParentId().intValue() != 0 && isInnerLink(menu)) + else if (StringUtils.isEmpty(menu.getComponent()) && menu.getParentId().intValue() != MENU_ROOT_ID && isInnerLink(menu)) { component = UserConstants.INNER_LINK; } @@ -434,10 +481,21 @@ public class SysMenuServiceImpl implements ISysMenuService */ public boolean isMenuFrame(SysMenu menu) { - return menu.getParentId().intValue() == 0 && UserConstants.TYPE_MENU.equals(menu.getMenuType()) + return menu.getParentId().intValue() == MENU_ROOT_ID && UserConstants.TYPE_MENU.equals(menu.getMenuType()) && menu.getIsFrame().equals(UserConstants.NO_FRAME); } + /** + * 是否为parent_view组件 + * + * @param menu 菜单信息 + * @return 结果 + */ + public boolean isParentView(SysMenu menu) + { + return menu.getParentId().intValue() != MENU_ROOT_ID && UserConstants.TYPE_DIR.equals(menu.getMenuType()); + } + /** * 是否为内链组件 * @@ -449,17 +507,6 @@ public class SysMenuServiceImpl implements ISysMenuService return menu.getIsFrame().equals(UserConstants.NO_FRAME) && StringUtils.ishttp(menu.getPath()); } - /** - * 是否为parent_view组件 - * - * @param menu 菜单信息 - * @return 结果 - */ - public boolean isParentView(SysMenu menu) - { - return menu.getParentId().intValue() != 0 && UserConstants.TYPE_DIR.equals(menu.getMenuType()); - } - /** * 根据父节点的ID获取所有子节点 * @@ -467,7 +514,7 @@ public class SysMenuServiceImpl implements ISysMenuService * @param parentId 传入的父节点ID * @return String */ - public List getChildPerms(List list, int parentId) + public List getChildPerms(List list, long parentId) { List returnList = new ArrayList(); for (Iterator iterator = list.iterator(); iterator.hasNext();) diff --git a/ruoyi-system/src/main/resources/mapper/system/SysMenuMapper.xml b/ruoyi-system/src/main/resources/mapper/system/SysMenuMapper.xml index e6be3aef..bc80401b 100644 --- a/ruoyi-system/src/main/resources/mapper/system/SysMenuMapper.xml +++ b/ruoyi-system/src/main/resources/mapper/system/SysMenuMapper.xml @@ -130,7 +130,12 @@ + +