Merge branch 'feature/REQ-2227' of https://axzsource.com/universal/infrastructure/backend/tyr into feature/REQ-2227
# Conflicts: # tyr-server/src/main/java/cn/axzo/tyr/server/controller/permission/FeatureResourceController.java
This commit is contained in:
commit
560a2aab48
@ -1,6 +1,7 @@
|
|||||||
package cn.axzo.tyr.client.feign;
|
package cn.axzo.tyr.client.feign;
|
||||||
|
|
||||||
import cn.axzo.framework.domain.web.result.ApiResult;
|
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.ResourceSyncReq;
|
||||||
import cn.axzo.tyr.client.model.req.FeatureResourceTreeSaveReq;
|
import cn.axzo.tyr.client.model.req.FeatureResourceTreeSaveReq;
|
||||||
import cn.axzo.tyr.client.model.res.FeatureResourceDetailResp;
|
import cn.axzo.tyr.client.model.res.FeatureResourceDetailResp;
|
||||||
@ -36,6 +37,10 @@ public interface FeatureResourceApi {
|
|||||||
@PostMapping("/api/featureResource/saveOrUpdate")
|
@PostMapping("/api/featureResource/saveOrUpdate")
|
||||||
ApiResult<Void> saveMenu(@RequestBody FeatureResourceTreeSaveReq req);
|
ApiResult<Void> saveMenu(@RequestBody FeatureResourceTreeSaveReq req);
|
||||||
|
|
||||||
|
/** 查询功能资源树 **/
|
||||||
|
@PostMapping("/api/featureResource/getTree")
|
||||||
|
ApiResult<List<FeatureResourceTreeNode>> getTree(@RequestBody @Valid GetFeatureResourceTreeReq req);
|
||||||
|
|
||||||
/** 删除菜单/页面/组件 **/
|
/** 删除菜单/页面/组件 **/
|
||||||
@PostMapping("/api/featureResource/delete")
|
@PostMapping("/api/featureResource/delete")
|
||||||
ApiResult<Void> deleteFeatureResource(@RequestParam Long featureId, @RequestParam Long operatorId);
|
ApiResult<Void> deleteFeatureResource(@RequestParam Long featureId, @RequestParam Long operatorId);
|
||||||
|
|||||||
@ -2,6 +2,7 @@ package cn.axzo.tyr.client.feign;
|
|||||||
|
|
||||||
import cn.axzo.framework.domain.web.result.ApiResult;
|
import cn.axzo.framework.domain.web.result.ApiResult;
|
||||||
import cn.axzo.tyr.client.model.req.QuerySaasRoleGroupReq;
|
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.client.model.vo.SaasRoleGroupVO;
|
||||||
import org.springframework.cloud.openfeign.FeignClient;
|
import org.springframework.cloud.openfeign.FeignClient;
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
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.RequestBody;
|
||||||
import org.springframework.web.bind.annotation.RequestParam;
|
import org.springframework.web.bind.annotation.RequestParam;
|
||||||
|
|
||||||
|
import javax.validation.Valid;
|
||||||
import javax.validation.constraints.NotEmpty;
|
import javax.validation.constraints.NotEmpty;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@ -61,5 +63,13 @@ public interface SaasRoleGroupApi {
|
|||||||
@GetMapping("/api/saasRoleGroup/listByCategoryCode")
|
@GetMapping("/api/saasRoleGroup/listByCategoryCode")
|
||||||
ApiResult<List<SaasRoleGroupVO>> listByCategoryCode(@RequestParam("categoryCode") List<String> categoryCodes);
|
ApiResult<List<SaasRoleGroupVO>> listByCategoryCode(@RequestParam("categoryCode") List<String> categoryCodes);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新角色分组的位置
|
||||||
|
* 向下移动,则找到后面位置的分组,替换sort
|
||||||
|
* 向上移动,则找到前面位置的分组,替换sort
|
||||||
|
* @param request
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@PostMapping("/api/role/group/offset/update")
|
||||||
|
ApiResult<Void> updateRoleGroupOffset(@Valid @RequestBody UpdateRoleGroupOffsetReq request);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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<Integer> featureTypes;
|
||||||
|
}
|
||||||
@ -44,4 +44,6 @@ public class QuerySaasRoleGroupReq {
|
|||||||
* 被那些角色使用到的分组
|
* 被那些角色使用到的分组
|
||||||
*/
|
*/
|
||||||
private List<Long> roleIds;
|
private List<Long> roleIds;
|
||||||
|
|
||||||
|
private Long parentId;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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;
|
||||||
|
}
|
||||||
@ -4,6 +4,7 @@ import lombok.extern.slf4j.Slf4j;
|
|||||||
import org.mybatis.spring.annotation.MapperScan;
|
import org.mybatis.spring.annotation.MapperScan;
|
||||||
import org.springframework.boot.SpringApplication;
|
import org.springframework.boot.SpringApplication;
|
||||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
|
import org.springframework.cache.annotation.EnableCaching;
|
||||||
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
|
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
|
||||||
import org.springframework.context.ConfigurableApplicationContext;
|
import org.springframework.context.ConfigurableApplicationContext;
|
||||||
import org.springframework.core.env.Environment;
|
import org.springframework.core.env.Environment;
|
||||||
@ -11,6 +12,7 @@ import org.springframework.scheduling.annotation.EnableAsync;
|
|||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@EnableAsync
|
@EnableAsync
|
||||||
|
@EnableCaching
|
||||||
@EnableDiscoveryClient
|
@EnableDiscoveryClient
|
||||||
@MapperScan(value = {"cn.axzo.tyr.server.repository.mapper"})
|
@MapperScan(value = {"cn.axzo.tyr.server.repository.mapper"})
|
||||||
@SpringBootApplication(scanBasePackages = "cn.axzo")
|
@SpringBootApplication(scanBasePackages = "cn.axzo")
|
||||||
|
|||||||
@ -3,6 +3,7 @@ package cn.axzo.tyr.server.controller.permission;
|
|||||||
import cn.axzo.framework.domain.web.result.ApiResult;
|
import cn.axzo.framework.domain.web.result.ApiResult;
|
||||||
import cn.axzo.tyr.client.feign.FeatureResourceApi;
|
import cn.axzo.tyr.client.feign.FeatureResourceApi;
|
||||||
import cn.axzo.tyr.client.model.req.FeatureResourceTreeSaveReq;
|
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.req.ResourceSyncReq;
|
||||||
import cn.axzo.tyr.client.model.res.FeatureResourceDetailResp;
|
import cn.axzo.tyr.client.model.res.FeatureResourceDetailResp;
|
||||||
import cn.axzo.tyr.client.model.res.FeatureResourceTreeNode;
|
import cn.axzo.tyr.client.model.res.FeatureResourceTreeNode;
|
||||||
@ -76,10 +77,11 @@ public class FeatureResourceController implements FeatureResourceApi {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ApiResult<FeatureResourceDetailResp> detail(Long featureId) {
|
public ApiResult<FeatureResourceDetailResp> detail(Long featureId) {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ApiResult<List<FeatureResourceTreeNode>> getTree(GetFeatureResourceTreeReq req) {
|
||||||
|
return ApiResult.ok(featureResourceService.getTree(req));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,6 +4,7 @@ import cn.axzo.basics.common.exception.ServiceException;
|
|||||||
import cn.axzo.framework.domain.web.result.ApiResult;
|
import cn.axzo.framework.domain.web.result.ApiResult;
|
||||||
import cn.axzo.tyr.client.feign.SaasRoleGroupApi;
|
import cn.axzo.tyr.client.feign.SaasRoleGroupApi;
|
||||||
import cn.axzo.tyr.client.model.req.QuerySaasRoleGroupReq;
|
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.client.model.vo.SaasRoleGroupVO;
|
||||||
import cn.axzo.tyr.server.service.SaasRoleGroupService;
|
import cn.axzo.tyr.server.service.SaasRoleGroupService;
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
@ -12,7 +13,9 @@ import lombok.extern.slf4j.Slf4j;
|
|||||||
import org.apache.commons.collections.CollectionUtils;
|
import org.apache.commons.collections.CollectionUtils;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
import java.util.Comparator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@RestController
|
@RestController
|
||||||
@ -56,4 +59,64 @@ public class SaasRoleGroupController implements SaasRoleGroupApi {
|
|||||||
return ApiResult.ok(saasRoleGroupService.listByCategoryCode(categoryCode));
|
return ApiResult.ok(saasRoleGroupService.listByCategoryCode(categoryCode));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ApiResult<Void> updateRoleGroupOffset(UpdateRoleGroupOffsetReq request) {
|
||||||
|
if (request.getOffset() != 1 && request.getOffset() != -1) {
|
||||||
|
throw new ServiceException("暂时只支持移动一个位置");
|
||||||
|
}
|
||||||
|
SaasRoleGroupVO saasRoleGroup = getById(request.getId()).getData();
|
||||||
|
|
||||||
|
List<SaasRoleGroupVO> 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<SaasRoleGroupVO> roleGroupList) {
|
||||||
|
List<Long> 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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,10 +1,17 @@
|
|||||||
package cn.axzo.tyr.server.repository.dao;
|
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.entity.SaasFeatureResource;
|
||||||
import cn.axzo.tyr.server.repository.mapper.SaasFeatureResourceMapper;
|
import cn.axzo.tyr.server.repository.mapper.SaasFeatureResourceMapper;
|
||||||
|
import cn.azxo.framework.common.utils.StringUtils;
|
||||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||||
|
import org.apache.commons.collections.CollectionUtils;
|
||||||
import org.springframework.stereotype.Repository;
|
import org.springframework.stereotype.Repository;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>
|
* <p>
|
||||||
* 功能资源表 服务实现类
|
* 功能资源表 服务实现类
|
||||||
@ -23,4 +30,17 @@ public class SaasFeatureResourceDao extends ServiceImpl<SaasFeatureResourceMappe
|
|||||||
public void replacePath(String oldPath, String newPath) {
|
public void replacePath(String oldPath, String newPath) {
|
||||||
this.baseMapper.replacePath(oldPath, newPath);
|
this.baseMapper.replacePath(oldPath, newPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<SaasFeatureResource> 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();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -13,6 +13,7 @@ import org.springframework.beans.factory.annotation.Autowired;
|
|||||||
import org.springframework.stereotype.Repository;
|
import org.springframework.stereotype.Repository;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
@Repository
|
@Repository
|
||||||
public class SaasRoleGroupDao extends ServiceImpl<SaasRoleGroupMapper, SaasRoleGroup> {
|
public class SaasRoleGroupDao extends ServiceImpl<SaasRoleGroupMapper, SaasRoleGroup> {
|
||||||
@ -37,6 +38,7 @@ public class SaasRoleGroupDao extends ServiceImpl<SaasRoleGroupMapper, SaasRoleG
|
|||||||
.in(CollectionUtils.isNotEmpty(req.getWorkspaceTypeCode()), SaasRoleGroup::getWorkspaceTypeCode, req.getWorkspaceTypeCode())
|
.in(CollectionUtils.isNotEmpty(req.getWorkspaceTypeCode()), SaasRoleGroup::getWorkspaceTypeCode, req.getWorkspaceTypeCode())
|
||||||
.in(CollectionUtils.isNotEmpty(req.getWorkspaceIds()), SaasRoleGroup::getWorkspaceId, req.getWorkspaceIds())
|
.in(CollectionUtils.isNotEmpty(req.getWorkspaceIds()), SaasRoleGroup::getWorkspaceId, req.getWorkspaceIds())
|
||||||
.in(CollectionUtils.isNotEmpty(req.getOuIds()), SaasRoleGroup::getOuId, req.getOuIds())
|
.in(CollectionUtils.isNotEmpty(req.getOuIds()), SaasRoleGroup::getOuId, req.getOuIds())
|
||||||
|
.eq(Objects.nonNull(req.getParentId()), SaasRoleGroup::getParentId, req.getParentId())
|
||||||
.eq(BaseEntity::getIsDelete, TableIsDeleteEnum.NORMAL.value);
|
.eq(BaseEntity::getIsDelete, TableIsDeleteEnum.NORMAL.value);
|
||||||
if(CollectionUtils.isNotEmpty(req.getOuTypeCode())){
|
if(CollectionUtils.isNotEmpty(req.getOuTypeCode())){
|
||||||
eq.last(" AND (" + condition.substring(0, condition.length() - 2) + ")");
|
eq.last(" AND (" + condition.substring(0, condition.length() - 2) + ")");
|
||||||
|
|||||||
@ -1,5 +1,7 @@
|
|||||||
package cn.axzo.tyr.server.service;
|
package cn.axzo.tyr.server.service;
|
||||||
|
|
||||||
|
import cn.axzo.tyr.client.model.req.GetFeatureResourceTreeReq;
|
||||||
|
import cn.axzo.tyr.client.model.res.FeatureResourceTreeNode;
|
||||||
import cn.axzo.tyr.server.model.ResourcePermission;
|
import cn.axzo.tyr.server.model.ResourcePermission;
|
||||||
import cn.axzo.tyr.server.model.ResourcePermissionQueryDTO;
|
import cn.axzo.tyr.server.model.ResourcePermissionQueryDTO;
|
||||||
import cn.axzo.tyr.server.repository.entity.SaasFeatureResource;
|
import cn.axzo.tyr.server.repository.entity.SaasFeatureResource;
|
||||||
@ -36,5 +38,8 @@ public interface SaasFeatureResourceService {
|
|||||||
/** 是否免授权 **/
|
/** 是否免授权 **/
|
||||||
boolean isAuthFree(Long featureId);
|
boolean isAuthFree(Long featureId);
|
||||||
|
|
||||||
|
/** 查询资源树 **/
|
||||||
|
List<FeatureResourceTreeNode> getTree(GetFeatureResourceTreeReq req);
|
||||||
|
|
||||||
SaasFeatureResource getByCode(String featureCode);
|
SaasFeatureResource getByCode(String featureCode);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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<SaasFeatureResource> getByResourceTreeParam (GetFeatureResourceTreeReq req) {
|
||||||
|
log.info("get feature resource tree has not user cache!");
|
||||||
|
return featureResourceDao.getByResourceTreeParam(req);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,7 +1,8 @@
|
|||||||
package cn.axzo.tyr.server.service.impl;
|
package cn.axzo.tyr.server.service.impl;
|
||||||
|
|
||||||
import cn.axzo.basics.common.BeanMapper;
|
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.mybatisplus.BaseEntity;
|
||||||
import cn.axzo.pokonyan.config.redis.RedisClient;
|
import cn.axzo.pokonyan.config.redis.RedisClient;
|
||||||
import cn.axzo.tyr.client.common.enums.FeatureResourceAuthType;
|
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.common.enums.FeatureResourceType;
|
||||||
import cn.axzo.tyr.client.model.req.FeatureComponentSaveReq;
|
import cn.axzo.tyr.client.model.req.FeatureComponentSaveReq;
|
||||||
import cn.axzo.tyr.client.model.req.FeatureResourceTreeSaveReq;
|
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.ResourcePermission;
|
||||||
import cn.axzo.tyr.server.model.ResourcePermissionQueryDTO;
|
import cn.axzo.tyr.server.model.ResourcePermissionQueryDTO;
|
||||||
import cn.axzo.tyr.server.repository.dao.SaasFeatureResourceDao;
|
import cn.axzo.tyr.server.repository.dao.SaasFeatureResourceDao;
|
||||||
import cn.axzo.tyr.server.repository.entity.SaasFeatureResource;
|
import cn.axzo.tyr.server.repository.entity.SaasFeatureResource;
|
||||||
import cn.axzo.tyr.server.service.SaasFeatureResourceService;
|
import cn.axzo.tyr.server.service.SaasFeatureResourceService;
|
||||||
|
import cn.azxo.framework.common.utils.StringUtils;
|
||||||
import cn.hutool.core.collection.CollectionUtil;
|
import cn.hutool.core.collection.CollectionUtil;
|
||||||
import cn.hutool.core.lang.Assert;
|
import cn.hutool.core.lang.Assert;
|
||||||
import cn.hutool.core.util.BooleanUtil;
|
import cn.hutool.core.util.BooleanUtil;
|
||||||
import io.swagger.models.auth.In;
|
import com.google.common.collect.Lists;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
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.stereotype.Service;
|
||||||
import org.springframework.util.CollectionUtils;
|
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Set;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
import java.util.stream.Collectors;
|
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
|
* @version V1.0
|
||||||
* @author: ZhanSiHu
|
* @author: ZhanSiHu
|
||||||
* @date: 2024/4/3 10:18
|
* @date: 2024/4/3 10:18
|
||||||
@ -46,9 +53,19 @@ import static cn.axzo.tyr.server.common.constants.CacheConstant.KEY_AUTH_FREE;
|
|||||||
@Slf4j
|
@Slf4j
|
||||||
@Service
|
@Service
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
|
@RefreshScope
|
||||||
public class SaasFeatureResourceServiceImpl implements SaasFeatureResourceService {
|
public class SaasFeatureResourceServiceImpl implements SaasFeatureResourceService {
|
||||||
|
|
||||||
private final SaasFeatureResourceDao featureResourceDao;
|
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<String, String> treeRootNodeMap;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<SaasFeatureResource> listNavByIds(List<Long> featureIds) {
|
public List<SaasFeatureResource> listNavByIds(List<Long> featureIds) {
|
||||||
@ -108,6 +125,40 @@ public class SaasFeatureResourceServiceImpl implements SaasFeatureResourceServic
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
public List<FeatureResourceTreeNode> getTree(GetFeatureResourceTreeReq req) {
|
||||||
|
List<FeatureResourceTreeNode> 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<SaasFeatureResource> saasFeatureResources = saasFeatureResourceCacheService.getByResourceTreeParam(req);
|
||||||
|
watch.stop();
|
||||||
|
if (CollectionUtils.isEmpty(saasFeatureResources)) {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
List<FeatureResourceTreeNode> 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<FeatureResourceTreeNode> filterResultNode = filterTreeNode(req.getKeyword(), treeList);
|
||||||
|
watch.stop();
|
||||||
|
|
||||||
|
//把处理后的树结构添加上根节点
|
||||||
|
watch.start("fill-children-to-root");
|
||||||
|
List<FeatureResourceTreeNode> 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) {
|
public void saveOrUpdateMenu(FeatureResourceTreeSaveReq req) {
|
||||||
SaasFeatureResource baseResource = BeanMapper.copyBean(req, SaasFeatureResource.class);
|
SaasFeatureResource baseResource = BeanMapper.copyBean(req, SaasFeatureResource.class);
|
||||||
baseResource.setUpdateBy(req.getOperatorId());
|
baseResource.setUpdateBy(req.getOperatorId());
|
||||||
@ -258,4 +309,52 @@ public class SaasFeatureResourceServiceImpl implements SaasFeatureResourceServic
|
|||||||
featureResourceDao.updateBatchById(parallelFeature);
|
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<FeatureResourceTreeNode> filterTreeNode(String keyword, List<FeatureResourceTreeNode> 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<FeatureResourceTreeNode> 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<FeatureResourceTreeNode> fillChildren2Root(List<FeatureResourceTreeNode> rootNodes, List<FeatureResourceTreeNode> childrenNodes) {
|
||||||
|
Map<String, FeatureResourceTreeNode> 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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -16,7 +16,13 @@ import org.apache.commons.collections.CollectionUtils;
|
|||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.springframework.stereotype.Service;
|
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;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@ -125,6 +131,7 @@ public class SaasRoleGroupServiceImpl implements SaasRoleGroupService {
|
|||||||
//新增
|
//新增
|
||||||
saasRoleGroup = new SaasRoleGroup();
|
saasRoleGroup = new SaasRoleGroup();
|
||||||
saasRoleGroup.setCreateAt(now);
|
saasRoleGroup.setCreateAt(now);
|
||||||
|
checkAdd(req);
|
||||||
} else {
|
} else {
|
||||||
//修改
|
//修改
|
||||||
saasRoleGroup = saasRoleGroupDao.lambdaQuery().eq(SaasRoleGroup::getId, req.getId())
|
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.setWorkspaceId(req.getWorkspaceId() != null ? req.getWorkspaceId() : -1L);
|
||||||
saasRoleGroup.setOuId(req.getOuId() != null ? req.getOuId() : -1L);
|
saasRoleGroup.setOuId(req.getOuId() != null ? req.getOuId() : -1L);
|
||||||
saasRoleGroup.setParentId(req.getParentId());
|
saasRoleGroup.setParentId(req.getParentId());
|
||||||
|
saasRoleGroup.setCode(req.getCode());
|
||||||
|
// 新增的时候,没有指定sort,sort放在同层级的最后
|
||||||
|
assembleSort(saasRoleGroup);
|
||||||
return saasRoleGroup;
|
return saasRoleGroup;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -164,4 +174,38 @@ public class SaasRoleGroupServiceImpl implements SaasRoleGroupService {
|
|||||||
public List<SaasRoleGroupVO> listByCategoryCode(List<String> categoryCode) {
|
public List<SaasRoleGroupVO> listByCategoryCode(List<String> categoryCode) {
|
||||||
return BeanUtil.copyToList(saasRoleGroupDao.listByCategoryCode(categoryCode), SaasRoleGroupVO.class);
|
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<SaasRoleGroup> 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("角色分组编码已经存在");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,4 +1,6 @@
|
|||||||
spring:
|
spring:
|
||||||
|
cache:
|
||||||
|
type: redis
|
||||||
application:
|
application:
|
||||||
name: tyr
|
name: tyr
|
||||||
cloud:
|
cloud:
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user