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