This commit is contained in:
2026-02-03 19:01:58 +08:00
6 changed files with 190 additions and 81 deletions

View File

@@ -47,6 +47,8 @@ public class TestSecondDbController {
private LyricVProjectStationPlanToDmService lyricVProjectStationPlanToDmService; private LyricVProjectStationPlanToDmService lyricVProjectStationPlanToDmService;
@Autowired @Autowired
private LyricVProjectResourcePlanDMService lyricVProjectResourcePlanDMService; private LyricVProjectResourcePlanDMService lyricVProjectResourcePlanDMService;
@Autowired
private LyricVProjectStationExcepTionToDMService lyricVProjectStationExcepTionToDMService;
@Autowired @Autowired
private DynamicSqlExecutor dynamicSqlExecutor; private DynamicSqlExecutor dynamicSqlExecutor;
@@ -232,6 +234,19 @@ public class TestSecondDbController {
return SdmResponse.success(map); return SdmResponse.success(map);
} }
@GetMapping("/getProjectException")
@Operation(summary = "查询项目-项目异常")
public SdmResponse<Map<String,Object>> getProjectException() {
Map<String, Object> map = new HashMap<>();
// 查询从数据源
List<LyricVProjectStationExcepTionToDM> list = lyricVProjectStationExcepTionToDMService.lambdaQuery().last("limit 3").list();
Long count = lyricVProjectStationExcepTionToDMService.lambdaQuery().count();
map.put("视图数据",list);
map.put("数据总数",count);
return SdmResponse.success(map);
}
/** /**
* 执行查询SQL接口 * 执行查询SQL接口
* @return SQL执行结果 * @return SQL执行结果

View File

@@ -0,0 +1,34 @@
package com.sdm.project.controller;
import com.sdm.common.common.SdmResponse;
import com.sdm.project.service.ILyricInternalService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@Slf4j
@RestController
@RequestMapping
@Tag(name = "测试外部模块系统交互", description = "测试外部模块系统交互,非前端调用")
public class ProjectTestController {
@Autowired
private ILyricInternalService lyricInternalService;
@GetMapping("/mockSyncLyricEx")
@Operation(summary = "mock测试同步lyric任务异常信息")
public SdmResponse<String> mockSyncLyricEx() {
SdmResponse response = lyricInternalService.syncException();
return response;
}
}

View File

@@ -64,6 +64,8 @@ public interface SimulationTaskMapper extends BaseMapper<SimulationTask> {
List<SpdmTaskVo> optimisedGtTaskList(@Param("tenantId") Long tenantId, @Param("req") SpdmTaskListReq req); List<SpdmTaskVo> optimisedGtTaskList(@Param("tenantId") Long tenantId, @Param("req") SpdmTaskListReq req);
List<SimulationTaskSyncExBo> queryLyricHasNotSyncExceptionDatas(); List<SimulationTaskSyncExBo> queryLyricHasNotSyncExceptionDatas(@Param("offset")int offset, @Param("pageSize")int pageSize);
int queryUnsyncedExceptionTasksTotal();
} }

View File

@@ -73,6 +73,7 @@ import java.util.concurrent.*;
import java.util.concurrent.locks.ReentrantLock; import java.util.concurrent.locks.ReentrantLock;
import java.util.function.Function; import java.util.function.Function;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import java.util.stream.Stream;
import java.util.zip.ZipEntry; import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream; import java.util.zip.ZipOutputStream;
@@ -165,6 +166,10 @@ public class LyricInternalServiceImpl implements ILyricInternalService {
@Autowired @Autowired
private SimulationTaskExtraMapper simulationTaskExtraMapper; private SimulationTaskExtraMapper simulationTaskExtraMapper;
// 每批次处理的任务数量,可根据实际业务调整
@Value("${lyric.syncException.batchSize:100}")
private Integer batchSize;
/** /**
* 判断字符串是否可以安全转换为Long类型 * 判断字符串是否可以安全转换为Long类型
* *
@@ -1771,54 +1776,87 @@ public class LyricInternalServiceImpl implements ILyricInternalService {
} }
/** /**
* 同步异常任务信息方法 * 同步异常任务信息方法 batchSize
*/ */
@Override @Override
public SdmResponse syncException() { public SdmResponse syncException() {
try { try {
// 1. 查询未同步异常任务 // 1. 查询未同步异常任务的总数量
List<SimulationTaskSyncExBo> unsyncedExceptionTasks = queryUnsyncedExceptionTasks(); int total = simulationTaskMapper.queryUnsyncedExceptionTasksTotal();
if (CollectionUtils.isEmpty(unsyncedExceptionTasks)) { if (total <= 0) {
log.warn("同步异常任务:暂无需要同步的任务"); log.warn("同步异常任务:暂无需要同步的任务");
return SdmResponse.success("同步异常任务:暂无需要同步的任务"); return SdmResponse.success("同步异常任务:暂无需要同步的任务");
} }
log.info("同步异常任务:待处理总任务数为{}条,将分批次处理,每批次{}条", total, batchSize);
// 2. 初始化批次参数,循环分批处理
int processedCount = 0; // 已处理的任务总数
int syncTotalCount = 0; // 最终同步成功的异常数据总数
int pageNum = 1; // 当前批次页码
while (processedCount < total) {
log.info("同步异常任务:开始处理第{}批次,已处理{}条,剩余{}条",
pageNum, processedCount, total - processedCount);
// 2. 构建标签对应的节点信息映射 // 计算当前批次的起始和结束索引(分页查询)
Map<String, SimulationNode> tag1NodeMap = buildTagNodeMap(unsyncedExceptionTasks, "tag1", "project"); int fromIndex = processedCount;
Map<String, SimulationNode> tag5NodeMap = buildTagNodeMap(unsyncedExceptionTasks, "tag5", "workspace"); int endIndex = Math.min(processedCount + batchSize, total);
// 3. 分批查询未同步异常任务
List<SimulationTaskSyncExBo> unsyncedExceptionTasks = queryUnsyncedExceptionTasks(fromIndex, endIndex);
if (CollectionUtils.isEmpty(unsyncedExceptionTasks)) {
log.warn("同步异常任务:第{}批次查询结果为空,跳过该批次", pageNum);
processedCount += batchSize;
pageNum++;
continue;
}
log.info("同步异常任务:第{}批次查询到{}条待处理任务", pageNum, unsyncedExceptionTasks.size());
// 4. 构建标签对应的节点信息映射
Map<String, SimulationNode> tag1NodeMap = buildTagNodeMap(unsyncedExceptionTasks, "tag1", "project");
Map<String, SimulationNode> tag5NodeMap = buildTagNodeMap(unsyncedExceptionTasks, "tag5", "workspace");
if (MapUtils.isEmpty(tag1NodeMap) && MapUtils.isEmpty(tag5NodeMap)) {
log.warn("同步异常任务:第{}批次标签对应的节点信息为空,跳过该批次", pageNum);
processedCount += unsyncedExceptionTasks.size();
pageNum++;
continue;
}
if (MapUtils.isEmpty(tag1NodeMap) && MapUtils.isEmpty(tag5NodeMap)) { // 5. 为任务赋值对应的节点编码
log.warn("同步异常任务:标签对应的节点信息为空"); assignNodeCodeToTasks(unsyncedExceptionTasks, tag1NodeMap, tag5NodeMap);
return SdmResponse.success("同步异常任务:标签对应的节点信息为空");
// 6. 过滤出编码完整的有效任务
List<SimulationTaskSyncExBo> validTasks = filterValidTasks(unsyncedExceptionTasks);
if (CollectionUtils.isEmpty(validTasks)) {
log.warn("同步异常任务:第{}批次过滤后无有效任务,跳过该批次", pageNum);
processedCount += unsyncedExceptionTasks.size();
pageNum++;
continue;
}
log.info("同步异常任务:第{}批次过滤后剩余{}条有效任务", pageNum, validTasks.size());
// 7. 查询异常数据并匹配任务
List<LyricExceptionModel> newExceptionModels = queryAndMatchExceptions(validTasks);
if (CollectionUtils.isEmpty(newExceptionModels)) {
log.info("同步异常任务:第{}批次无新增异常数据需要入库", pageNum);
processedCount += unsyncedExceptionTasks.size();
pageNum++;
continue;
}
// 8. 批量入库异常数据,累加同步成功数量
int syncCount = batchSaveExceptionData(newExceptionModels);
syncTotalCount += syncCount;
log.info("同步异常任务:第{}批次同步完成,本次同步{}条,累计同步{}条",
pageNum, syncCount, syncTotalCount);
// 更新已处理数量和页码
processedCount += unsyncedExceptionTasks.size();
pageNum++;
} }
// 3. 为任务赋值对应的节点编码 log.info("同步异常任务全部完成,总任务数{}条,累计同步异常数据{}条", total, syncTotalCount);
assignNodeCodeToTasks(unsyncedExceptionTasks, tag1NodeMap, tag5NodeMap); return SdmResponse.success("同步成功,总任务数" + total + "条,累计同步了" + syncTotalCount + "条异常数据");
// 4. 过滤出编码完整的任务tag1Code和tag5Code都不为空
List<SimulationTaskSyncExBo> validTasks = filterValidTasks(unsyncedExceptionTasks);
if (CollectionUtils.isEmpty(validTasks)) {
log.warn("同步异常任务过滤后无有效任务tag1Code/tag5Code为空");
return SdmResponse.success("同步异常任务:过滤后无有效任务");
}
// 5. 查询异常数据并匹配任务
List<LyricExceptionModel> newExceptionModels = queryAndMatchExceptions(validTasks);
if (CollectionUtils.isEmpty(newExceptionModels)) {
log.info("同步异常任务:无新增异常数据需要入库");
return SdmResponse.success("同步异常任务:无新增异常数据需要入库");
}
// 6. 批量入库异常数据
int syncCount = batchSaveExceptionData(newExceptionModels);
log.info("同步异常任务完成,本次同步{}条数据", syncCount);
return SdmResponse.success("同步成功,本次同步了" + syncCount + "条数据");
} catch (Exception e) { } catch (Exception e) {
log.error("同步异常任务失败", e); log.error("同步异常任务执行失败,已处理部分数据", e);
return SdmResponse.failed("同步异常任务失败:" + e.getMessage()); return SdmResponse.failed("同步异常任务失败:" + e.getMessage());
} }
} }
@Override @Override
@@ -1972,8 +2010,8 @@ public class LyricInternalServiceImpl implements ILyricInternalService {
/** /**
* 查询未同步异常的任务列表 * 查询未同步异常的任务列表
*/ */
private List<SimulationTaskSyncExBo> queryUnsyncedExceptionTasks() { private List<SimulationTaskSyncExBo> queryUnsyncedExceptionTasks(int fromIndex, int endIndex) {
return simulationTaskMapper.queryLyricHasNotSyncExceptionDatas(); return simulationTaskMapper.queryLyricHasNotSyncExceptionDatas(fromIndex,endIndex);
} }
/** /**
@@ -2069,39 +2107,37 @@ public class LyricInternalServiceImpl implements ILyricInternalService {
private int batchSaveExceptionData(List<LyricExceptionModel> exceptionModels) { private int batchSaveExceptionData(List<LyricExceptionModel> exceptionModels) {
// 构建扩展表数据 // 构建扩展表数据
List<SpdmNodeExtraReq> abnormalExtraList = new ArrayList<>(); List<SpdmNodeExtraReq> abnormalExtraList = new ArrayList<>();
List<SpdmNodeExtraReq> abnormalDetailExtraList = new ArrayList<>(); // List<SpdmNodeExtraReq> abnormalDetailExtraList = new ArrayList<>();
for (LyricExceptionModel model : exceptionModels) { for (LyricExceptionModel model : exceptionModels) {
if (model == null || StringUtils.isBlank(model.getUuid())) { if (model == null || StringUtils.isBlank(model.getUuid())) {
log.warn("同步异常任务异常模型数据无效跳过处理model={}", model); log.warn("同步异常任务异常模型数据无效跳过处理model={}", model);
continue; continue;
} }
// 构建异常标识扩展记录 // 构建异常标识扩展记录
SpdmNodeExtraReq abnormalExtra = new SpdmNodeExtraReq(); SpdmNodeExtraReq abnormalExtra = new SpdmNodeExtraReq();
abnormalExtra.setNodeId(model.getUuid()); abnormalExtra.setNodeId(model.getUuid());
abnormalExtra.setPropertyName("abnormal"); abnormalExtra.setPropertyName("abnormal");
abnormalExtra.setPropertyValue("1"); abnormalExtra.setPropertyValue("1");
abnormalExtraList.add(abnormalExtra); abnormalExtraList.add(abnormalExtra);
// // 构建异常详情扩展记录 异常的详情暂时不需要 项目号+工位号 查出来的异常非常多,如果存储的话需要注意
// SpdmNodeExtraReq detailExtra = new SpdmNodeExtraReq();
// detailExtra.setNodeId(model.getUuid());
// detailExtra.setPropertyName("abnormalDetail");
// detailExtra.setPropertyValue(JSONObject.toJSONString(model));
// abnormalDetailExtraList.add(detailExtra);
// 构建异常详情扩展记录(修复原代码空指针问题)
SpdmNodeExtraReq detailExtra = new SpdmNodeExtraReq();
detailExtra.setNodeId(model.getUuid());
detailExtra.setPropertyName("abnormalDetail");
detailExtra.setPropertyValue(JSONObject.toJSONString(model));
abnormalDetailExtraList.add(detailExtra);
} }
// 批量插入异常标识 // 批量插入异常标识
if (CollectionUtils.isNotEmpty(abnormalExtraList)) { if (CollectionUtils.isNotEmpty(abnormalExtraList)) {
int abnormalCount = simulationTaskExtraMapper.addTaskExtraBatch(abnormalExtraList); int abnormalCount = simulationTaskExtraMapper.addTaskExtraBatch(abnormalExtraList);
log.info("同步异常任务:批量插入异常标识{}条,成功{}条", abnormalExtraList.size(), abnormalCount); log.info("同步异常任务:批量插入异常标识{}条,成功{}条", abnormalExtraList.size(), abnormalCount);
} }
// 批量插入异常详情 // 批量插入异常详情
if (CollectionUtils.isNotEmpty(abnormalDetailExtraList)) { // if (CollectionUtils.isNotEmpty(abnormalDetailExtraList)) {
int detailCount = simulationTaskExtraMapper.addTaskExtraBatch(abnormalDetailExtraList); // int detailCount = simulationTaskExtraMapper.addTaskExtraBatch(abnormalDetailExtraList);
log.info("同步异常任务:批量插入异常详情{}条,成功{}条", abnormalDetailExtraList.size(), detailCount); // log.info("同步异常任务:批量插入异常详情{}条,成功{}条", abnormalDetailExtraList.size(), detailCount);
} // }
return exceptionModels.size(); return exceptionModels.size();
} }
@@ -2114,44 +2150,44 @@ public class LyricInternalServiceImpl implements ILyricInternalService {
*/ */
public List<LyricExceptionModel> matchExceptionAndTask(List<LyricVProjectStationExcepTionToDM> exceptionList, public List<LyricExceptionModel> matchExceptionAndTask(List<LyricVProjectStationExcepTionToDM> exceptionList,
List<SimulationTaskSyncExBo> noSyncLists) { List<SimulationTaskSyncExBo> noSyncLists) {
// 步骤1预处理 noSyncLists转换为 Mapkey: tag1Code_tag5Codevalue: SimulationTaskSyncExBo // 步骤1预处理 noSyncLists转换为 Mapkey: tag1Code_tag5Codevalue: List<SimulationTaskSyncExBo>
// 先过滤掉 tag1Code/tag5Code 为空的无效数据 Map<String, List<SimulationTaskSyncExBo>> taskMap = noSyncLists.stream()
Map<String, SimulationTaskSyncExBo> taskMap = noSyncLists.stream()
.filter(bo -> bo != null .filter(bo -> bo != null
&& bo.getTag1Code() != null && !bo.getTag1Code().trim().isEmpty() && bo.getTag1Code() != null && !bo.getTag1Code().trim().isEmpty()
&& bo.getTag5Code() != null && !bo.getTag5Code().trim().isEmpty()) && bo.getTag5Code() != null && !bo.getTag5Code().trim().isEmpty())
.collect(Collectors.toMap( .collect(Collectors.groupingBy(
// 组合键tag1Code + "_" + tag5Code确保唯一性 bo -> bo.getTag1Code().trim() + "_" + bo.getTag5Code().trim()
bo -> bo.getTag1Code().trim() + "_" + bo.getTag5Code().trim(),
// value 为当前 bo 对象
bo -> bo,
// 若存在重复组合键,保留第一个(避免报错)
(existing, replacement) -> existing
)); ));
// 用于记录已经处理过的 matchKey实现去重
Set<String> processedKeys = new HashSet<>();
// 步骤2遍历 exceptionList匹配并封装结果 // 步骤2遍历 exceptionList匹配并封装结果
List<LyricExceptionModel> resultList = exceptionList.stream() List<LyricExceptionModel> resultList = exceptionList.stream()
// 过滤掉异常列表中的无效数据null 或关键字段为空) // 过滤掉异常列表中的无效数据
.filter(exception -> exception != null .filter(exception -> exception != null
&& exception.getProjectNum() != null && !exception.getProjectNum().trim().isEmpty() && exception.getProjectNum() != null && !exception.getProjectNum().trim().isEmpty()
&& exception.getStationCode() != null && !exception.getStationCode().trim().isEmpty()) && exception.getStationCode() != null && !exception.getStationCode().trim().isEmpty())
.map(exception -> { // 使用 flatMap 实现一对多转换
// 生成匹配键projectNum + "_" + stationNum .flatMap(exception -> {
String matchKey = exception.getProjectNum().trim() + "_" + exception.getStationCode().trim(); String matchKey = exception.getProjectNum().trim() + "_" + exception.getStationCode().trim();
// 从 taskMap 中查找匹配的任务对象 // 如果该 key 已经处理过,直接返回空流,跳过
SimulationTaskSyncExBo matchTask = taskMap.get(matchKey); if (processedKeys.contains(matchKey)) {
if (matchTask != null) { return Stream.empty();
// 匹配成功,创建 LyricExceptionModel 对象
LyricExceptionModel model = new LyricExceptionModel();
model.setUuid(matchTask.getUuid()); // 设置任务的 uuid
model.setExceptionModel(exception); // 设置异常信息对象
return model;
} }
// 匹配失败返回 null List<SimulationTaskSyncExBo> matchTasks = taskMap.get(matchKey);
return null; // 如果没有匹配到任务,返回空流
if (CollectionUtils.isEmpty(matchTasks)) {
return Stream.empty();
}
// 标记该 key 已处理
processedKeys.add(matchKey);
// 遍历 matchTasks为每个任务创建一个 LyricExceptionModel
return matchTasks.stream().map(task -> {
LyricExceptionModel model = new LyricExceptionModel();
model.setUuid(task.getUuid());
// model.setExceptionModel(exception); // 项目编号+工位号在ep视图可能有多条数据具体的异常暂时不处理
return model;
});
}) })
// 过滤掉匹配失败的 null 元素
.filter(model -> model != null)
.collect(Collectors.toList()); .collect(Collectors.toList());
return resultList; return resultList;
} }

View File

@@ -2395,7 +2395,9 @@ public class SimulationRunServiceImpl extends ServiceImpl<SimulationRunMapper, S
.list(); .list();
Map<String, String> resultValueMap = new HashMap<>(); Map<String, String> resultValueMap = new HashMap<>();
if (CollectionUtils.isNotEmpty(runPerformanceList)) { if (CollectionUtils.isNotEmpty(runPerformanceList)) {
resultValueMap = runPerformanceList.stream().collect(Collectors.toMap(SimulationPerformance::getNodeCode, SimulationPerformance::getResultValue)); resultValueMap = runPerformanceList.stream()
.filter(sp -> sp.getResultValue() != null)
.collect(Collectors.toMap(SimulationPerformance::getNodeCode, SimulationPerformance::getResultValue));
} }
List<SimulationPerformance> simulationTaskPerformances = simulationPerformanceService.lambdaQuery() List<SimulationPerformance> simulationTaskPerformances = simulationPerformanceService.lambdaQuery()
.eq(SimulationPerformance::getTaskId, simulationRun.getTaskId()) .eq(SimulationPerformance::getTaskId, simulationRun.getTaskId())

View File

@@ -699,9 +699,29 @@
</select> </select>
<select id="queryLyricHasNotSyncExceptionDatas" resultType="com.sdm.outbridge.mode.SimulationTaskSyncExBo"> <select id="queryLyricHasNotSyncExceptionDatas" resultType="com.sdm.outbridge.mode.SimulationTaskSyncExBo">
select id,uuid,tag1,tag5 from simulation_task SELECT t.id, t.uuid, t.tag1, t.tag5
where uuid not in(select task_id from simulation_task_extra where property_name='abnormal') FROM simulation_task t
and tag1 is not null and tag5 is not null WHERE NOT EXISTS (
SELECT 1
FROM simulation_task_extra e
WHERE e.property_name = 'abnormal'
AND e.task_id = t.uuid
)
AND t.tag1 IS NOT NULL
AND t.tag5 IS NOT NULL
ORDER BY create_time ASC LIMIT #{offset}, #{pageSize}
</select>
<select id="queryUnsyncedExceptionTasksTotal" resultType="java.lang.Integer">
SELECT COUNT(*)
FROM simulation_task t
WHERE NOT EXISTS (
SELECT 1
FROM simulation_task_extra e
WHERE e.property_name = 'abnormal' AND e.task_id = t.uuid
)
AND t.tag1 IS NOT NULL
AND t.tag5 IS NOT NULL
</select> </select>