新增:利元亨现场,ecn信息刷新机制备用版本代码临时提交

This commit is contained in:
2026-02-06 13:47:44 +08:00
parent bbcff92a11
commit 4c7756ac12
13 changed files with 689 additions and 4 deletions

View File

@@ -1,2 +1,16 @@
ALTER TABLE `spdm_baseline`.`simulation_job` ALTER TABLE `spdm_baseline`.`simulation_job`
ADD COLUMN `del_flag` CHAR(1) NOT NULL DEFAULT 'N' COMMENT '逻辑删除标识N-未删除Y-已删除'; ADD COLUMN `del_flag` CHAR(1) NOT NULL DEFAULT 'N' COMMENT '逻辑删除标识N-未删除Y-已删除';
-- 创建任务异常信息记录表
CREATE TABLE `simulation_task_ecn` (
`id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键ID自增',
`project_code` VARCHAR(64) NOT NULL COMMENT '项目号',
`station_code` VARCHAR(64) NOT NULL COMMENT '工位号',
`ecn_info` MEDIUMTEXT NOT NULL COMMENT '异常数据存储JSON字符串',
`source` VARCHAR(64) NOT NULL DEFAULT 'lyric' COMMENT '数据来源默认值lyric',
`create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间,自动记录插入时间',
`update_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间,自动记录更新时间',
PRIMARY KEY (`id`),
KEY `idx_project_station` (`project_code`, `station_code`) COMMENT '项目号+工位号联合索引,提升查询效率'
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='任务异常信息记录表';

View File

@@ -0,0 +1,19 @@
package com.sdm.common.entity.req.pbs;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.io.Serializable;
@Data
public class DelHpcJobsFileToolReq implements Serializable {
private static final long serialVersionUID = 1L;
@Schema(description = "计算任务Id,job new 生成")
private String jobId;
@Schema(description = "任务执行输出的文件在Hpc的绝对路径共享目录+jobName文件回传)+uuid下面可能有多个文件")
private String stdoutHpcFilePath;
}

View File

@@ -9,6 +9,7 @@ public class LyricExceptionModel {
// 异常任务的taskid // 异常任务的taskid
private String uuid; private String uuid;
// 暂时没用,现在项目号+工位号下面有多个异常信息就算存储也是List<Object>
private LyricVProjectStationExcepTionToDM exceptionModel; private LyricVProjectStationExcepTionToDM exceptionModel;
} }

View File

@@ -0,0 +1,25 @@
package com.sdm.project.dao;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.sdm.outbridge.mode.SimulationTaskSyncExBo;
import com.sdm.project.model.entity.SimulationTaskEcn;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* <p>
* 任务异常信息记录表 Mapper 接口
* </p>
*
* @author author
* @since 2026-02-05
*/
@Mapper
public interface SimulationTaskEcnMapper extends BaseMapper<SimulationTaskEcn> {
List<SimulationTaskEcn> queryAllDataByProjectCodeAndStationCode(@Param("list") List<SimulationTaskSyncExBo> list);
}

View File

@@ -68,4 +68,8 @@ public interface SimulationTaskMapper extends BaseMapper<SimulationTask> {
int queryUnsyncedExceptionTasksTotal(); int queryUnsyncedExceptionTasksTotal();
int queryAllasksTotal();
List<SimulationTaskSyncExBo> queryLyricAllTasksDatas(@Param("offset")int offset, @Param("pageSize")int pageSize);
} }

View File

@@ -0,0 +1,57 @@
package com.sdm.project.model.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import java.io.Serializable;
import java.time.LocalDateTime;
/**
* @author author
* @since 2026-02-05
*/
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@TableName("simulation_task_ecn")
@ApiModel(value="SimulationTaskEcn对象", description="任务异常信息记录表")
public class SimulationTaskEcn implements Serializable {
private static final long serialVersionUID = 1L;
@ApiModelProperty(value = "主键ID自增")
@TableId(value = "id", type = IdType.AUTO)
private Long id;
@ApiModelProperty(value = "项目号")
@TableField("project_code")
private String projectCode;
@ApiModelProperty(value = "工位号")
@TableField("station_code")
private String stationCode;
@ApiModelProperty(value = "异常数据JSON字符串")
@TableField("ecn_info")
private String ecnInfo;
@ApiModelProperty(value = "数据来源,默认值 lyric ")
@TableField("source")
private String source;
@ApiModelProperty(value = "创建时间")
@TableField("create_time")
private LocalDateTime createTime;
@ApiModelProperty(value = "更新时间")
@TableField("update_time")
private LocalDateTime updateTime;
}

View File

@@ -1,6 +1,7 @@
package com.sdm.project.service; package com.sdm.project.service;
import com.baomidou.mybatisplus.extension.service.IService; import com.baomidou.mybatisplus.extension.service.IService;
import com.sdm.outbridge.mode.LyricExceptionModel;
import com.sdm.project.model.entity.SimulationTaskExtra; import com.sdm.project.model.entity.SimulationTaskExtra;
import com.sdm.project.model.req.SpdmNodeExtraReq; import com.sdm.project.model.req.SpdmNodeExtraReq;
@@ -39,4 +40,5 @@ public interface ISimulationTaskExtraService extends IService<SimulationTaskExtr
*/ */
int batchUpdate(List<SpdmNodeExtraReq> taskExtras); int batchUpdate(List<SpdmNodeExtraReq> taskExtras);
int batchRemoveAndSaveExceptionData(List<LyricExceptionModel> exceptionModels);
} }

View File

@@ -0,0 +1,23 @@
package com.sdm.project.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.sdm.outbridge.mode.SimulationTaskSyncExBo;
import com.sdm.project.model.entity.SimulationTaskEcn;
import java.util.List;
/**
* <p>
* 任务异常信息记录表 服务类
* </p>
*
* @author author
* @since 2026-02-05
*/
public interface SimulationTaskEcnService extends IService<SimulationTaskEcn> {
List<SimulationTaskEcn> queryAllDataByProjectCodeAndStationCode(List<SimulationTaskSyncExBo> validTasks);
int batchRemoveSaveTaskEcns(List<SimulationTaskEcn> newTaskEcns);
}

View File

@@ -0,0 +1,358 @@
package com.sdm.project.service.impl;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.sdm.common.common.SdmResponse;
import com.sdm.outbridge.entity.LyricVProjectStationExcepTionToDM;
import com.sdm.outbridge.mode.LyricExceptionModel;
import com.sdm.outbridge.mode.SimulationTaskSyncExBo;
import com.sdm.outbridge.service.lyric.LyricVProjectStationExcepTionToDMService;
import com.sdm.project.dao.SimulationNodeMapper;
import com.sdm.project.dao.SimulationTaskMapper;
import com.sdm.project.model.entity.SimulationNode;
import com.sdm.project.model.entity.SimulationTaskEcn;
import com.sdm.project.service.ISimulationTaskExtraService;
import com.sdm.project.service.SimulationTaskEcnService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.Pair;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;
@Service
@Slf4j
public class LyricInternalNewServiceImpl {
// 每批次处理的任务数量,可根据实际业务调整
@Value("${lyric.syncException.batchSize:100}")
private Integer batchSize;
@Autowired
private SimulationTaskMapper simulationTaskMapper;
@Autowired
private SimulationNodeMapper simulationNodeMapper;
@Autowired
private LyricVProjectStationExcepTionToDMService lyricVProjectStationExcepTionToDMService;
@Autowired
private SimulationTaskEcnService simulationTaskEcnService;
@Autowired
private ISimulationTaskExtraService simulationTaskExtraService;
/**
* 同步异常任务信息方法 batchSize
*/
public SdmResponse syncException() {
try {
// 1. 查询所有的
int total = simulationTaskMapper.queryAllasksTotal();
if (total <= 0) {
log.warn("同步异常任务:暂无需要同步的任务");
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);
// 计算当前批次的起始和结束索引(分页查询)
int fromIndex = processedCount;
int endIndex = Math.min(processedCount + batchSize, total);
// 3. 分批查询未同步异常任务
List<SimulationTaskSyncExBo> unsyncedExceptionTasks = queryAllTasks(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;
}
// 5. 为任务赋值对应的节点编码
assignNodeCodeToTasks(unsyncedExceptionTasks, tag1NodeMap, tag5NodeMap);
// 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);
Pair<List<LyricExceptionModel>, List<SimulationTaskEcn>> matchPair = queryAndMatchExceptions(validTasks);
List<LyricExceptionModel> newExceptionModels = matchPair.getLeft();
List<SimulationTaskEcn> newTaskEcns = matchPair.getRight();
if (CollectionUtils.isEmpty(newExceptionModels)) {
log.info("同步异常任务:第{}批次无新增异常数据需要入库", pageNum);
processedCount += unsyncedExceptionTasks.size();
pageNum++;
continue;
}
// 8. 批量入库异常数据,累加同步成功数量
int syncCount = 0;
try {
syncCount = simulationTaskExtraService.batchRemoveAndSaveExceptionData(newExceptionModels);
} catch (Exception e) {
log.error("batchRemoveAndSaveExceptionData error:{}", e.getMessage());
continue;
}
syncTotalCount += syncCount;
log.info("同步异常任务:第{}批次同步完成,本次同步{}条,累计同步{}条",
pageNum, syncCount, syncTotalCount);
// 更新已处理数量和页码
processedCount += unsyncedExceptionTasks.size();
pageNum++;
// 9. batchSaveTaskEcns记录EP异常的编码信息
try {
int ecnsCount = simulationTaskEcnService.batchRemoveSaveTaskEcns(newTaskEcns);
} catch (Exception e) {
log.error("batchRemoveSaveTaskEcns error:{}", e.getMessage());
}
}
log.info("同步异常任务全部完成,总任务数{}条,累计同步异常数据{}条", total, syncTotalCount);
return SdmResponse.success("同步成功,总任务数" + total + "条,累计同步了" + syncTotalCount + "条异常数据");
} catch (Exception e) {
log.error("同步异常任务执行失败,已处理部分数据", e);
return SdmResponse.failed("同步异常任务失败:" + e.getMessage());
}
}
/**
* 查询所有的任务
*/
private List<SimulationTaskSyncExBo> queryAllTasks(int fromIndex, int endIndex) {
return simulationTaskMapper.queryLyricAllTasksDatas(fromIndex,endIndex);
}
/**
* 构建标签对应的节点信息映射
* @param tasks 任务列表
* @param tagField 标签字段名tag1/tag5
* @param nodeType 节点类型project/workspace
*/
private Map<String, SimulationNode> buildTagNodeMap(List<SimulationTaskSyncExBo> tasks,
String tagField,
String nodeType) {
// 提取非空的标签值列表
List<String> tagValues = tasks.stream()
.filter(Objects::nonNull)
.map(task -> "tag1".equals(tagField) ? task.getTag1() : task.getTag5())
.filter(StringUtils::isNotBlank)
.distinct() // 去重,减少查询次数
.collect(Collectors.toList());
if (CollectionUtils.isEmpty(tagValues)) {
return Collections.emptyMap();
}
// 查询标签对应的节点信息
List<SimulationNode> nodes = simulationNodeMapper.queryNodeCodeByTags(tagValues, tagField, nodeType);
if (CollectionUtils.isEmpty(nodes)) {
log.warn("同步异常任务:{}类型节点查询结果为空,标签列表:{}", nodeType, tagValues);
return Collections.emptyMap();
}
// 转换为UUID->节点的映射处理重复UUID保留第一个
return nodes.stream()
.filter(node -> node != null && StringUtils.isNotBlank(node.getUuid()))
.collect(Collectors.toMap(
SimulationNode::getUuid,
node -> node,
(existing, replacement) -> existing
));
}
/**
* 为任务赋值对应的节点编码
*/
private void assignNodeCodeToTasks(List<SimulationTaskSyncExBo> tasks,
Map<String, SimulationNode> tag1NodeMap,
Map<String, SimulationNode> tag5NodeMap) {
tasks.stream()
.filter(Objects::nonNull)
.forEach(task -> {
// 赋值tag1Code
if (MapUtils.isNotEmpty(tag1NodeMap) && StringUtils.isNotBlank(task.getTag1())) {
SimulationNode node = tag1NodeMap.get(task.getTag1());
if (node != null) {
task.setTag1Code(node.getNodeCode());
}
}
// 赋值tag5Code
if (MapUtils.isNotEmpty(tag5NodeMap) && StringUtils.isNotBlank(task.getTag5())) {
SimulationNode node = tag5NodeMap.get(task.getTag5());
if (node != null) {
task.setTag5Code(node.getNodeCode());
}
}
});
}
/**
* 过滤出tag1Code和tag5Code都不为空的有效任务
*/
private List<SimulationTaskSyncExBo> filterValidTasks(List<SimulationTaskSyncExBo> tasks) {
return tasks.stream()
.filter(Objects::nonNull)
.filter(task -> StringUtils.isNotBlank(task.getTag1Code())
&& StringUtils.isNotBlank(task.getTag5Code()))
.collect(Collectors.toList());
}
/**
* 查询异常数据并匹配任务
*/
private Pair<List<LyricExceptionModel>,List<SimulationTaskEcn>> queryAndMatchExceptions(List<SimulationTaskSyncExBo> validTasks) {
// 查询EP视图异常数据
List<LyricVProjectStationExcepTionToDM> exceptionList = lyricVProjectStationExcepTionToDMService
.queryExceptionsByProjectAndStation(validTasks);
// 查询 simulation_task_ecn 异常信息的表数据
List<SimulationTaskEcn>taskEcnsList =simulationTaskEcnService.
queryAllDataByProjectCodeAndStationCode(validTasks);
// 匹配异常和任务,返回新增的异常数据
return matchExceptionAndTask(exceptionList, validTasks,taskEcnsList);
}
/**
* 匹配两个集合,筛选符合条件的数据并封装为 LyricExceptionModel 列表
* @param exceptionList 异常信息列表
* @param noSyncLists 没有同步的有异常的任务同步列表
* @return 匹配后的异常模型列表
*/
public Pair<List<LyricExceptionModel>,List<SimulationTaskEcn>> matchExceptionAndTask(List<LyricVProjectStationExcepTionToDM> exceptionList,
List<SimulationTaskSyncExBo> noSyncLists, List<SimulationTaskEcn>taskEcnsList) {
List<LyricExceptionModel> ingDealExceptionList = new ArrayList<>();
List<SimulationTaskEcn> ingDealTaskEcnList = new ArrayList<>();
// key = ProjectCode_StationCode sdpm系统已经记录的异常信息
Map<String, List<String>> spdmDbEcnMap=new HashMap<>();
if(CollectionUtils.isNotEmpty(taskEcnsList)) {
spdmDbEcnMap = taskEcnsList.stream()
.collect(Collectors.toMap(
// 生成KeyprojectCode + "_" + stationCode
ecn -> ecn.getProjectCode() + "_" + ecn.getStationCode(),
// 解析ecnInfo JSON字符串为List<String>
ecn -> JSON.parseArray(ecn.getEcnInfo(), String.class),
// 解决Key冲突若存在相同projectCode+stationCode合并两个List
(existing, replacement) -> {
existing.addAll(replacement);
return existing;
}
));
}
// key = ProjectCode_StationCode ep拉回来的异常信息
Map<String, List<String>> epExceptionsMap = new HashMap<>();
if(CollectionUtils.isNotEmpty(exceptionList)) {
epExceptionsMap = exceptionList.stream()
.collect(Collectors.toMap(
// 生成 KeyprojectNum_stationCode
dto -> dto.getProjectNum() + "_" + dto.getStationCode(),
// 生成 Value将单个 ecnCode 封装为 List
dto -> {
List<String> ecnCodeList = new ArrayList<>();
ecnCodeList.add(dto.getEcnCode());
return ecnCodeList;
},
// Key 冲突时,合并 List将新的 ecnCode 添加到原有 List 中)
(existingList, newList) -> {
existingList.addAll(newList);
return existingList;
}
));
}
// spdm db的task
Map<String, List<SimulationTaskSyncExBo>> taskDbMap=new HashMap<>();
if(CollectionUtils.isNotEmpty(noSyncLists)) {
taskDbMap = noSyncLists.stream()
.filter(bo -> bo != null
&& bo.getTag1Code() != null && !bo.getTag1Code().trim().isEmpty()
&& bo.getTag5Code() != null && !bo.getTag5Code().trim().isEmpty())
.collect(Collectors.groupingBy(
bo -> bo.getTag1Code().trim() + "_" + bo.getTag5Code().trim()
));
}
// 判断是否需要修改
// 后面再次拉取异常假如没有新增原始的3条不动即使spdm任务增加到4条也不动
//假如新增了异常,那拓展的数据需要修改+新增。
// 遍历 任务的Map 的 entrySet同时获取 key 和对应的 List<SimulationTaskSyncExBo>
for (Map.Entry<String, List<SimulationTaskSyncExBo>> entry : taskDbMap.entrySet()) {
// 获取当前键
String key = entry.getKey();
// ep异常和spdm task对应上了
if(epExceptionsMap.containsKey(key)) {
// 这个任务有异常
List<String> epEcnCodes = epExceptionsMap.get(key);
List<String> spdmEcnCodes = spdmDbEcnMap.get(key);
// 调用方法判断是否相等,异常是否有新增
boolean isEqual = Objects.equals(epEcnCodes, spdmEcnCodes);
// 异常信息变了,重新维护任务异常,及异常编号的记录
if(!isEqual) {
// 获取当前值List 集合)
List<SimulationTaskSyncExBo> spdmDbtaskList = entry.getValue();
// 1. 先判断 List 是否为空(避免空指针,最佳实践)
if (CollectionUtils.isNotEmpty(spdmDbtaskList)) {
String projectCode="";
String stationCode="";
// 2. 处理每个任务的异常
for (SimulationTaskSyncExBo taskDb : spdmDbtaskList) {
LyricExceptionModel model = new LyricExceptionModel();
model.setUuid(taskDb.getUuid());
ingDealExceptionList.add(model);
if(StringUtils.isNotBlank(projectCode)) {projectCode=taskDb.getTag1Code();}
if(StringUtils.isNotBlank(stationCode)) {stationCode=taskDb.getTag5Code();}
}
if(CollectionUtils.isNotEmpty(epEcnCodes)) {
// 处理项目+工位下的异常
SimulationTaskEcn taskEcn = new SimulationTaskEcn();
taskEcn.setEcnInfo(JSONObject.toJSONString(epEcnCodes));
taskEcn.setSource("lyric");
taskEcn.setProjectCode(projectCode);
taskEcn.setStationCode(stationCode);
taskEcn.setCreateTime(LocalDateTime.now());
taskEcn.setUpdateTime(LocalDateTime.now());
ingDealTaskEcnList.add(taskEcn);
}
}
}
}
}
return Pair.of(ingDealExceptionList, ingDealTaskEcnList);
}
}

View File

@@ -0,0 +1,71 @@
package com.sdm.project.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.sdm.outbridge.mode.SimulationTaskSyncExBo;
import com.sdm.project.dao.SimulationTaskEcnMapper;
import com.sdm.project.model.entity.SimulationTaskEcn;
import com.sdm.project.service.SimulationTaskEcnService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
/**
* <p>
* 任务异常信息记录表 服务实现类
* </p>
*
* @author author
* @since 2026-02-05
*/
@Slf4j
@Service
public class SimulationTaskEcnServiceImpl extends ServiceImpl<SimulationTaskEcnMapper, SimulationTaskEcn> implements SimulationTaskEcnService {
@Autowired
private SimulationTaskEcnMapper simulationTaskEcnMapper;
@Override
public List<SimulationTaskEcn> queryAllDataByProjectCodeAndStationCode(List<SimulationTaskSyncExBo> validTasks) {
return simulationTaskEcnMapper.queryAllDataByProjectCodeAndStationCode(validTasks);
}
@Override
@Transactional(rollbackFor = Exception.class)
public int batchRemoveSaveTaskEcns(List<SimulationTaskEcn> newTaskEcns) {
// 先删除,再插入
// 1. 判空处理:集合为空直接返回,避免全表删除
if (CollectionUtils.isEmpty(newTaskEcns)) {
return 0;
}
// 2. 构建 Lambda 查询条件
LambdaQueryWrapper<SimulationTaskEcn> queryWrapper = new LambdaQueryWrapper<>();
// 3. 遍历集合,拼接多组 (projectCode AND stationCode) 条件
for (SimulationTaskEcn taskEcn : newTaskEcns) {
// 每一组条件都用 and() 包裹,确保逻辑正确
queryWrapper.or(i -> i
.eq(SimulationTaskEcn::getProjectCode, taskEcn.getProjectCode())
.eq(SimulationTaskEcn::getStationCode, taskEcn.getStationCode())
);
}
// 4. 执行删除
boolean remove = this.remove(queryWrapper);
log.warn("batchSaveTaskEcns before delete: {}", remove);
if(!remove) {
log.error("batchSaveTaskEcns before delete failed");
throw new RuntimeException("batchSaveTaskEcns before delete failed");
}
boolean b = this.saveBatch(newTaskEcns);
if(!b) {
log.error("batchSaveTaskEcns after save failed");
throw new RuntimeException("batchSaveTaskEcns after save failed");
}
log.info("batchSaveTaskEcns after save: {}", b);
return newTaskEcns.size();
}
}

View File

@@ -2,16 +2,19 @@ package com.sdm.project.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.sdm.outbridge.mode.LyricExceptionModel;
import com.sdm.project.dao.SimulationTaskExtraMapper; import com.sdm.project.dao.SimulationTaskExtraMapper;
import com.sdm.project.model.entity.SimulationTaskExtra; import com.sdm.project.model.entity.SimulationTaskExtra;
import com.sdm.project.model.req.SpdmNodeExtraReq; import com.sdm.project.model.req.SpdmNodeExtraReq;
import com.sdm.project.service.ISimulationTaskExtraService; import com.sdm.project.service.ISimulationTaskExtraService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.Collections; import java.util.*;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors; import java.util.stream.Collectors;
/** /**
@@ -22,9 +25,13 @@ import java.util.stream.Collectors;
* @author author * @author author
* @since 2025-09-16 * @since 2025-09-16
*/ */
@Slf4j
@Service @Service
public class SimulationTaskExtraServiceImpl extends ServiceImpl<SimulationTaskExtraMapper, SimulationTaskExtra> implements ISimulationTaskExtraService { public class SimulationTaskExtraServiceImpl extends ServiceImpl<SimulationTaskExtraMapper, SimulationTaskExtra> implements ISimulationTaskExtraService {
@Autowired
private SimulationTaskExtraMapper simulationTaskExtraMapper;
@Override @Override
public Map<String, Map<String, SimulationTaskExtra>> batchGetTaskExtraMap(List<String> taskIds, List<String> propertyNames) { public Map<String, Map<String, SimulationTaskExtra>> batchGetTaskExtraMap(List<String> taskIds, List<String> propertyNames) {
if (CollectionUtils.isEmpty(taskIds) || CollectionUtils.isEmpty(propertyNames)) { if (CollectionUtils.isEmpty(taskIds) || CollectionUtils.isEmpty(propertyNames)) {
@@ -68,4 +75,68 @@ public class SimulationTaskExtraServiceImpl extends ServiceImpl<SimulationTaskEx
return successCount; return successCount;
} }
/**
* 批量保存异常数据到扩展表
*/
@Override
@Transactional(rollbackFor = Exception.class)
public int batchRemoveAndSaveExceptionData(List<LyricExceptionModel> exceptionModels) {
// 先删除,再插入
List<String> taskIdList = exceptionModels.stream()
// 提取每个 LyricExceptionModel 对象的 uuid 字段
.map(LyricExceptionModel::getUuid)
// 过滤掉 null 的 uuid可选根据业务需求决定是否保留
.filter(Objects::nonNull)
// 收集为新的 List<String>
.collect(Collectors.toList());
// 2. 构建 Lambda 查询条件
LambdaQueryWrapper<SimulationTaskExtra> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.in(SimulationTaskExtra::getTaskId, taskIdList);
// 3. 执行删除
boolean remove = this.remove(queryWrapper);
log.warn("batchSaveExceptionData before delete: {}", remove);
if(!remove) {
log.error("batchSaveExceptionData before delete failed");
throw new RuntimeException("batchSaveExceptionData before delete failed");
}
// 构建扩展表数据
List<SpdmNodeExtraReq> abnormalExtraList = new ArrayList<>();
// List<SpdmNodeExtraReq> abnormalDetailExtraList = new ArrayList<>();
for (LyricExceptionModel model : exceptionModels) {
if (model == null || StringUtils.isBlank(model.getUuid())) {
log.warn("同步异常任务异常模型数据无效跳过处理model={}", model);
continue;
}
// 构建异常标识扩展记录
SpdmNodeExtraReq abnormalExtra = new SpdmNodeExtraReq();
abnormalExtra.setNodeId(model.getUuid());
abnormalExtra.setPropertyName("abnormal");
abnormalExtra.setPropertyValue("1");
abnormalExtraList.add(abnormalExtra);
// // 构建异常详情扩展记录 异常的详情暂时不需要 项目号+工位号 查出来的异常非常多,如果存储的话需要注意
// SpdmNodeExtraReq detailExtra = new SpdmNodeExtraReq();
// detailExtra.setNodeId(model.getUuid());
// detailExtra.setPropertyName("abnormalDetail");
// detailExtra.setPropertyValue(JSONObject.toJSONString(model));
// abnormalDetailExtraList.add(detailExtra);
}
// 批量插入异常标识
if (CollectionUtils.isNotEmpty(abnormalExtraList)) {
int abnormalCount = simulationTaskExtraMapper.addTaskExtraBatch(abnormalExtraList);
if(abnormalCount <=0) {
throw new RuntimeException("batchSaveExceptionData failed");
}
log.info("同步异常任务:批量插入异常标识{}条,成功{}条", abnormalExtraList.size(), abnormalCount);
}
// 批量插入异常详情
// if (CollectionUtils.isNotEmpty(abnormalDetailExtraList)) {
// int detailCount = simulationTaskExtraMapper.addTaskExtraBatch(abnormalDetailExtraList);
// log.info("同步异常任务:批量插入异常详情{}条,成功{}条", abnormalDetailExtraList.size(), detailCount);
// }
return exceptionModels.size();
}
} }

View File

@@ -0,0 +1,27 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.sdm.project.dao.SimulationTaskEcnMapper">
<select id="queryAllDataByProjectCodeAndStationCode"
resultType="com.sdm.project.model.entity.SimulationTaskEcn">
SELECT
id AS id,
project_code AS projectCode,
station_code AS stationCode,
ecn_info AS ecnInfo,
source AS source,
create_time AS createTime,
update_time AS updateTime
FROM simulation_task_ecn
WHERE 1=1
AND (
<foreach collection="list" item="task" separator="OR">
<!-- 核心条件project_num = tag1Code 且 station_code = tag5Code -->
(project_code = #{task.tag1Code} AND station_code = #{task.tag5Code})
</foreach>
)
</select>
</mapper>

View File

@@ -743,5 +743,18 @@
AND t.tag5 IS NOT NULL AND t.tag5 IS NOT NULL
</select> </select>
<select id="queryAllasksTotal" resultType="java.lang.Integer">
SELECT COUNT(*)
FROM simulation_task t
WHERE t.tag1 IS NOT NULL AND t.tag5 IS NOT NULL
</select>
<select id="queryLyricAllTasksDatas" resultType="com.sdm.outbridge.mode.SimulationTaskSyncExBo">
SELECT t.id, t.uuid, t.tag1, t.tag5
FROM simulation_task t
WHERE t.tag1 IS NOT NULL
AND t.tag5 IS NOT NULL
ORDER BY create_time ASC LIMIT #{offset}, #{pageSize}
</select>
</mapper> </mapper>