This commit is contained in:
2026-03-04 12:45:47 +08:00
11 changed files with 205 additions and 107 deletions

View File

@@ -24,12 +24,4 @@ public enum NodeTypeEnum {
return value;
}
/**
* 是否节点类型
*/
public static boolean isNodeType(String value) {
return PROJECT.getValue().equals(value) || PHASE.getValue().equals(value)
|| DISCIPLINE.getValue().equals(value) || MACHINE.getValue().equals(value)
|| WORKSPACE.getValue().equals(value);
}
}

View File

@@ -135,6 +135,9 @@ public class UploadFilesReq {
@Schema(description = "知识库文件审批模板名称")
private String templateName;
@Schema(description = "是否需要覆盖同名文件")
private Boolean isConverSameNameFile;
/**
* 扩展信息
*/

View File

@@ -31,4 +31,12 @@ public class TagMapService {
// project-->tag1 phase-->tag2
return tagMapList.getData().stream().collect(Collectors.toMap(DataDictionary::getDictValue, DataDictionary::getDictName));
}
/**
* 是否节点类型
*/
public boolean isNodeType(String tag) {
Map<String, String> tagMap = getTagMapName();
return tagMap.containsKey(tag);
}
}

View File

@@ -8,9 +8,7 @@ import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.*;
@Data
public class QueryBigFileReq extends BaseReq {
@@ -22,7 +20,7 @@ public class QueryBigFileReq extends BaseReq {
/**
* 目录ID列表
*/
private List<Long> dirIds = new ArrayList<>();
private Set<Long> dirIds = new HashSet<>();
/**
* 目录ID列表的大小用于 HAVING 子句

View File

@@ -68,7 +68,7 @@ public class DataAnalysisServiceImpl implements IDataAnalysisService {
BeanUtils.copyProperties(getSimulationTaskFileReq, queryBigFileReq);
// 步骤 1: 收集所有直接传入的 dirId
List<Long> allDirIds = new ArrayList<>();
Set<Long> allDirIds = new HashSet<>();
if (CollectionUtils.isNotEmpty(getSimulationTaskFileReq.getProjectDirIds())) {
allDirIds.addAll(getSimulationTaskFileReq.getProjectDirIds());
}

View File

@@ -554,7 +554,7 @@ public class DataStorageAnalysisImpl implements DataStorageAnalysis {
}
Long tenantId = ThreadLocalContext.getTenantId();
List<Long> dirIds = CollectionUtils.isEmpty(queryBigFileReq.getDirIds()) ? null : queryBigFileReq.getDirIds();
Set<Long> dirIds = CollectionUtils.isEmpty(queryBigFileReq.getDirIds()) ? null : queryBigFileReq.getDirIds();
// 查询符合标签的文件id
return fileTagRelService.lambdaQuery()

View File

@@ -26,6 +26,7 @@ import com.sdm.common.entity.resp.system.CIDUserResp;
import com.sdm.common.feign.impl.project.SimulationNodeFeignClientImpl;
import com.sdm.common.feign.impl.system.SysUserFeignClientImpl;
import com.sdm.common.feign.inter.project.ISimulationTaskFeignClient;
import com.sdm.common.service.TagMapService;
import com.sdm.common.utils.CidSysUserUtil;
import com.sdm.common.utils.PageUtils;
import com.sdm.data.convert.FileMetadataConvert;
@@ -87,6 +88,10 @@ public class DimensionTemplateServiceImpl extends ServiceImpl<DimensionTemplateM
@Autowired
private ISimulationTaskFeignClient simulationTaskFeignClient;
@Autowired
private TagMapService tagMapService;
@Override
@Transactional(rollbackFor = Exception.class)
public SdmResponse saveDimensionTemplateWithHierarchies(TemplateCreationRequest request) {
@@ -237,22 +242,20 @@ public class DimensionTemplateServiceImpl extends ServiceImpl<DimensionTemplateM
List<String> chooseUuids = nodeDirInfos.stream().map(FileMetadataInfo::getRelatedResourceUuid).toList();
// chooseUuid和chooseNodeType不为空,并且是node节点类型才是节点文件夹才需要查询子节点文件夹文件
if (ObjectUtils.isNotEmpty(chooseUuids) && ObjectUtils.isNotEmpty(chooseNodeType) && NodeTypeEnum.isNodeType(chooseNodeType)) {
if (ObjectUtils.isNotEmpty(chooseUuids) && ObjectUtils.isNotEmpty(chooseNodeType) && tagMapService.isNodeType(chooseNodeType)) {
// 从dimensionNodeTyepOrderList中获取chooseNodeType下一个位置的数据有可能chooseNodeType所在位置就是最后一层节点,SdmResponse返回空数据
int index = dimensionNodeTyepOrderList.indexOf(chooseNodeType);
if (index == -1) {
return SdmResponse.failed("选中节点类型不在数据展示维度中");
}
// 判断是否是最后一层节点,如果是最后一层节点,则不需要查询子节点文件
if (index != dimensionNodeTyepOrderList.size() - 1) {
// 获取dimensionNodeTyepOrderList的index+1位置的节点类型
String nextNodeType = dimensionNodeTyepOrderList.get(index + 1);
SdmResponse<List<AllNodeByProjectIdAndTypeResp>> allNodeByProjectIdAndType = simuluationNodeFeignClient.getAllNodeByProjectIdAndType(chooseUuids, nextNodeType);
if (allNodeByProjectIdAndType.isSuccess() && ObjectUtils.isNotEmpty(allNodeByProjectIdAndType.getData())) {
uuids.addAll(allNodeByProjectIdAndType.getData().stream().map(AllNodeByProjectIdAndTypeResp::getUuid).toList());
}
// 非最后一层:查模板下一层;最后一层:查同类型连续子节点(例如 分类->分类)
String nextNodeType = (index != dimensionNodeTyepOrderList.size() - 1)
? dimensionNodeTyepOrderList.get(index + 1)
: chooseNodeType;
SdmResponse<List<AllNodeByProjectIdAndTypeResp>> allNodeByProjectIdAndType = simuluationNodeFeignClient.getAllNodeByProjectIdAndType(chooseUuids, nextNodeType);
if (allNodeByProjectIdAndType.isSuccess() && ObjectUtils.isNotEmpty(allNodeByProjectIdAndType.getData())) {
uuids.addAll(allNodeByProjectIdAndType.getData().stream().map(AllNodeByProjectIdAndTypeResp::getUuid).toList());
}
}
@@ -466,7 +469,7 @@ public class DimensionTemplateServiceImpl extends ServiceImpl<DimensionTemplateM
.in(FileMetadataInfo::getParentId, fileIds).list();
}else if(NodeTypeEnum.RUN.getValue().equalsIgnoreCase(nodeType)){
runFileInfos = nodeFileInfos;
} else if (NodeTypeEnum.isNodeType(nodeType)) {
} else if (tagMapService.isNodeType(nodeType)) {
// 基于 nodeUUids 获取 算列的run的uuids
SpdmQueryRunListReq spdmQueryRunListReq = new SpdmQueryRunListReq();
spdmQueryRunListReq.setNodeIdList(nodeUUids);

View File

@@ -833,7 +833,7 @@ public class MinioFileIDataFileServiceImpl implements IDataFileService {
QueryBigFileReq queryBigFileReq = new QueryBigFileReq();
List<Long> dirIds = new ArrayList<>();
Set<Long> dirIds = new HashSet<>();
Integer dirType;
if (ObjectUtils.isNotEmpty(minioFileSearchReq.getParentUuid())) {
// 项目节点下搜索文件
@@ -2058,6 +2058,11 @@ public class MinioFileIDataFileServiceImpl implements IDataFileService {
}
FileMetadataInfo dirMetadataInfo = dirResponse.getData();
SdmResponse<?> permissionResponse = checkUploadPermission(dirMetadataInfo);
if (!permissionResponse.isSuccess()) {
return permissionResponse;
}
String originalName = resolveOriginalName(req);
SdmResponse<String> versionedNameResponse = buildVersionedFileName(originalName);
if (!versionedNameResponse.isSuccess()) {
@@ -2068,11 +2073,12 @@ public class MinioFileIDataFileServiceImpl implements IDataFileService {
SdmResponse<?> existsResponse = ensureFileNotExists(fileMinioObjectKey);
if (!existsResponse.isSuccess()) {
return existsResponse;
}
SdmResponse<?> permissionResponse = checkUploadPermission(dirMetadataInfo);
if (!permissionResponse.isSuccess()) {
return permissionResponse;
if(!req.getIsConverSameNameFile()) {
return permissionResponse;
}else {
// 支持覆盖同名文件直接minioService.uploadFile 覆盖一下原文件就行
minioService.uploadFile(req.getFile(), fileMinioObjectKey, null, dirMetadataInfo.getBucketName());
}
}
try {

View File

@@ -179,7 +179,6 @@ public class MapperCompatibilityTest {
void testFileStorageMapperSelectBigFiles() {
QueryBigFileReq req = new QueryBigFileReq();
req.setIsLatest(true);
req.setDirIds(Arrays.asList(1L));
List<FileStorage> result = fileStorageMapper.selectBigFiles(req, 1000L, 1L);
assertNotNull(result);

View File

@@ -3,7 +3,7 @@ package com.sdm.project.schedule.lyric;
import com.alibaba.fastjson2.JSON;
import com.sdm.common.common.SdmResponse;
import com.sdm.common.utils.MdcUtil;
import com.sdm.project.service.ILyricInternalService;
import com.sdm.project.service.impl.LyricInternalNewServiceImpl;
import com.xxl.job.core.context.XxlJobHelper;
import com.xxl.job.core.handler.annotation.XxlJob;
import lombok.extern.slf4j.Slf4j;
@@ -15,8 +15,11 @@ import org.springframework.stereotype.Component;
public class LyricEncExceptionSchedule {
// @Autowired
// private ILyricInternalService lyricInternalService;
@Autowired
private ILyricInternalService lyricInternalService;
private LyricInternalNewServiceImpl lyricInternalNewService;
// xxljob平台配置定时任务
@XxlJob("lyricEncExceptionHandler")
@@ -25,7 +28,7 @@ public class LyricEncExceptionSchedule {
String traceId = MdcUtil.generateAndPutTraceId();
XxlJobHelper.log("{} XXL-JOB:拉起lyric异常任务信息开始,param:{}", traceId);
long startTime = System.currentTimeMillis();
SdmResponse response = lyricInternalService.syncException();
SdmResponse response = lyricInternalNewService.syncException();
long endTime = System.currentTimeMillis();
long second = (endTime - startTime) / 1000;
log.info("{} lyricEncExceptionHandler cost [{}] s", traceId,second);

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