1、同步待办时,如果项目信息未同步,将项目信息也进行同步

This commit is contained in:
2026-02-09 07:10:36 +08:00
parent 4377c67cff
commit bcf3cfd84f
8 changed files with 717 additions and 48 deletions

View File

@@ -0,0 +1,20 @@
package com.sdm.project.common;
import lombok.Getter;
@Getter
public enum DemandTypeEnum {
ANIMATION("动画"),
FINITE_ELEMENT_SIMULATION("有限元仿真"),
ROBOT_SIMULATION("机器人仿真"),
LOGISTICS_SIMULATION("物流仿真");
private final String name;
DemandTypeEnum(String name) {
this.name = name;
}
}

View File

@@ -51,8 +51,8 @@ public class SimulationLyricNodeController {
@GetMapping("/optimisedGetTodoList")
@Operation(summary = "获取待办列表(优化版)", description = "获取待办列表(优化版)")
public SdmResponse optimisedGetTodoList() {
return lyricInternalService.optimisedGetTodoList("http");
public SdmResponse optimisedGetTodoList(@RequestParam(value = "startTime") @Validated String startTime,@RequestParam(value = "endTime") @Validated String endTime) {
return lyricInternalService.optimisedGetTodoList("http",startTime,endTime);
}
@GetMapping("/getProjectList")

View File

@@ -8,6 +8,7 @@ import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
import java.util.Set;
@Mapper
public interface SimulationDemandMapper extends BaseMapper<SimulationDemand> {
@@ -42,6 +43,8 @@ public interface SimulationDemandMapper extends BaseMapper<SimulationDemand> {
List<SpdmDemandVo> getAllList();
Set<String> getAllCodeList();
List<SpdmDemandVo> getDemandListWithCondition(@Param("req") DemandQryReq req);
}

View File

@@ -52,5 +52,5 @@ public interface ILyricInternalService {
SdmResponse listNoPermission(SpdmNodeListReq req);
SdmResponse optimisedGetTodoList(String http);
SdmResponse optimisedGetTodoList(String http,String startTime,String endTime);
}

View File

@@ -31,6 +31,7 @@ import com.sdm.outbridge.mode.LyricExceptionModel;
import com.sdm.outbridge.mode.SimulationTaskSyncExBo;
import com.sdm.outbridge.service.lyric.*;
import com.sdm.project.common.ApprovalStatusEnum;
import com.sdm.project.common.DemandTypeEnum;
import com.sdm.project.common.MemberTypeEnum;
import com.sdm.project.common.generator.UniqueFileNameGenerator;
import com.sdm.project.dao.SimulationDemandMapper;
@@ -71,6 +72,8 @@ import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.*;
import java.util.concurrent.locks.ReentrantLock;
@@ -102,6 +105,9 @@ public class LyricInternalServiceImpl implements ILyricInternalService {
// 同步待办锁
private final ReentrantLock syncTodoInfoLock = new ReentrantLock();
// 同步待办关联的项目锁
private final ReentrantLock syncTodoInfoProjectLock = new ReentrantLock();
@Autowired
private LyricIntegrateService lyricIntegrateService;
@@ -157,6 +163,9 @@ public class LyricInternalServiceImpl implements ILyricInternalService {
@Value("${lyric.syncTodoDataWaitSeconds:3}")
private Long syncTodoDataWaitSeconds;
@Value("${lyric.syncProjectDataWaitSeconds:5}")
private Long syncProjectDataWaitSeconds;
@Autowired
private SimulationTaskMapper simulationTaskMapper;
@@ -173,6 +182,12 @@ public class LyricInternalServiceImpl implements ILyricInternalService {
@Value("${lyric.syncException.batchSize:100}")
private Integer batchSize;
private static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
// 同步待办时,查询待办的最大时间间隔,单位:天
// @Value("${lyricTodoInterval:7}")
// private int lyricTodoInterval;
/**
* 判断字符串是否可以安全转换为Long类型
*
@@ -323,8 +338,8 @@ public class LyricInternalServiceImpl implements ILyricInternalService {
* 核心同步逻辑:构建数据并执行批量操作
*/
private SdmResponse syncTodoData(List<SimulationNode> projectNodeList,
List<LyricVTodoEmulationInfoDM> todoInfoList,String traceId) {
if(StringUtils.isNotBlank(traceId)){
List<LyricVTodoEmulationInfoDM> todoInfoList, String traceId) {
if (StringUtils.isNotBlank(traceId)) {
MdcUtil.putTraceId(traceId);
}
// 尝试获取锁(立即返回,不等待)
@@ -375,7 +390,7 @@ public class LyricInternalServiceImpl implements ILyricInternalService {
SpdmAddDemandReq demandReq = buildDemandReq(todo, demandUuid, curDateStr);
List<SpdmDemandRelateMemberReq> memberList = buildDemandMemberList(todo, demandUuid, jobNumber, curDateStr);
// 2. 构建权限更新参数
buildPermissionReqList(demandUuid, jobNumber, todo, updatePermissionList,usernameToUserIdMap);
buildPermissionReqList(demandUuid, jobNumber, todo, updatePermissionList, usernameToUserIdMap);
// 3. 构建需求文件夹节点
demandDirNodeList.add(buildDemandDirNode(demandUuid, projectNode, demandReq.getDemandName()));
// 4. 异步保存需求数据
@@ -398,17 +413,17 @@ public class LyricInternalServiceImpl implements ILyricInternalService {
// 执行批量操作
executeBatchOperations(createDirItemList, updatePermissionList);
if(CollectionUtils.isNotEmpty(demandToCreateTaskList)){
if (CollectionUtils.isNotEmpty(demandToCreateTaskList)) {
simulationTaskService.batchCreateTaskFromDemand(demandToCreateTaskList);
}
return SdmResponse.success();
} catch (Exception e) {
log.error("syncTodoData 未知 error: {}", e.getMessage());
return SdmResponse.failed();
}finally {
return SdmResponse.failed();
} finally {
syncTodoInfoLock.unlock();
if(StringUtils.isNotBlank(traceId)){
if (StringUtils.isNotBlank(traceId)) {
MdcUtil.removeTraceId();
}
}
@@ -572,7 +587,7 @@ public class LyricInternalServiceImpl implements ILyricInternalService {
req.setUserId(userId);
req.setUuid(uuid);
Map<Long, Byte> permissions = new HashMap<>();
if (MemberTypeEnum.PRINCIPAL.getCode().equals(type) || MemberTypeEnum.EXECUTOR.getCode().equals(type)) {
if (MemberTypeEnum.PRINCIPAL.getCode().equals(type) || MemberTypeEnum.EXECUTOR.getCode().equals(type)) {
permissions.put(userId, FilePermissionEnum.BASE.getValue());
} else {
permissions.put(userId, FilePermissionEnum.ALL.getValue());
@@ -628,7 +643,7 @@ public class LyricInternalServiceImpl implements ILyricInternalService {
} catch (Exception e) {
log.error("异步保存需求[{}]数据异常: ", demandReq.getDemandCode(), e);
}
},projectTaskThreadPoolExecutor);
}, projectTaskThreadPoolExecutor);
}
/**
@@ -641,26 +656,26 @@ public class LyricInternalServiceImpl implements ILyricInternalService {
// project的uuidcreateDirItemList中每一项project的uuid都一样取第一个即可
String projectNodeId = createDirItemList.get(0).getParentDirNodeInfo().getUuId();
if (StringUtils.isBlank(projectNodeId)) {
log.error("projectNodeId为空createDirItemList{}",createDirItemList);
log.error("projectNodeId为空createDirItemList{}", createDirItemList);
return;
}
SdmResponse<FileMetadataInfoResp> fileMetadataInfoResp = dataFeignClient.queryFileMetadataInfo(projectNodeId, NodeTypeEnum.PROJECT.getValue(), 0L);
if (fileMetadataInfoResp.getData() == null) {
log.error("fileMetadataInfoResp为空,projectNodeId为{}",projectNodeId);
log.error("fileMetadataInfoResp为空,projectNodeId为{}", projectNodeId);
return;
}
// 查询需求附件的uuid元数据表中【parentId是project的元数据主键id且originalName为需求附件】
FileMetadataInfoResp projectMetadataInfo = fileMetadataInfoResp.getData();
SdmResponse<List<FileMetadataInfoResp>> listSdmResponse = dataFeignClient.listDir(DirTypeEnum.PROJECT_NODE_DIR.getValue(), projectMetadataInfo.getId());
if (!listSdmResponse.isSuccess() || CollectionUtils.isEmpty(listSdmResponse.getData())) {
log.error("listSdmResponse为空,project的元数据主键id为{}",projectMetadataInfo.getId());
log.error("listSdmResponse为空,project的元数据主键id为{}", projectMetadataInfo.getId());
return;
}
List<FileMetadataInfoResp> childrenMetadataInfoList = listSdmResponse.getData();
FileMetadataInfoResp demandAttachFileMetadataInfoResp = childrenMetadataInfoList.stream().filter(metadataInfo -> AttachFileTypeEnum.DEMAND_FILE.getValue().equals(metadataInfo.getOriginalName())).findFirst().orElse(null);
Long demandAttachFileMetadataInfoId;
if (ObjectUtils.isEmpty(demandAttachFileMetadataInfoResp)) {
log.info("未查询到需求附件文件夹,当前项目下的子文件夹为:{}",childrenMetadataInfoList);
log.info("未查询到需求附件文件夹,当前项目下的子文件夹为:{}", childrenMetadataInfoList);
// 项目层级文件夹和需求文件夹中,新增一层【需求附件】文件夹
List<FolderItemReq> demandAttachFolderItemReqList = new ArrayList<>();
BatchCreateNormalDirReq demandAttachBatchCreateNormalDirReq = new BatchCreateNormalDirReq();
@@ -697,7 +712,7 @@ public class LyricInternalServiceImpl implements ILyricInternalService {
}
// 需求附件文件夹的元数据主键id
demandAttachFileMetadataInfoId = successList.get(0).getId();
}else {
} else {
demandAttachFileMetadataInfoId = demandAttachFileMetadataInfoResp.getId();
}
for (BatchCreateDirItem batchCreateDirItem : createDirItemList) {
@@ -720,7 +735,6 @@ public class LyricInternalServiceImpl implements ILyricInternalService {
}
// 批量更新权限
if (CollectionUtils.isNotEmpty(updatePermissionList)) {
List<BatchUpdatePermissionReq.FilePermissionItem> filePermissions = new ArrayList<>();
@@ -779,8 +793,8 @@ public class LyricInternalServiceImpl implements ILyricInternalService {
}
// 4. 构建同步数据并执行批量操作
return (Objects.equals("http",from)) ? httpSyncTodoData(projectNodeList, todoInfoList):
syncTodoData(projectNodeList, todoInfoList,"");
return (Objects.equals("http", from)) ? httpSyncTodoData(projectNodeList, todoInfoList) :
syncTodoData(projectNodeList, todoInfoList, "");
}
@@ -1420,7 +1434,7 @@ public class LyricInternalServiceImpl implements ILyricInternalService {
} catch (MyBatisSystemException ex) {
// 查询发生异常,记录异常日志(可能是测试环境预期异常)
log.warn("查询EP项目列表时发生异常可能是测试环境预期异常项目编号{},项目名称:{},项目类型:{},异常信息:{}",
req.getProjectNum(),req.getProjectName(),req.getDifficultyType(), ex.getMessage());
req.getProjectNum(), req.getProjectName(), req.getDifficultyType(), ex.getMessage());
}
PageInfo<LyricVProjectToDM> page = new PageInfo<>(projectList);
return PageUtils.getJsonObjectSdmResponse(projectList, page);
@@ -1497,7 +1511,7 @@ public class LyricInternalServiceImpl implements ILyricInternalService {
throw new RuntimeException(e);
}
}
},projectTaskThreadPoolExecutor);
}, projectTaskThreadPoolExecutor);
nodeService.lambdaUpdate().set(SimulationNode::getApprovalStatus, String.valueOf(ApprovalStatusEnum.ING.getCode()))
.eq(SimulationNode::getNodeCode, req.getWorkspaceCode())
.eq(SimulationNode::getNodeType, NodeTypeEnum.WORKSPACE.getValue())
@@ -1686,7 +1700,7 @@ public class LyricInternalServiceImpl implements ILyricInternalService {
} catch (Exception e) {
throw new RuntimeException(e);
}
}else {
} else {
try {
// entry.getValue() = "uuid1,uuid2"
setTagProperty(addNode, preTag, entry.getValue());
@@ -1732,9 +1746,9 @@ public class LyricInternalServiceImpl implements ILyricInternalService {
Map<Long, Byte> userPermissions = new HashMap<>();
userPermissions.put(userId, FilePermissionEnum.ALL.getValue());
updatePermissionReq.setUserPermissions(userPermissions);
log.info("syncPhase更新用户权限的参数为{}",updatePermissionReq);
log.info("syncPhase更新用户权限的参数为{}", updatePermissionReq);
SdmResponse updatePermissionResponse = dataFeignClient.updatePermission(updatePermissionReq);
log.info("syncPhase更新用户权限的返回值为{}",updatePermissionResponse);
log.info("syncPhase更新用户权限的返回值为{}", updatePermissionResponse);
return SdmResponse.success(true);
}
@@ -1771,10 +1785,11 @@ public class LyricInternalServiceImpl implements ILyricInternalService {
/**
* 构建规范的分页返回结果,保证返回格式统一
*
* @param current 当前页
* @param size 页大小
* @param total 总条数
* @param data 分页数据
* @param size 页大小
* @param total 总条数
* @param data 分页数据
* @return 标准分页JSON
*/
private JSONObject buildPageResult(int current, int size, long total, List<LyricVProjectResourcePlanDM> data) {
@@ -1788,14 +1803,15 @@ public class LyricInternalServiceImpl implements ILyricInternalService {
/**
* 查询项目参与人员
*
* @param projectId 项目的uuid
* @param queryType 区分人员状态的标识为空代表查询所有状态的人员0存在, 1删除 , 2冻结
* @param current 当前页码从1开始
* @param size 每页展示的条数
* @param current 当前页码从1开始
* @param size 每页展示的条数
* @return
*/
@Override
public SdmResponse queryProjectMember(String projectId,Integer queryType, Integer current, Integer size) {
public SdmResponse queryProjectMember(String projectId, Integer queryType, Integer current, Integer size) {
log.info("开始查询项目参与人员信息projectId{}", projectId);
// 1. 入参校验
if (StringUtils.isBlank(projectId)) {
@@ -1826,7 +1842,7 @@ public class LyricInternalServiceImpl implements ILyricInternalService {
try {
projectMemberList = lyricVProjectResourcePlanDMService.lambdaQuery().eq(LyricVProjectResourcePlanDM::getProjectId, syncProjectId)
.eq(ObjectUtils.isNotEmpty(queryType), LyricVProjectResourcePlanDM::getDelFlag, queryType).list();
}catch (Exception ex) {
} catch (Exception ex) {
// 查询发生异常,记录异常日志(可能是测试环境预期异常)
if (ex instanceof MyBatisSystemException) {
log.warn("查询项目参与人员视图发生预期异常测试环境syncProjectId{},异常信息:{}",
@@ -2049,34 +2065,655 @@ public class LyricInternalServiceImpl implements ILyricInternalService {
return SdmResponse.success(jsonObject);
}
@Override
public SdmResponse optimisedGetTodoList(String http) {
/**
* 查询固定时间内的待办数据
*/
private List<LyricVTodoEmulationInfoDM> queryTodoListWithFixedTime(String startTime, String endTime) {
// 查询原始待办数据
// TODO 这里要确认是不是只拉取有限元仿真
List<LyricVTodoEmulationInfoDM> todoInfoList = lyricVTodoInfoService.lambdaQuery()
.in(LyricVTodoEmulationInfoDM::getRelevanceTask, Arrays.asList(DemandTypeEnum.FINITE_ELEMENT_SIMULATION.getName()))
.ge(LyricVTodoEmulationInfoDM::getCreateTime, startTime)
.le(LyricVTodoEmulationInfoDM::getCreateTime, endTime)
.list();
if (CollectionUtils.isEmpty(todoInfoList)) {
log.info("未查询到{}到{}的待同步的待办数据", startTime, endTime);
return Collections.emptyList();
}
// 先查询系统内所有待办
// 过滤已同步的待办
Set<String> existDemandCodeSet = demandMapper.getAllCodeList();
if (CollectionUtils.isEmpty(existDemandCodeSet)) {
return todoInfoList;
}
List<LyricVTodoEmulationInfoDM> filterTodoList = todoInfoList.stream()
.filter(todoInfo -> !existDemandCodeSet.contains(String.valueOf(todoInfo.getTodoId())))
.collect(Collectors.toList());
return null;
if (CollectionUtils.isEmpty(filterTodoList)) {
log.info("本次手动同步到的待办都已经进行过同步");
}
return filterTodoList;
}
private SdmResponse httpSyncTodoData( List<SimulationNode> projectNodeList,List<LyricVTodoEmulationInfoDM> todoInfoList){
/**
* 根据间隔天数计算时间范围
* @param lyricTodoInterval 倒退的天数int类型
* @return 数组索引0是起始时间字符串索引1是结束时间当前时间字符串
*/
public static String[] calculateTimeRange(int lyricTodoInterval) {
// 1. 获取当前时间(精确到时分秒)
LocalDateTime currentTime = LocalDateTime.now();
// 2. 计算起始时间:当前时间向前倒退指定天数
LocalDateTime startTime = currentTime.minusDays(lyricTodoInterval);
// 3. 格式化时间为指定的字符串格式
String startTimeStr = startTime.format(DATE_TIME_FORMATTER);
String endTimeStr = currentTime.format(DATE_TIME_FORMATTER);
return new String[]{startTimeStr, endTimeStr};
}
@Override
public SdmResponse optimisedGetTodoList(String http, String startTime, String endTime) {
Long tenantId = ThreadLocalContext.getTenantId();
Long jobNumber = ThreadLocalContext.getUserId();
// 缓存校验
SdmResponse cacheCheckResponse = checkSyncCache();
if (cacheCheckResponse != null) {
return cacheCheckResponse;
}
// TODO 现场手动同步完成后,根据配置文件动态计算拉取待办的开始、结束时间
// String[] timeArray = calculateTimeRange(lyricTodoInterval);
// String startTime = timeArray[0];
// String endTime = timeArray[1];
// 先查询系统内所有待办90天内仿真类型,同步历史待办时先取startTime和endTime同步固定某段时间内的待办
List<LyricVTodoEmulationInfoDM> lyricVTodoEmulationInfoDMList = queryTodoListWithFixedTime(startTime, endTime);
// 待办信息在系统中是否都已经存在
if (CollectionUtils.isEmpty(lyricVTodoEmulationInfoDMList)) {
log.info("lyricVTodoEmulationInfoDMList为空");
return SdmResponse.success();
}
log.info("本次共同步待办:{}个",lyricVTodoEmulationInfoDMList.stream());
// 根据待办关联的项目情况,分为关联的项目已在系统和关联的项目未在系统两部分数据
List<LyricVTodoEmulationInfoDM> noRelatedProjectVTodoEmulationInfoDMList;
List<String> projectCodeList = lyricVTodoEmulationInfoDMList.stream().map(LyricVTodoEmulationInfoDM::getProject)
.filter(StringUtils::isNotBlank).distinct().collect(Collectors.toList());
if (CollectionUtils.isEmpty(projectCodeList)) {
log.info("同步到的待办的项目号都是空待办id{}", lyricVTodoEmulationInfoDMList.stream().map(LyricVTodoEmulationInfoDM::getId).collect(Collectors.toSet()));
return SdmResponse.success();
}
// 根据projectCodeList查询系统内的项目信息
List<SimulationNode> projectNodeList = nodeService.lambdaQuery().in(SimulationNode::getNodeCode, projectCodeList).list();
if (CollectionUtils.isEmpty(projectNodeList)) {
// 本次同步到的待办的关联项目都未在系统内
log.info("本次同步到的待办的关联项目都未在系统内");
noRelatedProjectVTodoEmulationInfoDMList = lyricVTodoEmulationInfoDMList;
} else {
// 本次同步到的待办的关联项目有一部分已经在系统内
log.info("本次同步到的待办的关联项目有一部分已经在系统内");
List<String> projectNodeCodeList = projectNodeList.stream().map(SimulationNode::getNodeCode).toList();
noRelatedProjectVTodoEmulationInfoDMList = lyricVTodoEmulationInfoDMList.stream().filter(lyricVTodoEmulationInfoDM -> !projectNodeCodeList.contains(lyricVTodoEmulationInfoDM.getProject())).collect(Collectors.toList());
}
// 关联的项目未在系统
// 取项目视图、工位相关视图构建项目树信息(只同步当前阶段)创建任务(不创建任务文件夹,等下发时进行创建)
if (CollectionUtils.isNotEmpty(noRelatedProjectVTodoEmulationInfoDMList)) {
SdmResponse response = httpSyncHandleNoRelatedProjectTodo(noRelatedProjectVTodoEmulationInfoDMList, tenantId, jobNumber);
log.info("httpSyncHandleNoRelatedProjectTodo响应值为{}",response);
if (!response.isSuccess()) {
return response;
}
}
// 关联的项目已在系统
// 直接关联在相应的项目下 创建任务(不创建任务文件夹,等下发时进行创建)
SdmResponse response = handleRelatedProjectTodo(projectNodeList, lyricVTodoEmulationInfoDMList);
log.info("handleRelatedProjectTodo响应值为{}",response);
return response;
}
private SdmResponse httpSyncHandleNoRelatedProjectTodo(List<LyricVTodoEmulationInfoDM> noRelatedProjectVTodoEmulationInfoDMList, Long tenantId, Long jobNumber) {
CompletableFuture<SdmResponse> syncHandleNoRelatedProjectTodoFeature = CompletableFuture.supplyAsync(() ->
handleNoRelatedProjectTodo(noRelatedProjectVTodoEmulationInfoDMList, tenantId, jobNumber));
try {
SdmResponse sdmResponse = syncHandleNoRelatedProjectTodoFeature.get(syncProjectDataWaitSeconds, TimeUnit.SECONDS);
return sdmResponse;
} catch (InterruptedException e) {
log.error("同步项目信息异常终止:{}", e.getMessage());
return SdmResponse.failed("同步项目信息异常终止");
} catch (ExecutionException e) {
log.error("同步项目信息执行错误:{}", e.getMessage());
return SdmResponse.failed("同步项目信息执行出错误");
} catch (TimeoutException e) {
log.warn("同步项目信息执行超时:{}", e.getMessage());
return SdmResponse.success("同步项目信息执行中,请稍后");
} catch (Exception e) {
log.error("同步项目信息未知错误:{}", e.getMessage());
return SdmResponse.failed("同步项目信息未知错误");
}
}
private SdmResponse handleNoRelatedProjectTodo(List<LyricVTodoEmulationInfoDM> noRelatedProjectVTodoEmulationInfoDMList, Long tenantId, Long jobNumber) {
// 尝试获取锁(立即返回,不等待)
if (!syncTodoInfoProjectLock.tryLock()) {
return SdmResponse.success("有数据同步任务(同步项目信息)正在执行中,请稍后再试");
}
// 取项目视图、工位相关视图构建项目树信息(只同步当前阶段)
// 根据待办获取所有项目编号
try {
List<String> projectNumList = noRelatedProjectVTodoEmulationInfoDMList.stream().map(LyricVTodoEmulationInfoDM::getProject)
.filter(StringUtils::isNotBlank).distinct().toList();
if (CollectionUtils.isEmpty(projectNumList)) {
log.info("projectNumList为空");
return SdmResponse.success("projectNumList为空");
}
// 根据项目编号查询项目视图获取项目信息
List<LyricVProjectToDM> lyricVProjectToDMList = lyricVProjectToDmService.lambdaQuery().in(LyricVProjectToDM::getProjectNum, projectNumList).list();
if (CollectionUtils.isEmpty(lyricVProjectToDMList)) {
log.info("lyricVProjectToDMList为空");
return SdmResponse.success("lyricVProjectToDMList为空");
}
for (LyricVProjectToDM lyricVProjectToDM : lyricVProjectToDMList) {
buildProjectForTodoInfo(lyricVProjectToDM, tenantId, jobNumber);
}
}catch (Exception e) {
log.error("handleNoRelatedProjectTodo 未知 error: {}", e.getMessage());
return SdmResponse.failed();
} finally {
syncTodoInfoProjectLock.unlock();
}
return SdmResponse.success();
}
public static String getTagProperty(Object obj, String propertyName) throws Exception {
Class<?> clazz = obj.getClass();
Field field = clazz.getDeclaredField(propertyName);
field.setAccessible(true);
return (String) field.get(obj);
}
/**
* 筛选不同类型的节点,封装为统一对象
*/
private NodeServiceImpl.NodeTypeFilterResult filterNodesByType(List<SpdmProjectNodeEditReq> addNodeList) {
SpdmProjectNodeEditReq projectNode = addNodeList.stream()
.filter(node -> NodeTypeEnum.PROJECT.getValue().equals(node.getNodeType()))
.findFirst()
.orElse(null);
List<SpdmProjectNodeEditReq> phaseNodes = addNodeList.stream()
.filter(node -> NodeTypeEnum.PHASE.getValue().equals(node.getNodeType()))
.collect(Collectors.toList());
List<SpdmProjectNodeEditReq> machineNodes = addNodeList.stream()
.filter(node -> NodeTypeEnum.MACHINE.getValue().equals(node.getNodeType()))
.collect(Collectors.toList());
List<SpdmProjectNodeEditReq> workspaceNodes = addNodeList.stream()
.filter(node -> NodeTypeEnum.WORKSPACE.getValue().equals(node.getNodeType()))
.collect(Collectors.toList());
return new NodeServiceImpl.NodeTypeFilterResult(projectNode, phaseNodes, machineNodes, workspaceNodes);
}
/**
* 仅创建单个阶段节点
*/
private void createSinglePhaseDir(List<SpdmProjectNodeEditReq> phaseNodes) {
if (CollectionUtils.isEmpty(phaseNodes)) {
log.warn("无阶段节点可创建");
return;
}
SpdmProjectNodeEditReq firstPhaseNode = phaseNodes.get(0);
createDir(firstPhaseNode.getUuid(), firstPhaseNode.getNodeType(),
firstPhaseNode.getPid(), firstPhaseNode.getNodeName());
}
/**
* 通用方法构建单个DirNodeInfo
*/
private DirNodeInfo buildDirNodeInfo(String uuid, String parentUuid, String nodeType, String dirName) {
DirNodeInfo dirNodeInfo = new DirNodeInfo();
dirNodeInfo.setUuId(uuid);
dirNodeInfo.setParentUuId(parentUuid);
dirNodeInfo.setUuIdOwnType(nodeType);
dirNodeInfo.setDirName(dirName);
return dirNodeInfo;
}
/**
* 通用方法批量构建DirNodeInfo列表
*/
private List<DirNodeInfo> buildDirNodeInfoList(List<SpdmProjectNodeEditReq> nodeList, String parentUuid, String nodeType) {
if (CollectionUtils.isEmpty(nodeList)) {
return new ArrayList<>();
}
return nodeList.stream()
.map(node -> buildDirNodeInfo(node.getUuid(), parentUuid, nodeType, node.getNodeName()))
.collect(Collectors.toList());
}
/**
* 构建项目节点的dirItem
*/
private void buildProjectDirItem(NodeServiceImpl.NodeTypeFilterResult filterResult, List<BatchCreateDirItem> createDirItemList) {
SpdmProjectNodeEditReq projectNode = filterResult.getProjectNode();
List<SpdmProjectNodeEditReq> phaseNodes = filterResult.getAddPhaseNodeList();
BatchCreateDirItem projectCreateDirItem = new BatchCreateDirItem();
DirNodeInfo projectDirNodeInfo = buildDirNodeInfo(
projectNode.getUuid(), null,
NodeTypeEnum.PROJECT.getValue(), projectNode.getNodeName()
);
projectCreateDirItem.setParentDirNodeInfo(projectDirNodeInfo);
// 构建项目下的阶段子节点
List<DirNodeInfo> phaseDirInfoList = buildDirNodeInfoList(
phaseNodes, projectNode.getUuid(), NodeTypeEnum.PHASE.getValue()
);
projectCreateDirItem.setChildDirNodeInfos(phaseDirInfoList);
createDirItemList.add(projectCreateDirItem);
}
/**
* 构建阶段节点的dirItem
*/
private BatchCreateDirItem buildPhaseDirItem(SpdmProjectNodeEditReq phaseNode, String projectUuid, List<SpdmProjectNodeEditReq> machineNodes) {
BatchCreateDirItem phaseCreateDirItem = new BatchCreateDirItem();
DirNodeInfo phaseDirNodeInfo = buildDirNodeInfo(
phaseNode.getUuid(), projectUuid,
NodeTypeEnum.PHASE.getValue(), phaseNode.getNodeName()
);
phaseCreateDirItem.setParentDirNodeInfo(phaseDirNodeInfo);
// 若无机台节点,子节点为空
List<DirNodeInfo> phaseChildDirInfoList = CollectionUtils.isEmpty(machineNodes)
? new ArrayList<>()
: buildDirNodeInfoList(
machineNodes.stream()
.filter(machineNode -> phaseNode.getUuid().equals(machineNode.getPid()))
.collect(Collectors.toList()),
phaseNode.getUuid(), NodeTypeEnum.MACHINE.getValue()
);
phaseCreateDirItem.setChildDirNodeInfos(phaseChildDirInfoList);
return phaseCreateDirItem;
}
/**
* 构建机台节点的dirItem
*/
private BatchCreateDirItem buildMachineDirItem(SpdmProjectNodeEditReq machineNode,
String phaseUuid,
List<SpdmProjectNodeEditReq> workspaceNodes) {
BatchCreateDirItem machineCreateDirItem = new BatchCreateDirItem();
DirNodeInfo machineDirNodeInfo = buildDirNodeInfo(
machineNode.getUuid(), phaseUuid,
NodeTypeEnum.MACHINE.getValue(), machineNode.getNodeName()
);
machineCreateDirItem.setParentDirNodeInfo(machineDirNodeInfo);
// 构建机台下的工位子节点
List<DirNodeInfo> workspaceDirInfoList = buildDirNodeInfoList(
workspaceNodes.stream()
.filter(workspaceNode -> machineNode.getUuid().equals(workspaceNode.getPid()))
.collect(Collectors.toList()),
machineNode.getUuid(), NodeTypeEnum.WORKSPACE.getValue()
);
machineCreateDirItem.setChildDirNodeInfos(workspaceDirInfoList);
return machineCreateDirItem;
}
/**
* 构建工位节点的dirItem
*/
private void buildWorkspaceDirItems(SpdmProjectNodeEditReq machineNode,
List<SpdmProjectNodeEditReq> currentWorkspaceNodes,
List<BatchCreateDirItem> createDirItemList) {
if (CollectionUtils.isEmpty(currentWorkspaceNodes)) {
return;
}
for (SpdmProjectNodeEditReq workspaceNode : currentWorkspaceNodes) {
BatchCreateDirItem workspaceCreateDirItem = new BatchCreateDirItem();
DirNodeInfo workspaceDirNodeInfo = buildDirNodeInfo(
workspaceNode.getUuid(), machineNode.getUuid(),
NodeTypeEnum.WORKSPACE.getValue(), workspaceNode.getNodeName()
);
workspaceCreateDirItem.setParentDirNodeInfo(workspaceDirNodeInfo);
workspaceCreateDirItem.setChildDirNodeInfos(new ArrayList<>());
createDirItemList.add(workspaceCreateDirItem);
}
}
/**
* 构建机台、工位的dirItem
*/
private void buildMachineWorkspaceDirItems(SpdmProjectNodeEditReq phaseNode,
List<SpdmProjectNodeEditReq> currentMachineNodes,
List<SpdmProjectNodeEditReq> workspaceNodes,
List<BatchCreateDirItem> createDirItemList) {
if (CollectionUtils.isEmpty(currentMachineNodes)) {
return;
}
for (SpdmProjectNodeEditReq machineNode : currentMachineNodes) {
// 构建机台节点的dirItem
BatchCreateDirItem machineCreateDirItem = buildMachineDirItem(machineNode, phaseNode.getUuid(), workspaceNodes);
createDirItemList.add(machineCreateDirItem);
// 筛选当前机台下的工位节点
List<SpdmProjectNodeEditReq> currentWorkspaceNodes = workspaceNodes.stream()
.filter(workspaceNode -> machineNode.getUuid().equals(workspaceNode.getPid()))
.collect(Collectors.toList());
// 构建工位节点的dirItem
buildWorkspaceDirItems(machineNode, currentWorkspaceNodes, createDirItemList);
}
}
/**
* 构建阶段、机台、工位的层级dirItem
*/
private void buildPhaseMachineWorkspaceDirItems(NodeServiceImpl.NodeTypeFilterResult filterResult, List<BatchCreateDirItem> createDirItemList) {
SpdmProjectNodeEditReq projectNode = filterResult.getProjectNode();
List<SpdmProjectNodeEditReq> phaseNodes = filterResult.getAddPhaseNodeList();
List<SpdmProjectNodeEditReq> machineNodes = filterResult.getAddMachineNodeList();
List<SpdmProjectNodeEditReq> workspaceNodes = filterResult.getAddWorkspaceNodeList();
if (CollectionUtils.isEmpty(phaseNodes)) {
return;
}
for (SpdmProjectNodeEditReq phaseNode : phaseNodes) {
// 构建阶段节点的dirItem
BatchCreateDirItem phaseCreateDirItem = buildPhaseDirItem(phaseNode, projectNode.getUuid(), machineNodes);
createDirItemList.add(phaseCreateDirItem);
// 筛选当前阶段下的机台节点
List<SpdmProjectNodeEditReq> currentMachineNodes = machineNodes.stream()
.filter(machineNode -> phaseNode.getUuid().equals(machineNode.getPid()))
.collect(Collectors.toList());
// 构建机台、工位的dirItem
buildMachineWorkspaceDirItems(phaseNode, currentMachineNodes, workspaceNodes, createDirItemList);
}
}
/**
* 构建批量创建文件夹请求
*/
private BatchCreateDirReq buildBatchCreateDirReq(NodeServiceImpl.NodeTypeFilterResult filterResult) {
BatchCreateDirReq batchCreateDirReq = new BatchCreateDirReq();
List<BatchCreateDirItem> createDirItemList = new ArrayList<>();
// 构建项目节点的dirItem
buildProjectDirItem(filterResult, createDirItemList);
// 构建阶段、机台、工位的层级dirItem
buildPhaseMachineWorkspaceDirItems(filterResult, createDirItemList);
batchCreateDirReq.setItems(createDirItemList);
batchCreateDirReq.setDirType(DirTypeEnum.PROJECT_NODE_DIR.getValue());
return batchCreateDirReq;
}
/**
* 构建批量创建节点文件夹的参数并调用接口
* @param addNodeList
*/
public void batchCreateNodeDir(List<SpdmProjectNodeEditReq> addNodeList) {
// 1. 分类筛选节点
NodeServiceImpl.NodeTypeFilterResult filterResult = filterNodesByType(addNodeList);
// 2. 无项目节点时,仅创建单个阶段节点
if (ObjectUtils.isEmpty(filterResult.getProjectNode())) {
createSinglePhaseDir(filterResult.getAddPhaseNodeList());
return;
}
// 3. 有项目节点时,批量构建层级化文件夹创建请求
BatchCreateDirReq batchCreateDirReq = buildBatchCreateDirReq(filterResult);
// 4. 调用批量创建接口并记录日志
callBatchCreateDirApi(batchCreateDirReq);
// 项目下新增一层【项目文件】文件夹项目文件Tab上传的文件都放到这个文件夹里
// 5. 创建项目文件夹下【项目文件】层级文件夹
BatchCreateNormalDirReq batchCreateNormalDirReq = new BatchCreateNormalDirReq();
SpdmProjectNodeEditReq projectNode = filterResult.getProjectNode();
batchCreateNormalDirReq.setParentUUId(projectNode.getUuid());
List<FolderItemReq> folderItemReqList = new ArrayList<>();
FolderItemReq folderItemReq = new FolderItemReq();
folderItemReq.setFolderName(AttachFileTypeEnum.PROJECT_FILE.getValue());
folderItemReq.setFolderUuid(RandomUtil.generateString(32));
folderItemReqList.add(folderItemReq);
batchCreateNormalDirReq.setFolderItems(folderItemReqList);
log.info("创建【项目文件】文件夹请求参数:{}", batchCreateNormalDirReq);
try {
SdmResponse response = dataFeignClient.batchCreateNormalDirs(batchCreateNormalDirReq);
log.info("创建【项目文件】文件夹响应:{}", response);
} catch (Exception e) {
log.error("创建【项目文件】文件夹接口失败", e);
}
}
/**
* 调用批量创建文件夹接口并记录日志
*/
private void callBatchCreateDirApi(BatchCreateDirReq batchCreateDirReq) {
log.info("创建节点时,调用批量创建文件夹的参数为:{}", batchCreateDirReq);
SdmResponse response = dataFeignClient.batchCreateDir(batchCreateDirReq);
log.info("创建节点时,调用批量创建文件夹的返回值为:{}", response);
}
private void buildProjectForTodoInfo(LyricVProjectToDM lyricVProjectToDM, Long tenantId, Long jobNumber) {
String curDateStr = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
List<SpdmProjectNodeEditReq> currentNodeList;
List<SpdmProjectNodeEditReq> addNodeList = new ArrayList<>();
// 构建项目——阶段——机台——工位节点树
SpdmProjectNodeEditReq spdmProjectNodeEditReq = new SpdmProjectNodeEditReq();
spdmProjectNodeEditReq.setUuid(RandomUtil.generateString(32));
spdmProjectNodeEditReq.setNodeCode(lyricVProjectToDM.getProjectNum());
spdmProjectNodeEditReq.setNodeName(lyricVProjectToDM.getProjectName());
spdmProjectNodeEditReq.setNodeType(NodeTypeEnum.PROJECT.getValue());
spdmProjectNodeEditReq.setPid("");
spdmProjectNodeEditReq.setCreateTime(curDateStr);
spdmProjectNodeEditReq.setCreator(jobNumber);
spdmProjectNodeEditReq.setTenantId(tenantId);
spdmProjectNodeEditReq.setProjectSource(SYNC_PROJECT_SOURCE);
// 根据projectId查询项目机台工位信息的视图
List<LyricVProjectStationToDM> projectStationList = new ArrayList<>();
try {
projectStationList = lyricVProjectStationToDmService.lambdaQuery()
.eq(LyricVProjectStationToDM::getProjectId, spdmProjectNodeEditReq.getProjectId())
.list();
} catch (MyBatisSystemException ex) {
// 查询发生异常,记录异常日志(可能是测试环境预期异常)
log.warn("查询项目机台工位信息的视图时发生异常可能是测试环境预期异常项目id{},异常信息:{}",
spdmProjectNodeEditReq.getProjectId(), ex.getMessage());
}
if (CollectionUtils.isNotEmpty(projectStationList)) {
// 同步EP中的节点、机台、工位到DM
// 查询当前阶段
LyricVProjectToDM lyricVProject = null;
try {
lyricVProject = lyricVProjectToDmService.lambdaQuery()
.eq(LyricVProjectToDM::getProjectNum, spdmProjectNodeEditReq.getNodeCode())
.one();
} catch (MyBatisSystemException ex) {
// 查询发生异常,记录异常日志(可能是测试环境预期异常)
log.warn("查询当前阶段时发生异常(可能是测试环境预期异常),项目编码:{},异常信息:{}",
spdmProjectNodeEditReq.getProjectId(), ex.getMessage());
}
if (ObjectUtils.isNotEmpty(lyricVProject)) {
// 当前阶段
String currentPhase = lyricVProject.getStage();
SpdmProjectNodeEditReq phaseNode = new SpdmProjectNodeEditReq();
phaseNode.setUuid(RandomUtil.generateString(32));
phaseNode.setNodeCode(currentPhase);
phaseNode.setNodeName(currentPhase);
phaseNode.setNodeType(NodeTypeEnum.PHASE.getValue());
phaseNode.setCreateTime(curDateStr);
phaseNode.setCreator(jobNumber);
phaseNode.setTenantId(tenantId);
phaseNode.setProjectSource(SYNC_PROJECT_SOURCE);
phaseNode.setPid(spdmProjectNodeEditReq.getUuid());
addNodeList.add(phaseNode);
// 机台、工位
Map<String, List<LyricVProjectStationToDM>> machineMap = projectStationList.stream().collect(Collectors.groupingBy(LyricVProjectStationToDM::getMachineNumber));
for (Map.Entry<String, List<LyricVProjectStationToDM>> machineEntry : machineMap.entrySet()) {
String machineNumber = machineEntry.getKey();
List<LyricVProjectStationToDM> projectStationByMachineNumberList = machineEntry.getValue();
SpdmProjectNodeEditReq machineNode = new SpdmProjectNodeEditReq();
machineNode.setUuid(RandomUtil.generateString(32));
machineNode.setNodeCode(machineNumber);
machineNode.setNodeName(projectStationByMachineNumberList.get(0).getMachineName());
machineNode.setNodeType(NodeTypeEnum.MACHINE.getValue());
machineNode.setCreateTime(curDateStr);
machineNode.setCreator(jobNumber);
machineNode.setTenantId(tenantId);
machineNode.setProjectSource(SYNC_PROJECT_SOURCE);
machineNode.setPid(phaseNode.getUuid());
addNodeList.add(machineNode);
for (LyricVProjectStationToDM lyricVProjectStationToDM : projectStationByMachineNumberList) {
SpdmProjectNodeEditReq workspaceNode = new SpdmProjectNodeEditReq();
workspaceNode.setUuid(RandomUtil.generateString(32));
workspaceNode.setNodeCode(lyricVProjectStationToDM.getStationNum());
workspaceNode.setNodeName(lyricVProjectStationToDM.getStationName());
workspaceNode.setNodeType(NodeTypeEnum.WORKSPACE.getValue());
workspaceNode.setCreateTime(curDateStr);
workspaceNode.setCreator(jobNumber);
workspaceNode.setTenantId(tenantId);
workspaceNode.setProjectSource(SYNC_PROJECT_SOURCE);
workspaceNode.setPid(machineNode.getUuid());
addNodeList.add(workspaceNode);
}
}
}
}
List<TaskNodeTag> tagMap = new ArrayList<>();
TaskNodeTag projectTaskNodeTag = new TaskNodeTag();
projectTaskNodeTag.setKey(NodeTypeEnum.PROJECT.getValue());
projectTaskNodeTag.setValue("tag1");
TaskNodeTag phaseTaskNodeTag = new TaskNodeTag();
phaseTaskNodeTag.setKey(NodeTypeEnum.PHASE.getValue());
phaseTaskNodeTag.setValue("tag2");
TaskNodeTag machineTaskNodeTag = new TaskNodeTag();
machineTaskNodeTag.setKey(NodeTypeEnum.MACHINE.getValue());
machineTaskNodeTag.setValue("tag4");
TaskNodeTag workspaceTaskNodeTag = new TaskNodeTag();
workspaceTaskNodeTag.setKey(NodeTypeEnum.WORKSPACE.getValue());
workspaceTaskNodeTag.setValue("tag5");
tagMap.add(projectTaskNodeTag);
tagMap.add(phaseTaskNodeTag);
tagMap.add(machineTaskNodeTag);
tagMap.add(workspaceTaskNodeTag);
for (TaskNodeTag tagReq : tagMap) {
String currentNodeType = tagReq.getKey(); // project phase
log.info("当前nodeType为{}tag为{}", currentNodeType, tagReq.getValue());
currentNodeList = addNodeList.stream().filter(node -> node.getNodeType().equals(currentNodeType)).toList(); // projectNodeList phaseNodeList
if (CollectionUtils.isEmpty(currentNodeList)) {
log.error("addNodeList中不存在{}类型的节点", currentNodeType);
continue;
}
SpdmProjectNodeEditReq eachSpdmProjectNodeEditReq;
String tagListProperty;
for (SpdmProjectNodeEditReq addNode : currentNodeList) {
if (StringUtils.isBlank(addNode.getUuid())) {
addNode.setUuid(RandomUtil.generateString(32));
}
String pid = addNode.getPid();
if (StringUtils.isBlank(pid)) {
try {
// tagReq.getValue()="Tag1"
setTagProperty(addNode, tagReq.getValue(), addNode.getUuid());
} catch (Exception e) {
throw new RuntimeException(e);
}
} else {
// 复制父节点的tag
eachSpdmProjectNodeEditReq = addNodeList.stream().filter(node -> pid.equals(node.getUuid())).findFirst().orElse(null);
if (ObjectUtils.isNotEmpty(eachSpdmProjectNodeEditReq)) {
for (int i = 1; i <= 10; i++) {
try {
tagListProperty = getTagProperty(eachSpdmProjectNodeEditReq, "tag" + i);
if (StringUtils.isBlank(tagListProperty)) {
continue;
}
setTagProperty(addNode, "tag" + i, tagListProperty);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
try {
// tagReq.getValue()="Tag1"
setTagProperty(addNode, tagReq.getValue(), addNode.getUuid());
} catch (Exception e) {
throw new RuntimeException(e);
}
}
// 设置 当前节点所属项目根节点uuid
// addNode.getPid()为空时在创建项目ownRootNodeUuid就是addNode本身uuid
// addNode.getPid()不为空时在创建阶段ownRootNodeUuid就是入参的pid父节点
addNode.setOwnRootNodeUuid(ObjectUtils.isEmpty(addNode.getPid()) ? addNode.getUuid() : addNode.getPid());
addNode.setCreateTime(curDateStr);
addNode.setCreator(jobNumber);
addNode.setTenantId(tenantId);
}
}
if (nodeMapper.addNodeBatch(addNodeList) <= 0) {
return ;
}
// 批量创建文件夹
batchCreateNodeDir(addNodeList);
// 批量更新权限
List<BatchUpdatePermissionReq.FilePermissionItem> filePermissions = new ArrayList<>();
for (SpdmProjectNodeEditReq addNode : addNodeList) {
BatchUpdatePermissionReq.FilePermissionItem item = new BatchUpdatePermissionReq.FilePermissionItem();
item.setUuid(addNode.getUuid());
Map<Long, Byte> userPermissions = new HashMap<>();
// 2026-02-09 因为项目视图中没有项目经理,这里将项目创建人当成项目经理
userPermissions.put(jobNumber, FilePermissionEnum.ALL.getValue());
item.setUserPermissions(userPermissions);
filePermissions.add(item);
}
if (CollectionUtils.isNotEmpty(filePermissions)) {
BatchUpdatePermissionReq batchReq = new BatchUpdatePermissionReq();
batchReq.setFilePermissions(filePermissions);
log.info("创建项目阶段时,批量更新权限,任务数量:{}", filePermissions.size());
SdmResponse response = dataFeignClient.batchUpdatePermission(batchReq);
log.info("创建项目阶段时,批量更新权限结果:{}", response);
if (!response.isSuccess()) {
log.error("批量更新权限失败:{}", response.getMessage());
}
}
}
private SdmResponse handleRelatedProjectTodo(List<SimulationNode> projectNodeList, List<LyricVTodoEmulationInfoDM> relatedProjectVTodoEmulationInfoDMList) {
return httpSyncTodoData(projectNodeList, relatedProjectVTodoEmulationInfoDMList);
}
private SdmResponse httpSyncTodoData(List<SimulationNode> projectNodeList, List<LyricVTodoEmulationInfoDM> todoInfoList) {
String traceId = MdcUtil.getTraceId();
CompletableFuture<SdmResponse> syncTodoDataFeature = CompletableFuture.supplyAsync(() ->
syncTodoData(projectNodeList, todoInfoList,traceId));
syncTodoData(projectNodeList, todoInfoList, traceId));
try {
SdmResponse sdmResponse = syncTodoDataFeature.get(syncTodoDataWaitSeconds, TimeUnit.SECONDS);
return sdmResponse;
} catch (InterruptedException e) {
log.error("同步异常终止:{}",e.getMessage());
log.error("同步异常终止:{}", e.getMessage());
return SdmResponse.failed("同步异常终止");
} catch (ExecutionException e) {
log.error("同步执行错误:{}",e.getMessage());
log.error("同步执行错误:{}", e.getMessage());
return SdmResponse.failed("同步执行出错误");
} catch (TimeoutException e) {
log.warn("同步执行超时:{}",e.getMessage());
log.warn("同步执行超时:{}", e.getMessage());
return SdmResponse.success("同步执行中,请稍后");
}catch (Exception e) {
log.error("同步未知错误:{}",e.getMessage());
} catch (Exception e) {
log.error("同步未知错误:{}", e.getMessage());
return SdmResponse.failed("同步未知错误");
}
}
@@ -2085,12 +2722,13 @@ public class LyricInternalServiceImpl implements ILyricInternalService {
* 查询未同步异常的任务列表
*/
private List<SimulationTaskSyncExBo> queryUnsyncedExceptionTasks(int fromIndex, int endIndex) {
return simulationTaskMapper.queryLyricHasNotSyncExceptionDatas(fromIndex,endIndex);
return simulationTaskMapper.queryLyricHasNotSyncExceptionDatas(fromIndex, endIndex);
}
/**
* 构建标签对应的节点信息映射
* @param tasks 任务列表
*
* @param tasks 任务列表
* @param tagField 标签字段名tag1/tag5
* @param nodeType 节点类型project/workspace
*/
@@ -2218,8 +2856,9 @@ public class LyricInternalServiceImpl implements ILyricInternalService {
/**
* 匹配两个集合,筛选符合条件的数据并封装为 LyricExceptionModel 列表
*
* @param exceptionList 异常信息列表
* @param noSyncLists 没有同步的有异常的任务同步列表
* @param noSyncLists 没有同步的有异常的任务同步列表
* @return 匹配后的异常模型列表
*/
public List<LyricExceptionModel> matchExceptionAndTask(List<LyricVProjectStationExcepTionToDM> exceptionList,

View File

@@ -878,7 +878,7 @@ public class NodeServiceImpl extends ServiceImpl<SimulationNodeMapper, Simulatio
/**
* 内部静态类:封装节点类型筛选结果
*/
private static class NodeTypeFilterResult {
public static class NodeTypeFilterResult {
private final SpdmProjectNodeEditReq projectNode;
private final List<SpdmProjectNodeEditReq> addPhaseNodeList;
private final List<SpdmProjectNodeEditReq> addMachineNodeList;

View File

@@ -188,4 +188,7 @@ xxl:
# 通过标识判断是否走查询现场视图逻辑0不查询1查询
lyricFlag : 0
lyricFlag : 0
# 同步待办时,查询待办的最大时间间隔,单位:天
#lyricTodoInterval : 7

View File

@@ -177,6 +177,10 @@
select * from simulation_demand where demandSource = 'EP'
</select>
<select id="getAllCodeList" resultType="java.lang.String">
select distinct demand_code from simulation_demand where demandSource = 'EP' and demand_code is not null and demand_code != ''
</select>
<select id="getDemandListWithCondition" resultType="com.sdm.project.model.vo.SpdmDemandVo">
SELECT
sd.*,