fix:数据总览,兼容同类型多级构建

This commit is contained in:
2026-03-04 10:05:16 +08:00
parent 55058a9333
commit 0e1f2d2b86
7 changed files with 177 additions and 90 deletions

View File

@@ -2293,94 +2293,180 @@ public class NodeServiceImpl extends ServiceImpl<SimulationNodeMapper, Simulatio
@Override
public SdmResponse<List<AllNodeByProjectIdAndTypeResp>> getAllNodeByProjectIdAndType(List<String> uuids, String nextNodeType) {
Map<String, String> TagMap = tagMapService.getTagMapName();
if ( ObjectUtils.isEmpty(TagMap)) {
if (CollectionUtils.isEmpty(uuids) || StringUtils.isBlank(nextNodeType)) {
return SdmResponse.success();
}
Map<String, String> tagMap = tagMapService.getTagMapName();
if (ObjectUtils.isEmpty(tagMap)) {
log.error("字典信息查询失败");
return SdmResponse.success();
}
Optional<SimulationNode> simulationNodeOptional = this.lambdaQuery().in(SimulationNode::getUuid, uuids).list().stream().findFirst();
if (!simulationNodeOptional.isPresent()) {
List<SimulationNode> currentNodes = this.lambdaQuery()
.in(SimulationNode::getUuid, uuids)
.list();
if (CollectionUtils.isEmpty(currentNodes)) {
return SdmResponse.failed("未找到节点");
}
SimulationNode currentNode = simulationNodeOptional.get();
SimulationNode currentNode = currentNodes.get(0);
String currentNodeType = currentNode.getNodeType();
String currentNodeTag = TagMap.get(currentNodeType);
String nextNodeTag = TagMap.get(nextNodeType);
// 当前节点向前搜索
List<String> preUUids = this.lambdaQuery()
.in(TagConstant.TAG1.equals(currentNodeTag), SimulationNode::getTag1, uuids)
.in(TagConstant.TAG2.equals(currentNodeTag), SimulationNode::getTag2, uuids)
.in(TagConstant.TAG3.equals(currentNodeTag), SimulationNode::getTag3, uuids)
.in(TagConstant.TAG4.equals(currentNodeTag), SimulationNode::getTag4, uuids)
.in(TagConstant.TAG5.equals(currentNodeTag), SimulationNode::getTag5, uuids)
.in(TagConstant.TAG6.equals(currentNodeTag), SimulationNode::getTag6, uuids)
.in(TagConstant.TAG7.equals(currentNodeTag), SimulationNode::getTag7, uuids)
.in(TagConstant.TAG8.equals(currentNodeTag), SimulationNode::getTag8, uuids)
.in(TagConstant.TAG9.equals(currentNodeTag), SimulationNode::getTag9, uuids)
.in(TagConstant.TAG10.equals(currentNodeTag), SimulationNode::getTag10, uuids)
.orderByDesc(SimulationNode::getCreateTime)
.list().stream().map(simulationNode -> {
if (TagConstant.TAG1.equals(nextNodeTag)) {
return simulationNode.getTag1();
} else if (TagConstant.TAG2.equals(nextNodeTag)) {
return simulationNode.getTag2();
} else if (TagConstant.TAG3.equals(nextNodeTag)) {
return simulationNode.getTag3();
} else if (TagConstant.TAG4.equals(nextNodeTag)) {
return simulationNode.getTag4();
} else if (TagConstant.TAG5.equals(nextNodeTag)) {
return simulationNode.getTag5();
} else if (TagConstant.TAG6.equals(nextNodeTag)) {
return simulationNode.getTag6();
} else if (TagConstant.TAG7.equals(nextNodeTag)) {
return simulationNode.getTag7();
} else if (TagConstant.TAG8.equals(nextNodeTag)) {
return simulationNode.getTag8();
} else if (TagConstant.TAG9.equals(nextNodeTag)) {
return simulationNode.getTag9();
} else if (TagConstant.TAG10.equals(nextNodeTag)) {
return simulationNode.getTag10();
} else {
return null;
}
}
).toList();
List<SimulationNode> preSimulationNodeList = this.lambdaQuery().in(SimulationNode::getUuid, preUUids).list();
// 当前节点向后搜索
List<SimulationNode> simulationNodeList = this.lambdaQuery()
.in(TagConstant.TAG1.equals(currentNodeTag), SimulationNode::getTag1, uuids)
.in(TagConstant.TAG2.equals(currentNodeTag), SimulationNode::getTag2, uuids)
.in(TagConstant.TAG3.equals(currentNodeTag), SimulationNode::getTag3, uuids)
.in(TagConstant.TAG4.equals(currentNodeTag), SimulationNode::getTag4, uuids)
.in(TagConstant.TAG5.equals(currentNodeTag), SimulationNode::getTag5, uuids)
.in(TagConstant.TAG6.equals(currentNodeTag), SimulationNode::getTag6, uuids)
.in(TagConstant.TAG7.equals(currentNodeTag), SimulationNode::getTag7, uuids)
.in(TagConstant.TAG8.equals(currentNodeTag), SimulationNode::getTag8, uuids)
.in(TagConstant.TAG9.equals(currentNodeTag), SimulationNode::getTag9, uuids)
.in(TagConstant.TAG10.equals(currentNodeTag), SimulationNode::getTag10, uuids)
.eq(SimulationNode::getNodeType, nextNodeType)
// 先查当前节点下是否存在同类型直接子节点(连续同类型场景)
List<SimulationNode> sameTypeChildren = this.lambdaQuery()
.in(SimulationNode::getParentId, uuids)
.eq(SimulationNode::getNodeType, currentNodeType)
.orderByDesc(SimulationNode::getCreateTime)
.list();
log.info("getAllNodeByProjectIdAndType sameTypeChildren size:{}, currentNodeType:{}, inputUuidsSize:{}",
sameTypeChildren.size(), currentNodeType, uuids.size());
Set<String> matchedParentUuids = sameTypeChildren.stream()
.map(SimulationNode::getParentId)
.filter(StringUtils::isNotBlank)
.collect(Collectors.toSet());
List<String> remainingUuids = uuids.stream()
.filter(uuid -> !matchedParentUuids.contains(uuid))
.toList();
log.info("getAllNodeByProjectIdAndType remainingUuids size:{}, matchedParentUuids size:{}",
remainingUuids.size(), matchedParentUuids.size());
List<SimulationNode> simulationNodeList = new ArrayList<>(sameTypeChildren);
// 当 nextNodeType 与 currentNodeType 相同(最后一层继续同类型下钻)时,
// 仅允许返回直接子节点,禁止对 remainingUuids 走 tag 链路查询,避免引入平级数据。
if (StringUtils.equals(currentNodeType, nextNodeType)) {
if (CollectionUtils.isEmpty(simulationNodeList)) {
return SdmResponse.success();
}
return SdmResponse.success(buildNodeRespList(simulationNodeList));
}
if (CollectionUtils.isNotEmpty(remainingUuids)) {
String currentNodeTag = tagMap.get(currentNodeType);
String nextNodeTag = tagMap.get(nextNodeType);
if (StringUtils.isBlank(currentNodeTag) || StringUtils.isBlank(nextNodeTag)) {
log.error("节点类型未配置tag映射,currentNodeType:{},nextNodeType:{}", currentNodeType, nextNodeType);
if (CollectionUtils.isEmpty(simulationNodeList)) {
return SdmResponse.success();
}
} else {
// 规则1剩余节点不能直接拿uuid去匹配tag必须先取出当前层对应的tag值兼容tag链路逗号拼接
List<String> currentTagValues = extractTagValuesByNodeTag(currentNodes, remainingUuids, currentNodeTag);
if (CollectionUtils.isEmpty(currentTagValues)) {
log.info("getAllNodeByProjectIdAndType currentTagValues empty, currentNodeTag:{}, remainingUuidsSize:{}",
currentNodeTag, remainingUuids.size());
} else {
// 规则2按当前层tag值定位同链路节点再映射到下一层tag值并反查uuid
List<SimulationNode> matchedChainNodes = queryNodesByCurrentTagValues(currentNodeTag, currentTagValues);
List<String> preUUids = matchedChainNodes.stream()
.map(simulationNode -> resolveTagValue(simulationNode, nextNodeTag))
.filter(StringUtils::isNotBlank)
.map(tag-> {
return tag.split(",")[0];
})
.toList();
List<SimulationNode> preSimulationNodeList = CollectionUtils.isEmpty(preUUids)
? Collections.emptyList()
: this.lambdaQuery().in(SimulationNode::getUuid, preUUids).list();
simulationNodeList.addAll(preSimulationNodeList);
// 规则3同时保留原有“按nextNodeType正向查下一层”能力
/* List<SimulationNode> nextTypeNodeList = matchedChainNodes.stream()
.filter(node -> StringUtils.equals(node.getNodeType(), nextNodeType))
.toList();
simulationNodeList.addAll(nextTypeNodeList);
*/
log.info("getAllNodeByProjectIdAndType matchedChainNodes size:{}, nextNodeType:{}",
matchedChainNodes.size(), nextNodeType);
}
}
}
simulationNodeList.addAll(preSimulationNodeList);
if (CollectionUtils.isEmpty(simulationNodeList)) {
return SdmResponse.success();
}
List<AllNodeByProjectIdAndTypeResp> allNodeByProjectIdAndTypeRespList = new ArrayList<>();
simulationNodeList.forEach(simulationNode -> {
AllNodeByProjectIdAndTypeResp allNodeByProjectIdAndTypeResp = new AllNodeByProjectIdAndTypeResp();
BeanUtils.copyProperties(simulationNode, allNodeByProjectIdAndTypeResp);
allNodeByProjectIdAndTypeResp.setId(simulationNode.getId().longValue());
allNodeByProjectIdAndTypeRespList.add(allNodeByProjectIdAndTypeResp);
});
return SdmResponse.success(allNodeByProjectIdAndTypeRespList);
return SdmResponse.success(buildNodeRespList(simulationNodeList));
}
/**
* 根据当前节点类型对应的tag位从当前节点集合中提取tag值。
* 说明:
* 1) 这里只从 remainingUuids 对应节点提取,避免混入已命中同类型子节点的父节点;
* 2) 提取的是 tag 字段值,不是 uuid兼容 tag4 这类“逗号拼接链路”场景;
* 3) 统一去空和去重,减少后续 in 查询的数据量。
*/
private List<String> extractTagValuesByNodeTag(List<SimulationNode> currentNodes, List<String> remainingUuids, String currentNodeTag) {
return currentNodes.stream()
.filter(node -> remainingUuids.contains(node.getUuid()))
.map(node -> resolveTagValue(node, currentNodeTag))
.filter(StringUtils::isNotBlank)
.distinct()
.toList();
}
/**
* 按“当前层tag值”查询同链路节点。
* 规则tag字段存的是层级链路值因此这里必须用 tag 值匹配,不使用 uuid 直接匹配 tag 字段。
*/
private List<SimulationNode> queryNodesByCurrentTagValues(String currentNodeTag, List<String> currentTagValues) {
return this.lambdaQuery()
.in(TagConstant.TAG1.equals(currentNodeTag), SimulationNode::getTag1, currentTagValues)
.in(TagConstant.TAG2.equals(currentNodeTag), SimulationNode::getTag2, currentTagValues)
.in(TagConstant.TAG3.equals(currentNodeTag), SimulationNode::getTag3, currentTagValues)
.in(TagConstant.TAG4.equals(currentNodeTag), SimulationNode::getTag4, currentTagValues)
.in(TagConstant.TAG5.equals(currentNodeTag), SimulationNode::getTag5, currentTagValues)
.in(TagConstant.TAG6.equals(currentNodeTag), SimulationNode::getTag6, currentTagValues)
.in(TagConstant.TAG7.equals(currentNodeTag), SimulationNode::getTag7, currentTagValues)
.in(TagConstant.TAG8.equals(currentNodeTag), SimulationNode::getTag8, currentTagValues)
.in(TagConstant.TAG9.equals(currentNodeTag), SimulationNode::getTag9, currentTagValues)
.in(TagConstant.TAG10.equals(currentNodeTag), SimulationNode::getTag10, currentTagValues)
.list();
}
/**
* 按 tag 位读取节点的 tag 值。
*/
private String resolveTagValue(SimulationNode node, String tag) {
if (TagConstant.TAG1.equals(tag)) {
return node.getTag1();
} else if (TagConstant.TAG2.equals(tag)) {
return node.getTag2();
} else if (TagConstant.TAG3.equals(tag)) {
return node.getTag3();
} else if (TagConstant.TAG4.equals(tag)) {
return node.getTag4();
} else if (TagConstant.TAG5.equals(tag)) {
return node.getTag5();
} else if (TagConstant.TAG6.equals(tag)) {
return node.getTag6();
} else if (TagConstant.TAG7.equals(tag)) {
return node.getTag7();
} else if (TagConstant.TAG8.equals(tag)) {
return node.getTag8();
} else if (TagConstant.TAG9.equals(tag)) {
return node.getTag9();
} else if (TagConstant.TAG10.equals(tag)) {
return node.getTag10();
}
return null;
}
/**
* 将节点列表转为响应对象并按 uuid 去重,避免多路径合并导致重复。
*/
private List<AllNodeByProjectIdAndTypeResp> buildNodeRespList(List<SimulationNode> simulationNodeList) {
return simulationNodeList.stream()
.collect(Collectors.toMap(SimulationNode::getUuid, Function.identity(), (a, b) -> a, LinkedHashMap::new))
.values().stream().map(simulationNode -> {
AllNodeByProjectIdAndTypeResp resp = new AllNodeByProjectIdAndTypeResp();
BeanUtils.copyProperties(simulationNode, resp);
resp.setId(simulationNode.getId().longValue());
return resp;
}).toList();
}
@Override