diff --git a/common/src/main/java/com/sdm/common/config/CacheConfig.java b/common/src/main/java/com/sdm/common/config/CacheConfig.java index ada42515..0f3ed61c 100644 --- a/common/src/main/java/com/sdm/common/config/CacheConfig.java +++ b/common/src/main/java/com/sdm/common/config/CacheConfig.java @@ -26,7 +26,9 @@ public class CacheConfig { SimpleCacheManager cacheManager = new SimpleCacheManager(); cacheManager.setCaches(Arrays.asList( // 用户名缓存 - new ConcurrentMapCache("userNames") + new ConcurrentMapCache("userNames"), + // 查询任务树列表缓存 + new ConcurrentMapCache("taskTreeListCache") // 可以添加其他缓存配置 )); return cacheManager; diff --git a/outbridge/src/main/java/com/sdm/outbridge/mode/HkUploadFileReq.java b/outbridge/src/main/java/com/sdm/outbridge/mode/HkUploadFileReq.java index 864b5dbb..cfabdef2 100644 --- a/outbridge/src/main/java/com/sdm/outbridge/mode/HkUploadFileReq.java +++ b/outbridge/src/main/java/com/sdm/outbridge/mode/HkUploadFileReq.java @@ -27,7 +27,7 @@ public class HkUploadFileReq { public long componentInstId = 8000004142460000204L; @Schema(description = "表名称") - public String tableName = "oa_threee_d_review"; + public String tableName = "oa_three_d_review"; @Schema(description = "字段名称") public String columnName = "simulation_table;"; diff --git a/outbridge/src/main/java/com/sdm/outbridge/service/lyric/LyricIntegrateService.java b/outbridge/src/main/java/com/sdm/outbridge/service/lyric/LyricIntegrateService.java index 9e7ece68..d0502b3f 100644 --- a/outbridge/src/main/java/com/sdm/outbridge/service/lyric/LyricIntegrateService.java +++ b/outbridge/src/main/java/com/sdm/outbridge/service/lyric/LyricIntegrateService.java @@ -489,9 +489,6 @@ public class LyricIntegrateService { return response; } - public String getHkToken(String jobNo) { - return getHKCloudToken(jobNo); - } } diff --git a/project/src/main/java/com/sdm/project/controller/SimulationProjectController.java b/project/src/main/java/com/sdm/project/controller/SimulationProjectController.java index 7b37696a..374b841e 100644 --- a/project/src/main/java/com/sdm/project/controller/SimulationProjectController.java +++ b/project/src/main/java/com/sdm/project/controller/SimulationProjectController.java @@ -5,6 +5,7 @@ import com.sdm.common.entity.req.task.TaskExportExcelFormat; import com.sdm.common.entity.req.task.TaskTreeExportExcelFormat; import com.sdm.common.log.annotation.SysLog; import com.sdm.project.model.bo.ModifyProjectNode; +import com.sdm.project.model.req.ProjectTreeListReq; import com.sdm.project.model.req.ProjectTreeTagReq; import com.sdm.project.model.req.SpdmNodeReq; import com.sdm.project.service.IProjectService; @@ -68,5 +69,18 @@ public class SimulationProjectController { return taskService.newExportTaskTree(taskTreeExportExcelFormat, httpservletResponse); } + /** + * 任务分析项树 + * + * @param req + * @return + */ + @SysLog("获取多个项目的任务分析项树") + @PostMapping("/getTaskTreeList") + @Operation(summary = "获取多个项目的任务分析项树", description = "获取多个项目的任务分析项树") + public SdmResponse getTaskTreeList(@RequestBody ProjectTreeListReq req) { + return projectService.getTaskTreeList(req); + } + } diff --git a/project/src/main/java/com/sdm/project/dao/SimulationProjectMapper.java b/project/src/main/java/com/sdm/project/dao/SimulationProjectMapper.java index 39af2ef4..fb5dd0dd 100644 --- a/project/src/main/java/com/sdm/project/dao/SimulationProjectMapper.java +++ b/project/src/main/java/com/sdm/project/dao/SimulationProjectMapper.java @@ -181,4 +181,7 @@ public interface SimulationProjectMapper { List querySimulationNodeByUuids(@Param("list")List uuids); List getNodeByIdList(@Param("nodeIdList") List nodeIdList); + + List getNodeListByType(@Param("nodeTypeList") List nodeTypeList); + } diff --git a/project/src/main/java/com/sdm/project/model/req/ProjectTreeListReq.java b/project/src/main/java/com/sdm/project/model/req/ProjectTreeListReq.java new file mode 100644 index 00000000..aaa8e2cc --- /dev/null +++ b/project/src/main/java/com/sdm/project/model/req/ProjectTreeListReq.java @@ -0,0 +1,19 @@ +package com.sdm.project.model.req; + +import com.sdm.project.model.bo.TaskNodeTag; +import jakarta.validation.constraints.NotEmpty; +import lombok.Data; + +import java.util.List; + +@Data +public class ProjectTreeListReq { + + private String projectNodeId; + + private String phaseNodeId; + + @NotEmpty(message = "tagMap不能为空") + private List tagMap; + +} diff --git a/project/src/main/java/com/sdm/project/service/IProjectService.java b/project/src/main/java/com/sdm/project/service/IProjectService.java index 45c7f39e..bb3dc0d0 100644 --- a/project/src/main/java/com/sdm/project/service/IProjectService.java +++ b/project/src/main/java/com/sdm/project/service/IProjectService.java @@ -28,4 +28,6 @@ public interface IProjectService { SdmResponse exportTaskTree(TaskTreeExportExcelFormat taskTreeExportExcelFormat, HttpServletResponse httpservletResponse); + SdmResponse getTaskTreeList(ProjectTreeListReq req); + } diff --git a/project/src/main/java/com/sdm/project/service/impl/LyricInternalServiceImpl.java b/project/src/main/java/com/sdm/project/service/impl/LyricInternalServiceImpl.java index 6bf529e8..f4c6df5d 100644 --- a/project/src/main/java/com/sdm/project/service/impl/LyricInternalServiceImpl.java +++ b/project/src/main/java/com/sdm/project/service/impl/LyricInternalServiceImpl.java @@ -1171,7 +1171,7 @@ public class LyricInternalServiceImpl implements ILyricInternalService { uploadFileReq.setSysId(1691399963692630016L); uploadFileReq.setFormId(1847115435993071616L); uploadFileReq.setComponentInstId(8000004142460000204L); - uploadFileReq.setTableName("oa_threee_d_review"); + uploadFileReq.setTableName("oa_three_d_review"); uploadFileReq.setColumnName("simulation_table"); uploadFileReq.setXmh(req.getProjectCode()); uploadFileReq.setGwh(req.getWorkspaceCode()); @@ -1435,7 +1435,7 @@ public class LyricInternalServiceImpl implements ILyricInternalService { if (cidUserRespSdmResponse.getData() == null) { return SdmResponse.failed("根据工号获取username失败"); } - String token = lyricIntegrateService.getHkToken(cidUserRespSdmResponse.getData().getUsername()); + String token = lyricIntegrateService.getHKCloudToken(cidUserRespSdmResponse.getData().getUsername()); return SdmResponse.success(token); } diff --git a/project/src/main/java/com/sdm/project/service/impl/ProjectServiceImpl.java b/project/src/main/java/com/sdm/project/service/impl/ProjectServiceImpl.java index 2226a94e..16bd179e 100644 --- a/project/src/main/java/com/sdm/project/service/impl/ProjectServiceImpl.java +++ b/project/src/main/java/com/sdm/project/service/impl/ProjectServiceImpl.java @@ -36,6 +36,7 @@ import com.sdm.project.model.req.*; import com.sdm.project.model.vo.SpdmExportNewTaskVo; import com.sdm.project.model.vo.SpdmNewTaskVo; import com.sdm.project.model.vo.SpdmNodeExtraVo; +import com.sdm.project.model.vo.SpdmNodeVo; import com.sdm.project.service.IProjectService; import com.sdm.project.service.ISimulationPerformanceExtraService; import com.sdm.project.service.ISimulationPerformanceService; @@ -48,6 +49,8 @@ import org.apache.commons.lang3.ObjectUtils; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.cache.Cache; +import org.springframework.cache.CacheManager; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.interceptor.TransactionAspectSupport; @@ -139,6 +142,15 @@ public class ProjectServiceImpl extends BaseService implements IProjectService { private static final String PERFORMANCE_CODE = "指标编号"; + private static final String TAG1 = "tag1"; + private static final String TAG2 = "tag2"; + private static final String NODE_TYPE_PROJECT = NodeTypeEnum.PROJECT.getValue(); + private static final String NODE_TYPE_PHASE = NodeTypeEnum.PHASE.getValue(); + private static final List EMPTY_TAG_LIST = Collections.emptyList(); + @Autowired + private CacheManager cacheManager; + + @Override @Transactional public SdmResponse add(JSONObject jsonObject) { @@ -2508,4 +2520,234 @@ public class ProjectServiceImpl extends BaseService implements IProjectService { return projectNodePo; } + /** + * 调用getTaskTree并统一处理返回结果 + * @param req + * @return + */ + private List getTaskTreeData(ProjectTreeTagReq req) { + if (req == null || CollectionUtils.isEmpty(req.getIdMap())) { + return new ArrayList<>(); + } + // 构建缓存key:唯一标识本次查询 + String cacheKey = "taskTree_" + req.getIdMap().stream().map(t -> t.getKey() + "_" + t.getValue()).collect(Collectors.joining(",")); + Cache cache = cacheManager.getCache("taskTreeListCache"); + if (cache != null && cache.get(cacheKey) != null) { + // 缓存命中,直接返回,不调用getTaskTree() + log.info("--------------------------命中缓存--------------------------"); + return (List) cache.get(cacheKey).get(); + } + // 缓存未命中,执行原逻辑 + SdmResponse taskTree = getTaskTree(req); + if (taskTree == null || taskTree.getData() == null) { + return new ArrayList<>(); + } + if (!(taskTree.getData() instanceof List)) { + return new ArrayList<>(); + } + List dataList = (List) taskTree.getData(); + if (dataList.stream().noneMatch(NodeAllBase.class::isInstance)) { + return new ArrayList<>(); + } + List result = dataList.stream().map(NodeAllBase.class::cast).collect(Collectors.toList()); + // 存入缓存,设置过期时间(根据业务调整,比如5分钟,避免数据不一致) + if (cache != null) { + cache.put(cacheKey, result); + } + return result; + } + + + public SdmResponse getTaskTreeList(ProjectTreeListReq req) { + // 1. 提取入参,统一变量 + String projectNodeId = req.getProjectNodeId(); + String phaseNodeId = req.getPhaseNodeId(); + List tagMap = req.getTagMap(); + // 2. 四种业务场景 + if (StringUtils.isNotBlank(projectNodeId) && StringUtils.isNotBlank(phaseNodeId)) { + return handleBothIdsSpecified(projectNodeId, phaseNodeId, tagMap); + } else if (StringUtils.isBlank(projectNodeId) && StringUtils.isBlank(phaseNodeId)) { + return handleNoIdsSpecified(tagMap); + } else if (StringUtils.isBlank(projectNodeId)) { + return handleOnlyPhaseSpecified(phaseNodeId, tagMap); + } else if (StringUtils.isBlank(phaseNodeId)) { + return handleOnlyProjectSpecified(projectNodeId, tagMap); + } + return SdmResponse.success(Collections.emptyList()); + } + + /** + * 构建ProjectTreeTagReq请求对象 + */ + private ProjectTreeTagReq buildProjectTreeTagReq(List idMapList, List tagMap) { + ProjectTreeTagReq req = new ProjectTreeTagReq(); + req.setIdMap(CollectionUtils.isEmpty(idMapList) ? EMPTY_TAG_LIST : idMapList); + req.setTagMap(CollectionUtils.isEmpty(tagMap) ? EMPTY_TAG_LIST : tagMap); + return req; + } + + /** + * 创建单个TaskNodeTag对象 + */ + private TaskNodeTag createTaskNodeTag(String key, String value) { + TaskNodeTag tag = new TaskNodeTag(); + tag.setKey(key); + tag.setValue(value); + return tag; + } + + private void batchSetNodeExtras(List nodeList) { + if (CollectionUtils.isEmpty(nodeList)) { + return; + } + // 1. 提取所有需要查询的节点UUID + List nodeUuids = nodeList.stream() + .map(ProjectNodePo::getUuid) + .filter(StringUtils::isNotBlank) + .distinct() // 去重,避免重复查询相同UUID + .collect(Collectors.toList()); + if (CollectionUtils.isEmpty(nodeUuids)) { + return; + } + // 2. 批量查询所有扩展信息 + List allExtras = nodeMapper.getNodeExtraListByNodeIdList(nodeUuids); + if (CollectionUtils.isEmpty(allExtras)) { + return; + } + // 3. 转Map映射 + Map> extraMap = allExtras.stream() + .collect(Collectors.groupingBy(SpdmNodeExtraVo::getNodeId)); + // 4. 批量赋值 + nodeList.forEach(node -> node.setExtras(extraMap.getOrDefault(node.getUuid(), new ArrayList<>()))); + } + + + /** + * 场景1:项目ID+阶段ID 都传的情况 + */ + private SdmResponse handleBothIdsSpecified(String projectNodeId, String phaseNodeId, List tagMap) { + // 构建查询参数 - 复用常量,减少对象创建 + List idMap = Arrays.asList( + createTaskNodeTag(projectNodeId, TAG1), + createTaskNodeTag(phaseNodeId, TAG2) + ); + ProjectTreeTagReq req = buildProjectTreeTagReq(idMap, tagMap); + // 获取任务树数据 + List nodeAllBaseList = getTaskTreeData(req); + if (CollectionUtils.isEmpty(nodeAllBaseList)) { + return SdmResponse.success(Collections.emptyList()); + } + // 查询节点信息 + List nodeIds = Arrays.asList(projectNodeId, phaseNodeId); + List nodeList = mapper.getNodeListByNodeIdList(nodeIds); + if (CollectionUtils.isEmpty(nodeList) || nodeList.size() != 2) { + log.error("【双ID查询】节点数量异常, projectNodeId={}, phaseNodeId={}, 数量={}", projectNodeId, phaseNodeId, nodeList.size()); + return SdmResponse.success(Collections.emptyList()); + } + // 流式过滤+Optional处理 + ProjectNodePo projectNode = nodeList.stream().filter(node -> NODE_TYPE_PROJECT.equals(node.getNodeType())).findFirst().orElse(null); + ProjectNodePo phaseNode = nodeList.stream().filter(node -> NODE_TYPE_PHASE.equals(node.getNodeType())).findFirst().orElse(null); + if (projectNode == null || phaseNode == null) { + log.error("【双ID查询】未匹配到对应类型节点, projectNodeId={}, phaseNodeId={}", projectNodeId, phaseNodeId); + return SdmResponse.success(Collections.emptyList()); + } + // 组装树形结构 + 【批量赋值扩展信息】仅1次查询 + batchSetNodeExtras(Arrays.asList(projectNode, phaseNode)); + phaseNode.setChildren(nodeAllBaseList); + projectNode.setChildren(Collections.singletonList(phaseNode)); + return SdmResponse.success(Collections.singletonList(projectNode)); + } + + /** + * 场景2:项目ID+阶段ID 都不传的情况(查所有项目) + */ + private SdmResponse handleNoIdsSpecified(List tagMap) { + List projectNodeList = mapper.getNodeListByType(Collections.singletonList(NODE_TYPE_PROJECT)); + if (CollectionUtils.isEmpty(projectNodeList)) { + log.error("【全量查询】未查询到任何项目节点"); + return SdmResponse.success(Collections.emptyList()); + } + // 批量设置扩展信息 + batchSetNodeExtras(projectNodeList); + projectNodeList.forEach(projectNode -> { + List idMap = Collections.singletonList(createTaskNodeTag(projectNode.getUuid(), TAG1)); + ProjectTreeTagReq req = buildProjectTreeTagReq(idMap, tagMap); + List children = getTaskTreeData(req); + if (!CollectionUtils.isEmpty(children)) { + projectNode.setChildren(children); + } + }); + return SdmResponse.success(projectNodeList); + } + + /** + * 场景3:只传阶段ID,不传项目ID(查所有项目的指定阶段) + */ + private SdmResponse handleOnlyPhaseSpecified(String phaseNodeId, List tagMap) { + List phaseNodeList = mapper.getNodeListByNodeIdList(Collections.singletonList(phaseNodeId)); + if (CollectionUtils.isEmpty(phaseNodeList)) { + log.error("【仅阶段查询】未查询到阶段节点, phaseNodeId={}", phaseNodeId); + return SdmResponse.success(Collections.emptyList()); + } + // 提取项目ID+批量查询项目节点 + 转MAP + List projectIdList = phaseNodeList.stream() + .map(ProjectNodePo::getTag1) + .filter(StringUtils::isNotBlank) + .distinct() + .collect(Collectors.toList()); + if (CollectionUtils.isEmpty(projectIdList)) { + log.error("【仅阶段查询】无关联的项目ID, phaseNodeId={}", phaseNodeId); + return SdmResponse.success(Collections.emptyList()); + } + List projectNodeList = mapper.getNodeListByNodeIdList(projectIdList); + if (CollectionUtils.isEmpty(projectNodeList)) { + log.error("【仅阶段查询】未查询到关联项目节点, projectIdList={}", projectIdList); + return SdmResponse.success(Collections.emptyList()); + } + Map projectNodeMap = projectNodeList.stream() + .collect(Collectors.toMap(ProjectNodePo::getUuid, p -> p, (k1, k2) -> k1)); // 解决重复key问题 + // 批量设置所有节点的扩展信息 + batchSetNodeExtras(phaseNodeList); + batchSetNodeExtras(projectNodeList); + phaseNodeList.forEach(phaseNode -> { + List idMap = Arrays.asList( + createTaskNodeTag(phaseNode.getUuid(), TAG1), + createTaskNodeTag(phaseNode.getUuid(), TAG2) + ); + ProjectTreeTagReq req = buildProjectTreeTagReq(idMap, tagMap); + List children = getTaskTreeData(req); + if (!CollectionUtils.isEmpty(children)) { + phaseNode.setChildren(children); + } + // MAP直接取值,O(1)效率 + ProjectNodePo projectNode = projectNodeMap.get(phaseNode.getTag1()); + if (projectNode != null) { + projectNode.setChildren(Collections.singletonList(phaseNode)); + } + }); + return SdmResponse.success(projectNodeList); + } + + /** + * 场景4:只传项目ID,不传阶段ID(查指定项目的全量数据) + */ + private SdmResponse handleOnlyProjectSpecified(String projectNodeId, List tagMap) { + List projectNodeList = mapper.getNodeListByNodeIdList(Collections.singletonList(projectNodeId)); + if (CollectionUtils.isEmpty(projectNodeList)) { + log.error("【仅项目查询】未查询到项目节点, projectNodeId={}", projectNodeId); + return SdmResponse.success(Collections.emptyList()); + } + // 批量设置扩展信息 + batchSetNodeExtras(projectNodeList); + projectNodeList.forEach(projectNode -> { + List idMap = Collections.singletonList(createTaskNodeTag(projectNode.getUuid(), TAG1)); + ProjectTreeTagReq req = buildProjectTreeTagReq(idMap, tagMap); + List children = getTaskTreeData(req); + if (!CollectionUtils.isEmpty(children)) { + projectNode.setChildren(children); + } + }); + return SdmResponse.success(projectNodeList); + } + } diff --git a/project/src/main/resources/application-lyric.yml b/project/src/main/resources/application-lyric.yml index 98f1b289..dccd98c6 100644 --- a/project/src/main/resources/application-lyric.yml +++ b/project/src/main/resources/application-lyric.yml @@ -124,6 +124,7 @@ security: - /run/getSimulationKeyResultFileIds - /run/generateReportInternal - /dataManager/tree/node/listUserByIds + - /node/updateApprovalStatus #logging: # config: ./config/logback.xml diff --git a/project/src/main/resources/mapper/SimulationProjectMapper.xml b/project/src/main/resources/mapper/SimulationProjectMapper.xml index 3f5d6cfc..3508c252 100644 --- a/project/src/main/resources/mapper/SimulationProjectMapper.xml +++ b/project/src/main/resources/mapper/SimulationProjectMapper.xml @@ -713,6 +713,14 @@ ) + +