feat: (feature/REQ-3167) 修改菜单同步支持同步前端资源

This commit is contained in:
李龙 2024-12-02 10:52:33 +08:00
parent a906d4fd50
commit 0c18ff1988
8 changed files with 141 additions and 18 deletions

View File

@ -164,6 +164,7 @@ public class FeatureResourceDTO implements Serializable {
/**
* 页面元素对象
*/
@Deprecated
private List<PageElementBasicDTO> pageElements;
/**

View File

@ -35,6 +35,8 @@ public class FeatureResourceTreeNode extends FeatureResourceDTO implements IBase
*/
private List<Role> roles;
private List<PageElementFeatureResourceRelationResp> pageElementFeatureResourceRelationResps;
@Data
@Builder
@NoArgsConstructor

View File

@ -20,7 +20,7 @@ import java.util.List;
* @author: ZhanSiHu
* @date: 2024/4/3 10:25
*/
@FeignClient(name = "tyr", url = "${axzo.service.base.tyr:https://test-api.axzo.cn/tyr}")
@FeignClient(name = "tyr", url = "${axzo.service.base.tyr:https://pre-api.axzo.cn/tyr}")
public interface BaseFeatureResourceApi {

View File

@ -9,7 +9,7 @@ import org.springframework.web.bind.annotation.RequestBody;
import java.util.List;
@FeignClient(name = "tyr", url = "${axzo.service.base.tyr:https://test-api.axzo.cn/tyr}")
@FeignClient(name = "tyr", url = "${axzo.service.base.tyr:https://pre-api.axzo.cn/tyr}")
public interface BasePageElementApi {
@PostMapping("/api/pageElement/list")

View File

@ -9,7 +9,7 @@ import org.springframework.web.bind.annotation.RequestBody;
import java.util.List;
@FeignClient(name = "tyr", url = "${axzo.service.base.tyr:https://test-api.axzo.cn/tyr}")
@FeignClient(name = "tyr", url = "${axzo.service.base.tyr:https://pre-api.axzo.cn/tyr}")
public interface BasePageElementCategoryApi {
/** 查询页面元素类型(按端分组) **/

View File

@ -6,6 +6,7 @@ import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
import java.util.Set;
/**
* @author likunpeng
@ -27,4 +28,9 @@ public class RelationOperateLogResourceBindRoleDO {
* 角色code列表
*/
private List<String> roleCodes;
/**
* 前端资源code列表
*/
private Set<String> pageElementCodes;
}

View File

@ -2,6 +2,7 @@ package cn.axzo.tyr.server.service.impl;
import cn.axzo.basics.common.BeanMapper;
import cn.axzo.basics.common.constant.enums.DeleteEnum;
import cn.axzo.basics.common.constant.enums.TableIsDeleteEnum;
import cn.axzo.basics.common.util.TreeUtil;
import cn.axzo.basics.profiles.api.UserProfileServiceApi;
import cn.axzo.basics.profiles.dto.basic.PersonProfileDto;
@ -11,10 +12,12 @@ import cn.axzo.tyr.client.common.enums.FeatureResourceType;
import cn.axzo.tyr.client.common.enums.PermissionRelationOperateLogSceneEnum;
import cn.axzo.tyr.client.model.enums.RolePermissionTagEnum;
import cn.axzo.tyr.client.model.req.GetFeatureResourceTreeReq;
import cn.axzo.tyr.client.model.req.PageSaasFeatureResourceReq;
import cn.axzo.tyr.client.model.req.PageElementFeatureResourceRelationReq;
import cn.axzo.tyr.client.model.req.PageElementReq;
import cn.axzo.tyr.client.model.req.ResourceSyncReq;
import cn.axzo.tyr.client.model.res.FeatureResourceTreeNode;
import cn.axzo.tyr.client.model.res.SaasFeatureResourceResp;
import cn.axzo.tyr.client.model.res.PageElementFeatureResourceRelationResp;
import cn.axzo.tyr.client.model.res.PageElementResp;
import cn.axzo.tyr.server.config.MqProducer;
import cn.axzo.tyr.server.event.payload.RolePermissionCreatedPayload;
import cn.axzo.tyr.server.event.payload.SaasFeatureResourceUpsertPayload;
@ -32,7 +35,8 @@ import cn.axzo.tyr.server.repository.entity.SaasPgroupPermissionRelationOperateL
import cn.axzo.tyr.server.repository.entity.SaasPgroupRoleRelation;
import cn.axzo.tyr.server.repository.entity.SaasRole;
import cn.axzo.tyr.server.service.FeatureResourceSyncService;
import cn.axzo.tyr.server.service.SaasFeatureResourceService;
import cn.axzo.tyr.server.service.SaasPageElementFeatureResourceRelationService;
import cn.axzo.tyr.server.service.SaasPageElementService;
import cn.axzo.tyr.server.service.SaasPgroupPermissionRelationOperateLogService;
import cn.axzo.tyr.server.util.RpcInternalUtil;
import cn.azxo.framework.common.constatns.Constants;
@ -49,6 +53,7 @@ import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.MDC;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
@ -98,7 +103,8 @@ public class FeatureResourceSyncServiceImpl implements FeatureResourceSyncServic
private final SaasPgroupPermissionRelationOperateLogService saasPgroupPermissionRelationOperateLogService;
private final UserProfileServiceApi userProfileServiceApi;
private final SaasFeatureResourceService saasFeatureResourceService;
private final SaasPageElementFeatureResourceRelationService saasPageElementFeatureResourceRelationService;
private final SaasPageElementService saasPageElementService;
@Qualifier("asyncExecutor")
@Autowired
@ -139,6 +145,8 @@ public class FeatureResourceSyncServiceImpl implements FeatureResourceSyncServic
}
Map<Long, List<FeatureResourceTreeNode.Role>> featureResourceRoleCodeMap = getFeatureResourceRoleCodeMap(allFeatureResourceIds);
Map<String, List<PageElementFeatureResourceRelationResp>> pageElementMap = listPageElement(resourceList);
List<FeatureResourceTreeNode> dtoList = BeanMapper.copyList(resourceList, FeatureResourceTreeNode.class);
dtoList.forEach(e -> {
List<FeatureResourceTreeNode.Role> roles = featureResourceRoleCodeMap.get(e.getId());
@ -150,20 +158,60 @@ public class FeatureResourceSyncServiceImpl implements FeatureResourceSyncServic
.distinct()
.collect(Collectors.toList()));
e.setRoles(roles);
e.setPageElementFeatureResourceRelationResps(pageElementMap.get(e.getUniCode()));
});
return TreeUtil.buildTree(dtoList);
}
private Map<String, List<PageElementFeatureResourceRelationResp>> listPageElement(List<SaasFeatureResource> resourceList) {
if (CollectionUtils.isEmpty(resourceList)) {
return Collections.emptyMap();
}
Set<String> uniCodes = resourceList.stream()
.map(SaasFeatureResource::getUniCode)
.collect(Collectors.toSet());
PageElementFeatureResourceRelationReq pageElementFeatureResourceRelationReq = PageElementFeatureResourceRelationReq.builder()
.featureResourceUniCodes(uniCodes)
.needPageElement(true)
.build();
List<PageElementFeatureResourceRelationResp> pageElementFeatureResourceRelations = saasPageElementFeatureResourceRelationService.list(pageElementFeatureResourceRelationReq);
return pageElementFeatureResourceRelations.stream()
.filter(e -> e.getPageElement() != null)
.collect(Collectors.groupingBy(PageElementFeatureResourceRelationResp::getFeatureResourceUniCode));
}
@Override
@Transactional(rollbackFor = Exception.class)
public void syncFromBase(ResourceSyncReq req) {
// TODO 删除代码同步处理但是改的比较多
req.setTraceId(MDC.get(Constants.CTX_LOG_ID_MDC));
if (req.getIds().size() > 1) {
//超过一个异步处理
CompletableFuture.runAsync(() -> doSyncFromBase(req), asyncExecutor).whenComplete((t, ex) -> saasFeatureResourceCacheService.clearCache());
// 同步这里不要求效率没有角色id全部刷新也不容易找这个
Event event = Event.builder()
.targetType(ROLE_PERMISSION_TARGET_TYPE)
.eventCode(ROLE_PERMISSION_CREATED.getEventCode())
.data(RolePermissionCreatedPayload.builder()
.build())
.build();
mqProducer.send(event);
return;
}
doSyncFromBase(req);
// 同步这里不要求效率没有角色id全部刷新也不容易找这个
Event event = Event.builder()
.targetType(ROLE_PERMISSION_TARGET_TYPE)
.eventCode(ROLE_PERMISSION_CREATED.getEventCode())
.data(RolePermissionCreatedPayload.builder()
.build())
.build();
mqProducer.send(event);
saasFeatureResourceCacheService.clearCache();
}
@ -173,13 +221,14 @@ public class FeatureResourceSyncServiceImpl implements FeatureResourceSyncServic
//处理数据缓存避免同级节点上级重复处理 - 上级code查询
final Map<Long, String> codeCache = new ConcurrentHashMap<>();
Set<Long> syncedRoleFeatureResourceIds = Sets.newConcurrentHashSet();
Set<Long> syncedPageElementFeatureResourceIds = Sets.newConcurrentHashSet();
Set<String> terminals = Sets.newHashSet();
try {
for (Long id : req.getIds()) {
//获取基准环境配置数据:同步某个ID的数据 需要同步处理它所有上级及下级组件
List<FeatureResourceTreeNode> syncList = RpcInternalUtil.rpcProcessor(() -> baseFeatureResourceApi.getSyncTreeById(id),
"get base sync tree by id", id).getData();
syncResourceProcess(syncList, codeCache, req.getOperatorId(), operateDos, syncedRoleFeatureResourceIds);
syncResourceProcess(syncList, codeCache, req.getOperatorId(), operateDos, syncedRoleFeatureResourceIds, syncedPageElementFeatureResourceIds);
terminals.addAll(syncList.stream()
.map(FeatureResourceTreeNode::getTerminal)
.collect(Collectors.toSet()));
@ -236,7 +285,8 @@ public class FeatureResourceSyncServiceImpl implements FeatureResourceSyncServic
}
private void syncResourceProcess(List<FeatureResourceTreeNode> syncList, Map<Long, String> codeCache, Long operatorId,
List<RelationOperateLogResourceBindRoleDO> operateDos, Set<Long> syncedRoleFeatureResourceIds) {
List<RelationOperateLogResourceBindRoleDO> operateDos, Set<Long> syncedRoleFeatureResourceIds,
Set<Long> syncedPageElementFeatureResourceIds) {
for (FeatureResourceTreeNode treeNode : syncList) {
if (codeCache.containsKey(treeNode.getId())) {
@ -244,7 +294,7 @@ public class FeatureResourceSyncServiceImpl implements FeatureResourceSyncServic
log.info("already sync resource:{}", treeNode.getId());
//递归子节点
if (CollectionUtils.isNotEmpty(treeNode.getChildren())) {
syncResourceProcess(treeNode.getChildren(), codeCache, operatorId, operateDos, syncedRoleFeatureResourceIds);
syncResourceProcess(treeNode.getChildren(), codeCache, operatorId, operateDos, syncedRoleFeatureResourceIds, syncedRoleFeatureResourceIds);
}
continue;
}
@ -305,9 +355,13 @@ public class FeatureResourceSyncServiceImpl implements FeatureResourceSyncServic
operateDos.add(logResourceBindRoleDO);
}
RelationOperateLogResourceBindRoleDO relationOperateLogResourceBindRoleDO = syncPageElement(baseResource, treeNode, operatorId, syncedPageElementFeatureResourceIds);
if (Objects.nonNull(relationOperateLogResourceBindRoleDO)) {
operateDos.add(relationOperateLogResourceBindRoleDO);
}
//递归子节点
if (CollectionUtils.isNotEmpty(treeNode.getChildren())) {
syncResourceProcess(treeNode.getChildren(), codeCache, operatorId, operateDos, syncedRoleFeatureResourceIds);
syncResourceProcess(treeNode.getChildren(), codeCache, operatorId, operateDos, syncedRoleFeatureResourceIds, syncedPageElementFeatureResourceIds);
}
}
}
@ -408,15 +462,73 @@ public class FeatureResourceSyncServiceImpl implements FeatureResourceSyncServic
logResourceBindRoleDO.setRoleCodes(saasRoles.stream().filter(e -> existRoleIds.contains(e.getId())).map(SaasRole::getRoleCode).collect(Collectors.toList()));
}
return logResourceBindRoleDO;
}
// 同步这里不要求效率没有角色id全部刷新也不容易找这个
Event event = Event.builder()
.targetType(ROLE_PERMISSION_TARGET_TYPE)
.eventCode(ROLE_PERMISSION_CREATED.getEventCode())
.data(RolePermissionCreatedPayload.builder()
.build())
private RelationOperateLogResourceBindRoleDO syncPageElement(SaasFeatureResource featureResource,
FeatureResourceTreeNode treeNode,
Long operatorId,
Set<Long> syncedPageElementFeatureResourceIds) {
if (Objects.isNull(featureResource)) {
return null;
}
// 同一FeatureResource如果已经处理过前端资源同步不再进行再次处理
if (syncedPageElementFeatureResourceIds.contains(featureResource.getId())) {
log.warn("sync role bind has handled,feature resource id:{}", featureResource.getId());
return null;
}
syncedPageElementFeatureResourceIds.add(featureResource.getId());
// 先清除资源绑定的角色 @20240723 产品武艳华要求资源绑定的前端资源以PRE角色为准
List<PageElementFeatureResourceRelationResp> oldData = saasPageElementFeatureResourceRelationService.list(PageElementFeatureResourceRelationReq.builder()
.featureResourceUniCodes(Sets.newHashSet(featureResource.getUniCode()))
.build());
if (CollectionUtils.isNotEmpty(oldData)) {
log.warn("sync menu delete PageElementFeatureResourceRelation operateId:{} featureResourceId:{}, PageElementFeatureResourceRelationIds:{}", operatorId, featureResource.getId(), oldData.stream().map(PageElementFeatureResourceRelationResp::getId).collect(Collectors.toList()));
saasPageElementFeatureResourceRelationDao.lambdaUpdate()
.in(SaasPageElementFeatureResourceRelation::getId, Lists.transform(oldData, PageElementFeatureResourceRelationResp::getId))
.set(SaasPageElementFeatureResourceRelation::getUpdateBy, operatorId)
.set(SaasPageElementFeatureResourceRelation::getIsDelete, TableIsDeleteEnum.DELETE.value)
.update();
}
// 操作日志
RelationOperateLogResourceBindRoleDO logResourceBindRoleDO = RelationOperateLogResourceBindRoleDO.builder()
.uniCode(featureResource.getUniCode())
.build();
mqProducer.send(event);
Set<String> pageElementCodes = CollectionUtils.emptyIfNull(treeNode.getPageElementFeatureResourceRelationResps()).stream()
.map(PageElementFeatureResourceRelationResp::getPageElementCode)
.filter(StringUtils::isNotBlank)
.collect(Collectors.toSet());
if (CollectionUtils.isEmpty(pageElementCodes)) {
return logResourceBindRoleDO;
}
Set<String> localPageElementCodes = saasPageElementService.list(PageElementReq.builder()
.codes(pageElementCodes)
.build())
.stream()
.map(PageElementResp::getCode)
.collect(Collectors.toSet());
if (CollectionUtils.isEmpty(localPageElementCodes)) {
return logResourceBindRoleDO;
}
// 只关联本地已经有的前端资源code
List<SaasPageElementFeatureResourceRelation> inserts = treeNode.getPageElementFeatureResourceRelationResps().stream()
.filter(e -> localPageElementCodes.contains(e.getPageElementCode()))
.map(e -> {
SaasPageElementFeatureResourceRelation result = SaasPageElementFeatureResourceRelation.builder().build();
BeanUtils.copyProperties(e, result);
result.setId(null);
return result;
})
.collect(Collectors.toList());
saasPageElementFeatureResourceRelationDao.saveBatch(inserts);
return logResourceBindRoleDO;
}
@ -475,6 +587,7 @@ public class FeatureResourceSyncServiceImpl implements FeatureResourceSyncServic
return null;
}
return saasRoles.stream()
.filter(Objects::nonNull)
.map(role -> PermissionGroupRoleWrapper.builder()
.featureId(e.getFeatureId())
.roleCode(role.getRoleCode())

View File

@ -925,6 +925,7 @@ public class SaasFeatureResourceServiceImpl extends ServiceImpl<SaasFeatureResou
PageElementFeatureResourceRelationReq pageElementFeatureResourceRelationReq = PageElementFeatureResourceRelationReq.builder()
.featureResourceUniCodes(uniCodes)
.types(param.getPageElementTypes())
.needPageElement(true)
.build();
List<PageElementFeatureResourceRelationResp> pageElementFeatureResourceRelations = saasPageElementFeatureResourceRelationService.list(pageElementFeatureResourceRelationReq);