diff --git a/tyr-api/src/main/java/cn/axzo/tyr/client/feign/FeatureResourceApi.java b/tyr-api/src/main/java/cn/axzo/tyr/client/feign/FeatureResourceApi.java index 57225992..93f5f820 100644 --- a/tyr-api/src/main/java/cn/axzo/tyr/client/feign/FeatureResourceApi.java +++ b/tyr-api/src/main/java/cn/axzo/tyr/client/feign/FeatureResourceApi.java @@ -1,6 +1,7 @@ package cn.axzo.tyr.client.feign; import cn.axzo.framework.domain.web.result.ApiResult; +import cn.axzo.tyr.client.model.req.GetFeatureResourceTreeReq; import cn.axzo.tyr.client.model.req.ResourceSyncReq; import cn.axzo.tyr.client.model.req.FeatureResourceTreeSaveReq; import cn.axzo.tyr.client.model.res.FeatureResourceDetailResp; @@ -36,6 +37,10 @@ public interface FeatureResourceApi { @PostMapping("/api/featureResource/saveOrUpdate") ApiResult saveMenu(@RequestBody FeatureResourceTreeSaveReq req); + /** 查询功能资源树 **/ + @PostMapping("/api/featureResource/getTree") + ApiResult> getTree(@RequestBody @Valid GetFeatureResourceTreeReq req); + /** 删除菜单/页面/组件 **/ @PostMapping("/api/featureResource/delete") ApiResult deleteFeatureResource(@RequestParam Long featureId, @RequestParam Long operatorId); diff --git a/tyr-api/src/main/java/cn/axzo/tyr/client/feign/SaasRoleGroupApi.java b/tyr-api/src/main/java/cn/axzo/tyr/client/feign/SaasRoleGroupApi.java index c261b38e..0df9e9c7 100644 --- a/tyr-api/src/main/java/cn/axzo/tyr/client/feign/SaasRoleGroupApi.java +++ b/tyr-api/src/main/java/cn/axzo/tyr/client/feign/SaasRoleGroupApi.java @@ -2,6 +2,7 @@ package cn.axzo.tyr.client.feign; import cn.axzo.framework.domain.web.result.ApiResult; import cn.axzo.tyr.client.model.req.QuerySaasRoleGroupReq; +import cn.axzo.tyr.client.model.req.UpdateRoleGroupOffsetReq; import cn.axzo.tyr.client.model.vo.SaasRoleGroupVO; import org.springframework.cloud.openfeign.FeignClient; import org.springframework.web.bind.annotation.GetMapping; @@ -9,6 +10,7 @@ import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestParam; +import javax.validation.Valid; import javax.validation.constraints.NotEmpty; import java.util.List; @@ -61,5 +63,13 @@ public interface SaasRoleGroupApi { @GetMapping("/api/saasRoleGroup/listByCategoryCode") ApiResult> listByCategoryCode(@RequestParam("categoryCode") List categoryCodes); - + /** + * 更新角色分组的位置 + * 向下移动,则找到后面位置的分组,替换sort + * 向上移动,则找到前面位置的分组,替换sort + * @param request + * @return + */ + @PostMapping("/api/role/group/offset/update") + ApiResult updateRoleGroupOffset(@Valid @RequestBody UpdateRoleGroupOffsetReq request); } diff --git a/tyr-api/src/main/java/cn/axzo/tyr/client/model/req/GetFeatureResourceTreeReq.java b/tyr-api/src/main/java/cn/axzo/tyr/client/model/req/GetFeatureResourceTreeReq.java new file mode 100644 index 00000000..2c2438d3 --- /dev/null +++ b/tyr-api/src/main/java/cn/axzo/tyr/client/model/req/GetFeatureResourceTreeReq.java @@ -0,0 +1,30 @@ +package cn.axzo.tyr.client.model.req; + +import lombok.*; + +import java.util.List; + +/** + * @author likunpeng + * @version 1.0 + * @date 2024/4/9 + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@ToString +public class GetFeatureResourceTreeReq { + + /** 查询搜索关键字 **/ + private String keyword; + + /** 端 **/ + private String terminal; + + /** 展示状态 默认不传返回全部 0-隐藏 1-显示 **/ + private Integer status; + + /** feature类型列表 **/ + private List featureTypes; +} diff --git a/tyr-api/src/main/java/cn/axzo/tyr/client/model/req/QuerySaasRoleGroupReq.java b/tyr-api/src/main/java/cn/axzo/tyr/client/model/req/QuerySaasRoleGroupReq.java index 2e6cab57..6c732293 100644 --- a/tyr-api/src/main/java/cn/axzo/tyr/client/model/req/QuerySaasRoleGroupReq.java +++ b/tyr-api/src/main/java/cn/axzo/tyr/client/model/req/QuerySaasRoleGroupReq.java @@ -44,4 +44,6 @@ public class QuerySaasRoleGroupReq { * 被那些角色使用到的分组 */ private List roleIds; + + private Long parentId; } diff --git a/tyr-api/src/main/java/cn/axzo/tyr/client/model/req/UpdateRoleGroupOffsetReq.java b/tyr-api/src/main/java/cn/axzo/tyr/client/model/req/UpdateRoleGroupOffsetReq.java new file mode 100644 index 00000000..203eef0c --- /dev/null +++ b/tyr-api/src/main/java/cn/axzo/tyr/client/model/req/UpdateRoleGroupOffsetReq.java @@ -0,0 +1,27 @@ +package cn.axzo.tyr.client.model.req; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import javax.validation.constraints.NotNull; + +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class UpdateRoleGroupOffsetReq { + + /** + * 角色分组id + */ + @NotNull(message = "id不能为空") + private Long id; + + /** + * 偏移量:向上移就是负数,例如上移一位:-1,向下移就是正数,例如下移一位:1 + */ + @NotNull(message = "offset不能为空") + private Integer offset; +} diff --git a/tyr-server/src/main/java/cn/axzo/tyr/server/TyrApplication.java b/tyr-server/src/main/java/cn/axzo/tyr/server/TyrApplication.java index e07a81da..9df76d7a 100644 --- a/tyr-server/src/main/java/cn/axzo/tyr/server/TyrApplication.java +++ b/tyr-server/src/main/java/cn/axzo/tyr/server/TyrApplication.java @@ -4,6 +4,7 @@ import lombok.extern.slf4j.Slf4j; import org.mybatis.spring.annotation.MapperScan; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.cache.annotation.EnableCaching; import org.springframework.cloud.client.discovery.EnableDiscoveryClient; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.core.env.Environment; @@ -11,6 +12,7 @@ import org.springframework.scheduling.annotation.EnableAsync; @Slf4j @EnableAsync +@EnableCaching @EnableDiscoveryClient @MapperScan(value = {"cn.axzo.tyr.server.repository.mapper"}) @SpringBootApplication(scanBasePackages = "cn.axzo") diff --git a/tyr-server/src/main/java/cn/axzo/tyr/server/controller/permission/FeatureResourceController.java b/tyr-server/src/main/java/cn/axzo/tyr/server/controller/permission/FeatureResourceController.java index b0871bc4..3aa30cc9 100644 --- a/tyr-server/src/main/java/cn/axzo/tyr/server/controller/permission/FeatureResourceController.java +++ b/tyr-server/src/main/java/cn/axzo/tyr/server/controller/permission/FeatureResourceController.java @@ -3,6 +3,7 @@ package cn.axzo.tyr.server.controller.permission; import cn.axzo.framework.domain.web.result.ApiResult; import cn.axzo.tyr.client.feign.FeatureResourceApi; import cn.axzo.tyr.client.model.req.FeatureResourceTreeSaveReq; +import cn.axzo.tyr.client.model.req.GetFeatureResourceTreeReq; import cn.axzo.tyr.client.model.req.ResourceSyncReq; import cn.axzo.tyr.client.model.res.FeatureResourceDetailResp; import cn.axzo.tyr.client.model.res.FeatureResourceTreeNode; @@ -76,10 +77,11 @@ public class FeatureResourceController implements FeatureResourceApi { @Override public ApiResult detail(Long featureId) { - - - - return null; } + + @Override + public ApiResult> getTree(GetFeatureResourceTreeReq req) { + return ApiResult.ok(featureResourceService.getTree(req)); + } } diff --git a/tyr-server/src/main/java/cn/axzo/tyr/server/controller/role/SaasRoleGroupController.java b/tyr-server/src/main/java/cn/axzo/tyr/server/controller/role/SaasRoleGroupController.java index 994e8e52..6e507ce3 100644 --- a/tyr-server/src/main/java/cn/axzo/tyr/server/controller/role/SaasRoleGroupController.java +++ b/tyr-server/src/main/java/cn/axzo/tyr/server/controller/role/SaasRoleGroupController.java @@ -4,6 +4,7 @@ import cn.axzo.basics.common.exception.ServiceException; import cn.axzo.framework.domain.web.result.ApiResult; import cn.axzo.tyr.client.feign.SaasRoleGroupApi; import cn.axzo.tyr.client.model.req.QuerySaasRoleGroupReq; +import cn.axzo.tyr.client.model.req.UpdateRoleGroupOffsetReq; import cn.axzo.tyr.client.model.vo.SaasRoleGroupVO; import cn.axzo.tyr.server.service.SaasRoleGroupService; import com.google.common.collect.Lists; @@ -12,7 +13,9 @@ import lombok.extern.slf4j.Slf4j; import org.apache.commons.collections.CollectionUtils; import org.springframework.web.bind.annotation.RestController; +import java.util.Comparator; import java.util.List; +import java.util.stream.Collectors; @Slf4j @RestController @@ -56,4 +59,64 @@ public class SaasRoleGroupController implements SaasRoleGroupApi { return ApiResult.ok(saasRoleGroupService.listByCategoryCode(categoryCode)); } + @Override + public ApiResult updateRoleGroupOffset(UpdateRoleGroupOffsetReq request) { + if (request.getOffset() != 1 && request.getOffset() != -1) { + throw new ServiceException("暂时只支持移动一个位置"); + } + SaasRoleGroupVO saasRoleGroup = getById(request.getId()).getData(); + + List roleGroupList = saasRoleGroupService.getRoleGroupList(QuerySaasRoleGroupReq.builder() + .parentId(saasRoleGroup.getParentId()) + .workspaceTypeCode(Lists.newArrayList(saasRoleGroup.getWorkspaceTypeCode())) + .build()) + .stream() + .sorted(Comparator.comparing(SaasRoleGroupVO::getSort)) + .collect(Collectors.toList()); + + SaasRoleGroupVO exchangeRoleGroup = findExchangeRoleGroup(request, saasRoleGroup, roleGroupList); + if (exchangeRoleGroup == null) { + throw new ServiceException("未找到可以移动的位置"); + } + saasRoleGroupService.saveOrUpdate(SaasRoleGroupVO.builder() + .id(saasRoleGroup.getId()) + .sort(exchangeRoleGroup.getSort()) + .build()); + + saasRoleGroupService.saveOrUpdate(SaasRoleGroupVO.builder() + .id(exchangeRoleGroup.getId()) + .sort(saasRoleGroup.getSort()) + .build()); + return ApiResult.ok(); + } + + /** + * 只支持移动一位 + * @param request + * @param saasRoleGroup + * @param roleGroupList + * @return + */ + private SaasRoleGroupVO findExchangeRoleGroup(UpdateRoleGroupOffsetReq request, + SaasRoleGroupVO saasRoleGroup, + List roleGroupList) { + List ids = roleGroupList.stream() + .map(SaasRoleGroupVO::getId) + .collect(Collectors.toList()); + int currentIndex = ids.indexOf(request.getId()); + // 下移一位 + if (request.getOffset() == 1) { + int exchangeIndex = currentIndex + 1; + if (roleGroupList.size() > exchangeIndex) { + return roleGroupList.get(exchangeIndex); + } + } else if (request.getOffset() == -1) { + if (currentIndex == 0) { + return null; + } + int exchangeIndex = currentIndex - 1; + return roleGroupList.get(exchangeIndex); + } + return null; + } } diff --git a/tyr-server/src/main/java/cn/axzo/tyr/server/repository/dao/SaasFeatureResourceDao.java b/tyr-server/src/main/java/cn/axzo/tyr/server/repository/dao/SaasFeatureResourceDao.java index e421cdc0..89382aa8 100644 --- a/tyr-server/src/main/java/cn/axzo/tyr/server/repository/dao/SaasFeatureResourceDao.java +++ b/tyr-server/src/main/java/cn/axzo/tyr/server/repository/dao/SaasFeatureResourceDao.java @@ -1,10 +1,17 @@ package cn.axzo.tyr.server.repository.dao; +import cn.axzo.basics.common.constant.enums.TableIsDeleteEnum; +import cn.axzo.tyr.client.model.req.GetFeatureResourceTreeReq; import cn.axzo.tyr.server.repository.entity.SaasFeatureResource; import cn.axzo.tyr.server.repository.mapper.SaasFeatureResourceMapper; +import cn.azxo.framework.common.utils.StringUtils; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.apache.commons.collections.CollectionUtils; import org.springframework.stereotype.Repository; +import java.util.List; +import java.util.Objects; + /** *

* 功能资源表 服务实现类 @@ -23,4 +30,17 @@ public class SaasFeatureResourceDao extends ServiceImpl getByResourceTreeParam(GetFeatureResourceTreeReq req) { + return this.lambdaQuery().select(SaasFeatureResource::getId, SaasFeatureResource::getFeatureCode, + SaasFeatureResource::getFeatureName, SaasFeatureResource::getFeatureType, + SaasFeatureResource::getTerminal, SaasFeatureResource::getParentId, + SaasFeatureResource::getDisplayOrder) + .eq(SaasFeatureResource::getIsDelete, TableIsDeleteEnum.NORMAL.value) + .eq(StringUtils.isNotBlank(req.getTerminal()), SaasFeatureResource::getTerminal, req.getTerminal()) + .eq(Objects.nonNull(req.getStatus()), SaasFeatureResource::getStatus, req.getStatus()) + .in(CollectionUtils.isNotEmpty(req.getFeatureTypes()), SaasFeatureResource::getFeatureType, req.getFeatureTypes()) + .list(); + } + } diff --git a/tyr-server/src/main/java/cn/axzo/tyr/server/repository/dao/SaasRoleGroupDao.java b/tyr-server/src/main/java/cn/axzo/tyr/server/repository/dao/SaasRoleGroupDao.java index 8d5c7128..ffcd7dd6 100644 --- a/tyr-server/src/main/java/cn/axzo/tyr/server/repository/dao/SaasRoleGroupDao.java +++ b/tyr-server/src/main/java/cn/axzo/tyr/server/repository/dao/SaasRoleGroupDao.java @@ -13,6 +13,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Repository; import java.util.List; +import java.util.Objects; @Repository public class SaasRoleGroupDao extends ServiceImpl { @@ -37,6 +38,7 @@ public class SaasRoleGroupDao extends ServiceImpl getTree(GetFeatureResourceTreeReq req); + SaasFeatureResource getByCode(String featureCode); } diff --git a/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/SaasFeatureResourceCacheService.java b/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/SaasFeatureResourceCacheService.java new file mode 100644 index 00000000..e57bbb5d --- /dev/null +++ b/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/SaasFeatureResourceCacheService.java @@ -0,0 +1,31 @@ +package cn.axzo.tyr.server.service.impl; + +import cn.axzo.tyr.client.model.req.GetFeatureResourceTreeReq; +import cn.axzo.tyr.server.repository.dao.SaasFeatureResourceDao; +import cn.axzo.tyr.server.repository.entity.SaasFeatureResource; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.stereotype.Component; + +import java.util.List; + +/** + * @author likunpeng + * @version 1.0 + * @date 2024/4/9 + */ +@Slf4j +@Component +@RequiredArgsConstructor +public class SaasFeatureResourceCacheService { + public static final String CACHE_FEATURE_RESOURCE_TREE = "featureResource:tree"; + + private final SaasFeatureResourceDao featureResourceDao; + + @Cacheable(value = CACHE_FEATURE_RESOURCE_TREE, key = "#req.keyword + '_' + #req.terminal+ '_' + #req.featureTypes", unless = "#result.isEmpty()") + public List getByResourceTreeParam (GetFeatureResourceTreeReq req) { + log.info("get feature resource tree has not user cache!"); + return featureResourceDao.getByResourceTreeParam(req); + } +} diff --git a/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/SaasFeatureResourceServiceImpl.java b/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/SaasFeatureResourceServiceImpl.java index 3429c952..7bcc9f08 100644 --- a/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/SaasFeatureResourceServiceImpl.java +++ b/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/SaasFeatureResourceServiceImpl.java @@ -1,7 +1,8 @@ package cn.axzo.tyr.server.service.impl; import cn.axzo.basics.common.BeanMapper; -import cn.axzo.basics.common.model.IBaseTree; +import cn.axzo.basics.common.util.StopWatchUtil; +import cn.axzo.basics.common.util.TreeUtil; import cn.axzo.pokonyan.config.mybatisplus.BaseEntity; import cn.axzo.pokonyan.config.redis.RedisClient; import cn.axzo.tyr.client.common.enums.FeatureResourceAuthType; @@ -9,27 +10,32 @@ import cn.axzo.tyr.client.common.enums.FeatureResourceStatus; import cn.axzo.tyr.client.common.enums.FeatureResourceType; import cn.axzo.tyr.client.model.req.FeatureComponentSaveReq; import cn.axzo.tyr.client.model.req.FeatureResourceTreeSaveReq; +import cn.axzo.tyr.client.model.req.GetFeatureResourceTreeReq; +import cn.axzo.tyr.client.model.res.FeatureResourceDTO; +import cn.axzo.tyr.client.model.res.FeatureResourceTreeNode; import cn.axzo.tyr.server.model.ResourcePermission; import cn.axzo.tyr.server.model.ResourcePermissionQueryDTO; import cn.axzo.tyr.server.repository.dao.SaasFeatureResourceDao; import cn.axzo.tyr.server.repository.entity.SaasFeatureResource; import cn.axzo.tyr.server.service.SaasFeatureResourceService; +import cn.azxo.framework.common.utils.StringUtils; import cn.hutool.core.collection.CollectionUtil; import cn.hutool.core.lang.Assert; import cn.hutool.core.util.BooleanUtil; -import io.swagger.models.auth.In; +import com.google.common.collect.Lists; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.collections.CollectionUtils; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.cache.annotation.CacheEvict; +import org.springframework.cloud.context.config.annotation.RefreshScope; import org.springframework.stereotype.Service; -import org.springframework.util.CollectionUtils; import java.util.Collections; import java.util.Comparator; -import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Objects; -import java.util.Set; import java.util.concurrent.TimeUnit; import java.util.function.Function; import java.util.stream.Collectors; @@ -38,7 +44,8 @@ import static cn.axzo.tyr.server.common.constants.CacheConstant.KEY_AUTH_FREE; /** * 功能资源服务实现 - * + * 功能资源树查询增加了redis缓存,在新增、修改该表时,记得清空缓存, + * 实现:对应方法加上注解@CacheEvict(value = SaasFeatureResourceCacheService.CACHE_FEATURE_RESOURCE_TREE,allEntries = true) * @version V1.0 * @author: ZhanSiHu * @date: 2024/4/3 10:18 @@ -46,9 +53,19 @@ import static cn.axzo.tyr.server.common.constants.CacheConstant.KEY_AUTH_FREE; @Slf4j @Service @RequiredArgsConstructor +@RefreshScope public class SaasFeatureResourceServiceImpl implements SaasFeatureResourceService { private final SaasFeatureResourceDao featureResourceDao; + private final SaasFeatureResourceCacheService saasFeatureResourceCacheService; + + /** + * 功能资源树根节点配置 + * key < - > TerminalInfo定义的terminal + * value < - > 端描述 + */ + @Value("#{${featureResourceTreeRootNodeMap:{'NT_CMS_WEB_GENERAL':'CMS端', 'NT_OMS_WEB':'OMS端'}}}") + private Map treeRootNodeMap; @Override public List listNavByIds(List featureIds) { @@ -108,6 +125,40 @@ public class SaasFeatureResourceServiceImpl implements SaasFeatureResourceServic } @Override + public List getTree(GetFeatureResourceTreeReq req) { + List rootNodes = treeRootNodeMap.entrySet().stream().map(e -> FeatureResourceTreeNode.builder() + .id(0L).terminal(e.getKey()).featureName(e.getValue()).children(Lists.newArrayList()).build()).collect(Collectors.toList()); + + StopWatchUtil watch = StopWatchUtil.createStarted("feature-resource-tree"); + watch.start("dbQuery"); + List saasFeatureResources = saasFeatureResourceCacheService.getByResourceTreeParam(req); + watch.stop(); + if (CollectionUtils.isEmpty(saasFeatureResources)) { + return Collections.emptyList(); + } + + List treeList = TreeUtil.buildTree(saasFeatureResources.stream() + .map(this::featureResource2Node) + .sorted(Comparator.comparing(FeatureResourceDTO::getDisplayOrder)) + .collect(Collectors.toList())); + saasFeatureResources = null; // help GC + + //搜索或需要按授权策略过滤 - 有额外的过滤条件 + watch.start("filter-node"); + List filterResultNode = filterTreeNode(req.getKeyword(), treeList); + watch.stop(); + + //把处理后的树结构添加上根节点 + watch.start("fill-children-to-root"); + List resultNode = fillChildren2Root(rootNodes, filterResultNode); + watch.stop(); + + log.info("feature-resource-tree cost:{} , ms:{}", watch.prettyPrint(), watch.getTotalTimeMillis()); + return resultNode; + } + + @Override + @CacheEvict(value = SaasFeatureResourceCacheService.CACHE_FEATURE_RESOURCE_TREE,allEntries = true) public void saveOrUpdateMenu(FeatureResourceTreeSaveReq req) { SaasFeatureResource baseResource = BeanMapper.copyBean(req, SaasFeatureResource.class); baseResource.setUpdateBy(req.getOperatorId()); @@ -258,4 +309,52 @@ public class SaasFeatureResourceServiceImpl implements SaasFeatureResourceServic featureResourceDao.updateBatchById(parallelFeature); } + + private FeatureResourceTreeNode featureResource2Node(SaasFeatureResource featureResource) { + return FeatureResourceTreeNode.builder() + .id(featureResource.getId()) + .featureCode(featureResource.getFeatureCode()) + .featureName(featureResource.getFeatureName()) + .featureType(featureResource.getFeatureType()) + .terminal(featureResource.getTerminal()) + .parentId(featureResource.getParentId()) + .displayOrder(featureResource.getDisplayOrder()) + .build(); + } + + private List filterTreeNode(String keyword, List treeList) { + if (StringUtils.isBlank(keyword)) { + return treeList; + } + + return treeList.stream().filter(x -> this.recursionFilter(keyword, x)).collect(Collectors.toList()); + } + + private boolean recursionFilter(String keyword, FeatureResourceTreeNode node) { + boolean matched = node.getFeatureName().contains(keyword); + if (CollectionUtils.isEmpty(node.getNodeChildren())) { + return matched; + } + // 过滤子节点 + List filterChildren = node.getChildren().stream().filter(x -> recursionFilter(keyword, x)).collect(Collectors.toList()); + // 重置子节点 + node.setChildren(filterChildren); + if (CollectionUtils.isEmpty(filterChildren)) { + return matched; + } + return true; + } + + private List fillChildren2Root(List rootNodes, List childrenNodes) { + Map rootNodeMap = rootNodes.stream().collect(Collectors.toMap(FeatureResourceDTO::getTerminal, Function.identity(), (v1, v2) -> v1)); + for(FeatureResourceTreeNode child : childrenNodes) { + FeatureResourceTreeNode rootNode = rootNodeMap.get(child.getTerminal()); + if (child.getParentId() > 0 || Objects.isNull(rootNode)) { + continue; + } + rootNode.getChildren().add(child); + } + + return rootNodes; + } } diff --git a/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/SaasRoleGroupServiceImpl.java b/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/SaasRoleGroupServiceImpl.java index 8aa00f0b..7ccc9388 100644 --- a/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/SaasRoleGroupServiceImpl.java +++ b/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/SaasRoleGroupServiceImpl.java @@ -16,7 +16,13 @@ import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang3.StringUtils; import org.springframework.stereotype.Service; -import java.util.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Date; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Optional; import java.util.stream.Collectors; @Slf4j @@ -125,6 +131,7 @@ public class SaasRoleGroupServiceImpl implements SaasRoleGroupService { //新增 saasRoleGroup = new SaasRoleGroup(); saasRoleGroup.setCreateAt(now); + checkAdd(req); } else { //修改 saasRoleGroup = saasRoleGroupDao.lambdaQuery().eq(SaasRoleGroup::getId, req.getId()) @@ -157,6 +164,9 @@ public class SaasRoleGroupServiceImpl implements SaasRoleGroupService { saasRoleGroup.setWorkspaceId(req.getWorkspaceId() != null ? req.getWorkspaceId() : -1L); saasRoleGroup.setOuId(req.getOuId() != null ? req.getOuId() : -1L); saasRoleGroup.setParentId(req.getParentId()); + saasRoleGroup.setCode(req.getCode()); + // 新增的时候,没有指定sort,sort放在同层级的最后 + assembleSort(saasRoleGroup); return saasRoleGroup; } @@ -164,4 +174,38 @@ public class SaasRoleGroupServiceImpl implements SaasRoleGroupService { public List listByCategoryCode(List categoryCode) { return BeanUtil.copyToList(saasRoleGroupDao.listByCategoryCode(categoryCode), SaasRoleGroupVO.class); } + + private void assembleSort(SaasRoleGroup saasRoleGroup) { + if (saasRoleGroup.getSort() != null || saasRoleGroup.getId() != null || saasRoleGroup.getParentId() == null) { + return; + } + + Optional last = saasRoleGroupDao.lambdaQuery() + .eq(SaasRoleGroup::getParentId, saasRoleGroup.getParentId()) + .eq(SaasRoleGroup::getWorkspaceTypeCode, saasRoleGroup.getWorkspaceTypeCode()) + .eq(SaasRoleGroup::getIsDelete, TableIsDeleteEnum.NORMAL.value) + .orderByDesc(SaasRoleGroup::getSort) + .last("limit 1") + .list() + .stream() + .findFirst(); + saasRoleGroup.setSort(last.map(e -> e.getSort() == null ? 1 : e.getSort() + 1).orElse(1)); + } + + private void checkAdd(SaasRoleGroupVO req) { + // 只有新增的时候才会提交code + if (req.getId() != null) { + return; + } + + if (StringUtils.isNotBlank(req.getCode())) { + Integer count = saasRoleGroupDao.lambdaQuery() + .eq(SaasRoleGroup::getCode, req.getCode()) + .eq(SaasRoleGroup::getIsDelete, TableIsDeleteEnum.NORMAL.value) + .count(); + if (count > 0) { + throw new ServiceException("角色分组编码已经存在"); + } + } + } } diff --git a/tyr-server/src/main/resources/bootstrap.yml b/tyr-server/src/main/resources/bootstrap.yml index 9bf74eb2..9a6a3cb1 100644 --- a/tyr-server/src/main/resources/bootstrap.yml +++ b/tyr-server/src/main/resources/bootstrap.yml @@ -1,4 +1,6 @@ spring: + cache: + type: redis application: name: tyr cloud: