package org.ruoyi.system.service.impl; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.convert.Convert; import cn.hutool.core.lang.tree.Tree; import cn.hutool.core.util.ObjectUtil; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import lombok.RequiredArgsConstructor; import org.ruoyi.common.core.constant.UserConstants; import org.ruoyi.common.core.utils.MapstructUtils; import org.ruoyi.common.core.utils.StreamUtils; import org.ruoyi.common.core.utils.StringUtils; import org.ruoyi.common.core.utils.TreeBuildUtils; import org.ruoyi.common.satoken.utils.LoginHelper; import org.ruoyi.system.domain.SysMenu; import org.ruoyi.system.domain.SysRole; import org.ruoyi.system.domain.SysRoleMenu; import org.ruoyi.system.domain.SysTenantPackage; import org.ruoyi.system.domain.bo.SysMenuBo; import org.ruoyi.system.domain.vo.MetaVo; import org.ruoyi.system.domain.vo.RouterVo; import org.ruoyi.system.domain.vo.SysMenuVo; import org.ruoyi.system.mapper.SysMenuMapper; import org.ruoyi.system.mapper.SysRoleMapper; import org.ruoyi.system.mapper.SysRoleMenuMapper; import org.ruoyi.system.mapper.SysTenantPackageMapper; import org.ruoyi.system.service.ISysMenuService; import org.springframework.stereotype.Service; import java.util.*; /** * 菜单 业务层处理 * * @author Lion Li */ @RequiredArgsConstructor @Service public class SysMenuServiceImpl implements ISysMenuService { private final SysMenuMapper baseMapper; private final SysRoleMapper roleMapper; private final SysRoleMenuMapper roleMenuMapper; private final SysTenantPackageMapper tenantPackageMapper; /** * 根据用户查询系统菜单列表 * * @param userId 用户ID * @return 菜单列表 */ @Override public List selectMenuList(Long userId) { return selectMenuList(new SysMenuBo(), userId); } /** * 查询系统菜单列表 * * @param menu 菜单信息 * @return 菜单列表 */ @Override public List selectMenuList(SysMenuBo menu, Long userId) { List menuList; // 管理员显示所有菜单信息 if (LoginHelper.isSuperAdmin(userId)) { menuList = baseMapper.selectVoList(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 { QueryWrapper wrapper = Wrappers.query(); wrapper.eq("sur.user_id", userId) .like(StringUtils.isNotBlank(menu.getMenuName()), "m.menu_name", menu.getMenuName()) .eq(StringUtils.isNotBlank(menu.getVisible()), "m.visible", menu.getVisible()) .eq(StringUtils.isNotBlank(menu.getStatus()), "m.status", menu.getStatus()) .orderByAsc("m.parent_id") .orderByAsc("m.order_num"); List list = baseMapper.selectMenuListByUserId(wrapper); menuList = MapstructUtils.convert(list, SysMenuVo.class); } 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(StringUtils.splitList(perm.trim())); } } return permsSet; } /** * 根据角色ID查询权限 * * @param roleId 角色ID * @return 权限列表 */ @Override public Set selectMenuPermsByRoleId(Long roleId) { List perms = baseMapper.selectMenuPermsByRoleId(roleId); Set permsSet = new HashSet<>(); for (String perm : perms) { if (StringUtils.isNotEmpty(perm)) { permsSet.addAll(StringUtils.splitList(perm.trim())); } } return permsSet; } /** * 根据用户ID查询菜单 * * @param userId 用户名称 * @return 菜单列表 */ @Override public List selectMenuTreeByUserId(Long userId) { List menus; if (LoginHelper.isSuperAdmin(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.getMenuCheckStrictly()); } /** * 根据租户套餐ID查询菜单树信息 * * @param packageId 租户套餐ID * @return 选中菜单列表 */ @Override public List selectMenuListByPackageId(Long packageId) { SysTenantPackage tenantPackage = tenantPackageMapper.selectById(packageId); List menuIds = StringUtils.splitTo(tenantPackage.getMenuIds(), Convert::toLong); if (CollUtil.isEmpty(menuIds)) { return List.of(); } List parentIds = null; if (tenantPackage.getMenuCheckStrictly()) { parentIds = baseMapper.selectObjs(new LambdaQueryWrapper() .select(SysMenu::getParentId) .in(SysMenu::getMenuId, menuIds), x -> {return Convert.toLong(x);}); } return baseMapper.selectObjs(new LambdaQueryWrapper() .in(SysMenu::getMenuId, menuIds) .notIn(CollUtil.isNotEmpty(parentIds), SysMenu::getMenuId, parentIds), x -> {return Convert.toLong(x);}); } /** * 构建前端路由所需要的菜单 * * @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(menu.getRouteName()); router.setPath(menu.getRouterPath()); router.setComponent(menu.getComponentInfo()); router.setQuery(menu.getQueryParam()); router.setMeta(new MetaVo(menu.getMenuName(), menu.getIcon(), StringUtils.equals("1", menu.getIsCache()), menu.getPath())); List cMenus = menu.getChildren(); if (CollUtil.isNotEmpty(cMenus) && UserConstants.TYPE_DIR.equals(menu.getMenuType())) { router.setAlwaysShow(true); router.setRedirect("noRedirect"); router.setChildren(buildMenus(cMenus)); } else if (menu.isMenuFrame()) { router.setMeta(null); List childrenList = new ArrayList<>(); RouterVo children = new RouterVo(); children.setPath(menu.getPath()); children.setComponent(menu.getComponentInfo()); children.setName(StringUtils.capitalize(menu.getPath())); children.setMeta(new MetaVo(menu.getMenuName(), menu.getIcon(), StringUtils.equals("1", menu.getIsCache()), menu.getPath())); children.setQuery(menu.getQueryParam()); childrenList.add(children); router.setChildren(childrenList); } else if (menu.getParentId().intValue() == 0 && menu.isInnerLink()) { router.setMeta(new MetaVo(menu.getMenuName(), menu.getIcon())); router.setPath("/"); List childrenList = new ArrayList<>(); RouterVo children = new RouterVo(); String routerPath = SysMenu.innerLinkReplaceEach(menu.getPath()); 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) { if (CollUtil.isEmpty(menus)) { return CollUtil.newArrayList(); } 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 SysMenuVo selectMenuById(Long menuId) { return baseMapper.selectVoById(menuId); } /** * 是否存在菜单子节点 * * @param menuId 菜单ID * @return 结果 */ @Override public boolean hasChildByMenuId(Long menuId) { return baseMapper.exists(new LambdaQueryWrapper().eq(SysMenu::getParentId, menuId)); } /** * 查询菜单使用数量 * * @param menuId 菜单ID * @return 结果 */ @Override public boolean checkMenuExistRole(Long menuId) { return roleMenuMapper.exists(new LambdaQueryWrapper().eq(SysRoleMenu::getMenuId, menuId)); } /** * 新增保存菜单信息 * * @param bo 菜单信息 * @return 结果 */ @Override public int insertMenu(SysMenuBo bo) { SysMenu menu = MapstructUtils.convert(bo, SysMenu.class); return baseMapper.insert(menu); } /** * 修改保存菜单信息 * * @param bo 菜单信息 * @return 结果 */ @Override public int updateMenu(SysMenuBo bo) { SysMenu menu = MapstructUtils.convert(bo, SysMenu.class); return baseMapper.updateById(menu); } /** * 删除菜单管理信息 * * @param menuId 菜单ID * @return 结果 */ @Override public int deleteMenuById(Long menuId) { return baseMapper.deleteById(menuId); } /** * 校验菜单名称是否唯一 * * @param menu 菜单信息 * @return 结果 */ @Override public boolean checkMenuNameUnique(SysMenuBo menu) { boolean exist = baseMapper.exists(new LambdaQueryWrapper() .eq(SysMenu::getMenuName, menu.getMenuName()) .eq(SysMenu::getParentId, menu.getParentId()) .ne(ObjectUtil.isNotNull(menu.getMenuId()), SysMenu::getMenuId, menu.getMenuId())); return !exist; } /** * 根据父节点的ID获取所有子节点 * * @param list 分类表 * @param parentId 传入的父节点ID * @return String */ private 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; } /** * 递归列表 */ private void recursionFn(List list, SysMenu t) { // 得到子节点列表 List childList = StreamUtils.filter(list, n -> n.getParentId().equals(t.getMenuId())); t.setChildren(childList); for (SysMenu tChild : childList) { // 判断是否有子节点 if (list.stream().anyMatch(n -> n.getParentId().equals(tChild.getMenuId()))) { recursionFn(list, tChild); } } } }