ludc
2024-07-10 4d571ecaabae01dc825f01ce92ff4a5023f56fb0
Source/UBCS/ubcs-service/ubcs-system/src/main/java/com/vci/ubcs/system/service/impl/MenuServiceImpl.java
@@ -21,18 +21,17 @@
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.vci.ubcs.code.feign.ICodeClassifyClient;
import com.vci.ubcs.starter.util.MybatisParameterUtil;
import com.vci.ubcs.starter.web.util.VciBaseUtil;
import com.vci.ubcs.system.cache.NacosConfigCache;
import com.vci.ubcs.system.cache.SysCache;
import com.vci.ubcs.system.dto.MenuDTO;
import com.vci.ubcs.system.entity.*;
import com.vci.ubcs.system.mapper.ClassifyAuthMapper;
import com.vci.ubcs.system.service.*;
import com.vci.ubcs.system.vo.MenuVO;
import com.vci.ubcs.system.mapper.MenuMapper;
import com.vci.ubcs.system.service.IMenuService;
import com.vci.ubcs.system.service.IRoleMenuService;
import com.vci.ubcs.system.service.IRoleScopeService;
import com.vci.ubcs.system.service.ITopMenuSettingService;
import com.vci.ubcs.system.wrapper.MenuWrapper;
import lombok.AllArgsConstructor;
import org.springblade.core.log.exception.ServiceException;
@@ -68,7 +67,10 @@
   private final IRoleMenuService roleMenuService;
   private final IRoleScopeService roleScopeService;
   private final MenuMapper menuMapper;
   private final ITopMenuSettingService topMenuSettingService;
   private final ICodeClassifyClient codeClassifyClient;
   private final ClassifyAuthMapper classifyAuthMapper;
   private final static String PARENT_ID = "parentId";
   private final static Integer MENU_CATEGORY = 1;
@@ -89,7 +91,6 @@
      return baseMapper.lazyMenuPage(parentId, param, Condition.getPage(query));
   }
   @Override
   public List<MenuVO> routes(String roleId, Long topMenuId) {
      if (StringUtil.isBlank(roleId)) {
@@ -98,12 +99,11 @@
      List<Menu> allMenus = baseMapper.allMenu();
      List<Menu> roleMenus;
      // 超级管理员并且不是顶部菜单请求则返回全部菜单
      // if (AuthUtil.isAdministrator() && Func.isEmpty(topMenuId)) {
      if (VciBaseUtil.checkAdminTenant() && Func.isEmpty(topMenuId)) {
         roleMenus = allMenus;
      }
      // 非超级管理员并且不是顶部菜单请求则返回对应角色权限菜单
      else if (!AuthUtil.isAdministrator() && Func.isEmpty(topMenuId)) {
      else if (!VciBaseUtil.checkAdminTenant() && Func.isEmpty(topMenuId)) {
         roleMenus = tenantPackageMenu(baseMapper.roleMenuByRoleId(Func.toLongList(roleId)));
      }
      // 顶部菜单请求返回对应角色权限菜单
@@ -228,6 +228,7 @@
    * 租户菜单权限自定义筛选
    */
   private List<Menu> tenantPackageMenu(List<Menu> menu) {
      // 租户包配置查询
      TenantPackage tenantPackage = SysCache.getTenantPackage(AuthUtil.getTenantId());
      if (Func.isNotEmpty(tenantPackage) && tenantPackage.getId() > 0L) {
         List<Long> menuIds = Func.toLongList(tenantPackage.getMenuId());
@@ -324,18 +325,75 @@
   }
   /**
    * 获取菜单下面的按钮
    * 获取菜单下面的按钮,别乱调用,这个方法是针对主数据管理按钮查询的
    * @param classifyId
    * @param btmType 业务类型
    * @return List<Menu>
    * @param authType
    * @return
    */
    @Override
   //@Cacheable(cacheNames = MENU_CACHE, key = "'auth:menuButton:'+ #btmType +':'+ #userId ")
    public List<Menu> getMenuButtonByType(String btmType,Long userId) {
      List<String> roleIds = null;
      if(!VciBaseUtil.checkAdminTenant()){
         roleIds = Arrays.asList(AuthUtil.getUser().getRoleId().split(","));
    public List<Menu> getMenuButtonByType(String classifyId,String btmType,String authType) {
      // baseMapper.selectMenuChildByBtnType(btmType,roleIds);
      if(Func.isBlank(classifyId)){
         throw new ServiceException("必传参数分类oid不能为空!");
      }
      return baseMapper.selectMenuChildByBtnType(btmType,roleIds);
      //查询分类节点的所有父级节点
      R<List<String>> listR = codeClassifyClient.selectAllParentOid(classifyId);
      if (!listR.isSuccess() && !listR.getData().isEmpty()) {
         throw new ServiceException("获取分类信息失败!");
      }
      // 返回的分类oid是当前节点为第一个,后面依次是他的上层节点
      List<String> classifyOidList = listR.getData();
      final List<String> roleIds = Func.toStrList(",",AuthUtil.getUser().getRoleId());
      // 先查询按钮id列表
      LambdaQueryWrapper<ClassifyAuth> wrapper = Wrappers.<ClassifyAuth>query()
         .lambda().eq(ClassifyAuth::getClassifyId, classifyId)
         .eq(ClassifyAuth::getAuthType,authType)
         .in(ClassifyAuth::getRoleId, roleIds);
      List<ClassifyAuth> classifyAuths = classifyAuthMapper.selectList(wrapper);
      //如果当前分类没有找到授权配置,就依次从当前节点往上层节点找授权配置,找到了就停止,没找到就一直找到最后
      if(classifyAuths.isEmpty()){
         // 下标从1开始因为当前节点0已经查询过
         for (int i = 1; i < classifyOidList.size(); i++) {
            classifyAuths = classifyAuthMapper.selectList(
               Wrappers.<ClassifyAuth>query()
                  .lambda().eq(ClassifyAuth::getClassifyId, classifyOidList.get(i))
                  .eq(ClassifyAuth::getAuthType,authType)
                  .in(ClassifyAuth::getRoleId, roleIds)
            );
            if(!classifyAuths.isEmpty()){
               break;
            }
         }
      }
      //出现了多条数据
      if(classifyAuths.size()>1){
         // 校验是否存在错误数据,同一个角色和同一个分类id存在多条授权记录
         List<ClassifyAuth> finalClassifyAuths = classifyAuths;
         boolean hasDuplicate = classifyAuths.stream()
            .anyMatch(auth1 -> finalClassifyAuths.stream()
               .filter(auth2 -> auth1 != auth2)
               .anyMatch(auth2 -> auth1.getRoleId().equals(auth2.getRoleId()) && auth1.getClassifyId().equals(auth2.getClassifyId())));
         if (hasDuplicate) {
            throw new ServiceException("角色和分类配置存在多条记录,请联系管理人员清理错误配置!");
         }
      }
      // 是否为超管
      Boolean isAdmin = VciBaseUtil.checkAdminTenant();
      // 未配置按钮权限
      if(!isAdmin && (classifyAuths.isEmpty() || Func.isBlank(classifyAuths.get(0).getButtonIds()))){
         return new ArrayList<>();
      }
      List<String> ids = new ArrayList<>();
      // 如果不是超管用户
      if(!isAdmin){
         String concatenatedButtonIds = classifyAuths.stream()
            .map(ClassifyAuth::getButtonIds) // 获取每个classifyAuths对象的buttonIds
            .collect(Collectors.joining(",")); // 用逗号分隔拼接成一个字符串
         ids.addAll(Arrays.asList(concatenatedButtonIds.split(",")));
      }
      return this.getMenuListByCode(ids,btmType,roleIds);
    }
   /**
@@ -353,7 +411,7 @@
      LambdaQueryWrapper<Menu> wrapper = Wrappers.<Menu>query()
         .lambda()
         .in(Menu::getCode, codes)
         .eq(Menu::getIsDeleted,0) /*未被删除*/
         .eq(Menu::getIsDeleted,BladeConstant.DB_NOT_DELETED) /*未被删除*/
         .eq(Menu::getCategory,1) /*菜单类型不能为按钮*/
         .orderByAsc(Menu::getCode);  /*根据code排序与classify的btmtypeid对应*/
      // 超管不用根据角色来查询
@@ -372,6 +430,16 @@
         }
      }
      return this.list(wrapper);
   }
   /**
    * 根据父级菜单的code查询按钮信息
    * @param code
    * @return
    */
   @Override
   public List<Menu> getButtonByParentCode(String code) {
      return menuMapper.getButtonsByRoleIdAndCode(null,code);
   }
   /**
@@ -430,4 +498,34 @@
      return this.saveBatch(newButtons) ? R.success("按钮克隆成功!"):R.fail("按钮克隆失败!");
   }
   /**
    * 根据主键获取菜单信息
    * @param ids
    * @param menuCode
    * @param roleIds
    * @return
    */
   @Override
   public List<Menu> getMenuListByCode(List<String> ids,String menuCode,List<String> roleIds){
      List<Menu> menuButtonList = null;
      if(VciBaseUtil.checkAdminTenant()){
         // 正常情况下来说这个不存在为空的情况
         // 查询该菜单下的所有按钮
         menuButtonList = menuMapper.getButtonByIdsOrByParentCode(null, menuCode, null);
      }else {
         menuButtonList = menuMapper.getButtonByIdsOrByParentCode(roleIds,null,ids);
      }
      return menuButtonList;
   }
   /**
    * 根据角色id获取已授权的按钮信息
    * @param roleId
    * @return
    */
   @Override
   public List<Menu> getButtonsByRoleId(String roleId, String menuCode) {
      return menuMapper.getButtonsByRoleIdAndCode(roleId,menuCode);
   }
}