Parcourir la source

pms 瑞都日报 项目任务基本信息完善 任务进度

zhangcl il y a 2 jours
Parent
commit
29335675b3

+ 206 - 1
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/iotprojecttask/IotProjectTaskController.java

@@ -14,10 +14,16 @@ import cn.iocoder.yudao.module.pms.controller.admin.iotprojecttask.vo.IotProject
 import cn.iocoder.yudao.module.pms.controller.admin.iotprojecttask.vo.IotProjectTaskPlatformVO;
 import cn.iocoder.yudao.module.pms.controller.admin.iotprojecttask.vo.IotProjectTaskRespVO;
 import cn.iocoder.yudao.module.pms.controller.admin.iotprojecttask.vo.IotTaskSaveVO;
+import cn.iocoder.yudao.module.pms.controller.admin.iotrddailyreport.vo.IotRdDailyReportPageReqVO;
+import cn.iocoder.yudao.module.pms.controller.admin.iotrddailyreport.vo.IotRdDailyReportStatisticsItemVO;
 import cn.iocoder.yudao.module.pms.dal.dataobject.iotprojectinfo.IotProjectInfoDO;
 import cn.iocoder.yudao.module.pms.dal.dataobject.iotprojecttask.IotProjectTaskDO;
+import cn.iocoder.yudao.module.pms.dal.dataobject.iotprojecttaskattrs.IotTaskAttrModelProperty;
+import cn.iocoder.yudao.module.pms.dal.dataobject.iotrddailyreport.IotRdDailyReportDO;
+import cn.iocoder.yudao.module.pms.dal.mysql.iotrddailyreport.IotRdDailyReportMapper;
 import cn.iocoder.yudao.module.pms.service.iotprojectinfo.IotProjectInfoService;
 import cn.iocoder.yudao.module.pms.service.iotprojecttask.IotProjectTaskService;
+import cn.iocoder.yudao.module.pms.service.iotrddailyreport.IotRdDailyReportService;
 import cn.iocoder.yudao.module.system.dal.dataobject.dept.DeptDO;
 import cn.iocoder.yudao.module.system.service.dept.DeptService;
 import io.swagger.v3.oas.annotations.Operation;
@@ -31,6 +37,7 @@ import javax.annotation.Resource;
 import javax.servlet.http.HttpServletResponse;
 import javax.validation.Valid;
 import java.io.IOException;
+import java.math.BigDecimal;
 import java.util.*;
 
 import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.EXPORT;
@@ -52,6 +59,10 @@ public class IotProjectTaskController {
 
     @Resource
     private IotProjectInfoService iotProjectInfoService;
+    @Resource
+    private IotRdDailyReportMapper iotRdDailyReportMapper;
+    @Resource
+    private IotRdDailyReportService iotRdDailyReportService;
 
     @PostMapping("/create")
     @Operation(summary = "创建项目信息任务拆分")
@@ -110,6 +121,138 @@ public class IotProjectTaskController {
             return Collections.emptyList();
         }
         Map<Long, List<IotProjectTaskPlatformVO>> platformWellPair = new HashMap<>();
+        // 查询每口井的已完成工作量
+        IotRdDailyReportPageReqVO reportReqVO = new IotRdDailyReportPageReqVO();
+        reportReqVO.setTaskIds(convertList(pagedTasks, IotProjectTaskDO::getId));
+        List<IotRdDailyReportDO> dailyReports = iotRdDailyReportMapper.dailyReports(reportReqVO);
+        // key任务井id      value队伍工作量数据
+        Map<Long, BigDecimal> bridgePlugPair = new HashMap<>();
+        Map<Long, BigDecimal> runCountPair = new HashMap<>();
+        Map<Long, BigDecimal> cumulativeWorkingWellPair = new HashMap<>();
+        Map<Long, BigDecimal> hourCountPair = new HashMap<>();
+        Map<Long, BigDecimal> waterVolumePair = new HashMap<>();
+        Map<Long, BigDecimal> pumpTripsPair = new HashMap<>();
+        Map<Long, BigDecimal> cumulativeWorkingLayersPair = new HashMap<>();
+        Map<Long, BigDecimal> mixSandPair = new HashMap<>();
+        if (CollUtil.isNotEmpty(dailyReports)) {
+            dailyReports.forEach(report -> {
+                // 设置每个任务的工作量数据  单位相同的工作量值作合并处理
+                List<IotTaskAttrModelProperty> taskAttrs = report.getExtProperty();
+                // 暂存不同单位的工作量属性值
+                BigDecimal tempTotalBridgePlug = BigDecimal.ZERO;               // 桥塞(个数)
+                BigDecimal tempTotalRunCount = BigDecimal.ZERO;                 // 趟数
+                BigDecimal tempTotalCumulativeWorkingWell = BigDecimal.ZERO;    // 井数
+                BigDecimal tempTotalHourCount = BigDecimal.ZERO;                // 小时H
+                BigDecimal tempTotalWaterVolume = BigDecimal.ZERO;              // 水方量(方)
+                BigDecimal tempTotalPumpTrips = BigDecimal.ZERO;
+                BigDecimal tempTotalCumulativeWorkingLayers = BigDecimal.ZERO;  // 段数  累计施工-层
+                BigDecimal tempTotalMixSand = BigDecimal.ZERO;                  // 台次 当日泵车台次 当日仪表/混砂
+                if (CollUtil.isNotEmpty(taskAttrs)) {
+                    for (IotTaskAttrModelProperty attr : taskAttrs) {
+                        String unit = attr.getUnit();   // 工作量单位
+                        String actualValueStr = attr.getActualValue();  // 工作量属性的实际值
+                        // 处理实际值:避免null或非数字字符串导致的异常
+                        BigDecimal actualValue = BigDecimal.ZERO;
+                        if (StrUtil.isNotBlank(actualValueStr)) {  // 假设使用Hutool的StrUtil,或自行判断null/空
+                            try {
+                                actualValue = new BigDecimal(actualValueStr);
+                            } catch (NumberFormatException e) {
+                                // 若字符串格式错误,默认按0处理(可根据业务调整)
+                                actualValue = BigDecimal.ZERO;
+                            }
+                        }
+                        if ("个数".equals(unit)) {
+                            // 钻可溶桥塞  钻复合桥塞
+                            tempTotalBridgePlug = tempTotalBridgePlug.add(actualValue);
+                            if (bridgePlugPair.containsKey(report.getTaskId())) {
+                                BigDecimal tempBridgePlug = bridgePlugPair.get(report.getTaskId());
+                                bridgePlugPair.put(report.getTaskId(), tempTotalBridgePlug.add(tempBridgePlug));
+                            } else {
+                                bridgePlugPair.put(report.getTaskId(), tempTotalBridgePlug);
+                            }
+                        }
+                        if ("趟数".equals(unit)) {
+                            tempTotalRunCount = tempTotalRunCount.add(actualValue);
+                            if (runCountPair.containsKey(report.getTaskId())) {
+                                BigDecimal tempRunCount = runCountPair.get(report.getTaskId());
+                                runCountPair.put(report.getTaskId(), tempTotalRunCount.add(tempRunCount));
+                            } else {
+                                runCountPair.put(report.getTaskId(), tempTotalRunCount);
+                            }
+                        }
+                        if ("小时".equals(unit)) {
+                            tempTotalHourCount = tempTotalHourCount.add(actualValue);
+                            if (hourCountPair.containsKey(report.getTaskId())) {
+                                BigDecimal tempHourCount = hourCountPair.get(report.getTaskId());
+                                hourCountPair.put(report.getTaskId(), tempTotalHourCount.add(tempHourCount));
+                            } else {
+                                hourCountPair.put(report.getTaskId(), tempTotalHourCount);
+                            }
+                        }
+                        if ("天数".equals(unit)) {
+                            // 将 actualValue 换算成 H
+                            BigDecimal hours = actualValue.multiply(new BigDecimal("24"));
+                            tempTotalHourCount = tempTotalHourCount.add(hours);
+                            if (hourCountPair.containsKey(report.getTaskId())) {
+                                BigDecimal tempHourCount = hourCountPair.get(report.getTaskId());
+                                hourCountPair.put(report.getTaskId(), tempTotalHourCount.add(tempHourCount));
+                            } else {
+                                hourCountPair.put(report.getTaskId(), tempTotalHourCount);
+                            }
+                        }
+                        if ("方".equals(unit)) {
+                            tempTotalWaterVolume = tempTotalWaterVolume.add(actualValue);
+                            if (waterVolumePair.containsKey(report.getTaskId())) {
+                                BigDecimal tempWaterVolume = waterVolumePair.get(report.getTaskId());
+                                waterVolumePair.put(report.getTaskId(), tempTotalWaterVolume.add(tempWaterVolume));
+                            } else {
+                                waterVolumePair.put(report.getTaskId(), tempTotalWaterVolume);
+                            }
+                        }
+                        if ("井数".equals(unit)) {
+                            tempTotalCumulativeWorkingWell = tempTotalCumulativeWorkingWell.add(actualValue);
+                            if (cumulativeWorkingWellPair.containsKey(report.getTaskId())) {
+                                BigDecimal tempWorkingWell = cumulativeWorkingWellPair.get(report.getTaskId());
+                                cumulativeWorkingWellPair.put(report.getTaskId(), tempTotalCumulativeWorkingWell.add(tempWorkingWell));
+                            } else {
+                                cumulativeWorkingWellPair.put(report.getTaskId(), tempTotalCumulativeWorkingWell);
+                            }
+                        }
+                        if ("段数".equals(unit)) {
+                            // 累计施工层
+                            tempTotalCumulativeWorkingLayers = tempTotalCumulativeWorkingLayers.add(actualValue);
+                            if (cumulativeWorkingLayersPair.containsKey(report.getTaskId())) {
+                                BigDecimal tempWorkingLayer = cumulativeWorkingLayersPair.get(report.getTaskId());
+                                cumulativeWorkingLayersPair.put(report.getTaskId(), tempTotalCumulativeWorkingLayers.add(tempWorkingLayer));
+                            } else {
+                                cumulativeWorkingLayersPair.put(report.getTaskId(), tempTotalCumulativeWorkingLayers);
+                            }
+                        }
+                        if ("台次".equals(unit) && "当日泵车台次".equals(attr.getName())) {
+                            tempTotalPumpTrips = tempTotalPumpTrips.add(actualValue);
+                            if (pumpTripsPair.containsKey(report.getTaskId())) {
+                                BigDecimal tempPumpTrips = pumpTripsPair.get(report.getTaskId());
+                                pumpTripsPair.put(report.getTaskId(), tempTotalPumpTrips.add(tempPumpTrips));
+                            } else {
+                                pumpTripsPair.put(report.getTaskId(), tempTotalPumpTrips);
+                            }
+                        }
+                        if ("台次".equals(unit) && ("当日仪表/混砂".equals(attr.getName())
+                                || "当日混砂".equals(attr.getName()) || "当日仪表".equals(attr.getName()))) {
+                            tempTotalMixSand = tempTotalMixSand.add(actualValue);
+                            if (mixSandPair.containsKey(report.getTaskId())) {
+                                BigDecimal tempMixSand = mixSandPair.get(report.getTaskId());
+                                mixSandPair.put(report.getTaskId(), tempTotalMixSand.add(tempMixSand));
+                            } else {
+                                mixSandPair.put(report.getTaskId(), tempTotalMixSand);
+                            }
+                        }
+                    }
+                }
+            });
+        }
+        // key任务id   value任务已经完成的工作量集合
+        Map<Long, List<IotRdDailyReportStatisticsItemVO>> taskFinishedWorkloadPair = new HashMap<>();
         // 循环每个任务 找到任务 关联的平台井
         if (CollUtil.isNotEmpty(pagedTasks)) {
             pagedTasks.forEach(task -> {
@@ -131,12 +274,74 @@ public class IotProjectTaskController {
                     });
                     platformWellPair.put(task.getId(), platforms);
                 }
+                // 设置每个任务的已完成工作量信息
+                List<IotRdDailyReportStatisticsItemVO> items = new ArrayList<>();
+                // 以队伍为维度 设置每种施工工艺的工作量 总和
+                if (bridgePlugPair.containsKey(task.getId())) {
+                    // 钻可溶桥塞  钻复合桥塞
+                    IotRdDailyReportStatisticsItemVO item = new IotRdDailyReportStatisticsItemVO();
+                    item.setUnit("个数");
+                    item.setWorkload(bridgePlugPair.get(task.getId()));
+                    items.add(item);
+                }
+                if (runCountPair.containsKey(task.getId())) {
+                    // 通刮洗  冲砂
+                    IotRdDailyReportStatisticsItemVO item = new IotRdDailyReportStatisticsItemVO();
+                    item.setUnit("趟数");
+                    item.setWorkload(runCountPair.get(task.getId()));
+                    items.add(item);
+                }
+                if (hourCountPair.containsKey(task.getId())) {
+                    // 液氮泵车(时间D)  千型泵车(时间H)
+                    IotRdDailyReportStatisticsItemVO item = new IotRdDailyReportStatisticsItemVO();
+                    item.setUnit("小时");
+                    item.setWorkload(hourCountPair.get(task.getId()));
+                    items.add(item);
+                }
+                if (waterVolumePair.containsKey(task.getId())) {
+                    // 注水
+                    IotRdDailyReportStatisticsItemVO item = new IotRdDailyReportStatisticsItemVO();
+                    item.setUnit("方");
+                    item.setWorkload(waterVolumePair.get(task.getId()));
+                    items.add(item);
+                }
+                if (cumulativeWorkingWellPair.containsKey(task.getId())) {
+                    // 连续油管常规作业
+                    IotRdDailyReportStatisticsItemVO item = new IotRdDailyReportStatisticsItemVO();
+                    item.setUnit("井数");
+                    item.setWorkload(cumulativeWorkingWellPair.get(task.getId()));
+                    items.add(item);
+                }
+                if (cumulativeWorkingLayersPair.containsKey(task.getId())) {
+                    // 压裂大包 压裂总包
+                    IotRdDailyReportStatisticsItemVO item = new IotRdDailyReportStatisticsItemVO();
+                    item.setUnit("段数");
+                    item.setWorkload(cumulativeWorkingLayersPair.get(task.getId()));
+                    items.add(item);
+                }
+                if (pumpTripsPair.containsKey(task.getId())) {
+                    // 主压裂车 当日泵车台次
+                    IotRdDailyReportStatisticsItemVO item = new IotRdDailyReportStatisticsItemVO();
+                    item.setUnit("台次");
+                    item.setWorkload(pumpTripsPair.get(task.getId()));
+                    items.add(item);
+                }
+                if (mixSandPair.containsKey(task.getId())) {
+                    // 当日仪表/混砂 台次
+                    IotRdDailyReportStatisticsItemVO item = new IotRdDailyReportStatisticsItemVO();
+                    item.setUnit("台次");
+                    item.setWorkload(mixSandPair.get(task.getId()));
+                    items.add(item);
+                }
+                taskFinishedWorkloadPair.put(task.getId(), items);
             });
         }
         // 2. 拼接数据
         return BeanUtils.toBean(pagedTasks, IotProjectTaskRespVO.class, (taskVO) -> {
-            // 2.1 拼接平台井信息
+            // 拼接平台井信息
             findAndThen(platformWellPair, taskVO.getId(), tasks -> taskVO.setPlatformWells(tasks));
+            // 任务已经完成的工作量
+            findAndThen(taskFinishedWorkloadPair, taskVO.getId(), workloads -> taskVO.setItems(workloads));
         });
     }
 

+ 4 - 0
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/iotprojecttask/vo/IotProjectTaskRespVO.java

@@ -1,5 +1,6 @@
 package cn.iocoder.yudao.module.pms.controller.admin.iotprojecttask.vo;
 
+import cn.iocoder.yudao.module.pms.controller.admin.iotrddailyreport.vo.IotRdDailyReportStatisticsItemVO;
 import cn.iocoder.yudao.module.pms.dal.dataobject.iotprojecttaskattrs.IotTaskAttrModelProperty;
 import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
 import com.alibaba.excel.annotation.ExcelProperty;
@@ -122,4 +123,7 @@ public class IotProjectTaskRespVO {
 
     @Schema(description = "平台井明细", example = "[{\"井号\": #233, \"工作量\": 234}]")
     private List<IotProjectTaskPlatformVO> platformWells;
+
+    @Schema(description = "当前任务已经完成的工作量明细")
+    private List<IotRdDailyReportStatisticsItemVO> items;
 }

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

@@ -19,10 +19,7 @@ import cn.iocoder.yudao.module.pms.controller.admin.iotdailyreportfuel.vo.IotDai
 import cn.iocoder.yudao.module.pms.controller.admin.iotprojectinfo.vo.IotProjectInfoPageReqVO;
 import cn.iocoder.yudao.module.pms.controller.admin.iotprojecttask.vo.IotProjectTaskPageReqVO;
 import cn.iocoder.yudao.module.pms.controller.admin.iotprojecttask.vo.IotProjectTaskPlatformVO;
-import cn.iocoder.yudao.module.pms.controller.admin.iotrddailyreport.vo.IotRdDailyReportPageReqVO;
-import cn.iocoder.yudao.module.pms.controller.admin.iotrddailyreport.vo.IotRdDailyReportRespVO;
-import cn.iocoder.yudao.module.pms.controller.admin.iotrddailyreport.vo.IotRdDailyReportSaveReqVO;
-import cn.iocoder.yudao.module.pms.controller.admin.iotrddailyreport.vo.IotRdDailyReportStatisticsRespVO;
+import cn.iocoder.yudao.module.pms.controller.admin.iotrddailyreport.vo.*;
 import cn.iocoder.yudao.module.pms.controller.admin.vo.IotDevicePageReqVO;
 import cn.iocoder.yudao.module.pms.controller.admin.vo.IotDeviceRespVO;
 import cn.iocoder.yudao.module.pms.controller.admin.vo.IotDeviceSimpleRespVO;
@@ -70,6 +67,7 @@ import java.time.LocalDate;
 import java.time.LocalDateTime;
 import java.time.format.DateTimeFormatter;
 import java.time.format.DateTimeParseException;
+import java.time.temporal.ChronoUnit;
 import java.util.*;
 import java.util.stream.Collectors;
 
@@ -205,14 +203,60 @@ public class IotRdDailyReportController {
         if (CollUtil.isNotEmpty(reportFuels)) {
             hasFuels = true;
             dailyReportVO.setReportedFuels(reportFuels);
-        } else {
         }
+        // 查询施工工艺字典数据
+        List<DictDataDO> rdTechniquesDicts = dictDataService.getDictDataListByDictType("rq_iot_project_technology_rd");
+        // 工作量单位 数据字典
+        List<DictDataDO> measureUnitDicts = dictDataService.getDictDataListByDictType("rq_iot_project_measure_unit");
+        // 施工状态 数据字典
+        List<DictDataDO> rdStatusDicts = dictDataService.getDictDataListByDictType("rdStatus");
+        //  施工状态 key字典键值     value字典标签
+        Map<String, String> statusDictPair = new HashMap<>();
+        // 停待状态 的字典数据集合
+        Set<String> tdStatuses = new HashSet<>();
+        //  施工工艺 key字典键值     value字典标签
+        Map<String, String> techniqueDictPair = new HashMap<>();
+        //  工作量单位 key字典键值     value字典标签
+        Map<String, String> unitDictPair = new HashMap<>();
+        if (CollUtil.isNotEmpty(rdTechniquesDicts)) {
+            rdTechniquesDicts.forEach(tech -> {
+                techniqueDictPair.put(tech.getValue(), tech.getLabel());
+            });
+        }
+        if (CollUtil.isNotEmpty(measureUnitDicts)) {
+            measureUnitDicts.forEach(tech -> {
+                unitDictPair.put(tech.getValue(), tech.getLabel());
+            });
+        }
+        if (CollUtil.isNotEmpty(rdStatusDicts)) {
+            rdStatusDicts.forEach(status -> {
+                statusDictPair.put(status.getValue(), status.getLabel());
+                // 找到属于 停待状态 的字典数据
+                if ("TD".equals(status.getRemark())) {
+                    tdStatuses.add(status.getValue());
+                }
+            });
+        }
+
         // 查询日报对应的任务信息
         if (ObjUtil.isNotEmpty(dailyReport.getTaskId())) {
             IotProjectTaskDO task = iotProjectTaskService.getIotProjectTask(dailyReport.getTaskId());
             dailyReportVO.setTaskName(StrUtil.join("-", task.getWellName(), task.getLocation()));
             dailyReportVO.setWellName(task.getWellName());
             dailyReportVO.setLocation(task.getLocation());
+            // 任务施工工艺
+            String techniqueValue = task.getTechnique();
+            if (StrUtil.isNotBlank(techniqueValue)) {
+                dailyReportVO.setTechniqueNames(techniqueDictPair.get(techniqueValue));
+            }
+            // 任务工作量
+            String workloadDesign = task.getWorkloadDesign();
+            // 任务工作量单位
+            String workloadDesignUnit = task.getWorkloadUnit();
+            if (StrUtil.isNotBlank(workloadDesignUnit)) {
+                dailyReportVO.setWorkloadDesign(StrUtil.join(" ", workloadDesign, unitDictPair.get(workloadDesignUnit)));
+            }
+
             Set<Long> deviceIds = task.getDeviceIds();
             Set<Long> responsiblePersonIds = task.getResponsiblePerson();
             // 日报对应的任务中的设备列表
@@ -281,6 +325,85 @@ public class IotRdDailyReportController {
                 List<IotDeviceSimpleRespVO> simpleDevices = BeanUtils.toBean(selectedDevices, IotDeviceSimpleRespVO.class);
                 dailyReportVO.setSelectedDevices(simpleDevices);
             }
+            // 查询相同任务id的日报 查询开工日期 完工日期 施工周期
+            IotRdDailyReportPageReqVO reportReqVO  = new IotRdDailyReportPageReqVO();
+            reportReqVO.setTaskId(dailyReport.getTaskId());
+            List<IotRdDailyReportDO> reports = iotRdDailyReportService.dailyReports(reportReqVO);
+            if (CollUtil.isNotEmpty(reports)) {
+                // 找出开工日期:最早创建时间
+                Optional<LocalDateTime> startDateOpt = reports.stream()
+                        .filter(report -> StrUtil.isNotBlank(report.getRdStatus()))
+                        .map(IotRdDailyReportDO::getCreateTime)
+                        .filter(Objects::nonNull)
+                        .min(LocalDateTime::compareTo);
+                // 找出完工日期:rdStatus='wg' 的日报创建时间(取最早的一个)
+                Optional<LocalDateTime> endDateOpt = reports.stream()
+                        .filter(report -> "wg".equals(report.getRdStatus()))
+                        .map(IotRdDailyReportDO::getCreateTime)
+                        .filter(Objects::nonNull)
+                        .min(LocalDateTime::compareTo);
+                startDateOpt.ifPresent(startDate ->
+                        dailyReportVO.setCommencementDate(LocalDateTimeUtil.format(startDate, DatePattern.NORM_DATE_PATTERN))
+                );
+                endDateOpt.ifPresent(finishDate ->
+                        dailyReportVO.setCompletionDate(LocalDateTimeUtil.format(finishDate, DatePattern.NORM_DATE_PATTERN))
+                );
+                // 计算施工周期(包含开工和完工日期)
+                if (startDateOpt.isPresent() && endDateOpt.isPresent()) {
+                    LocalDateTime startDate = startDateOpt.get();
+                    LocalDateTime endDate = endDateOpt.get();
+
+                    // 将LocalDateTime转换为LocalDate进行计算
+                    LocalDate startLocalDate = startDate.toLocalDate();
+                    LocalDate endLocalDate = endDate.toLocalDate();
+
+                    // 计算天数(包含起始和结束日期)
+                    long daysBetween = ChronoUnit.DAYS.between(startLocalDate, endLocalDate) + 1;
+                    dailyReportVO.setConstructionPeriod(String.valueOf(daysBetween));
+                }
+                // 找到处于停待状态 的日报数据
+                long tdStatusCount = reports.stream()
+                        .filter(report -> StrUtil.isNotBlank(report.getRdStatus()) && tdStatuses.contains(report.getRdStatus()))
+                        .count();
+                dailyReportVO.setIdleTime(String.valueOf(tdStatusCount));
+                // 当前日报关联任务的施工进度
+                if (CollUtil.isNotEmpty(statusDictPair)) {
+                    // 1. 过滤有效数据并排序(按时间升序)
+                    List<IotRdDailyReportDO> validReports = reports.stream()
+                            .filter(report -> StrUtil.isNotBlank(report.getRdStatus())
+                                    && ObjUtil.isNotEmpty(report.getCreateTime())
+                                    && statusDictPair.containsKey(report.getRdStatus()))
+                            .sorted(Comparator.comparing(IotRdDailyReportDO::getCreateTime))
+                            .collect(Collectors.toList());
+                    Map<String, List<IotRdDailyReportDO>> rdStatusReportPair = new HashMap<>();
+                    List<IotRdDailyReportDO> uniqueRdStatusReports = new ArrayList<>();
+                    if (CollUtil.isNotEmpty(validReports)) {
+                        validReports.forEach(report -> {
+                            // 获取集合中的最后一个元素 如果最后一个元素的rdStatus 与当前日报 rdStatus 不同
+                            // 则将 当前report 加入 集合 uniqueRdStatusReports
+                            if (CollUtil.isEmpty(uniqueRdStatusReports)) {
+                                uniqueRdStatusReports.add(report);
+                            } else {
+                                IotRdDailyReportDO lastElement = uniqueRdStatusReports.get(uniqueRdStatusReports.size() - 1);
+                                if (ObjUtil.isNotEmpty(lastElement) && !lastElement.getRdStatus().equals(report.getRdStatus())) {
+                                    uniqueRdStatusReports.add(report);
+                                }
+                            }
+                        });
+                    }
+                    List<IotRdDailyReportTaskProgressVO> progresses = new ArrayList<>();
+                    if (CollUtil.isNotEmpty(uniqueRdStatusReports)) {
+                        uniqueRdStatusReports.forEach(report -> {
+                            IotRdDailyReportTaskProgressVO progress = new IotRdDailyReportTaskProgressVO();
+                            progress.setRdStatusLabel(statusDictPair.get(report.getRdStatus()));
+                            progress.setCreateTime(LocalDateTimeUtil.format(report.getCreateTime(), DatePattern.NORM_DATE_PATTERN));
+                            progresses.add(progress);
+                        });
+                        dailyReportVO.setTaskProgresses(progresses);
+                    }
+                }
+            }
+
             if (CollUtil.isNotEmpty(responsiblePersonIds)) {
                 List<AdminUserRespDTO> users = adminUserApi.getUserList(responsiblePersonIds);
                 String userNames = users.stream()
@@ -362,24 +485,8 @@ public class IotRdDailyReportController {
             DeptDO dept = deptService.getDept(dailyReport.getDeptId());
             dailyReportVO.setDeptName(dept.getName());
         }
-        // 查询施工工艺字典数据
-        List<DictDataDO> rdStatusDicts = dictDataService.getDictDataListByDictType("rdStatus");
-        // 查询施工工艺字典数据
-        List<DictDataDO> rdTechniquesDicts = dictDataService.getDictDataListByDictType("rq_iot_project_technology_rd");
-        //  施工状态 key字典键值     value字典标签
-        Map<String, String> statusDictPair = new HashMap<>();
-        //  施工工艺 key字典键值     value字典标签
-        Map<String, String> techniqueDictPair = new HashMap<>();
-        if (CollUtil.isNotEmpty(rdStatusDicts)) {
-            rdStatusDicts.forEach(tech -> {
-                statusDictPair.put(tech.getValue(), tech.getLabel());
-            });
-        }
-        if (CollUtil.isNotEmpty(rdTechniquesDicts)) {
-            rdTechniquesDicts.forEach(tech -> {
-                techniqueDictPair.put(tech.getValue(), tech.getLabel());
-            });
-        }
+
+
         // 日报任务对应的平台井列表
         if (1 == dailyReport.getPlatformWell()) {
             // 查询未施工完成的平台井 关联井列表

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

@@ -277,10 +277,14 @@ public class IotRdDailyReportRespVO {
     @ExcelProperty("完工日期")
     private String completionDate;
 
-    @Schema(description = "施工周期", example = "125")
-    @ExcelProperty("施工周期")
+    @Schema(description = "施工周期D", example = "125")
+    @ExcelProperty("施工周期D")
     private String constructionPeriod;
 
+    @Schema(description = "停待时间D", example = "12")
+    @ExcelProperty("停待时间D")
+    private String idleTime;
+
     /**
      * 扩展属性
      */
@@ -308,4 +312,10 @@ public class IotRdDailyReportRespVO {
 
     @Schema(description = "日报关联的已经填报的油耗记录")
     private List<IotDailyReportFuelDO> reportedFuels;
+
+    @Schema(description = "工作量", example = "1 井次")
+    private String workloadDesign;
+
+    @Schema(description = "任务施工进度", example = "施工准备2025-12-01 -> 施工2025-12-02")
+    private List<IotRdDailyReportTaskProgressVO> taskProgresses;
 }

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

@@ -0,0 +1,15 @@
+package cn.iocoder.yudao.module.pms.controller.admin.iotrddailyreport.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+@Schema(description = "管理后台 - 瑞都日报 任务施工进度 Response VO")
+@Data
+public class IotRdDailyReportTaskProgressVO {
+
+    @Schema(description = "施工进度", example = "施工")
+    private String rdStatusLabel;
+
+    @Schema(description = "日期")
+    private String createTime;
+}

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

@@ -513,6 +513,7 @@ public class IotRdDailyReportServiceImpl implements IotRdDailyReportService {
 
             dailyReports.forEach(report -> {
                 BigDecimal dailyFuel = report.getDailyFuel();
+                dailyFuel = ObjUtil.isEmpty(dailyFuel) ? BigDecimal.ZERO : dailyFuel;
                 if (taskFuelPair.containsKey(report.getTaskId())) {
                     BigDecimal existTotalFuel = taskFuelPair.get(report.getTaskId());
                     BigDecimal tempTotalFuel = existTotalFuel.add(dailyFuel);