package com.ruoyi.system.service.impl; import cn.hutool.core.lang.tree.Tree; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.ruoyi.common.constant.Constants; import com.ruoyi.common.constant.UserConstants; import com.ruoyi.common.core.domain.entity.SysMenu; import com.ruoyi.common.core.domain.entity.SysRole; import com.ruoyi.common.core.domain.entity.SysUser; import com.ruoyi.common.core.mybatisplus.core.ServicePlusImpl; import com.ruoyi.common.utils.SecurityUtils; import com.ruoyi.common.utils.StringUtils; import com.ruoyi.common.utils.TreeBuildUtils; import com.ruoyi.system.domain.SysRoleMenu; import com.ruoyi.system.domain.vo.MetaVo; import com.ruoyi.system.domain.vo.RouterVo; import com.ruoyi.system.mapper.SysMenuMapper; import com.ruoyi.system.mapper.SysRoleMapper; import com.ruoyi.system.mapper.SysRoleMenuMapper; import com.ruoyi.system.service.ISysMenuService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.*; /** * 菜单 业务层处理 * * @author Lion Li */ @Service public class SysMenuServiceImpl extends ServicePlusImpl implements ISysMenuService { @Autowired private SysRoleMapper roleMapper; @Autowired private SysRoleMenuMapper roleMenuMapper; /** * 根据用户查询系统菜单列表 * * @param userId 用户ID * @return 菜单列表 */ @Override public List selectMenuList(Long userId) { return selectMenuList(new SysMenu(), userId); } /** * 查询系统菜单列表 * * @param menu 菜单信息 * @return 菜单列表 */ @Override public List selectMenuList(SysMenu menu, Long userId) { List menuList = null; // 管理员显示所有菜单信息 if (SysUser.isAdmin(userId)) { menuList = list(new LambdaQueryWrapper() .like(StringUtils.isNotBlank(menu.getMenuName()), SysMenu::getMenuName, menu.getMenuName()) .eq(StringUtils.isNotBlank(menu.getVisible()), SysMenu::getVisible, menu.getVisible()) .eq(StringUtils.isNotBlank(menu.getStatus()), SysMenu::getStatus, menu.getStatus()) .orderByAsc(SysMenu::getParentId) .orderByAsc(SysMenu::getOrderNum)); } else { menu.getParams().put("userId", userId); menuList = baseMapper.selectMenuListByUserId(menu); } return menuList; } /** * 根据用户ID查询权限 * * @param userId 用户ID * @return 权限列表 */ @Override public Set selectMenuPermsByUserId(Long userId) { List perms = baseMapper.selectMenuPermsByUserId(userId); Set permsSet = new HashSet<>(); for (String perm : perms) { if (StringUtils.isNotEmpty(perm)) { permsSet.addAll(Arrays.asList(perm.trim().split(","))); } } return permsSet; } /** * 根据用户ID查询菜单 * * @param userId 用户名称 * @return 菜单列表 */ @Override public List selectMenuTreeByUserId(Long userId) { List menus = null; if (SecurityUtils.isAdmin(userId)) { menus = baseMapper.selectMenuTreeAll(); } else { menus = baseMapper.selectMenuTreeByUserId(userId); } return getChildPerms(menus, 0); } /** * 根据角色ID查询菜单树信息 * * @param roleId 角色ID * @return 选中菜单列表 */ @Override public List selectMenuListByRoleId(Long roleId) { SysRole role = roleMapper.selectById(roleId); return baseMapper.selectMenuListByRoleId(roleId, role.isMenuCheckStrictly()); } /** * 构建前端路由所需要的菜单 * * @param menus 菜单列表 * @return 路由列表 */ @Override public List buildMenus(List menus) { List routers = new LinkedList(); for (SysMenu menu : menus) { RouterVo router = new RouterVo(); router.setHidden("1".equals(menu.getVisible())); router.setName(getRouteName(menu)); router.setPath(getRouterPath(menu)); router.setComponent(getComponent(menu)); router.setQuery(menu.getQuery()); router.setMeta(new MetaVo(menu.getMenuName(), menu.getIcon(), StringUtils.equals("1", menu.getIsCache()), menu.getPath())); List cMenus = (List) menu.getChildren(); if (!cMenus.isEmpty() && UserConstants.TYPE_DIR.equals(menu.getMenuType())) { router.setAlwaysShow(true); router.setRedirect("noRedirect"); router.setChildren(buildMenus(cMenus)); } else if (isMenuFrame(menu)) { router.setMeta(null); List childrenList = new ArrayList(); RouterVo children = new RouterVo(); children.setPath(menu.getPath()); children.setComponent(menu.getComponent()); children.setName(StringUtils.capitalize(menu.getPath())); children.setMeta(new MetaVo(menu.getMenuName(), menu.getIcon(), StringUtils.equals("1", menu.getIsCache()), menu.getPath())); children.setQuery(menu.getQuery()); childrenList.add(children); router.setChildren(childrenList); } else if (menu.getParentId().intValue() == 0 && isInnerLink(menu)) { router.setMeta(new MetaVo(menu.getMenuName(), menu.getIcon())); router.setPath("/inner"); List childrenList = new ArrayList(); RouterVo children = new RouterVo(); String routerPath = StringUtils.replaceEach(menu.getPath(), new String[]{Constants.HTTP, Constants.HTTPS}, new String[]{"", ""}); children.setPath(routerPath); children.setComponent(UserConstants.INNER_LINK); children.setName(StringUtils.capitalize(routerPath)); children.setMeta(new MetaVo(menu.getMenuName(), menu.getIcon(), menu.getPath())); childrenList.add(children); router.setChildren(childrenList); } routers.add(router); } return routers; } /** * 构建前端所需要下拉树结构 * * @param menus 菜单列表 * @return 下拉树结构列表 */ @Override public List> buildMenuTreeSelect(List menus) { return TreeBuildUtils.build(menus, (menu, tree) -> tree.setId(menu.getMenuId()) .setParentId(menu.getParentId()) .setName(menu.getMenuName()) .setWeight(menu.getOrderNum())); } /** * 根据菜单ID查询信息 * * @param menuId 菜单ID * @return 菜单信息 */ @Override public SysMenu selectMenuById(Long menuId) { return getById(menuId); } /** * 是否存在菜单子节点 * * @param menuId 菜单ID * @return 结果 */ @Override public boolean hasChildByMenuId(Long menuId) { long result = count(new LambdaQueryWrapper().eq(SysMenu::getParentId, menuId)); return result > 0; } /** * 查询菜单使用数量 * * @param menuId 菜单ID * @return 结果 */ @Override public boolean checkMenuExistRole(Long menuId) { long result = roleMenuMapper.selectCount(new LambdaQueryWrapper().eq(SysRoleMenu::getMenuId, menuId)); return result > 0; } /** * 新增保存菜单信息 * * @param menu 菜单信息 * @return 结果 */ @Override public int insertMenu(SysMenu menu) { return baseMapper.insert(menu); } /** * 修改保存菜单信息 * * @param menu 菜单信息 * @return 结果 */ @Override public int updateMenu(SysMenu menu) { return baseMapper.updateById(menu); } /** * 删除菜单管理信息 * * @param menuId 菜单ID * @return 结果 */ @Override public int deleteMenuById(Long menuId) { return baseMapper.deleteById(menuId); } /** * 校验菜单名称是否唯一 * * @param menu 菜单信息 * @return 结果 */ @Override public String checkMenuNameUnique(SysMenu menu) { Long menuId = StringUtils.isNull(menu.getMenuId()) ? -1L : menu.getMenuId(); long count = count(new LambdaQueryWrapper() .eq(SysMenu::getMenuName, menu.getMenuName()) .eq(SysMenu::getParentId, menu.getParentId()) .ne(SysMenu::getMenuId, menuId)); if (count > 0) { return UserConstants.NOT_UNIQUE; } return UserConstants.UNIQUE; } /** * 获取路由名称 * * @param menu 菜单信息 * @return 路由名称 */ public String getRouteName(SysMenu menu) { String routerName = StringUtils.capitalize(menu.getPath()); // 非外链并且是一级目录(类型为目录) if (isMenuFrame(menu)) { routerName = StringUtils.EMPTY; } return routerName; } /** * 获取路由地址 * * @param menu 菜单信息 * @return 路由地址 */ public String getRouterPath(SysMenu menu) { String routerPath = menu.getPath(); // 内链打开外网方式 if (menu.getParentId().intValue() != 0 && isInnerLink(menu)) { routerPath = StringUtils.replaceEach(routerPath, new String[]{Constants.HTTP, Constants.HTTPS}, new String[]{"", ""}); } // 非外链并且是一级目录(类型为目录) if (0 == menu.getParentId().intValue() && UserConstants.TYPE_DIR.equals(menu.getMenuType()) && UserConstants.NO_FRAME.equals(menu.getIsFrame())) { routerPath = "/" + menu.getPath(); } // 非外链并且是一级目录(类型为菜单) else if (isMenuFrame(menu)) { routerPath = "/"; } return routerPath; } /** * 获取组件信息 * * @param menu 菜单信息 * @return 组件信息 */ public String getComponent(SysMenu menu) { String component = UserConstants.LAYOUT; if (StringUtils.isNotEmpty(menu.getComponent()) && !isMenuFrame(menu)) { component = menu.getComponent(); } else if (StringUtils.isEmpty(menu.getComponent()) && menu.getParentId().intValue() != 0 && isInnerLink(menu)) { component = UserConstants.INNER_LINK; } else if (StringUtils.isEmpty(menu.getComponent()) && isParentView(menu)) { component = UserConstants.PARENT_VIEW; } return component; } /** * 是否为菜单内部跳转 * * @param menu 菜单信息 * @return 结果 */ public boolean isMenuFrame(SysMenu menu) { return menu.getParentId().intValue() == 0 && UserConstants.TYPE_MENU.equals(menu.getMenuType()) && menu.getIsFrame().equals(UserConstants.NO_FRAME); } /** * 是否为内链组件 * * @param menu 菜单信息 * @return 结果 */ public boolean isInnerLink(SysMenu menu) { 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获取所有子节点 * * @param list 分类表 * @param parentId 传入的父节点ID * @return String */ public List getChildPerms(List list, int parentId) { List returnList = new ArrayList(); for (SysMenu t : list) { // 一、根据传入的某个父节点ID,遍历该父节点的所有子节点 if (t.getParentId() == parentId) { recursionFn(list, t); returnList.add(t); } } return returnList; } /** * 递归列表 * * @param list * @param t */ private void recursionFn(List list, SysMenu t) { // 得到子节点列表 List childList = getChildList(list, t); t.setChildren(childList); for (SysMenu tChild : childList) { if (hasChild(list, tChild)) { recursionFn(list, tChild); } } } /** * 得到子节点列表 */ private List getChildList(List list, SysMenu t) { List tlist = new ArrayList(); for (SysMenu n : list) { if (n.getParentId().longValue() == t.getMenuId().longValue()) { tlist.add(n); } } return tlist; } /** * 判断是否有子节点 */ private boolean hasChild(List list, SysMenu t) { return getChildList(list, t).size() > 0; } }