From 303ba868c5c8a20da29d9c55d15d7caa8aef4491 Mon Sep 17 00:00:00 2001 From: gulongcheng <474084054@qq.com> Date: Wed, 11 Feb 2026 16:56:45 +0800 Subject: [PATCH 1/2] =?UTF-8?q?fix:=E4=BC=98=E5=8C=96=E6=96=87=E4=BB=B6?= =?UTF-8?q?=E5=88=A0=E9=99=A4=E5=9B=9E=E6=94=B6=E7=AB=99=E5=8A=9F=E8=83=BD?= =?UTF-8?q?,=E6=94=AF=E6=8C=81=E6=89=B9=E9=87=8F=E8=AE=BE=E7=BD=AE?= =?UTF-8?q?=E8=BF=87=E6=9C=9F=E6=97=B6=E9=97=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../data/PermanentDeleteFromRecycleReq.java | 8 +- .../req/data/RestoreFromRecycleReq.java | 8 +- .../req/data/UpdateRecycleExpireReq.java | 21 ++++ .../data/controller/DataFileController.java | 21 +++- .../sdm/data/service/IDataFileService.java | 19 +++- .../impl/MinioFileIDataFileServiceImpl.java | 106 +++++++++++++++++- 6 files changed, 165 insertions(+), 18 deletions(-) create mode 100644 common/src/main/java/com/sdm/common/entity/req/data/UpdateRecycleExpireReq.java diff --git a/common/src/main/java/com/sdm/common/entity/req/data/PermanentDeleteFromRecycleReq.java b/common/src/main/java/com/sdm/common/entity/req/data/PermanentDeleteFromRecycleReq.java index 51f11965..f647109f 100644 --- a/common/src/main/java/com/sdm/common/entity/req/data/PermanentDeleteFromRecycleReq.java +++ b/common/src/main/java/com/sdm/common/entity/req/data/PermanentDeleteFromRecycleReq.java @@ -4,10 +4,12 @@ import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotNull; import lombok.Data; +import java.util.List; + @Data @Schema(description = "从回收站彻底删除请求") public class PermanentDeleteFromRecycleReq { - @Schema(description = "要彻底删除的文件/目录ID", requiredMode = Schema.RequiredMode.REQUIRED) - @NotNull(message = "文件/目录ID不能为空") - private Long id; + @Schema(description = "要彻底删除的文件/目录ID列表", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "文件/目录ID列表不能为空") + private List ids; } diff --git a/common/src/main/java/com/sdm/common/entity/req/data/RestoreFromRecycleReq.java b/common/src/main/java/com/sdm/common/entity/req/data/RestoreFromRecycleReq.java index 0e21bb2c..95deef5e 100644 --- a/common/src/main/java/com/sdm/common/entity/req/data/RestoreFromRecycleReq.java +++ b/common/src/main/java/com/sdm/common/entity/req/data/RestoreFromRecycleReq.java @@ -4,10 +4,12 @@ import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotNull; import lombok.Data; +import java.util.List; + @Data @Schema(description = "从回收站还原请求") public class RestoreFromRecycleReq { - @Schema(description = "要还原的文件/目录ID", requiredMode = Schema.RequiredMode.REQUIRED) - @NotNull(message = "文件/目录ID不能为空") - private Long id; + @Schema(description = "要还原的文件/目录ID列表", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "文件/目录ID列表不能为空") + private List ids; } diff --git a/common/src/main/java/com/sdm/common/entity/req/data/UpdateRecycleExpireReq.java b/common/src/main/java/com/sdm/common/entity/req/data/UpdateRecycleExpireReq.java new file mode 100644 index 00000000..d889b8dc --- /dev/null +++ b/common/src/main/java/com/sdm/common/entity/req/data/UpdateRecycleExpireReq.java @@ -0,0 +1,21 @@ +package com.sdm.common.entity.req.data; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.Min; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.util.List; + +@Data +@Schema(description = "批量更新回收站过期时间请求") +public class UpdateRecycleExpireReq { + @Schema(description = "文件/目录ID列表", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "文件/目录ID列表不能为空") + private List ids; + + @Schema(description = "保留天数(从删除时间开始计算)", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "保留天数不能为空") + @Min(value = 0, message = "保留天数不能小于0") + private Integer days; +} diff --git a/data/src/main/java/com/sdm/data/controller/DataFileController.java b/data/src/main/java/com/sdm/data/controller/DataFileController.java index b4431c42..c15d337e 100644 --- a/data/src/main/java/com/sdm/data/controller/DataFileController.java +++ b/data/src/main/java/com/sdm/data/controller/DataFileController.java @@ -146,31 +146,44 @@ public class DataFileController implements IDataFeignClient { } /** - * 从回收站还原 + * 批量从回收站还原 * * @param req * @return */ @SysLog("从回收站还原") @PostMapping("/restoreFromRecycle") - @Operation(summary = "从回收站还原", description = "将文件/目录从回收站还原到原位置") + @Operation(summary = "从回收站还原", description = "将文件/目录从回收站还原到原位置(支持批量)") public SdmResponse restoreFromRecycle(@RequestBody @Validated RestoreFromRecycleReq req) { return IDataFileService.restoreFromRecycle(req); } /** - * 从回收站彻底删除 + * 批量从回收站彻底删除 * * @param req * @return */ @SysLog("从回收站彻底删除") @PostMapping("/permanentDeleteFromRecycle") - @Operation(summary = "从回收站彻底删除", description = "从回收站彻底删除文件/目录(物理删除,不可恢复)") + @Operation(summary = "从回收站彻底删除", description = "从回收站彻底删除文件/目录(物理删除,不可恢复,支持批量)") public SdmResponse permanentDeleteFromRecycle(@RequestBody @Validated PermanentDeleteFromRecycleReq req) { return IDataFileService.permanentDeleteFromRecycle(req); } + /** + * 批量更新回收站过期时间 + * + * @param req + * @return + */ + @SysLog("更新回收站过期时间") + @PostMapping("/updateRecycleExpire") + @Operation(summary = "更新回收站过期时间", description = "批量更新回收站中文件/目录的过期时间") + public SdmResponse updateRecycleExpire(@RequestBody @Validated UpdateRecycleExpireReq req) { + return IDataFileService.updateRecycleExpire(req); + } + /** * 搜索文件 * diff --git a/data/src/main/java/com/sdm/data/service/IDataFileService.java b/data/src/main/java/com/sdm/data/service/IDataFileService.java index dc8a18c6..329ae09e 100644 --- a/data/src/main/java/com/sdm/data/service/IDataFileService.java +++ b/data/src/main/java/com/sdm/data/service/IDataFileService.java @@ -140,25 +140,34 @@ public interface IDataFileService { * @param req 回收站列表查询请求参数 * @return 回收站列表响应 */ - default SdmResponse listRecycleBin(com.sdm.common.entity.req.data.ListRecycleBinReq req) { + default SdmResponse listRecycleBin(ListRecycleBinReq req) { return null; } /** - * 从回收站还原文件/目录 + * 批量从回收站还原文件/目录 * @param req 还原请求参数 * @return 还原结果响应 */ - default SdmResponse restoreFromRecycle(com.sdm.common.entity.req.data.RestoreFromRecycleReq req) { + default SdmResponse restoreFromRecycle(RestoreFromRecycleReq req) { return null; } /** - * 从回收站彻底删除文件/目录 + * 批量从回收站彻底删除文件/目录 * @param req 彻底删除请求参数 * @return 删除结果响应 */ - default SdmResponse permanentDeleteFromRecycle(com.sdm.common.entity.req.data.PermanentDeleteFromRecycleReq req) { + default SdmResponse permanentDeleteFromRecycle(PermanentDeleteFromRecycleReq req) { + return null; + } + + /** + * 批量更新回收站过期时间 + * @param req 更新过期时间请求参数 + * @return 更新结果响应 + */ + default SdmResponse updateRecycleExpire(com.sdm.common.entity.req.data.UpdateRecycleExpireReq req) { return null; } diff --git a/data/src/main/java/com/sdm/data/service/impl/MinioFileIDataFileServiceImpl.java b/data/src/main/java/com/sdm/data/service/impl/MinioFileIDataFileServiceImpl.java index 1c6498fd..9c51ff4c 100644 --- a/data/src/main/java/com/sdm/data/service/impl/MinioFileIDataFileServiceImpl.java +++ b/data/src/main/java/com/sdm/data/service/impl/MinioFileIDataFileServiceImpl.java @@ -105,6 +105,10 @@ public class MinioFileIDataFileServiceImpl implements IDataFileService { private static final String FLOWABLE_SIMULATION_BASEDIR = "/home/simulation/"; @Value("${data.recycle.retention-days:7}") + + + + private Integer recycleRetentionDays; @Autowired @@ -4686,8 +4690,30 @@ public class MinioFileIDataFileServiceImpl implements IDataFileService { @Override @Transactional(rollbackFor = Exception.class) public SdmResponse restoreFromRecycle(RestoreFromRecycleReq req) { + if (ObjectUtils.isEmpty(req.getIds())) { + return SdmResponse.failed("未选择要还原的文件"); + } + + List messages = new ArrayList<>(); + for (Long id : req.getIds()) { + SdmResponse resp = restoreSingleFile(id); + if (!resp.isSuccess()) { + throw new RuntimeException("还原文件(ID:" + id + ")失败: " + resp.getMessage()); + } + if (resp.getData() != null && !Objects.equals(resp.getData(), "还原成功")) { + messages.add(resp.getData().toString()); + } + } + + if (!messages.isEmpty()) { + return SdmResponse.success("还原成功,部分文件已重命名: " + String.join("; ", messages)); + } + return SdmResponse.success("批量还原成功"); + } + + private SdmResponse restoreSingleFile(Long id) { FileMetadataInfo metadata = fileMetadataInfoService.lambdaQuery() - .eq(FileMetadataInfo::getId, req.getId()) + .eq(FileMetadataInfo::getId, id) .isNotNull(FileMetadataInfo::getDeletedAt) .one(); @@ -4778,7 +4804,7 @@ public class MinioFileIDataFileServiceImpl implements IDataFileService { } log.info("成功从回收站还原: id={}, oldKey={}, newKey={}, newName={}", metadata.getId(), oldKey, restoreKey, restoreName); - return SdmResponse.success(Objects.equals(restoreName, originalName) ? "还原成功" : "还原成功,原路径已存在,已重命名为: " + restoreName); + return SdmResponse.success(Objects.equals(restoreName, originalName) ? "还原成功" : "已重命名为: " + restoreName); } catch (Exception e) { log.error("还原失败", e); @@ -4789,8 +4815,22 @@ public class MinioFileIDataFileServiceImpl implements IDataFileService { @Override @Transactional(rollbackFor = Exception.class) public SdmResponse permanentDeleteFromRecycle(PermanentDeleteFromRecycleReq req) { + if (ObjectUtils.isEmpty(req.getIds())) { + return SdmResponse.failed("未选择要删除的文件"); + } + + for (Long id : req.getIds()) { + SdmResponse resp = permanentDeleteSingleFile(id); + if (!resp.isSuccess()) { + throw new RuntimeException("删除文件(ID:" + id + ")失败: " + resp.getMessage()); + } + } + return SdmResponse.success("批量彻底删除成功"); + } + + private SdmResponse permanentDeleteSingleFile(Long id) { FileMetadataInfo metadata = fileMetadataInfoService.lambdaQuery() - .eq(FileMetadataInfo::getId, req.getId()) + .eq(FileMetadataInfo::getId, id) .isNotNull(FileMetadataInfo::getDeletedAt) .one(); @@ -4816,4 +4856,64 @@ public class MinioFileIDataFileServiceImpl implements IDataFileService { } } + @Override + @Transactional(rollbackFor = Exception.class) + public SdmResponse updateRecycleExpire(UpdateRecycleExpireReq req) { + if (ObjectUtils.isEmpty(req.getIds())) { + return SdmResponse.failed("未选择要更新的文件"); + } + + List metadataList = fileMetadataInfoService.listByIds(req.getIds()); + if (CollectionUtils.isEmpty(metadataList)) { + return SdmResponse.failed("文件不存在"); + } + + int successCount = 0; + for (FileMetadataInfo metadata : metadataList) { + // 仅处理已删除的文件 + if (metadata.getDeletedAt() == null) { + continue; + } + + // 计算新的过期时间:基于 deletedAt + days + LocalDateTime newExpireAt = metadata.getDeletedAt().plusDays(req.getDays()); + + // 如果是目录,递归更新子项 + if (Objects.equals(DataTypeEnum.DIRECTORY.getValue(), metadata.getDataType())) { + updateDirectoryRecycleExpire(metadata, newExpireAt); + } else { + // 单文件更新 + metadata.setRecycleExpireAt(newExpireAt); + metadata.setUpdateTime(LocalDateTime.now()); + fileMetadataInfoService.updateById(metadata); + } + successCount++; + } + + return SdmResponse.success("成功更新 " + successCount + " 个文件的回收站过期时间"); + } + + private void updateDirectoryRecycleExpire(FileMetadataInfo rootDir, LocalDateTime newExpireAt) { + // 1. 更新目录本身 + rootDir.setRecycleExpireAt(newExpireAt); + rootDir.setUpdateTime(LocalDateTime.now()); + fileMetadataInfoService.updateById(rootDir); + + // 2. 批量更新子项(包括子目录和文件) + // 只要是该目录下的(objectKey以目录key为前缀),且已删除的,都更新 + String dirKey = rootDir.getObjectKey(); + if (!dirKey.endsWith("/")) { + dirKey += "/"; + } + + // 使用 LambdaUpdateWrapper 批量更新,效率更高 + fileMetadataInfoService.lambdaUpdate() + .likeRight(FileMetadataInfo::getObjectKey, dirKey) // objectKey like 'dirKey%' + .eq(FileMetadataInfo::getBucketName, rootDir.getBucketName()) + .isNotNull(FileMetadataInfo::getDeletedAt) // 必须是已删除的 + .set(FileMetadataInfo::getRecycleExpireAt, newExpireAt) + .set(FileMetadataInfo::getUpdateTime, LocalDateTime.now()) + .update(); + } + } \ No newline at end of file From 3fc949d4365a844424cdb15cccff108385c3f41a Mon Sep 17 00:00:00 2001 From: lidongyang <506508008@qq.com> Date: Thu, 12 Feb 2026 05:19:55 +0800 Subject: [PATCH 2/2] =?UTF-8?q?1=E3=80=81=E7=8E=B0=E5=9C=BA=E9=97=AE?= =?UTF-8?q?=E9=A2=98=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/impl/DemandServiceImpl.java | 58 ++++++++++-- .../impl/LyricInternalServiceImpl.java | 90 +++++++++++-------- .../project/service/impl/NodeServiceImpl.java | 2 +- .../impl/SimulationRunServiceImpl.java | 49 ++++++---- .../project/service/impl/TaskServiceImpl.java | 2 +- .../mapper/SimulationDemandMapper.xml | 2 +- .../resources/mapper/SimulationTaskMapper.xml | 2 +- 7 files changed, 144 insertions(+), 61 deletions(-) diff --git a/project/src/main/java/com/sdm/project/service/impl/DemandServiceImpl.java b/project/src/main/java/com/sdm/project/service/impl/DemandServiceImpl.java index b0c795b2..49f07d42 100644 --- a/project/src/main/java/com/sdm/project/service/impl/DemandServiceImpl.java +++ b/project/src/main/java/com/sdm/project/service/impl/DemandServiceImpl.java @@ -101,7 +101,12 @@ public class DemandServiceImpl extends BaseService implements IDemandService { public SdmResponse addDemand(SpdmAddDemandReq req) { Long tenantId = ThreadLocalContext.getTenantId(); Long jobNumber = ThreadLocalContext.getUserId(); - req.setCreator(jobNumber); + String workNo = ThreadLocalContext.getJobNumber(); + if (isConvertibleToLong(workNo)) { + req.setCreator(Long.valueOf(workNo)); + }else { + req.setCreator(jobNumber); + } log.info("新增需求时,当前租户id为:{},工号为:{}", tenantId, jobNumber); // 获取仿真负责人 String pMemberList = req.getPMemberList(); @@ -433,10 +438,19 @@ public class DemandServiceImpl extends BaseService implements IDemandService { return SdmResponse.success(); } + public static String removeLeadingZeros(String jobNumber) { + if (StringUtils.isNotBlank(jobNumber)) { + return ""; + } + String trimmed = jobNumber.replaceAll("^0+",""); + return trimmed.isEmpty() ? "0" : trimmed; + } + @Override public SdmResponse list(SpdmDemandListReq req) { Long tenantId = ThreadLocalContext.getTenantId(); - Long jobNumber = ThreadLocalContext.getUserId(); + String jobNumber = removeLeadingZeros(ThreadLocalContext.getJobNumber()); + Long currentUserId = ThreadLocalContext.getUserId(); if (ObjectUtils.isEmpty(tenantId) || ObjectUtils.isEmpty(jobNumber)) { log.error("公司和工号都不能为空"); return SdmResponse.failed("公司和工号都不能为空"); @@ -461,10 +475,10 @@ public class DemandServiceImpl extends BaseService implements IDemandService { } if (type == 0) { // 创建人是当前用户 - demandList = demandList.stream().filter(demand -> jobNumber.equals(demand.getCreator())).toList(); + demandList = demandList.stream().filter(demand -> jobNumber.equals(String.valueOf(demand.getCreator()))).toList(); } else { // 仿真负责人是当前用户 - List pDemandMemberVoList = demandMemberVoList.stream().filter(member -> MemberTypeEnum.PRINCIPAL.getCode().equals(member.getType()) && Long.valueOf(jobNumber).equals(member.getUserId())).toList(); + List pDemandMemberVoList = demandMemberVoList.stream().filter(member -> MemberTypeEnum.PRINCIPAL.getCode().equals(member.getType()) && currentUserId.equals(member.getUserId())).toList(); if (CollectionUtils.isNotEmpty(pDemandMemberVoList)) { List myDemandIdList = pDemandMemberVoList.stream().map(SpdmDemandMemberVo::getDemandId).toList(); demandList = demandList.stream().filter(demand -> myDemandIdList.contains(demand.getUuid())).toList(); @@ -1208,12 +1222,46 @@ public class DemandServiceImpl extends BaseService implements IDemandService { return SdmResponse.success(demandVoList); } + /** + * 判断字符串是否可以安全转换为Long类型 + * @param str 待校验的字符串 + * @return true-可以转换,false-不可以转换 + */ + public static boolean isConvertibleToLong(String str) { + // 1. 处理null、空字符串、全空格字符串 + if (str == null || str.trim().isEmpty()) { + return false; + } + String trimmedStr = str.trim(); + + // 2. 正则校验数字格式(支持正负号,纯数字) + // 正则说明:^-? 匹配开头的负号(可选);\\d+ 匹配1个及以上数字;$ 匹配结尾 + if (!trimmedStr.matches("^-?\\d+$")) { + return false; + } + + // 3. 校验数值范围,避免溢出 + try { + // 直接调用Long.parseLong,利用其自带的范围校验 + Long.parseLong(trimmedStr); + return true; + } catch (NumberFormatException e) { + // 捕获数值超出Long范围的异常 + return false; + } + } + @Transactional @Override public SdmResponse addDemandNoPermission(SpdmAddDemandReq req) { Long tenantId = ThreadLocalContext.getTenantId(); Long jobNumber = ThreadLocalContext.getUserId(); - req.setCreator(jobNumber); + String workNo = ThreadLocalContext.getJobNumber(); + if (isConvertibleToLong(workNo)) { + req.setCreator(Long.valueOf(workNo)); + }else { + req.setCreator(jobNumber); + } log.info("新增需求时(无权限校验),当前租户id为:{},工号为:{}", tenantId, jobNumber); // 获取仿真负责人 String pMemberList = req.getPMemberList(); 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 b86c7bcb..7e0f1f39 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 @@ -405,7 +405,7 @@ public class LyricInternalServiceImpl implements ILyricInternalService { try { String demandUuid = RandomUtil.generateString(UUID_LENGTH); // 1. 构建需求基础参数 + 成员 + 权限 - SpdmAddDemandReq demandReq = buildDemandReq(todo, demandUuid, curDateStr); + SpdmAddDemandReq demandReq = buildDemandReq(todo, demandUuid, curDateStr,tenantId,usernameToUserIdMap); List memberList = buildDemandMemberList(todo, demandUuid, jobNumber, curDateStr); List demandExtraList = buildDemandExtraList(todo, demandUuid, jobNumber, curDateStr); // 2. 构建权限更新参数 @@ -478,7 +478,9 @@ public class LyricInternalServiceImpl implements ILyricInternalService { */ private SpdmAddDemandReq buildDemandReq(LyricVTodoEmulationInfoDM todo, String demandUuid, - String curDateStr) { + String curDateStr, + Long tenantId, + Map usernameToUserIdMap) { SpdmAddDemandReq req = new SpdmAddDemandReq(); req.setUuid(demandUuid); req.setDemandName(todo.getSubject()); @@ -492,7 +494,13 @@ public class LyricInternalServiceImpl implements ILyricInternalService { req.setEndTime(todo.getClosedTime()); req.setCreateTime(curDateStr); req.setDemandSource(SYNC_PROJECT_SOURCE); - req.setCreator(Long.valueOf(todo.getIntroduceBy())); + if (isConvertibleToInt(todo.getIntroduceBy())) { + req.setCreator(Long.valueOf(todo.getIntroduceBy())); + }else { + req.setCreator(usernameToUserIdMap.get(todo.getIntroduceBy())); + } + req.setTenantId(tenantId); + // 补充项目/阶段/工位ID fillProjectPhaseWorkspaceId(req, todo); @@ -503,20 +511,18 @@ public class LyricInternalServiceImpl implements ILyricInternalService { * 填充需求的项目/阶段/工位ID */ private void fillProjectPhaseWorkspaceId(SpdmAddDemandReq req, LyricVTodoEmulationInfoDM todo) { - List allNodeList = nodeService.lambdaQuery() + SimulationNode projectNode = nodeService.lambdaQuery() .in(SimulationNode::getNodeCode, Arrays.asList(todo.getProject(), todo.getProjectStage(), todo.getStationNum())) - .list(); + .one(); - if (CollectionUtils.isEmpty(allNodeList)) { + if (ObjectUtils.isEmpty(projectNode)) { return; } // 填充需求的项目ID - allNodeList.stream() - .filter(node -> NodeTypeEnum.PROJECT.getValue().equals(node.getNodeType()) - && node.getNodeCode().equals(todo.getProject())) - .findFirst() - .ifPresent(node -> req.setProjectId(node.getUuid())); + req.setProjectId(projectNode.getUuid()); + + List allNodeList = nodeService.lambdaQuery().eq(SimulationNode::getTag1, projectNode.getUuid()).list(); // 填充需求的阶段ID allNodeList.stream() @@ -694,13 +700,17 @@ public class LyricInternalServiceImpl implements ILyricInternalService { try { demandMapper.addDemand(demandReq, tenantId, demandReq.getCreator()); if (CollectionUtils.isNotEmpty(memberList)) { + List normalMemberList = new ArrayList<>(); for (SpdmDemandRelateMemberReq member : memberList) { - Long cidUserId = usernameToUserIdMap.get(String.valueOf(member.getUserId())); - if (cidUserId != null) { - member.setUserId(cidUserId); + Long cidUserId = usernameToUserIdMap.get(member.getUserIdStr()); + if (cidUserId == null) { + log.info("工号为:{}的用户未查询到用户id", member.getUserIdStr()); + continue; } + member.setUserId(cidUserId); + normalMemberList.add(member); } - demandMapper.addDemandMember(memberList); + demandMapper.addDemandMember(normalMemberList); } if (CollectionUtils.isNotEmpty(demandExtraList)) { demandMapper.addDemandExtra(demandExtraList); @@ -2238,10 +2248,12 @@ public class LyricInternalServiceImpl implements ILyricInternalService { // 关联的项目未在系统 // 取项目视图、工位相关视图构建项目树信息(只同步当前阶段)创建任务(不创建任务文件夹,等下发时进行创建) if (CollectionUtils.isNotEmpty(noRelatedProjectVTodoEmulationInfoDMList)) { - SdmResponse response = httpSyncHandleNoRelatedProjectTodo(noRelatedProjectVTodoEmulationInfoDMList, tenantId, jobNumber); - log.info("httpSyncHandleNoRelatedProjectTodo响应值为:{}",response); - if (!response.isSuccess()) { - return response; + List spdmProjectNodeEditReqList = httpSyncHandleNoRelatedProjectTodo(noRelatedProjectVTodoEmulationInfoDMList, tenantId, jobNumber); + log.info("httpSyncHandleNoRelatedProjectTodo响应值为:{}",spdmProjectNodeEditReqList); + for (SpdmProjectNodeEditReq spdmProjectNodeEditReq : spdmProjectNodeEditReqList) { + SimulationNode simulationNode = new SimulationNode(); + BeanUtils.copyProperties(spdmProjectNodeEditReq,simulationNode); + projectNodeList.add(simulationNode); } } @@ -2252,57 +2264,61 @@ public class LyricInternalServiceImpl implements ILyricInternalService { return response; } - private SdmResponse httpSyncHandleNoRelatedProjectTodo(List noRelatedProjectVTodoEmulationInfoDMList, Long tenantId, Long jobNumber) { - CompletableFuture syncHandleNoRelatedProjectTodoFeature = CompletableFuture.supplyAsync(() -> + private List httpSyncHandleNoRelatedProjectTodo(List noRelatedProjectVTodoEmulationInfoDMList, Long tenantId, Long jobNumber) { + CompletableFuture> syncHandleNoRelatedProjectTodoFeature = CompletableFuture.supplyAsync(() -> handleNoRelatedProjectTodo(noRelatedProjectVTodoEmulationInfoDMList, tenantId, jobNumber)); try { - SdmResponse sdmResponse = syncHandleNoRelatedProjectTodoFeature.get(syncProjectDataWaitSeconds, TimeUnit.SECONDS); - return sdmResponse; + List spdmProjectNodeEditReqList = syncHandleNoRelatedProjectTodoFeature.get(syncProjectDataWaitSeconds, TimeUnit.SECONDS); + return spdmProjectNodeEditReqList; } catch (InterruptedException e) { log.error("同步项目信息异常终止:{}", e.getMessage()); - return SdmResponse.failed("同步项目信息异常终止"); + return new ArrayList<>(); } catch (ExecutionException e) { log.error("同步项目信息执行错误:{}", e.getMessage()); - return SdmResponse.failed("同步项目信息执行出错误"); + return new ArrayList<>(); } catch (TimeoutException e) { log.warn("同步项目信息执行超时:{}", e.getMessage()); - return SdmResponse.success("同步项目信息执行中,请稍后"); + return new ArrayList<>(); } catch (Exception e) { log.error("同步项目信息未知错误:{}", e.getMessage()); - return SdmResponse.failed("同步项目信息未知错误"); + return new ArrayList<>(); } } - private SdmResponse handleNoRelatedProjectTodo(List noRelatedProjectVTodoEmulationInfoDMList, Long tenantId, Long jobNumber) { + private List handleNoRelatedProjectTodo(List noRelatedProjectVTodoEmulationInfoDMList, Long tenantId, Long jobNumber) { // 尝试获取锁(立即返回,不等待) if (!syncTodoInfoProjectLock.tryLock()) { - return SdmResponse.success("有数据同步任务(同步项目信息)正在执行中,请稍后再试"); + return new ArrayList<>(); } // 取项目视图、工位相关视图构建项目树信息(只同步当前阶段) // 根据待办获取所有项目编号 + List spdmProjectNodeEditReqList = new ArrayList<>(); try { List projectNumList = noRelatedProjectVTodoEmulationInfoDMList.stream().map(LyricVTodoEmulationInfoDM::getProject) .filter(StringUtils::isNotBlank).distinct().toList(); if (CollectionUtils.isEmpty(projectNumList)) { log.info("projectNumList为空"); - return SdmResponse.success("projectNumList为空"); + return new ArrayList<>(); } // 根据项目编号查询项目视图获取项目信息 List lyricVProjectToDMList = lyricVProjectToDmService.lambdaQuery().in(LyricVProjectToDM::getProjectNum, projectNumList).list(); if (CollectionUtils.isEmpty(lyricVProjectToDMList)) { log.info("lyricVProjectToDMList为空"); - return SdmResponse.success("lyricVProjectToDMList为空"); + return new ArrayList<>(); } for (LyricVProjectToDM lyricVProjectToDM : lyricVProjectToDMList) { - buildProjectForTodoInfo(lyricVProjectToDM, tenantId, jobNumber); + SpdmProjectNodeEditReq spdmProjectNodeEditReq = buildProjectForTodoInfo(lyricVProjectToDM, tenantId, jobNumber); + if (spdmProjectNodeEditReq != null) { + spdmProjectNodeEditReqList.add(spdmProjectNodeEditReq); + } } }catch (Exception e) { log.error("handleNoRelatedProjectTodo 未知 error: {}", e.getMessage()); - return SdmResponse.failed(); + return new ArrayList<>(); } finally { syncTodoInfoProjectLock.unlock(); } - return SdmResponse.success(); + return spdmProjectNodeEditReqList; } public static String getTagProperty(Object obj, String propertyName) throws Exception { @@ -2570,7 +2586,7 @@ public class LyricInternalServiceImpl implements ILyricInternalService { log.info("创建节点时,调用批量创建文件夹的返回值为:{}", response); } - private void buildProjectForTodoInfo(LyricVProjectToDM lyricVProjectToDM, Long tenantId, Long jobNumber) { + private SpdmProjectNodeEditReq buildProjectForTodoInfo(LyricVProjectToDM lyricVProjectToDM, Long tenantId, Long jobNumber) { String curDateStr = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()); List currentNodeList; List addNodeList = new ArrayList<>(); @@ -2734,7 +2750,7 @@ public class LyricInternalServiceImpl implements ILyricInternalService { } if (nodeMapper.addNodeBatch(addNodeList) <= 0) { - return ; + return null; } // 保存拓展字段 @@ -2874,6 +2890,8 @@ public class LyricInternalServiceImpl implements ILyricInternalService { SdmResponse response = dataFeignClient.batchUpdatePermission(batchReq); log.info("同步待办拉取项目时,批量更新权限结果为:{}",response); } + + return spdmProjectNodeEditReq; } diff --git a/project/src/main/java/com/sdm/project/service/impl/NodeServiceImpl.java b/project/src/main/java/com/sdm/project/service/impl/NodeServiceImpl.java index eb4bc2a1..babf63e8 100644 --- a/project/src/main/java/com/sdm/project/service/impl/NodeServiceImpl.java +++ b/project/src/main/java/com/sdm/project/service/impl/NodeServiceImpl.java @@ -393,8 +393,8 @@ public class NodeServiceImpl extends ServiceImpl taskIdList = taskNodePoList.stream().map(SimulationTask::getUuid).toList(); + taskService.lambdaUpdate().in(SimulationTask::getUuid,taskIdList).remove(); nodeMapper.deleteTaskExtraBatch(taskIdList); nodeMapper.deleteTaskMemberBatch(taskIdList); // 删除当前节点及子节点下的指标相关信息 diff --git a/project/src/main/java/com/sdm/project/service/impl/SimulationRunServiceImpl.java b/project/src/main/java/com/sdm/project/service/impl/SimulationRunServiceImpl.java index 90433691..ee415875 100644 --- a/project/src/main/java/com/sdm/project/service/impl/SimulationRunServiceImpl.java +++ b/project/src/main/java/com/sdm/project/service/impl/SimulationRunServiceImpl.java @@ -81,6 +81,7 @@ import java.nio.file.StandardCopyOption; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.util.*; +import java.util.function.Function; import java.util.stream.Collectors; import static com.sdm.common.service.BaseService.generateUuid; @@ -249,13 +250,7 @@ public class SimulationRunServiceImpl extends ServiceImpl currentCidUserResp = sysUserFeignClient.queryUserDetail(UserQueryReq.builder().userId(userId).build()); - if (ObjectUtils.isEmpty(currentCidUserResp.getData())) { - log.error("根据userId:{},未查询到用户", userId); - return ; - } - Long curUserId = currentCidUserResp.getData().getUserId(); + Long curUserId = ThreadLocalContext.getUserId(); // 查询当前节点下任务 List currentNodeAssociatedTaskList = new ArrayList<>(); int currentNodeDepth = getCurrentNodeDepth(projectNodePo); @@ -309,19 +304,41 @@ public class SimulationRunServiceImpl extends ServiceImpl> cidUserResp = sysUserFeignClient.listUserByIds(UserQueryReq.builder().userIds(memberList.stream().map(SimulationTaskMember::getUserId).toList()).build()); + if (ObjectUtils.isEmpty(cidUserResp)) { + return; + } + List cidUserRespList = cidUserResp.getData(); + if (CollectionUtils.isEmpty(cidUserRespList)) { + return; + } + Map cidUserMap = cidUserRespList.stream().collect(Collectors.toMap(CIDUserResp::getUserId, Function.identity())); // 查询当前任务的负责人和执行人 for (TaskNodePo taskNodePo : currentNodeAssociatedTaskList) { - if (CollectionUtils.isNotEmpty(memberList)) { - List eUserIdList = memberList.stream().filter(member -> MemberTypeEnum.EXECUTOR.getCode().equals(member.getType())).map(SimulationTaskMember::getUserId).distinct().toList(); - List pUserIdList = memberList.stream().filter(member -> MemberTypeEnum.PRINCIPAL.getCode().equals(member.getType())).map(SimulationTaskMember::getUserId).distinct().toList(); - if (CollectionUtils.isNotEmpty(eUserIdList)) { - SdmResponse> cidUserResp = sysUserFeignClient.listUserByIds(UserQueryReq.builder().userIds(eUserIdList).build()); - taskNodePo.setEMemberList(cidUserResp.getData()); + List eUserIdList = memberList.stream().filter(member -> MemberTypeEnum.EXECUTOR.getCode().equals(member.getType()) && taskNodePo.getUuid().equals(member.getTaskId())).map(SimulationTaskMember::getUserId).distinct().toList(); + List pUserIdList = memberList.stream().filter(member -> MemberTypeEnum.PRINCIPAL.getCode().equals(member.getType()) && taskNodePo.getUuid().equals(member.getTaskId())).map(SimulationTaskMember::getUserId).distinct().toList(); + if (CollectionUtils.isNotEmpty(eUserIdList)) { + List eUserList = new ArrayList<>(); + for (Long eUserId : eUserIdList) { + CIDUserResp eCidUser = cidUserMap.get(eUserId); + if (ObjectUtils.isEmpty(eCidUser)) { + continue; + } + eUserList.add(eCidUser); } - if (CollectionUtils.isNotEmpty(pUserIdList)) { - SdmResponse> cidUserResp = sysUserFeignClient.listUserByIds(UserQueryReq.builder().userIds(pUserIdList).build()); - taskNodePo.setPMemberList(cidUserResp.getData()); + taskNodePo.setEMemberList(eUserList); + } + + if (CollectionUtils.isNotEmpty(pUserIdList)) { + List pUserList = new ArrayList<>(); + for (Long eUserId : pUserIdList) { + CIDUserResp pCidUser = cidUserMap.get(eUserId); + if (ObjectUtils.isEmpty(pCidUser)) { + continue; + } + pUserList.add(pCidUser); } + taskNodePo.setPMemberList(pUserList); } } } diff --git a/project/src/main/java/com/sdm/project/service/impl/TaskServiceImpl.java b/project/src/main/java/com/sdm/project/service/impl/TaskServiceImpl.java index 7ff6f1db..a3170257 100644 --- a/project/src/main/java/com/sdm/project/service/impl/TaskServiceImpl.java +++ b/project/src/main/java/com/sdm/project/service/impl/TaskServiceImpl.java @@ -295,7 +295,7 @@ public class TaskServiceImpl implements ITaskService { List demandVoList = demandMapper.getDemandListById(demandIdList); demandMap = demandVoList.stream() .collect(Collectors.toMap(SpdmDemandVo::getUuid, Function.identity())); - demandSubmitMap = demandVoList.stream() + demandSubmitMap = demandVoList.stream().filter(spdmDemandVo -> ObjectUtils.isNotEmpty(spdmDemandVo.getCreator())) .collect(Collectors.toMap(SpdmDemandVo::getUuid, SpdmDemandVo::getCreator)); } diff --git a/project/src/main/resources/mapper/SimulationDemandMapper.xml b/project/src/main/resources/mapper/SimulationDemandMapper.xml index 0f2d4b03..00e3713b 100644 --- a/project/src/main/resources/mapper/SimulationDemandMapper.xml +++ b/project/src/main/resources/mapper/SimulationDemandMapper.xml @@ -8,7 +8,7 @@ insert into simulation_demand (uuid,demand_name,demand_code,demand_type,sim_type,demand_status,achieve_status,progress,approval_status, begin_time,end_time,finish_time,project_id,phase_id,workspace_id,tenant_id,creator,create_time,demandSource,description,machine_id) values (#{req.uuid},#{req.demandName},#{req.demandCode},#{req.demandType},#{req.simType},#{req.demandStatus},#{req.achieveStatus},#{req.progress},#{req.approvalStatus}, - #{req.beginTime},#{req.endTime},'',#{req.projectId},#{req.phaseId},#{req.workspaceId},#{tenantId},#{jobNumber},#{req.createTime},#{req.demandSource},#{req.description},#{req.machineId}) + #{req.beginTime},#{req.endTime},'',#{req.projectId},#{req.phaseId},#{req.workspaceId},#{req.creator},#{jobNumber},#{req.createTime},#{req.demandSource},#{req.description},#{req.machineId}) diff --git a/project/src/main/resources/mapper/SimulationTaskMapper.xml b/project/src/main/resources/mapper/SimulationTaskMapper.xml index a7ea975e..f9e23cc6 100644 --- a/project/src/main/resources/mapper/SimulationTaskMapper.xml +++ b/project/src/main/resources/mapper/SimulationTaskMapper.xml @@ -36,7 +36,7 @@ insert into simulation_task_extra (task_id, property_name, property_value, value_type, property_class, creator, create_time) values - (#{taskExtra.taskId}}, #{taskExtra.propertyName}, #{taskExtra.propertyValue}, #{taskExtra.valueType}, #{taskExtra.propertyClass}, #{taskExtra.creator}, #{taskExtra.createTime}) + (#{taskExtra.taskId}, #{taskExtra.propertyName}, #{taskExtra.propertyValue}, #{taskExtra.valueType}, #{taskExtra.propertyClass}, #{taskExtra.creator}, #{taskExtra.createTime})