Compare commits

...

51 Commits

Author SHA1 Message Date
bcea5255e6 修复常数对齐 2026-02-06 23:58:48 +08:00
a718557762 使用iot-s7完成通信 2026-02-06 23:52:26 +08:00
6db871f99b 通信数据修正 2026-02-03 14:48:29 +08:00
82cffb7ea3 后端更改为ONLINE全部下发 2026-02-02 17:59:50 +08:00
f8b7d6b813 修正循环依赖,添加了停机Type的查询 2026-02-02 16:20:49 +08:00
d8f0e102c9 加入上线时的下一设定值写入,生产状态转化后的其他数据写入 2026-02-02 15:58:57 +08:00
a6756bc7db 前后端加入炉火跟踪数据,以及质保书加入数据 2026-01-30 13:40:40 +08:00
cd192d86ba PRODUCING到PRODUCT状态转化bug修复,计划更改,辊缝追踪加入动态追踪,修复退火炉张力读写问题 2026-01-22 17:20:18 +08:00
b5dfb0c9b4 日志优化+PRODUCING到PRODUCT状态转化优化 2026-01-21 19:28:29 +08:00
675dd43262 日志优化+PRODUCING到PRODUCT状态转化优化 2026-01-21 14:29:12 +08:00
53e4635506 配合甩尾删除 2026-01-20 18:27:23 +08:00
a3e46674b3 1,2写入区分修正 2026-01-20 17:56:48 +08:00
65d9f59ac4 开卷机问题修复回去 2026-01-20 16:09:13 +08:00
e6c2b0aec2 Merge remote-tracking branch 'origin/main' 2026-01-15 16:36:02 +08:00
26bb8f33c4 30开卷机问题 2026-01-15 16:35:31 +08:00
5622507416 feat(crm-pdo-excoil): 实绩管理功能支持分页查询
- 继承BaseController以获得分页功能支持
- 修改list接口返回TableDataInfo类型支持分页数据
- 在CrmPdoExcoilForm表单中添加pageNum和pageSize字段
- 集成PageHelper实现分页逻辑
- 更新服务方法注释为支持分页查询
- 移除提前返回逻辑以确保完整查询流程执行
2026-01-15 09:50:07 +08:00
2d2c0779b9 优化G30日志 2026-01-11 21:43:17 +08:00
62036f85be g30前端以及生产状态变更问题已经解决 2026-01-11 17:22:56 +08:00
c179c22f25 chore(i18n): 国际化日志消息文本
- 将AppMeasureHandler中的钢卷焊缝跟踪信号日志消息翻译为英文
- 将MatmapUtil中的钢卷焊缝跟踪日志消息翻译为英文
- 移除MessageReceiveSchedule类中的@AllArgsConstructor注解
- 更新SegmentTrackerService中的焊缝位置匹配逻辑日志消息为英文
- 将StripPositionService中的设备位置日志消息翻译为英文
2026-01-09 09:31:53 +08:00
b36787f01f refactor(PdiSetup): 重构张力参数服务接口和实现
- 移除旧的生产计划参数详情相关服务接口
- 添加全线张力、退火炉张力、平整机张力、矫直机张力等新服务接口
- 更新PdiSetupService接口方法签名和文档注释
- 移除Spring Security权限注解依赖
- 优化Mapper XML映射文件字段映射和查询逻辑
- 更新控制器方法名称和日志标题以匹配新功能
2026-01-08 14:33:53 +08:00
5e2610f087 feat(device): 添加设备数据快照和趋势分析功能
- 在AppMeasureHandler中集成DeviceSnapshotService,缓存最新测量数据
- 添加DeviceChartDataDTO、DeviceFieldTrendDTO等数据传输对象
- 创建DeviceEnumController和DeviceFieldMetaController提供设备枚举和字段元数据
- 实现DeviceSnapshot领域模型和DeviceSnapshotMapper数据访问层
- 开发DeviceSnapshotService核心服务处理数据快照创建和趋势分析
- 添加DeviceSnapshotSchedule定时任务每10分钟执行设备数据快照
- 创建DeviceSnapshotController提供快照数据查询API
- 实现WebSocket实时推送设备历史趋势和统计数据功能
2026-01-07 13:49:35 +08:00
8d8be94c2d 写入功能完成 2026-01-04 15:05:28 +08:00
76ad6bcbd7 写入功能完成 2026-01-02 17:06:16 +08:00
fcdefce214 feat(domain): 添加业务实体字段支持
- 在 BizSendJob 中添加 groupType 字段用于分组类型标识
- 在 BizSendTemplateItemVO 中添加 enabled 字段用于状态控制
- 在 SendJobLastSuccessVO 中添加 isFromHistory 字段用于历史记录标识
2026-01-02 16:23:12 +08:00
ca91e43067 写入功能完成 2026-01-02 16:00:11 +08:00
00154d29fa 1 2026-01-02 15:11:31 +08:00
e38f787994 新增传动、炉火写入页面新增修改开关 2026-01-02 14:30:53 +08:00
dfa1ec73c8 相关配置修改 2026-01-02 14:12:08 +08:00
fc8c05d572 新增写入功能,追踪弹窗 2025-12-31 20:05:30 +08:00
01ef096568 修复bug 2025-12-31 18:29:13 +08:00
f09b68bca6 新增动态修改模板 2025-12-31 18:11:03 +08:00
26418f6fff 新增传动、炉火写入页面 2025-12-31 18:02:36 +08:00
32fa2c89ed Merge remote-tracking branch 'origin/main' 2025-12-31 17:59:53 +08:00
5c7db39940 写入逻辑 2025-12-31 17:59:19 +08:00
178e57d653 ```
feat: 添加锌层厚度字段到PDI和PDO相关实体类

- 在CrmPdiPlan、CrmPdoExcoil等domain类中添加zincCoatingThickness字段
- 在CrmPdiPlanForm、CrmPdoExcoilForm等form类中添加zincCoatingThickness字段
- 在CrmPdiPlanVO、PdiPlanVO等VO类中添加zincCoatingThickness字段
- 在PdiPlanSubDTO、PdoExCoilSubDTO等DTO类中添加zincCoatingThickness字段
- 在PdoExCoilServiceImpl服务实现中设置锌层厚度值
- 为所有新增字段添加BigDecimal类型导入和Schema注解
```
2025-12-31 09:29:38 +08:00
6e85b45d7c 新增主页接口,然后中译英 2025-12-26 16:49:41 +08:00
de333aaf5c Merge remote-tracking branch 'origin/main' 2025-12-26 16:12:41 +08:00
dd1b172273 修改英文 2025-12-26 16:11:26 +08:00
3b2dcb713f refactor(dashboard): 修改依赖未注入
- 修改 DashboardController 继承 BaseController
- 调整导入顺序,将 BaseController 放在前面
- 保持原有资源注入和接口功能不变
2025-12-26 15:15:37 +08:00
e5b1f885aa 修改英文 2025-12-26 15:09:01 +08:00
90480eedac Merge remote-tracking branch 'origin/main' 2025-12-26 15:06:24 +08:00
19ef36511b 新增看板接口 2025-12-26 15:04:24 +08:00
2903efd41c chore(config): 将服务器端口从8081改回默认的8080
- 修改 application.yml 中 server.port 从 8081 到 8080
- 保持其他开发环境配置不变
2025-12-26 10:01:56 +08:00
053948a919 feat(msg): 更新测量消息数据结构和字段定义
- 修改 AppMeasureCoatMessage 中钢带张力字段命名和描述,从 BR5/BR6 系列更新为 BR8/BR9/BR10 系列
- 在 AppMeasureEntryMessage 中添加入口活套最大最小长度字段,移除张力字段
- 在 AppMeasureExitMessage 中添加出口活套最大最小长度字段
- 重命名 AppMeasureFurnaceMessage 中的入口钢卷标识和钢带位置字段并添加单位
- 将 AppMeasureFurnaceMessage 中的空燃比字段重命名为更明确的名称并添加单位
- 更新炉温相关字段描述并统一添加单位标识
- 在 DeviceEnum 中移除入口活套相关的最大最小长度和张力字段引用
- 新增 L2HeartMessage 心跳消息类
- 在测试调度中注释掉张力和钢带位置的设置代码
2025-12-25 17:48:55 +08:00
d7bbd3c1f1 feat(device): 更新设备枚举配置
- 为入口活套设备添加新的监控参数
- 修改涂机段张力监测点配置
- 更新拉矫段张力监测点配置
- 调整相关工艺段设备参数映射关系
2025-12-25 16:06:57 +08:00
86a413d56e 相关配置修改 2025-12-25 14:15:38 +08:00
0945324f59 修改连接前缀 2025-12-25 13:49:36 +08:00
db8e7fcda4 Merge remote-tracking branch 'origin/main' 2025-12-25 13:48:29 +08:00
1247bfb5ab 相关配置修改 2025-12-25 13:47:23 +08:00
a9df237de2 refactor(opc): 更新OPC消息ID映射配置
- 将空燃比相关参数重命名为燃烧比参数,包括RTF1、RTF2和SF炉体
- 添加PH炉体压力相关参数映射
- 将LTH炉体参数从单套配置更新为LTH1和LTH2双套配置
- 移除JCF2炉体相关参数配置
- 更新JCF风扇参数命名规范,移除部分风扇参数
- 重命名烟气温度相关参数,更新热交换前后温度参数
- 调整压力参数命名,将烟气压力统一为燃气压力
- 更新炉内气氛参数命名,优化氧含量和露点参数名称
- 重命名燃气消耗相关参数,调整瞬时流量和消耗参数
2025-12-25 10:05:54 +08:00
3c4662bc89 refactor(opc): 重命名为l2Setup
- 将loadPdiSetupIds方法重命名为loadL2SetupIds
- 在entryLineMeasureIds映射中为张力相关字段添加注释
- 更新方法调用以使用新的L2Setup标识符加载逻辑
2025-12-24 17:49:17 +08:00
170 changed files with 6843 additions and 38709 deletions

View File

@@ -115,6 +115,12 @@
<version>3.1.4.0.6.15</version>
</dependency>
<dependency>
<groupId>com.github.xingshuangs</groupId>
<artifactId>iot-communication</artifactId>
<version>1.5.5</version>
</dependency>
<!-- <dependency>-->
<!-- <groupId>com.alibaba</groupId>-->

View File

@@ -5,9 +5,10 @@ import com.fizz.business.constants.enums.OpcMessageType;
import com.fizz.business.domain.msg.*;
import com.fizz.business.scheduled.BaseSchedule;
import com.fizz.business.service.hanle.OpcReceiverHandler;
import com.fizz.business.service.ProStoppageService;
import com.fizz.business.domain.ProStoppage;
import com.kangaroohy.milo.model.ReadWriteEntity;
import com.kangaroohy.milo.service.MiloService;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.beanutils.BeanUtils;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
@@ -17,6 +18,9 @@ import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.lang.reflect.Field;
import java.time.Duration;
import java.time.LocalDateTime;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@@ -25,7 +29,6 @@ import static com.fizz.business.service.manager.OpcMessageIdsManager.*;
@Slf4j
@Component
@AllArgsConstructor
@ConditionalOnProperty(prefix = "kangaroohy.milo", name = "enabled", havingValue = "true")
public class MessageReceiveSchedule extends BaseSchedule {
@@ -34,6 +37,22 @@ public class MessageReceiveSchedule extends BaseSchedule {
@Resource
private OpcReceiverHandler opcReceiverHandler;
@Resource
private ProStoppageService proStoppageService;
/**
* 低速监控状态
*/
private LocalDateTime lowSpeedStartTime;
private boolean stopRecorded = false;
private Long currentStopId;
/**
* 恢复监控状态
*/
private LocalDateTime highSpeedStartTime;
@Scheduled(fixedDelay = 1000)
public void L1L2LineMeasure() {
try {
@@ -55,6 +74,9 @@ public class MessageReceiveSchedule extends BaseSchedule {
msg.setAppMeasureCoatMessage(coat);
msg.setAppMeasureFurnaceMessage(fur);
msg.setAppMeasureExitMessage(exit);
monitorStripSpeed(entry);
opcReceiverHandler.onMessageReceived(OpcMessageType.APP_MEASURE,msg);
} catch (Exception e) {
@@ -86,4 +108,67 @@ public class MessageReceiveSchedule extends BaseSchedule {
}
});
}
/**
* stripSpeed<5 持续5分钟判定停机>5 持续1分钟结束停机并更新维持时间
*/
private void monitorStripSpeed(AppMeasureEntryMessage entry) {
if (entry == null || entry.getStripSpeed() == null) {
resetSpeedFlags();
return;
}
boolean lowSpeed = entry.getStripSpeed().compareTo(BigDecimal.valueOf(5)) < 0;
LocalDateTime now = LocalDateTime.now();
if (lowSpeed) {
highSpeedStartTime = null; // 重置恢复计时
if (lowSpeedStartTime == null) {
lowSpeedStartTime = now;
}
// 低速已持续超过5分钟且尚未入库则新增停机记录
if (!stopRecorded && Duration.between(lowSpeedStartTime, now).toMinutes() >= 5) {
ProStoppage stoppage = new ProStoppage();
stoppage.setStartDate(lowSpeedStartTime);
stoppage.setDuration(BigDecimal.ZERO); // 初始为0恢复后再更新
stoppage.setStopType("AUTO_LOW_SPEED");
stoppage.setRemark("stripSpeed<5 自动停机");
if (proStoppageService.save(stoppage)) {
currentStopId = stoppage.getStopid();
stopRecorded = true;
log.info("自动新增低速停机记录stopId={} start={}", currentStopId, lowSpeedStartTime);
} else {
log.warn("自动新增低速停机记录失败");
}
}
} else {
lowSpeedStartTime = null;
if (stopRecorded) {
if (highSpeedStartTime == null) {
highSpeedStartTime = now;
}
if (Duration.between(highSpeedStartTime, now).toMinutes() >= 1 && currentStopId != null) {
ProStoppage update = new ProStoppage();
update.setStopid(currentStopId);
update.setEndDate(now);
// duration 以秒存储
ProStoppage existing = proStoppageService.getById(currentStopId);
LocalDateTime start = existing != null && existing.getStartDate() != null ? existing.getStartDate() : highSpeedStartTime;
long seconds = Duration.between(start, now).getSeconds();
update.setDuration(BigDecimal.valueOf(seconds));
proStoppageService.updateById(update);
log.info("低速停机结束更新stopId={} duration={}s", currentStopId, seconds);
resetSpeedFlags();
}
} else {
highSpeedStartTime = null;
}
}
}
private void resetSpeedFlags() {
lowSpeedStartTime = null;
highSpeedStartTime = null;
// 不重置 stopRecorded/currentStopId避免短暂无值时丢失状态
}
}

View File

@@ -86,7 +86,7 @@ public class MessageSubscriptionRunner implements ApplicationRunner {
EntryMovementMessage msg =new EntryMovementMessage();
writeMessage( msg,entryMoveIds);
log.info("接收入口移动信号:从 {} 移动到 {} ", msg.getMaterialPlaceSource(), msg.getMaterialPlaceDestination());
logDataService.logInfo("TRACK","接收入口移动信号:从 {} 移动到 {} ", msg.getMaterialPlaceSource(), msg.getMaterialPlaceDestination());
logDataService.logInfo("TRACK","Received entry movement signal: from " + msg.getMaterialPlaceSource() + " to " + msg.getMaterialPlaceDestination());
opcReceiverHandler.onMessageReceived(OpcMessageType.ENTRY_MOVEMENT,msg);
} catch (Exception e) {
}
@@ -96,9 +96,9 @@ public class MessageSubscriptionRunner implements ApplicationRunner {
{
try {
ExitCutMessage msg = new ExitCutMessage();
writeMessage( msg,exitCutIds);
writeMessage(msg,exitCutIds);
log.info("接收到出口剪切信号:剪切类型 {},剪切长度{} ", msg.getCutType().toString(), msg.getCutLength());
logDataService.logInfo("TRACK","接收到出口剪切信号:剪切类型 {},剪切长度{} ", msg.getCutType().toString(), msg.getCutLength());
logDataService.logInfo("TRACK","Received exit cut signal: cut type " + msg.getCutType().toString() + ", cut length " + msg.getCutLength());
opcReceiverHandler.onMessageReceived(OpcMessageType.EXIT_CUT,msg);
} catch (Exception e) {
}
@@ -110,7 +110,7 @@ public class MessageSubscriptionRunner implements ApplicationRunner {
ExitMovementMessage msg = new ExitMovementMessage();
writeMessage( msg,exitMoveIds);
log.info("接收出口移动信号:从 {} 移动到 {} ", msg.getExSrc(), msg.getExDesc());
logDataService.logInfo("TRACK","接收出口移动信号:从 {} 移动到 {} ", msg.getExSrc(), msg.getExDesc());
logDataService.logInfo("TRACK","Received exit movement signal: from " + msg.getExSrc() + " to " + msg.getExDesc());
opcReceiverHandler.onMessageReceived(OpcMessageType.EXIT_MOVEMENT,msg);
} catch (Exception e) {
}
@@ -122,7 +122,7 @@ public class MessageSubscriptionRunner implements ApplicationRunner {
ExitMeasureMessage msg = new ExitMeasureMessage();
writeMessage(msg,exitMeasureIds);
log.info("接收出口称重信号:重量 {} ", msg.getWeight());
logDataService.logInfo("TRACK","接收出口称重信号:重量 {} ", msg.getWeight());
logDataService.logInfo("TRACK","Received exit weight signal: weight " + msg.getWeight());
opcReceiverHandler.onMessageReceived(OpcMessageType.EXIT_MEASURE,msg);
} catch (Exception e) {
}

View File

@@ -61,12 +61,12 @@ public class MessageTestSchedule extends BaseSchedule {
entryMsg.setTensionBr1Br2(BigDecimal.valueOf(rand.nextDouble()*100));
entryMsg.setTensionBr2Br3(BigDecimal.valueOf(rand.nextDouble()*100));
entryMsg.setStripSpeed(BigDecimal.valueOf(rand.nextDouble()*300));
entryMsg.setTensionCel(BigDecimal.valueOf(rand.nextDouble()*100));
// entryMsg.setTensionCel(BigDecimal.valueOf(rand.nextDouble()*100));
entryMsg.setCelLength(celLength);
entryMsg.setCelCapacity(celLength.divide(maxCelLength));
AppMeasureFurnaceMessage furMsg = new AppMeasureFurnaceMessage();
furMsg.setStripLocation(welderLength2);
// furMsg.setStripLocation(welderLength2);
// furMsg.setStripSpeed(BigDecimal.valueOf(rand.nextDouble()*100));
AppMeasureCoatMessage coatMsg = new AppMeasureCoatMessage();

View File

@@ -4,6 +4,7 @@ import com.fizz.business.domain.msg.OpcMessage;
import com.fizz.business.domain.msg.PdiSetup;
import com.kangaroohy.milo.model.ReadWriteEntity;
import com.kangaroohy.milo.service.MiloService;
import com.fizz.business.service.LogDataService;
import lombok.extern.log4j.Log4j2;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.stereotype.Service;
@@ -14,6 +15,7 @@ import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import static com.fizz.business.service.manager.OpcMessageIdsManager.findIdentifierByFieldName;
import static com.fizz.business.service.manager.OpcMessageIdsManager.pdiSetupIds;
@Service
@@ -24,6 +26,9 @@ public class OpcMessageSend {
@Resource
private MiloService miloService;
@Resource
private LogDataService logDataService;
private void sendPdiSetup(PdiSetup pdiSetup) {
try {
List<ReadWriteEntity> entities = getWriteEntities(pdiSetup, pdiSetupIds);
@@ -61,6 +66,78 @@ public class OpcMessageSend {
}
}
/**
* 通用写数据方法:通过字段名向指定点位写入单个值
* @param fieldName 字段名对象属性名例如coilId
* @param value 要写入的值
* @return 是否写入成功
*/
public boolean writeDataByFieldName(String fieldName, Object value) {
try {
String identifier = findIdentifierByFieldName(fieldName);
if (identifier == null) {
log.error("未找到字段名对应的 OPC 节点路径fieldName={}", fieldName);
return false;
}
List<ReadWriteEntity> entities = new ArrayList<>();
entities.add(ReadWriteEntity.builder()
.identifier(identifier)
.value(value)
.build());
miloService.writeToOpcUa(entities);
log.info("写入 OPC 数据成功fieldName={}, identifier={}, value={}", fieldName, identifier, value);
return true;
} catch (Exception e) {
log.error("写入 OPC 数据失败fieldName={}, value={},原因:{}", fieldName, value, e.getMessage(), e);
return false;
}
}
/**
* 通用写数据方法:向指定点位写入单个值(直接使用节点路径)
* @param identifier OPC 点位标识符(节点路径)
* @param value 要写入的值
* @return 是否写入成功
*/
public boolean writeData(String identifier, Object value) {
try {
List<ReadWriteEntity> entities = new ArrayList<>();
entities.add(ReadWriteEntity.builder()
.identifier(identifier)
.value(value)
.build());
miloService.writeToOpcUa(entities);
log.info("写入 OPC 数据成功identifier={}, value={}", identifier, value);
return true;
} catch (Exception e) {
log.error("写入 OPC 数据失败identifier={}, value={},原因:{}", identifier, value, e.getMessage(), e);
return false;
}
}
/**
* 批量写数据方法:向多个点位写入数据(直接使用节点路径)
* @param dataMap 点位标识符和值的映射key 为 identifiervalue 为要写入的值
* @return 是否全部写入成功
*/
public boolean batchWriteData(Map<String, Object> dataMap) {
try {
List<ReadWriteEntity> entities = new ArrayList<>();
for (Map.Entry<String, Object> entry : dataMap.entrySet()) {
entities.add(ReadWriteEntity.builder()
.identifier(entry.getKey())
.value(entry.getValue())
.build());
}
miloService.writeToOpcUa(entities);
logDataService.logInfo("WRITE","批量写入 OPC 数据成功,共"+ entities.size()+ "个点位");
return true;
} catch (Exception e) {
logDataService.logInfo("WRITE","批量写入 OPC 数据失败,原因:"+ e.getMessage()+","+ e);
return false;
}
}
private List<ReadWriteEntity> getWriteEntities(OpcMessage msg, Map<String,String> msgIds) {
List<ReadWriteEntity> entities = new ArrayList<>();
for (String key : msgIds.keySet()) {
@@ -76,7 +153,7 @@ public class OpcMessageSend {
} catch (NoSuchFieldException | IllegalAccessException e) {
// 处理字段不存在或访问异常,可记录日志或设置默认值
e.printStackTrace();
return new ArrayList<>();
return new ArrayList<>();
}
ReadWriteEntity entity = ReadWriteEntity.builder()

View File

@@ -2,7 +2,9 @@ package com.fizz.business.constants;
import com.fizz.business.constants.enums.DeviceEnum;
import static com.fizz.business.constants.enums.DeviceEnum.INS;
import static com.fizz.business.constants.enums.DeviceEnum.COAT;
public class CommonConstants {
@@ -50,7 +52,7 @@ public class CommonConstants {
public static final String SEG_STRIP_LEN = "SEG_STRIP_LEN";
//卷取机前一个设备idx
public static final DeviceEnum BEFORE_TR_IDX = INS;
public static final DeviceEnum BEFORE_TR_IDX = COAT;
// 工艺规程点位代码
public static final String SETUP_POINT_CODE = "SETUP_POINT_CODE";

View File

@@ -5,49 +5,69 @@ import lombok.Getter;
import java.util.*;
/**
* 细粒度设备枚举
* - position: 基准位置单位m
* - sectionType: 所属段(入口 / 工艺 / 出口)
* - sourceType: 数据来源(ENTRY/FURNACE/COAT/EXIT
* - paramFields: 对应AppMeasure*Message中的字段
* Fine-grained device enumeration / 细粒度设备枚举
* - position: base position (m) / 基准位置单位m
* - sectionType: section (entry / process / exit) / 所属段(入口 / 工艺 / 出口)
* - sourceType: data source (ENTRY/FURNACE/COAT/EXIT) / 数据来源
* - paramFields: corresponding fields in AppMeasure*Message / 对应AppMeasure*Message中的字段
*/
@Getter
public enum DeviceEnum {
// === 入口段 ===
POR1(0, "1#开卷机", 0.0, SectionType.ENTRY, SourceType.ENTRY, Arrays.asList("tensionPorBr1", "stripSpeed")),
POR2(1, "2#开卷机", 0.0, SectionType.ENTRY, SourceType.ENTRY, Arrays.asList("tensionPorBr2", "stripSpeed")),
WELDER(2, "焊机", 4.98, SectionType.ENTRY, SourceType.ENTRY, Arrays.asList("weldStatus")),
ENL1(3, "入口活套1", 19.04, SectionType.PROCESS, SourceType.ENTRY, Arrays.asList("celLength", "celCapacity", "tensionCel")),
ENL2(4, "入口活套2", 167.09, SectionType.PROCESS, SourceType.ENTRY, Arrays.asList("celLength", "celCapacity", "tensionCel")),
ENL3(5, "入口活套3", 198.19, SectionType.PROCESS, SourceType.ENTRY, Arrays.asList("celLength", "celCapacity", "tensionCel")),
// === Entry section / 入口段 ===
POR1(0, "Uncoiler #1", 0.0, SectionType.ENTRY, SourceType.ENTRY, Arrays.asList("tensionPorBr1", "stripSpeed","tensionBr45Br6")),
POR2(1, "Uncoiler #2", 0.0, SectionType.ENTRY, SourceType.ENTRY, Arrays.asList("tensionPorBr2", "stripSpeed","tensionBr45Br6")),
WELDER(2, "Welder", 4.98, SectionType.ENTRY, SourceType.ENTRY, Arrays.asList("weldStatus")),
ENL1(3, "Entry Looper #1", 19.041, SectionType.PROCESS, SourceType.ENTRY, Arrays.asList("celLength", "celCapacity", "tensionCel")),
ENL2(4, "Entry Looper #2", 167.091, SectionType.PROCESS, SourceType.ENTRY, Arrays.asList("celLength", "celCapacity", "tensionCel")),
ENL3(5, "Entry Looper #3", 198.191, SectionType.PROCESS, SourceType.ENTRY, Arrays.asList("celLength", "celCapacity", "tensionCel","tensionBr45Br6")),
// === 工艺段 ===
CLEAN(6, "清洗段", 264.803, SectionType.PROCESS, SourceType.FURNACE, Arrays.asList("cleaningVoltage", "cleaningCurrent", "alkaliConcentration", "alkaliTemperature")),
FUR1(7, "退火炉-预热段", 302.837, SectionType.PROCESS, SourceType.FURNACE, Arrays.asList("phfExitStripTemp", "potTemperature", "gasConsumption")),
FUR2(8, "退火炉-加热段", 381.057, SectionType.PROCESS, SourceType.FURNACE, Arrays.asList("rtfExitStripTemp", "zincPotPower")),
FUR3(9, "退火炉-冷却段", 416.837, SectionType.PROCESS, SourceType.FURNACE, Arrays.asList("jcsExitStripTemp", "coolingTowerStripTemp")),
FUR4(10, "退火炉-均衡段", 432.16, SectionType.PROCESS, SourceType.FURNACE, Arrays.asList("scsExitStripTemp")),
POT(11, "锌锅", 442.994, SectionType.PROCESS, SourceType.COAT, Arrays.asList("scsExitStripTemp")),
TOWER(12, "冷却塔", 563.594, SectionType.PROCESS, SourceType.COAT, Arrays.asList("scsExitStripTemp")),
TM(13, "光整机", 586.529, SectionType.PROCESS, SourceType.COAT, Arrays.asList("tensionBr5Tm", "stripSpeedTmExit")),
TL(14, "拉矫机", 612.909, SectionType.PROCESS, SourceType.COAT, Arrays.asList("tlElongation", "tensionTlBr7")),
COAT(15, "后处理段", 712.699, SectionType.PROCESS, SourceType.COAT, Arrays.asList(
"avrCoatingWeightTop","stdCoatingWeightTop","maxCoatingWeightTop","minCoatingWeightTop",
"avrCoatingWeightBottom","stdCoatingWeightBottom","maxCoatingWeightBottom","minCoatingWeightBottom",
"airKnifePressure","airKnifeFlow","airKnifeGap","stripSpeedTmExit","tensionBr5Tm",
"tensionTmBr6","tensionBr5Br6","tmMask","tmElongation","rollForceOperator","rollForceDrive",
"motorTorque","bendingForce","antiCrimpingRollMesh","billyRollMesh",
"tensionTlBr7","tensionBr6Br7","tlFlag","tlElongation","levelingUnit1Mesh","levelingUnit2Mesh",
"antiCrossBowUnitMesh","tensionBr7Br8","stripSpeedAfp","stripTempAfp"
// === Process section / 工艺段 ===
CLEAN(6, "Cleaning Section", 264.803, SectionType.PROCESS, SourceType.FURNACE, Arrays.asList("cleaningVoltage", "cleaningCurrent", "alkaliConcentration", "alkaliTemperature")),
FUR1(7, "Annealing Furnace - Preheating", 302.837, SectionType.PROCESS, SourceType.FURNACE, Arrays.asList(
"phFurnaceTemperatureActual",
"nof1FurnaceTemperatureActual", "nof2FurnaceTemperatureActual", "nof3FurnaceTemperatureActual", "nof4FurnaceTemperatureActual",
"nofPlateTemperatureActual",
"nofFurnacePressureActual"
)),
FUR2(8, "Annealing Furnace - Heating", 381.057, SectionType.PROCESS, SourceType.FURNACE, Arrays.asList(
"rtf1FurnaceTemperatureActual", "rtf2FurnaceTemperatureActual",
"rtfPlateTemperatureActual",
"rtfFurnacePressureActual"
)),
FUR3(9, "Annealing Furnace - Cooling", 398.947, SectionType.PROCESS, SourceType.FURNACE, Arrays.asList(
"jcf1FurnaceTemperatureActual",
"jcfFan1ActualSpeed", "jcfFan2ActualSpeed", "jcfFan3ActualSpeed", "jcfFan4ActualSpeed"
)),
FUR4(10, "Annealing Furnace - Equalizing", 414.27, SectionType.PROCESS, SourceType.FURNACE, Arrays.asList(
"lthFurnaceTemperatureActual",
"tdsFurnaceTemperatureActual",
"lbzFurnaceTemperatureActual",
"tdsPlateTemperatureActual",
"tdsFurnacePressureActual"
)),
// === 出口段 ===
CXL1(16, "出口活套1", 720.709, SectionType.EXIT, SourceType.EXIT, Arrays.asList("cxlLength", "cxlCapacity", "tensionCxl")),
CXL2(17, "出口活套2", 888.789, SectionType.EXIT, SourceType.EXIT, Arrays.asList("cxlLength", "cxlCapacity", "tensionCxl")),
// INS(18, "检查站", 940.561, SectionType.EXIT, SourceType.EXIT, Arrays.asList("inspectionStatus")),
TR(19, "卷取机", 952.819, SectionType.EXIT, SourceType.EXIT, Arrays.asList("coilLength", "speedExitSection", "tensionBr9Tr")),
EXC(20, "卸卷小车", 9999999.0, SectionType.EXIT, SourceType.EXIT, Collections.emptyList()),
WEIGHT(21, "称重鞍座", 9999999.0, SectionType.EXIT, SourceType.EXIT, Collections.emptyList());
POT(11, "Zinc Pot", 425.104, SectionType.PROCESS, SourceType.COAT, Arrays.asList("potTemperature")),
TOWER(12, "Cooling Tower", 545.659, SectionType.PROCESS, SourceType.COAT, Arrays.asList("coolingTowerTemperature")),
TM(13, "Temper Mill", 568.639, SectionType.PROCESS, SourceType.COAT, Arrays.asList("tensionBr5Tm", "stripSpeedTmExit")),
TL(14, "Tension Leveler", 595.019, SectionType.PROCESS, SourceType.COAT, Arrays.asList("tlElongation", "tensionTlBr7")),
COAT(15, "Post-treatment Section", 694.809, SectionType.PROCESS, SourceType.COAT, Arrays.asList(
"avrCoatingWeightTop","stdCoatingWeightTop","maxCoatingWeightTop","minCoatingWeightTop",
"avrCoatingWeightBottom","stdCoatingWeightBottom","maxCoatingWeightBottom","minCoatingWeightBottom",
"airKnifePressure","airKnifeFlow","airKnifeGap","stripSpeedTmExit","tensionBr8Tm",
"tensionTmBr9","tensionBr8Br9","tmMask","tmElongation","rollForceOperator","rollForceDrive",
"motorTorque","bendingForce","antiCrimpingRollMesh","billyRollMesh",
"tensionTlBr10Br11","tensionBr9toBr10Br11","tlFlag","tlElongation","levelingUnit1Mesh","levelingUnit2Mesh",
"antiCrossBowUnitMesh","tensionBr10Br11Br12","stripSpeedAfp","stripTempAfp",
"potTemperature","coolingTowerTemperature","potPower"
)),
// === Exit section / 出口段 ===
CXL1(16, "Exit Looper #1", 702.819, SectionType.EXIT, SourceType.EXIT, Arrays.asList("cxlLength", "cxlCapacity", "tensionCxl")),
CXL2(17, "Exit Looper #2", 870.899, SectionType.EXIT, SourceType.EXIT, Arrays.asList("cxlLength", "cxlCapacity", "tensionCxl")),
// INS(18, "Inspection Station", 940.561, SectionType.EXIT, SourceType.EXIT, Arrays.asList("inspectionStatus")),
TR(18, "Recoiler", 934.929, SectionType.EXIT, SourceType.EXIT, Arrays.asList("coilLength", "speedExitSection", "tensionBr9Tr")),
EXC(19, "Coil Car", 9999999.0, SectionType.EXIT, SourceType.EXIT, Collections.emptyList()),
WEIGHT(20, "Weighing Saddle", 9999999.0, SectionType.EXIT, SourceType.EXIT, Collections.emptyList());
private final int idx;
private final String desc;

View File

@@ -8,17 +8,17 @@ import lombok.Getter;
*/
@Getter
public enum ExceptionCodeEnum {
// 系统级错误
SYSTEM_ERROR("SYS_500", "系统错误"),
SERVICE_UNAVAILABLE("SYS_503", "服务不可用"),
// System-level errors / 系统级错误
SYSTEM_ERROR("SYS_500", "System error"),
SERVICE_UNAVAILABLE("SYS_503", "Service unavailable"),
// 业务级错误
DATA_NOT_FOUND("BIZ_404", "数据不存在"),
DATA_VALIDATION_FAILED("BIZ_400", "数据验证失败"),
UNAUTHORIZED_ACCESS("BIZ_401", "未授权访问"),
// Business-level errors / 业务级错误
DATA_NOT_FOUND("BIZ_404", "Data not found"),
DATA_VALIDATION_FAILED("BIZ_400", "Data validation failed"),
UNAUTHORIZED_ACCESS("BIZ_401", "Unauthorized access"),
// 默认错误
ERROR("ERR_500", "未知错误");
// Default error / 默认错误
ERROR("ERR_500", "Unknown error");
private final String code;
private final String message;

View File

@@ -10,6 +10,7 @@ import com.fizz.business.service.CrmPdiPlanService;
import com.fizz.business.comm.OPC.OpcMessageSend;
import com.fizz.business.service.client.RedisCacheManager;
import com.fizz.business.service.impl.BeanFactory;
import com.fizz.business.service.strip.SegmentTrackerService;
import com.fizz.business.utils.MatmapUtil;
import com.fizz.business.utils.WebSocketUtil;
import com.fizz.business.vo.CrmPdiPlanVO;
@@ -40,6 +41,14 @@ public enum L1OperateMatEnum implements IEnum<String>, IOperateMat<L1OperateMatF
MatmapUtil.setMatmap(form.getPorIdx(), form.getEntryMatId(), form.getPlanId(), form.getPlanNo());
// 钢卷上线时, 缓存工艺规程
// BeanFactory.getBean(RedisCacheManager.class).setCoilSetup(form.getPlanId());
// ONLINE 时同步下发入口参数 + 张力下一设定值
try {
BeanFactory.getBean(SegmentTrackerService.class)
.sendAllPdiOnOnline(form.getEntryMatId(), form.getPorIdx());
} catch (Exception e) {
BeanFactory.getBean(com.fizz.business.service.LogDataService.class)
.logWarn("L1-ONLINE", "ONLINE下发异常, coilId={}, porIdx={}, err={}", form.getEntryMatId(), form.getPorIdx(), e.toString());
}
WebSocketUtil.sendSignalMsg(form);
WebSocketUtil.sendMatmapMsg();
}
@@ -73,8 +82,6 @@ public enum L1OperateMatEnum implements IEnum<String>, IOperateMat<L1OperateMatF
PRODUCT("生产完成") {
@Override
public void operate(L1OperateMatForm form) {
log.error("==================================================================");
log.error("form.planId={},entryMatId={}", form.getPlanId(), form.getEntryMatId());
PRODUCT.syncPlanStatus(form.getPlanId(),form.getEntryMatId());
WebSocketUtil.sendSignalMsg(form);
}
@@ -82,11 +89,11 @@ public enum L1OperateMatEnum implements IEnum<String>, IOperateMat<L1OperateMatF
PAY_OVER("甩尾") {
@Override
public void operate(L1OperateMatForm form) {
ArrayList<String> status = Lists.newArrayList(PlanStatusEnum.PRODUCING.name(), PlanStatusEnum.PRODUCT.name());
// ArrayList<String> status = Lists.newArrayList(PlanStatusEnum.PRODUCING.name(), PlanStatusEnum.PRODUCT.name());
CrmPdiPlanService planClient = BeanFactory.getBean(CrmPdiPlanService.class);
CrmPdiPlanVO plan = planClient.getByCoilIdAndOperId(form.getEntryMatId());
Assert.notNull(plan, "计划[{}]不存在", plan.getId());
Assert.isTrue(status.contains(plan.getStatus()), "当前状态[{}]不支持甩尾", plan.getStatus());
// Assert.isTrue(status.contains(plan.getStatus()), "当前状态[{}]不支持甩尾", plan.getStatus());
MatmapUtil.clearMatmap(form.getPorIdx());
WebSocketUtil.sendSignalMsg(form);
WebSocketUtil.sendMatmapMsg();
@@ -124,10 +131,14 @@ public enum L1OperateMatEnum implements IEnum<String>, IOperateMat<L1OperateMatF
private void syncPlanStatus(String planId, String matId) {
CrmPdiPlanService planClient = BeanFactory.getBean(CrmPdiPlanService.class);
planClient.changeStatus(ChangePlanStatusForm.builder()
boolean ok = planClient.changeStatus(ChangePlanStatusForm.builder()
.operation(this.name())
.id(planId)
.matId(matId)
.build());
if (!ok) {
throw new IllegalStateException(String.format("计划状态同步失败, operation=%s, planId=%s, matId=%s", this.name(), planId, matId));
}
}
}

View File

@@ -17,7 +17,7 @@ import java.util.Map;
@Getter
@AllArgsConstructor
public enum WsTypeEnum {
alarm, track_position, track_measure, track_signal, track_matmap,calc_setup_result;
alarm, track_position, track_measure, track_signal, track_matmap, calc_setup_result, device_history_trend, device_chart_data, device_field_trend;
private static final Map<String, WsTypeEnum> MAP = new HashMap<>(8);

View File

@@ -0,0 +1,93 @@
package com.fizz.business.controller;
import com.fizz.business.domain.BizSendTemplate;
import com.fizz.business.domain.BizSendTemplateItem;
import com.fizz.business.domain.dto.SendTemplateItemsBatchSaveDTO;
import com.fizz.business.domain.vo.BizSendTemplateVO;
import com.fizz.business.service.IBizSendTemplateItemService;
import com.fizz.business.service.IBizSendTemplateService;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.utils.SecurityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.Date;
import java.util.List;
/**
* 发送模板配置 Controller
*/
@RestController
@RequestMapping("/business/sendTemplate")
public class BizSendTemplateController extends BaseController {
@Autowired
private IBizSendTemplateService templateService;
@Autowired
private IBizSendTemplateItemService templateItemService;
/**
* 按模板编码获取模板(含明细)
*/
@GetMapping("/{templateCode}")
public AjaxResult getByCode(@PathVariable String templateCode) {
BizSendTemplateVO vo = templateService.getTemplateWithItems(templateCode);
if (vo == null) {
return AjaxResult.error("Template not found");
}
return AjaxResult.success(vo);
}
/**
* 更新模板主表(如 deviceName
*/
@PutMapping
public AjaxResult updateTemplate(@RequestBody BizSendTemplate template) {
if (template == null || template.getTemplateId() == null) {
return AjaxResult.error("templateId is required");
}
template.setUpdateBy(SecurityUtils.getUsername());
template.setUpdateTime(new Date());
return toAjax(templateService.updateById(template));
}
/**
* 批量更新模板明细address/defaultValueRaw/enabled等
*/
@PutMapping("/items")
public AjaxResult updateTemplateItems(@RequestBody List<BizSendTemplateItem> items) {
if (items == null || items.isEmpty()) {
return AjaxResult.success();
}
Date now = new Date();
String username = SecurityUtils.getUsername();
for (BizSendTemplateItem it : items) {
it.setUpdateBy(username);
it.setUpdateTime(now);
}
return toAjax(templateItemService.updateItemsBatch(items));
}
/**
* 模板明细批量保存(新增/更新/删除)
*/
@PutMapping("/items/batchSave")
public AjaxResult batchSaveItems(@RequestBody SendTemplateItemsBatchSaveDTO dto) {
if (dto == null || dto.getTemplateId() == null) {
return AjaxResult.error("templateId is required");
}
try {
Boolean ok = templateItemService.batchSave(
dto.getTemplateId(),
dto.getItems(),
dto.getDeleteIds(),
SecurityUtils.getUsername()
);
return toAjax(ok);
} catch (IllegalArgumentException e) {
return AjaxResult.error(e.getMessage());
}
}
}

View File

@@ -4,7 +4,9 @@ import com.fizz.business.domain.CrmPdoExcoil;
import com.fizz.business.form.CrmPdoExcoilForm;
import com.fizz.business.service.CrmPdoExcoilService;
import com.ruoyi.common.annotation.Anonymous;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.page.TableDataInfo;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.web.bind.annotation.*;
@@ -16,7 +18,7 @@ import java.util.List;
@RequestMapping("/api/pdo")
@Tag(name ="实绩管理")
@Anonymous
public class CrmPdoExcoilController {
public class CrmPdoExcoilController extends BaseController {
@Resource
private CrmPdoExcoilService crmPdoExcoilService;
@@ -48,7 +50,16 @@ public class CrmPdoExcoilController {
@PostMapping("/list")
@Operation(summary ="查询实绩列表")
public R<List<CrmPdoExcoil>> list(@RequestBody CrmPdoExcoilForm form) {
return R.ok(crmPdoExcoilService.listAll(form));
public TableDataInfo list(@RequestBody CrmPdoExcoilForm form) {
// 设置分页参数默认每页20条
if (form.getPageNum() == null || form.getPageNum() < 1) {
form.setPageNum(1);
}
if (form.getPageSize() == null || form.getPageSize() < 1) {
form.setPageSize(20);
}
com.github.pagehelper.PageHelper.startPage(form.getPageNum(), form.getPageSize());
List<CrmPdoExcoil> list = crmPdoExcoilService.listAll(form);
return getDataTable(list);
}
}

View File

@@ -0,0 +1,38 @@
package com.fizz.business.controller;
import com.fizz.business.service.DashboardService;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
/**
* 首页仪表板相关接口
*/
@RestController
public class DashboardController extends BaseController {
@Resource
private DashboardService dashboardService;
/**
* 当前生产中的计划信息crm_pdi_plan.status = 'PRODUCING'
*/
@GetMapping("/api/business/dashboard/currentPlan")
public AjaxResult getCurrentProducingPlan() {
return AjaxResult.success(dashboardService.getCurrentProducingPlan());
}
/**
* 当前生产卷的关键工艺参数
* - 从 cpl_segment_total.total_values_json 解析
* - 键名来自 DeviceEnum.paramFields
*/
@GetMapping("/api/business/dashboard/currentProcess")
public AjaxResult getCurrentProcessParams() {
return AjaxResult.success(dashboardService.getCurrentProcessParams());
}
}

View File

@@ -0,0 +1,55 @@
package com.fizz.business.controller;
import com.fizz.business.constants.enums.DeviceEnum;
import com.ruoyi.common.annotation.Anonymous;
import com.ruoyi.common.core.domain.R;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.Data;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
@RestController
@RequestMapping("/api/deviceEnum")
@Tag(name = "设备枚举")
@Anonymous
public class DeviceEnumController {
@GetMapping("/all")
@Operation(description = "获取DeviceEnum全量定义用于前端动态渲染")
public R<List<DeviceDefVO>> all() {
List<DeviceDefVO> list = Arrays.stream(DeviceEnum.values())
.map(DeviceDefVO::from)
.collect(Collectors.toList());
return R.ok(list);
}
@Data
public static class DeviceDefVO {
private String deviceCode; // DeviceEnum.name()
private Integer idx;
private String desc;
private Double basePosition;
private String sectionType;
private String sourceType;
private List<String> paramFields;
public static DeviceDefVO from(DeviceEnum e) {
DeviceDefVO vo = new DeviceDefVO();
vo.setDeviceCode(e.name());
vo.setIdx(e.getIdx());
vo.setDesc(e.getDesc());
vo.setBasePosition(e.getBasePosition());
vo.setSectionType(e.getSectionType().name());
vo.setSourceType(e.getSourceType().name());
vo.setParamFields(e.getParamFields());
return vo;
}
}
}

View File

@@ -0,0 +1,82 @@
package com.fizz.business.controller;
import com.fizz.business.domain.msg.AppMeasureCoatMessage;
import com.fizz.business.domain.msg.AppMeasureEntryMessage;
import com.fizz.business.domain.msg.AppMeasureExitMessage;
import com.fizz.business.domain.msg.AppMeasureFurnaceMessage;
import com.ruoyi.common.annotation.Anonymous;
import com.ruoyi.common.core.domain.R;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.Data;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.lang.reflect.Field;
import java.util.*;
@RestController
@RequestMapping("/api/deviceFieldMeta")
@Tag(name = "设备字段元数据")
@Anonymous
public class DeviceFieldMetaController {
@GetMapping("/all")
@Operation(description = "获取测量字段的友好文案(来自 @Schema(description)")
public R<Map<String, FieldMetaVO>> all() {
Map<String, FieldMetaVO> map = new HashMap<>();
// 4个消息类全扫一遍
collect(map, AppMeasureEntryMessage.class);
collect(map, AppMeasureFurnaceMessage.class);
collect(map, AppMeasureCoatMessage.class);
collect(map, AppMeasureExitMessage.class);
return R.ok(map);
}
private void collect(Map<String, FieldMetaVO> map, Class<?> clazz) {
for (Field f : clazz.getDeclaredFields()) {
String fieldName = f.getName();
Schema schema = f.getAnnotation(Schema.class);
if (schema == null) continue;
String desc = schema.description();
if (desc == null || desc.trim().isEmpty()) continue;
FieldMetaVO vo = new FieldMetaVO();
vo.setLabel(parseLabel(desc));
vo.setUnit(parseUnit(desc));
vo.setDescription(desc);
map.putIfAbsent(fieldName, vo);
}
}
// 例:"上层平均涂层重量 (g/m²)" -> label=上层平均涂层重量
private String parseLabel(String desc) {
int idx = desc.indexOf('(');
if (idx > 0) return desc.substring(0, idx).trim();
idx = desc.indexOf('');
if (idx > 0) return desc.substring(0, idx).trim();
return desc.trim();
}
// 例:"上层平均涂层重量 (g/m²)" -> unit=g/m²
private String parseUnit(String desc) {
int l = desc.indexOf('(');
int r = desc.indexOf(')');
if (l >= 0 && r > l) return desc.substring(l + 1, r).trim();
l = desc.indexOf('');
r = desc.indexOf('');
if (l >= 0 && r > l) return desc.substring(l + 1, r).trim();
return "";
}
@Data
public static class FieldMetaVO {
private String label;
private String unit;
private String description;
}
}

View File

@@ -0,0 +1,62 @@
package com.fizz.business.controller;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.fizz.business.domain.DeviceSnapshot;
import com.fizz.business.mapper.DeviceSnapshotMapper;
import com.ruoyi.common.annotation.Anonymous;
import com.ruoyi.common.core.domain.R;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.time.LocalDateTime;
import java.util.List;
@RestController
@RequestMapping("/api/deviceSnapshot")
@Tag(name = "设备数据快照")
@Anonymous
@RequiredArgsConstructor
public class DeviceSnapshotController {
private final DeviceSnapshotMapper deviceSnapshotMapper;
@GetMapping("/latest")
@Operation(description = "获取最新N条设备快照可按deviceCode过滤")
public R<List<DeviceSnapshot>> latest(@RequestParam(value = "limit", defaultValue = "60") Integer limit,
@RequestParam(value = "deviceCode", required = false) String deviceCode) {
LambdaQueryWrapper<DeviceSnapshot> qw = new LambdaQueryWrapper<DeviceSnapshot>()
.orderByDesc(DeviceSnapshot::getCreateTime)
.last("limit " + Math.max(1, Math.min(limit, 500)));
if (deviceCode != null && !deviceCode.isEmpty()) {
qw.eq(DeviceSnapshot::getDeviceCode, deviceCode);
}
return R.ok(deviceSnapshotMapper.selectList(qw));
}
@GetMapping("/range")
@Operation(description = "按时间范围查询设备快照可按deviceCode过滤")
public R<List<DeviceSnapshot>> range(@RequestParam("start") String start,
@RequestParam("end") String end,
@RequestParam(value = "deviceCode", required = false) String deviceCode) {
LocalDateTime startTime = LocalDateTime.parse(start);
LocalDateTime endTime = LocalDateTime.parse(end);
LambdaQueryWrapper<DeviceSnapshot> qw = new LambdaQueryWrapper<DeviceSnapshot>()
.between(DeviceSnapshot::getCreateTime, startTime, endTime)
.orderByAsc(DeviceSnapshot::getCreateTime);
if (deviceCode != null && !deviceCode.isEmpty()) {
qw.eq(DeviceSnapshot::getDeviceCode, deviceCode);
}
return R.ok(deviceSnapshotMapper.selectList(qw));
}
}

View File

@@ -0,0 +1,69 @@
package com.fizz.business.controller;
import com.fizz.business.form.OpcBatchWriteDataForm;
import com.fizz.business.form.OpcWriteDataForm;
import com.fizz.business.service.OpcDataService;
import com.ruoyi.common.annotation.Anonymous;
import com.ruoyi.common.core.domain.R;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
/**
* OPC 数据读写控制器
*/
@Slf4j
@RestController
@RequiredArgsConstructor
@RequestMapping("/api/opc/data")
@Tag(name = "OPC 数据读写")
@ConditionalOnProperty(prefix = "kangaroohy.milo", name = "enabled", havingValue = "true")
@Anonymous
public class OpcDataController {
private final OpcDataService opcDataService;
/**
* 向单个点位写入数据(通过字段名)
*/
@Operation(summary = "向单个点位写入数据", description = "通过字段名向指定的 OPC 点位写入数据")
@PostMapping("/write")
public R<?> writeData(@Valid @RequestBody OpcWriteDataForm form) {
try {
boolean success = opcDataService.writeData(form);
if (success) {
return R.ok("写入成功");
} else {
return R.fail("写入失败,可能是字段名未找到对应的 OPC 节点路径,请查看日志");
}
} catch (Exception e) {
log.error("写入 OPC 数据异常", e);
return R.fail("写入异常:" + e.getMessage());
}
}
/**
* 批量向多个点位写入数据(通过字段名)
*/
@Operation(summary = "批量向多个点位写入数据", description = "通过字段名向多个 OPC 点位批量写入数据")
@PostMapping("/batchWrite")
public R<?> batchWriteData(@Valid @RequestBody OpcBatchWriteDataForm form) {
try {
boolean success = opcDataService.batchWriteData(form);
if (success) {
return R.ok("批量写入成功,共 " + form.getDataList().size() + " 个点位");
} else {
return R.fail("批量写入失败,可能是部分字段名未找到对应的 OPC 节点路径,请查看日志");
}
} catch (Exception e) {
log.error("批量写入 OPC 数据异常", e);
return R.fail("批量写入异常:" + e.getMessage());
}
}
}

View File

@@ -4,7 +4,6 @@ import java.util.List;
import javax.servlet.http.HttpServletResponse;
import com.fizz.business.service.IPdiSetupService;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import com.ruoyi.common.annotation.Log;
@@ -12,13 +11,12 @@ import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.enums.BusinessType;
import com.fizz.business.domain.PdiSetups;
import com.fizz.business.service.IPdiSetupService;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.common.core.page.TableDataInfo;
/**
* 生产计划的参数详情Controller
*
*
* @author Joshi
* @date 2025-09-25
*/
@@ -53,12 +51,12 @@ public class PdiSetupController extends BaseController
}
/**
* 获取生产计划的参数详情详细信息
* 获取张力参数详细信息
*/
@GetMapping(value = "/{id}")
public AjaxResult getInfo(@PathVariable("id") Long id)
{
return success(pdiSetupService.selectPdiSetupByid(id));
return success(pdiSetupService.selectPdiSetupById(id));
}
/**
@@ -82,12 +80,12 @@ public class PdiSetupController extends BaseController
}
/**
* 删除生产计划的参数详情
* 删除张力参数
*/
@Log(title = "生产计划的参数详情", businessType = BusinessType.DELETE)
@DeleteMapping("/{ids}")
@Log(title = "张力参数", businessType = BusinessType.DELETE)
@DeleteMapping("/{ids}")
public AjaxResult remove(@PathVariable Long[] ids)
{
return toAjax(pdiSetupService.deletePdiSetupByids(ids));
return toAjax(pdiSetupService.deletePdiSetupByIds(ids));
}
}

View File

@@ -3,6 +3,8 @@ package com.fizz.business.controller;
import com.fizz.business.domain.ProStoppage;
import com.fizz.business.form.ProStoppageForm;
import com.fizz.business.service.ProStoppageService;
import com.fizz.business.service.ProStoppageTypeService;
import com.fizz.business.domain.vo.ProStoppageTypeVO;
import com.ruoyi.common.annotation.Anonymous;
import com.ruoyi.common.core.domain.R;
import io.swagger.v3.oas.annotations.Operation;
@@ -22,6 +24,9 @@ public class ProStoppageController {
@Resource
private ProStoppageService proStoppageService;
@Resource
private ProStoppageTypeService proStoppageTypeService;
// @PostMapping("/add")
// @ApiOperation("新增停机记录")
// public R<Boolean> add(@RequestBody ProStoppage proStoppage) {
@@ -51,4 +56,15 @@ public class ProStoppageController {
public R<List<Object>> calc(@RequestBody ProStoppageForm form) {
return R.ok(proStoppageService.calc(form));
}
@GetMapping("/types")
@Operation(summary = "查询停机类型")
public R<List<ProStoppageTypeVO>> types() {
return R.ok(proStoppageTypeService.listAll().stream().map(item -> {
ProStoppageTypeVO vo = new ProStoppageTypeVO();
vo.setStopType(item.getStopType());
vo.setRemark(item.getRemark());
return vo;
}).collect(java.util.stream.Collectors.toList()));
}
}

View File

@@ -0,0 +1,113 @@
package com.fizz.business.controller;
import com.fizz.business.domain.BizSendJob;
import com.fizz.business.domain.dto.SendJobCreateDTO;
import com.fizz.business.domain.dto.SendJobQueryDTO;
import com.fizz.business.domain.vo.SendJobDetailVO;
import com.fizz.business.service.ISendJobService;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.enums.BusinessType;
import com.fizz.business.domain.vo.FurnaceSendCoilInfoVO;
import com.fizz.business.domain.vo.SendJobLastSuccessVO;
import com.fizz.business.service.ISendJobQueryService;
import com.fizz.business.utils.RedisUtil;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.ruoyi.common.annotation.Log;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
* 发送任务 Controller
*/
@RestController
@RequestMapping("/business/sendJob")
public class SendJobController extends BaseController {
@Autowired
private ISendJobService sendJobService;
@Autowired
private ISendJobQueryService sendJobQueryService;
/**
* 创建发送任务
*/
@Log(title = "发送任务", businessType = BusinessType.INSERT)
@PostMapping
public AjaxResult create(@Validated @RequestBody SendJobCreateDTO dto) {
Integer jobId = sendJobService.createSendJob(dto);
return success(jobId);
}
/**
* 查询发送任务列表
*/
@GetMapping("/list")
public TableDataInfo list(SendJobQueryDTO query) {
startPage(); // 使用BaseController的分页方法
List<BizSendJob> list = sendJobService.selectSendJobList(query);
return getDataTable(list);
}
/**
* 获取发送任务详情
*/
@GetMapping("/{jobId}")
public AjaxResult getDetail(@PathVariable Integer jobId) {
SendJobDetailVO detail = sendJobService.selectSendJobDetail(jobId);
return success(detail);
}
/**
* 删除发送任务(逻辑删除)
*/
@Log(title = "发送任务", businessType = BusinessType.DELETE)
@DeleteMapping("/{jobIds}")
public AjaxResult remove(@PathVariable Integer[] jobIds) {
return toAjax(sendJobService.deleteSendJobByJobIds(jobIds));
}
/**
* 执行发送任务
*/
@Log(title = "发送任务", businessType = BusinessType.UPDATE)
@PostMapping("/{jobId}/execute")
public AjaxResult execute(@PathVariable Integer jobId) {
return toAjax(sendJobService.executeSendJob(jobId));
}
/**
* 查询最近一次成功发送(用于界面显示上次发送时间 + 推荐上次值)
* @param groupType DRIVE / FURNACE
*/
@GetMapping("/lastSuccess")
public AjaxResult lastSuccess(@RequestParam String groupType) {
SendJobLastSuccessVO vo = sendJobQueryService.getLastSuccess(groupType);
return AjaxResult.success(vo);
}
/**
* 获取上次炉火写入的钢卷信息
* @return 上次写入的钢卷信息coilId、planId、sendTime
*/
@GetMapping("/furnace/lastCoilInfo")
public AjaxResult getLastFurnaceSendCoilInfo() {
try {
String jsonValue = RedisUtil.getValue("furnace:send:coil:info");
if (jsonValue == null || jsonValue.isEmpty()) {
return AjaxResult.success(null);
}
ObjectMapper objectMapper = new ObjectMapper();
FurnaceSendCoilInfoVO coilInfo = objectMapper.readValue(jsonValue, FurnaceSendCoilInfoVO.class);
return AjaxResult.success(coilInfo);
} catch (Exception e) {
return AjaxResult.error("Failed to obtain the information of the last furnace fire to write the coil: " + e.getMessage());
}
}
}

View File

@@ -0,0 +1,83 @@
package com.fizz.business.controller;
import java.util.List;
import com.ruoyi.common.annotation.Anonymous;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.enums.BusinessType;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import com.fizz.business.domain.SetupTensionAllLine;
import com.fizz.business.service.ISetupTensionAllLineService;
/**
* 全线张力Controller无权限控制
*
* 三主键steelGrade + thick + yieldStren
*/
@RestController
@RequestMapping("/business/tension/all-line")
@Anonymous
public class SetupTensionAllLineController extends BaseController
{
@Autowired
private ISetupTensionAllLineService service;
/**
* 查询全线张力列表
*/
@GetMapping("/list")
public TableDataInfo list(SetupTensionAllLine query)
{
startPage();
List<SetupTensionAllLine> list = service.selectList(query);
return getDataTable(list);
}
/**
* 获取全线张力详细信息(按三主键)
*/
@GetMapping
public AjaxResult getInfo(@RequestParam("steelGrade") String steelGrade,
@RequestParam("thick") Float thick,
@RequestParam("yieldStren") Float yieldStren)
{
return success(service.selectByKey(steelGrade, thick, yieldStren));
}
/**
* 新增全线张力
*/
@Log(title = "全线张力", businessType = BusinessType.INSERT)
@PostMapping
public AjaxResult add(@RequestBody SetupTensionAllLine entity)
{
return toAjax(service.insert(entity));
}
/**
* 修改全线张力(按三主键定位)
*/
@Log(title = "全线张力", businessType = BusinessType.UPDATE)
@PutMapping
public AjaxResult edit(@RequestBody SetupTensionAllLine entity)
{
return toAjax(service.updateByKey(entity));
}
/**
* 删除全线张力(按三主键)
*/
@Log(title = "全线张力", businessType = BusinessType.DELETE)
@DeleteMapping
public AjaxResult remove(@RequestParam("steelGrade") String steelGrade,
@RequestParam("thick") Float thick,
@RequestParam("yieldStren") Float yieldStren)
{
return toAjax(service.deleteByKey(steelGrade, thick, yieldStren));
}
}

View File

@@ -0,0 +1,69 @@
package com.fizz.business.controller;
import java.util.List;
import com.ruoyi.common.annotation.Anonymous;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.enums.BusinessType;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import com.fizz.business.domain.SetupTensionAnnealingFurnace;
import com.fizz.business.service.ISetupTensionAnnealingFurnaceService;
/**
* 退火炉张力Controller无权限控制
*
* 三主键steelGrade + thick + yieldStren
*/
@RestController
@RequestMapping("/business/tension/annealing-furnace")
@Anonymous
public class SetupTensionAnnealingFurnaceController extends BaseController
{
@Autowired
private ISetupTensionAnnealingFurnaceService service;
@GetMapping("/list")
public TableDataInfo list(SetupTensionAnnealingFurnace query)
{
startPage();
List<SetupTensionAnnealingFurnace> list = service.selectList(query);
return getDataTable(list);
}
@GetMapping
public AjaxResult getInfo(@RequestParam("steelGrade") String steelGrade,
@RequestParam("thick") Float thick,
@RequestParam("yieldStren") Float yieldStren)
{
return success(service.selectByKey(steelGrade, thick, yieldStren));
}
@Log(title = "退火炉张力", businessType = BusinessType.INSERT)
@PostMapping
public AjaxResult add(@RequestBody SetupTensionAnnealingFurnace entity)
{
return toAjax(service.insert(entity));
}
@Log(title = "退火炉张力", businessType = BusinessType.UPDATE)
@PutMapping
public AjaxResult edit(@RequestBody SetupTensionAnnealingFurnace entity)
{
return toAjax(service.updateByKey(entity));
}
@Log(title = "退火炉张力", businessType = BusinessType.DELETE)
@DeleteMapping
public AjaxResult remove(@RequestParam("steelGrade") String steelGrade,
@RequestParam("thick") Float thick,
@RequestParam("yieldStren") Float yieldStren)
{
return toAjax(service.deleteByKey(steelGrade, thick, yieldStren));
}
}

View File

@@ -1,95 +0,0 @@
package com.fizz.business.controller;
import java.util.List;
import javax.servlet.http.HttpServletResponse;
import com.fizz.business.form.TensionDeleteForm;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.enums.BusinessType;
import com.fizz.business.domain.SetupTension;
import com.fizz.business.service.ISetupTensionService;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.common.core.page.TableDataInfo;
/**
* 全线张力Controller
*
* @author ruoyi
* @date 2025-09-26
*/
@RestController
@RequestMapping("/business/tension")
public class SetupTensionController extends BaseController
{
@Autowired
private ISetupTensionService setupTensionService;
/**
* 查询全线张力列表
*/
@GetMapping("/list")
public TableDataInfo list(SetupTension setupTension)
{
startPage();
List<SetupTension> list = setupTensionService.selectSetupTensionList(setupTension);
return getDataTable(list);
}
/**
* 导出全线张力列表
*/
@Log(title = "全线张力", businessType = BusinessType.EXPORT)
@PostMapping("/export")
public void export(HttpServletResponse response, SetupTension setupTension)
{
List<SetupTension> list = setupTensionService.selectSetupTensionList(setupTension);
ExcelUtil<SetupTension> util = new ExcelUtil<SetupTension>(SetupTension.class);
util.exportExcel(response, list, "全线张力数据");
}
/**
* 获取全线张力详细信息
*/
@GetMapping()
public AjaxResult getInfo(@RequestParam(required = false) Long thick ,@RequestParam(required = false) Long yieldStren)
{
return success(setupTensionService.selectSetupTensionByThick(thick, yieldStren));
}
/**
* 新增全线张力
*/
@Log(title = "全线张力", businessType = BusinessType.INSERT)
@PostMapping
public AjaxResult add(@RequestBody SetupTension setupTension)
{
return toAjax(setupTensionService.insertSetupTension(setupTension));
}
/**
* 修改全线张力
*/
@Log(title = "全线张力", businessType = BusinessType.UPDATE)
@PutMapping
public AjaxResult edit(@RequestBody SetupTension setupTension)
{
return toAjax(setupTensionService.updateSetupTension(setupTension));
}
/**
* 删除全线张力
*/
@Log(title = "全线张力", businessType = BusinessType.DELETE)
@DeleteMapping("/tension") // 建议添加路径区分不同删除接口
public AjaxResult removeTension(@RequestBody TensionDeleteForm form) {
return toAjax(setupTensionService.deleteSetupTensionByThicks(
form.getThicks(),
form.getYieldStrens()
));
}
}

View File

@@ -0,0 +1,69 @@
package com.fizz.business.controller;
import java.util.List;
import com.ruoyi.common.annotation.Anonymous;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.enums.BusinessType;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import com.fizz.business.domain.SetupTensionLeveler;
import com.fizz.business.service.ISetupTensionLevelerService;
/**
* 平整机张力Controller无权限控制
*
* 三主键steelGrade + thick + yieldStren
*/
@RestController
@RequestMapping("/business/tension/leveler")
@Anonymous
public class SetupTensionLevelerController extends BaseController
{
@Autowired
private ISetupTensionLevelerService service;
@GetMapping("/list")
public TableDataInfo list(SetupTensionLeveler query)
{
startPage();
List<SetupTensionLeveler> list = service.selectList(query);
return getDataTable(list);
}
@GetMapping
public AjaxResult getInfo(@RequestParam("steelGrade") String steelGrade,
@RequestParam("thick") Float thick,
@RequestParam("yieldStren") Float yieldStren)
{
return success(service.selectByKey(steelGrade, thick, yieldStren));
}
@Log(title = "平整机张力", businessType = BusinessType.INSERT)
@PostMapping
public AjaxResult add(@RequestBody SetupTensionLeveler entity)
{
return toAjax(service.insert(entity));
}
@Log(title = "平整机张力", businessType = BusinessType.UPDATE)
@PutMapping
public AjaxResult edit(@RequestBody SetupTensionLeveler entity)
{
return toAjax(service.updateByKey(entity));
}
@Log(title = "平整机张力", businessType = BusinessType.DELETE)
@DeleteMapping
public AjaxResult remove(@RequestParam("steelGrade") String steelGrade,
@RequestParam("thick") Float thick,
@RequestParam("yieldStren") Float yieldStren)
{
return toAjax(service.deleteByKey(steelGrade, thick, yieldStren));
}
}

View File

@@ -0,0 +1,69 @@
package com.fizz.business.controller;
import java.util.List;
import com.ruoyi.common.annotation.Anonymous;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.enums.BusinessType;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import com.fizz.business.domain.SetupTensionStraightener;
import com.fizz.business.service.ISetupTensionStraightenerService;
/**
* 矫直机张力Controller无权限控制
*
* 三主键steelGrade + thick + yieldStren
*/
@RestController
@RequestMapping("/business/tension/straightener")
@Anonymous
public class SetupTensionStraightenerController extends BaseController
{
@Autowired
private ISetupTensionStraightenerService service;
@GetMapping("/list")
public TableDataInfo list(SetupTensionStraightener query)
{
startPage();
List<SetupTensionStraightener> list = service.selectList(query);
return getDataTable(list);
}
@GetMapping
public AjaxResult getInfo(@RequestParam("steelGrade") String steelGrade,
@RequestParam("thick") Float thick,
@RequestParam("yieldStren") Float yieldStren)
{
return success(service.selectByKey(steelGrade, thick, yieldStren));
}
@Log(title = "矫直机张力", businessType = BusinessType.INSERT)
@PostMapping
public AjaxResult add(@RequestBody SetupTensionStraightener entity)
{
return toAjax(service.insert(entity));
}
@Log(title = "矫直机张力", businessType = BusinessType.UPDATE)
@PutMapping
public AjaxResult edit(@RequestBody SetupTensionStraightener entity)
{
return toAjax(service.updateByKey(entity));
}
@Log(title = "矫直机张力", businessType = BusinessType.DELETE)
@DeleteMapping
public AjaxResult remove(@RequestParam("steelGrade") String steelGrade,
@RequestParam("thick") Float thick,
@RequestParam("yieldStren") Float yieldStren)
{
return toAjax(service.deleteByKey(steelGrade, thick, yieldStren));
}
}

View File

@@ -1,96 +0,0 @@
package com.fizz.business.controller;
import java.util.List;
import javax.servlet.http.HttpServletResponse;
import com.fizz.business.form.TlDeleteForm;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.enums.BusinessType;
import com.fizz.business.domain.SetupTl;
import com.fizz.business.service.ISetupTlService;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.common.core.page.TableDataInfo;
/**
* 拉矫机参数Controller
*
* @author ruoyi
* @date 2025-09-26
*/
@RestController
@RequestMapping("/business/tl")
public class SetupTlController extends BaseController
{
@Autowired
private ISetupTlService setupTlService;
/**
* 查询拉矫机参数列表
*/
@GetMapping("/list")
public TableDataInfo list(SetupTl setupTl)
{
startPage();
List<SetupTl> list = setupTlService.selectSetupTlList(setupTl);
return getDataTable(list);
}
/**
* 导出拉矫机参数列表
*/
@Log(title = "拉矫机参数", businessType = BusinessType.EXPORT)
@PostMapping("/export")
public void export(HttpServletResponse response, SetupTl setupTl)
{
List<SetupTl> list = setupTlService.selectSetupTlList(setupTl);
ExcelUtil<SetupTl> util = new ExcelUtil<SetupTl>(SetupTl.class);
util.exportExcel(response, list, "拉矫机参数数据");
}
/**
* 获取拉矫机参数详细信息
*/
@GetMapping()
public AjaxResult getInfo(@RequestParam String steelGrade,
@RequestParam Long yieldStren,
@RequestParam Long thick)
{
return success(setupTlService.selectSetupTlBySteelGrade(steelGrade, yieldStren, thick));
}
/**
* 新增拉矫机参数
*/
@Log(title = "拉矫机参数", businessType = BusinessType.INSERT)
@PostMapping
public AjaxResult add(@RequestBody SetupTl setupTl)
{
return toAjax(setupTlService.insertSetupTl(setupTl));
}
/**
* 修改拉矫机参数
*/
@Log(title = "拉矫机参数", businessType = BusinessType.UPDATE)
@PutMapping
public AjaxResult edit(@RequestBody SetupTl setupTl)
{
return toAjax(setupTlService.updateSetupTl(setupTl));
}
// 拉矫机参数删除接口
@Log(title = "拉矫机参数", businessType = BusinessType.DELETE)
@DeleteMapping("/tl") // 不同路径区分
public AjaxResult removeTl(@RequestBody TlDeleteForm form) {
return toAjax(setupTlService.deleteSetupTlBySteelGrades(
form.getSteelGrades(),
form.getYieldStrens(),
form.getThicks()
));
}
}

View File

@@ -1,96 +0,0 @@
package com.fizz.business.controller;
import java.util.List;
import javax.servlet.http.HttpServletResponse;
import com.fizz.business.form.TmBendforceDeleteForm;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.enums.BusinessType;
import com.fizz.business.domain.SetupTmBendforce;
import com.fizz.business.service.ISetupTmBendforceService;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.common.core.page.TableDataInfo;
/**
* 光整机弯辊力Controller
*
* @author Joshi
* @date 2025-09-26
*/
@RestController
@RequestMapping("/business/bendforce")
public class SetupTmBendforceController extends BaseController
{
@Autowired
private ISetupTmBendforceService setupTmBendforceService;
/**
* 查询光整机弯辊力列表
*/
@GetMapping("/list")
public TableDataInfo list(SetupTmBendforce setupTmBendforce)
{
startPage();
List<SetupTmBendforce> list = setupTmBendforceService.selectSetupTmBendforceList(setupTmBendforce);
return getDataTable(list);
}
/**
* 导出光整机弯辊力列表
*/
@Log(title = "光整机弯辊力", businessType = BusinessType.EXPORT)
@PostMapping("/export")
public void export(HttpServletResponse response, SetupTmBendforce setupTmBendforce)
{
List<SetupTmBendforce> list = setupTmBendforceService.selectSetupTmBendforceList(setupTmBendforce);
ExcelUtil<SetupTmBendforce> util = new ExcelUtil<SetupTmBendforce>(SetupTmBendforce.class);
util.exportExcel(response, list, "光整机弯辊力数据");
}
/**
* 获取光整机弯辊力详细信息
*/
@GetMapping()
public AjaxResult getInfo(@RequestParam Long width,
@RequestParam Long rollForce)
{
return success(setupTmBendforceService.selectSetupTmBendforceByWidth(width,rollForce));
}
/**
* 新增光整机弯辊力
*/
@Log(title = "光整机弯辊力", businessType = BusinessType.INSERT)
@PostMapping
public AjaxResult add(@RequestBody SetupTmBendforce setupTmBendforce)
{
return toAjax(setupTmBendforceService.insertSetupTmBendforce(setupTmBendforce));
}
/**
* 修改光整机弯辊力
*/
@Log(title = "光整机弯辊力", businessType = BusinessType.UPDATE)
@PutMapping
public AjaxResult edit(@RequestBody SetupTmBendforce setupTmBendforce)
{
return toAjax(setupTmBendforceService.updateSetupTmBendforce(setupTmBendforce));
}
/**
* 删除光整机弯辊力
*/
@Log(title = "光整机弯辊力", businessType = BusinessType.DELETE)
@DeleteMapping("/tm/bendforce")
public AjaxResult removeTmBendforce(@RequestBody TmBendforceDeleteForm form) {
return toAjax(setupTmBendforceService.deleteSetupTmBendforceByWidths(
form.getWidths(),
form.getRollForces()
));
}
}

View File

@@ -1,98 +0,0 @@
package com.fizz.business.controller;
import java.util.List;
import javax.servlet.http.HttpServletResponse;
import com.fizz.business.form.TmMeshDeleteForm;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.enums.BusinessType;
import com.fizz.business.domain.SetupTmMesh;
import com.fizz.business.service.ISetupTmMeshService;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.common.core.page.TableDataInfo;
/**
* 光整机插入量Controller
*
* @author Joshi
* @date 2025-09-26
*/
@RestController
@RequestMapping("/business/mesh")
public class SetupTmMeshController extends BaseController
{
@Autowired
private ISetupTmMeshService setupTmMeshService;
/**
* 查询光整机插入量列表
*/
@GetMapping("/list")
public TableDataInfo list(SetupTmMesh setupTmMesh)
{
startPage();
List<SetupTmMesh> list = setupTmMeshService.selectSetupTmMeshList(setupTmMesh);
return getDataTable(list);
}
/**
* 导出光整机插入量列表
*/
@Log(title = "光整机插入量", businessType = BusinessType.EXPORT)
@PostMapping("/export")
public void export(HttpServletResponse response, SetupTmMesh setupTmMesh)
{
List<SetupTmMesh> list = setupTmMeshService.selectSetupTmMeshList(setupTmMesh);
ExcelUtil<SetupTmMesh> util = new ExcelUtil<SetupTmMesh>(SetupTmMesh.class);
util.exportExcel(response, list, "光整机插入量数据");
}
/**
* 获取光整机插入量详细信息
*/
@GetMapping()
public AjaxResult getInfo(@RequestParam String steelGrade,
@RequestParam Long yieldStren,
@RequestParam Long thick)
{
return success(setupTmMeshService.selectSetupTmMeshBySteelGrade(steelGrade, yieldStren, thick));
}
/**
* 新增光整机插入量
*/
@Log(title = "光整机插入量", businessType = BusinessType.INSERT)
@PostMapping
public AjaxResult add(@RequestBody SetupTmMesh setupTmMesh)
{
return toAjax(setupTmMeshService.insertSetupTmMesh(setupTmMesh));
}
/**
* 修改光整机插入量
*/
@Log(title = "光整机插入量", businessType = BusinessType.UPDATE)
@PutMapping
public AjaxResult edit(@RequestBody SetupTmMesh setupTmMesh)
{
return toAjax(setupTmMeshService.updateSetupTmMesh(setupTmMesh));
}
/**
* 删除光整机插入量
*/
@Log(title = "光整机插入量", businessType = BusinessType.DELETE)
@DeleteMapping("/tm/mesh")
public AjaxResult removeTmMesh(@RequestBody TmMeshDeleteForm form) {
return toAjax(setupTmMeshService.deleteSetupTmMeshBySteelGrades(
form.getSteelGrades(),
form.getYieldStrens(),
form.getThicks()
));
}
}

View File

@@ -1,100 +0,0 @@
package com.fizz.business.controller;
import java.util.List;
import javax.servlet.http.HttpServletResponse;
import com.fizz.business.form.TmRollforceDeleteForm;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.enums.BusinessType;
import com.fizz.business.domain.SetupTmRollforce;
import com.fizz.business.service.ISetupTmRollforceService;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.common.core.page.TableDataInfo;
/**
* 光整机轧制力Controller
*
* @author Joshi
* @date 2025-09-26
*/
@RestController
@RequestMapping("/business/rollforce")
public class SetupTmRollforceController extends BaseController
{
@Autowired
private ISetupTmRollforceService setupTmRollforceService;
/**
* 查询光整机轧制力列表
*/
@GetMapping("/list")
public TableDataInfo list(SetupTmRollforce setupTmRollforce)
{
startPage();
List<SetupTmRollforce> list = setupTmRollforceService.selectSetupTmRollforceList(setupTmRollforce);
return getDataTable(list);
}
/**
* 导出光整机轧制力列表
*/
@Log(title = "光整机轧制力", businessType = BusinessType.EXPORT)
@PostMapping("/export")
public void export(HttpServletResponse response, SetupTmRollforce setupTmRollforce)
{
List<SetupTmRollforce> list = setupTmRollforceService.selectSetupTmRollforceList(setupTmRollforce);
ExcelUtil<SetupTmRollforce> util = new ExcelUtil<SetupTmRollforce>(SetupTmRollforce.class);
util.exportExcel(response, list, "光整机轧制力数据");
}
/**
* 获取光整机轧制力详细信息
*/
@GetMapping()
public AjaxResult getInfo(@RequestParam String steelGrade,
@RequestParam Long yieldStren,
@RequestParam Long thick,
@RequestParam Long elong)
{
return success(setupTmRollforceService.selectSetupTmRollforceBySteelGrade(steelGrade, yieldStren, thick, elong));
}
/**
* 新增光整机轧制力
*/
@Log(title = "光整机轧制力", businessType = BusinessType.INSERT)
@PostMapping
public AjaxResult add(@RequestBody SetupTmRollforce setupTmRollforce)
{
return toAjax(setupTmRollforceService.insertSetupTmRollforce(setupTmRollforce));
}
/**
* 修改光整机轧制力
*/
@Log(title = "光整机轧制力", businessType = BusinessType.UPDATE)
@PutMapping
public AjaxResult edit(@RequestBody SetupTmRollforce setupTmRollforce)
{
return toAjax(setupTmRollforceService.updateSetupTmRollforce(setupTmRollforce));
}
/**
* 删除光整机轧制力
*/
@Log(title = "光整机轧制力", businessType = BusinessType.DELETE)
@DeleteMapping("/tm/rollforce")
public AjaxResult removeTmRollforce(@RequestBody TmRollforceDeleteForm form) {
return toAjax(setupTmRollforceService.deleteSetupTmRollforceBySteelGrades(
form.getSteelGrades(),
form.getThicks(),
form.getYieldStrens(),
form.getElongs()
));
}
}

View File

@@ -30,57 +30,45 @@ public class SteelGradeInfoController {
@Operation(summary = "查询钢种列表")
public R<List<StdAlloyVO>> list(@RequestParam(value = "keyword", required = false) String keyword) {
// 使用 LambdaQueryWrapper 查询 StdAlloy 表中的数据,支持按名称/编号模糊查询
// 严格按 cgldb.sql查询 std_alloy(GRADEID, NAME)
LambdaQueryWrapper<StdAlloy> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.select(StdAlloy::getGradeid, StdAlloy::getName); // 只查询 gradeId 和 name 字段
queryWrapper.select(StdAlloy::getGradeid, StdAlloy::getName);
if (StringUtils.isNotBlank(keyword)) {
queryWrapper.like(StdAlloy::getName, keyword)
.or()
.like(StdAlloy::getGradeid, keyword);
}
queryWrapper.orderByAsc(StdAlloy::getName); // 按 name 排序
queryWrapper.orderByAsc(StdAlloy::getName);
// 查询 StdAlloy 数据
List<StdAlloy> stdAlloyList = steelGradeInfoService.list(queryWrapper);
// 使用 BeanUtils 将 StdAlloy 对象的字段映射到 StdAlloyVO
List<StdAlloyVO> stdAlloyVOList = new ArrayList<>();
for (StdAlloy stdAlloy : stdAlloyList) {
StdAlloyVO stdAlloyVO = new StdAlloyVO();
BeanUtils.copyProperties(stdAlloy, stdAlloyVO); // 将 StdAlloy 属性复制到 StdAlloyVO
BeanUtils.copyProperties(stdAlloy, stdAlloyVO);
stdAlloyVOList.add(stdAlloyVO);
}
// 返回结果
return R.ok(stdAlloyVOList);
}
@GetMapping("/info")
@Operation(summary ="询单个钢种详情")
public R<StdAlloy> getSteelGradeInfo(@RequestParam Integer gradeid) {
// 使用 LambdaQueryWrapper 查询 StdAlloy 表中的数据
LambdaQueryWrapper<StdAlloy> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(StdAlloy::getGradeid, gradeid); // 只查询 gradeId 和 name 字段
// 查询 StdAlloy 数据
StdAlloy stdAlloyList = steelGradeInfoService.getById(gradeid);
// 返回结果
return R.ok(stdAlloyList);
return R.ok(steelGradeInfoService.getById(gradeid));
}
@PostMapping("/add")
@Operation(summary ="新增")
public R<Boolean> add(@RequestBody StdAlloy steelGradeInfo) {
return R.ok(steelGradeInfoService.save(steelGradeInfo));
public R<Boolean> add(@RequestBody StdAlloy stdAlloy) {
return R.ok(steelGradeInfoService.save(stdAlloy));
}
@PutMapping("/update")
@Operation(summary ="更新")
public R<Boolean> update(@RequestBody StdAlloy steelGradeInfo) {
return R.ok(steelGradeInfoService.updateById(steelGradeInfo));
public R<Boolean> update(@RequestBody StdAlloy stdAlloy) {
return R.ok(steelGradeInfoService.updateById(stdAlloy));
}
@Operation(summary ="删除")

View File

@@ -0,0 +1,60 @@
package com.fizz.business.domain;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.ruoyi.common.core.domain.BaseEntity;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.util.Date;
/**
* 业务发送批次表 biz_send_job
*
* @author Cascade
*/
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("biz_send_job")
public class BizSendJob extends BaseEntity {
private static final long serialVersionUID = 1L;
/** 批次ID */
@TableId(type = IdType.AUTO)
private Integer jobId;
/** 业务唯一键, 用于幂等控制 */
private String bizKey;
/** 目标设备/产线名称 (如 CGL_LINE_1, FURNACE_A) */
private String deviceName;
/** 计划发送时间 */
private Date planSendTime;
/** 实际开始发送时间 */
private Date actualSendTime;
/** 发送完成时间 */
private Date finishTime;
/** 批次状态: PENDING, IN_PROGRESS, COMPLETED, PARTIAL_SUCCESS, FAILED */
private String status;
/** 操作员ID */
private Long operatorId;
/** 操作员姓名 */
private String operatorName;
// 解决 BaseEntity 字段导致的未知列问题
@com.baomidou.mybatisplus.annotation.TableField(exist = false)
private String searchValue;
@com.baomidou.mybatisplus.annotation.TableField(exist = false)
private java.util.Map<String,Object> params;
// GroupType
private String groupType;
}

View File

@@ -0,0 +1,46 @@
package com.fizz.business.domain;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.ruoyi.common.core.domain.BaseEntity;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* 业务发送分组表 biz_send_job_group
*
* @author Cascade
*/
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("biz_send_job_group")
public class BizSendJobGroup extends BaseEntity {
private static final long serialVersionUID = 1L;
/** 分组ID */
@TableId(type = IdType.AUTO)
private Integer groupId;
/** 所属批次ID */
private Integer jobId;
/** 在本批次内的组序号 */
private Integer groupNo;
/** 组类型: DRIVE(传动), FURNACE(炉火) */
private String groupType;
/** 组名称 (可选) */
private String groupName;
/** 分组状态: PENDING, IN_PROGRESS, COMPLETED, FAILED */
private String status;
// 解决 BaseEntity 字段导致的未知列问题
@com.baomidou.mybatisplus.annotation.TableField(exist = false)
private String searchValue;
@com.baomidou.mybatisplus.annotation.TableField(exist = false)
private java.util.Map<String,Object> params;
}

View File

@@ -0,0 +1,64 @@
package com.fizz.business.domain;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.ruoyi.common.core.domain.BaseEntity;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.math.BigDecimal;
import java.util.Date;
/**
* 业务发送项历史表 biz_send_job_item
*
* @author Cascade
*/
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("biz_send_job_item")
public class BizSendJobItem extends BaseEntity {
private static final long serialVersionUID = 1L;
/** 发送项ID */
@TableId(type = IdType.AUTO)
private Integer itemId;
/** 所属批次ID (冗余) */
private Integer jobId;
/** 所属分组ID */
private Integer groupId;
/** 参数业务编码 */
private String paramCode;
/** 设定地址 (OPC地址) */
private String address;
/** 设定的原始值 */
private String valueRaw;
/** 设定值的数值形式 */
private BigDecimal valueNum;
/** 参数的设定时间 */
private Date setTime;
/** 发送结果: PENDING, SUCCESS, FAILED */
private String resultStatus;
/** 结果消息 */
private String resultMsg;
/** 重试次数 */
private Integer retryCount;
// 解决 BaseEntity 字段导致的未知列问题
@com.baomidou.mybatisplus.annotation.TableField(exist = false)
private String searchValue;
@com.baomidou.mybatisplus.annotation.TableField(exist = false)
private java.util.Map<String,Object> params;
}

View File

@@ -0,0 +1,41 @@
package com.fizz.business.domain;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.ruoyi.common.core.domain.BaseEntity;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* 发送默认模板主表
*/
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("biz_send_template")
public class BizSendTemplate extends BaseEntity {
@TableId(type = IdType.AUTO)
private Integer templateId;
// 解决 MyBatis-Plus 父类字段映射导致的 search_value 报错
@com.baomidou.mybatisplus.annotation.TableField(exist = false)
private String searchValue;
@com.baomidou.mybatisplus.annotation.TableField(exist = false)
private java.util.Map<String,Object> params;
/** 模板编码 */
private String templateCode;
/** 模板名称 */
private String templateName;
/** 默认设备名称 */
private String deviceName;
/** 组类型 DRIVE / FURNACE */
private String groupType;
/** 是否启用 */
private Integer enabled;
}

View File

@@ -0,0 +1,49 @@
package com.fizz.business.domain;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.ruoyi.common.core.domain.BaseEntity;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* 发送默认模板明细表
*/
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("biz_send_template_item")
public class BizSendTemplateItem extends BaseEntity {
@TableId(type = IdType.AUTO)
private Integer templateItemId;
private Integer templateId;
/** 明细序号 */
private Integer itemNo;
/** 参数编码 */
private String paramCode;
/** 英文显示名 */
private String labelEn;
/** 英文分组名 */
private String groupNameEn;
/** OPC地址 */
private String address;
/** 默认值(字符串) */
private String defaultValueRaw;
/** 是否启用 */
private Integer enabled;
// 解决 BaseEntity 字段导致的未知列问题
@com.baomidou.mybatisplus.annotation.TableField(exist = false)
private String searchValue;
@com.baomidou.mybatisplus.annotation.TableField(exist = false)
private java.util.Map<String,Object> params;
}

View File

@@ -313,4 +313,8 @@ public class CrmPdiPlan implements Serializable {
@Schema(description = "原卷号")
private String originCoilid;
//锌层厚度 zinc_coating_thickness
@Schema(description = "锌层厚度")
private BigDecimal zincCoatingThickness;
}

View File

@@ -8,6 +8,7 @@ import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.io.Serializable;
import java.math.BigDecimal;
import java.sql.Timestamp;
import java.time.LocalDateTime;
@@ -130,4 +131,7 @@ public class CrmPdoExcoil implements Serializable {
@Schema(description = "计划来源L3-L3计划MANUAL-人工")
private String planOrigin;
@Schema(description = "锌层厚度")
private BigDecimal zincCoatingThickness;
}

View File

@@ -0,0 +1,48 @@
package com.fizz.business.domain;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime;
@Data
@TableName("device_snapshot")
@Schema(description = "设备数据快照")
public class DeviceSnapshot {
@TableId(type = IdType.ASSIGN_ID)
@Schema(description = "主键")
private Long id;
@Schema(description = "快照时间")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime createTime;
@Schema(description = "设备idx对应DeviceEnum.idx")
private Integer deviceId;
@Schema(description = "设备枚举名对应DeviceEnum.name()")
private String deviceCode;
@Schema(description = "设备描述")
private String deviceName;
@Schema(description = "段类型 ENTRY/PROCESS/EXIT")
private String sectionType;
@Schema(description = "来源类型 ENTRY/FURNACE/COAT/EXIT")
private String sourceType;
@Schema(description = "基准位置(m)")
private Double basePosition;
@Schema(description = "快照数据JSON")
private String snapshotData;
}

View File

@@ -5,162 +5,95 @@ import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import com.ruoyi.common.annotation.Excel;
import com.ruoyi.common.core.domain.BaseEntity;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.Date;
/**
* 生产计划的参数详情对象 pdi_setup
* 张力参数表对象 pdi_setup
*
* @author Joshi
* @date 2025-09-25
* 表主键为自增 id。
*/
@Data
@TableName("pdi_setup")
public class PdiSetups implements Serializable
{
public class PdiSetups implements Serializable {
private static final long serialVersionUID = 1L;
/** 主键ID */
@TableId(value = "ID", type = IdType.AUTO)
/** 主键 */
@TableId(value = "id", type = IdType.AUTO)
private Long id;
/** 钢卷号 */
@Excel(name = "钢卷号")
@TableField("COILID")
private String coilid;
/** 计划号 */
@Excel(name = "计划号")
@TableField("PLANID")
private String planid;
/** 钢种 */
@Excel(name = "钢种")
private String steelGrade;
/** 厚度 */
@Excel(name = "厚度")
private BigDecimal thick;
/** 屈服强度 */
@Excel(name = "屈服强度")
private BigDecimal yieldStren;
/** 开卷机张力 */
@Excel(name = "开卷机张力")
@TableField("POR_TENSION")
private Long porTension;
private BigDecimal porTension;
/** 入口活套张力 */
@Excel(name = "入口活套张力")
@TableField("CEL_TENSION")
private Long celTension;
private BigDecimal celTension;
/** 清洗段张力 */
@Excel(name = "清洗段张力")
@TableField("CLEAN_TENSION")
private Long cleanTension;
private BigDecimal cleanTension;
/** 炉区张力 */
@Excel(name = "炉区张力")
@TableField("FUR_TENSION")
private Long furTension;
/** 冷却塔张力 */
@Excel(name = "冷却塔张力")
@TableField("TOWER_TENSION")
private Long towerTension;
/** 光整机不投张力 */
@Excel(name = "光整机不投张力")
@TableField("TM_NONE_TENSION")
private Long tmNoneTension;
/** 光整机入口张力 */
@Excel(name = "光整机入口张力")
@TableField("TM_ENTRY_TENSION")
private Long tmEntryTension;
/** 光整机出口张力 */
@Excel(name = "光整机出口张力")
@TableField("TM_EXIT_TENSION")
private Long tmExitTension;
/** 光整机轧制力 */
@Excel(name = "光整机轧制力")
@TableField("TM_ROLLFORCE")
private Long tmRollforce;
/** 光整机弯辊力 */
@Excel(name = "光整机弯辊力")
@TableField("TM_BENDFORCE")
private Long tmBendforce;
/** 光整机防皱辊插入量 */
@Excel(name = "光整机防皱辊插入量")
@TableField("TM_ACR_MESH")
private Long tmAcrMesh;
/** 光整机防颤辊插入量 */
@Excel(name = "光整机防颤辊插入量")
@TableField("TM_BR_MESH")
private Long tmBrMesh;
/** 拉矫机不投张力 */
@Excel(name = "拉矫机不投张力")
@TableField("TL_NONE_TENSION")
private Long tlNoneTension;
/** 拉矫机出口张力 */
@Excel(name = "拉矫机出口张力")
@TableField("TL_EXIT_TENSION")
private Long tlExitTension;
/** 拉矫机延伸率 */
@Excel(name = "拉矫机延伸率")
@TableField("TL_ELONG")
private Long tlElong;
/** 拉矫机矫直辊插入量1 */
@Excel(name = "拉矫机矫直辊插入量1")
@TableField("TL_LVL_MESH1")
private Long tlLvlMesh1;
/** 拉矫机矫直辊插入量2 */
@Excel(name = "拉矫机矫直辊插入量2")
@TableField("TL_LVL_MESH2")
private Long tlLvlMesh2;
/** 拉矫机防横弓插入量 */
@Excel(name = "拉矫机防横弓插入量")
@TableField("TL_ACB_MESH")
private Long tlAcbMesh;
/** 后处理张力 */
@Excel(name = "后处理张力")
@TableField("COAT_TENSION")
private Long coatTension;
/** 钝化段张力 */
@Excel(name = "钝化段张力")
private BigDecimal passivationTension;
/** 出口活套张力 */
@Excel(name = "出口活套张力")
@TableField("CXL_TENSION")
private Long cxlTension;
private BigDecimal cxlTension;
/** 卷取机张力 */
@Excel(name = "卷取机张力")
@TableField("TR_TENSION")
private Long trTension;
private BigDecimal trTension;
/** 类型,或可用于记录更改次数 */
@Excel(name = "类型,或可用于记录更改次数")
@TableField("TYPE")
private Long type;
/** 平整机入口张力 */
@Excel(name = "平整机入口张力")
private BigDecimal levelerEntryTension;
/** 预热段出口板温 */
@Excel(name = "预热段出口板温")
@TableField("PREHEATING_SECTION")
private Float preheatingSection;
/** 平整机出口张力 */
@Excel(name = "平整机出口张力")
private BigDecimal levelerExitTension;
/** 加热段出口板温 */
@Excel(name = "加热段出口板温")
@TableField("HEATING_SECTION")
private Float heatingSection;
/** 矫直机出口张力 */
@Excel(name = "矫直机出口张力")
private BigDecimal straightenerExitTension;
/** 冷却段出口板温 */
@Excel(name = "冷却段出口板温")
@TableField("COOLING_SECTION")
private Float coolingSection;
/** 炉区张力 */
@Excel(name = "炉区张力")
private BigDecimal furTension;
/** 冷却塔张力 */
@Excel(name = "冷却塔张力")
private BigDecimal towerTension;
/** 创建时间 */
@Excel(name = "创建时间")
private Date createTime;
/** 更新时间 */
@Excel(name = "更新时间")
private Date updateTime;
}

View File

@@ -0,0 +1,24 @@
package com.fizz.business.domain;
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 lombok.Data;
import java.time.LocalDateTime;
@Data
@TableName("pro_stoppage_type")
public class ProStoppageType {
@TableId(value = "STOP_TYPE", type = IdType.INPUT)
private Integer stopType;
@TableField("REMARK")
private String remark;
@TableField("INSDATE")
private LocalDateTime insdate;
}

View File

@@ -0,0 +1,150 @@
package com.fizz.business.domain;
import java.util.Date;
import com.ruoyi.common.annotation.Excel;
import com.ruoyi.common.core.domain.BaseEntity;
/**
* 全线张力对象 setup_tension_all_line
*
* 三主键steel_grade + thick + yield_stren
*/
public class SetupTensionAllLine extends BaseEntity
{
private static final long serialVersionUID = 1L;
/** 钢种 */
@Excel(name = "钢种")
private String steelGrade;
/** 厚度 */
@Excel(name = "厚度")
private Float thick;
/** 屈服强度 */
@Excel(name = "屈服强度")
private Float yieldStren;
/** 开卷机张力 */
@Excel(name = "开卷机张力")
private Float value1;
/** 入口活套张力 */
@Excel(name = "入口活套张力")
private Float value2;
/** 清洗段张力 */
@Excel(name = "清洗段张力")
private Float value3;
/** 钝化段张力 */
@Excel(name = "钝化段张力")
private Float value4;
/** 出口活套张力 */
@Excel(name = "出口活套张力")
private Float value5;
/** 卷取机张力 */
@Excel(name = "卷取机张力")
private Float value6;
/** 创建时间(表字段) */
private Date createTime;
/** 更新时间(表字段) */
private Date updateTime;
public String getSteelGrade() {
return steelGrade;
}
public void setSteelGrade(String steelGrade) {
this.steelGrade = steelGrade;
}
public Float getThick() {
return thick;
}
public void setThick(Float thick) {
this.thick = thick;
}
public Float getYieldStren() {
return yieldStren;
}
public void setYieldStren(Float yieldStren) {
this.yieldStren = yieldStren;
}
public Float getValue1() {
return value1;
}
public void setValue1(Float value1) {
this.value1 = value1;
}
public Float getValue2() {
return value2;
}
public void setValue2(Float value2) {
this.value2 = value2;
}
public Float getValue3() {
return value3;
}
public void setValue3(Float value3) {
this.value3 = value3;
}
public Float getValue4() {
return value4;
}
public void setValue4(Float value4) {
this.value4 = value4;
}
public Float getValue5() {
return value5;
}
public void setValue5(Float value5) {
this.value5 = value5;
}
public Float getValue6() {
return value6;
}
public void setValue6(Float value6) {
this.value6 = value6;
}
@Override
public Date getCreateTime() {
return createTime;
}
@Override
public void setCreateTime(Date createTime) {
this.createTime = createTime;
}
@Override
public Date getUpdateTime() {
return updateTime;
}
@Override
public void setUpdateTime(Date updateTime) {
this.updateTime = updateTime;
}
}

View File

@@ -0,0 +1,61 @@
package com.fizz.business.domain;
import java.util.Date;
import com.ruoyi.common.annotation.Excel;
import com.ruoyi.common.core.domain.BaseEntity;
/**
* 退火炉张力对象 setup_tension_annealing_furnace
*
* 三主键steel_grade + thick + yield_stren
*/
public class SetupTensionAnnealingFurnace extends BaseEntity
{
private static final long serialVersionUID = 1L;
@Excel(name = "钢种")
private String steelGrade;
@Excel(name = "厚度")
private Float thick;
@Excel(name = "屈服强度")
private Float yieldStren;
@Excel(name = "炉区张力")
private Float value1;
@Excel(name = "冷却塔张力")
private Float value2;
private Date createTime;
private Date updateTime;
public String getSteelGrade() { return steelGrade; }
public void setSteelGrade(String steelGrade) { this.steelGrade = steelGrade; }
public Float getThick() { return thick; }
public void setThick(Float thick) { this.thick = thick; }
public Float getYieldStren() { return yieldStren; }
public void setYieldStren(Float yieldStren) { this.yieldStren = yieldStren; }
public Float getValue1() { return value1; }
public void setValue1(Float value1) { this.value1 = value1; }
public Float getValue2() { return value2; }
public void setValue2(Float value2) { this.value2 = value2; }
@Override
public Date getCreateTime() { return createTime; }
@Override
public void setCreateTime(Date createTime) { this.createTime = createTime; }
@Override
public Date getUpdateTime() { return updateTime; }
@Override
public void setUpdateTime(Date updateTime) { this.updateTime = updateTime; }
}

View File

@@ -0,0 +1,61 @@
package com.fizz.business.domain;
import java.util.Date;
import com.ruoyi.common.annotation.Excel;
import com.ruoyi.common.core.domain.BaseEntity;
/**
* 平整机张力对象 setup_tension_leveler
*
* 三主键steel_grade + thick + yield_stren
*/
public class SetupTensionLeveler extends BaseEntity
{
private static final long serialVersionUID = 1L;
@Excel(name = "钢种")
private String steelGrade;
@Excel(name = "厚度")
private Float thick;
@Excel(name = "屈服强度")
private Float yieldStren;
@Excel(name = "平整机入口张力")
private Float value1;
@Excel(name = "平整机出口张力")
private Float value2;
private Date createTime;
private Date updateTime;
public String getSteelGrade() { return steelGrade; }
public void setSteelGrade(String steelGrade) { this.steelGrade = steelGrade; }
public Float getThick() { return thick; }
public void setThick(Float thick) { this.thick = thick; }
public Float getYieldStren() { return yieldStren; }
public void setYieldStren(Float yieldStren) { this.yieldStren = yieldStren; }
public Float getValue1() { return value1; }
public void setValue1(Float value1) { this.value1 = value1; }
public Float getValue2() { return value2; }
public void setValue2(Float value2) { this.value2 = value2; }
@Override
public Date getCreateTime() { return createTime; }
@Override
public void setCreateTime(Date createTime) { this.createTime = createTime; }
@Override
public Date getUpdateTime() { return updateTime; }
@Override
public void setUpdateTime(Date updateTime) { this.updateTime = updateTime; }
}

View File

@@ -0,0 +1,55 @@
package com.fizz.business.domain;
import java.util.Date;
import com.ruoyi.common.annotation.Excel;
import com.ruoyi.common.core.domain.BaseEntity;
/**
* 矫直机张力对象 setup_tension_straightener
*
* 三主键steel_grade + thick + yield_stren
*/
public class SetupTensionStraightener extends BaseEntity
{
private static final long serialVersionUID = 1L;
@Excel(name = "钢种")
private String steelGrade;
@Excel(name = "厚度")
private Float thick;
@Excel(name = "屈服强度")
private Float yieldStren;
@Excel(name = "矫直机出口张力")
private Float value1;
private Date createTime;
private Date updateTime;
public String getSteelGrade() { return steelGrade; }
public void setSteelGrade(String steelGrade) { this.steelGrade = steelGrade; }
public Float getThick() { return thick; }
public void setThick(Float thick) { this.thick = thick; }
public Float getYieldStren() { return yieldStren; }
public void setYieldStren(Float yieldStren) { this.yieldStren = yieldStren; }
public Float getValue1() { return value1; }
public void setValue1(Float value1) { this.value1 = value1; }
@Override
public Date getCreateTime() { return createTime; }
@Override
public void setCreateTime(Date createTime) { this.createTime = createTime; }
@Override
public Date getUpdateTime() { return updateTime; }
@Override
public void setUpdateTime(Date updateTime) { this.updateTime = updateTime; }
}

View File

@@ -2,10 +2,12 @@ package com.fizz.business.domain;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.time.LocalDateTime;
@Data
@TableName("std_alloy")
public class StdAlloy {
@TableId("GRADEID")

View File

@@ -0,0 +1,75 @@
package com.fizz.business.domain.dto;
import lombok.Data;
import javax.validation.Valid;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import java.util.Date;
import java.util.List;
/**
* 创建发送任务 DTO
*/
@Data
public class SendJobCreateDTO {
/** 目标设备/产线名称 (如 CGL_LINE_1, FURNACE_A) */
@NotBlank(message = "deviceName不能为空")
private String deviceName;
/** 计划发送时间 */
private Date planSendTime;
/** 操作员ID */
private Long operatorId;
/** 操作员姓名 */
private String operatorName;
/** 分组列表 */
@Valid
@NotNull(message = "groups不能为空")
@Size(min = 1, message = "至少需要一个分组")
private List<GroupDTO> groups;
@Data
public static class GroupDTO {
/** 在本批次内的组序号 */
@NotNull(message = "groupNo不能为空")
private Integer groupNo;
/** 组类型: DRIVE(传动), FURNACE(炉火) */
@NotBlank(message = "groupType不能为空")
private String groupType;
/** 组名称 (可选) */
private String groupName;
/** 参数项列表 */
@Valid
@NotNull(message = "items不能为空")
@Size(min = 1, message = "至少需要一个参数项")
private List<ItemDTO> items;
}
@Data
public static class ItemDTO {
/** 参数业务编码 */
private String paramCode;
/** 设定地址 (OPC地址) */
@NotBlank(message = "address不能为空")
private String address;
/** 设定的原始值 */
private String valueRaw;
/** 参数的设定时间 */
private Date setTime;
}
}

View File

@@ -0,0 +1,21 @@
package com.fizz.business.domain.dto;
import lombok.Data;
/**
* 发送任务查询 DTO
* 说明:分页参数沿用 RuoYi BaseController 的 startPage() 机制,从 request 里取 pageNum/pageSize。
*/
@Data
public class SendJobQueryDTO {
/** 设备/产线名称 */
private String deviceName;
/** 状态: PENDING, IN_PROGRESS, COMPLETED, PARTIAL_SUCCESS, FAILED, DELETED */
private String status;
/** 分组类型: DRIVE / FURNACE */
private String groupType;
}

View File

@@ -0,0 +1,23 @@
package com.fizz.business.domain.dto;
import com.fizz.business.domain.BizSendTemplateItem;
import lombok.Data;
import java.util.List;
/**
* 模板明细批量保存(新增/更新/删除)
*/
@Data
public class SendTemplateItemsBatchSaveDTO {
/** 模板ID */
private Integer templateId;
/** 需要新增/更新的明细 */
private List<BizSendTemplateItem> items;
/** 需要删除的明细ID */
private List<Integer> deleteIds;
}

View File

@@ -1,9 +1,9 @@
package com.fizz.business.domain.msg;
import com.fizz.business.domain.msg.OpcMessage;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.math.BigDecimal;
@Data
@@ -56,14 +56,14 @@ public class AppMeasureCoatMessage extends OpcMessage {
@Schema(description = "TM出口钢带速度 (m/min)")
private BigDecimal stripSpeedTmExit;
@Schema(description = "钢带张力 BR5 TM (daN)")
private BigDecimal tensionBr5Tm;
@Schema(description = "钢带张力 BR8 TM (daN)")
private BigDecimal tensionBr8Tm;
@Schema(description = "钢带张力 TM BR6 (daN)")
private BigDecimal tensionTmBr6;
@Schema(description = "钢带张力 TM BR9 (daN)")
private BigDecimal tensionTmBr9;
@Schema(description = "钢带张力 BR5 BR6 (daN)")
private BigDecimal tensionBr5Br6;
@Schema(description = "钢带张力 BR8 BR9 (daN)")
private BigDecimal tensionBr8Br9;
@Schema(description = "TM mask (0x0001 tempering, 0x0002 type, 0x0004 pure water, 0x0008 water+detergent, 0x0010 control mode)")
private Integer tmMask;
@@ -98,11 +98,11 @@ public class AppMeasureCoatMessage extends OpcMessage {
@Schema(description = "备用字段 3")
private BigDecimal spare3;
@Schema(description = "钢带张力 TL BR7 (calc., daN)")
private BigDecimal tensionTlBr7;
@Schema(description = "钢带张力 TL BR10/BR11 (calc., daN)")
private BigDecimal tensionTlBr10Br11;
@Schema(description = "钢带张力 BR6 BR7 (calc., daN)")
private BigDecimal tensionBr6Br7;
@Schema(description = "钢带张力 BR9 BR10/BR11 (calc., daN)")
private BigDecimal tensionBr9toBr10Br11;
@Schema(description = "拉矫机投用")
private Integer tlFlag;
@@ -119,8 +119,8 @@ public class AppMeasureCoatMessage extends OpcMessage {
@Schema(description = "Anti Cross Bow Unit - 网距 (mm)")
private BigDecimal antiCrossBowUnitMesh;
@Schema(description = "AFP段钢带张力 BR7 BR8 (N/mm²)")
private BigDecimal tensionBr7Br8;
@Schema(description = "钢带张力 BR10/BR11 BR12 (N/mm²)")
private BigDecimal tensionBr10Br11Br12;
@Schema(description = "AFP段钢带速度 (m/min)")
private BigDecimal stripSpeedAfp;
@@ -131,8 +131,8 @@ public class AppMeasureCoatMessage extends OpcMessage {
@Schema(description = "AFP段钢带温度 (℃)")
private Integer stripTempAfp;
@Schema(description = "BR4BR5张力")
private BigDecimal tensionBr4Br5;
@Schema(description = "钢带张力 BR6 BR7/BR8 (daN)")
private BigDecimal tensionBr6toBr7Br8;
@Schema(description = "锌锅温度")
private BigDecimal potTemperature;
@@ -142,4 +142,4 @@ public class AppMeasureCoatMessage extends OpcMessage {
@Schema(description = "锌锅功率")
private BigDecimal potPower;
}
}

View File

@@ -1,6 +1,5 @@
package com.fizz.business.domain.msg;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
@@ -33,18 +32,24 @@ public class AppMeasureEntryMessage extends OpcMessage {
@Schema(description = "钢带张力 BR2 BR3 (daN)")
private BigDecimal tensionBr2Br3;
@Schema(description = "钢带张力 BR4/5 BR6 (daN)")
private BigDecimal tensionBr45Br6;
@Schema(description = "钢带速度 (m/min)")
private BigDecimal stripSpeed;
@Schema(description = "入口活套位置(m)")
private BigDecimal celLength;
@Schema(description = "入口活套最大长度(m)")
private BigDecimal celLengthMax;
@Schema(description = "入口活套最小长度(m)")
private BigDecimal celLengthMin;
@Schema(description = "入口活套百分比(m)")
private BigDecimal celCapacity;
@Schema(description = "入口活套张力(m)")
private BigDecimal tensionCel ;
@Schema(description = "清洗电压 (V)")
private BigDecimal cleaningVoltage;
@@ -71,4 +76,5 @@ public class AppMeasureEntryMessage extends OpcMessage {
@Schema(description = "热风压力 (Pa)")
private BigDecimal hotAirPressure;
}
}

View File

@@ -1,6 +1,5 @@
package com.fizz.business.domain.msg;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
@@ -24,6 +23,12 @@ public class AppMeasureExitMessage extends OpcMessage {
@Schema(description = "出口活套位置(m)")
private BigDecimal cxlLength;
@Schema(description = "出口活套最大长度(m)")
private BigDecimal cxlLengthMax;
@Schema(description = "出口活套最小长度(m)")
private BigDecimal cxlLengthMin;
@Schema(description = "出口活套百分比(m)")
private BigDecimal cxlCapacity;
@@ -47,5 +52,4 @@ public class AppMeasureExitMessage extends OpcMessage {
@Schema(description = "钢卷长度 (m)")
private BigDecimal coilLength;
}
}

View File

@@ -1,6 +1,5 @@
package com.fizz.business.domain.msg;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
@@ -15,19 +14,19 @@ public class AppMeasureFurnaceMessage extends OpcMessage {
@Schema(description = "系统计数器 (ms)")
private BigDecimal systemCounter;
@Schema(description = "Entry coil identification")
private String entryCoilId;
@Schema(description = "入口钢卷标识")
private String EntryCoilIdentification;
@Schema(description = "Strip location (0 for strip head at reference point (weld detector 1))")
private BigDecimal stripLocation;
@Schema(description = "钢带位置 (0 表示钢带头部在参考点 (weld detector 1))")
private BigDecimal Striplocation;
@Schema(description = "PH炉温实际值")
@Schema(description = "PH炉温实际值 (℃)")
private BigDecimal phFurnaceTemperatureActual;
@Schema(description = "NOF1炉温实际值")
@Schema(description = "NOF1炉温实际值 (℃)")
private BigDecimal nof1FurnaceTemperatureActual;
@Schema(description = "NOF1炉温设定值")
@Schema(description = "NOF1炉温设定值 (℃)")
private BigDecimal nof1FurnaceTemperatureSet;
@Schema(description = "NOF1炉温控制输出值")
@@ -52,15 +51,15 @@ public class AppMeasureFurnaceMessage extends OpcMessage {
private BigDecimal nof1AirFlowControlOutput;
@Schema(description = "NOF1空燃比实际值")
private BigDecimal nof1AirFuelRatioActual;
private BigDecimal nof1UtheisaKongCombustionRatioActualValue;
@Schema(description = "NOF1空燃比设定值")
private BigDecimal nof1AirFuelRatioSet;
private BigDecimal nof1UtheisaKongCombustionRatioSettingValue;
@Schema(description = "NOF2炉温实际值")
@Schema(description = "NOF2炉温实际值 (℃)")
private BigDecimal nof2FurnaceTemperatureActual;
@Schema(description = "NOF2炉温设定值")
@Schema(description = "NOF2炉温设定值 (℃)")
private BigDecimal nof2FurnaceTemperatureSet;
@Schema(description = "NOF2炉温控制输出值")
@@ -85,15 +84,15 @@ public class AppMeasureFurnaceMessage extends OpcMessage {
private BigDecimal nof2AirFlowControlOutput;
@Schema(description = "NOF2空燃比实际值")
private BigDecimal nof2AirFuelRatioActual;
private BigDecimal nof2UtheisaKongCombustionRatioActualValue;
@Schema(description = "NOF2空燃比设定值")
private BigDecimal nof2AirFuelRatioSet;
private BigDecimal nof2UtheisaKongCombustionRatioSettingValue;
@Schema(description = "NOF3炉温实际值")
@Schema(description = "NOF3炉温实际值 (℃)")
private BigDecimal nof3FurnaceTemperatureActual;
@Schema(description = "NOF3炉温设定值")
@Schema(description = "NOF3炉温设定值 (℃)")
private BigDecimal nof3FurnaceTemperatureSet;
@Schema(description = "NOF3炉温控制输出值")
@@ -118,15 +117,15 @@ public class AppMeasureFurnaceMessage extends OpcMessage {
private BigDecimal nof3AirFlowControlOutput;
@Schema(description = "NOF3空燃比实际值")
private BigDecimal nof3AirFuelRatioActual;
private BigDecimal nof3UtheisaKongCombustionRatioActualValue;
@Schema(description = "NOF3空燃比设定值")
private BigDecimal nof3AirFuelRatioSet;
private BigDecimal nof3UtheisaKongCombustionRatioSettingValue;
@Schema(description = "NOF4炉温实际值")
@Schema(description = "NOF4炉温实际值 (℃)")
private BigDecimal nof4FurnaceTemperatureActual;
@Schema(description = "NOF4炉温设定值")
@Schema(description = "NOF4炉温设定值 (℃)")
private BigDecimal nof4FurnaceTemperatureSet;
@Schema(description = "NOF4炉温控制输出值")
@@ -151,48 +150,15 @@ public class AppMeasureFurnaceMessage extends OpcMessage {
private BigDecimal nof4AirFlowControlOutput;
@Schema(description = "NOF4空燃比实际值")
private BigDecimal nof4AirFuelRatioActual;
private BigDecimal nof4UtheisaKongCombustionRatioActualValue;
@Schema(description = "NOF4空燃比设定值")
private BigDecimal nof4AirFuelRatioSet;
private BigDecimal nof4UtheisaKongCombustionRatioSettingValue;
@Schema(description = "NOF5炉温实际值")
private BigDecimal nof5FurnaceTemperatureActual;
@Schema(description = "NOF5炉温设定值")
private BigDecimal nof5FurnaceTemperatureSet;
@Schema(description = "NOF5炉温控制输出值")
private BigDecimal nof5FurnaceTemperatureControlOutput;
@Schema(description = "NOF5燃气流量实际值")
private BigDecimal nof5GasFlowActual;
@Schema(description = "NOF5燃气流量设定值")
private BigDecimal nof5GasFlowSet;
@Schema(description = "NOF5燃气流量控制输出值")
private BigDecimal nof5GasFlowControlOutput;
@Schema(description = "NOF5空气流量实际值")
private BigDecimal nof5AirFlowActual;
@Schema(description = "NOF5空气流量设定值")
private BigDecimal nof5AirFlowSet;
@Schema(description = "NOF5空气流量控制输出值")
private BigDecimal nof5AirFlowControlOutput;
@Schema(description = "NOF5空燃比实际值")
private BigDecimal nof5AirFuelRatioActual;
@Schema(description = "NOF5空燃比设定值")
private BigDecimal nof5AirFuelRatioSet;
@Schema(description = "RTF1炉温实际值")
@Schema(description = "RTF1炉温实际值 (℃)")
private BigDecimal rtf1FurnaceTemperatureActual;
@Schema(description = "RTF1炉温设定值")
@Schema(description = "RTF1炉温设定值 (℃)")
private BigDecimal rtf1FurnaceTemperatureSet;
@Schema(description = "RTF1炉温控制输出值")
@@ -217,15 +183,15 @@ public class AppMeasureFurnaceMessage extends OpcMessage {
private BigDecimal rtf1AirFlowControlOutput;
@Schema(description = "RTF1空燃比实际值")
private BigDecimal rtf1AirFuelRatioActual;
private BigDecimal rtf1UtheisaKongCombustionRatioActualValue;
@Schema(description = "RTF1空燃比设定值")
private BigDecimal rtf1AirFuelRatioSet;
private BigDecimal rtf1UtheisaKongCombustionRatioSettingValue;
@Schema(description = "RTF2炉温实际值")
@Schema(description = "RTF2炉温实际值 (℃)")
private BigDecimal rtf2FurnaceTemperatureActual;
@Schema(description = "RTF2炉温设定值")
@Schema(description = "RTF2炉温设定值 (℃)")
private BigDecimal rtf2FurnaceTemperatureSet;
@Schema(description = "RTF2炉温控制输出值")
@@ -250,15 +216,15 @@ public class AppMeasureFurnaceMessage extends OpcMessage {
private BigDecimal rtf2AirFlowControlOutput;
@Schema(description = "RTF2空燃比实际值")
private BigDecimal rtf2AirFuelRatioActual;
private BigDecimal rtf2UtheisaKongCombustionRatioActualValue;
@Schema(description = "RTF2空燃比设定值")
private BigDecimal rtf2AirFuelRatioSet;
private BigDecimal rtf2UtheisaKongCombustionRatioSettingValue;
@Schema(description = "SF炉温实际值")
@Schema(description = "SF炉温实际值 (℃)")
private BigDecimal sfFurnaceTemperatureActual;
@Schema(description = "SF炉温设定值")
@Schema(description = "SF炉温设定值 (℃)")
private BigDecimal sfFurnaceTemperatureSet;
@Schema(description = "SF炉温控制输出值")
@@ -283,31 +249,31 @@ public class AppMeasureFurnaceMessage extends OpcMessage {
private BigDecimal sfAirFlowControlOutput;
@Schema(description = "SF空燃比实际值")
private BigDecimal sfAirFuelRatioActual;
private BigDecimal sfUtheisaKongCombustionRatioActualValue;
@Schema(description = "SF空燃比设定值")
private BigDecimal sfAirFuelRatioSet;
private BigDecimal sfUtheisaKongCombustionRatioSettingValue;
@Schema(description = "NOF板温实际值")
@Schema(description = "NOF板材温度实际值 (℃)")
private BigDecimal nofPlateTemperatureActual;
@Schema(description = "RTF板温实际值")
@Schema(description = "RTF板材温度实际值 (℃)")
private BigDecimal rtfPlateTemperatureActual;
@Schema(description = "SF板温实际值")
@Schema(description = "SF板材温度实际值 (℃)")
private BigDecimal sfPlateTemperatureActual;
@Schema(description = "TDS板温实际值")
@Schema(description = "TDS板材温度实际值 (℃)")
private BigDecimal tdsPlateTemperatureActual;
@Schema(description = "PH炉压实际值")
private BigDecimal phFurnacePressureActual;
private BigDecimal PHFurnacePressureActualValue;
@Schema(description = "PH炉压设定值")
private BigDecimal phFurnacePressureSet;
private BigDecimal PHFurnacePressureSettingValue;
@Schema(description = "PH炉压控制输出值")
private BigDecimal phFurnacePressureControlOutput;
private BigDecimal PHFurnacePressureControlOutputValue;
@Schema(description = "NOF炉压实际值")
private BigDecimal nofFurnacePressureActual;
@@ -318,220 +284,202 @@ public class AppMeasureFurnaceMessage extends OpcMessage {
@Schema(description = "TDS炉压实际值")
private BigDecimal tdsFurnacePressureActual;
@Schema(description = "JCF1炉温实际值")
@Schema(description = "JCF1炉温实际值 (℃)")
private BigDecimal jcf1FurnaceTemperatureActual;
@Schema(description = "JCF1炉温设定值")
@Schema(description = "JCF1炉温设定值 (℃)")
private BigDecimal jcf1FurnaceTemperatureSet;
@Schema(description = "JCF1炉温控制输出值")
private BigDecimal jcf1FurnaceTemperatureControlOutput;
@Schema(description = "JCF1 A相电流")
@Schema(description = "JCF1 A相电流 (A)")
private BigDecimal jcf1PhaseACurrent;
@Schema(description = "JCF1 B相电流")
@Schema(description = "JCF1 B相电流 (A)")
private BigDecimal jcf1PhaseBCurrent;
@Schema(description = "JCF1 C相电流")
@Schema(description = "JCF1 C相电流 (A)")
private BigDecimal jcf1PhaseCCurrent;
@Schema(description = "JCF2炉温实际值")
private BigDecimal jcf2FurnaceTemperatureActual;
@Schema(description = "JCF2炉温设定值")
private BigDecimal jcf2FurnaceTemperatureSet;
@Schema(description = "JCF2炉温控制输出值")
private BigDecimal jcf2FurnaceTemperatureControlOutput;
@Schema(description = "JCF2 A相电流")
private BigDecimal jcf2PhaseACurrent;
@Schema(description = "JCF2 B相电流")
private BigDecimal jcf2PhaseBCurrent;
@Schema(description = "JCF2 C相电流")
private BigDecimal jcf2PhaseCCurrent;
@Schema(description = "LTH炉温实际值")
@Schema(description = "LTH1炉温实际值 (℃)")
private BigDecimal lthFurnaceTemperatureActual;
@Schema(description = "LTH炉温设定值")
@Schema(description = "LTH1炉温设定值 (℃)")
private BigDecimal lthFurnaceTemperatureSet;
@Schema(description = "LTH炉温控制输出值")
@Schema(description = "LTH1炉温控制输出值")
private BigDecimal lthFurnaceTemperatureControlOutput;
@Schema(description = "LTH A相电流")
@Schema(description = "LTH1 A相电流 (A)")
private BigDecimal lthPhaseACurrent;
@Schema(description = "LTH B相电流")
@Schema(description = "LTH1 B相电流 (A)")
private BigDecimal lthPhaseBCurrent;
@Schema(description = "LTH C相电流")
@Schema(description = "LTH1 C相电流 (A)")
private BigDecimal lthPhaseCCurrent;
@Schema(description = "TDS炉温实际值")
@Schema(description = "LTH2炉温实际值 (℃)")
private BigDecimal LTH2FurnaceTemperatureActualValue;
@Schema(description = "LTH2炉温设定值 (℃)")
private BigDecimal LTH2FurnaceTemperatureSettingValue;
@Schema(description = "LTH2炉温控制输出值")
private BigDecimal LTH2FurnaceTemperatureControlOutputValue;
@Schema(description = "LTH2 A相电流 (A)")
private BigDecimal lth2PhaseACurrent;
@Schema(description = "LTH2 B相电流 (A)")
private BigDecimal lth2PhaseBCurrent;
@Schema(description = "LTH2 C相电流 (A)")
private BigDecimal lth2PhaseCCurrent;
@Schema(description = "TDS炉温实际值 (℃)")
private BigDecimal tdsFurnaceTemperatureActual;
@Schema(description = "TDS炉温设定值")
@Schema(description = "TDS炉温设定值 (℃)")
private BigDecimal tdsFurnaceTemperatureSet;
@Schema(description = "TDS炉温控制输出值")
private BigDecimal tdsFurnaceTemperatureControlOutput;
@Schema(description = "TDS A相电流")
@Schema(description = "TDS A相电流 (A)")
private BigDecimal tdsPhaseACurrent;
@Schema(description = "TDS B相电流")
@Schema(description = "TDS B相电流 (A)")
private BigDecimal tdsPhaseBCurrent;
@Schema(description = "TDS C相电流")
@Schema(description = "TDS C相电流 (A)")
private BigDecimal tdsPhaseCCurrent;
@Schema(description = "LBZ炉温实际值")
@Schema(description = "LBZ炉温实际值 (℃)")
private BigDecimal lbzFurnaceTemperatureActual;
@Schema(description = "LBZ炉温设定值")
@Schema(description = "LBZ炉温设定值 (℃)")
private BigDecimal lbzFurnaceTemperatureSet;
@Schema(description = "LBZ炉温控制输出值")
private BigDecimal lbzFurnaceTemperatureControlOutput;
@Schema(description = "LBZ A相电流")
@Schema(description = "LBZ A相电流 (A)")
private BigDecimal lbzPhaseACurrent;
@Schema(description = "LBZ B相电流")
@Schema(description = "LBZ B相电流 (A)")
private BigDecimal lbzPhaseBCurrent;
@Schema(description = "LBZ C相电流")
@Schema(description = "LBZ C相电流 (A)")
private BigDecimal lbzPhaseCCurrent;
@Schema(description = "JCF风机1实际速度")
@Schema(description = "JCF风机1实际速度 (rpm)")
private BigDecimal jcfFan1ActualSpeed;
@Schema(description = "JCF风机1设定速度")
@Schema(description = "JCF风机1设定速度 (rpm)")
private BigDecimal jcfFan1SetSpeed;
@Schema(description = "JCF风机2实际速度")
@Schema(description = "JCF风机2实际速度 (rpm)")
private BigDecimal jcfFan2ActualSpeed;
@Schema(description = "JCF风机2设定速度")
@Schema(description = "JCF风机2设定速度 (rpm)")
private BigDecimal jcfFan2SetSpeed;
@Schema(description = "JCF风机3实际速度")
@Schema(description = "JCF风机3实际速度 (rpm)")
private BigDecimal jcfFan3ActualSpeed;
@Schema(description = "JCF风机3设定速度")
@Schema(description = "JCF风机3设定速度 (rpm)")
private BigDecimal jcfFan3SetSpeed;
@Schema(description = "JCF风机4实际速度")
@Schema(description = "JCF风机4实际速度 (rpm)")
private BigDecimal jcfFan4ActualSpeed;
@Schema(description = "JCF风机4设定速度")
@Schema(description = "JCF风机4设定速度 (rpm)")
private BigDecimal jcfFan4SetSpeed;
@Schema(description = "JCF风机5实际速度")
private BigDecimal jcfFan5ActualSpeed;
@Schema(description = "NOF空预热器烟气换热前温度 (℃)")
private BigDecimal NOFUtetheisaKongFlueGasTemperatureBeforeHeatExchange;
@Schema(description = "JCF风机5设定速度")
private BigDecimal jcfFan5SetSpeed;
@Schema(description = "NOF空预热器烟气换热后温度 (℃)")
private BigDecimal NOFUtetheisaKongFlueGasTemperatureAfterHeatExchange;
@Schema(description = "JCF风机6实际速度")
private BigDecimal jcfFan6ActualSpeed;
@Schema(description = "NOF水预热器烟气换热前温度 (℃)")
private BigDecimal NOFWaterFlueGasTemperatureBeforeHeatExchange;
@Schema(description = "JCF风机6设定速度")
private BigDecimal jcfFan6SetSpeed;
@Schema(description = "NOF水预热器烟气换热后温度 (℃)")
private BigDecimal NOFWaterFlueGasTemperatureAfterHeatExchange;
@Schema(description = "JCF风机7实际速度")
private BigDecimal jcfFan7ActualSpeed;
@Schema(description = "NOF助燃空气温度 (℃)")
private BigDecimal NOFCombustionSupportingAirTemperature;
@Schema(description = "JCF风机7设定速度")
private BigDecimal jcfFan7SetSpeed;
@Schema(description = "RTF热风烟气换热前温度 (℃)")
private BigDecimal RTFHotWindGasTemperatureBeforeHeatExchange;
@Schema(description = "NOF空气换热前烟气温度")
private BigDecimal nofAirPreheatFlueGasTemperature;
@Schema(description = "RTF排烟风机入口烟气温度 (℃)")
private BigDecimal RTFSmokeExhaustFanInletGasTemperature;
@Schema(description = "NOF空气换热后烟气温度")
private BigDecimal nofAirPostheatFlueGasTemperature;
@Schema(description = "NOF水换热后烟气温度")
private BigDecimal nofWaterPostheatFlueGasTemperature;
@Schema(description = "NOF排烟风机前烟气温度")
private BigDecimal nofExhaustFanInletFlueGasTemperature;
@Schema(description = "NOF助燃空气温度")
private BigDecimal nofCombustionAirTemperature;
@Schema(description = "RTF热风换热前烟气温度")
private BigDecimal rtfAirPreheatFlueGasTemperature;
@Schema(description = "RTF排烟风机前烟气温度")
private BigDecimal rtfExhaustFanInletFlueGasTemperature;
@Schema(description = "NOF燃气压力")
@Schema(description = "NOF燃气压力 (Pa)")
private BigDecimal nofGasPressure;
@Schema(description = "点火燃气压力")
@Schema(description = "点火燃气压力 (Pa)")
private BigDecimal ignitionGasPressure;
@Schema(description = "点火空气压力")
private BigDecimal ignitionAirPressure;
@Schema(description = "NOF空气压力 (Pa)")
private BigDecimal nofAirPressure;
@Schema(description = "RTF燃气压力")
@Schema(description = "RTF燃气压力 (Pa)")
private BigDecimal rtfGasPressure;
@Schema(description = "NOF空气压力实际值")
@Schema(description = "NOF空气压力实际值 (Pa)")
private BigDecimal nofAirPressureActual;
@Schema(description = "NOF空气压力设定值")
@Schema(description = "NOF空气压力设定值 (Pa)")
private BigDecimal nofAirPressureSet;
@Schema(description = "NOF空气压力控制输出值")
private BigDecimal nofAirPressureControlOutput;
@Schema(description = "NOF烟气压力实际值")
private BigDecimal nofFlueGasPressureActual;
@Schema(description = "NOF烟气压力实际值 (Pa)")
private BigDecimal nofGasPressureActual;
@Schema(description = "NOF烟气压力设定值")
private BigDecimal nofFlueGasPressureSet;
@Schema(description = "NOF烟气压力设定值 (Pa)")
private BigDecimal nofGasPressureSet;
@Schema(description = "NOF烟气压力控制输出值")
private BigDecimal nofFlueGasPressureControlOutput;
private BigDecimal nofGasPressureControlOutput;
@Schema(description = "RTF空气压力实际值")
@Schema(description = "RTF空气压力实际值 (Pa)")
private BigDecimal rtfAirPressureActual;
@Schema(description = "RTF空气压力设定值")
@Schema(description = "RTF空气压力设定值 (Pa)")
private BigDecimal rtfAirPressureSet;
@Schema(description = "RTF空气压力控制输出值")
private BigDecimal rtfAirPressureControlOutput;
@Schema(description = "RTF烟气压力实际值")
private BigDecimal rtfFlueGasPressureActual;
@Schema(description = "RTF烟气压力实际值 (Pa)")
private BigDecimal rtfGasPressureActual;
@Schema(description = "RTF烟气压力设定值")
private BigDecimal rtfFlueGasPressureSet;
@Schema(description = "RTF烟气压力设定值 (Pa)")
private BigDecimal rtfGasPressureSet;
@Schema(description = "RTF烟气压力控制输出值")
private BigDecimal rtfFlueGasPressureControlOutput;
private BigDecimal rtfGasPressureControlOutput;
@Schema(description = "炉气氛微氧含量")
@Schema(description = "炉气氛微氧含量 (%)")
private BigDecimal furnaceAtmosphereOxygenContent;
@Schema(description = "炉气氛氢含量")
@Schema(description = "炉气氛氢含量 (%)")
private BigDecimal furnaceAtmosphereHydrogenContent;
@Schema(description = "炉气氛露点温度")
@Schema(description = "炉气氛露点温度 (℃)")
private BigDecimal furnaceAtmosphereDewPoint;
@Schema(description = "燃气瞬时流量")
private BigDecimal gasInstantaneousFlow;
private BigDecimal InstantaneousGasFlowRate;
@Schema(description = "燃气瞬时耗量")
private BigDecimal gasInstantaneousConsumption;
private BigDecimal InstantaneousGasConsumption;
}

View File

@@ -0,0 +1,13 @@
package com.fizz.business.domain.msg;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
@Data
@EqualsAndHashCode(callSuper = true)
@Schema(description = "出口移动电文")
public class L2HeartMessage extends OpcMessage{
@Schema(description = "计数器")
private Integer counter;
}

View File

@@ -120,6 +120,56 @@ public class PdiSetup extends OpcMessage{
@Schema(description = "BR9-TR 张力")
private BigDecimal tensionBR9TR;
// 新增的张力设定值字段
@Schema(description = "开卷机1当前张力")
private BigDecimal tensionPor1Current;
@Schema(description = "开卷机1下一设定张力")
private BigDecimal tensionPor1Next;
@Schema(description = "开卷机2当前张力")
private BigDecimal tensionPor2Current;
@Schema(description = "开卷机2下一设定张力")
private BigDecimal tensionPor2Next;
@Schema(description = "入口活套当前张力")
private BigDecimal tensionEnLpCurrent;
@Schema(description = "入口活套下一设定张力")
private BigDecimal tensionEnLpNext;
@Schema(description = "清洗段当前张力")
private BigDecimal tensionCleaningCurrent;
@Schema(description = "清洗段下一设定张力")
private BigDecimal tensionCleaningNext;
@Schema(description = "炉区当前张力")
private BigDecimal tensionFuranceCurrent;
@Schema(description = "炉区下一设定张力")
private BigDecimal tensionFuranceNext;
@Schema(description = "镀后冷却当前张力")
private BigDecimal tensionGalvanizingCoolCurrent;
@Schema(description = "镀后冷却下一设定张力")
private BigDecimal tensionGalvanizingCoolNext;
@Schema(description = "光整机入口当前张力")
private BigDecimal tensionTmEntryCurrent;
@Schema(description = "光整机入口下一设定张力")
private BigDecimal tensionTmEntryNext;
@Schema(description = "光整机出口当前张力")
private BigDecimal tensionTmExitCurrent;
@Schema(description = "光整机出口下一设定张力")
private BigDecimal tensionTmExitNext;
@Schema(description = "拉矫机当前张力")
private BigDecimal tensionTlCurrent;
@Schema(description = "拉矫机下一设定张力")
private BigDecimal tensionTlNext;
@Schema(description = "涂敷段当前张力")
private BigDecimal tensionCoatingCurrent;
@Schema(description = "涂敷段下一设定张力")
private BigDecimal tensionCoatingNext;
@Schema(description = "出口活套当前张力")
private BigDecimal tensionExLpCurrent;
@Schema(description = "出口活套下一设定张力")
private BigDecimal tensionExLpNext;
@Schema(description = "卷取机当前张力")
private BigDecimal tensionTrCurrent;
@Schema(description = "卷取机下一设定张力")
private BigDecimal tensionTrNext;
@Schema(description = "涂油投入")
private Integer oilingFlag;
@Schema(description = "上表面涂油量")

View File

@@ -0,0 +1,33 @@
package com.fizz.business.domain.s7;
import com.github.xingshuangs.iot.common.enums.EDataType;
import com.github.xingshuangs.iot.protocol.s7.serializer.S7Variable;
import lombok.Data;
@Data
public class DB35501Data {
@S7Variable(address = "DB35501.0", type = EDataType.STRING, count = 20)
private String coilId;
@S7Variable(address = "DB35501.30", type = EDataType.FLOAT32)
private float entryCoilWeight;
@S7Variable(address = "DB35501.34", type = EDataType.FLOAT32)
private float entryCoilLength;
@S7Variable(address = "DB35501.38", type = EDataType.FLOAT32)
private float entryCoilWidth;
@S7Variable(address = "DB35501.42", type = EDataType.FLOAT32)
private float entryCoilThick;
@S7Variable(address = "DB35501.46", type = EDataType.FLOAT32)
private float entryCoilInnerDia;
@S7Variable(address = "DB35501.50", type = EDataType.FLOAT32)
private float entryCoilOuterDia;
@S7Variable(address = "DB35501.54", type = EDataType.BYTE)
private byte alloyCode;
}

View File

@@ -0,0 +1,39 @@
package com.fizz.business.domain.s7;
import com.github.xingshuangs.iot.common.enums.EDataType;
import com.github.xingshuangs.iot.protocol.s7.serializer.S7Variable;
import lombok.Data;
@Data
public class DB35502Data {
@S7Variable(address = "DB35502.114", type = EDataType.FLOAT32)
private float tensionPor1Next;
@S7Variable(address = "DB35502.122", type = EDataType.FLOAT32)
private float tensionPor2Next;
@S7Variable(address = "DB35502.130", type = EDataType.FLOAT32)
private float tensionEnLpNext;
@S7Variable(address = "DB35502.138", type = EDataType.FLOAT32)
private float tensionCleaningNext;
@S7Variable(address = "DB35502.162", type = EDataType.FLOAT32)
private float tensionGalvanizingCoolNext;
@S7Variable(address = "DB35502.266", type = EDataType.FLOAT32)
private float tensionExLpNext;
@S7Variable(address = "DB35502.232", type = EDataType.FLOAT32)
private float tensionTlNext;
@S7Variable(address = "DB35502.198", type = EDataType.FLOAT32)
private float tensionTmExitNext;
@S7Variable(address = "DB35502.146", type = EDataType.FLOAT32)
private float tensionFuranceNext;
@S7Variable(address = "DB35502.274", type = EDataType.FLOAT32)
private float tensionTrNext;
}

View File

@@ -0,0 +1,22 @@
package com.fizz.business.domain.vo;
import lombok.Data;
/**
* 模板明细 VO
*/
@Data
public class BizSendTemplateItemVO {
private Integer templateItemId;
private Integer templateId;
private Integer itemNo;
private String paramCode;
private String labelEn;
private String groupNameEn;
private String address;
private String defaultValueRaw;
private Boolean enabled;
}

View File

@@ -0,0 +1,21 @@
package com.fizz.business.domain.vo;
import lombok.Data;
import java.util.List;
/**
* 模板主VO含明细
*/
@Data
public class BizSendTemplateVO {
private Integer templateId;
private String templateCode;
private String templateName;
private String deviceName;
private String groupType;
private Integer enabled;
private List<BizSendTemplateItemVO> items;
}

View File

@@ -0,0 +1,22 @@
package com.fizz.business.domain.vo;
import lombok.Data;
import java.util.Date;
/**
* 炉火写入时的钢卷信息(存储到 Redis
*/
@Data
public class FurnaceSendCoilInfoVO {
/** 钢卷号 */
private String coilId;
/** 计划ID */
private String planId;
/** 写入时间 */
private Date sendTime;
}

View File

@@ -0,0 +1,12 @@
package com.fizz.business.domain.vo;
import lombok.Data;
@Data
public class ProStoppageTypeVO {
private Integer stopType;
private String remark;
}

View File

@@ -0,0 +1,26 @@
package com.fizz.business.domain.vo;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.util.Date;
import java.util.List;
/**
* 发送任务详情 VO
*/
@Data
@EqualsAndHashCode(callSuper = true)
public class SendJobDetailVO extends SendJobVO {
private Date planSendTime;
private Date actualSendTime;
private Date finishTime;
private String remark;
private List<SendJobGroupVO> groups;
}

View File

@@ -0,0 +1,27 @@
package com.fizz.business.domain.vo;
import lombok.Data;
import java.util.List;
/**
* 发送任务分组 VO
*/
@Data
public class SendJobGroupVO {
private Integer groupId;
private Integer jobId;
private Integer groupNo;
private String groupType;
private String groupName;
private String status;
private List<SendJobItemVO> items;
}

View File

@@ -0,0 +1,39 @@
package com.fizz.business.domain.vo;
import lombok.Data;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.Date;
/**
* 发送任务明细项 VO
*/
@Data
public class SendJobItemVO {
private Integer itemId;
private Integer jobId;
private Integer groupId;
private String paramCode;
private String address;
private String valueRaw;
private BigDecimal valueNum;
private Date setTime;
private String resultStatus;
private String resultMsg;
private Integer retryCount;
private LocalDateTime createTime;
}

View File

@@ -0,0 +1,26 @@
package com.fizz.business.domain.vo;
import lombok.Data;
import java.util.Date;
import java.util.Map;
/**
* 最近一次成功发送结果(用于前端推荐默认值 + 显示上次发送时间)
*/
@Data
public class SendJobLastSuccessVO {
/** 最近一次成功发送时间job.finish_time */
private Date lastSendTime;
/** paramCode -> valueRaw */
private Map<String, String> values;
/** 最近一次成功的jobId可选 */
private Integer jobId;
//IsFromHistory
private Boolean isFromHistory;
}

View File

@@ -0,0 +1,27 @@
package com.fizz.business.domain.vo;
import lombok.Data;
import java.util.Date;
/**
* 发送任务列表 VO
*/
@Data
public class SendJobVO {
private Integer jobId;
private String bizKey;
private String deviceName;
private String status;
private Long operatorId;
private String operatorName;
private Date createTime;
}

View File

@@ -0,0 +1,153 @@
package com.fizz.business.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
import java.util.List;
import java.util.Map;
/**
* 设备图表数据 DTO
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Schema(description = "设备图表数据")
public class DeviceChartDataDTO implements Serializable {
private static final long serialVersionUID = 1L;
@Schema(description = "设备类型分布饼图数据")
private PieChartData deviceTypePieChart;
@Schema(description = "数据来源分布条形图数据")
private BarChartData sourceTypeBarChart;
@Schema(description = "同类型设备对比折线图数据(单位相同)")
private LineChartData sameTypeDeviceCompareChart;
@Schema(description = "设备统计数据")
private List<DeviceStatistics> deviceStatistics;
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Schema(description = "饼图数据")
public static class PieChartData implements Serializable {
private static final long serialVersionUID = 1L;
@Schema(description = "数据系列")
private List<PieSeries> series;
}
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Schema(description = "饼图系列")
public static class PieSeries implements Serializable {
private static final long serialVersionUID = 1L;
@Schema(description = "名称")
private String name;
@Schema(description = "数值")
private Double data;
@Schema(description = "颜色")
private String color;
}
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Schema(description = "条形图数据")
public static class BarChartData implements Serializable {
private static final long serialVersionUID = 1L;
@Schema(description = "分类轴")
private List<String> categories;
@Schema(description = "数据系列")
private List<BarSeries> series;
}
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Schema(description = "条形图系列")
public static class BarSeries implements Serializable {
private static final long serialVersionUID = 1L;
@Schema(description = "系列名称")
private String name;
@Schema(description = "数据值列表")
private List<Double> data;
}
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Schema(description = "折线图数据")
public static class LineChartData implements Serializable {
private static final long serialVersionUID = 1L;
@Schema(description = "时间轴")
private List<String> categories;
@Schema(description = "数据系列")
private List<LineSeries> series;
}
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Schema(description = "折线图系列")
public static class LineSeries implements Serializable {
private static final long serialVersionUID = 1L;
@Schema(description = "系列名称")
private String name;
@Schema(description = "数据值列表")
private List<Double> data;
}
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Schema(description = "设备统计数据")
public static class DeviceStatistics implements Serializable {
private static final long serialVersionUID = 1L;
@Schema(description = "设备代码")
private String deviceCode;
@Schema(description = "设备名称")
private String deviceName;
@Schema(description = "平均值")
private String avg;
@Schema(description = "最大值")
private String max;
@Schema(description = "最小值")
private String min;
@Schema(description = "当前值")
private String current;
}
}

View File

@@ -0,0 +1,55 @@
package com.fizz.business.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
import java.util.List;
/**
* 单设备-单字段的趋势与统计
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Schema(description = "设备字段趋势数据")
public class DeviceFieldTrendDTO implements Serializable {
private static final long serialVersionUID = 1L;
@Schema(description = "设备代码")
private String deviceCode;
@Schema(description = "设备名称")
private String deviceName;
@Schema(description = "字段名")
private String fieldName;
@Schema(description = "字段中文名(可选)")
private String fieldLabel;
@Schema(description = "单位(可选)")
private String unit;
@Schema(description = "时间轴(HH:mm)")
private List<String> categories;
@Schema(description = "数据点")
private List<Double> data;
@Schema(description = "统计-平均值")
private Double avg;
@Schema(description = "统计-最大值")
private Double max;
@Schema(description = "统计-最小值")
private Double min;
@Schema(description = "统计-最新值")
private Double last;
}

View File

@@ -0,0 +1,26 @@
package com.fizz.business.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.io.Serializable;
import java.util.List;
/**
* WS 订阅:设备字段趋势
*/
@Data
@Schema(description = "设备字段趋势订阅请求")
public class DeviceFieldTrendSubscribeReq implements Serializable {
private static final long serialVersionUID = 1L;
@Schema(description = "设备代码列表,为空表示不变")
private List<String> deviceCodes;
@Schema(description = "字段名列表,为空表示不变")
private List<String> fieldNames;
@Schema(description = "是否只推送可见范围(用于懒加载)true=只推 deviceCodes/fieldNames 命中的数据")
private Boolean lazy;
}

View File

@@ -0,0 +1,54 @@
package com.fizz.business.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
import java.util.List;
import java.util.Map;
/**
* 设备历史趋势数据 DTO
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Schema(description = "设备历史趋势数据")
public class DeviceHistoryTrendDTO implements Serializable {
private static final long serialVersionUID = 1L;
@Schema(description = "设备代码")
private String deviceCode;
@Schema(description = "设备描述")
private String deviceName;
@Schema(description = "时间轴格式HH:mm")
private List<String> categories;
@Schema(description = "数据系列key为字段名value为数据值列表")
private List<SeriesData> series;
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Schema(description = "数据系列")
public static class SeriesData implements Serializable {
private static final long serialVersionUID = 1L;
@Schema(description = "系列名称(字段标签)")
private String name;
@Schema(description = "字段名")
private String fieldName;
@Schema(description = "数据值列表")
private List<Double> data;
}
}

View File

@@ -5,6 +5,7 @@ import lombok.Getter;
import lombok.Setter;
import java.io.Serializable;
import java.math.BigDecimal;
/**
* 子计划数据
@@ -57,4 +58,7 @@ public class PdiPlanSubDTO implements Serializable {
@Schema(description = "实际重量")
private Double actualWeight;
@Schema(description = "锌层厚度")
private BigDecimal zincCoatingThickness;
}

View File

@@ -6,6 +6,7 @@ import lombok.Getter;
import lombok.Setter;
import java.io.Serializable;
import java.math.BigDecimal;
import java.time.LocalDateTime;
/**
@@ -71,4 +72,7 @@ public class PdoExCoilSubDTO implements Serializable {
@Schema(description = "结束时间")
private LocalDateTime endTime;
@Schema(description = "锌层厚度")
private BigDecimal zincCoatingThickness;
}

View File

@@ -115,5 +115,5 @@ public class CrmPdiPlanForm {
private BigDecimal tailendGaugeLength; // 尾端测厚长度(mm)
private String origin; // 产地
private String originCoilid; // 原卷号
private BigDecimal zincCoatingThickness;//锌层厚度
}

View File

@@ -3,6 +3,7 @@ package com.fizz.business.form;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.math.BigDecimal;
import java.time.LocalDateTime;
@Data
@@ -18,4 +19,13 @@ public class CrmPdoExcoilForm {
@Schema(description = "结束日期")
private String endDate;
@Schema(description = "锌层厚度")
private BigDecimal zincCoatingThickness;
@Schema(description = "页码", example = "1")
private Integer pageNum = 1;
@Schema(description = "每页数量", example = "20")
private Integer pageSize = 20;
}

View File

@@ -0,0 +1,27 @@
package com.fizz.business.form;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import javax.validation.Valid;
import javax.validation.constraints.NotEmpty;
import java.io.Serializable;
import java.util.List;
/**
* OPC 批量写数据请求表单
*/
@Data
@Schema(description = "OPC 批量写数据请求")
public class OpcBatchWriteDataForm implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 批量写数据列表
*/
@Schema(description = "批量写数据列表")
@NotEmpty(message = "写数据列表不能为空")
@Valid
private List<OpcWriteDataForm> dataList;
}

View File

@@ -0,0 +1,35 @@
package com.fizz.business.form;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import java.io.Serializable;
import java.util.List;
import java.util.Map;
/**
* OPC 写数据请求表单
*/
@Data
@Schema(description = "OPC 写数据请求")
public class OpcWriteDataForm implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 字段名对象属性名例如coilId
* 系统会自动查找对应的 OPC 节点路径
*/
@Schema(description = "字段名(对象属性名)", example = "coilId")
@NotBlank(message = "字段名不能为空")
private String fieldName;
/**
* 要写入的值支持多种类型String, Integer, Double, Boolean 等)
*/
@Schema(description = "要写入的值", example = "COIL001")
@NotNull(message = "写入值不能为空")
private Object value;
}

View File

@@ -0,0 +1,10 @@
package com.fizz.business.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.fizz.business.domain.BizSendJobGroup;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface BizSendJobGroupMapper extends BaseMapper<BizSendJobGroup> {
}

View File

@@ -0,0 +1,10 @@
package com.fizz.business.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.fizz.business.domain.BizSendJobItem;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface BizSendJobItemMapper extends BaseMapper<BizSendJobItem> {
}

View File

@@ -0,0 +1,10 @@
package com.fizz.business.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.fizz.business.domain.BizSendJob;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface BizSendJobMapper extends BaseMapper<BizSendJob> {
}

View File

@@ -0,0 +1,10 @@
package com.fizz.business.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.fizz.business.domain.BizSendTemplateItem;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface BizSendTemplateItemMapper extends BaseMapper<BizSendTemplateItem> {
}

View File

@@ -0,0 +1,10 @@
package com.fizz.business.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.fizz.business.domain.BizSendTemplate;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface BizSendTemplateMapper extends BaseMapper<BizSendTemplate> {
}

View File

@@ -0,0 +1,10 @@
package com.fizz.business.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.fizz.business.domain.DeviceSnapshot;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface DeviceSnapshotMapper extends BaseMapper<DeviceSnapshot> {
}

View File

@@ -1,63 +1,16 @@
package com.fizz.business.mapper;
import java.util.List;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.fizz.business.domain.PdiSetups;
/**
* 生产计划的参数详情Mapper接口
*
*
* @author Joshi
* @date 2025-09-25
*/
public interface PdiSetupMapper extends BaseMapper<PdiSetups>
{
/**
* 查询生产计划的参数详情
*
* @param id 生产计划的参数详情主键
* @return 生产计划的参数详情
*/
public PdiSetups selectPdiSetupById(Long id);
/**
* 查询生产计划的参数详情列表
*
* @param pdiSetup 生产计划的参数详情
* @return 生产计划的参数详情集合
*/
public List<PdiSetups> selectPdiSetupList(PdiSetups pdiSetup);
/**
* 新增生产计划的参数详情
*
* @param pdiSetup 生产计划的参数详情
* @return 结果
*/
public int insertPdiSetup(PdiSetups pdiSetup);
/**
* 修改生产计划的参数详情
*
* @param pdiSetup 生产计划的参数详情
* @return 结果
*/
public int updatePdiSetup(PdiSetups pdiSetup);
/**
* 删除生产计划的参数详情
*
* @param id 生产计划的参数详情主键
* @return 结果
*/
public int deletePdiSetupById(Long id);
/**
* 批量删除生产计划的参数详情
*
* @param ids 需要删除的数据主键集合
* @return 结果
*/
public int deletePdiSetupByIds(Long[] ids);
// 使用 MyBatis-Plus BaseMapper 提供基础 CRUD含按 id 的 selectById/deleteById/updateById 等)。
}

View File

@@ -0,0 +1,20 @@
package com.fizz.business.mapper;
import org.apache.ibatis.annotations.Mapper;
import java.util.Map;
/**
* 计划相关仪表板 Mappercrm_pdi_plan
*/
@Mapper
public interface PlanDashboardMapper {
/**
* 查询当前生产中的计划status = 'PRODUCING'
* 返回字段至少包括:
* - coilid, planid, steel_grade, entry_weight, entry_thick, entry_width, start_date 等
*/
Map<String, Object> selectCurrentProducingPlan();
}

View File

@@ -0,0 +1,8 @@
package com.fizz.business.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.fizz.business.domain.ProStoppageType;
public interface ProStoppageTypeMapper extends BaseMapper<ProStoppageType> {
}

View File

@@ -1,18 +1,16 @@
package com.fizz.business.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.fizz.business.domain.SegmentTotal;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
/**
* <p>
* 各机张力,电流等架跟踪表 Mapper 接口
* </p>
*
* @author baomidou
* @since 2023-10-26
* 带钢段工艺参数 Mappercpl_segment_total
*/
@Mapper
public interface SegmentTotalMapper extends BaseMapper<SegmentTotal> {
SegmentTotal getLatestRecord();
public interface SegmentTotalMapper {
/**
* 根据入库钢卷号查询最新一段的 total_values_json
*/
String selectLatestTotalValuesJsonByCoilId(@Param("coilId") String coilId);
}

View File

@@ -0,0 +1,26 @@
package com.fizz.business.mapper;
import java.util.List;
import org.apache.ibatis.annotations.Param;
import com.fizz.business.domain.SetupTensionAllLine;
/**
* 全线张力Mapper接口
*/
public interface SetupTensionAllLineMapper
{
SetupTensionAllLine selectByKey(@Param("steelGrade") String steelGrade,
@Param("thick") Float thick,
@Param("yieldStren") Float yieldStren);
List<SetupTensionAllLine> selectList(SetupTensionAllLine query);
int insert(SetupTensionAllLine entity);
int updateByKey(SetupTensionAllLine entity);
int deleteByKey(@Param("steelGrade") String steelGrade,
@Param("thick") Float thick,
@Param("yieldStren") Float yieldStren);
}

View File

@@ -0,0 +1,26 @@
package com.fizz.business.mapper;
import java.util.List;
import org.apache.ibatis.annotations.Param;
import com.fizz.business.domain.SetupTensionAnnealingFurnace;
/**
* 退火炉张力Mapper接口
*/
public interface SetupTensionAnnealingFurnaceMapper
{
SetupTensionAnnealingFurnace selectByKey(@Param("steelGrade") String steelGrade,
@Param("thick") Float thick,
@Param("yieldStren") Float yieldStren);
List<SetupTensionAnnealingFurnace> selectList(SetupTensionAnnealingFurnace query);
int insert(SetupTensionAnnealingFurnace entity);
int updateByKey(SetupTensionAnnealingFurnace entity);
int deleteByKey(@Param("steelGrade") String steelGrade,
@Param("thick") Float thick,
@Param("yieldStren") Float yieldStren);
}

View File

@@ -0,0 +1,26 @@
package com.fizz.business.mapper;
import java.util.List;
import org.apache.ibatis.annotations.Param;
import com.fizz.business.domain.SetupTensionLeveler;
/**
* 平整机张力Mapper接口
*/
public interface SetupTensionLevelerMapper
{
SetupTensionLeveler selectByKey(@Param("steelGrade") String steelGrade,
@Param("thick") Float thick,
@Param("yieldStren") Float yieldStren);
List<SetupTensionLeveler> selectList(SetupTensionLeveler query);
int insert(SetupTensionLeveler entity);
int updateByKey(SetupTensionLeveler entity);
int deleteByKey(@Param("steelGrade") String steelGrade,
@Param("thick") Float thick,
@Param("yieldStren") Float yieldStren);
}

View File

@@ -1,62 +0,0 @@
package com.fizz.business.mapper;
import java.util.List;
import com.fizz.business.domain.SetupTension;
import org.apache.ibatis.annotations.Param;
/**
* 全线张力Mapper接口
*
* @author ruoyi
* @date 2025-09-26
*/
public interface SetupTensionMapper
{
/**
* 查询全线张力
*
* @param thick 全线张力主键
* @return 全线张力
*/
public SetupTension selectSetupTensionByThick(@Param("thick") Long thick,@Param("yieldStren") Long yieldStren);
/**
* 查询全线张力列表
*
* @param setupTension 全线张力
* @return 全线张力集合
*/
public List<SetupTension> selectSetupTensionList(SetupTension setupTension);
/**
* 新增全线张力
*
* @param setupTension 全线张力
* @return 结果
*/
public int insertSetupTension(SetupTension setupTension);
/**
* 修改全线张力
*
* @param setupTension 全线张力
* @return 结果
*/
public int updateSetupTension(SetupTension setupTension);
/**
* 删除全线张力
*
* @param thick 全线张力主键
* @return 结果
*/
public int deleteSetupTensionByThick(Long thick);
/**
* 批量删除全线张力
*
* @param thicks 需要删除的数据主键集合
* @return 结果
*/
public int deleteSetupTensionByThicks(@Param("thicks") Long[] thicks,@Param("yieldStrens") Long[] yieldStrens);
}

View File

@@ -0,0 +1,26 @@
package com.fizz.business.mapper;
import java.util.List;
import org.apache.ibatis.annotations.Param;
import com.fizz.business.domain.SetupTensionStraightener;
/**
* 矫直机张力Mapper接口
*/
public interface SetupTensionStraightenerMapper
{
SetupTensionStraightener selectByKey(@Param("steelGrade") String steelGrade,
@Param("thick") Float thick,
@Param("yieldStren") Float yieldStren);
List<SetupTensionStraightener> selectList(SetupTensionStraightener query);
int insert(SetupTensionStraightener entity);
int updateByKey(SetupTensionStraightener entity);
int deleteByKey(@Param("steelGrade") String steelGrade,
@Param("thick") Float thick,
@Param("yieldStren") Float yieldStren);
}

View File

@@ -1,62 +0,0 @@
package com.fizz.business.mapper;
import java.util.List;
import com.fizz.business.domain.SetupTl;
import org.apache.ibatis.annotations.Param;
/**
* 拉矫机参数Mapper接口
*
* @author ruoyi
* @date 2025-09-26
*/
public interface SetupTlMapper
{
/**
* 查询拉矫机参数
*
* @param steelGrade 拉矫机参数主键
* @return 拉矫机参数
*/
public SetupTl selectSetupTlBySteelGrade(@Param("steelGrade") String steelGrade,@Param("yieldStren") Long yieldStren,@Param("thick") Long thick);
/**
* 查询拉矫机参数列表
*
* @param setupTl 拉矫机参数
* @return 拉矫机参数集合
*/
public List<SetupTl> selectSetupTlList(SetupTl setupTl);
/**
* 新增拉矫机参数
*
* @param setupTl 拉矫机参数
* @return 结果
*/
public int insertSetupTl(SetupTl setupTl);
/**
* 修改拉矫机参数
*
* @param setupTl 拉矫机参数
* @return 结果
*/
public int updateSetupTl(SetupTl setupTl);
/**
* 删除拉矫机参数
*
* @param steelGrade 拉矫机参数主键
* @return 结果
*/
public int deleteSetupTlBySteelGrade(String steelGrade);
/**
* 批量删除拉矫机参数
*
* @param steelGrades 需要删除的数据主键集合
* @return 结果
*/
public int deleteSetupTlBySteelGrades(@Param("steelGrades") String[] steelGrades,@Param("yieldStrens") Long[] yieldStrens,@Param("thicks") Long[] thicks);
}

View File

@@ -1,62 +0,0 @@
package com.fizz.business.mapper;
import java.util.List;
import com.fizz.business.domain.SetupTmBendforce;
import org.apache.ibatis.annotations.Param;
/**
* 光整机弯辊力Mapper接口
*
* @author Joshi
* @date 2025-09-26
*/
public interface SetupTmBendforceMapper
{
/**
* 查询光整机弯辊力
*
* @param width 光整机弯辊力主键
* @return 光整机弯辊力
*/
public SetupTmBendforce selectSetupTmBendforceByWidth(@Param("width") Long width,@Param("rollForce") Long rollForce);
/**
* 查询光整机弯辊力列表
*
* @param setupTmBendforce 光整机弯辊力
* @return 光整机弯辊力集合
*/
public List<SetupTmBendforce> selectSetupTmBendforceList(SetupTmBendforce setupTmBendforce);
/**
* 新增光整机弯辊力
*
* @param setupTmBendforce 光整机弯辊力
* @return 结果
*/
public int insertSetupTmBendforce(SetupTmBendforce setupTmBendforce);
/**
* 修改光整机弯辊力
*
* @param setupTmBendforce 光整机弯辊力
* @return 结果
*/
public int updateSetupTmBendforce(SetupTmBendforce setupTmBendforce);
/**
* 删除光整机弯辊力
*
* @param width 光整机弯辊力主键
* @return 结果
*/
public int deleteSetupTmBendforceByWidth(Long width);
/**
* 批量删除光整机弯辊力
*
* @param widths 需要删除的数据主键集合
* @return 结果
*/
public int deleteSetupTmBendforceByWidths(@Param("widths") Long[] widths,@Param("rollForces") Long[] rollForces);
}

View File

@@ -1,64 +0,0 @@
package com.fizz.business.mapper;
import java.util.List;
import com.fizz.business.domain.SetupTmMesh;
import org.apache.ibatis.annotations.Param;
/**
* 光整机插入量Mapper接口
*
* @author Joshi
* @date 2025-09-26
*/
public interface SetupTmMeshMapper
{
/**
* 查询光整机插入量
*
* @param steelGrade 光整机插入量主键
* @return 光整机插入量
*/
public SetupTmMesh selectSetupTmMeshBySteelGrade(@Param("steelGrade") String steelGrade,@Param("yieldStren") Long yieldStren,@Param("thick") Long thick);
/**
* 查询光整机插入量列表
*
* @param setupTmMesh 光整机插入量
* @return 光整机插入量集合
*/
public List<SetupTmMesh> selectSetupTmMeshList(SetupTmMesh setupTmMesh);
/**
* 新增光整机插入量
*
* @param setupTmMesh 光整机插入量
* @return 结果
*/
public int insertSetupTmMesh(SetupTmMesh setupTmMesh);
/**
* 修改光整机插入量
*
* @param setupTmMesh 光整机插入量
* @return 结果
*/
public int updateSetupTmMesh(SetupTmMesh setupTmMesh);
/**
* 删除光整机插入量
*
* @param steelGrade 光整机插入量主键
* @return 结果
*/
public int deleteSetupTmMeshBySteelGrade(String steelGrade);
/**
* 批量删除光整机插入量
*
* @param steelGrades 需要删除的数据主键集合
* @return 结果
*/
public int deleteSetupTmMeshBySteelGrades(@Param("steelGrades") String[] steelGrades,
@Param("yieldStrens") Long[] yieldStrens,
@Param("thicks") Long[] thicks);
}

View File

@@ -1,65 +0,0 @@
package com.fizz.business.mapper;
import java.util.List;
import com.fizz.business.domain.SetupTmRollforce;
import org.apache.ibatis.annotations.Param;
/**
* 光整机轧制力Mapper接口
*
* @author Joshi
* @date 2025-09-26
*/
public interface SetupTmRollforceMapper
{
/**
* 查询光整机轧制力
*
* @param steelGrade 光整机轧制力主键
* @return 光整机轧制力
*/
public SetupTmRollforce selectSetupTmRollforceBySteelGrade(@Param("steelGrade") String steelGrade,@Param("yieldStren") Long yieldStren,@Param("thick") Long thick,@Param("elong") Long elong);
/**
* 查询光整机轧制力列表
*
* @param setupTmRollforce 光整机轧制力
* @return 光整机轧制力集合
*/
public List<SetupTmRollforce> selectSetupTmRollforceList(SetupTmRollforce setupTmRollforce);
/**
* 新增光整机轧制力
*
* @param setupTmRollforce 光整机轧制力
* @return 结果
*/
public int insertSetupTmRollforce(SetupTmRollforce setupTmRollforce);
/**
* 修改光整机轧制力
*
* @param setupTmRollforce 光整机轧制力
* @return 结果
*/
public int updateSetupTmRollforce(SetupTmRollforce setupTmRollforce);
/**
* 删除光整机轧制力
*
* @param steelGrade 光整机轧制力主键
* @return 结果
*/
public int deleteSetupTmRollforceBySteelGrade(String steelGrade);
/**
* 批量删除光整机轧制力
*
* @param steelGrades 需要删除的数据主键集合
* @return 结果
*/
public int deleteSetupTmRollforceBySteelGrades(@Param("steelGrades") String[] steelGrades,
@Param("thicks") Long[] thicks,
@Param("yieldStrens") Long[] yieldStrens,
@Param("elongs") Long[] elongs);
}

View File

@@ -3,7 +3,6 @@ package com.fizz.business.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.fizz.business.domain.StdAlloy;
import com.fizz.business.domain.SteelGradeInfo;
import org.apache.ibatis.annotations.Mapper;
@Mapper

View File

@@ -0,0 +1,40 @@
package com.fizz.business.scheduled;
import com.fizz.business.service.DeviceSnapshotService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
/**
* 设备数据快照定时任务
* 每10分钟执行一次设备数据快照
*/
@Slf4j
@Component
@RequiredArgsConstructor
public class DeviceSnapshotSchedule {
private final DeviceSnapshotService deviceSnapshotService;
/**
* 每10分钟执行一次设备数据快照
* 使用cron表达式0 0/10 * * * ?
* 表示每10分钟执行一次在每分钟的0秒触发
*/
@Scheduled(cron = "0 0/10 * * * ?")
public void captureDeviceSnapshots() {
try {
log.info("开始执行设备数据快照任务...");
long startTime = System.currentTimeMillis();
// 创建设备数据快照
deviceSnapshotService.createDeviceSnapshots();
long endTime = System.currentTimeMillis();
log.info("设备数据快照任务执行完成,耗时:{}ms", (endTime - startTime));
} catch (Exception e) {
log.error("执行设备数据快照任务失败: {}", e.getMessage(), e);
}
}
}

View File

@@ -28,5 +28,11 @@ public interface CrmPdiPlanService extends IService<CrmPdiPlan> {
*/
CrmPdiPlan getFirstUnProducedCoil();
void changeStatus(ChangePlanStatusForm build);
boolean changeStatus(ChangePlanStatusForm build);
/**
* 获取当前正在线上的钢卷优先级ONLINE > PRODUCING > READY/NEW
* @return 当前正在线上的钢卷如果没有则返回null
*/
CrmPdiPlan getCurrentOnlineCoil();
}

View File

@@ -0,0 +1,27 @@
package com.fizz.business.service;
import java.util.Map;
/**
* 首页仪表板统计服务
*/
public interface DashboardService {
/**
* 当前生产中的计划信息(包含卷号、规格、时间等)
*/
Map<String, Object> getCurrentProducingPlan();
/**
* 当前生产卷的关键工艺参数
* 结构说明(示例):
* {
* "coilId": "...",
* "entrySection": { "POR1": { ... }, "POR2": { ... }, ... },
* "processSection":{ "CLEAN": { ... }, "FUR1": { ... }, ... },
* "exitSection": { "TR": { ... }, "CXL1": { ... }, ... }
* }
*/
Map<String, Object> getCurrentProcessParams();
}

View File

@@ -0,0 +1,793 @@
package com.fizz.business.service;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.fizz.business.constants.enums.DeviceEnum;
import com.fizz.business.constants.enums.WsTypeEnum;
import com.fizz.business.domain.DeviceSnapshot;
import com.fizz.business.domain.msg.*;
import com.fizz.business.dto.DeviceChartDataDTO;
import com.fizz.business.dto.DeviceFieldTrendDTO;
import com.fizz.business.dto.DeviceHistoryTrendDTO;
import com.fizz.business.mapper.DeviceSnapshotMapper;
import com.fizz.business.utils.WebSocketUtil;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;
/**
* 设备数据快照服务
*/
@Slf4j
@Service
@RequiredArgsConstructor
public class DeviceSnapshotService {
// 使用ConcurrentHashMap存储最新的测量数据
private final Map<Class<?>, OpcMessage> latestMeasurements = new ConcurrentHashMap<>();
private final DeviceSnapshotMapper deviceSnapshotMapper;
private final ObjectMapper objectMapper;
/**
* 更新最新的测量数据
* @param message 测量数据消息
*/
public void updateLatestMeasurement(OpcMessage message) {
if (message != null) {
latestMeasurements.put(message.getClass(), message);
}
}
/**
* 创建当前所有设备的数据快照
*/
@Transactional(rollbackFor = Exception.class)
public void createDeviceSnapshots() {
try {
// 获取当前时间戳
LocalDateTime now = LocalDateTime.now();
// 获取最新的测量数据
AppMeasureEntryMessage entry = (AppMeasureEntryMessage) latestMeasurements.get(AppMeasureEntryMessage.class);
AppMeasureFurnaceMessage furnace = (AppMeasureFurnaceMessage) latestMeasurements.get(AppMeasureFurnaceMessage.class);
AppMeasureCoatMessage coat = (AppMeasureCoatMessage) latestMeasurements.get(AppMeasureCoatMessage.class);
AppMeasureExitMessage exit = (AppMeasureExitMessage) latestMeasurements.get(AppMeasureExitMessage.class);
if (entry == null && furnace == null && coat == null && exit == null) {
log.warn("没有可用的测量数据,跳过快照创建");
return;
}
// 为每个设备创建快照
List<DeviceSnapshot> snapshots = new ArrayList<>();
for (DeviceEnum device : DeviceEnum.values()) {
try {
DeviceSnapshot snapshot = createDeviceSnapshot(device, now, entry, furnace, coat, exit);
if (snapshot != null) {
snapshots.add(snapshot);
}
} catch (Exception e) {
log.error("创建设备[{}]快照失败: {}", device.name(), e.getMessage(), e);
}
}
// 批量保存快照
if (!snapshots.isEmpty()) {
for (DeviceSnapshot snapshot : snapshots) {
deviceSnapshotMapper.insert(snapshot);
}
log.info("成功创建{}个设备数据快照", snapshots.size());
// 推送所有设备的历史趋势数据
pushAllDevicesHistoryTrend();
// 推送设备统计数据
pushAllChartData();
// 推送每个设备每个字段的趋势数据(供前端画“点位趋势小图”)
pushAllDeviceFieldTrends();
}
} catch (Exception e) {
log.error("创建设备数据快照失败: {}", e.getMessage(), e);
throw e;
}
}
/**
* 推送所有设备的历史趋势数据今天一天的数据10分钟间隔
*/
public void pushAllDevicesHistoryTrend() {
try {
for (DeviceEnum device : DeviceEnum.values()) {
DeviceHistoryTrendDTO trendData = getDeviceHistoryTrend(device.name());
if (trendData != null && trendData.getSeries() != null && !trendData.getSeries().isEmpty()) {
WebSocketUtil.sendHistoryTrendMessage(trendData);
}
}
} catch (Exception e) {
log.error("推送设备历史趋势数据失败: {}", e.getMessage(), e);
}
}
/**
* 推送设备统计数据
*/
public void pushAllChartData() {
try {
DeviceChartDataDTO chartData = buildAllChartData();
if (chartData != null) {
WebSocketUtil.sendChartDataMessage(chartData);
}
} catch (Exception e) {
log.error("推送统计数据失败: {}", e.getMessage(), e);
}
}
/**
* 推送每个设备每个字段的趋势数据今天范围10分钟间隔采样
*/
public void pushAllDeviceFieldTrends() {
try {
for (DeviceEnum device : DeviceEnum.values()) {
List<String> fields = device.getParamFields();
if (fields == null || fields.isEmpty()) continue;
for (String field : fields) {
DeviceFieldTrendDTO dto = getDeviceFieldTrend(device.name(), field);
if (dto != null) {
WebSocketUtil.sendDeviceFieldTrendMessage(dto);
}
}
}
} catch (Exception e) {
log.error("推送设备字段趋势失败: {}", e.getMessage(), e);
}
}
/**
* 获取 单设备-单字段 今日趋势与统计10分钟采样
*/
public DeviceFieldTrendDTO getDeviceFieldTrend(String deviceCode, String fieldName) {
try {
DeviceEnum device = DeviceEnum.fromName(deviceCode);
if (device == null) return null;
// 今天范围
LocalDate today = LocalDate.now();
LocalDateTime startTime = today.atStartOfDay();
LocalDateTime endTime = today.atTime(LocalTime.MAX);
// 查询今天的快照
LambdaQueryWrapper<DeviceSnapshot> qw = new LambdaQueryWrapper<DeviceSnapshot>()
.eq(DeviceSnapshot::getDeviceCode, deviceCode)
.between(DeviceSnapshot::getCreateTime, startTime, endTime)
.orderByAsc(DeviceSnapshot::getCreateTime);
List<DeviceSnapshot> rows = deviceSnapshotMapper.selectList(qw);
if (rows == null || rows.isEmpty()) return null;
// 10分钟采样
List<DeviceSnapshot> sampled = sampleDataByInterval(rows, 10);
DateTimeFormatter timeFormatter = DateTimeFormatter.ofPattern("HH:mm");
List<String> categories = new ArrayList<>(sampled.size());
List<Double> data = new ArrayList<>(sampled.size());
for (DeviceSnapshot s : sampled) {
categories.add(s.getCreateTime().format(timeFormatter));
double v = 0.0;
try {
Map<String, Object> json = objectMapper.readValue(s.getSnapshotData(), Map.class);
Object raw = json.get(fieldName);
if (raw instanceof Number) v = ((Number) raw).doubleValue();
} catch (Exception ignore) {
}
data.add(v);
}
// 统计忽略全0
List<Double> valid = new ArrayList<>();
for (Double v : data) {
if (v != null && v != 0.0) valid.add(v);
}
Double avg = null, max = null, min = null;
if (!valid.isEmpty()) {
double sum = 0;
max = valid.get(0);
min = valid.get(0);
for (Double v : valid) {
sum += v;
if (v > max) max = v;
if (v < min) min = v;
}
avg = sum / valid.size();
}
Double last = data.isEmpty() ? null : data.get(data.size() - 1);
return DeviceFieldTrendDTO.builder()
.deviceCode(deviceCode)
.deviceName(device.getDesc())
.fieldName(fieldName)
// label/unit 目前后端没有统一来源,这里先留空,前端可用 fieldMeta 补齐
.fieldLabel(null)
.unit(null)
.categories(categories)
.data(data)
.avg(avg)
.max(max)
.min(min)
.last(last)
.build();
} catch (Exception e) {
log.error("获取设备字段趋势失败, deviceCode={}, fieldName={}, err={}", deviceCode, fieldName, e.getMessage(), e);
return null;
}
}
/**
* 构建设备图表数据
*/
private DeviceChartDataDTO buildAllChartData() {
try {
// 1. 设备类型分布饼图
DeviceChartDataDTO.PieChartData pieChartData = buildDeviceTypePieChart();
// 2. 数据来源分布条形图
DeviceChartDataDTO.BarChartData barChartData = buildSourceTypeBarChart();
// 3. 同类型设备对比折线图(只对比单位相同的设备)
DeviceChartDataDTO.LineChartData lineChartData = buildSameTypeDeviceCompareChart();
// 4. 设备统计数据
List<DeviceChartDataDTO.DeviceStatistics> statistics = buildDeviceStatistics();
return DeviceChartDataDTO.builder()
.deviceTypePieChart(pieChartData)
.sourceTypeBarChart(barChartData)
.sameTypeDeviceCompareChart(lineChartData)
.deviceStatistics(statistics)
.build();
} catch (Exception e) {
log.error("构建图表数据失败: {}", e.getMessage(), e);
return null;
}
}
/**
* 构建设备类型分布饼图数据
*/
private DeviceChartDataDTO.PieChartData buildDeviceTypePieChart() {
Map<String, Integer> distribution = new HashMap<>();
distribution.put("入口段", 0);
distribution.put("处理段", 0);
distribution.put("出口段", 0);
distribution.put("其他", 0);
for (DeviceEnum device : DeviceEnum.values()) {
String sectionType = device.getSectionType().name();
if ("ENTRY".equals(sectionType)) {
distribution.put("入口段", distribution.get("入口段") + 1);
} else if ("PROCESS".equals(sectionType)) {
distribution.put("处理段", distribution.get("处理段") + 1);
} else if ("EXIT".equals(sectionType)) {
distribution.put("出口段", distribution.get("出口段") + 1);
} else {
distribution.put("其他", distribution.get("其他") + 1);
}
}
String[] colors = {"#0066cc", "#409eff", "#66b1ff", "#a0cfff"};
List<DeviceChartDataDTO.PieSeries> series = new ArrayList<>();
int colorIndex = 0;
for (Map.Entry<String, Integer> entry : distribution.entrySet()) {
if (entry.getValue() > 0) {
series.add(DeviceChartDataDTO.PieSeries.builder()
.name(entry.getKey())
.data(entry.getValue().doubleValue())
.color(colors[colorIndex % colors.length])
.build());
colorIndex++;
}
}
return DeviceChartDataDTO.PieChartData.builder()
.series(series)
.build();
}
/**
* 构建数据来源分布条形图数据
*/
private DeviceChartDataDTO.BarChartData buildSourceTypeBarChart() {
Map<String, Integer> distribution = new HashMap<>();
distribution.put("ENTRY", 0);
distribution.put("FURNACE", 0);
distribution.put("COAT", 0);
distribution.put("EXIT", 0);
for (DeviceEnum device : DeviceEnum.values()) {
String sourceType = device.getSourceType().name();
if (distribution.containsKey(sourceType)) {
distribution.put(sourceType, distribution.get(sourceType) + 1);
}
}
List<String> categories = new ArrayList<>();
List<Double> data = new ArrayList<>();
for (Map.Entry<String, Integer> entry : distribution.entrySet()) {
if (entry.getValue() > 0) {
categories.add(entry.getKey());
data.add(entry.getValue().doubleValue());
}
}
return DeviceChartDataDTO.BarChartData.builder()
.categories(categories)
.series(Collections.singletonList(
DeviceChartDataDTO.BarSeries.builder()
.name("设备数量")
.data(data)
.build()
))
.build();
}
/**
* 构建同类型设备对比折线图数据(只对比单位相同的设备)
*/
private DeviceChartDataDTO.LineChartData buildSameTypeDeviceCompareChart() {
// 获取今天的数据
LocalDate today = LocalDate.now();
LocalDateTime startTime = today.atStartOfDay();
LocalDateTime endTime = today.atTime(LocalTime.MAX);
// 按数据来源分组,同一来源的设备单位相同,可以对比
Map<String, List<DeviceEnum>> devicesBySource = new HashMap<>();
for (DeviceEnum device : DeviceEnum.values()) {
if (device.getParamFields() == null || device.getParamFields().isEmpty()) {
continue;
}
String sourceType = device.getSourceType().name();
devicesBySource.computeIfAbsent(sourceType, k -> new ArrayList<>()).add(device);
}
// 选择设备数量最多的数据源取前5个设备进行对比
String selectedSource = devicesBySource.entrySet().stream()
.max(Map.Entry.comparingByValue((a, b) -> Integer.compare(a.size(), b.size())))
.map(Map.Entry::getKey)
.orElse(null);
if (selectedSource == null || devicesBySource.get(selectedSource).isEmpty()) {
return null;
}
List<DeviceEnum> selectedDevices = devicesBySource.get(selectedSource).stream()
.limit(5)
.collect(Collectors.toList());
List<String> categories = new ArrayList<>();
List<DeviceChartDataDTO.LineSeries> series = new ArrayList<>();
// 生成时间轴最近10个时间点每10分钟一个
DateTimeFormatter timeFormatter = DateTimeFormatter.ofPattern("HH:mm");
LocalDateTime now = LocalDateTime.now();
for (int i = 9; i >= 0; i--) {
LocalDateTime time = now.minusMinutes(i * 10L);
categories.add(time.format(timeFormatter));
}
// 为每个设备生成数据系列
for (DeviceEnum device : selectedDevices) {
if (device.getParamFields() == null || device.getParamFields().isEmpty()) {
continue;
}
// 获取该设备今天的历史数据
LambdaQueryWrapper<DeviceSnapshot> qw = new LambdaQueryWrapper<DeviceSnapshot>()
.eq(DeviceSnapshot::getDeviceCode, device.name())
.between(DeviceSnapshot::getCreateTime, startTime, endTime)
.orderByAsc(DeviceSnapshot::getCreateTime);
List<DeviceSnapshot> rows = deviceSnapshotMapper.selectList(qw);
List<DeviceSnapshot> sampledRows = sampleDataByInterval(rows, 10);
// 使用第一个字段的数据
String firstField = device.getParamFields().get(0);
List<Double> data = new ArrayList<>();
// 填充数据如果历史数据不足用0填充
for (int i = 0; i < 10; i++) {
if (i < sampledRows.size()) {
try {
Map<String, Object> jsonData = objectMapper.readValue(
sampledRows.get(i).getSnapshotData(), Map.class);
Object value = jsonData.get(firstField);
double numValue = 0.0;
if (value instanceof Number) {
numValue = ((Number) value).doubleValue();
}
data.add(numValue);
} catch (Exception e) {
data.add(0.0);
}
} else {
data.add(0.0);
}
}
series.add(DeviceChartDataDTO.LineSeries.builder()
.name(device.getDesc())
.data(data)
.build());
}
if (series.isEmpty()) {
return null;
}
return DeviceChartDataDTO.LineChartData.builder()
.categories(categories)
.series(series)
.build();
}
/**
* 构建设备统计数据
*/
private List<DeviceChartDataDTO.DeviceStatistics> buildDeviceStatistics() {
List<DeviceChartDataDTO.DeviceStatistics> statistics = new ArrayList<>();
LocalDate today = LocalDate.now();
LocalDateTime startTime = today.atStartOfDay();
LocalDateTime endTime = today.atTime(LocalTime.MAX);
// 获取最新的测量数据
AppMeasureEntryMessage entry = (AppMeasureEntryMessage) latestMeasurements.get(AppMeasureEntryMessage.class);
AppMeasureFurnaceMessage furnace = (AppMeasureFurnaceMessage) latestMeasurements.get(AppMeasureFurnaceMessage.class);
AppMeasureCoatMessage coat = (AppMeasureCoatMessage) latestMeasurements.get(AppMeasureCoatMessage.class);
AppMeasureExitMessage exit = (AppMeasureExitMessage) latestMeasurements.get(AppMeasureExitMessage.class);
for (DeviceEnum device : DeviceEnum.values()) {
if (device.getParamFields() == null || device.getParamFields().isEmpty()) {
continue;
}
String firstField = device.getParamFields().get(0);
// 获取当前值
double currentValue = 0.0;
switch (device.getSourceType()) {
case ENTRY:
if (entry != null) {
currentValue = getFieldValue(entry, firstField);
}
break;
case FURNACE:
if (furnace != null) {
currentValue = getFieldValue(furnace, firstField);
}
break;
case COAT:
if (coat != null) {
currentValue = getFieldValue(coat, firstField);
}
break;
case EXIT:
if (exit != null) {
currentValue = getFieldValue(exit, firstField);
}
break;
}
// 从历史数据中计算统计值
LambdaQueryWrapper<DeviceSnapshot> qw = new LambdaQueryWrapper<DeviceSnapshot>()
.eq(DeviceSnapshot::getDeviceCode, device.name())
.between(DeviceSnapshot::getCreateTime, startTime, endTime)
.orderByAsc(DeviceSnapshot::getCreateTime);
List<DeviceSnapshot> rows = deviceSnapshotMapper.selectList(qw);
List<Double> values = new ArrayList<>();
for (DeviceSnapshot snapshot : rows) {
try {
Map<String, Object> jsonData = objectMapper.readValue(
snapshot.getSnapshotData(), Map.class);
Object value = jsonData.get(firstField);
if (value instanceof Number) {
double numValue = ((Number) value).doubleValue();
if (numValue > 0) {
values.add(numValue);
}
}
} catch (Exception e) {
// ignore
}
}
String avg = "";
String max = "";
String min = "";
if (!values.isEmpty()) {
double avgValue = values.stream().mapToDouble(Double::doubleValue).average().orElse(0.0);
double maxValue = values.stream().mapToDouble(Double::doubleValue).max().orElse(0.0);
double minValue = values.stream().mapToDouble(Double::doubleValue).min().orElse(0.0);
avg = String.format("%.2f", avgValue);
max = String.format("%.2f", maxValue);
min = String.format("%.2f", minValue);
}
statistics.add(DeviceChartDataDTO.DeviceStatistics.builder()
.deviceCode(device.name())
.deviceName(device.getDesc())
.avg(avg)
.max(max)
.min(min)
.current(currentValue > 0 ? String.format("%.2f", currentValue) : "")
.build());
}
return statistics;
}
/**
* 获取字段值
*/
private double getFieldValue(Object message, String fieldName) {
try {
java.lang.reflect.Field field = message.getClass().getDeclaredField(fieldName);
field.setAccessible(true);
Object value = field.get(message);
if (value instanceof Number) {
return ((Number) value).doubleValue();
}
} catch (Exception e) {
// ignore
}
return 0.0;
}
/**
* 获取设备今天一天的历史趋势数据10分钟间隔采样
* @param deviceCode 设备代码
* @return 历史趋势数据
*/
public DeviceHistoryTrendDTO getDeviceHistoryTrend(String deviceCode) {
try {
// 获取今天开始和结束时间
LocalDate today = LocalDate.now();
LocalDateTime startTime = today.atStartOfDay();
LocalDateTime endTime = today.atTime(LocalTime.MAX);
// 查询今天的所有快照数据
LambdaQueryWrapper<DeviceSnapshot> qw = new LambdaQueryWrapper<DeviceSnapshot>()
.eq(DeviceSnapshot::getDeviceCode, deviceCode)
.between(DeviceSnapshot::getCreateTime, startTime, endTime)
.orderByAsc(DeviceSnapshot::getCreateTime);
List<DeviceSnapshot> rows = deviceSnapshotMapper.selectList(qw);
if (rows == null || rows.isEmpty()) {
return null;
}
// 按10分钟间隔采样数据
List<DeviceSnapshot> sampledRows = sampleDataByInterval(rows, 10);
// 获取设备信息
DeviceEnum device = DeviceEnum.valueOf(deviceCode);
if (device == null) {
return null;
}
// 构建历史趋势数据
List<String> categories = new ArrayList<>();
Map<String, List<Double>> seriesMap = new HashMap<>();
List<String> fields = device.getParamFields();
if (fields == null || fields.isEmpty()) {
return null;
}
// 初始化系列数据
for (String field : fields) {
seriesMap.put(field, new ArrayList<>());
}
// 处理采样后的数据
DateTimeFormatter timeFormatter = DateTimeFormatter.ofPattern("HH:mm");
for (DeviceSnapshot snapshot : sampledRows) {
categories.add(snapshot.getCreateTime().format(timeFormatter));
Map<String, Object> jsonData = new HashMap<>();
try {
jsonData = objectMapper.readValue(snapshot.getSnapshotData(), Map.class);
} catch (Exception e) {
log.warn("解析快照数据失败: {}", snapshot.getSnapshotData());
}
for (String field : fields) {
Object value = jsonData.get(field);
double numValue = 0.0;
if (value instanceof Number) {
numValue = ((Number) value).doubleValue();
}
seriesMap.get(field).add(numValue);
}
}
// 构建系列数据最多6个字段
List<DeviceHistoryTrendDTO.SeriesData> series = fields.stream()
.limit(6)
.map(field -> DeviceHistoryTrendDTO.SeriesData.builder()
.fieldName(field)
.name(field) // 前端可以根据字段元数据替换为标签
.data(seriesMap.get(field))
.build())
.collect(Collectors.toList());
return DeviceHistoryTrendDTO.builder()
.deviceCode(deviceCode)
.deviceName(device.getDesc())
.categories(categories)
.series(series)
.build();
} catch (Exception e) {
log.error("获取设备[{}]历史趋势数据失败: {}", deviceCode, e.getMessage(), e);
return null;
}
}
/**
* 按时间间隔采样数据每N分钟取一条
* @param rows 原始数据列表
* @param intervalMinutes 间隔分钟数
* @return 采样后的数据列表
*/
private List<DeviceSnapshot> sampleDataByInterval(List<DeviceSnapshot> rows, int intervalMinutes) {
if (rows == null || rows.isEmpty()) {
return new ArrayList<>();
}
List<DeviceSnapshot> sampled = new ArrayList<>();
LocalDateTime lastTime = null;
for (DeviceSnapshot row : rows) {
LocalDateTime rowTime = row.getCreateTime();
if (lastTime == null) {
// 第一条数据
sampled.add(row);
lastTime = rowTime;
} else {
// 计算时间差(分钟)
long diffMinutes = java.time.Duration.between(lastTime, rowTime).toMinutes();
// 如果时间差大于等于间隔,则采样这条数据
if (diffMinutes >= intervalMinutes) {
sampled.add(row);
lastTime = rowTime;
}
}
}
return sampled;
}
/**
* 创建设备快照
*/
private DeviceSnapshot createDeviceSnapshot(DeviceEnum device, LocalDateTime timestamp,
AppMeasureEntryMessage entry,
AppMeasureFurnaceMessage furnace,
AppMeasureCoatMessage coat,
AppMeasureExitMessage exit) {
try {
// 创建快照对象
DeviceSnapshot snapshot = new DeviceSnapshot();
snapshot.setCreateTime(timestamp);
snapshot.setDeviceId(device.getIdx());
snapshot.setDeviceCode(device.name());
snapshot.setDeviceName(device.getDesc());
snapshot.setSectionType(device.getSectionType().name());
snapshot.setSourceType(device.getSourceType().name());
snapshot.setBasePosition(device.getBasePosition());
// 根据设备类型获取对应的测量数据
ObjectNode dataNode = objectMapper.createObjectNode();
switch (device.getSourceType()) {
case ENTRY:
if (entry != null) {
extractData(entry, device.getParamFields(), dataNode);
}
break;
case FURNACE:
if (furnace != null) {
extractData(furnace, device.getParamFields(), dataNode);
}
break;
case COAT:
if (coat != null) {
extractData(coat, device.getParamFields(), dataNode);
}
break;
case EXIT:
if (exit != null) {
extractData(exit, device.getParamFields(), dataNode);
}
break;
}
// 如果没有数据,则跳过
if (dataNode.isEmpty()) {
return null;
}
// 设置快照数据
snapshot.setSnapshotData(dataNode.toString());
return snapshot;
} catch (Exception e) {
log.error("创建设备[{}]快照时发生错误: {}", device.name(), e.getMessage(), e);
return null;
}
}
/**
* 从消息对象中提取指定字段的数据
*/
private void extractData(Object message, List<String> fields, ObjectNode dataNode) {
if (message == null || fields == null || fields.isEmpty()) {
return;
}
try {
for (String field : fields) {
try {
// 使用反射获取字段值
java.lang.reflect.Field declaredField = message.getClass().getDeclaredField(field);
declaredField.setAccessible(true);
Object value = declaredField.get(message);
// 处理不同类型的值
if (value != null) {
if (value instanceof Integer) {
dataNode.put(field, (Integer) value);
} else if (value instanceof Long) {
dataNode.put(field, (Long) value);
} else if (value instanceof Float) {
dataNode.put(field, (Float) value);
} else if (value instanceof Double) {
dataNode.put(field, (Double) value);
} else if (value instanceof Boolean) {
dataNode.put(field, (Boolean) value);
} else if (value instanceof String) {
dataNode.put(field, (String) value);
} else if (value instanceof Enum) {
dataNode.put(field, value.toString());
}
}
} catch (NoSuchFieldException e) {
log.trace("字段[{}]在消息[{}]中不存在", field, message.getClass().getSimpleName());
} catch (Exception e) {
log.warn("获取字段[{}]值失败: {}", field, e.getMessage());
}
}
} catch (Exception e) {
log.error("提取数据时发生错误: {}", e.getMessage(), e);
}
}
}

View File

@@ -0,0 +1,23 @@
package com.fizz.business.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.fizz.business.domain.BizSendTemplateItem;
import java.util.List;
/**
* 发送模板明细 Service
*/
public interface IBizSendTemplateItemService extends IService<BizSendTemplateItem> {
/**
* 批量更新模板明细仅更新已有ID
*/
Boolean updateItemsBatch(List<BizSendTemplateItem> items);
/**
* 批量保存模板明细(新增/更新/删除)
*/
Boolean batchSave(Integer templateId, List<BizSendTemplateItem> items, List<Integer> deleteIds, String username);
}

Some files were not shown because too many files have changed in this diff Show More