From 808b3a2b6648f35fa8668a519f73ea0c16dd2c24 Mon Sep 17 00:00:00 2001
From: zhanglei <lei.zhang@kingtroldata.com>
Date: Tue, 11 Mar 2025 20:27:02 +0800
Subject: [PATCH] feat(equipment): 添加设备健康度定时更新功能

- 新增设备健康度和健康状态字段
- 实现设备列表查询和屏幕列表查询接口
- 添加设备健康度定时更新任务
- 优化设备信息查询 SQL
---
 sk-module-equipment/src/main/java/com/skua/modules/equipment/controller/EquipmentController.java        |   2 ++
 sk-module-equipment/src/main/java/com/skua/modules/equipment/entity/EquipmentInfo.java                  |  12 ++++++++++++
 sk-module-equipment/src/main/java/com/skua/modules/equipment/mapper/EquipmentInfoMapper.java            |   7 +++++++
 sk-module-equipment/src/main/java/com/skua/modules/equipment/mapper/xml/EquipmentInfoMapper.xml         |  20 ++++++++++++++++++++
 sk-module-equipment/src/main/java/com/skua/modules/equipment/quartz/EquipHealthLevelJob.java            | 191 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 sk-module-equipment/src/main/java/com/skua/modules/equipment/service/IEquipmentInfoService.java         |   5 +++++
 sk-module-equipment/src/main/java/com/skua/modules/equipment/service/impl/EquipmentInfoServiceImpl.java |  17 +++++++++++------
 7 files changed, 248 insertions(+), 6 deletions(-)
 create mode 100644 sk-module-equipment/src/main/java/com/skua/modules/equipment/quartz/EquipHealthLevelJob.java

diff --git a/sk-module-equipment/src/main/java/com/skua/modules/equipment/controller/EquipmentController.java b/sk-module-equipment/src/main/java/com/skua/modules/equipment/controller/EquipmentController.java
index d918117..c561cba 100644
--- a/sk-module-equipment/src/main/java/com/skua/modules/equipment/controller/EquipmentController.java
+++ b/sk-module-equipment/src/main/java/com/skua/modules/equipment/controller/EquipmentController.java
@@ -332,6 +332,8 @@ public class EquipmentController {
         }
         queryWrapper.eq(flag, "EquipmentInfo_isSpecial", isSpecial)
                 .groupBy("EquipmentInfo_equipmentStatus");//EquipmentInfo_isSpecial
+        sql = sql.replace("EquipmentInfo.maintenance_cost as EquipmentInfo_maintenanceCost,", "")
+                .replace("EquipmentInfo.gz_count as EquipmentInfo_gzCount,", "");
         List<Map<String, Object>> countMapList = iCommonSqlService.queryWrapperForList(sql, queryWrapper);
         for (Map<String, Object> item : countMapList) {
             String key = "" + item.get("EquipmentInfo_equipmentStatus");
diff --git a/sk-module-equipment/src/main/java/com/skua/modules/equipment/entity/EquipmentInfo.java b/sk-module-equipment/src/main/java/com/skua/modules/equipment/entity/EquipmentInfo.java
index df06099..24a9faf 100644
--- a/sk-module-equipment/src/main/java/com/skua/modules/equipment/entity/EquipmentInfo.java
+++ b/sk-module-equipment/src/main/java/com/skua/modules/equipment/entity/EquipmentInfo.java
@@ -1,6 +1,7 @@
 package com.skua.modules.equipment.entity;
 
 import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
 import com.baomidou.mybatisplus.annotation.TableId;
 import com.baomidou.mybatisplus.annotation.TableName;
 import com.fasterxml.jackson.annotation.JsonFormat;
@@ -276,11 +277,22 @@ public class EquipmentInfo {
 
     @ApiModelProperty(value = "性能分数")
     private String performanceScore;
+
     @ApiModelProperty(value = "设备健康度")
     private String equipmentHealthLevel;
+
     @ApiModelProperty(value = "设备健康状态")
+    @Dict(dicCode = "equipment_health_status")
     private String equipmentHealthStatus;
 
+    //维护费用
+    @TableField(exist = false)
+    private String maintenanceCost;
+
+    //维修次数
+    @TableField(exist = false)
+    private String gzCount;
+
     //检测机构
     @ApiModelProperty(value = "检测机构")
     private String testingDepart;
diff --git a/sk-module-equipment/src/main/java/com/skua/modules/equipment/mapper/EquipmentInfoMapper.java b/sk-module-equipment/src/main/java/com/skua/modules/equipment/mapper/EquipmentInfoMapper.java
index 565e8b7..80ba757 100644
--- a/sk-module-equipment/src/main/java/com/skua/modules/equipment/mapper/EquipmentInfoMapper.java
+++ b/sk-module-equipment/src/main/java/com/skua/modules/equipment/mapper/EquipmentInfoMapper.java
@@ -1,11 +1,13 @@
 package com.skua.modules.equipment.mapper;
 
 import java.util.List;
+import java.util.Map;
 
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.skua.modules.equipment.entity.EquipmentInfo;
 import com.skua.modules.equipment.vo.EquipmentInfoForMonitorVO;
+import io.lettuce.core.dynamic.annotation.Param;
 
 /**
  * 设备信息
@@ -24,4 +26,9 @@ public interface EquipmentInfoMapper extends BaseMapper<EquipmentInfo> {
 	List<EquipmentInfoForMonitorVO> queryCustomPageList(Page<EquipmentInfoForMonitorVO> pageList, EquipmentInfoForMonitorVO equipmentInfoForMonitorVO);
 
     void clearDigitaltwins();
+
+    List<EquipmentInfo> getEquipmentList();
+
+	List<Map<String, Object>> getScreenList(@Param("screenType") String screenType);
+
 }
diff --git a/sk-module-equipment/src/main/java/com/skua/modules/equipment/mapper/xml/EquipmentInfoMapper.xml b/sk-module-equipment/src/main/java/com/skua/modules/equipment/mapper/xml/EquipmentInfoMapper.xml
index 76f34af..99dcbe1 100644
--- a/sk-module-equipment/src/main/java/com/skua/modules/equipment/mapper/xml/EquipmentInfoMapper.xml
+++ b/sk-module-equipment/src/main/java/com/skua/modules/equipment/mapper/xml/EquipmentInfoMapper.xml
@@ -28,4 +28,24 @@
 	<update id="clearDigitaltwins">
     	update equipment_info set digital_twins_struct_code = ''
     </update>
+	<select id="getEquipmentList" resultType="com.skua.modules.equipment.entity.EquipmentInfo">
+		SELECT
+			ifnull( t.maintenance_cost, 0 ) maintenance_cost,
+			ifnull( r.id_count, 0 ) gz_count,
+			e.*
+		FROM
+			equipment_info e
+				LEFT JOIN ( SELECT SUM( maintenance_cost ) AS maintenance_cost, equipment_id FROM equipment_maintain_task GROUP BY equipment_id ) t ON e.id = t.equipment_id
+				LEFT JOIN ( SELECT count( id ) id_count, info_id FROM equipment_repair GROUP BY info_id ) r ON e.id = r.info_id
+	</select>
+	<select id="getScreenList" resultType="java.util.HashMap">
+		SELECT
+			context_code AS code,
+			context_title AS value,
+			context_name AS name
+		FROM
+			screen_user_context
+		WHERE
+			screen_type = #{screenType}
+	</select>
 </mapper>
diff --git a/sk-module-equipment/src/main/java/com/skua/modules/equipment/quartz/EquipHealthLevelJob.java b/sk-module-equipment/src/main/java/com/skua/modules/equipment/quartz/EquipHealthLevelJob.java
new file mode 100644
index 0000000..d04c346
--- /dev/null
+++ b/sk-module-equipment/src/main/java/com/skua/modules/equipment/quartz/EquipHealthLevelJob.java
@@ -0,0 +1,191 @@
+package com.skua.modules.equipment.quartz;
+
+import com.skua.core.util.ConvertUtils;
+import com.skua.core.util.DateUtils;
+import com.skua.core.util.DoubleOperaUtils;
+import com.skua.modules.equipment.entity.EquipmentInfo;
+import com.skua.modules.equipment.service.IEquipmentInfoService;
+import lombok.extern.slf4j.Slf4j;
+import org.quartz.Job;
+import org.quartz.JobExecutionContext;
+import org.quartz.JobExecutionException;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @program: skboot
+ * @description: 设备健康度定时任务
+ * @author: zhanglei
+ * @create: 2025/03/08 16:05:05
+ */
+@Slf4j
+@Component
+public class EquipHealthLevelJob implements Job {
+
+    @Autowired
+    private IEquipmentInfoService equipmentInfoService;
+
+    private static final String qz_screen_type = "71";//权重标识
+    private static final String status_screen_type = "70";//状态标识
+
+    @Override
+    public void execute(JobExecutionContext context) throws JobExecutionException {
+        log.info("设备健康度更新任务开始");
+        //获取当前时间 yyyy-MM-dd
+        String today = DateUtils.formatDate(new Date(), "yyyy-MM-dd");
+        Map<String,Double> qzMap = initQzMap();
+        Map<String,String> statusValueMap = initStatusMap();
+        //workingLife 使用年限、originalValue 购置价格、installDate 安装日期
+        List<EquipmentInfo> list = equipmentInfoService.getEquipmentList();
+        for (EquipmentInfo equipmentInfo : list){
+            double performanceScore = 100.00;//性能得分
+            double faultScore = 100.00;//故障得分
+            double maintainScore = 100.00;//维护得分
+            double useYearScore = 100.00;//使用年限得分
+            //性能分数
+            if(ConvertUtils.isNotEmpty(equipmentInfo.getPerformanceScore())){
+                performanceScore = Double.valueOf(equipmentInfo.getPerformanceScore());
+            }
+            performanceScore = DoubleOperaUtils.bigDecimalRound(qzMap.get("xnzb")/100.00 * performanceScore,2);
+            //故障分数
+            faultScore = getFaultScore(equipmentInfo.getGzCount(),qzMap.get("gzl")/100.00);
+            //维护分数
+            maintainScore = getMaintainScore(equipmentInfo.getMaintenanceCost(), equipmentInfo.getOriginalValue(),qzMap.get("whcb")/100.00);
+            //使用年限分数
+            useYearScore = getUseYearScore(equipmentInfo.getWorkingLife(),equipmentInfo.getInstallDate(),today,qzMap.get("synx")/100.00);
+            //计算总分
+            double score = performanceScore + faultScore + maintainScore + useYearScore;
+            equipmentInfo.setEquipmentHealthLevel(String.valueOf(score));
+
+            //判断score在statusValueMap的key值的哪个区间,返回对应的value
+            String statusValue = getEquipmentHealthStatus(score,statusValueMap);
+
+            equipmentInfo.setEquipmentHealthStatus(statusValue);
+            equipmentInfoService.updateById(equipmentInfo);
+        }
+
+    }
+
+    private String getEquipmentHealthStatus(double score,Map<String,String> statusValueMap) {
+        String statusValue = "";
+        for (Map.Entry<String, String> entry : statusValueMap.entrySet()) {
+            String key = entry.getKey();
+            String value = entry.getValue();
+            if (score >= Double.valueOf(key.split("-")[0]) && score <= Double.valueOf(key.split("-")[1])) {
+                statusValue = value.split("-")[0];
+                break;
+            }
+        }
+        return statusValue;
+    }
+
+    //初始化权重
+    private Map<String,Double> initQzMap() {
+        Map<String,Double> qzMap = new HashMap<>();
+        qzMap.put("xnzb",40.00);//性能指标
+        qzMap.put("gzl",20.00);//故障率
+        qzMap.put("whcb",20.00);//维护成本
+        qzMap.put("synx",20.00);//使用年限
+        //获取权重及分值信息
+        List<Map<String,Object>> weightList = equipmentInfoService.getScreenList(qz_screen_type);
+        for (Map<String,Object> map : weightList){
+            if("xnzb".equals(map.get("code"))){
+                qzMap.put("xnzb",Double.valueOf(map.get("value").toString()));
+            }
+            if("gzl".equals(map.get("code"))){
+                qzMap.put("gzl",Double.valueOf(map.get("value").toString()));
+            }
+            if("whcb".equals(map.get("code"))){
+                qzMap.put("whcb",Double.valueOf(map.get("value").toString()));
+            }
+            if("synx".equals(map.get("code"))){
+                qzMap.put("synx",Double.valueOf(map.get("value").toString()));
+            }
+        }
+        return qzMap;
+    }
+
+    //初始化状态字典
+    private Map<String,String> initStatusMap() {
+        Map<String,String> statusValueMap = new HashMap<>();
+        statusValueMap.put("90-100","wdyx-稳定运行");//稳定运行
+        statusValueMap.put("60-90","qwth-轻微退化");//轻微退化
+        statusValueMap.put("40-60","mxxj-明显下降");//明显下降
+        statusValueMap.put("0-40","jjbf-接近报废");//接近报废
+        List<Map<String,Object>> statusList = equipmentInfoService.getScreenList(status_screen_type);
+        for (Map<String,Object> map : statusList){
+            if("wdyx".equals(map.get("code"))){
+                statusValueMap.put(map.get("value").toString(),"wdyx-"+map.get("name").toString());//稳定运行
+            }
+            if("qwth".equals(map.get("code"))){
+                statusValueMap.put(map.get("value").toString(),"qwth-"+map.get("name").toString());//轻微退化
+            }
+            if("mxxj".equals(map.get("code"))){
+                statusValueMap.put(map.get("value").toString(),"mxxj-"+map.get("name").toString());//明显下降
+            }
+            if("jjbf".equals(map.get("code"))){
+                statusValueMap.put(map.get("value").toString(),"jjbf-"+map.get("name").toString());//接近报废
+            }
+        }
+        return statusValueMap;
+    }
+
+    /**
+     * 计算故障评分
+     * @param gzCount 设备信息
+     * @param qz 权重因子
+     * @return 返回计算得到的故障评分
+     */
+    private double getFaultScore(String gzCount, double qz) {
+        double score = 100.00;
+        if(Double.valueOf(gzCount) >= 4){
+            score = 0.00;
+        }else{
+            score = 100 - 100*Double.valueOf(gzCount)/4;
+        }
+        return DoubleOperaUtils.bigDecimalRound(qz * score,2);
+    }
+
+    /**
+     * 计算维护得分
+     * @param maintenanceCost   设备维护费用
+     * @param originalValue     购置金额
+     * @param qz                权重
+     * @return 返回计算得到的维护得分
+     */
+    private double getMaintainScore(String maintenanceCost, String originalValue, double qz) {
+        double score = 100.00;
+        if(ConvertUtils.isNotEmpty(originalValue)){
+            double gzfy = Double.valueOf(originalValue);
+            double whfy = Double.valueOf(maintenanceCost);
+            score = 100*(gzfy-whfy)/gzfy;
+        }
+        return DoubleOperaUtils.bigDecimalRound(qz * score,2);
+    }
+
+    /**
+     * 计算使用寿命得分
+     * @param workingLife 使用年限
+     * @param installDate 安装日期
+     * @param today       当前日期
+     * @param qz          权重因子
+     * @return 返回使用寿命得分,固定为100分的20%
+     */
+    private double getUseYearScore(String workingLife, String installDate, String today, double qz) {
+        double score = 100.00;
+        if(ConvertUtils.isNotEmpty(installDate)){
+            if(ConvertUtils.isNotEmpty(workingLife)){
+                double sjsy = Double.valueOf(DateUtils.dayDiff(installDate,today));
+                double sm = 365*Double.valueOf(workingLife);
+                score = 100 * (sm-sjsy)/sm;
+            }
+        }
+        return DoubleOperaUtils.bigDecimalRound(qz * score,2);
+    }
+
+}
diff --git a/sk-module-equipment/src/main/java/com/skua/modules/equipment/service/IEquipmentInfoService.java b/sk-module-equipment/src/main/java/com/skua/modules/equipment/service/IEquipmentInfoService.java
index 30fa8c7..ad57c96 100644
--- a/sk-module-equipment/src/main/java/com/skua/modules/equipment/service/IEquipmentInfoService.java
+++ b/sk-module-equipment/src/main/java/com/skua/modules/equipment/service/IEquipmentInfoService.java
@@ -87,4 +87,9 @@ public interface IEquipmentInfoService extends IService<EquipmentInfo> {
     String reCreateQrCode(String id);
 
     void batchConfigDigitaltwins(JSONObject jsonObject);
+
+    List<EquipmentInfo> getEquipmentList();
+
+	List<Map<String, Object>> getScreenList(String screenType);
+
 }
diff --git a/sk-module-equipment/src/main/java/com/skua/modules/equipment/service/impl/EquipmentInfoServiceImpl.java b/sk-module-equipment/src/main/java/com/skua/modules/equipment/service/impl/EquipmentInfoServiceImpl.java
index 203214a..63cfc08 100644
--- a/sk-module-equipment/src/main/java/com/skua/modules/equipment/service/impl/EquipmentInfoServiceImpl.java
+++ b/sk-module-equipment/src/main/java/com/skua/modules/equipment/service/impl/EquipmentInfoServiceImpl.java
@@ -3,11 +3,7 @@ package com.skua.modules.equipment.service.impl;
 import java.io.File;
 import java.io.IOException;
 import java.io.InputStream;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
+import java.util.*;
 
 import cn.hutool.json.JSONObject;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
@@ -79,7 +75,6 @@ public class EquipmentInfoServiceImpl extends ServiceImpl<EquipmentInfoMapper, E
 	@Autowired
 	private IEquipmentAssetService equipmentAssetService;
 
-
 	@Override
 	public void addData(Result<EquipmentVO> result, EquipmentDTO equipmentDTO) throws Exception {
 
@@ -360,4 +355,14 @@ public class EquipmentInfoServiceImpl extends ServiceImpl<EquipmentInfoMapper, E
 		}
 	}
 
+	@Override
+	public List<EquipmentInfo> getEquipmentList() {
+		return equipmentInfoMapper.getEquipmentList();
+	}
+
+	@Override
+	public List<Map<String, Object>> getScreenList(String screenType) {
+		return equipmentInfoMapper.getScreenList(screenType);
+	}
+
 }
--
libgit2 0.24.0