diff --git a/tyr-api/src/main/java/cn/axzo/tyr/client/model/enums/DelegatedType.java b/tyr-api/src/main/java/cn/axzo/tyr/client/model/enums/DelegatedType.java index cc9bf3bd..85c54168 100644 --- a/tyr-api/src/main/java/cn/axzo/tyr/client/model/enums/DelegatedType.java +++ b/tyr-api/src/main/java/cn/axzo/tyr/client/model/enums/DelegatedType.java @@ -1,6 +1,7 @@ package cn.axzo.tyr.client.model.enums; import lombok.AllArgsConstructor; +import lombok.Getter; import java.util.HashMap; import java.util.Map; @@ -12,6 +13,7 @@ import java.util.Map; * @author: ZhanSiHu * @date: 2023/9/6 11:05 */ +@Getter @AllArgsConstructor public enum DelegatedType { @@ -30,7 +32,7 @@ public enum DelegatedType { } } - public DelegatedType apply(Integer code) { + public static DelegatedType apply(Integer code) { return code == null ? null :MAPPING.get(code); } } diff --git a/tyr-api/src/main/java/cn/axzo/tyr/client/model/enums/FeatureType.java b/tyr-api/src/main/java/cn/axzo/tyr/client/model/enums/FeatureType.java new file mode 100644 index 00000000..63e1b2ea --- /dev/null +++ b/tyr-api/src/main/java/cn/axzo/tyr/client/model/enums/FeatureType.java @@ -0,0 +1,39 @@ +package cn.axzo.tyr.client.model.enums; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.HashMap; +import java.util.Map; + +/** + * 权限点元素类型 + * + * @version V1.0 + * @author: ZhanSiHu + * @date: 2023/9/6 21:03 + */ +@Getter +@AllArgsConstructor +public enum FeatureType { + + MODULE(0, "模块"), + MENU(1, "菜单"), + PAGE(2, "页面"), + BUTTON(3, "按钮"), + ; + + private Integer code; + private String desc; + + private static final Map MAPPING = new HashMap<>(); + static { + for (FeatureType type : FeatureType.values()) { + MAPPING.put(type.code, type); + } + } + + public static FeatureType apply(Integer code) { + return code == null ? null :MAPPING.get(code); + } +} diff --git a/tyr-api/src/main/java/cn/axzo/tyr/client/model/permission/PermissionPointDTO.java b/tyr-api/src/main/java/cn/axzo/tyr/client/model/permission/PermissionPointDTO.java index bec51d28..d76d2277 100644 --- a/tyr-api/src/main/java/cn/axzo/tyr/client/model/permission/PermissionPointDTO.java +++ b/tyr-api/src/main/java/cn/axzo/tyr/client/model/permission/PermissionPointDTO.java @@ -3,6 +3,7 @@ package cn.axzo.tyr.client.model.permission; import lombok.Data; import java.time.LocalDateTime; +import java.util.List; /** * 权限点对象 @@ -35,10 +36,13 @@ public class PermissionPointDTO { private String icon; /** - * 上级权限点id + * 父级权限点id */ private Long parentId; + /** 父级权限点名称 **/ + private String parentName; + /** * 页面路由 @@ -65,6 +69,9 @@ public class PermissionPointDTO { */ private String path; + /** 上级节点层级名称 **/ + private List parentPath; + /** * 排序 */ diff --git a/tyr-api/src/main/java/cn/axzo/tyr/client/model/permission/PermissionPointTreeNode.java b/tyr-api/src/main/java/cn/axzo/tyr/client/model/permission/PermissionPointTreeNode.java index 76658990..e3f6b053 100644 --- a/tyr-api/src/main/java/cn/axzo/tyr/client/model/permission/PermissionPointTreeNode.java +++ b/tyr-api/src/main/java/cn/axzo/tyr/client/model/permission/PermissionPointTreeNode.java @@ -40,6 +40,10 @@ public class PermissionPointTreeNode implements IBaseTree children; diff --git a/tyr-api/src/main/java/cn/axzo/tyr/client/model/permission/PermissionPointTreeQueryReq.java b/tyr-api/src/main/java/cn/axzo/tyr/client/model/permission/PermissionPointTreeQueryReq.java index 6c5bf761..0a0b5f5e 100644 --- a/tyr-api/src/main/java/cn/axzo/tyr/client/model/permission/PermissionPointTreeQueryReq.java +++ b/tyr-api/src/main/java/cn/axzo/tyr/client/model/permission/PermissionPointTreeQueryReq.java @@ -15,7 +15,7 @@ import java.util.List; public class PermissionPointTreeQueryReq { /** 授权策略 0-全部 1-平台授权型 2-客户授权型 3-免授权型**/ - private Integer delegateType; + private Integer delegateType = 0; /** 搜索关键字 - 名称模糊搜索 **/ private String keyword; diff --git a/tyr-server/src/main/java/cn/axzo/tyr/server/controller/permission/PermissionPointController.java b/tyr-server/src/main/java/cn/axzo/tyr/server/controller/permission/PermissionPointController.java index c1cc1252..b90c1a09 100644 --- a/tyr-server/src/main/java/cn/axzo/tyr/server/controller/permission/PermissionPointController.java +++ b/tyr-server/src/main/java/cn/axzo/tyr/server/controller/permission/PermissionPointController.java @@ -28,6 +28,7 @@ public class PermissionPointController implements PermissionPointApi { @Override public ApiResult> listTreeNodes(PermissionPointTreeQueryReq request) { + //查询数据 return ApiResult.ok(permissionPointService.listTreeNodes(request)); } } diff --git a/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/PermissionPointServiceImpl.java b/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/PermissionPointServiceImpl.java index 5041aed9..f7ffd5cf 100644 --- a/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/PermissionPointServiceImpl.java +++ b/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/PermissionPointServiceImpl.java @@ -1,21 +1,32 @@ package cn.axzo.tyr.server.service.impl; import cn.axzo.basics.common.BeanMapper; +import cn.axzo.basics.common.util.TreeUtil; +import cn.axzo.framework.domain.web.BizException; +import cn.axzo.framework.domain.web.code.BaseCode; +import cn.axzo.tyr.client.model.enums.FeatureType; import cn.axzo.tyr.client.model.permission.PermissionPointTreeNode; import cn.axzo.tyr.client.model.permission.PermissionPointTreeQueryReq; import cn.axzo.tyr.server.repository.entity.SaasFeature; import cn.axzo.tyr.server.repository.service.SaasFeatureDao; import cn.axzo.tyr.server.service.PermissionPointService; +import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.CollectionUtil; +import cn.hutool.core.util.NumberUtil; +import cn.hutool.core.util.StrUtil; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; +import java.util.ArrayList; +import java.util.Comparator; import java.util.List; +import java.util.Map; import java.util.Objects; import java.util.stream.Collectors; +import java.util.stream.Stream; /** * 权限点服务实现 @@ -32,12 +43,81 @@ public class PermissionPointServiceImpl implements PermissionPointService { @Override public List listTreeNodes(PermissionPointTreeQueryReq request) { - List list = saasFeatureDao.list(new LambdaQueryWrapper() - .eq(Objects.isNull(request.getDelegateType()), SaasFeature::getDelegatedType, request.getDelegateType()) - .eq(Objects.isNull(request.getParentId()), SaasFeature::getParentId, request.getParentId()) - .in(CollectionUtil.isEmpty(request.getTerminalList()), SaasFeature::getTerminal, request.getTerminalList()) - ); - return list.stream().map(this::feature2Node).collect(Collectors.toList()); + //查询条件构建 + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper() + .in(CollectionUtil.isNotEmpty(request.getTerminalList()), SaasFeature::getTerminal, request.getTerminalList()); + //查指定节点子级处理条件 + if (request.getParentId() != null && request.getParentId() != 0) { + SaasFeature parent = this.saasFeatureDao.getById(request.getParentId()); + if (parent == null) { + log.error("指定的父级节点不存在:{}", request.getParentId()); + throw new BizException(BaseCode.BAD_REQUEST); + } + //追加条件path左匹配 + queryWrapper.likeRight(SaasFeature::getPath, parent.getPath() + parent.getId() + "/"); + } + List list = saasFeatureDao.list(queryWrapper); + + //构建树形结构, 整体排序保证层级内的有序 - 优化点:构建树形结构时进行过滤 + List treeList = TreeUtil.buildTree(list.stream() + .map(this::feature2Node) + .sorted(Comparator.comparing(PermissionPointTreeNode::getSort)) + .collect(Collectors.toList())); + list = null; //for GC + + //搜索或需要按授权策略过滤 - 有额外的过滤条件 + List result = filterTreeNode(request, treeList); + + //指定parent后不需要顶级的工作台 + if (request.getParentId() != null) { + return result; + } + + //按terminal分组 + Map> mappingNode = treeList.stream() + .collect(Collectors.groupingBy(PermissionPointTreeNode::getTerminal)); + //构建terminal工作台层级 + + return result; + } + + private List filterTreeNode(PermissionPointTreeQueryReq request, List treeList) { + //过滤条件 + boolean needFilter = StrUtil.isNotBlank(request.getKeyword()) + || request.getDelegateType() != 0; + + if (needFilter) { + return treeList.stream().filter(x -> this.recursionFilter(request, x)).collect(Collectors.toList()); + } + return treeList; + } + + private boolean recursionFilter(PermissionPointTreeQueryReq request, PermissionPointTreeNode node) { + + //条件匹配 - 关键字 + boolean matchKeyword = request.getKeyword() == null || node.getPermissionName().contains(request.getKeyword()); + + //条件匹配 - 授权策略类型 + boolean matchDelegateType = request.getDelegateType() == 0 || Objects.equals(request.getDelegateType(), node.getDelegatedType()); + + if (matchKeyword && matchDelegateType) { + //如果匹配直接返回,否则过滤子节点 + return true; + } + + if (CollectionUtil.isEmpty(node.getChildren())) { + return false; + } + //过滤子节点 - 递归 - 必要时改为循环 + List filterChildren = node.getChildren().stream() + .filter(x -> recursionFilter(request, x)) + .collect(Collectors.toList()); + + if (CollectionUtil.isEmpty(filterChildren)) { + return false; + } + node.setChildren(filterChildren); + return true; } @Override @@ -51,6 +131,10 @@ public class PermissionPointServiceImpl implements PermissionPointService { node.setPermissionName(feature.getFeatureName()); node.setParentId(feature.getParentId()); node.setTerminal(feature.getTerminal()); + node.setFeatureType(feature.getFeatureType()); + node.setFeatureTypeDesc(FeatureType.apply(feature.getFeatureType()).getDesc()); + node.setPath(feature.getPath()); + node.setSort(feature.getSort()); return node; } diff --git a/tyr-server/src/test/java/cn/axzo/tyr/server/permission/PermissionPointTest.java b/tyr-server/src/test/java/cn/axzo/tyr/server/permission/PermissionPointTest.java index 1a4ba03b..38ea49e2 100644 --- a/tyr-server/src/test/java/cn/axzo/tyr/server/permission/PermissionPointTest.java +++ b/tyr-server/src/test/java/cn/axzo/tyr/server/permission/PermissionPointTest.java @@ -1,9 +1,13 @@ package cn.axzo.tyr.server.permission; +import cn.axzo.framework.domain.web.result.ApiResult; +import cn.axzo.tyr.client.model.permission.PermissionPointTreeNode; +import cn.axzo.tyr.client.model.permission.PermissionPointTreeQueryReq; import cn.axzo.tyr.server.controller.permission.PermissionPointController; import cn.axzo.tyr.server.repository.entity.SaasFeature; import cn.axzo.tyr.server.repository.service.SaasFeatureDao; import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.serializer.SerializerFeature; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; @@ -30,4 +34,14 @@ public class PermissionPointTest { List saasFeatures = saasFeatureDao.listByIds(Arrays.asList(206L, 207L, 208L)); System.out.println(JSON.toJSONString(saasFeatures)); } + + @Test + public void testListTreeNode() { + PermissionPointTreeQueryReq request = new PermissionPointTreeQueryReq(); + request.setParentId(354L); + request.setKeyword("合同"); + ApiResult> result = controller.listTreeNodes(request); + System.out.println("---------------"); + System.out.println(JSON.toJSONString(result, SerializerFeature.DisableCircularReferenceDetect)); + } }