fix:数据总览文件排序

This commit is contained in:
2026-03-24 14:23:56 +08:00
parent 05ecc1eb3c
commit 4e3a74a658

View File

@@ -419,61 +419,16 @@ public class DimensionTemplateServiceImpl extends ServiceImpl<DimensionTemplateM
// 设置聚合结果
List<FileMetadataChildrenDTO> result = new ArrayList<>();
groupedChildren.values().forEach(children -> {
for (List<FileMetadataChildrenDTO> children : groupedChildren.values()) {
FileMetadataChildrenDTO baseDto = new FileMetadataChildrenDTO();
BeanUtils.copyProperties(children.get(0),baseDto);
baseDto.setMergeSameNameChildren(children);
baseDto.setFileIds(children.stream().map(FileMetadataInfoResp::getId).toList());
result.add(baseDto);
});
}
if(CollectionUtils.isNotEmpty(result)) {
// 判断是否存在PHASE类型的节点
boolean hasPhaseNode = result.stream()
.flatMap(dto -> dto.getMergeSameNameChildren().stream())
.anyMatch(child -> NodeTypeEnum.PHASE.getValue().equals(child.getRelatedResourceUuidOwnType()));
// 先按dataType排序文件夹在前dataType=1文件在后dataType=2再按children中的最大创建时间倒序排序
result.sort((dto1, dto2) -> {
// 首先按dataType排序文件夹(1)在前,文件(2)在后
Integer dataType1 = dto1.getDataType();
Integer dataType2 = dto2.getDataType();
if (dataType1 != null && dataType2 != null && !dataType1.equals(dataType2)) {
return dataType1.compareTo(dataType2); // 升序1(文件夹) < 2(文件)
}
boolean isWorkspace1 = dto1.getMergeSameNameChildren().stream()
.anyMatch(child -> NodeTypeEnum.WORKSPACE.getValue().equals(child.getRelatedResourceUuidOwnType()));
boolean isWorkspace2 = dto2.getMergeSameNameChildren().stream()
.anyMatch(child -> NodeTypeEnum.WORKSPACE.getValue().equals(child.getRelatedResourceUuidOwnType()));
if (isWorkspace1 && isWorkspace2) {
return compareWorkspaceNodeCode(dto1.getNodeCode(), dto2.getNodeCode());
}
// 如果存在PHASE类型节点dataType相同时按主键ID正序排序
if (hasPhaseNode) {
Long id1 = dto1.getId();
Long id2 = dto2.getId();
if (id1 != null && id2 != null && !id1.equals(id2)) {
return id1.compareTo(id2); // 正序排序
}
}
// dataType相同或都为null时按创建时间倒序排序
LocalDateTime maxCreateTime1 = dto1.getMergeSameNameChildren().stream()
.map(FileMetadataInfoResp::getCreateTime)
.filter(Objects::nonNull)
.max(LocalDateTime::compareTo)
.orElse(LocalDateTime.MIN);
LocalDateTime maxCreateTime2 = dto2.getMergeSameNameChildren().stream()
.map(FileMetadataInfoResp::getCreateTime)
.filter(Objects::nonNull)
.max(LocalDateTime::compareTo)
.orElse(LocalDateTime.MIN);
return maxCreateTime2.compareTo(maxCreateTime1); // 倒序排序
});
result = sortMergedNodeDirResult(result);
}
log.info("getSimulationNodeTree 方法耗时 " +
@@ -484,31 +439,126 @@ public class DimensionTemplateServiceImpl extends ServiceImpl<DimensionTemplateM
"批量填充文件类型标签信息:" + (start6-start5) + "毫秒," +
"结果排序:" + (System.currentTimeMillis() - start6) + "毫秒");
// 特殊的定制逻辑,工位需要排序
moveWorkspaceToFirst(result);
return result;
}
private void moveWorkspaceToFirst(List<FileMetadataChildrenDTO> result) {
if (CollectionUtils.isEmpty(result)) {
return;
/**
* 聚合后的节点目录排序规则(分层分组 + 组内排序):
*
* <pre>
* 一、顶层:先文件夹,后文件
* 1) 文件夹dataType=1
* 2) 文件dataType!=1按创建时间倒序最新在前
*
* 二、文件夹层:先普通文件夹,后节点类型文件夹
* 1) 普通文件夹:按创建时间倒序(最新在前)
* 2) 节点类型文件夹:按节点类型分组后依次展开
*
* 三、节点类型文件夹分组顺序
* 1) TASK / RUN 分组优先
* 2) 其他节点类型分组在后
* 同优先级分组按节点类型字符串字典序兜底,保证结果稳定
*
* 四、节点类型分组内排序
* 1) WORKSPACE先将 nodeCode 包含 "-M" 的工位置前,再按 compareWorkspaceNodeCode 排序
* 2) TASK / RUN / PHASE / 其他:按主键 ID 正序;若 ID 相同或为空,再按创建时间倒序兜底
* </pre>
*
* 说明:创建时间使用 mergeSameNameChildren 中的最大 createTime 参与比较。
*/
private List<FileMetadataChildrenDTO> sortMergedNodeDirResult(List<FileMetadataChildrenDTO> source) {
List<FileMetadataChildrenDTO> folders = source.stream()
.filter(this::isFolder)
.collect(Collectors.toCollection(ArrayList::new));
List<FileMetadataChildrenDTO> files = source.stream()
.filter(dto -> !isFolder(dto))
.sorted(Comparator.comparing(this::getMaxCreateTime, Comparator.nullsLast(Comparator.naturalOrder())).reversed())
.collect(Collectors.toCollection(ArrayList::new));
List<FileMetadataChildrenDTO> normalFolders = folders.stream()
.filter(dto -> !isNodeTypeFolder(dto))
.sorted(Comparator.comparing(this::getMaxCreateTime, Comparator.nullsLast(Comparator.naturalOrder())).reversed())
.collect(Collectors.toCollection(ArrayList::new));
List<FileMetadataChildrenDTO> nodeTypeFolders = folders.stream()
.filter(this::isNodeTypeFolder)
.collect(Collectors.toCollection(ArrayList::new));
Map<String, List<FileMetadataChildrenDTO>> groupedByNodeType = nodeTypeFolders.stream()
.collect(Collectors.groupingBy(this::getNodeTypeKey));
List<String> nodeTypeOrder = groupedByNodeType.keySet().stream()
.sorted(Comparator.comparingInt(this::nodeTypeGroupPriority).thenComparing(String::compareTo))
.toList();
List<FileMetadataChildrenDTO> sortedNodeTypeFolders = new ArrayList<>();
for (String nodeType : nodeTypeOrder) {
List<FileMetadataChildrenDTO> group = new ArrayList<>(groupedByNodeType.get(nodeType));
group.sort(getNodeTypeFolderComparator(nodeType));
sortedNodeTypeFolders.addAll(group);
}
FileMetadataChildrenDTO specialWorkspace = result.stream()
.filter(this::isWorkspaceNode)
.filter(dto -> StringUtils.contains(dto.getNodeCode(), "-M"))
.findFirst()
.orElse(null);
if (specialWorkspace != null) {
result.remove(specialWorkspace);
result.add(0, specialWorkspace);
}
List<FileMetadataChildrenDTO> result = new ArrayList<>(source.size());
result.addAll(normalFolders);
result.addAll(sortedNodeTypeFolders);
result.addAll(files);
return result;
}
private boolean isWorkspaceNode(FileMetadataChildrenDTO dto) {
return dto != null && CollectionUtils.isNotEmpty(dto.getMergeSameNameChildren())
&& dto.getMergeSameNameChildren().stream()
.anyMatch(child -> NodeTypeEnum.WORKSPACE.getValue().equals(child.getRelatedResourceUuidOwnType()));
private Comparator<FileMetadataChildrenDTO> getNodeTypeFolderComparator(String nodeType) {
if (NodeTypeEnum.WORKSPACE.getValue().equals(nodeType)) {
return (a, b) -> {
boolean isSpecialA = StringUtils.contains(a.getNodeCode(), "-M");
boolean isSpecialB = StringUtils.contains(b.getNodeCode(), "-M");
if (isSpecialA != isSpecialB) {
return isSpecialA ? -1 : 1;
}
return compareWorkspaceNodeCode(a.getNodeCode(), b.getNodeCode());
};
}
return Comparator
.comparing(FileMetadataChildrenDTO::getId, Comparator.nullsLast(Long::compareTo))
.thenComparing(Comparator.comparing(this::getMaxCreateTime, Comparator.nullsLast(Comparator.naturalOrder())).reversed());
}
private int nodeTypeGroupPriority(String nodeType) {
if (NodeTypeEnum.TASK.getValue().equals(nodeType) || NodeTypeEnum.RUN.getValue().equals(nodeType)) {
return 0;
}
return 1;
}
private boolean isFolder(FileMetadataChildrenDTO dto) {
return dto != null &&Objects.equals(DataTypeEnum.DIRECTORY.getValue(), dto.getDataType());
}
private boolean isNodeTypeFolder(FileMetadataChildrenDTO dto) {
String nodeType = getNodeTypeKey(dto);
return StringUtils.isNotBlank(nodeType);
}
private String getNodeTypeKey(FileMetadataChildrenDTO dto) {
if (dto == null || CollectionUtils.isEmpty(dto.getMergeSameNameChildren())) {
return "";
}
return dto.getMergeSameNameChildren().stream()
.map(FileMetadataInfoResp::getRelatedResourceUuidOwnType)
.filter(StringUtils::isNotBlank)
.findFirst()
.orElse("");
}
private LocalDateTime getMaxCreateTime(FileMetadataChildrenDTO dto) {
if (dto == null || CollectionUtils.isEmpty(dto.getMergeSameNameChildren())) {
return LocalDateTime.MIN;
}
return dto.getMergeSameNameChildren().stream()
.map(FileMetadataInfoResp::getCreateTime)
.filter(Objects::nonNull)
.max(LocalDateTime::compareTo)
.orElse(LocalDateTime.MIN);
}
private int compareWorkspaceNodeCode(String nodeCode1, String nodeCode2) {