Forráskód Böngészése

pms 成套监控 参数前缀 保养查询列表显示 累计时长公里数

zhangcl 7 órája
szülő
commit
46b0d7eb4d

+ 73 - 18
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/devicegroup/IotDeviceGroupController.java

@@ -214,7 +214,16 @@ public class IotDeviceGroupController {
                                 if (row.getModelName().contains("氮气纯度") || row.getModelName().contains("氮气压力") || row.getModelName().contains("瞬时流量") ||
                                         row.getModelName().contains("PSA累计流量") || row.getModelName().contains("运行状态")) {
                                     IotDeviceGroupMonitorVO monitor = new IotDeviceGroupMonitorVO();
-                                    monitor.setModelName(row.getModelName());
+                                    String originalName = row.getModelName();
+                                    String psaPrefix = getModelNamePrefix(originalName, "PSA");
+                                    // 去掉前缀,设置modelName
+                                    if (StrUtil.isNotBlank(psaPrefix)) {
+                                        // 使用replaceFirst去掉前缀
+                                        String cleanedName = originalName.replaceFirst(psaPrefix, "");
+                                        monitor.setModelName(cleanedName);
+                                    } else {
+                                        monitor.setModelName(originalName);
+                                    }
                                     monitor.setValue(row.getValue());
                                     monitors.add(monitor);
                                 }
@@ -222,23 +231,23 @@ public class IotDeviceGroupController {
                         } else {
                             // 没有返回数据 填充空值
                             IotDeviceGroupMonitorVO pure = new IotDeviceGroupMonitorVO();
-                            pure.setModelName("PSA氮气纯度");
+                            pure.setModelName("氮气纯度");
                             pure.setValue("");
                             monitors.add(pure);
                             IotDeviceGroupMonitorVO pressure = new IotDeviceGroupMonitorVO();
-                            pressure.setModelName("PSA氮气压力");
+                            pressure.setModelName("氮气压力");
                             pressure.setValue("");
                             monitors.add(pressure);
                             IotDeviceGroupMonitorVO instantFlow = new IotDeviceGroupMonitorVO();
-                            instantFlow.setModelName("PSA氮气瞬时流量");
+                            instantFlow.setModelName("氮气瞬时流量");
                             instantFlow.setValue("");
                             monitors.add(instantFlow);
                             IotDeviceGroupMonitorVO totalFlow = new IotDeviceGroupMonitorVO();
-                            totalFlow.setModelName("PSA累计流量");
+                            totalFlow.setModelName("累计流量");
                             totalFlow.setValue("");
                             monitors.add(totalFlow);
                             IotDeviceGroupMonitorVO status = new IotDeviceGroupMonitorVO();
-                            status.setModelName("PSA运行状态");
+                            status.setModelName("运行状态");
                             status.setValue("");
                             monitors.add(status);
                         }
@@ -289,7 +298,16 @@ public class IotDeviceGroupController {
                                         row.getModelName().contains("后轴承温度") || row.getModelName().contains("总运行时间") || row.getModelName().contains("设备状态")
                                         || row.getModelName().contains("总用电能")) {
                                     IotDeviceGroupMonitorVO monitor = new IotDeviceGroupMonitorVO();
-                                    monitor.setModelName(row.getModelName());
+                                    String originalName = row.getModelName();
+                                    String prefix = getModelNamePrefix(originalName, "中压");
+                                    // 去掉前缀,设置modelName
+                                    if (StrUtil.isNotBlank(prefix)) {
+                                        // 使用replaceFirst去掉前缀
+                                        String cleanedName = originalName.replaceFirst(prefix, "");
+                                        monitor.setModelName(cleanedName);
+                                    } else {
+                                        monitor.setModelName(originalName);
+                                    }
                                     monitor.setValue(row.getValue());
                                     monitors.add(monitor);
                                 }
@@ -297,23 +315,23 @@ public class IotDeviceGroupController {
                         } else {
                             // 没有返回数据 填充空值
                             IotDeviceGroupMonitorVO outPress = new IotDeviceGroupMonitorVO();
-                            outPress.setModelName("中压排气压力");
+                            outPress.setModelName("排气压力");
                             outPress.setValue("");
                             monitors.add(outPress);
                             IotDeviceGroupMonitorVO outTemp = new IotDeviceGroupMonitorVO();
-                            outTemp.setModelName("中压排气温度");
+                            outTemp.setModelName("排气温度");
                             outTemp.setValue("");
                             monitors.add(outTemp);
                             IotDeviceGroupMonitorVO sysPress = new IotDeviceGroupMonitorVO();
-                            sysPress.setModelName("中压系统压力");
+                            sysPress.setModelName("系统压力");
                             sysPress.setValue("");
                             monitors.add(sysPress);
                             IotDeviceGroupMonitorVO backTemp = new IotDeviceGroupMonitorVO();
-                            backTemp.setModelName("中压后轴承温度");
+                            backTemp.setModelName("后轴承温度");
                             backTemp.setValue("");
                             monitors.add(backTemp);
                             IotDeviceGroupMonitorVO totalTime = new IotDeviceGroupMonitorVO();
-                            totalTime.setModelName("中压总运行时间");
+                            totalTime.setModelName("总运行时间");
                             totalTime.setValue("");
                             monitors.add(totalTime);
                             IotDeviceGroupMonitorVO totalPower = new IotDeviceGroupMonitorVO();
@@ -341,7 +359,18 @@ public class IotDeviceGroupController {
                                         || row.getModelName().contains("喷油温度") || row.getModelName().contains("喷油压力") ||
                                         row.getModelName().contains("运行状态") || row.getModelName().contains("加载状态")) {
                                     IotDeviceGroupMonitorVO monitor = new IotDeviceGroupMonitorVO();
-                                    monitor.setModelName(row.getModelName());
+                                    // 属性名称去掉 空压x
+                                    // 获取"空压x"前缀部分
+                                    String originalName = row.getModelName();
+                                    String kongYaPrefix = getKongYaPart(originalName);
+                                    // 去掉前缀,设置modelName
+                                    if (StrUtil.isNotBlank(kongYaPrefix)) {
+                                        // 方法1:使用replaceFirst去掉前缀
+                                        String cleanedName = originalName.replaceFirst(kongYaPrefix, "");
+                                        monitor.setModelName(cleanedName);
+                                    } else {
+                                        monitor.setModelName(originalName);
+                                    }
                                     monitor.setValue(row.getValue());
                                     monitors.add(monitor);
                                     // 排序 运行状态 加载状态 字段 置后
@@ -363,7 +392,16 @@ public class IotDeviceGroupController {
                                 if (row.getModelName().contains("入口压力") || row.getModelName().contains("出口温度") || row.getModelName().contains("冷却后温度") ||
                                         row.getModelName().contains("出口压力")) {
                                     IotDeviceGroupMonitorVO monitor = new IotDeviceGroupMonitorVO();
-                                    monitor.setModelName(row.getModelName());
+                                    String originalName = row.getModelName();
+                                    String prefix = getModelNamePrefix(originalName, "液驱");
+                                    // 去掉前缀,设置modelName
+                                    if (StrUtil.isNotBlank(prefix)) {
+                                        // 使用replaceFirst去掉前缀
+                                        String cleanedName = originalName.replaceFirst(prefix, "");
+                                        monitor.setModelName(cleanedName);
+                                    } else {
+                                        monitor.setModelName(originalName);
+                                    }
                                     monitor.setValue(row.getValue());
                                     monitors.add(monitor);
                                 }
@@ -371,19 +409,19 @@ public class IotDeviceGroupController {
                         } else {
                             // 没有返回数据 填充空值
                             IotDeviceGroupMonitorVO enterPressure = new IotDeviceGroupMonitorVO();
-                            enterPressure.setModelName("液驱入口压力");
+                            enterPressure.setModelName("入口压力");
                             enterPressure.setValue("");
                             monitors.add(enterPressure);
                             IotDeviceGroupMonitorVO onePressure = new IotDeviceGroupMonitorVO();
-                            onePressure.setModelName("液驱一级入口压力");
+                            onePressure.setModelName("一级入口压力");
                             onePressure.setValue("");
                             monitors.add(onePressure);
                             IotDeviceGroupMonitorVO aOneOutTemp = new IotDeviceGroupMonitorVO();
-                            aOneOutTemp.setModelName("液驱A缸一级出口温度");
+                            aOneOutTemp.setModelName("A缸一级出口温度");
                             aOneOutTemp.setValue("");
                             monitors.add(aOneOutTemp);
                             IotDeviceGroupMonitorVO aOneColdTemp = new IotDeviceGroupMonitorVO();
-                            aOneColdTemp.setModelName("液驱A缸一级冷却后温度");
+                            aOneColdTemp.setModelName("A缸一级冷却后温度");
                             aOneColdTemp.setValue("");
                             monitors.add(aOneColdTemp);
                             IotDeviceGroupMonitorVO aTwoEnterPressure = new IotDeviceGroupMonitorVO();
@@ -705,4 +743,21 @@ public class IotDeviceGroupController {
                 .orElse(""); // 无“空压”/输入null时返回空字符串
     }
 
+    /**
+     * J仅基于“PSA”截取字符串,不依赖任何其他分隔符
+     * @param input 原始字符串
+     * @return 截取结果(无匹配返回空字符串)
+     */
+    private static String getModelNamePrefix(String input, String prefix) {
+        Pattern PSA_PATTERN = Pattern.compile(prefix);
+        return Optional.ofNullable(input)          // 处理输入为null的情况
+                .filter(str -> str.contains(prefix)) // 仅判断是否包含“空压”
+                .map(str -> {
+                    Matcher matcher = PSA_PATTERN.matcher(str);
+                    // 找到第一个匹配的“PSA”子串,无则返回空
+                    return matcher.find() ? matcher.group() : "";
+                })
+                .orElse(""); // 无“PSA”/输入null时返回空字符串
+    }
+
 }

+ 111 - 19
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/iotrddailyreport/IotRdDailyReportController.java

@@ -75,6 +75,7 @@ import java.time.temporal.ChronoUnit;
 import java.util.*;
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.stream.Collectors;
+import java.util.stream.Stream;
 
 import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.EXPORT;
 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
@@ -2321,6 +2322,12 @@ public class IotRdDailyReportController {
                 constructStatusPair.put(data.getValue(), data.getLabel());
             });
         }
+        // 设置非生产时间标识
+        Map<String, Boolean> reportNonProductFlagPair = new HashMap<>();
+        // key平台井标识  value非生产时间累计和列表
+        Map<String, List<BigDecimal>> platformNonProductPair = new HashMap<>();
+        // key平台井标识  value平台井非生产时效集合
+        Map<String, BigDecimal> platformNptPair = new HashMap<>();
         DataPermissionUtils.executeIgnore(() -> {
             // 查询日报关联的项目信息
             IotProjectInfoPageReqVO reqVO = new IotProjectInfoPageReqVO();
@@ -2389,6 +2396,7 @@ public class IotRdDailyReportController {
                     }
                 }
             }
+
             // 平台井 主井施工完成 需要显示 关联井的施工状态 井号
             if (CollUtil.isNotEmpty(relatedWellReports)) {
                 Map<String, IotRdDailyReportDO> relatedPlatformGroupPair = new HashMap<>();
@@ -2398,6 +2406,27 @@ public class IotRdDailyReportController {
                         if (!relatedPlatformGroupPair.containsKey(report.getPlatformGroup())) {
                             relatedPlatformGroupPair.put(report.getPlatformGroup(), report);
                         }
+                        // 查询关联井的 非生产时间填写情况 只要有1个关联井填写了 非生产时间 就显示为 已填写
+                        IotRdDailyReportRespVO reportRespVO = BeanUtils.toBean(report, IotRdDailyReportRespVO.class);
+                        Boolean flag = setNoProductFlag(reportRespVO);
+                        if (flag) {
+                            reportNonProductFlagPair.put(report.getPlatformGroup(), true);
+                        }
+                        // 设置平台井 的非生产时效 所有 井数据 累加平均
+                        if (CollUtil.isNotEmpty(report.getExtProperty()) || StrUtil.isNotBlank(report.getRdStatus())) {
+                            // 说明当前日报设置过 工作量 施工状态
+                            IotRdDailyReportRespVO rdDailyReportResp = BeanUtils.toBean(report, IotRdDailyReportRespVO.class);
+                            BigDecimal nonProductTime = calculateNonProductTime(rdDailyReportResp);
+                            if (platformNonProductPair.containsKey(report.getPlatformGroup())) {
+                                List<BigDecimal> tempSumNpts = platformNonProductPair.get(report.getPlatformGroup());
+                                tempSumNpts.add(nonProductTime);
+                                platformNonProductPair.put(report.getPlatformGroup(), tempSumNpts);
+                            } else {
+                                List<BigDecimal> tempSumNpts = new ArrayList<>();
+                                tempSumNpts.add(nonProductTime);
+                                platformNonProductPair.put(report.getPlatformGroup(), tempSumNpts);
+                            }
+                        }
                     }
                 });
                 relatedWellReports.forEach(report -> {
@@ -2479,6 +2508,25 @@ public class IotRdDailyReportController {
                     taskSubmitterPair.put(task.getId(), submitterNames);
                 });
             }
+            // 统计计算出平台井中每个井的 非生产时效
+            if (CollUtil.isNotEmpty(platformNonProductPair)) {
+                platformNonProductPair.forEach((platformGroup, npts) -> {
+                    // npts是各平台井的非生产时间累计和集合
+                    // 1. 计算分子:集合中所有BigDecimal元素的总和
+                    BigDecimal numerator = npts.stream()
+                            .reduce(BigDecimal.ZERO, BigDecimal::add);
+                    int denominatorInt = npts.size() * 24;
+                    BigDecimal denominator = BigDecimal.valueOf(denominatorInt);
+                    BigDecimal nonProductionRate;
+                    if (denominator.compareTo(BigDecimal.ZERO) == 0) {
+                        nonProductionRate = BigDecimal.ZERO; // 分母为0时比率设为0
+                    } else {
+                        // 除法:指定精度(保留4位小数)和舍入模式(四舍五入),可根据业务调整
+                        nonProductionRate = numerator.divide(denominator, 4, RoundingMode.HALF_UP);
+                    }
+                    platformNptPair.put(platformGroup, nonProductionRate);
+                } );
+            }
             // 查询所有任务的工作量数据 单位相同的工作量属性值合并处理
             for (IotRdDailyReportDO report : reports) {
                 // 设置每个任务的工作量数据  单位相同的工作量值作合并处理
@@ -2564,29 +2612,17 @@ public class IotRdDailyReportController {
                     reportVO.setRdStatusLabel(constructStatusPair.get(reportVO.getRdStatus()));
                 }
             }
-            BigDecimal accidentTime = reportVO.getAccidentTime();
-            BigDecimal repairTime = reportVO.getRepairTime();
-            BigDecimal selfStopTime = reportVO.getSelfStopTime();
-            BigDecimal complexityTime = reportVO.getComplexityTime();
-            BigDecimal relocationTime = reportVO.getRelocationTime();
-            BigDecimal rectificationTime = reportVO.getRectificationTime();
-            BigDecimal waitingStopTime = reportVO.getWaitingStopTime();
-            BigDecimal winterBreakTime = reportVO.getWinterBreakTime();
-            BigDecimal partyaDesignTime = reportVO.getPartyaDesign();
-            BigDecimal partyaPrepareTime = reportVO.getPartyaPrepare();
-            BigDecimal partyaResourceTime = reportVO.getPartyaResource();
-            BigDecimal otherNptTime = reportVO.getOtherNptTime();
-            if (accidentTime.compareTo(BigDecimal.ZERO) > 0 || repairTime.compareTo(BigDecimal.ZERO) > 0 || selfStopTime.compareTo(BigDecimal.ZERO) > 0
-            || complexityTime.compareTo(BigDecimal.ZERO) > 0 || relocationTime.compareTo(BigDecimal.ZERO) > 0 || rectificationTime.compareTo(BigDecimal.ZERO) > 0
-            || waitingStopTime.compareTo(BigDecimal.ZERO) > 0 || winterBreakTime.compareTo(BigDecimal.ZERO) > 0 || partyaDesignTime.compareTo(BigDecimal.ZERO) > 0
-            || partyaPrepareTime.compareTo(BigDecimal.ZERO) > 0 || partyaResourceTime.compareTo(BigDecimal.ZERO) > 0 || otherNptTime.compareTo(BigDecimal.ZERO) > 0) {
-                // 设置非生产时间填写标识
-                reportVO.setNonProductFlag(true);
-            }
+            // 计算非生产时效 如果是平台井 需要计算 所有平台井 的 非生产时效
+            BigDecimal nonProductionTimes = calculateNonProductTime(reportVO);
+            reportVO.setNonProductionRate(nonProductionTimes.divide(BigDecimal.valueOf(24), 4, RoundingMode.HALF_UP ));
+            // 设置非生产时间填写标识 noProductFlag 为 true 或者 processInstanceId 为 2 的时候 显示 已填写
+            reportVO.setNonProductFlag(setNoProductFlag(reportVO));
             // 创建时间 格式化 yyyy-MM-dd
             if (ObjUtil.isNotEmpty(reportVO.getCreateTime())) {
                 reportVO.setCreateTimeStr(LocalDateTimeUtil.format(reportVO.getCreateTime(), DatePattern.NORM_DATE_PATTERN));
             }
+            // 平台井 非生产时效
+            findAndThen(platformNptPair, reportVO.getPlatformGroup(), npt -> reportVO.setNonProductionRate(npt));
             // 部门信息 任务中关联的施工队伍
             findAndThen(taskTeamsPair, reportVO.getTaskId(), deptNames -> reportVO.setDeptName(deptNames));
             // 日报关联的项目信息
@@ -2595,6 +2631,8 @@ public class IotRdDailyReportController {
             findAndThen(taskPair, reportVO.getTaskId(), taskName -> reportVO.setTaskName(taskName));
             // 日报关联的任务信息(兼容主井完工 关联井未完工的情况)
             findAndThen(relatedPlatformPair, reportVO.getPlatformGroup(), relatedTaskName -> reportVO.setTaskName(relatedTaskName));
+            // 平台井相关的非生产时间标识
+            findAndThen(reportNonProductFlagPair, reportVO.getPlatformGroup(), nonProductFlag -> reportVO.setNonProductFlag(nonProductFlag));
             // 日报关联的任务施工状态(兼容主井完工 关联井未完工的情况)
             findAndThen(relatedWellStatusPair, reportVO.getPlatformGroup(), rdStatus -> reportVO.setRdStatus(rdStatus));
             // 日报关联的责任人
@@ -2604,6 +2642,60 @@ public class IotRdDailyReportController {
         });
     }
 
+    /**
+     *  检测是否已经维护了生产时效
+     * @param dailyReport
+     * @return
+     */
+    private Boolean setNoProductFlag(IotRdDailyReportRespVO dailyReport){
+        BigDecimal accidentTime = dailyReport.getAccidentTime();
+        BigDecimal repairTime = dailyReport.getRepairTime();
+        BigDecimal selfStopTime = dailyReport.getSelfStopTime();
+        BigDecimal complexityTime = dailyReport.getComplexityTime();
+        BigDecimal relocationTime = dailyReport.getRelocationTime();
+        BigDecimal rectificationTime = dailyReport.getRectificationTime();
+        BigDecimal waitingStopTime = dailyReport.getWaitingStopTime();
+        BigDecimal winterBreakTime = dailyReport.getWinterBreakTime();
+        BigDecimal partyaDesignTime = dailyReport.getPartyaDesign();
+        BigDecimal partyaPrepareTime = dailyReport.getPartyaPrepare();
+        BigDecimal partyaResourceTime = dailyReport.getPartyaResource();
+        BigDecimal otherNptTime = dailyReport.getOtherNptTime();
+        if (accidentTime.compareTo(BigDecimal.ZERO) > 0 || repairTime.compareTo(BigDecimal.ZERO) > 0 || selfStopTime.compareTo(BigDecimal.ZERO) > 0
+                || complexityTime.compareTo(BigDecimal.ZERO) > 0 || relocationTime.compareTo(BigDecimal.ZERO) > 0 || rectificationTime.compareTo(BigDecimal.ZERO) > 0
+                || waitingStopTime.compareTo(BigDecimal.ZERO) > 0 || winterBreakTime.compareTo(BigDecimal.ZERO) > 0 || partyaDesignTime.compareTo(BigDecimal.ZERO) > 0
+                || partyaPrepareTime.compareTo(BigDecimal.ZERO) > 0 || partyaResourceTime.compareTo(BigDecimal.ZERO) > 0 || otherNptTime.compareTo(BigDecimal.ZERO) > 0) {
+            // 设置非生产时间填写标识
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     *  计算非生产时间累加值 计算非生产时效
+     * @param dailyReport
+     * @return
+     */
+    private BigDecimal calculateNonProductTime(IotRdDailyReportRespVO dailyReport){
+        return Stream.of(
+                        dailyReport.getAccidentTime(),
+                        dailyReport.getRepairTime(),
+                        dailyReport.getSelfStopTime(),
+                        dailyReport.getComplexityTime(),
+                        dailyReport.getRelocationTime(),
+                        dailyReport.getRectificationTime(),
+                        dailyReport.getWaitingStopTime(),
+                        dailyReport.getWinterBreakTime(),
+                        dailyReport.getPartyaDesign(),    // 注:字段名虽无Time但属于非生产时间,保留
+                        dailyReport.getPartyaPrepare(),
+                        dailyReport.getPartyaResource(),
+                        dailyReport.getOtherNptTime()
+                )
+                // 处理null值,避免调用add()时抛出NullPointerException
+                .map(bd -> Objects.isNull(bd) ? BigDecimal.ZERO : bd)
+                // Stream.reduce:从初始值0开始,依次累加所有元素
+                .reduce(BigDecimal.ZERO, BigDecimal::add);
+    }
+
     @GetMapping("/taskActualProgress")
     @Operation(summary = "查询日报所属任务的实际进度")
     @PreAuthorize("@ss.hasPermission('pms:iot-rd-daily-report:query')")

+ 3 - 0
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/iotrddailyreport/vo/IotRdDailyReportRespVO.java

@@ -333,4 +333,7 @@ public class IotRdDailyReportRespVO {
 
     @Schema(description = "小组内最后1条记录标识 true false")
     private boolean lastGroupIdFlag = false;
+
+    @Schema(description = "非生产时效")
+    private BigDecimal nonProductionRate;
 }

+ 3 - 0
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/iotrddailyreport/vo/IotRdDailyReportStatisticsRespVO.java

@@ -121,4 +121,7 @@ public class IotRdDailyReportStatisticsRespVO {
     @Schema(description = "压裂井数")
     @ExcelProperty("压裂井数")
     private Integer ylWellCount;
+
+    @Schema(description = "非生产时效")
+    private BigDecimal nonProductionRate;
 }

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

@@ -11,6 +11,7 @@ import lombok.Data;
 import java.math.BigDecimal;
 import java.time.LocalDateTime;
 import java.util.List;
+import java.util.Map;
 
 @Schema(description = "管理后台 - 设备台账 Response VO")
 @Data
@@ -214,6 +215,12 @@ public class IotDeviceRespVO {
     @Schema(description = "模板中涉及多个累计运行公里数的属性集合")
     private List<IotDeviceRunLogRespVO> mileageAccumulatedAttrs;
 
+    @Schema(description = "设备多个属性累计运转时长集合")
+    private Map<String, BigDecimal> multiAttrsTotalRuntime;
+
+    @Schema(description = "设备多个属性累计运行公里数集合")
+    private Map<String, BigDecimal> multiAttrsTotalMileage;
+
     @Schema(description = "启用日期")
     @ExcelProperty("投运日期")
     private String enableDate;

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

@@ -485,6 +485,13 @@ public class IotMainWorkOrderServiceImpl implements IotMainWorkOrderService {
         Map<Long, List<Map<String, Object>>> orderDistancePair = new HashMap<>();
         // 设备保养明细 key设备id  value设备保养工单明细下所有保养规则数据最小值
         Map<Long, String> resultMap = new HashMap<>();
+        // 设置每个设备的 累计运转时长 累计运转公里数 保养查询列表使用
+        Map<Long, BigDecimal> deviceRunningTimePair = new HashMap<>();
+        Map<Long, BigDecimal> deviceRunningKiloPair = new HashMap<>();
+        // 多属性累计运行时长
+        Map<Long, Map<String, BigDecimal>> multiAttrRunningTimePair = new HashMap<>();
+        // 多属性累计运行里程
+        Map<Long, Map<String, BigDecimal>> multiAttrRunningKiloPair = new HashMap<>();
         // 记录保养项的 提前量 key设备id-保养项id-距离保养值   value提前量
         Map<String, BigDecimal> bomLeadPair = new HashMap<>();
         if (CollUtil.isNotEmpty(mainBomS)) {
@@ -499,11 +506,25 @@ public class IotMainWorkOrderServiceImpl implements IotMainWorkOrderService {
                     BigDecimal totalRunTime = BigDecimal.ZERO;
                     if (deviceRunLogMap.containsKey(bom.getDeviceId())) {
                         totalRunTime = deviceRunLogMap.get(bom.getDeviceId()).getTotalRunTime();
+                        // 单一累计运行时长集合
+                        deviceRunningTimePair.put(bom.getDeviceId(), totalRunTime);
                     } else {
                         // 运行记录模板中包含多个累计时长 公里数类型的属性
                         String uniqueKey = StrUtil.join("-", bom.getDeviceId(), bom.getCode());
                         if (tempTotalRunDataPair.containsKey(uniqueKey)) {
                             totalRunTime = tempTotalRunDataPair.get(uniqueKey);
+                            // 设置多属性累计运行时长集合
+                            if (StrUtil.isNotBlank(bom.getCode())) {
+                                if (multiAttrRunningTimePair.containsKey(bom.getDeviceId())) {
+                                    Map<String, BigDecimal> tempRunningTimePair = multiAttrRunningTimePair.get(bom.getDeviceId());
+                                    tempRunningTimePair.put(bom.getCode(), totalRunTime);
+                                    multiAttrRunningTimePair.put(bom.getDeviceId(), tempRunningTimePair);
+                                } else {
+                                    Map<String, BigDecimal> tempRunningTimePair = new HashMap<>();
+                                    tempRunningTimePair.put(bom.getCode(), totalRunTime);
+                                    multiAttrRunningTimePair.put(bom.getDeviceId(), tempRunningTimePair);
+                                }
+                            }
                         }
                     }
                     BigDecimal lastRunningTime = bom.getLastRunningTime();      // 上次保养运行时间
@@ -518,11 +539,25 @@ public class IotMainWorkOrderServiceImpl implements IotMainWorkOrderService {
                     BigDecimal totalMileage = BigDecimal.ZERO;
                     if (deviceRunLogMap.containsKey(bom.getDeviceId())) {
                         totalMileage = deviceRunLogMap.get(bom.getDeviceId()).getTotalMileage();
+                        // 单一累计运行里程集合
+                        deviceRunningKiloPair.put(bom.getDeviceId(), totalMileage);
                     } else {
                         // 运行记录模板中包含多个累计时长 公里数类型的属性
                         String uniqueKey = StrUtil.join("-", bom.getDeviceId(), bom.getType());
                         if (tempTotalRunDataPair.containsKey(uniqueKey)) {
                             totalMileage = tempTotalRunDataPair.get(uniqueKey);
+                            // 设置多属性累计运行里程集合
+                            if (StrUtil.isNotBlank(bom.getType())) {
+                                if (multiAttrRunningKiloPair.containsKey(bom.getDeviceId())) {
+                                    Map<String, BigDecimal> tempRunningKiloPair = multiAttrRunningKiloPair.get(bom.getDeviceId());
+                                    tempRunningKiloPair.put(bom.getType(), totalMileage);
+                                    multiAttrRunningKiloPair.put(bom.getDeviceId(), tempRunningKiloPair);
+                                } else {
+                                    Map<String, BigDecimal> tempRunningKiloPair = new HashMap<>();
+                                    tempRunningKiloPair.put(bom.getCode(), totalMileage);
+                                    multiAttrRunningKiloPair.put(bom.getDeviceId(), tempRunningKiloPair);
+                                }
+                            }
                         }
                     }
                     BigDecimal lastRunningKilo = bom.getLastRunningKilometers();      // 上次保养运行里程
@@ -704,6 +739,20 @@ public class IotMainWorkOrderServiceImpl implements IotMainWorkOrderService {
                     if (shouldWorkOrderFlags.contains(device.getId())) {
                         device.setShouldWorkOrder(true);
                     }
+                    // 设置每个设备 不同保养项 的 累计运转时间 累计运转公里数
+                    if (deviceRunningTimePair.containsKey(device.getId())) {
+                        device.setTotalRunTime(deviceRunningTimePair.get(device.getId()));
+                    }
+                    if (deviceRunningKiloPair.containsKey(device.getId())) {
+                        device.setTotalMileage(deviceRunningKiloPair.get(device.getId()));
+                    }
+                    // 设置多属性累计值集合
+                    if (multiAttrRunningTimePair.containsKey(device.getId())) {
+                        device.setMultiAttrsTotalRuntime(multiAttrRunningTimePair.get(device.getId()));
+                    }
+                    if (multiAttrRunningKiloPair.containsKey(device.getId())) {
+                        device.setMultiAttrsTotalMileage(multiAttrRunningKiloPair.get(device.getId()));
+                    }
                 });
             }
             return new PageResult<>(page.getRecords(), page.getTotal());

+ 87 - 8
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/service/iotrddailyreport/IotRdDailyReportServiceImpl.java

@@ -61,7 +61,9 @@ import java.time.temporal.ChronoUnit;
 import java.util.*;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicReference;
 import java.util.stream.Collectors;
+import java.util.stream.Stream;
 
 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
 import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
@@ -130,10 +132,17 @@ public class IotRdDailyReportServiceImpl implements IotRdDailyReportService {
         }
         // 更新
         IotRdDailyReportDO updateObj = BeanUtils.toBean(updateReqVO, IotRdDailyReportDO.class);
-        // 设置 日报填写状态 保存 已完成
-        updateObj.setStatus(1);
-        // 设置 日报审批状态为 审批中 auditStatus = 10
-        updateObj.setAuditStatus(10);
+        // 如果是修改 非生产时间 ,则不必再发起审批
+        if (StrUtil.isBlank(updateReqVO.getNonProduct())) {
+            // 设置 日报填写状态 保存 已完成
+            updateObj.setStatus(1);
+            // 设置 日报审批状态为 审批中 auditStatus = 10
+            updateObj.setAuditStatus(10);
+        }
+        // 如果 修改 了时效 只要保存 不管是否 填写了 非生产时间 都确认为已经 维护了 非生产时间
+        if (StrUtil.isNotBlank(updateReqVO.getNonProduct())) {
+            updateObj.setProcessInstanceId("2");
+        }
         iotRdDailyReportMapper.updateById(updateObj);
         // 保存油耗信息
         if (CollUtil.isNotEmpty(updateReqVO.getReportFuels())) {
@@ -510,6 +519,8 @@ public class IotRdDailyReportServiceImpl implements IotRdDailyReportService {
             // 以任务为单位组装任务关联的日报的当日油耗总和
             // key任务id   value任务关联的日报油耗总和
             Map<Long, BigDecimal> taskFuelPair = new HashMap<>();
+            // key任务id  value多个非生产时间累计值
+            Map<Long, List<BigDecimal>> taskNonProductValuesPair = new HashMap<>();
 
             // 设置 小队 任务已经完成的工作量集合 (按照不同的单位统计任务的不同工作量)
             // key任务井id      value队伍工作量数据
@@ -533,6 +544,18 @@ public class IotRdDailyReportServiceImpl implements IotRdDailyReportService {
                     taskFuelPair.put(report.getTaskId(), dailyFuel);
                 }
 
+                // 统计每个日报的 非生产时效 任务的非生产时效 任务关联的日报的 sum(非生产时间)/24n
+                BigDecimal sumNpt = calculateNonProductTime(report);
+                if (taskNonProductValuesPair.containsKey(report.getTaskId())) {
+                    List<BigDecimal> tempNptValues = taskNonProductValuesPair.get(report.getTaskId());
+                    tempNptValues.add(sumNpt);
+                    taskNonProductValuesPair.put(report.getTaskId(), tempNptValues);
+                } else {
+                    List<BigDecimal> tempNptValues = new ArrayList<>();
+                    tempNptValues.add(sumNpt);
+                    taskNonProductValuesPair.put(report.getTaskId(), tempNptValues);
+                }
+
                 // 设置每个任务的工作量数据  单位相同的工作量值作合并处理
                 List<IotTaskAttrModelProperty> taskAttrs = report.getExtProperty();
                 Long taskId = report.getTaskId();
@@ -669,6 +692,26 @@ public class IotRdDailyReportServiceImpl implements IotRdDailyReportService {
                     /* if (teamDeptPair.containsKey(deptId)) {
                         uniqueReport.setDeptName(teamDeptPair.get(deptId));
                     } */
+                    // 任务 非生产时间 加和 相除
+                    if (taskNonProductValuesPair.containsKey(taskId)) {
+                        List<BigDecimal> tempNptValues = taskNonProductValuesPair.get(taskId);
+                        // 根据集合 tempNptValues 计算 分母天数
+                        // 1. 计算分子:集合中所有BigDecimal元素的总和
+                        BigDecimal numerator = tempNptValues.stream()
+                                .reduce(BigDecimal.ZERO, BigDecimal::add);
+                        // 2. 计算分母:size * 24(转为BigDecimal避免类型问题)
+                        int denominatorInt = tempNptValues.size() * 24;
+                        BigDecimal denominator = BigDecimal.valueOf(denominatorInt);
+                        // 3. 计算比率:处理分母为0的情况,避免除零异常
+                        BigDecimal nonProductionRate;
+                        if (denominator.compareTo(BigDecimal.ZERO) == 0) {
+                            nonProductionRate = BigDecimal.ZERO; // 分母为0时比率设为0
+                        } else {
+                            // 除法:指定精度(保留4位小数)和舍入模式(四舍五入),可根据业务调整
+                            nonProductionRate = numerator.divide(denominator, 4, RoundingMode.HALF_UP);
+                        }
+                        uniqueReport.setNonProductionRate(nonProductionRate);
+                    }
                     uniqueReport.setTaskId(taskId);
                     if (taskDeptNamePair.containsKey(taskId)) {
                         uniqueReport.setDeptName(taskDeptNamePair.get(taskId));
@@ -775,6 +818,32 @@ public class IotRdDailyReportServiceImpl implements IotRdDailyReportService {
         return result;
     }
 
+    /**
+     *  计算非生产时间累加值 计算非生产时效
+     * @param dailyReport
+     * @return
+     */
+    private BigDecimal calculateNonProductTime(IotRdDailyReportDO dailyReport){
+        return Stream.of(
+                        dailyReport.getAccidentTime(),
+                        dailyReport.getRepairTime(),
+                        dailyReport.getSelfStopTime(),
+                        dailyReport.getComplexityTime(),
+                        dailyReport.getRelocationTime(),
+                        dailyReport.getRectificationTime(),
+                        dailyReport.getWaitingStopTime(),
+                        dailyReport.getWinterBreakTime(),
+                        dailyReport.getPartyaDesign(),    // 注:字段名虽无Time但属于非生产时间,保留
+                        dailyReport.getPartyaPrepare(),
+                        dailyReport.getPartyaResource(),
+                        dailyReport.getOtherNptTime()
+                )
+                // 处理null值,避免调用add()时抛出NullPointerException
+                .map(bd -> Objects.isNull(bd) ? BigDecimal.ZERO : bd)
+                // Stream.reduce:从初始值0开始,依次累加所有元素
+                .reduce(BigDecimal.ZERO, BigDecimal::add);
+    }
+
     @Override
     public List<IotRdDailyReportStatisticsRespVO> summaryStatistics(IotRdDailyReportPageReqVO pageReqVO) {
         List<IotRdDailyReportStatisticsRespVO> result = new ArrayList<>();
@@ -2190,7 +2259,12 @@ public class IotRdDailyReportServiceImpl implements IotRdDailyReportService {
         List<IotRdDailyReportDO> mainPlatformReports = new ArrayList<>();
         // 关联井日报
         List<IotRdDailyReportDO> relatePlatformReports = new ArrayList<>();
+        // 维护非生产时间标识 nonProduct
+        AtomicReference<String> nonProduct = new AtomicReference<>(StrUtil.EMPTY);
         reports.forEach(report -> {
+            if (StrUtil.isNotBlank(report.getNonProduct())) {
+                nonProduct.set(report.getNonProduct());
+            }
             IotRdDailyReportDO updatedReport = updateIotRdDailyReport(report);
             // 标识当前任务井是 普通井 或 平台井主井 关联的任务审批人发送提醒消息
             if (1 == updatedReport.getPlatformWell() || 0 == updatedReport.getPlatformWell()) {
@@ -2219,10 +2293,15 @@ public class IotRdDailyReportServiceImpl implements IotRdDailyReportService {
             List<IotRdDailyReportDO> mainWellReports = iotRdDailyReportMapper.dailyReports(reqVO);
             if (CollUtil.isNotEmpty(mainWellReports)) {
                 IotRdDailyReportDO mainWellReport = mainWellReports.get(0);
-                // 设置 日报审批状态为 审批中 auditStatus = 10
-                mainWellReport.setAuditStatus(10);
-                // 设置 日报填写状态 保存 已完成
-                mainWellReport.setStatus(1);
+                if (StrUtil.isBlank(nonProduct.get())) {
+                    // 不是在维护非生产时间
+                    // 设置 日报审批状态为 审批中 auditStatus = 10
+                    mainWellReport.setAuditStatus(10);
+                    // 设置 日报填写状态 保存 已完成
+                    mainWellReport.setStatus(1);
+                } else {
+                    mainWellReport.setProcessInstanceId("2");
+                }
                 iotRdDailyReportMapper.updateById(mainWellReport);
             }
         }