From 8782476e9cb4480be5da588888d08022b7942d0c Mon Sep 17 00:00:00 2001
From: xiaoyi <908147524@qq.com>
Date: 星期六, 07 十一月 2026 14:07:59 +0800
Subject: [PATCH] feat: 补齐需求10/15/16/17/18/21/23,改用现有模块替代 ERP 依赖

---
 yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/safety/SafetyRiskSourceService.java |   98 ++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 97 insertions(+), 1 deletions(-)

diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/safety/SafetyRiskSourceService.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/safety/SafetyRiskSourceService.java
index 66df97c..376fe47 100644
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/safety/SafetyRiskSourceService.java
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/safety/SafetyRiskSourceService.java
@@ -3,24 +3,47 @@
 import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
 import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
 import cn.iocoder.yudao.module.mes.controller.admin.safety.vo.risk.SafetyRiskSourceSaveReqVO;
+import cn.iocoder.yudao.module.mes.dal.dataobject.collect.MesCollectRealtimeDO;
 import cn.iocoder.yudao.module.mes.dal.dataobject.safety.SafetyRiskSourceDO;
+import cn.iocoder.yudao.module.mes.dal.mysql.collect.MesCollectRealtimeMapper;
 import cn.iocoder.yudao.module.mes.dal.mysql.safety.SafetyRiskSourceMapper;
+import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
 import jakarta.annotation.Resource;
+import lombok.extern.slf4j.Slf4j;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
+import java.math.BigDecimal;
 import java.time.LocalDateTime;
-import java.util.Objects;
+import java.util.*;
+import tools.jackson.core.type.TypeReference;
 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.invalidParamException;
 
+/**
+ * 瀹夊叏鐢熶骇 - 鍗遍櫓婧愮洃娴嬨��
+ *
+ * <p>鏀寔涓ょ鏁版嵁鏉ユ簮锛�
+ * <ol>
+ *   <li>浜哄伐褰曞叆 currentValue锛氫粎琛ㄧず浜哄伐鎶勫綍鐨勫綋鍓嶅�硷紱</li>
+ *   <li>缁戝畾璁惧锛坢achineryId + metricKey锛夛細鐢辨暟閲囧疄鏃惰〃鑷姩鍙栧�硷紝澶嶇敤鐜版湁璁惧閲囬泦锛屼笉寮曞叆鏂版帴鍙c��</li>
+ * </ol>
+ */
+@Slf4j
 @Service public class SafetyRiskSourceService {
     @Resource private SafetyRiskSourceMapper mapper;
+    @Resource private MesCollectRealtimeMapper realtimeMapper;
+
     public PageResult<SafetyRiskSourceDO> page(PageParam page, String name) {
         return mapper.selectPage(page, new LambdaQueryWrapperX<SafetyRiskSourceDO>().likeIfPresent(SafetyRiskSourceDO::getName,name).orderByDesc(SafetyRiskSourceDO::getId));
     }
+
     @Transactional(rollbackFor=Exception.class)
     public Long save(SafetyRiskSourceSaveReqVO req) {
         SafetyRiskSourceDO old = req.getId()==null ? null : mapper.selectById(req.getId());
         if (req.getId()!=null && old==null) throw invalidParamException("鍗遍櫓婧愪笉瀛樺湪");
+        if (req.getMachineryId()!=null && (req.getMetricKey()==null || req.getMetricKey().isBlank()))
+            throw invalidParamException("缁戝畾璁惧鍚庡繀椤诲~鍐欐暟閲囨寚鏍囬敭");
+        if (req.getMachineryId()==null && req.getMetricKey()!=null && !req.getMetricKey().isBlank())
+            throw invalidParamException("濉啓鏁伴噰鎸囨爣閿墠璇峰厛缁戝畾璁惧");
         String status;
         try { status=SafetyRiskThreshold.evaluate(req.getCurrentValue(),req.getLowerLimit(),req.getUpperLimit()); }
         catch (IllegalArgumentException e) { throw invalidParamException(e.getMessage()); }
@@ -30,5 +53,78 @@
         if (old==null) mapper.insert(row); else mapper.updateById(row);
         return row.getId();
     }
+
     public void delete(Long id) { if (mapper.selectById(id)==null) throw invalidParamException("鍗遍櫓婧愪笉瀛樺湪"); mapper.deleteById(id); }
+
+    /**
+     * 鐢ㄨ澶囬噰闆嗘暟鎹埛鏂版墍鏈夊凡缁戝畾璁惧鐨勫嵄闄╂簮銆�
+     *
+     * <p>鍙栧�奸『搴忥細data_json 涓� metricKey 瀵瑰簲瀛楁锛涙湭鍙栧埌鏃剁疆 UNKNOWN 骞朵繚鐣欎笂娆¤娴嬫椂闂翠笉鍙樸��
+     *
+     * @return 鏈鍒锋柊鍚庡浜� ALARM 鐘舵�佺殑鍗遍櫓婧�
+     */
+    @Transactional(rollbackFor=Exception.class)
+    public List<SafetyRiskSourceDO> refreshFromCollect() {
+        List<SafetyRiskSourceDO> bound = mapper.selectList(new LambdaQueryWrapperX<SafetyRiskSourceDO>()
+                .isNotNull(SafetyRiskSourceDO::getMachineryId));
+        List<SafetyRiskSourceDO> alarms = new ArrayList<>();
+        Map<Long, MesCollectRealtimeDO> cache = new HashMap<>();
+        for (SafetyRiskSourceDO source : bound) {
+            MesCollectRealtimeDO realtime = cache.computeIfAbsent(source.getMachineryId(), id ->
+                    realtimeMapper.selectOne(new LambdaQueryWrapperX<MesCollectRealtimeDO>()
+                            .eq(MesCollectRealtimeDO::getMachineryId, id)
+                            .orderByDesc(MesCollectRealtimeDO::getCollectTime).last("LIMIT 1")));
+            BigDecimal value = realtime == null ? null : extractMetric(realtime, source.getMetricKey());
+            String status;
+            try { status = SafetyRiskThreshold.evaluate(value, source.getLowerLimit(), source.getUpperLimit()); }
+            catch (IllegalArgumentException e) { log.warn("鍗遍櫓婧怺{}]闃堝�奸厤缃潪娉曪細{}", source.getName(), e.getMessage()); continue; }
+            if (value == null) {
+                // 鍙栦笉鍒伴噰闆嗗�硷細涓嶈鐩栧巻鍙茶娴嬫椂闂达紝閬垮厤浼�犳暟鎹�
+                if (!"UNKNOWN".equals(source.getRiskStatus())) {
+                    var upd = new SafetyRiskSourceDO();
+                    upd.setId(source.getId()); upd.setRiskStatus(status);
+                    mapper.updateById(upd);
+                    source.setRiskStatus(status);
+                }
+                continue;
+            }
+            var upd = new SafetyRiskSourceDO();
+            upd.setId(source.getId());
+            upd.setCurrentValue(value);
+            upd.setObservedAt(realtime.getCollectTime() == null ? LocalDateTime.now() : realtime.getCollectTime());
+            upd.setRiskStatus(status);
+            mapper.updateById(upd);
+            source.setCurrentValue(value);
+            source.setObservedAt(upd.getObservedAt());
+            source.setRiskStatus(status);
+            if ("ALARM".equals(status)) alarms.add(source);
+        }
+        return alarms;
+    }
+
+    /** 浠庡疄鏃堕噰闆嗚褰曚腑鎻愬彇鎸囨爣鍊硷紱浼樺厛 data_json锛屽叾娆″鐢ㄥ疄鏃惰〃鐨勬爣鍑嗗瓧娈点�� */
+    BigDecimal extractMetric(MesCollectRealtimeDO realtime, String metricKey) {
+        if (metricKey == null || metricKey.isBlank() || realtime == null) return null;
+        String json = realtime.getDataJson();
+        if (json != null && !json.isBlank()) {
+            try {
+                Map<String, Object> map = JsonUtils.parseObjectQuietly(json, new TypeReference<Map<String, Object>>() {});
+                Object raw = map == null ? null : map.get(metricKey);
+                if (raw != null) {
+                    if (raw instanceof Number n) return new BigDecimal(n.toString());
+                    String text = raw.toString().trim();
+                    if (!text.isEmpty()) return new BigDecimal(text);
+                }
+            } catch (Exception e) {
+                log.debug("瑙f瀽鏁伴噰 data_json 澶辫触锛宮achineryId={}锛歿}", realtime.getMachineryId(), e.getMessage());
+            }
+        }
+        // 鍏煎锛歮etricKey 鐩存帴鍙栧疄鏃惰〃瀛楁锛坥t 杩愯鏃堕暱绛夛級
+        return switch (metricKey) {
+            case "ot" -> realtime.getOt();
+            case "sts" -> realtime.getSts() == null ? null : BigDecimal.valueOf(realtime.getSts());
+            case "opm" -> realtime.getOpm() == null ? null : BigDecimal.valueOf(realtime.getOpm());
+            default -> null;
+        };
+    }
 }

--
Gitblit v1.9.3