Эх сурвалжийг харах

pms 保养预警 列表功能优化

zhangcl 2 сар өмнө
parent
commit
1016f34e05

+ 5 - 0
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/vo/IotDeviceRespVO.java

@@ -177,4 +177,9 @@ public class IotDeviceRespVO {
 
     @Schema(description = "距离保养时间 单位可能是 H D KM")
     private String mainDistance;
+
+    @Schema(description = "保养工单id")
+    private String workOrderId;
+    @Schema(description = "保养计划id")
+    private String planId;
 }

+ 12 - 1
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/dal/mysql/IotDeviceMapper.java

@@ -174,5 +174,16 @@ public interface IotDeviceMapper extends BaseMapperX<IotDeviceDO> {
 
 
     IPage<IotDeviceRespVO> deviceDistances(IPage<IotDeviceRespVO> page, @Param("reqVO") IotMainWorkOrderPageReqVO reqVO,
-                                           @Param("sortedDeviceIds") Collection<Long> sortedDeviceIds, @Param("deptIds") Collection<Long> deptIds);
+                                           @Param("sortedDeviceIds") Collection<Long> sortedDeviceIds,
+                                           @Param("deviceIds") Collection<Long> deviceIds,
+                                           @Param("mainBomDeviceIds") Collection<Long> mainBomDeviceIds, @Param("deptIds") Collection<Long> deptIds);
+
+
+    IPage<IotDeviceRespVO> allDeviceDistances(IPage<IotDeviceRespVO> page, @Param("reqVO") IotMainWorkOrderPageReqVO reqVO,
+                                           @Param("alarmDeviceIds") Collection<Long> alarmDeviceIds,
+                                           @Param("deptIds") Collection<Long> deptIds);
+
+    List<IotDeviceRespVO> deviceAlarmDistances(@Param("sortedDeviceIds") Collection<Long> sortedDeviceIds,
+                                           @Param("deviceIds") Collection<Long> deviceIds,
+                                           @Param("mainBomDeviceIds") Collection<Long> mainBomDeviceIds);
 }

+ 5 - 0
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/dal/mysql/iotmaintenancebom/IotMaintenanceBomMapper.java

@@ -86,6 +86,11 @@ public interface IotMaintenanceBomMapper extends BaseMapperX<IotMaintenanceBomDO
                 .betweenIfPresent(IotMaintenanceBomDO::getCreateTime, reqVO.getCreateTime()));
     }
 
+    default List<IotMaintenanceBomDO> selectAlarmList(IotMaintenanceBomPageReqVO reqVO) {
+        return selectList(new LambdaQueryWrapperX<IotMaintenanceBomDO>()
+                .notIn(IotMaintenanceBomDO::getDeviceId, reqVO.getDeviceIds()));
+    }
+
     default int deleteByPlanId(Long planId) {
         return delete(IotMaintenanceBomDO::getPlanId, planId);
     }

+ 106 - 7
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/service/iotmainworkorder/IotMainWorkOrderServiceImpl.java

@@ -156,11 +156,92 @@ public class IotMainWorkOrderServiceImpl implements IotMainWorkOrderService {
                 .map(IotMainWorkOrderBomDO::getDeviceId) // 获取 deviceId
                 .filter(Objects::nonNull)      // 过滤非空值
                 .collect(Collectors.toSet());  // 收集到 Set 中
+        Set<Long> orderDeviceIds = new HashSet<>();
+        orderDeviceIds.addAll(deviceIds);
+        // 查询保养计划明细中不包含 deviceIds 的设备id集合
+        List<IotMaintenanceBomDO> mainBomS = new ArrayList<>();
+        Set<Long> mainBomDeviceIds = new HashSet<>();
+        if (CollUtil.isNotEmpty(deviceIds)) {
+            IotMaintenanceBomPageReqVO mainBomReqVO = new IotMaintenanceBomPageReqVO();
+            mainBomReqVO.setDeviceIds(new ArrayList<>(deviceIds));
+            mainBomS = iotMaintenanceBomMapper.selectAlarmList(mainBomReqVO);
+            mainBomDeviceIds = CollUtil.isEmpty(mainBomS)
+                    ? Collections.emptySet()
+                    : mainBomS.stream()
+                    .map(IotMaintenanceBomDO::getDeviceId) // 获取 deviceId
+                    .filter(Objects::nonNull)      // 过滤非空值
+                    .collect(Collectors.toSet());  // 收集到 Set 中
+            deviceIds.addAll(mainBomDeviceIds);
+        }
         Map<Long, IotDeviceRunLogRespVO> deviceRunLogMap = iotDeviceRunLogService.getDeviceRunLogMap(new ArrayList<>(deviceIds));
         // 以设备为维度统计每个设备相关的保养项的最近保养距离 key设备id    value设备下每个保养项的的最小保养距离集合
         Map<Long, List<Map<String, Object>>> orderDistancePair = new HashMap<>();
         // 设备保养明细 key设备id  value设备保养工单明细下所有保养规则数据最小值
         Map<Long, String> resultMap = new HashMap<>();
+        if (CollUtil.isNotEmpty(mainBomS)) {
+            // 遍历保养计划明细 计算 保养计划中的设备 的最近的保养时间
+            mainBomS.forEach(bom -> {
+                BigDecimal runningTimeDistance = null;
+                BigDecimal runningKiloDistance = null;
+                BigDecimal naturalDateDistance = null;
+                // 计算每个保养项 每个保养规则下的 距离保养时间 单位 小时
+                if (0 == bom.getRunningTimeRule()) {
+                    // 运行时间保养规则
+                    if (deviceRunLogMap.containsKey(bom.getDeviceId())) {
+                        BigDecimal totalRunTime = deviceRunLogMap.get(bom.getDeviceId()).getTotalRunTime();
+                        BigDecimal lastRunningTime = bom.getLastRunningTime();      // 上次保养运行时间
+                        BigDecimal runningTimePeriod = bom.getNextRunningTime();    // 运行时间周期
+                        BigDecimal timePeriodLead = bom.getTimePeriodLead();    // 运行时间周期提前量
+                        runningTimeDistance = (lastRunningTime.add(runningTimePeriod).subtract(timePeriodLead)).subtract(totalRunTime);
+                    }
+                }
+                if (0 == bom.getMileageRule()) {
+                    // 运行里程保养规则 累计运行里程规则 累计运行里程 >= (上次保养运行里程+运行里程周期-提前量)
+                    if (deviceRunLogMap.containsKey(bom.getDeviceId())) {
+                        BigDecimal totalMileage = deviceRunLogMap.get(bom.getDeviceId()).getTotalMileage();
+                        BigDecimal lastRunningKilo = bom.getLastRunningKilometers();      // 上次保养运行里程
+                        BigDecimal runningKiloPeriod = bom.getNextRunningKilometers();    // 运行里程周期
+                        BigDecimal kiloCycleLead = bom.getKiloCycleLead();    // 运行里程周期提前量
+                        runningKiloDistance = (lastRunningKilo.add(runningKiloPeriod).subtract(kiloCycleLead)).subtract(totalMileage);
+                    }
+                }
+                if (0 == bom.getNaturalDateRule()) {
+                    // 自然日期保养规则
+                    LocalDateTime lastNaturalDate = bom.getLastNaturalDate();      // 上次保养自然日期
+                    BigDecimal naturalDatePeriod = bom.getNextNaturalDate();        // 自然日周期
+                    BigDecimal natualDateLead = bom.getNaturalDatePeriodLead();    // 自然日周期提前量
+                    if (ObjUtil.isNotEmpty(lastNaturalDate) && ObjUtil.isNotEmpty(naturalDatePeriod) && ObjUtil.isNotEmpty(natualDateLead)) {
+                        // 计算有效天数 = 自然日周期 - 提前量
+                        long days = naturalDatePeriod.subtract(natualDateLead).longValue(); // 转为长整型天数
+                        // 计算目标日期:上次保养日期 + 有效天数(注意:LocalDateTime加天数会自动处理日期进位)
+                        LocalDateTime targetDate = lastNaturalDate.plusDays(days);
+                        // 获取当前日期时间
+                        LocalDateTime now = LocalDateTime.now();
+                        // 计算日期差值(以天为单位)
+                        naturalDateDistance = new BigDecimal(ChronoUnit.DAYS.between(targetDate, now));
+                    }
+                }
+                // 找出距离0最近的数,作为工单的最近保养距离数据
+                Object closet = chooseNearestDistance(runningTimeDistance, runningKiloDistance, naturalDateDistance);
+                Map<String, Object> tempDistance = new HashMap<>();
+                if (closet == runningTimeDistance) {
+                    tempDistance.put("H", closet);
+                } else if (closet == runningKiloDistance) {
+                    tempDistance.put("KM", closet);
+                } else if (closet == naturalDateDistance) {
+                    tempDistance.put("D", closet);
+                }
+                if (orderDistancePair.containsKey(bom.getDeviceId())) {
+                    List<Map<String, Object>> tempDistances = orderDistancePair.get(bom.getDeviceId());
+                    tempDistances.add(tempDistance);
+                    orderDistancePair.put(bom.getDeviceId(), tempDistances);
+                } else {
+                    List<Map<String, Object>> tempDistances = new ArrayList<>();
+                    tempDistances.add(tempDistance);
+                    orderDistancePair.put(bom.getDeviceId(), tempDistances);
+                }
+            });
+        }
         // 计算出每个保养工单明细的不同保养规则的保养距离最小值
         if (CollUtil.isNotEmpty(workOrderBomS)) {
             workOrderBomS.forEach(bom -> {
@@ -231,22 +312,40 @@ public class IotMainWorkOrderServiceImpl implements IotMainWorkOrderService {
             // 排序后输出一个 List<Long> 类型的集合,排序对应上面的排序规则
             List<Long> sortedDeviceIds = sortByNumericValue(resultMap);
             try {
-                // 组织层级查询
+                // 左侧组织树 组织层级查询
                 Set<Long> ids = new HashSet<>();
                 if (Objects.nonNull(pageReqVO.getDeptId())) {
                     ids = deptService.getChildDeptIdListFromCache(pageReqVO.getDeptId());
                     ids.add(pageReqVO.getDeptId());
                 }
-                IPage<IotDeviceRespVO> page = iotDeviceMapper.deviceDistances(
-                        new Page<>(pageReqVO.getPageNo(), pageReqVO.getPageSize()), pageReqVO, sortedDeviceIds, ids);
+                // 筛选出已计算出保养距离的设备id
+                /* IPage<IotDeviceRespVO> page = iotDeviceMapper.deviceDistances(
+                        new Page<>(pageReqVO.getPageNo(), pageReqVO.getPageSize()), pageReqVO, sortedDeviceIds, orderDeviceIds, mainBomDeviceIds, ids); */
+                List<IotDeviceRespVO> alarmDevices = iotDeviceMapper.deviceAlarmDistances(sortedDeviceIds, orderDeviceIds, mainBomDeviceIds);
                 // 处理当前分页数据 拼接上已经排序的 筛选出的设备保养项 最小保养距离
-                if (CollUtil.isNotEmpty(page.getRecords())) {
-                    for (IotDeviceRespVO device : page.getRecords()) {
+                List<Long> alarmDeviceIds = new ArrayList<>();
+                Map<Long, IotDeviceRespVO> alarmDevicePair = new HashMap<>();
+                if (CollUtil.isNotEmpty(alarmDevices)) {
+                    for (IotDeviceRespVO device : alarmDevices) {
                         if (resultMap.containsKey(device.getId())) {
                             device.setMainDistance(resultMap.get(device.getId()));
+                            alarmDeviceIds.add(device.getId());
                         }
+                        alarmDevicePair.put(device.getId(), device);
                     }
                 }
+                // 查询所有设备列表 通过SQL形式 使用 FIELD 字段
+                IPage<IotDeviceRespVO> page = iotDeviceMapper.allDeviceDistances(
+                        new Page<>(pageReqVO.getPageNo(), pageReqVO.getPageSize()), pageReqVO, alarmDeviceIds, ids);
+                if (CollUtil.isNotEmpty(page.getRecords())) {
+                    page.getRecords().forEach(device -> {
+                        if (alarmDevicePair.containsKey(device.getId())) {
+                            device.setMainDistance(alarmDevicePair.get(device.getId()).getMainDistance());
+                            device.setPlanId(alarmDevicePair.get(device.getId()).getPlanId());
+                            device.setWorkOrderId(alarmDevicePair.get(device.getId()).getWorkOrderId());
+                        }
+                    });
+                }
                 return new PageResult<>(page.getRecords(), page.getTotal());
             } catch (Exception exception) {
                 if (exception.getMessage().contains("Table does not exist")) {
@@ -581,8 +680,8 @@ public class IotMainWorkOrderServiceImpl implements IotMainWorkOrderService {
                 .filter(order -> !order.getId().equals(updateObj.getId()))
                 .collect(Collectors.toList());
         if (CollUtil.isNotEmpty(filteredOrders)) {
-            // 将关联工单设置为 已执行
-            filteredOrders.forEach(order -> order.setResult(2));
+            // 将关联工单设置为 已执行 直接删除
+            filteredOrders.forEach(order -> {order.setResult(2);  order.setDeleted(true);});
             iotMainWorkOrderMapper.updateBatch(filteredOrders);
             List<Long> workOrderIds = filteredOrders.stream()
                     .map(IotMainWorkOrderDO::getId)

+ 142 - 4
yudao-module-pms/yudao-module-pms-biz/src/main/resources/mapper/static/IotDeviceMapper.xml

@@ -47,15 +47,57 @@
         </if>
     </select>
 
+    <select id="allDeviceDistances"
+            resultType="cn.iocoder.yudao.module.pms.controller.admin.vo.IotDeviceRespVO">
+        SELECT
+        rid.id,
+        rid.dept_id AS deptId,
+        rid.device_code AS deviceCode,
+        rid.device_name AS deviceName,
+        rid.device_status AS deviceStatus,
+        rid.asset_property AS assetProperty
+        FROM rq_iot_device rid
+        WHERE rid.deleted = 0
+        <if test="deptIds != null and deptIds.size &gt; 0">
+            AND rid.dept_id IN
+            <foreach collection="deptIds" index="index" item="key" open="(" separator="," close=")">
+                #{key}
+            </foreach>
+        </if>
+        <if test="reqVO.deviceName!=null and reqVO.deviceName!=''">
+            AND rid.device_name LIKE concat(concat("%",#{reqVO.deviceName}),"%")
+        </if>
+        <if test="reqVO.deviceCode!=null and reqVO.deviceCode!=''">
+            AND rid.device_code LIKE concat(concat("%",#{reqVO.deviceCode}),"%")
+        </if>
+        ORDER BY
+        <if test="alarmDeviceIds != null and alarmDeviceIds.size &gt; 0">
+            CASE WHEN rid.id IN
+            <foreach collection="alarmDeviceIds" index="index" item="key" open="(" separator="," close=")">
+                #{key}
+            </foreach>
+            THEN 0 ELSE 1 END,
+            FIELD(rid.id,
+            <foreach collection="alarmDeviceIds" index="index" item="key" separator=",">
+                #{key}
+            </foreach>),
+        </if>
+        rid.id DESC;
+    </select>
+
     <select id="deviceDistances"
             resultType="cn.iocoder.yudao.module.pms.controller.admin.vo.IotDeviceRespVO">
+        SELECT *
+        FROM (
         SELECT
         rid.id,
         rid.dept_id	deptId,
         rid.device_code deviceCode,
         rid.device_name deviceName,
         rid.device_status deviceStatus,
-        rid.asset_property assetProperty
+        rid.asset_property assetProperty,
+        MAX(mwoo.work_order_id) workOrderId,
+        '' planId
         FROM rq_iot_main_work_order_bom mwoo
         LEFT JOIN rq_iot_device rid ON rid.id = mwoo.device_id
         WHERE mwoo.deleted = 0
@@ -67,9 +109,9 @@
                 #{key}
             </foreach>
         </if>
-        <if test="sortedDeviceIds != null and sortedDeviceIds.size &gt; 0">
+        <if test="deviceIds != null and deviceIds.size &gt; 0">
             AND rid.id IN
-            <foreach collection="sortedDeviceIds" index="index" item="key" open="(" separator="," close=")">
+            <foreach collection="deviceIds" index="index" item="key" open="(" separator="," close=")">
                 #{key}
             </foreach>
         </if>
@@ -80,7 +122,103 @@
             AND rid.device_code LIKE concat(concat("%",#{reqVO.deviceCode}),"%")
         </if>
         GROUP BY mwoo.device_id
-        ORDER BY FIELD(rid.id,
+
+        UNION ALL
+
+        SELECT
+        rid.id,
+        rid.dept_id	deptId,
+        rid.device_code deviceCode,
+        rid.device_name deviceName,
+        rid.device_status deviceStatus,
+        rid.asset_property assetProperty,
+        '' workOrderId,
+        MAX(mb.plan_id) planId
+        FROM rq_iot_maintenance_bom mb
+        LEFT JOIN rq_iot_device rid ON rid.id = mb.device_id
+        WHERE mb.deleted = 0
+        AND mb.`status` = 0
+        AND rid.device_code IS NOT NULL
+        <if test="deptIds != null and deptIds.size &gt; 0">
+            AND rid.dept_id IN
+            <foreach collection="deptIds" index="index" item="key" open="(" separator="," close=")">
+                #{key}
+            </foreach>
+        </if>
+        <if test="mainBomDeviceIds != null and mainBomDeviceIds.size &gt; 0">
+            AND rid.id IN
+            <foreach collection="mainBomDeviceIds" index="index" item="key" open="(" separator="," close=")">
+                #{key}
+            </foreach>
+        </if>
+        <if test="reqVO.deviceName!=null and reqVO.deviceName!=''">
+            AND rid.device_name LIKE concat(concat("%",#{reqVO.deviceName}),"%")
+        </if>
+        <if test="reqVO.deviceCode!=null and reqVO.deviceCode!=''">
+            AND rid.device_code LIKE concat(concat("%",#{reqVO.deviceCode}),"%")
+        </if>
+        GROUP BY mb.device_id
+        ) tmp
+        ORDER BY FIELD(tmp.id,
+        <if test="sortedDeviceIds != null and sortedDeviceIds.size &gt; 0">
+            <foreach collection="sortedDeviceIds" index="index" item="key" separator=",">
+                #{key}
+            </foreach>
+        </if>
+        )
+    </select>
+
+    <select id="deviceAlarmDistances"
+            resultType="cn.iocoder.yudao.module.pms.controller.admin.vo.IotDeviceRespVO">
+        SELECT *
+        FROM (
+        SELECT
+        rid.id,
+        rid.dept_id	deptId,
+        rid.device_code deviceCode,
+        rid.device_name deviceName,
+        rid.device_status deviceStatus,
+        rid.asset_property assetProperty,
+        MAX(mwoo.work_order_id) workOrderId,
+        '' planId
+        FROM rq_iot_main_work_order_bom mwoo
+        LEFT JOIN rq_iot_device rid ON rid.id = mwoo.device_id
+        WHERE mwoo.deleted = 0
+        AND mwoo.`status` = 0
+        AND rid.device_code IS NOT NULL
+        <if test="deviceIds != null and deviceIds.size &gt; 0">
+            AND rid.id IN
+            <foreach collection="deviceIds" index="index" item="key" open="(" separator="," close=")">
+                #{key}
+            </foreach>
+        </if>
+        GROUP BY mwoo.device_id
+
+        UNION ALL
+
+        SELECT
+        rid.id,
+        rid.dept_id	deptId,
+        rid.device_code deviceCode,
+        rid.device_name deviceName,
+        rid.device_status deviceStatus,
+        rid.asset_property assetProperty,
+        '' workOrderId,
+        MAX(mb.plan_id) planId
+        FROM rq_iot_maintenance_bom mb
+        LEFT JOIN rq_iot_device rid ON rid.id = mb.device_id
+        WHERE mb.deleted = 0
+        AND mb.`status` = 0
+        AND rid.device_code IS NOT NULL
+        <if test="mainBomDeviceIds != null and mainBomDeviceIds.size &gt; 0">
+            AND rid.id IN
+            <foreach collection="mainBomDeviceIds" index="index" item="key" open="(" separator="," close=")">
+                #{key}
+            </foreach>
+        </if>
+        GROUP BY mb.device_id
+        ) tmp
+        ORDER BY FIELD(tmp.id,
         <if test="sortedDeviceIds != null and sortedDeviceIds.size &gt; 0">
             <foreach collection="sortedDeviceIds" index="index" item="key" separator=",">
                 #{key}