From d752188d01f82a6c56a23c1f5c66b639b5d538f2 Mon Sep 17 00:00:00 2001 From: Joshi <3040996759@qq.com> Date: Sun, 4 Jan 2026 15:09:55 +0800 Subject: [PATCH] =?UTF-8?q?feat(send-job):=20=E6=96=B0=E5=A2=9E=E7=82=89?= =?UTF-8?q?=E7=81=AB=E5=86=99=E5=85=A5=E9=92=A2=E5=8D=B7=E4=BF=A1=E6=81=AF?= =?UTF-8?q?=E5=8A=9F=E8=83=BD=E5=B9=B6=E4=BC=98=E5=8C=96=E5=8F=91=E9=80=81?= =?UTF-8?q?=E4=BD=9C=E4=B8=9A=E6=9C=8D=E5=8A=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增 FurnaceSendCoilInfoVO 类用于存储炉火写入的钢卷信息 - 在 SendJobController 中添加获取上次炉火写入钢卷信息的接口 - 在 SendJobServiceImpl 中实现炉火写入成功后自动存储钢卷信息到 Redis - 新增 getCurrentOnlineCoil 方法用于获取当前正在线上的钢卷 - 优化 CrmPdiPlanService 接口定义和实现类代码格式 - 修复 SendJobQueryServiceImpl 中的错误提示信息国际化 - 优化 SendJobServiceImpl 中的代码结构和依赖注入 - 添加完整的 Java 代码注释和文档说明 --- .../controller/BizSendTemplateController.java | 6 +- .../controller/SendJobController.java | 23 ++++ .../domain/vo/FurnaceSendCoilInfoVO.java | 22 ++++ .../business/service/CrmPdiPlanService.java | 16 ++- .../impl/BizSendTemplateItemServiceImpl.java | 6 +- .../service/impl/CrmPdiPlanServiceImpl.java | 43 +++++- .../service/impl/SendJobQueryServiceImpl.java | 2 +- .../service/impl/SendJobServiceImpl.java | 123 ++++++++++++------ 8 files changed, 186 insertions(+), 55 deletions(-) create mode 100644 business/src/main/java/com/fizz/business/domain/vo/FurnaceSendCoilInfoVO.java diff --git a/business/src/main/java/com/fizz/business/controller/BizSendTemplateController.java b/business/src/main/java/com/fizz/business/controller/BizSendTemplateController.java index 43035da..9dd150b 100644 --- a/business/src/main/java/com/fizz/business/controller/BizSendTemplateController.java +++ b/business/src/main/java/com/fizz/business/controller/BizSendTemplateController.java @@ -35,7 +35,7 @@ public class BizSendTemplateController extends BaseController { public AjaxResult getByCode(@PathVariable String templateCode) { BizSendTemplateVO vo = templateService.getTemplateWithItems(templateCode); if (vo == null) { - return AjaxResult.error("Template not found"); + return AjaxResult.error("模板未找到"); } return AjaxResult.success(vo); } @@ -46,7 +46,7 @@ public class BizSendTemplateController extends BaseController { @PutMapping public AjaxResult updateTemplate(@RequestBody BizSendTemplate template) { if (template == null || template.getTemplateId() == null) { - return AjaxResult.error("templateId is required"); + return AjaxResult.error("模板ID是必需的"); } template.setUpdateBy(SecurityUtils.getUsername()); template.setUpdateTime(new Date()); @@ -76,7 +76,7 @@ public class BizSendTemplateController extends BaseController { @PutMapping("/items/batchSave") public AjaxResult batchSaveItems(@RequestBody SendTemplateItemsBatchSaveDTO dto) { if (dto == null || dto.getTemplateId() == null) { - return AjaxResult.error("templateId is required"); + return AjaxResult.error("模板ID是必需的"); } try { Boolean ok = templateItemService.batchSave( diff --git a/business/src/main/java/com/fizz/business/controller/SendJobController.java b/business/src/main/java/com/fizz/business/controller/SendJobController.java index 65b9260..bdb387f 100644 --- a/business/src/main/java/com/fizz/business/controller/SendJobController.java +++ b/business/src/main/java/com/fizz/business/controller/SendJobController.java @@ -9,8 +9,11 @@ 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; @@ -87,4 +90,24 @@ public class SendJobController extends BaseController { 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("获取上次炉火写入钢卷信息失败: " + e.getMessage()); + } + } } diff --git a/business/src/main/java/com/fizz/business/domain/vo/FurnaceSendCoilInfoVO.java b/business/src/main/java/com/fizz/business/domain/vo/FurnaceSendCoilInfoVO.java new file mode 100644 index 0000000..ce6b92b --- /dev/null +++ b/business/src/main/java/com/fizz/business/domain/vo/FurnaceSendCoilInfoVO.java @@ -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; +} + diff --git a/business/src/main/java/com/fizz/business/service/CrmPdiPlanService.java b/business/src/main/java/com/fizz/business/service/CrmPdiPlanService.java index a929d9f..d9f9757 100644 --- a/business/src/main/java/com/fizz/business/service/CrmPdiPlanService.java +++ b/business/src/main/java/com/fizz/business/service/CrmPdiPlanService.java @@ -13,15 +13,15 @@ import java.util.List; public interface CrmPdiPlanService extends IService { - CrmPdiPlanVO getByCoilIdAndOperId(String coilid); + CrmPdiPlanVO getByCoilIdAndOperId(String coilid); - boolean addCrmPdiPlan(CrmPdiPlan crmPdiPlan); + boolean addCrmPdiPlan(CrmPdiPlan crmPdiPlan); - boolean updateCrmPdiPlan(CrmPdiPlan crmPdiPlan); + boolean updateCrmPdiPlan(CrmPdiPlan crmPdiPlan); - boolean deleteCrmPdiPlan(List coilid); + boolean deleteCrmPdiPlan(List coilid); - List listAll(PlanQueryForm form); + List listAll(PlanQueryForm form); /** * 获取未生产的第一个钢卷(按顺序号或创建时间最早) @@ -29,4 +29,10 @@ public interface CrmPdiPlanService extends IService { CrmPdiPlan getFirstUnProducedCoil(); void changeStatus(ChangePlanStatusForm build); + + /** + * 获取当前正在线上的钢卷(优先级:ONLINE > PRODUCING > READY/NEW) + * @return 当前正在线上的钢卷,如果没有则返回null + */ + CrmPdiPlan getCurrentOnlineCoil(); } diff --git a/business/src/main/java/com/fizz/business/service/impl/BizSendTemplateItemServiceImpl.java b/business/src/main/java/com/fizz/business/service/impl/BizSendTemplateItemServiceImpl.java index 864bb2f..7efbd64 100644 --- a/business/src/main/java/com/fizz/business/service/impl/BizSendTemplateItemServiceImpl.java +++ b/business/src/main/java/com/fizz/business/service/impl/BizSendTemplateItemServiceImpl.java @@ -53,11 +53,11 @@ public class BizSendTemplateItemServiceImpl extends ServiceImpl seen = new HashSet<>(); for (BizSendTemplateItem it : items) { if (it.getParamCode() == null || it.getParamCode().trim().isEmpty()) { - throw new IllegalArgumentException("paramCode is required"); + throw new IllegalArgumentException("参数编码是必需的"); } String code = it.getParamCode().trim(); if (!seen.add(code)) { - throw new IllegalArgumentException("Duplicate paramCode in request: " + code); + throw new IllegalArgumentException("请求中包含重复参数编码: " + code); } it.setParamCode(code); } @@ -72,7 +72,7 @@ public class BizSendTemplateItemServiceImpl extends ServiceImpl 0) { - throw new IllegalArgumentException("paramCode already exists: " + it.getParamCode()); + throw new IllegalArgumentException("参数编码已存在: " + it.getParamCode()); } } diff --git a/business/src/main/java/com/fizz/business/service/impl/CrmPdiPlanServiceImpl.java b/business/src/main/java/com/fizz/business/service/impl/CrmPdiPlanServiceImpl.java index 31ecf10..f48fa66 100644 --- a/business/src/main/java/com/fizz/business/service/impl/CrmPdiPlanServiceImpl.java +++ b/business/src/main/java/com/fizz/business/service/impl/CrmPdiPlanServiceImpl.java @@ -60,7 +60,7 @@ public class CrmPdiPlanServiceImpl extends ServiceImpl PRODUCING > READY/NEW) + * @return 当前正在线上的钢卷,如果没有则返回null + */ + @Override + public CrmPdiPlan getCurrentOnlineCoil() { + + + // 1. 优先查找 PRODUCING 状态的钢卷 + CrmPdiPlan producingPlan = this.lambdaQuery() + .eq(CrmPdiPlan::getStatus, "PRODUCING") + .orderByAsc(CrmPdiPlan::getSeqid) + .last("limit 1") + .one(); + + if (producingPlan != null) { + return producingPlan; + } + + // 2. 其次查找 ONLINE 状态的钢卷 + CrmPdiPlan onlinePlan = this.lambdaQuery() + .eq(CrmPdiPlan::getStatus, "ONLINE") + .orderByAsc(CrmPdiPlan::getSeqid) + .last("limit 1") + .one(); + + if (onlinePlan != null) { + return onlinePlan; + } + + + // 3. 最后查找 READY 或 NEW 状态的钢卷(按顺序号排序,取第一个) + CrmPdiPlan readyOrNewPlan = this.lambdaQuery() + .in(CrmPdiPlan::getStatus, "READY", "NEW") + .orderByAsc(CrmPdiPlan::getSeqid) + .last("limit 1") + .one(); + + return readyOrNewPlan; + } + } diff --git a/business/src/main/java/com/fizz/business/service/impl/SendJobQueryServiceImpl.java b/business/src/main/java/com/fizz/business/service/impl/SendJobQueryServiceImpl.java index 976c6ed..5763913 100644 --- a/business/src/main/java/com/fizz/business/service/impl/SendJobQueryServiceImpl.java +++ b/business/src/main/java/com/fizz/business/service/impl/SendJobQueryServiceImpl.java @@ -160,7 +160,7 @@ public class SendJobQueryServiceImpl implements ISendJobQueryService { } if (currentPlan == null) { - return createEmptyResponse("No active or ready plan found."); + return createEmptyResponse("未找到活跃或就绪的计划"); } // 将 CrmPdiPlan 对象的字段反射为 Map diff --git a/business/src/main/java/com/fizz/business/service/impl/SendJobServiceImpl.java b/business/src/main/java/com/fizz/business/service/impl/SendJobServiceImpl.java index ca267e8..da782e5 100644 --- a/business/src/main/java/com/fizz/business/service/impl/SendJobServiceImpl.java +++ b/business/src/main/java/com/fizz/business/service/impl/SendJobServiceImpl.java @@ -13,8 +13,13 @@ import com.fizz.business.domain.vo.SendJobItemVO; import com.fizz.business.mapper.BizSendJobGroupMapper; import com.fizz.business.mapper.BizSendJobItemMapper; import com.fizz.business.mapper.BizSendJobMapper; +import com.fizz.business.domain.CrmPdiPlan; +import com.fizz.business.domain.vo.FurnaceSendCoilInfoVO; +import com.fizz.business.service.CrmPdiPlanService; import com.fizz.business.service.ISendJobService; import com.fizz.business.service.manager.OpcMessageIdsManager; +import com.fizz.business.utils.RedisUtil; +import com.fasterxml.jackson.databind.ObjectMapper; import com.ruoyi.common.utils.SecurityUtils; import com.ruoyi.common.utils.StringUtils; import lombok.extern.slf4j.Slf4j; @@ -38,33 +43,38 @@ public class SendJobServiceImpl extends ServiceImpl selectSendJobList(SendJobQueryDTO query) { LambdaQueryWrapper qw = new LambdaQueryWrapper<>(); qw.eq(StringUtils.isNotBlank(query.getDeviceName()), - BizSendJob::getDeviceName, query.getDeviceName()) - .eq(StringUtils.isNotBlank(query.getStatus()), - BizSendJob::getStatus, query.getStatus()) - .orderByDesc(BizSendJob::getCreateTime); + BizSendJob::getDeviceName, query.getDeviceName()) + .eq(StringUtils.isNotBlank(query.getStatus()), + BizSendJob::getStatus, query.getStatus()) + .orderByDesc(BizSendJob::getCreateTime); List jobs = baseMapper.selectList(qw); if (jobs == null || jobs.isEmpty()) { @@ -124,9 +134,9 @@ public class SendJobServiceImpl extends ServiceImpl jobIds = jobs.stream().map(BizSendJob::getJobId).collect(Collectors.toList()); List groups = jobGroupMapper.selectList( - new LambdaQueryWrapper() - .in(BizSendJobGroup::getJobId, jobIds) - .eq(BizSendJobGroup::getGroupType, gt) + new LambdaQueryWrapper() + .in(BizSendJobGroup::getJobId, jobIds) + .eq(BizSendJobGroup::getGroupType, gt) ); if (groups == null || groups.isEmpty()) { return Collections.emptyList(); @@ -146,55 +156,55 @@ public class SendJobServiceImpl extends ServiceImpl groups = jobGroupMapper.selectList( - new LambdaQueryWrapper() - .eq(BizSendJobGroup::getJobId, jobId) - .orderByAsc(BizSendJobGroup::getGroupNo) + new LambdaQueryWrapper() + .eq(BizSendJobGroup::getJobId, jobId) + .orderByAsc(BizSendJobGroup::getGroupNo) ); - + if (groups.isEmpty()) { return detailVO; } - + // 4. 查询所有明细项 List groupIds = groups.stream() - .map(BizSendJobGroup::getGroupId) - .collect(Collectors.toList()); - + .map(BizSendJobGroup::getGroupId) + .collect(Collectors.toList()); + List items = jobItemMapper.selectList( - new LambdaQueryWrapper() - .in(BizSendJobItem::getGroupId, groupIds) + new LambdaQueryWrapper() + .in(BizSendJobItem::getGroupId, groupIds) ); - + // 5. 按groupId分组 Map> groupItemsMap = items.stream() - .collect(Collectors.groupingBy(BizSendJobItem::getGroupId)); - + .collect(Collectors.groupingBy(BizSendJobItem::getGroupId)); + // 6. 构建分组VO List groupVOs = groups.stream().map(group -> { SendJobGroupVO groupVO = new SendJobGroupVO(); BeanUtils.copyProperties(group, groupVO); - + // 设置分组下的明细项 List groupItems = groupItemsMap - .getOrDefault(group.getGroupId(), Collections.emptyList()); - + .getOrDefault(group.getGroupId(), Collections.emptyList()); + List itemVOs = groupItems.stream().map(item -> { SendJobItemVO itemVO = new SendJobItemVO(); BeanUtils.copyProperties(item, itemVO); return itemVO; }).collect(Collectors.toList()); - + groupVO.setItems(itemVOs); return groupVO; }).collect(Collectors.toList()); - + detailVO.setGroups(groupVOs); return detailVO; } @@ -244,16 +254,16 @@ public class SendJobServiceImpl extends ServiceImpl items = jobItemMapper.selectList( new LambdaQueryWrapper() - .eq(BizSendJobItem::getJobId, jobId) - .eq(BizSendJobItem::getResultStatus, "PENDING") + .eq(BizSendJobItem::getJobId, jobId) + .eq(BizSendJobItem::getResultStatus, "PENDING") ); - + // 如果没有 PENDING 的项,检查是否有其他状态的项 if (items == null || items.isEmpty()) { boolean hasItems = jobItemMapper.selectCount( - new LambdaQueryWrapper().eq(BizSendJobItem::getJobId, jobId) + new LambdaQueryWrapper().eq(BizSendJobItem::getJobId, jobId) ) > 0; - + BizSendJob finish = new BizSendJob(); finish.setJobId(jobId); finish.setStatus(hasItems ? "COMPLETED" : "FAILED"); @@ -338,6 +348,35 @@ public class SendJobServiceImpl extends ServiceImpl "FURNACE".equalsIgnoreCase(g.getGroupType())); + + if (isFurnaceSend && allSuccess) { + CrmPdiPlan currentCoil = crmPdiPlanService.getCurrentOnlineCoil(); + if (currentCoil != null) { + FurnaceSendCoilInfoVO coilInfo = new FurnaceSendCoilInfoVO(); + coilInfo.setCoilId(currentCoil.getCoilid()); + coilInfo.setPlanId(currentCoil.getPlanid()); + coilInfo.setSendTime(new Date()); + + // 存储到 Redis(使用 JSON 格式) + ObjectMapper objectMapper = new ObjectMapper(); + String jsonValue = objectMapper.writeValueAsString(coilInfo); + RedisUtil.setValue(REDIS_KEY_FURNACE_SEND_COIL_INFO, jsonValue); + + log.info("炉火写入成功,已保存钢卷信息到 Redis: coilId={}, planId={}", + coilInfo.getCoilId(), coilInfo.getPlanId()); + } else { + log.warn("炉火写入成功,但未找到当前正在线上的钢卷"); + } + } + } catch (Exception e) { + log.error("保存炉火写入钢卷信息到 Redis 失败", e); + // 不影响主流程,只记录日志 + } + return true; } }