package com.iailab.module.system.convert.auth; import cn.hutool.core.collection.CollUtil; import com.iailab.framework.common.util.object.BeanUtils; import com.iailab.module.system.api.sms.dto.code.SmsCodeSendReqDTO; import com.iailab.module.system.api.sms.dto.code.SmsCodeUseReqDTO; import com.iailab.module.system.api.social.dto.SocialUserBindReqDTO; import com.iailab.module.system.controller.admin.auth.vo.*; import com.iailab.module.system.dal.dataobject.oauth2.OAuth2AccessTokenDO; import com.iailab.module.system.dal.dataobject.permission.MenuDO; import com.iailab.module.system.dal.dataobject.permission.RoleDO; import com.iailab.module.system.dal.dataobject.user.AdminUserDO; import com.iailab.module.system.enums.permission.MenuTypeEnum; import org.mapstruct.Mapper; import org.mapstruct.factory.Mappers; import org.slf4j.LoggerFactory; import java.util.*; import static com.iailab.framework.common.util.collection.CollectionUtils.convertSet; import static com.iailab.framework.common.util.collection.CollectionUtils.filterList; import static com.iailab.module.system.dal.dataobject.permission.MenuDO.ID_ROOT; @Mapper public interface AuthConvert { AuthConvert INSTANCE = Mappers.getMapper(AuthConvert.class); AuthLoginRespVO convert(OAuth2AccessTokenDO bean); default AuthPermissionInfoRespVO convert(AdminUserDO user, List roleList, List menuList) { return AuthPermissionInfoRespVO.builder() .user(BeanUtils.toBean(user, AuthPermissionInfoRespVO.UserVO.class)) .roles(convertSet(roleList, RoleDO::getCode)) // 权限标识信息 .permissions(convertSet(menuList, MenuDO::getPermission)) // 菜单树 .menus(buildMenuTree(menuList)) .build(); } default AuthPermissionInfoRespVO convertAppMenu(AdminUserDO user, List roleList, List menuList) { return AuthPermissionInfoRespVO.builder() .user(BeanUtils.toBean(user, AuthPermissionInfoRespVO.UserVO.class)) .roles(convertSet(roleList, RoleDO::getCode)) // 权限标识信息 .permissions(convertSet(menuList, MenuDO::getPermission)) // 菜单树 .menus(buildAppMenuTree(menuList)) .build(); } AuthPermissionInfoRespVO.MenuVO convertTreeNode(MenuDO menu); /** * 将菜单列表,构建成菜单树 * * @param menuList 菜单列表 * @return 菜单树 */ default List buildMenuTree(List menuList) { if (CollUtil.isEmpty(menuList)) { return Collections.emptyList(); } // 移除按钮和应用菜单 menuList.removeIf(menu -> menu.getType().equals(MenuTypeEnum.BUTTON.getType())); // 排序,保证菜单的有序性 menuList.sort(Comparator.comparing(MenuDO::getSort)); // 构建菜单树 // 使用 LinkedHashMap 的原因,是为了排序 。实际也可以用 Stream API ,就是太丑了。 Map treeNodeMap = new LinkedHashMap<>(); menuList.forEach(menu -> treeNodeMap.put(menu.getId(), AuthConvert.INSTANCE.convertTreeNode(menu))); // 处理父子关系 treeNodeMap.values().stream().filter(node -> !node.getParentId().equals(ID_ROOT)).forEach(childNode -> { // 获得父节点 AuthPermissionInfoRespVO.MenuVO parentNode = treeNodeMap.get(childNode.getParentId()); if (parentNode == null) { LoggerFactory.getLogger(getClass()).error("[buildRouterTree][resource({}) 找不到父资源({})]", childNode.getId(), childNode.getParentId()); return; } // 将自己添加到父节点中 if (parentNode.getChildren() == null) { parentNode.setChildren(new ArrayList<>()); } parentNode.getChildren().add(childNode); }); // 获得到所有的根节点 return filterList(treeNodeMap.values(), node -> ID_ROOT.equals(node.getParentId())); } /** * 将菜单列表,构建成菜单树 * * @param menuList 菜单列表 * @return 菜单树 */ default List buildAppMenuTree(List menuList) { if (CollUtil.isEmpty(menuList)) { return Collections.emptyList(); } // 移除按钮和应用菜单 menuList.removeIf(menu -> menu.getType().equals(MenuTypeEnum.BUTTON.getType())); // 排序,保证菜单的有序性 menuList.sort(Comparator.comparing(MenuDO::getSort)); // 构建菜单树 // 使用 LinkedHashMap 的原因,是为了排序 。实际也可以用 Stream API ,就是太丑了。 Map treeNodeMap = new LinkedHashMap<>(); menuList.forEach(menu -> treeNodeMap.put(menu.getId(), AuthConvert.INSTANCE.convertTreeNode(menu))); // 处理父子关系 treeNodeMap.values().stream().filter(node -> !node.getParentId().equals(ID_ROOT)).forEach(childNode -> { // 获得父节点 AuthPermissionInfoRespVO.MenuVO parentNode = treeNodeMap.get(childNode.getParentId()); if (parentNode == null) { LoggerFactory.getLogger(getClass()).error("[buildRouterTree][resource({}) 找不到父资源({})]", childNode.getId(), childNode.getParentId()); return; } // 将自己添加到父节点中 if (parentNode.getChildren() == null) { parentNode.setChildren(new ArrayList<>()); } parentNode.getChildren().add(childNode); }); // 获得到所有的根节点 return filterList(treeNodeMap.values(), node -> ID_ROOT.equals(node.getParentId())); } /** * 将菜单列表,构建成菜单树 * * @param menuList 菜单列表 * @return 菜单树 */ default List buildMenuTree(List menuList, Long id, String parentPath) { if (CollUtil.isEmpty(menuList)) { return Collections.emptyList(); } // 移除按钮 menuList.removeIf(menu -> menu.getType().equals(MenuTypeEnum.BUTTON.getType())); // 排序,保证菜单的有序性 menuList.sort(Comparator.comparing(MenuDO::getSort)); // 构建菜单树 // 使用 LinkedHashMap 的原因,是为了排序 。实际也可以用 Stream API ,就是太丑了。 Map treeNodeMap = new LinkedHashMap<>(); menuList.forEach(menu -> treeNodeMap.put(menu.getId(), AuthConvert.INSTANCE.convertTreeNode(menu))); // 处理父子关系 treeNodeMap.values().stream().filter(node -> !node.getParentId().equals(id)).forEach(childNode -> { // 获得父节点 AuthPermissionInfoRespVO.MenuVO parentNode = treeNodeMap.get(childNode.getParentId()); if (parentNode == null) { LoggerFactory.getLogger(getClass()).error("[buildRouterTree][resource({}) 找不到父资源({})]", childNode.getId(), childNode.getParentId()); return; } // 将自己添加到父节点中 if (parentNode.getChildren() == null) { parentNode.setChildren(new ArrayList<>()); } parentNode.getChildren().add(childNode); }); // 获得到所有的根节点 List menuVOS = filterList(treeNodeMap.values(), node -> id.equals(node.getParentId())); menuVOS.stream().forEach(menuVO -> { menuVO.setPath((parentPath + "/" + menuVO.getPath()).replace("//", "/")); }); return menuVOS; } /** * 将菜单列表,构建成菜单树 * * @param menuList 菜单列表 * @return 菜单树 */ default List buildMenuTree(List menuList, Long id, String parentPath, Integer type) { if (CollUtil.isEmpty(menuList)) { return Collections.emptyList(); } // 移除按钮 menuList.removeIf(menu -> menu.getType().equals(MenuTypeEnum.BUTTON.getType())); // 排序,保证菜单的有序性 menuList.sort(Comparator.comparing(MenuDO::getSort)); // 构建菜单树 // 使用 LinkedHashMap 的原因,是为了排序 。实际也可以用 Stream API ,就是太丑了。 Map treeNodeMap = new LinkedHashMap<>(); menuList.forEach(menu -> treeNodeMap.put(menu.getId(), AuthConvert.INSTANCE.convertTreeNode(menu))); // 处理父子关系 treeNodeMap.values().stream().filter(node -> !node.getParentId().equals(id)).forEach(childNode -> { // 获得父节点 AuthPermissionInfoRespVO.MenuVO parentNode = treeNodeMap.get(childNode.getParentId()); if (parentNode == null) { LoggerFactory.getLogger(getClass()).error("[buildRouterTree][resource({}) 找不到父资源({})]", childNode.getId(), childNode.getParentId()); return; } // 将自己添加到父节点中 if (parentNode.getChildren() == null) { parentNode.setChildren(new ArrayList<>()); } parentNode.getChildren().add(childNode); }); // 获得到所有的根节点 List menuVOS = filterList(treeNodeMap.values(), node -> id.equals(node.getParentId())); if(type == 0) { menuVOS.stream().forEach(menuVO -> { // 不处理外链菜单path if(!menuVO.getPath().contains("http:") && !menuVO.getPath().contains("https:")) { menuVO.setPath((parentPath + "/" + menuVO.getPath()).replace("//", "/")); } }); } return menuVOS; } SocialUserBindReqDTO convert(Long userId, Integer userType, AuthSocialLoginReqVO reqVO); SmsCodeSendReqDTO convert(AuthSmsSendReqVO reqVO); SmsCodeUseReqDTO convert(AuthSmsLoginReqVO reqVO, Integer scene, String usedIp); }