Selaa lähdekoodia

Merge remote-tracking branch 'origin/master'

lipenghui 2 päivää sitten
vanhempi
commit
9970093752
34 muutettua tiedostoa jossa 2247 lisäystä ja 99 poistoa
  1. 2 0
      yudao-module-pms/yudao-module-pms-api/src/main/java/cn/iocoder/yudao/module/pms/enums/ErrorCodeConstant.java
  2. 93 0
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/iotcarzhbd/IotCarZhbdController.java
  3. 48 0
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/iotcarzhbd/vo/IotCarZhbdPageReqVO.java
  4. 43 0
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/iotcarzhbd/vo/IotCarZhbdRespVO.java
  5. 28 0
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/iotcarzhbd/vo/IotCarZhbdSaveReqVO.java
  6. 93 0
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/iotdailyreportfuel/IotDailyReportFuelController.java
  7. 59 0
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/iotdailyreportfuel/vo/IotDailyReportFuelPageReqVO.java
  8. 68 0
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/iotdailyreportfuel/vo/IotDailyReportFuelRespVO.java
  9. 49 0
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/iotdailyreportfuel/vo/IotDailyReportFuelSaveReqVO.java
  10. 73 3
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/iotrhdailyreport/IotRhDailyReportController.java
  11. 194 0
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/iotrhdailyreport/IotZHBDController.java
  12. 0 1
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/iotrhdailyreport/vo/IotRhDailyReportPolylineVO.java
  13. 11 0
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/iotrhdailyreport/vo/IotRhDailyReportRespVO.java
  14. 6 9
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/iotrhdailyreport/vo/IotRhDailyReportStatisticsRespVO.java
  15. 100 2
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/iotrydailyreport/IotRyDailyReportController.java
  16. 67 0
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/iotrydailyreport/vo/IotRyDailyReportPolylineVO.java
  17. 4 7
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/iotrydailyreport/vo/IotRyDailyReportStatisticsRespVO.java
  18. 47 7
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/stat/IotStaticController.java
  19. 50 0
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/dal/dataobject/iotcarzhbd/IotCarZhbdDO.java
  20. 77 0
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/dal/dataobject/iotdailyreportfuel/IotDailyReportFuelDO.java
  21. 4 0
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/dal/dataobject/iotrhdailyreport/IotRhDailyReportDO.java
  22. 43 0
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/dal/mysql/iotcarzhbd/IotCarZhbdMapper.java
  23. 54 0
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/dal/mysql/iotdailyreportfuel/IotDailyReportFuelMapper.java
  24. 33 0
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/job/IotDeviceCarFuelVO.java
  25. 14 0
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/job/httpEntity/ApiOilResponse.java
  26. 16 0
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/job/httpEntity/ResponseOilData.java
  27. 55 0
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/service/iotcarzhbd/IotCarZhbdService.java
  28. 71 0
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/service/iotcarzhbd/IotCarZhbdServiceImpl.java
  29. 64 0
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/service/iotdailyreportfuel/IotDailyReportFuelService.java
  30. 78 0
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/service/iotdailyreportfuel/IotDailyReportFuelServiceImpl.java
  31. 145 70
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/service/iotrhdailyreport/IotRhDailyReportServiceImpl.java
  32. 8 0
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/service/iotrydailyreport/IotRyDailyReportService.java
  33. 416 0
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/service/iotrydailyreport/IotRyDailyReportServiceImpl.java
  34. 134 0
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/util/ZHBDUtil.java

+ 2 - 0
yudao-module-pms/yudao-module-pms-api/src/main/java/cn/iocoder/yudao/module/pms/enums/ErrorCodeConstant.java

@@ -97,4 +97,6 @@ public interface ErrorCodeConstant{
     ErrorCode IOT_DAILY_REPORT_TIME_NOT_EXISTS = new ErrorCode(272, "未传递创建时间查询参数");
     ErrorCode IOT_DAILY_REPORT_DEPT_NOT_EXISTS = new ErrorCode(273, "未选择项目部");
     ErrorCode IOT_DEPT_TYPE_NOT_EXISTS = new ErrorCode(274, "部门类型不存在");
+    ErrorCode IOT_CAR_ZHBD_NOT_EXISTS = new ErrorCode(275, "中航北斗车辆表不存在");
+    ErrorCode IOT_DAILY_REPORT_FUEL_NOT_EXISTS = new ErrorCode(276, "日报-油耗不存在");
 }

+ 93 - 0
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/iotcarzhbd/IotCarZhbdController.java

@@ -0,0 +1,93 @@
+package cn.iocoder.yudao.module.pms.controller.admin.iotcarzhbd;
+
+import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
+import cn.iocoder.yudao.framework.common.pojo.CommonResult;
+import cn.iocoder.yudao.framework.common.pojo.PageParam;
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
+import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
+import cn.iocoder.yudao.module.pms.controller.admin.iotcarzhbd.vo.IotCarZhbdPageReqVO;
+import cn.iocoder.yudao.module.pms.controller.admin.iotcarzhbd.vo.IotCarZhbdRespVO;
+import cn.iocoder.yudao.module.pms.controller.admin.iotcarzhbd.vo.IotCarZhbdSaveReqVO;
+import cn.iocoder.yudao.module.pms.dal.dataobject.iotcarzhbd.IotCarZhbdDO;
+import cn.iocoder.yudao.module.pms.service.iotcarzhbd.IotCarZhbdService;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import javax.annotation.Resource;
+import javax.servlet.http.HttpServletResponse;
+import javax.validation.Valid;
+import java.io.IOException;
+import java.util.List;
+
+import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.EXPORT;
+import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
+
+@Tag(name = "管理后台 - 中航北斗车辆表")
+@RestController
+@RequestMapping("/pms/iot-car-zhbd")
+@Validated
+public class IotCarZhbdController {
+
+    @Resource
+    private IotCarZhbdService iotCarZhbdService;
+
+    @PostMapping("/create")
+    @Operation(summary = "创建中航北斗车辆表")
+    @PreAuthorize("@ss.hasPermission('pms:iot-car-zhbd:create')")
+    public CommonResult<Long> createIotCarZhbd(@Valid @RequestBody IotCarZhbdSaveReqVO createReqVO) {
+        return success(iotCarZhbdService.createIotCarZhbd(createReqVO));
+    }
+
+    @PutMapping("/update")
+    @Operation(summary = "更新中航北斗车辆表")
+    @PreAuthorize("@ss.hasPermission('pms:iot-car-zhbd:update')")
+    public CommonResult<Boolean> updateIotCarZhbd(@Valid @RequestBody IotCarZhbdSaveReqVO updateReqVO) {
+        iotCarZhbdService.updateIotCarZhbd(updateReqVO);
+        return success(true);
+    }
+
+    @DeleteMapping("/delete")
+    @Operation(summary = "删除中航北斗车辆表")
+    @Parameter(name = "id", description = "编号", required = true)
+    @PreAuthorize("@ss.hasPermission('pms:iot-car-zhbd:delete')")
+    public CommonResult<Boolean> deleteIotCarZhbd(@RequestParam("id") Long id) {
+        iotCarZhbdService.deleteIotCarZhbd(id);
+        return success(true);
+    }
+
+    @GetMapping("/get")
+    @Operation(summary = "获得中航北斗车辆表")
+    @Parameter(name = "id", description = "编号", required = true, example = "1024")
+    @PreAuthorize("@ss.hasPermission('pms:iot-car-zhbd:query')")
+    public CommonResult<IotCarZhbdRespVO> getIotCarZhbd(@RequestParam("id") Long id) {
+        IotCarZhbdDO iotCarZhbd = iotCarZhbdService.getIotCarZhbd(id);
+        return success(BeanUtils.toBean(iotCarZhbd, IotCarZhbdRespVO.class));
+    }
+
+    @GetMapping("/page")
+    @Operation(summary = "获得中航北斗车辆表分页")
+    @PreAuthorize("@ss.hasPermission('pms:iot-car-zhbd:query')")
+    public CommonResult<PageResult<IotCarZhbdRespVO>> getIotCarZhbdPage(@Valid IotCarZhbdPageReqVO pageReqVO) {
+        PageResult<IotCarZhbdDO> pageResult = iotCarZhbdService.getIotCarZhbdPage(pageReqVO);
+        return success(BeanUtils.toBean(pageResult, IotCarZhbdRespVO.class));
+    }
+
+    @GetMapping("/export-excel")
+    @Operation(summary = "导出中航北斗车辆表 Excel")
+    @PreAuthorize("@ss.hasPermission('pms:iot-car-zhbd:export')")
+    @ApiAccessLog(operateType = EXPORT)
+    public void exportIotCarZhbdExcel(@Valid IotCarZhbdPageReqVO pageReqVO,
+              HttpServletResponse response) throws IOException {
+        pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
+        List<IotCarZhbdDO> list = iotCarZhbdService.getIotCarZhbdPage(pageReqVO).getList();
+        // 导出 Excel
+        ExcelUtils.write(response, "中航北斗车辆表.xls", "数据", IotCarZhbdRespVO.class,
+                        BeanUtils.toBean(list, IotCarZhbdRespVO.class));
+    }
+
+}

+ 48 - 0
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/iotcarzhbd/vo/IotCarZhbdPageReqVO.java

@@ -0,0 +1,48 @@
+package cn.iocoder.yudao.module.pms.controller.admin.iotcarzhbd.vo;
+
+import cn.iocoder.yudao.framework.common.pojo.PageParam;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.ToString;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.time.LocalDateTime;
+import java.util.Collection;
+
+import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
+
+@Schema(description = "管理后台 - 中航北斗车辆表分页 Request VO")
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+public class IotCarZhbdPageReqVO extends PageParam {
+
+    @Schema(description = "组织id")
+    private String deviceCode;
+
+    @Schema(description = "工单名称", example = "芋艿")
+    private String deviceName;
+
+    @Schema(description = "工单类型", example = "10570")
+    private String carId;
+
+    @Schema(description = "创建时间")
+    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+    private LocalDateTime[] createTime;
+
+    @Schema(description = "用户名称", example = "芋艿")
+    private String userName;
+
+    @Schema(description = "用户id", example = "26763")
+    private Long userId;
+
+    /**
+     * 扩展字段
+     */
+    @Schema(description = "设备编码 有的编码在设备表中不存在", example = "10570")
+    private Collection<String> deviceCodes;
+
+    @Schema(description = "设备编码 与设备表额外匹配的编码", example = "10570")
+    private Collection<String> customDeviceCodes;
+}

+ 43 - 0
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/iotcarzhbd/vo/IotCarZhbdRespVO.java

@@ -0,0 +1,43 @@
+package cn.iocoder.yudao.module.pms.controller.admin.iotcarzhbd.vo;
+
+import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
+import com.alibaba.excel.annotation.ExcelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.time.LocalDateTime;
+
+@Schema(description = "管理后台 - 中航北斗车辆表 Response VO")
+@Data
+@ExcelIgnoreUnannotated
+public class IotCarZhbdRespVO {
+
+    @Schema(description = "主键id", requiredMode = Schema.RequiredMode.REQUIRED, example = "10183")
+    @ExcelProperty("主键id")
+    private Long id;
+
+    @Schema(description = "组织id")
+    @ExcelProperty("组织id")
+    private String deviceCode;
+
+    @Schema(description = "工单名称", example = "芋艿")
+    @ExcelProperty("工单名称")
+    private String deviceName;
+
+    @Schema(description = "工单类型", example = "10570")
+    @ExcelProperty("工单类型")
+    private String carId;
+
+    @Schema(description = "创建时间")
+    @ExcelProperty("创建时间")
+    private LocalDateTime createTime;
+
+    @Schema(description = "用户名称", example = "芋艿")
+    @ExcelProperty("用户名称")
+    private String userName;
+
+    @Schema(description = "用户id", example = "26763")
+    @ExcelProperty("用户id")
+    private Long userId;
+
+}

+ 28 - 0
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/iotcarzhbd/vo/IotCarZhbdSaveReqVO.java

@@ -0,0 +1,28 @@
+package cn.iocoder.yudao.module.pms.controller.admin.iotcarzhbd.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+@Schema(description = "管理后台 - 中航北斗车辆表新增/修改 Request VO")
+@Data
+public class IotCarZhbdSaveReqVO {
+
+    @Schema(description = "主键id", requiredMode = Schema.RequiredMode.REQUIRED, example = "10183")
+    private Long id;
+
+    @Schema(description = "组织id")
+    private String deviceCode;
+
+    @Schema(description = "工单名称", example = "芋艿")
+    private String deviceName;
+
+    @Schema(description = "工单类型", example = "10570")
+    private String carId;
+
+    @Schema(description = "用户名称", example = "芋艿")
+    private String userName;
+
+    @Schema(description = "用户id", example = "26763")
+    private Long userId;
+
+}

+ 93 - 0
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/iotdailyreportfuel/IotDailyReportFuelController.java

@@ -0,0 +1,93 @@
+package cn.iocoder.yudao.module.pms.controller.admin.iotdailyreportfuel;
+
+import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
+import cn.iocoder.yudao.framework.common.pojo.CommonResult;
+import cn.iocoder.yudao.framework.common.pojo.PageParam;
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
+import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
+import cn.iocoder.yudao.module.pms.controller.admin.iotdailyreportfuel.vo.IotDailyReportFuelPageReqVO;
+import cn.iocoder.yudao.module.pms.controller.admin.iotdailyreportfuel.vo.IotDailyReportFuelRespVO;
+import cn.iocoder.yudao.module.pms.controller.admin.iotdailyreportfuel.vo.IotDailyReportFuelSaveReqVO;
+import cn.iocoder.yudao.module.pms.dal.dataobject.iotdailyreportfuel.IotDailyReportFuelDO;
+import cn.iocoder.yudao.module.pms.service.iotdailyreportfuel.IotDailyReportFuelService;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import javax.annotation.Resource;
+import javax.servlet.http.HttpServletResponse;
+import javax.validation.Valid;
+import java.io.IOException;
+import java.util.List;
+
+import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.EXPORT;
+import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
+
+@Tag(name = "管理后台 - 日报-油耗")
+@RestController
+@RequestMapping("/pms/iot-daily-report-fuel")
+@Validated
+public class IotDailyReportFuelController {
+
+    @Resource
+    private IotDailyReportFuelService iotDailyReportFuelService;
+
+    @PostMapping("/create")
+    @Operation(summary = "创建日报-油耗")
+    @PreAuthorize("@ss.hasPermission('pms:iot-daily-report-fuel:create')")
+    public CommonResult<Long> createIotDailyReportFuel(@Valid @RequestBody IotDailyReportFuelSaveReqVO createReqVO) {
+        return success(iotDailyReportFuelService.createIotDailyReportFuel(createReqVO));
+    }
+
+    @PutMapping("/update")
+    @Operation(summary = "更新日报-油耗")
+    @PreAuthorize("@ss.hasPermission('pms:iot-daily-report-fuel:update')")
+    public CommonResult<Boolean> updateIotDailyReportFuel(@Valid @RequestBody IotDailyReportFuelSaveReqVO updateReqVO) {
+        iotDailyReportFuelService.updateIotDailyReportFuel(updateReqVO);
+        return success(true);
+    }
+
+    @DeleteMapping("/delete")
+    @Operation(summary = "删除日报-油耗")
+    @Parameter(name = "id", description = "编号", required = true)
+    @PreAuthorize("@ss.hasPermission('pms:iot-daily-report-fuel:delete')")
+    public CommonResult<Boolean> deleteIotDailyReportFuel(@RequestParam("id") Long id) {
+        iotDailyReportFuelService.deleteIotDailyReportFuel(id);
+        return success(true);
+    }
+
+    @GetMapping("/get")
+    @Operation(summary = "获得日报-油耗")
+    @Parameter(name = "id", description = "编号", required = true, example = "1024")
+    @PreAuthorize("@ss.hasPermission('pms:iot-daily-report-fuel:query')")
+    public CommonResult<IotDailyReportFuelRespVO> getIotDailyReportFuel(@RequestParam("id") Long id) {
+        IotDailyReportFuelDO iotDailyReportFuel = iotDailyReportFuelService.getIotDailyReportFuel(id);
+        return success(BeanUtils.toBean(iotDailyReportFuel, IotDailyReportFuelRespVO.class));
+    }
+
+    @GetMapping("/page")
+    @Operation(summary = "获得日报-油耗分页")
+    @PreAuthorize("@ss.hasPermission('pms:iot-daily-report-fuel:query')")
+    public CommonResult<PageResult<IotDailyReportFuelRespVO>> getIotDailyReportFuelPage(@Valid IotDailyReportFuelPageReqVO pageReqVO) {
+        PageResult<IotDailyReportFuelDO> pageResult = iotDailyReportFuelService.getIotDailyReportFuelPage(pageReqVO);
+        return success(BeanUtils.toBean(pageResult, IotDailyReportFuelRespVO.class));
+    }
+
+    @GetMapping("/export-excel")
+    @Operation(summary = "导出日报-油耗 Excel")
+    @PreAuthorize("@ss.hasPermission('pms:iot-daily-report-fuel:export')")
+    @ApiAccessLog(operateType = EXPORT)
+    public void exportIotDailyReportFuelExcel(@Valid IotDailyReportFuelPageReqVO pageReqVO,
+              HttpServletResponse response) throws IOException {
+        pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
+        List<IotDailyReportFuelDO> list = iotDailyReportFuelService.getIotDailyReportFuelPage(pageReqVO).getList();
+        // 导出 Excel
+        ExcelUtils.write(response, "日报-油耗.xls", "数据", IotDailyReportFuelRespVO.class,
+                        BeanUtils.toBean(list, IotDailyReportFuelRespVO.class));
+    }
+
+}

+ 59 - 0
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/iotdailyreportfuel/vo/IotDailyReportFuelPageReqVO.java

@@ -0,0 +1,59 @@
+package cn.iocoder.yudao.module.pms.controller.admin.iotdailyreportfuel.vo;
+
+import cn.iocoder.yudao.framework.common.pojo.PageParam;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.ToString;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+
+import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
+
+@Schema(description = "管理后台 - 日报-油耗分页 Request VO")
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+public class IotDailyReportFuelPageReqVO extends PageParam {
+
+    @Schema(description = "瑞恒RH 瑞鹰RY 瑞都RD", example = "1")
+    private String type;
+
+    @Schema(description = "日报id", example = "13065")
+    private Long reportId;
+
+    @Schema(description = "设备(车辆)id", example = "887")
+    private Long deviceId;
+
+    @Schema(description = "设备编码")
+    private String deviceCode;
+
+    @Schema(description = "油服设备编码")
+    private String yfDeviceCode;
+
+    @Schema(description = "设备名称", example = "赵六")
+    private String deviceName;
+
+    @Schema(description = "zhbd车辆id", example = "23704")
+    private String carId;
+
+    @Schema(description = "zhdb油耗(L)")
+    private BigDecimal zhbdFuel;
+
+    @Schema(description = "修正后的油耗(L)")
+    private BigDecimal customFuel;
+
+    @Schema(description = "获取油耗时的日期")
+    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+    private LocalDateTime[] queryDate;
+
+    @Schema(description = "备注", example = "你猜")
+    private String remark;
+
+    @Schema(description = "创建时间")
+    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+    private LocalDateTime[] createTime;
+
+}

+ 68 - 0
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/iotdailyreportfuel/vo/IotDailyReportFuelRespVO.java

@@ -0,0 +1,68 @@
+package cn.iocoder.yudao.module.pms.controller.admin.iotdailyreportfuel.vo;
+
+import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
+import com.alibaba.excel.annotation.ExcelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+
+@Schema(description = "管理后台 - 日报-油耗 Response VO")
+@Data
+@ExcelIgnoreUnannotated
+public class IotDailyReportFuelRespVO {
+
+    @Schema(description = "主键id", requiredMode = Schema.RequiredMode.REQUIRED, example = "23733")
+    @ExcelProperty("主键id")
+    private Long id;
+
+    @Schema(description = "瑞恒RH 瑞鹰RY 瑞都RD", example = "1")
+    @ExcelProperty("瑞恒RH 瑞鹰RY 瑞都RD")
+    private String type;
+
+    @Schema(description = "日报id", example = "13065")
+    @ExcelProperty("日报id")
+    private Long reportId;
+
+    @Schema(description = "设备(车辆)id", example = "887")
+    @ExcelProperty("设备(车辆)id")
+    private Long deviceId;
+
+    @Schema(description = "设备编码")
+    @ExcelProperty("设备编码")
+    private String deviceCode;
+
+    @Schema(description = "油服设备编码")
+    @ExcelProperty("油服设备编码")
+    private String yfDeviceCode;
+
+    @Schema(description = "设备名称", example = "赵六")
+    @ExcelProperty("设备名称")
+    private String deviceName;
+
+    @Schema(description = "zhbd车辆id", example = "23704")
+    @ExcelProperty("zhbd车辆id")
+    private String carId;
+
+    @Schema(description = "zhdb油耗(L)")
+    @ExcelProperty("zhdb油耗(L)")
+    private BigDecimal zhbdFuel;
+
+    @Schema(description = "修正后的油耗(L)")
+    @ExcelProperty("修正后的油耗(L)")
+    private BigDecimal customFuel;
+
+    @Schema(description = "获取油耗时的日期")
+    @ExcelProperty("获取油耗时的日期")
+    private LocalDateTime queryDate;
+
+    @Schema(description = "备注", example = "你猜")
+    @ExcelProperty("备注")
+    private String remark;
+
+    @Schema(description = "创建时间")
+    @ExcelProperty("创建时间")
+    private LocalDateTime createTime;
+
+}

+ 49 - 0
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/iotdailyreportfuel/vo/IotDailyReportFuelSaveReqVO.java

@@ -0,0 +1,49 @@
+package cn.iocoder.yudao.module.pms.controller.admin.iotdailyreportfuel.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+
+@Schema(description = "管理后台 - 日报-油耗新增/修改 Request VO")
+@Data
+public class IotDailyReportFuelSaveReqVO {
+
+    @Schema(description = "主键id", requiredMode = Schema.RequiredMode.REQUIRED, example = "23733")
+    private Long id;
+
+    @Schema(description = "瑞恒RH 瑞鹰RY 瑞都RD", example = "1")
+    private String type;
+
+    @Schema(description = "日报id", example = "13065")
+    private Long reportId;
+
+    @Schema(description = "设备(车辆)id", example = "887")
+    private Long deviceId;
+
+    @Schema(description = "设备编码")
+    private String deviceCode;
+
+    @Schema(description = "油服设备编码")
+    private String yfDeviceCode;
+
+    @Schema(description = "设备名称", example = "赵六")
+    private String deviceName;
+
+    @Schema(description = "zhbd车辆id", example = "23704")
+    private String carId;
+
+    @Schema(description = "zhdb油耗(L)")
+    private BigDecimal zhbdFuel;
+
+    @Schema(description = "修正后的油耗(L)")
+    private BigDecimal customFuel;
+
+    @Schema(description = "获取油耗时的日期")
+    private LocalDateTime queryDate;
+
+    @Schema(description = "备注", example = "你猜")
+    private String remark;
+
+}

+ 73 - 3
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/iotrhdailyreport/IotRhDailyReportController.java

@@ -11,17 +11,20 @@ import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
 import cn.iocoder.yudao.framework.datapermission.core.annotation.DataPermission;
 import cn.iocoder.yudao.framework.datapermission.core.util.DataPermissionUtils;
 import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
+import cn.iocoder.yudao.module.pms.controller.admin.iotdailyreportfuel.vo.IotDailyReportFuelPageReqVO;
 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.iotrddailyreport.vo.IotRdDailyReportPageReqVO;
 import cn.iocoder.yudao.module.pms.controller.admin.iotrhdailyreport.vo.*;
 import cn.iocoder.yudao.module.pms.controller.admin.iotrydailyreport.vo.IotRyDailyReportPageReqVO;
 import cn.iocoder.yudao.module.pms.controller.admin.iotrydailyreport.vo.IotRyDailyReportStatisticsVO;
+import cn.iocoder.yudao.module.pms.dal.dataobject.iotdailyreportfuel.IotDailyReportFuelDO;
 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.dataobject.iotrhdailyreport.IotRhDailyReportDO;
+import cn.iocoder.yudao.module.pms.service.iotdailyreportfuel.IotDailyReportFuelService;
 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;
@@ -72,6 +75,8 @@ public class IotRhDailyReportController {
     @Resource
     private IotRyDailyReportService iotRyDailyReportService;
     @Resource
+    private IotDailyReportFuelService iotDailyReportFuelService;
+    @Resource
     private DictDataService dictDataService;
 
     @PostMapping("/create")
@@ -108,6 +113,12 @@ public class IotRhDailyReportController {
         BigDecimal capacity = iotRhDailyReportService.queryCapacity(iotRhDailyReport.getDeptId());
         IotRhDailyReportRespVO result = BeanUtils.toBean(iotRhDailyReport, IotRhDailyReportRespVO.class);
         result.setCapacity(capacity);
+        // 查询日报关联油耗记录
+        IotDailyReportFuelPageReqVO reqVO = new IotDailyReportFuelPageReqVO();
+        reqVO.setReportId(result.getId());
+        reqVO.setType("RH");
+        List<IotDailyReportFuelDO> reportFuels = iotDailyReportFuelService.getIotDailyReportFuels(reqVO);
+        result.setReportFuels(reportFuels);
         return success(result);
     }
 
@@ -210,6 +221,7 @@ public class IotRhDailyReportController {
             long completeRyCount = 0;
             IotRyDailyReportPageReqVO ryReqVO = new IotRyDailyReportPageReqVO();
             ryReqVO.setCreateTime(pageReqVO.getCreateTime());
+            ryReqVO.setProjectClassification("2");  // 暂时先统计修井
             List<IotRyDailyReportStatisticsVO> ryReports = iotRyDailyReportService.ryDailyReportStatistics(ryReqVO);
             if (CollUtil.isNotEmpty(ryReports)) {
                 for (IotRyDailyReportStatisticsVO ryReport : ryReports) {
@@ -235,7 +247,8 @@ public class IotRhDailyReportController {
     @GetMapping("/statistics")
     @Operation(summary = "获得瑞恒日报汇总统计")
     @PreAuthorize("@ss.hasPermission('pms:iot-rh-daily-report:query')")
-    public CommonResult<List<IotRhDailyReportStatisticsRespVO>> statistics(@Valid IotRhDailyReportPageReqVO pageReqVO) {
+    public CommonResult<Map<String, Object>> statistics(@Valid IotRhDailyReportPageReqVO pageReqVO) {
+        Map<String, Object> resultMap = new HashMap<>();
         List<IotRhDailyReportStatisticsRespVO> result = new ArrayList<>();
         // 根据查询参数筛选出 符合条件 的记录id 再传入 分页查询
         Set<Long> projectIds = new HashSet<>();
@@ -264,7 +277,9 @@ public class IotRhDailyReportController {
         }
         List<IotRhDailyReportStatisticsRespVO> statistics = iotRhDailyReportService.statistics(pageReqVO);
         result.addAll(statistics);
-        return success(result);
+        resultMap.put("list", result);
+        resultMap.put("total", result.size());
+        return success(resultMap);
     }
 
     @GetMapping("/polylineStatistics")
@@ -344,6 +359,7 @@ public class IotRhDailyReportController {
                 BigDecimal dailyGasInjection = report.getDailyGasInjection();
                 BigDecimal dailyWaterInjection = report.getDailyWaterInjection();
                 BigDecimal powerConsumption = report.getDailyPowerUsage();
+                BigDecimal oilConsumption = report.getDailyOilUsage();
                 if (ObjUtil.isNotEmpty(dailyGasInjection)) {
                     totalGasInjection = totalGasInjection.add(dailyGasInjection);
                 }
@@ -353,7 +369,9 @@ public class IotRhDailyReportController {
                 if (ObjUtil.isNotEmpty(powerConsumption)) {
                     totalPowerConsumption = totalPowerConsumption.add(powerConsumption);
                 }
-
+                if (ObjUtil.isNotEmpty(oilConsumption)) {
+                    totalFuelConsumption = totalFuelConsumption.add(oilConsumption);
+                }
             }
             // 汇总 指定搜索时间段内的 累计注气量 累计注水量 累计用电量 累计油耗
             result.put("totalGasInjection", totalGasInjection);
@@ -550,4 +568,56 @@ public class IotRhDailyReportController {
                 buildRhDailyReports(list));
     }
 
+    @GetMapping("/exportStatistics")
+    @Operation(summary = "导出瑞恒日报汇总 Excel")
+    @PreAuthorize("@ss.hasPermission('pms:iot-rh-daily-report:export')")
+    @ApiAccessLog(operateType = EXPORT)
+    public void exportStatistics(@Valid IotRhDailyReportPageReqVO pageReqVO,
+                                            HttpServletResponse response) throws IOException {
+        pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
+        // 根据查询参数筛选出 符合条件 的记录id 再传入 分页查询
+        Set<Long> projectIds = new HashSet<>();
+        Set<Long> taskIds = new HashSet<>();
+        if (StrUtil.isNotBlank(pageReqVO.getContractName())) {
+            IotProjectInfoPageReqVO reqVO = new IotProjectInfoPageReqVO();
+            reqVO.setContractName(pageReqVO.getContractName());
+            List<IotProjectInfoDO> projects = iotProjectInfoService.getIotProjectInfos(reqVO);
+            if (CollUtil.isNotEmpty(projects)) {
+                projects.forEach(project -> {
+                    projectIds.add(project.getId());
+                });
+                pageReqVO.setProjectIds(projectIds);
+            }
+        }
+        if (StrUtil.isNotBlank(pageReqVO.getTaskName())) {
+            IotProjectTaskPageReqVO reqVO = new IotProjectTaskPageReqVO();
+            reqVO.setSearchKey(pageReqVO.getTaskName());
+            List<IotProjectTaskDO> tasks = iotProjectTaskService.projectTasks(reqVO);
+            if (CollUtil.isNotEmpty(tasks)) {
+                tasks.forEach(task -> {
+                    taskIds.add(task.getId());
+                });
+                pageReqVO.setTaskIds(taskIds);
+            }
+        }
+        List<IotRhDailyReportStatisticsRespVO> statistics = iotRhDailyReportService.statistics(pageReqVO);
+        // 设置 运行时效 转换为 %
+        if (CollUtil.isNotEmpty(statistics)) {
+            statistics.forEach(stat -> {
+                BigDecimal transitTime = stat.getTransitTime();
+                if (ObjUtil.isEmpty(transitTime) || transitTime.compareTo(BigDecimal.ZERO) == 0) {
+                    stat.setTransitTimePercent("0.00%");
+                } else {
+                    // 转换逻辑:乘以100 → 保留2位小数(四舍五入)→ 拼接%
+                    BigDecimal percent = transitTime.multiply(new BigDecimal("100"))
+                            .setScale(2, RoundingMode.HALF_UP);
+                    stat.setTransitTimePercent(percent + "%");
+                }
+            });
+        }
+        // 导出 Excel
+        ExcelUtils.write(response, "瑞恒日报汇总.xls", "日报汇总数据",
+                IotRhDailyReportStatisticsRespVO.class, statistics);
+    }
+
 }

+ 194 - 0
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/iotrhdailyreport/IotZHBDController.java

@@ -0,0 +1,194 @@
+package cn.iocoder.yudao.module.pms.controller.admin.iotrhdailyreport;
+
+import cn.hutool.core.util.StrUtil;
+import cn.iocoder.yudao.framework.common.pojo.CommonResult;
+import cn.iocoder.yudao.module.pms.dal.mysql.IotDeviceMapper;
+import cn.iocoder.yudao.module.pms.dal.mysql.TDDeviceMapper;
+import cn.iocoder.yudao.module.pms.dal.mysql.iotopeationfill.IotOpeationFillMapper;
+import cn.iocoder.yudao.module.pms.job.httpEntity.ApiOilResponse;
+import cn.iocoder.yudao.module.pms.job.httpEntity.LoginRequestEntity;
+import cn.iocoder.yudao.module.pms.job.httpEntity.LoginResponseEntity;
+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.iotrhdailyreport.IotRhDailyReportService;
+import cn.iocoder.yudao.module.system.service.dept.DeptService;
+import cn.iocoder.yudao.module.system.service.dict.DictDataService;
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONObject;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import lombok.extern.slf4j.Slf4j;
+import okhttp3.OkHttpClient;
+import okhttp3.Request;
+import okhttp3.Response;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.redis.core.StringRedisTemplate;
+import org.springframework.http.*;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.client.RestTemplate;
+
+import javax.annotation.Resource;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.concurrent.TimeUnit;
+
+import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
+
+@Tag(name = "中航北斗")
+@RestController
+@RequestMapping("/pms/iot-rh-daily-report")
+@Validated
+@Slf4j
+public class IotZHBDController {
+
+    @Resource
+    private IotRhDailyReportService iotRhDailyReportService;
+    @Resource
+    private DeptService deptService;
+    @Resource
+    private IotProjectInfoService iotProjectInfoService;
+    @Resource
+    private IotProjectTaskService iotProjectTaskService;
+    @Resource
+    private DictDataService dictDataService;
+
+    private static final String ID = "NjI1LjUyNS42ODg";
+    private static final String SECRET = "3897865b70d7bf29fcca5029147f7d0a";
+    private static final String TOKEN_URL = "https://zhbdgps.cn/video/webapi/user/login";
+    private static final String LOCATION_URL="https://zhbdgps.cn/video/webapi/report/fuel/daily/detail";
+    private static final String parameter = "lng,lat,today_distance,distance,todayoil,totaloil,online,oil1,oil2,oil3,oil4,vehicle_name";
+    @Autowired
+    private StringRedisTemplate redisTemplate;
+    @Autowired
+    private RestTemplate restTemplate;
+    @Autowired
+    private IotOpeationFillMapper zhbdmapper;
+    @Autowired
+    private TDDeviceMapper deviceMapper;
+    @Autowired
+    private IotDeviceMapper iotDeviceMapper;
+
+    @GetMapping("/getOil")
+    @Operation(summary = "获得车辆油耗")
+    public CommonResult<Map<Integer, Double>> getIotRhDailyReport() {
+        String zhbdtoken = redisTemplate.opsForValue().get("zhbdtoken");
+        if (StrUtil.isBlank(zhbdtoken)) {
+            Map<String, String> map = new HashMap<>();
+            map.put("id", ID);
+            map.put("secret", SECRET);
+            JSONObject entries = restTemplate.postForObject(TOKEN_URL, map, JSONObject.class);
+            if (Objects.nonNull(entries)&&entries.get("code") != null&&Integer.parseInt(String.valueOf(entries.get("code")))==200) {
+                com.alibaba.fastjson.JSONObject jsonObject = JSON.parseObject(JSON.toJSONString(entries.get("data")));
+                zhbdtoken = jsonObject.get("token").toString();
+                redisTemplate.opsForValue().set("zhbdtoken", zhbdtoken, 80000, TimeUnit.SECONDS);
+            }
+        }
+        // 构建请求JSON
+        Map<String, Object> requestMap = new HashMap<>();
+        requestMap.put("client_ids", ID);
+        requestMap.put("vehicle_ids", "2109,14777");
+        requestMap.put("begin_time", "2025-11-15 8:00:00");
+        requestMap.put("end_time", "2025-11-30 8:00:00");
+        requestMap.put("page_num", 1);
+        requestMap.put("page_size", 10);
+        // key车辆carId   value油耗值
+        Map<Integer, Double> carOilFuelPair = new HashMap<>();
+        if (StrUtil.isNotBlank(zhbdtoken)) {
+            try {
+                String jsonResponse = sendPostRequest(requestMap, zhbdtoken);
+                ApiOilResponse response = parseResponse(jsonResponse);
+                if (response != null && response.code == 200) {
+                    List<Map<String, Object>> details = response.data.pageList;
+                    // 组装某辆车 某天的油耗
+
+                    for (Map<String, Object> detail : details) {
+                        System.out.println("当前油耗:" + (detail.get("oil")));
+                        Integer carId = Integer.valueOf(detail.get("vehicle_id").toString());
+                        Double oil = Double.valueOf(detail.get("oil").toString());
+                        String vehicleName = String.valueOf(detail.get("vehicle_name"));
+                        carOilFuelPair.put(carId, oil);
+                    }
+                }
+            } catch (Exception e) {
+                log.info("获取油耗数据失败!");
+            }
+        }
+        return success(carOilFuelPair);
+    }
+
+    private String getLoginToken(String id, String secret) {
+
+        // 2. 创建请求实体类
+        LoginRequestEntity request = new LoginRequestEntity();
+        request.setId(id);
+        request.setSecret(secret);
+
+        // 3. 设置请求头
+        HttpHeaders headers = new HttpHeaders();
+        headers.setContentType(MediaType.APPLICATION_JSON);
+
+        // 4. 封装请求实体
+        HttpEntity<LoginRequestEntity> entity = new HttpEntity<>(request, headers);
+
+        // 5. 发送POST请求
+        RestTemplate restTemplate = new RestTemplate();
+        ResponseEntity<LoginResponseEntity> response = restTemplate.exchange(
+                TOKEN_URL,
+                HttpMethod.POST,
+                entity,
+                LoginResponseEntity.class
+        );
+
+        // 6. 处理响应
+        if (response.getStatusCode() == HttpStatus.OK && response.getBody() != null) {
+            LoginResponseEntity body = response.getBody();
+            if (body.getData() != null && body.getData().getToken() != null) {
+                return body.getData().getToken();
+            } else {
+                log.error("登录响应中token为空,响应内容: {}", body);
+                return null;
+            }
+        } else {
+            log.error("登录失败,状态码: {}", response.getStatusCode());
+            return null;
+        }
+    }
+
+    private String sendPostRequest(Map<String, Object> requestData,String token) throws IOException {
+
+        OkHttpClient client = new OkHttpClient();
+        ObjectMapper objectMapper = new ObjectMapper();
+        String json = objectMapper.writeValueAsString(requestData);
+        okhttp3.RequestBody body = okhttp3.RequestBody.create(json, okhttp3.MediaType.parse("application/json"));
+
+        Request request = new Request.Builder()
+                .url(LOCATION_URL)
+                .post(body)
+                .addHeader("Content-Type", "application/json")
+                .addHeader("Authorization", "Bearer " + token)// 关键头信息
+                .build();
+        String responseData = "";
+        try (Response response = client.newCall(request).execute()) {
+            if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);
+            responseData = response.body().string();
+            System.out.println(responseData);
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+
+        return responseData;
+    }
+
+    private ApiOilResponse parseResponse(String json) throws IOException {
+        ObjectMapper mapper = new ObjectMapper();
+        return mapper.readValue(json, ApiOilResponse.class);
+    }
+
+}

+ 0 - 1
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/iotrhdailyreport/vo/IotRhDailyReportPolylineVO.java

@@ -6,7 +6,6 @@ import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 
 import java.math.BigDecimal;
-import java.time.LocalDateTime;
 
 @Schema(description = "管理后台 - 瑞恒日报 汇总统计 折线图 Response VO")
 @Data

+ 11 - 0
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/iotrhdailyreport/vo/IotRhDailyReportRespVO.java

@@ -1,5 +1,6 @@
 package cn.iocoder.yudao.module.pms.controller.admin.iotrhdailyreport.vo;
 
+import cn.iocoder.yudao.module.pms.dal.dataobject.iotdailyreportfuel.IotDailyReportFuelDO;
 import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
 import com.alibaba.excel.annotation.ExcelProperty;
 import io.swagger.v3.oas.annotations.media.Schema;
@@ -7,6 +8,7 @@ import lombok.Data;
 
 import java.math.BigDecimal;
 import java.time.LocalDateTime;
+import java.util.List;
 
 @Schema(description = "管理后台 - 瑞恒日报 Response VO")
 @Data
@@ -83,6 +85,10 @@ public class IotRhDailyReportRespVO {
     @ExcelProperty("当日用电量(kWh)")
     private BigDecimal dailyPowerUsage;
 
+    @Schema(description = "当日油耗(L)")
+    @ExcelProperty("当日油耗(L)")
+    private BigDecimal dailyOilUsage;
+
     @Schema(description = "非生产时间(H)")
     @ExcelProperty("非生产时间(H)")
     private BigDecimal nonProductionTime;
@@ -151,4 +157,9 @@ public class IotRhDailyReportRespVO {
     @Schema(description = "审批状态 未提交、审批中、审批通过、审批不通过、已取消", example = "1")
     private Integer auditStatus;
 
+    /**
+     * 扩展字段
+     */
+    @Schema(description = "日报关联的油耗记录")
+    private List<IotDailyReportFuelDO> reportFuels;
 }

+ 6 - 9
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/iotrhdailyreport/vo/IotRhDailyReportStatisticsRespVO.java

@@ -13,15 +13,12 @@ import java.math.BigDecimal;
 public class IotRhDailyReportStatisticsRespVO {
 
     @Schema(description = "主键id", requiredMode = Schema.RequiredMode.REQUIRED, example = "13853")
-    @ExcelProperty("主键id")
     private Long id;
 
     @Schema(description = "项目部id", example = "125")
-    @ExcelProperty("项目部id")
     private Long projectDeptId;
 
     @Schema(description = "队伍id", example = "125")
-    @ExcelProperty("队伍id")
     private Long teamId;
 
     @Schema(description = "项目部名称", example = "塔河项目部")
@@ -33,23 +30,20 @@ public class IotRhDailyReportStatisticsRespVO {
     private String teamName;
 
     @Schema(description = "任务id", example = "15678")
-    @ExcelProperty("任务id")
     private Long taskId;
 
     @Schema(description = "排序", example = "1")
-    @ExcelProperty("排序")
     private Integer sort;
 
     @Schema(description = "部门类型(公司级1 项目部2 队伍3)", example = "1")
-    @ExcelProperty("部门类型(公司级1 项目部2 队伍3)")
     private String type;
 
     @Schema(description = "累计注气量(方)")
     @ExcelProperty("累计注气量(方)")
     private BigDecimal cumulativeGasInjection = BigDecimal.ZERO;
 
-    @Schema(description = "累计注量(方)")
-    @ExcelProperty("累计注量(方)")
+    @Schema(description = "累计注量(方)")
+    @ExcelProperty("累计注量(方)")
     private BigDecimal cumulativeWaterInjection = BigDecimal.ZERO;
 
     @Schema(description = "累计用电量(kWh)")
@@ -61,7 +55,10 @@ public class IotRhDailyReportStatisticsRespVO {
     private BigDecimal cumulativeFuelConsumption = BigDecimal.ZERO;
 
     @Schema(description = "运行时效")
-    @ExcelProperty("运行时效")
     private BigDecimal transitTime = BigDecimal.ZERO;
 
+    @Schema(description = "运行时效")
+    @ExcelProperty("运行时效")
+    private String transitTimePercent;
+
 }

+ 100 - 2
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/iotrydailyreport/IotRyDailyReportController.java

@@ -34,6 +34,7 @@ import javax.servlet.http.HttpServletResponse;
 import javax.validation.Valid;
 import java.io.IOException;
 import java.math.BigDecimal;
+import java.math.RoundingMode;
 import java.time.LocalDateTime;
 import java.util.*;
 import java.util.concurrent.atomic.AtomicReference;
@@ -145,7 +146,8 @@ public class IotRyDailyReportController {
     @GetMapping("/statistics")
     @Operation(summary = "获得瑞鹰日报汇总统计")
     @PreAuthorize("@ss.hasPermission('pms:iot-ry-daily-report:query')")
-    public CommonResult<List<IotRyDailyReportStatisticsRespVO>> statistics(@Valid IotRyDailyReportPageReqVO pageReqVO) {
+    public CommonResult<Map<String, Object>> statistics(@Valid IotRyDailyReportPageReqVO pageReqVO) {
+        Map<String, Object> resultMap = new HashMap<>();
         List<IotRyDailyReportStatisticsRespVO> result = new ArrayList<>();
         // 根据查询参数筛选出 符合条件 的记录id 再传入 分页查询
         Set<Long> projectIds = new HashSet<>();
@@ -174,7 +176,9 @@ public class IotRyDailyReportController {
         }
         List<IotRyDailyReportStatisticsRespVO> statistics = iotRyDailyReportService.statistics(pageReqVO);
         result.addAll(statistics);
-        return success(result);
+        resultMap.put("list", result);
+        resultMap.put("total", result.size());
+        return success(resultMap);
     }
 
     /**
@@ -318,6 +322,41 @@ public class IotRyDailyReportController {
         });
     }
 
+    @GetMapping("/polylineStatistics")
+    @Operation(summary = "获得瑞鹰日报汇总统计 折线图")
+    @PreAuthorize("@ss.hasPermission('pms:iot-ry-daily-report:query')")
+    public CommonResult<List<IotRyDailyReportPolylineVO>> polylineStatistics(@Valid IotRyDailyReportPageReqVO pageReqVO) {
+        List<IotRyDailyReportPolylineVO> result = new ArrayList<>();
+        // 根据查询参数筛选出 符合条件 的记录id 再传入 分页查询
+        Set<Long> projectIds = new HashSet<>();
+        Set<Long> taskIds = new HashSet<>();
+        if (StrUtil.isNotBlank(pageReqVO.getContractName())) {
+            IotProjectInfoPageReqVO reqVO = new IotProjectInfoPageReqVO();
+            reqVO.setContractName(pageReqVO.getContractName());
+            List<IotProjectInfoDO> projects = iotProjectInfoService.getIotProjectInfos(reqVO);
+            if (CollUtil.isNotEmpty(projects)) {
+                projects.forEach(project -> {
+                    projectIds.add(project.getId());
+                });
+                pageReqVO.setProjectIds(projectIds);
+            }
+        }
+        if (StrUtil.isNotBlank(pageReqVO.getTaskName())) {
+            IotProjectTaskPageReqVO reqVO = new IotProjectTaskPageReqVO();
+            reqVO.setSearchKey(pageReqVO.getTaskName());
+            List<IotProjectTaskDO> tasks = iotProjectTaskService.projectTasks(reqVO);
+            if (CollUtil.isNotEmpty(tasks)) {
+                tasks.forEach(task -> {
+                    taskIds.add(task.getId());
+                });
+                pageReqVO.setTaskIds(taskIds);
+            }
+        }
+        List<IotRyDailyReportPolylineVO> statistics = iotRyDailyReportService.polylineStatistics(pageReqVO);
+        result.addAll(statistics);
+        return success(result);
+    }
+
     @GetMapping("/totalWorkload")
     @Operation(summary = "累计工作量统计")
     @PreAuthorize("@ss.hasPermission('pms:iot-ry-daily-report:query')")
@@ -432,4 +471,63 @@ public class IotRyDailyReportController {
                         BeanUtils.toBean(list, IotRyDailyReportRespVO.class));
     }
 
+    @GetMapping("/exportStatistics")
+    @Operation(summary = "导出瑞鹰日报汇总 Excel")
+    @PreAuthorize("@ss.hasPermission('pms:iot-ry-daily-report:export')")
+    @ApiAccessLog(operateType = EXPORT)
+    public void exportStatistics(@Valid IotRyDailyReportPageReqVO pageReqVO,
+                                 HttpServletResponse response) throws IOException {
+        pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
+        // 根据查询参数筛选出 符合条件 的记录id 再传入 分页查询
+        Set<Long> projectIds = new HashSet<>();
+        Set<Long> taskIds = new HashSet<>();
+        if (StrUtil.isNotBlank(pageReqVO.getContractName())) {
+            IotProjectInfoPageReqVO reqVO = new IotProjectInfoPageReqVO();
+            reqVO.setContractName(pageReqVO.getContractName());
+            List<IotProjectInfoDO> projects = iotProjectInfoService.getIotProjectInfos(reqVO);
+            if (CollUtil.isNotEmpty(projects)) {
+                projects.forEach(project -> {
+                    projectIds.add(project.getId());
+                });
+                pageReqVO.setProjectIds(projectIds);
+            }
+        }
+        if (StrUtil.isNotBlank(pageReqVO.getTaskName())) {
+            IotProjectTaskPageReqVO reqVO = new IotProjectTaskPageReqVO();
+            reqVO.setSearchKey(pageReqVO.getTaskName());
+            List<IotProjectTaskDO> tasks = iotProjectTaskService.projectTasks(reqVO);
+            if (CollUtil.isNotEmpty(tasks)) {
+                tasks.forEach(task -> {
+                    taskIds.add(task.getId());
+                });
+                pageReqVO.setTaskIds(taskIds);
+            }
+        }
+        List<IotRyDailyReportStatisticsRespVO> statistics = iotRyDailyReportService.statistics(pageReqVO);
+        if (CollUtil.isNotEmpty(statistics)) {
+            statistics.forEach(stat -> {
+                BigDecimal transitTime = stat.getTransitTime();
+                if (ObjUtil.isEmpty(transitTime) || transitTime.compareTo(BigDecimal.ZERO) == 0) {
+                    stat.setTransitTimePercent("0.00%");
+                } else {
+                    // 转换逻辑:乘以100 → 保留2位小数(四舍五入)→ 拼接%
+                    BigDecimal percent = transitTime.multiply(new BigDecimal("100"))
+                            .setScale(2, RoundingMode.HALF_UP);
+                    stat.setTransitTimePercent(percent + "%");
+                }
+            });
+        }
+        String sheetName = StrUtil.EMPTY;
+        if ("1".equals(pageReqVO.getProjectClassification())) {
+            // 钻井日报汇总数据
+            sheetName = "钻井日报汇总数据";
+        } else {
+            // 修井日报汇总数据
+            sheetName = "修井日报汇总数据";
+        }
+        // 导出 Excel
+        ExcelUtils.write(response, "瑞鹰日报汇总.xls", sheetName,
+                IotRyDailyReportStatisticsRespVO.class, statistics);
+    }
+
 }

+ 67 - 0
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/iotrydailyreport/vo/IotRyDailyReportPolylineVO.java

@@ -0,0 +1,67 @@
+package cn.iocoder.yudao.module.pms.controller.admin.iotrydailyreport.vo;
+
+import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
+import com.alibaba.excel.annotation.ExcelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.math.BigDecimal;
+
+@Schema(description = "管理后台 - 瑞鹰日报 汇总统计 折线图 Response VO")
+@Data
+@ExcelIgnoreUnannotated
+public class IotRyDailyReportPolylineVO {
+
+    @Schema(description = "项目部id", example = "125")
+    @ExcelProperty("项目部id")
+    private Long projectDeptId;
+
+    @Schema(description = "队伍id", example = "125")
+    @ExcelProperty("队伍id")
+    private Long teamId;
+
+    @Schema(description = "项目部名称", example = "新疆目部")
+    @ExcelProperty("项目部名称")
+    private String projectDeptName;
+
+    @Schema(description = "队伍名称", example = "7009队")
+    @ExcelProperty("队伍名称")
+    private String teamName;
+
+    @Schema(description = "任务id", example = "15678")
+    @ExcelProperty("任务id")
+    private Long taskId;
+
+    @Schema(description = "日报日期 yyyy-MM-dd", example = "1")
+    @ExcelProperty("日报日期 yyyy-MM-dd")
+    private String reportDate;
+
+    @Schema(description = "部门类型(公司级1 项目部2 队伍3)", example = "1")
+    @ExcelProperty("部门类型(公司级1 项目部2 队伍3)")
+    private String type;
+
+    @Schema(description = "累计进尺(m)")
+    @ExcelProperty("累计进尺(m)")
+    private BigDecimal cumulativeFootage = BigDecimal.ZERO;
+
+    @Schema(description = "累计施工井数")
+    @ExcelProperty("累计施工井数")
+    private Integer cumulativeConstructWells = 0;
+
+    @Schema(description = "累计完工井数")
+    @ExcelProperty("累计完工井数")
+    private Integer cumulativeCompletedWells = 0;
+
+    @Schema(description = "累计用电量(kWh)")
+    @ExcelProperty("累计用电量(kWh)")
+    private BigDecimal cumulativePowerConsumption = BigDecimal.ZERO;
+
+    @Schema(description = "累计油耗(吨)")
+    @ExcelProperty("累计油耗(吨)")
+    private BigDecimal cumulativeFuelConsumption = BigDecimal.ZERO;
+
+    @Schema(description = "运行时效")
+    @ExcelProperty("运行时效")
+    private BigDecimal transitTime = BigDecimal.ZERO;
+
+}

+ 4 - 7
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/iotrydailyreport/vo/IotRyDailyReportStatisticsRespVO.java

@@ -13,15 +13,12 @@ import java.math.BigDecimal;
 public class IotRyDailyReportStatisticsRespVO {
 
     @Schema(description = "主键id", requiredMode = Schema.RequiredMode.REQUIRED, example = "13853")
-    @ExcelProperty("主键id")
     private Long id;
 
     @Schema(description = "项目部id", example = "125")
-    @ExcelProperty("项目部id")
     private Long projectDeptId;
 
     @Schema(description = "队伍id", example = "125")
-    @ExcelProperty("队伍id")
     private Long teamId;
 
     @Schema(description = "项目部名称", example = "新疆项目部")
@@ -33,15 +30,12 @@ public class IotRyDailyReportStatisticsRespVO {
     private String teamName;
 
     @Schema(description = "任务id", example = "15678")
-    @ExcelProperty("任务id")
     private Long taskId;
 
     @Schema(description = "排序", example = "1")
-    @ExcelProperty("排序")
     private Integer sort;
 
     @Schema(description = "部门类型(公司级1 项目部2 队伍3)", example = "1")
-    @ExcelProperty("部门类型(公司级1 项目部2 队伍3)")
     private String type;
 
     @Schema(description = "累计进尺(m)")
@@ -65,7 +59,10 @@ public class IotRyDailyReportStatisticsRespVO {
     private BigDecimal cumulativeFuelConsumption = BigDecimal.ZERO;
 
     @Schema(description = "运行时效")
-    @ExcelProperty("运行时效")
     private BigDecimal transitTime = BigDecimal.ZERO;
 
+    @Schema(description = "运行时效")
+    @ExcelProperty("运行时效")
+    private String transitTimePercent;
+
 }

+ 47 - 7
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/stat/IotStaticController.java

@@ -12,6 +12,7 @@ import cn.iocoder.yudao.framework.common.pojo.Pms;
 import cn.iocoder.yudao.framework.common.util.date.DateUtils;
 import cn.iocoder.yudao.framework.common.util.number.NumberUtils;
 import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
+import cn.iocoder.yudao.module.pms.controller.admin.depttype.vo.IotDeptTypePageReqVO;
 import cn.iocoder.yudao.module.pms.controller.admin.failure.vo.IotFailureReportPageReqVO;
 import cn.iocoder.yudao.module.pms.controller.admin.inspect.order.vo.IotInspectOrderPageReqVO;
 import cn.iocoder.yudao.module.pms.controller.admin.inspect.plan.vo.IotInspectPlanPageReqVO;
@@ -34,6 +35,7 @@ import cn.iocoder.yudao.module.pms.controller.admin.vo.IotDevicePageReqVO;
 import cn.iocoder.yudao.module.pms.controller.admin.vo.IotProductClassifyListReqVO;
 import cn.iocoder.yudao.module.pms.dal.dataobject.IotDeviceDO;
 import cn.iocoder.yudao.module.pms.dal.dataobject.IotProductClassifyDO;
+import cn.iocoder.yudao.module.pms.dal.dataobject.depttype.IotDeptTypeDO;
 import cn.iocoder.yudao.module.pms.dal.dataobject.failure.IotFailureReportDO;
 import cn.iocoder.yudao.module.pms.dal.dataobject.inspect.IotInspectOrderDO;
 import cn.iocoder.yudao.module.pms.dal.dataobject.inspect.IotInspectOrderDetailDO;
@@ -49,6 +51,7 @@ import cn.iocoder.yudao.module.pms.dal.dataobject.maintain.IotMaintainDO;
 import cn.iocoder.yudao.module.pms.dal.mysql.IotDeviceMapper;
 import cn.iocoder.yudao.module.pms.dal.mysql.IotProductClassifyMapper;
 import cn.iocoder.yudao.module.pms.dal.mysql.TDDeviceMapper;
+import cn.iocoder.yudao.module.pms.dal.mysql.depttype.IotDeptTypeMapper;
 import cn.iocoder.yudao.module.pms.dal.mysql.failure.IotFailureReportMapper;
 import cn.iocoder.yudao.module.pms.dal.mysql.inspect.IotInspectOrderDetailMapper;
 import cn.iocoder.yudao.module.pms.dal.mysql.inspect.IotInspectOrderMapper;
@@ -166,6 +169,8 @@ public class IotStaticController {
     private IotRyDailyReportMapper iotRyDailyReportMapper;
     @Autowired
     private IotRdDailyReportMapper iotRdDailyReportMapper;
+    @Resource
+    private IotDeptTypeMapper iotDeptTypeMapper;
 
     @GetMapping("/main/day")
     public CommonResult<Map<String, Object>> getMaintainDay() {
@@ -1194,12 +1199,32 @@ public class IotStaticController {
         Set<Long> projectDeptIds = new HashSet<>();
         // key项目部id     value项目部名称
         Map<Long, String> projectDeptPair = new HashMap<>();
+
+        IotDeptTypePageReqVO deptTypeReqVO = new IotDeptTypePageReqVO();
+        // 查询 钻井 修井 类型的部门
+        if ("repair".equals(type)) {
+            // 修井
+            deptTypeReqVO.setType("xj");
+        } else {
+            // 钻井
+            deptTypeReqVO.setType("zj");
+        }
+        List<IotDeptTypeDO> deptTypes = iotDeptTypeMapper.selectList(deptTypeReqVO);
+        List<Long> zjOrXjDeptIds = new ArrayList<>();
+        if (CollUtil.isNotEmpty(deptTypes)) {
+            deptTypes.forEach(dept -> {
+                zjOrXjDeptIds.add(dept.getDeptId());
+            });
+        }
+
         if (CollUtil.isNotEmpty(depts)) {
             depts.forEach(dept -> {
-                if (dept.getName().contains("项目部")) {
+                // 类型(公司级1 项目部2 队伍3)
+                if ("2".equals(dept.getType())) {
                     projectDeptIds.add(dept.getId());
                     projectDeptPair.put(dept.getId(), dept.getName());
-                } else {
+                }
+                if ("3".equals(dept.getType()) && zjOrXjDeptIds.contains(dept.getId())) {
                     teamProjectPair.put(dept.getId(), dept.getParentId());
                 }
             });
@@ -1350,8 +1375,6 @@ public class IotStaticController {
             ImmutableMap<String, Serializable> yearResult = ImmutableMap.of("name", "年累进尺~~en**annualFootage", "data", yearData);
             return success(ImmutableMap.of("xAxis", xAxis, "series", ImmutableList.of(dailyResult, monthResult, yearResult)));
         }
-
-
     }
 
     /**
@@ -1372,20 +1395,37 @@ public class IotStaticController {
         Set<Long> projectDeptIds = new HashSet<>();
         // key项目部id     value项目部名称
         Map<Long, String> projectDeptPair = new HashMap<>();
+
+        // 查询 钻井 业务相关 部门
+        IotDeptTypePageReqVO deptTypeReqVO = new IotDeptTypePageReqVO();
+        deptTypeReqVO.setType("zj");
+        List<IotDeptTypeDO> deptTypes = iotDeptTypeMapper.selectList(deptTypeReqVO);
+        List<Long> zjOrXjDeptIds = new ArrayList<>();
+        if (CollUtil.isNotEmpty(deptTypes)) {
+            deptTypes.forEach(dept -> {
+                zjOrXjDeptIds.add(dept.getDeptId());
+            });
+        }
+
         if (CollUtil.isNotEmpty(depts)) {
             depts.forEach(dept -> {
-                if (dept.getName().contains("项目部")) {
+                // 类型(公司级1 项目部2 队伍3)
+                if ("2".equals(dept.getType())) {
+                    // 项目部
                     projectDeptIds.add(dept.getId());
                     projectDeptPair.put(dept.getId(), dept.getName());
-                } else {
+                }
+                if ("3".equals(dept.getType()) && zjOrXjDeptIds.contains(dept.getId())) {
+                    // 队伍
                     teamProjectPair.put(dept.getId(), dept.getParentId());
                     teamPair.put(dept.getId(), dept.getName());
                 }
             });
         }
+
         IotRyDailyReportPageReqVO reqVO = new IotRyDailyReportPageReqVO();
         // 钻井
-        reqVO.setProjectClassification("2");
+        reqVO.setProjectClassification("1");
         // 钻井 日报统计 月完井数 年完井数
         List<IotRyDailyReportTaskCountVO> repairReports = iotRyDailyReportService.countDateRigTasksByDepartment();
         Map<String, Integer> deptDailyPair = new HashMap<>();

+ 50 - 0
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/dal/dataobject/iotcarzhbd/IotCarZhbdDO.java

@@ -0,0 +1,50 @@
+package cn.iocoder.yudao.module.pms.dal.dataobject.iotcarzhbd;
+
+import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
+import com.baomidou.mybatisplus.annotation.KeySequence;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.*;
+
+/**
+ * 中航北斗车辆表 DO
+ *
+ * @author ruiqi
+ */
+@TableName("rq_iot_car_zhbd")
+@KeySequence("rq_iot_car_zhbd_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class IotCarZhbdDO extends BaseDO {
+
+    /**
+     * 主键id
+     */
+    @TableId
+    private Long id;
+    /**
+     * 组织id
+     */
+    private String deviceCode;
+    /**
+     * 工单名称
+     */
+    private String deviceName;
+    /**
+     * 工单类型
+     */
+    private String carId;
+    /**
+     * 用户名称
+     */
+    private String userName;
+    /**
+     * 用户id
+     */
+    private Long userId;
+
+}

+ 77 - 0
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/dal/dataobject/iotdailyreportfuel/IotDailyReportFuelDO.java

@@ -0,0 +1,77 @@
+package cn.iocoder.yudao.module.pms.dal.dataobject.iotdailyreportfuel;
+
+import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
+import com.baomidou.mybatisplus.annotation.KeySequence;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.*;
+
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+
+/**
+ * 日报-油耗 DO
+ *
+ * @author ruiqi
+ */
+@TableName("rq_iot_daily_report_fuel")
+@KeySequence("rq_iot_daily_report_fuel_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class IotDailyReportFuelDO extends BaseDO {
+
+    /**
+     * 主键id
+     */
+    @TableId
+    private Long id;
+    /**
+     * 瑞恒RH 瑞鹰RY 瑞都RD
+     */
+    private String type;
+    /**
+     * 日报id
+     */
+    private Long reportId;
+    /**
+     * 设备(车辆)id
+     */
+    private Long deviceId;
+    /**
+     * 设备编码
+     */
+    private String deviceCode;
+    /**
+     * 油服设备编码
+     */
+    private String yfDeviceCode;
+    /**
+     * 设备名称
+     */
+    private String deviceName;
+    /**
+     * zhbd车辆id
+     */
+    private String carId;
+    /**
+     * zhdb油耗(L)
+     */
+    private BigDecimal zhbdFuel;
+    /**
+     * 修正后的油耗(L)
+     */
+    private BigDecimal customFuel;
+    /**
+     * 获取油耗时的日期
+     */
+    private LocalDateTime queryDate;
+    /**
+     * 备注
+     */
+    private String remark;
+
+}

+ 4 - 0
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/dal/dataobject/iotrhdailyreport/IotRhDailyReportDO.java

@@ -73,6 +73,10 @@ public class IotRhDailyReportDO extends BaseDO {
      * 当日用电量(kWh)
      */
     private BigDecimal dailyPowerUsage;
+    /**
+     * 当日油耗(L)
+     */
+    private BigDecimal dailyOilUsage;
     /**
      * 非生产时间(H)
      */

+ 43 - 0
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/dal/mysql/iotcarzhbd/IotCarZhbdMapper.java

@@ -0,0 +1,43 @@
+package cn.iocoder.yudao.module.pms.dal.mysql.iotcarzhbd;
+
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
+import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
+import cn.iocoder.yudao.module.pms.controller.admin.iotcarzhbd.vo.IotCarZhbdPageReqVO;
+import cn.iocoder.yudao.module.pms.dal.dataobject.iotcarzhbd.IotCarZhbdDO;
+import org.apache.ibatis.annotations.Mapper;
+
+import java.util.List;
+
+/**
+ * 中航北斗车辆表 Mapper
+ *
+ * @author ruiqi
+ */
+@Mapper
+public interface IotCarZhbdMapper extends BaseMapperX<IotCarZhbdDO> {
+
+    default PageResult<IotCarZhbdDO> selectPage(IotCarZhbdPageReqVO reqVO) {
+        return selectPage(reqVO, new LambdaQueryWrapperX<IotCarZhbdDO>()
+                .eqIfPresent(IotCarZhbdDO::getDeviceCode, reqVO.getDeviceCode())
+                .likeIfPresent(IotCarZhbdDO::getDeviceName, reqVO.getDeviceName())
+                .eqIfPresent(IotCarZhbdDO::getCarId, reqVO.getCarId())
+                .betweenIfPresent(IotCarZhbdDO::getCreateTime, reqVO.getCreateTime())
+                .likeIfPresent(IotCarZhbdDO::getUserName, reqVO.getUserName())
+                .eqIfPresent(IotCarZhbdDO::getUserId, reqVO.getUserId())
+                .orderByDesc(IotCarZhbdDO::getId));
+    }
+
+    default List<IotCarZhbdDO> selectList(IotCarZhbdPageReqVO reqVO) {
+        return selectList(new LambdaQueryWrapperX<IotCarZhbdDO>()
+                .eqIfPresent(IotCarZhbdDO::getDeviceCode, reqVO.getDeviceCode())
+                .likeIfPresent(IotCarZhbdDO::getDeviceName, reqVO.getDeviceName())
+                .eqIfPresent(IotCarZhbdDO::getCarId, reqVO.getCarId())
+                .betweenIfPresent(IotCarZhbdDO::getCreateTime, reqVO.getCreateTime())
+                .likeIfPresent(IotCarZhbdDO::getUserName, reqVO.getUserName())
+                .inIfPresent(IotCarZhbdDO::getUserName, reqVO.getCustomDeviceCodes())
+                .eqIfPresent(IotCarZhbdDO::getUserId, reqVO.getUserId())
+                .orderByDesc(IotCarZhbdDO::getId));
+    }
+
+}

+ 54 - 0
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/dal/mysql/iotdailyreportfuel/IotDailyReportFuelMapper.java

@@ -0,0 +1,54 @@
+package cn.iocoder.yudao.module.pms.dal.mysql.iotdailyreportfuel;
+
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
+import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
+import cn.iocoder.yudao.module.pms.controller.admin.iotdailyreportfuel.vo.IotDailyReportFuelPageReqVO;
+import cn.iocoder.yudao.module.pms.dal.dataobject.iotdailyreportfuel.IotDailyReportFuelDO;
+import org.apache.ibatis.annotations.Mapper;
+
+import java.util.List;
+
+/**
+ * 日报-油耗 Mapper
+ *
+ * @author ruiqi
+ */
+@Mapper
+public interface IotDailyReportFuelMapper extends BaseMapperX<IotDailyReportFuelDO> {
+
+    default PageResult<IotDailyReportFuelDO> selectPage(IotDailyReportFuelPageReqVO reqVO) {
+        return selectPage(reqVO, new LambdaQueryWrapperX<IotDailyReportFuelDO>()
+                .eqIfPresent(IotDailyReportFuelDO::getType, reqVO.getType())
+                .eqIfPresent(IotDailyReportFuelDO::getReportId, reqVO.getReportId())
+                .eqIfPresent(IotDailyReportFuelDO::getDeviceId, reqVO.getDeviceId())
+                .eqIfPresent(IotDailyReportFuelDO::getDeviceCode, reqVO.getDeviceCode())
+                .eqIfPresent(IotDailyReportFuelDO::getYfDeviceCode, reqVO.getYfDeviceCode())
+                .likeIfPresent(IotDailyReportFuelDO::getDeviceName, reqVO.getDeviceName())
+                .eqIfPresent(IotDailyReportFuelDO::getCarId, reqVO.getCarId())
+                .eqIfPresent(IotDailyReportFuelDO::getZhbdFuel, reqVO.getZhbdFuel())
+                .eqIfPresent(IotDailyReportFuelDO::getCustomFuel, reqVO.getCustomFuel())
+                .betweenIfPresent(IotDailyReportFuelDO::getQueryDate, reqVO.getQueryDate())
+                .eqIfPresent(IotDailyReportFuelDO::getRemark, reqVO.getRemark())
+                .betweenIfPresent(IotDailyReportFuelDO::getCreateTime, reqVO.getCreateTime())
+                .orderByDesc(IotDailyReportFuelDO::getId));
+    }
+
+    default List<IotDailyReportFuelDO> selectList(IotDailyReportFuelPageReqVO reqVO) {
+        return selectList(new LambdaQueryWrapperX<IotDailyReportFuelDO>()
+                .eqIfPresent(IotDailyReportFuelDO::getType, reqVO.getType())
+                .eqIfPresent(IotDailyReportFuelDO::getReportId, reqVO.getReportId())
+                .eqIfPresent(IotDailyReportFuelDO::getDeviceId, reqVO.getDeviceId())
+                .eqIfPresent(IotDailyReportFuelDO::getDeviceCode, reqVO.getDeviceCode())
+                .eqIfPresent(IotDailyReportFuelDO::getYfDeviceCode, reqVO.getYfDeviceCode())
+                .likeIfPresent(IotDailyReportFuelDO::getDeviceName, reqVO.getDeviceName())
+                .eqIfPresent(IotDailyReportFuelDO::getCarId, reqVO.getCarId())
+                .eqIfPresent(IotDailyReportFuelDO::getZhbdFuel, reqVO.getZhbdFuel())
+                .eqIfPresent(IotDailyReportFuelDO::getCustomFuel, reqVO.getCustomFuel())
+                .betweenIfPresent(IotDailyReportFuelDO::getQueryDate, reqVO.getQueryDate())
+                .eqIfPresent(IotDailyReportFuelDO::getRemark, reqVO.getRemark())
+                .betweenIfPresent(IotDailyReportFuelDO::getCreateTime, reqVO.getCreateTime())
+                .orderByDesc(IotDailyReportFuelDO::getId));
+    }
+
+}

+ 33 - 0
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/job/IotDeviceCarFuelVO.java

@@ -0,0 +1,33 @@
+package cn.iocoder.yudao.module.pms.job;
+
+import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+@Schema(description = "管理后台 - zhbd 车辆-油耗 VO")
+@Data
+@ExcelIgnoreUnannotated
+public class IotDeviceCarFuelVO {
+
+    @Schema(description = "油耗", example = "10.37 (L)")
+    private Double oil;
+
+    @Schema(description = "行驶里程", example = "43.39km")
+    private Double distance;
+
+    @Schema(description = "百公里油耗", example = "23.9 (L)")
+    private String oilkilmeter;
+
+    @Schema(description = "时间", example = "2025-11-26")
+    private String createtime;
+
+    @Schema(description = "车辆id", example = "8203")
+    private Integer vehicleId;
+
+    @Schema(description = "客户名称", example = "威远")
+    private String clientName;
+
+    @Schema(description = "车牌号", example = "鲁E99659底盘")
+    private String vehicleName;
+
+}

+ 14 - 0
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/job/httpEntity/ApiOilResponse.java

@@ -0,0 +1,14 @@
+package cn.iocoder.yudao.module.pms.job.httpEntity;
+
+/**
+ * @author suiyy
+ * @version 1.0
+ * @className ApiResponse
+ * @date 2025/12/1 14:56
+ * @description
+ */
+public class ApiOilResponse {
+    public int code;
+    public ResponseOilData data;
+    public String message;
+}

+ 16 - 0
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/job/httpEntity/ResponseOilData.java

@@ -0,0 +1,16 @@
+package cn.iocoder.yudao.module.pms.job.httpEntity;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author suiyy
+ * @version 1.0
+ * @className ResponseData
+ * @date 2025/12/1 14:58
+ * @description
+ */
+public class ResponseOilData {
+    public List<Map<String,Object>> pageList;
+    public long total;
+}

+ 55 - 0
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/service/iotcarzhbd/IotCarZhbdService.java

@@ -0,0 +1,55 @@
+package cn.iocoder.yudao.module.pms.service.iotcarzhbd;
+
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.module.pms.controller.admin.iotcarzhbd.vo.IotCarZhbdPageReqVO;
+import cn.iocoder.yudao.module.pms.controller.admin.iotcarzhbd.vo.IotCarZhbdSaveReqVO;
+import cn.iocoder.yudao.module.pms.dal.dataobject.iotcarzhbd.IotCarZhbdDO;
+
+import javax.validation.Valid;
+
+/**
+ * 中航北斗车辆表 Service 接口
+ *
+ * @author ruiqi
+ */
+public interface IotCarZhbdService {
+
+    /**
+     * 创建中航北斗车辆表
+     *
+     * @param createReqVO 创建信息
+     * @return 编号
+     */
+    Long createIotCarZhbd(@Valid IotCarZhbdSaveReqVO createReqVO);
+
+    /**
+     * 更新中航北斗车辆表
+     *
+     * @param updateReqVO 更新信息
+     */
+    void updateIotCarZhbd(@Valid IotCarZhbdSaveReqVO updateReqVO);
+
+    /**
+     * 删除中航北斗车辆表
+     *
+     * @param id 编号
+     */
+    void deleteIotCarZhbd(Long id);
+
+    /**
+     * 获得中航北斗车辆表
+     *
+     * @param id 编号
+     * @return 中航北斗车辆表
+     */
+    IotCarZhbdDO getIotCarZhbd(Long id);
+
+    /**
+     * 获得中航北斗车辆表分页
+     *
+     * @param pageReqVO 分页查询
+     * @return 中航北斗车辆表分页
+     */
+    PageResult<IotCarZhbdDO> getIotCarZhbdPage(IotCarZhbdPageReqVO pageReqVO);
+
+}

+ 71 - 0
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/service/iotcarzhbd/IotCarZhbdServiceImpl.java

@@ -0,0 +1,71 @@
+package cn.iocoder.yudao.module.pms.service.iotcarzhbd;
+
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
+import cn.iocoder.yudao.module.pms.controller.admin.iotcarzhbd.vo.IotCarZhbdPageReqVO;
+import cn.iocoder.yudao.module.pms.controller.admin.iotcarzhbd.vo.IotCarZhbdSaveReqVO;
+import cn.iocoder.yudao.module.pms.dal.dataobject.iotcarzhbd.IotCarZhbdDO;
+import cn.iocoder.yudao.module.pms.dal.mysql.iotcarzhbd.IotCarZhbdMapper;
+import org.springframework.stereotype.Service;
+import org.springframework.validation.annotation.Validated;
+
+import javax.annotation.Resource;
+
+import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
+import static cn.iocoder.yudao.module.pms.enums.ErrorCodeConstant.IOT_CAR_ZHBD_NOT_EXISTS;
+
+/**
+ * 中航北斗车辆表 Service 实现类
+ *
+ * @author ruiqi
+ */
+@Service
+@Validated
+public class IotCarZhbdServiceImpl implements IotCarZhbdService {
+
+    @Resource
+    private IotCarZhbdMapper iotCarZhbdMapper;
+
+    @Override
+    public Long createIotCarZhbd(IotCarZhbdSaveReqVO createReqVO) {
+        // 插入
+        IotCarZhbdDO iotCarZhbd = BeanUtils.toBean(createReqVO, IotCarZhbdDO.class);
+        iotCarZhbdMapper.insert(iotCarZhbd);
+        // 返回
+        return iotCarZhbd.getId();
+    }
+
+    @Override
+    public void updateIotCarZhbd(IotCarZhbdSaveReqVO updateReqVO) {
+        // 校验存在
+        validateIotCarZhbdExists(updateReqVO.getId());
+        // 更新
+        IotCarZhbdDO updateObj = BeanUtils.toBean(updateReqVO, IotCarZhbdDO.class);
+        iotCarZhbdMapper.updateById(updateObj);
+    }
+
+    @Override
+    public void deleteIotCarZhbd(Long id) {
+        // 校验存在
+        validateIotCarZhbdExists(id);
+        // 删除
+        iotCarZhbdMapper.deleteById(id);
+    }
+
+    private void validateIotCarZhbdExists(Long id) {
+        if (iotCarZhbdMapper.selectById(id) == null) {
+            throw exception(IOT_CAR_ZHBD_NOT_EXISTS);
+        }
+    }
+
+    @Override
+    public IotCarZhbdDO getIotCarZhbd(Long id) {
+        return iotCarZhbdMapper.selectById(id);
+    }
+
+    @Override
+    public PageResult<IotCarZhbdDO> getIotCarZhbdPage(IotCarZhbdPageReqVO pageReqVO) {
+        return iotCarZhbdMapper.selectPage(pageReqVO);
+    }
+
+}

+ 64 - 0
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/service/iotdailyreportfuel/IotDailyReportFuelService.java

@@ -0,0 +1,64 @@
+package cn.iocoder.yudao.module.pms.service.iotdailyreportfuel;
+
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.module.pms.controller.admin.iotdailyreportfuel.vo.IotDailyReportFuelPageReqVO;
+import cn.iocoder.yudao.module.pms.controller.admin.iotdailyreportfuel.vo.IotDailyReportFuelSaveReqVO;
+import cn.iocoder.yudao.module.pms.dal.dataobject.iotdailyreportfuel.IotDailyReportFuelDO;
+
+import javax.validation.Valid;
+import java.util.List;
+
+/**
+ * 日报-油耗 Service 接口
+ *
+ * @author ruiqi
+ */
+public interface IotDailyReportFuelService {
+
+    /**
+     * 创建日报-油耗
+     *
+     * @param createReqVO 创建信息
+     * @return 编号
+     */
+    Long createIotDailyReportFuel(@Valid IotDailyReportFuelSaveReqVO createReqVO);
+
+    /**
+     * 更新日报-油耗
+     *
+     * @param updateReqVO 更新信息
+     */
+    void updateIotDailyReportFuel(@Valid IotDailyReportFuelSaveReqVO updateReqVO);
+
+    /**
+     * 删除日报-油耗
+     *
+     * @param id 编号
+     */
+    void deleteIotDailyReportFuel(Long id);
+
+    /**
+     * 获得日报-油耗
+     *
+     * @param id 编号
+     * @return 日报-油耗
+     */
+    IotDailyReportFuelDO getIotDailyReportFuel(Long id);
+
+    /**
+     * 获得日报-油耗分页
+     *
+     * @param pageReqVO 分页查询
+     * @return 日报-油耗分页
+     */
+    PageResult<IotDailyReportFuelDO> getIotDailyReportFuelPage(IotDailyReportFuelPageReqVO pageReqVO);
+
+    /**
+     * 获得日报-油耗列表
+     *
+     * @param pageReqVO 列表查询
+     * @return 日报-油耗列表
+     */
+    List<IotDailyReportFuelDO> getIotDailyReportFuels(IotDailyReportFuelPageReqVO pageReqVO);
+
+}

+ 78 - 0
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/service/iotdailyreportfuel/IotDailyReportFuelServiceImpl.java

@@ -0,0 +1,78 @@
+package cn.iocoder.yudao.module.pms.service.iotdailyreportfuel;
+
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
+import cn.iocoder.yudao.module.pms.controller.admin.iotdailyreportfuel.vo.IotDailyReportFuelPageReqVO;
+import cn.iocoder.yudao.module.pms.controller.admin.iotdailyreportfuel.vo.IotDailyReportFuelSaveReqVO;
+import cn.iocoder.yudao.module.pms.dal.dataobject.iotdailyreportfuel.IotDailyReportFuelDO;
+import cn.iocoder.yudao.module.pms.dal.mysql.iotdailyreportfuel.IotDailyReportFuelMapper;
+import org.springframework.stereotype.Service;
+import org.springframework.validation.annotation.Validated;
+
+import javax.annotation.Resource;
+
+import java.util.List;
+
+import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
+import static cn.iocoder.yudao.module.pms.enums.ErrorCodeConstant.IOT_DAILY_REPORT_FUEL_NOT_EXISTS;
+
+/**
+ * 日报-油耗 Service 实现类
+ *
+ * @author ruiqi
+ */
+@Service
+@Validated
+public class IotDailyReportFuelServiceImpl implements IotDailyReportFuelService {
+
+    @Resource
+    private IotDailyReportFuelMapper iotDailyReportFuelMapper;
+
+    @Override
+    public Long createIotDailyReportFuel(IotDailyReportFuelSaveReqVO createReqVO) {
+        // 插入
+        IotDailyReportFuelDO iotDailyReportFuel = BeanUtils.toBean(createReqVO, IotDailyReportFuelDO.class);
+        iotDailyReportFuelMapper.insert(iotDailyReportFuel);
+        // 返回
+        return iotDailyReportFuel.getId();
+    }
+
+    @Override
+    public void updateIotDailyReportFuel(IotDailyReportFuelSaveReqVO updateReqVO) {
+        // 校验存在
+        validateIotDailyReportFuelExists(updateReqVO.getId());
+        // 更新
+        IotDailyReportFuelDO updateObj = BeanUtils.toBean(updateReqVO, IotDailyReportFuelDO.class);
+        iotDailyReportFuelMapper.updateById(updateObj);
+    }
+
+    @Override
+    public void deleteIotDailyReportFuel(Long id) {
+        // 校验存在
+        validateIotDailyReportFuelExists(id);
+        // 删除
+        iotDailyReportFuelMapper.deleteById(id);
+    }
+
+    private void validateIotDailyReportFuelExists(Long id) {
+        if (iotDailyReportFuelMapper.selectById(id) == null) {
+            throw exception(IOT_DAILY_REPORT_FUEL_NOT_EXISTS);
+        }
+    }
+
+    @Override
+    public IotDailyReportFuelDO getIotDailyReportFuel(Long id) {
+        return iotDailyReportFuelMapper.selectById(id);
+    }
+
+    @Override
+    public PageResult<IotDailyReportFuelDO> getIotDailyReportFuelPage(IotDailyReportFuelPageReqVO pageReqVO) {
+        return iotDailyReportFuelMapper.selectPage(pageReqVO);
+    }
+
+    @Override
+    public List<IotDailyReportFuelDO> getIotDailyReportFuels(IotDailyReportFuelPageReqVO pageReqVO) {
+        return iotDailyReportFuelMapper.selectList(pageReqVO);
+    }
+
+}

+ 145 - 70
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/service/iotrhdailyreport/IotRhDailyReportServiceImpl.java

@@ -8,30 +8,37 @@ import cn.hutool.core.util.StrUtil;
 import cn.iocoder.yudao.framework.common.pojo.PageParam;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
+import cn.iocoder.yudao.module.pms.controller.admin.iotcarzhbd.vo.IotCarZhbdPageReqVO;
 import cn.iocoder.yudao.module.pms.controller.admin.iotdevicecategorytemplateattrs.vo.IotDeviceProperty;
 import cn.iocoder.yudao.module.pms.controller.admin.iotprojecttask.vo.IotProjectTaskPageReqVO;
 import cn.iocoder.yudao.module.pms.controller.admin.iotrhdailyreport.vo.*;
 import cn.iocoder.yudao.module.pms.controller.admin.vo.IotDevicePageReqVO;
 import cn.iocoder.yudao.module.pms.dal.dataobject.IotDeviceDO;
+import cn.iocoder.yudao.module.pms.dal.dataobject.iotcarzhbd.IotCarZhbdDO;
+import cn.iocoder.yudao.module.pms.dal.dataobject.iotdailyreportfuel.IotDailyReportFuelDO;
 import cn.iocoder.yudao.module.pms.dal.dataobject.iotopeationfill.IotOpeationFillDO;
 import cn.iocoder.yudao.module.pms.dal.dataobject.iotprojecttask.IotProjectTaskDO;
 import cn.iocoder.yudao.module.pms.dal.dataobject.iotrhdailyreport.IotRhDailyReportDO;
 import cn.iocoder.yudao.module.pms.dal.mysql.IotDeviceMapper;
+import cn.iocoder.yudao.module.pms.dal.mysql.iotcarzhbd.IotCarZhbdMapper;
+import cn.iocoder.yudao.module.pms.dal.mysql.iotdailyreportfuel.IotDailyReportFuelMapper;
 import cn.iocoder.yudao.module.pms.dal.mysql.iotdevicerunlog.IotDeviceRunLogMapper;
 import cn.iocoder.yudao.module.pms.dal.mysql.iotopeationfill.IotOpeationFillMapper;
 import cn.iocoder.yudao.module.pms.dal.mysql.iotprojecttask.IotProjectTaskMapper;
 import cn.iocoder.yudao.module.pms.dal.mysql.iotrhdailyreport.IotRhDailyReportMapper;
 import cn.iocoder.yudao.module.pms.enums.common.FailureAuditStatusEnum;
+import cn.iocoder.yudao.module.pms.job.IotDeviceCarFuelVO;
+import cn.iocoder.yudao.module.pms.util.ZHBDUtil;
 import cn.iocoder.yudao.module.system.controller.admin.dept.vo.dept.DeptListReqVO;
 import cn.iocoder.yudao.module.system.dal.dataobject.dept.DeptDO;
 import cn.iocoder.yudao.module.system.dal.dataobject.dict.DictTypeDO;
 import cn.iocoder.yudao.module.system.service.dept.DeptService;
-import cn.iocoder.yudao.module.system.service.dict.DictDataService;
 import cn.iocoder.yudao.module.system.service.dict.DictTypeService;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.google.gson.Gson;
 import com.google.gson.reflect.TypeToken;
+import lombok.extern.log4j.Log4j;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.validation.annotation.Validated;
@@ -43,6 +50,7 @@ import java.math.RoundingMode;
 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.concurrent.atomic.AtomicReference;
@@ -58,6 +66,7 @@ import static cn.iocoder.yudao.module.pms.enums.ErrorCodeConstant.*;
  */
 @Service
 @Validated
+@Log4j
 public class IotRhDailyReportServiceImpl implements IotRhDailyReportService {
 
     @Resource
@@ -67,7 +76,7 @@ public class IotRhDailyReportServiceImpl implements IotRhDailyReportService {
     @Resource
     private IotDeviceMapper iotDeviceMapper;
     @Resource
-    private DictDataService dictDataService;
+    private ZHBDUtil zhbdUtil;
     @Resource
     private DictTypeService dictTypeService;
     @Resource
@@ -76,6 +85,11 @@ public class IotRhDailyReportServiceImpl implements IotRhDailyReportService {
     private IotDeviceRunLogMapper iotDeviceRunLogMapper;
     @Resource
     private DeptService deptService;
+    @Resource
+    private IotCarZhbdMapper iotCarZhbdMapper;
+
+    @Resource
+    private IotDailyReportFuelMapper iotDailyReportFuelMapper;
 
     @Override
     @Transactional(rollbackFor = Exception.class)
@@ -97,6 +111,12 @@ public class IotRhDailyReportServiceImpl implements IotRhDailyReportService {
         reqVO.setDeptId(createReqVO.getDeptId());
         // 查询包含当前日报施工队伍的任务
         List<IotProjectTaskDO> tasks = iotProjectTaskMapper.selectList(reqVO);
+        // 日报对应的任务中的设备列表
+        Set<String> carDeviceCodes = new HashSet<>();
+        // 生成 carId 与 IotDeviceDO 的对应关系Map
+        Map<String, IotDeviceDO> carIdDevicePair = new HashMap<>();
+        // 中航北斗车辆id集合
+        Set<String> zhbdCarIds = new HashSet<>();
         if (CollUtil.isNotEmpty(tasks)) {
             IotProjectTaskDO task = tasks.get(0);
             // 暂时只考虑1个施工队伍只属于1个任务
@@ -111,6 +131,52 @@ public class IotRhDailyReportServiceImpl implements IotRhDailyReportService {
             }
             // 查询任务的设备列表
             deviceIds = task.getDeviceIds();
+            IotDevicePageReqVO deviceReqVO = new IotDevicePageReqVO();
+            deviceReqVO.setDeviceIds(new ArrayList<>(deviceIds));
+            List<IotDeviceDO> carDevices = iotDeviceMapper.selectListAlone(deviceReqVO);
+            // key设备编码   value设备对象
+            Map<String, IotDeviceDO> devicePair = new HashMap<>();
+            // key中航北斗carId   value设备编码
+            Map<String, String> carIdDeviceCodePair = new HashMap<>();
+
+            if (CollUtil.isNotEmpty(carDevices)) {
+                carDevices.forEach(device -> {
+                    carDeviceCodes.add(device.getDeviceCode());
+                    if (ObjUtil.isNotEmpty(device.getCarId())) {
+                        zhbdCarIds.add(String.valueOf(device.getCarId()));
+                        carIdDeviceCodePair.put(String.valueOf(device.getCarId()), device.getDeviceCode());
+                    }
+                    devicePair.put(device.getDeviceCode(), device);
+                });
+                // 查询中航北斗表中的设备车辆
+                IotCarZhbdPageReqVO customDeviceReqVO = new IotCarZhbdPageReqVO();
+                // 设备表中存在的设备编码
+                customDeviceReqVO.setCustomDeviceCodes(carDeviceCodes);
+                List<IotCarZhbdDO> deviceCars = iotCarZhbdMapper.selectList(customDeviceReqVO);
+                if (CollUtil.isNotEmpty(deviceCars)) {
+                    deviceCars.forEach(car -> {
+                        zhbdCarIds.add(car.getCarId());
+                        carIdDeviceCodePair.put(car.getCarId(), car.getDeviceCode());
+                    });
+                }
+                // 额外匹配的 RA 与 设备表对应的编码
+                customDeviceReqVO.setCustomDeviceCodes(null);
+                customDeviceReqVO.setDeviceCodes(carDeviceCodes);
+                List<IotCarZhbdDO> raCars = iotCarZhbdMapper.selectList(customDeviceReqVO);
+                if (CollUtil.isNotEmpty(raCars)) {
+                    raCars.forEach(car -> {
+                        zhbdCarIds.add(car.getCarId());
+                        carIdDeviceCodePair.put(car.getCarId(), car.getUserName());
+                    });
+                }
+                // 生成 carId 与 IotDeviceDO 的对应关系Map
+                carIdDevicePair = carIdDeviceCodePair.entrySet().stream()
+                        .filter(entry -> devicePair.containsKey(entry.getValue()))
+                        .collect(Collectors.toMap(
+                                Map.Entry::getKey,
+                                entry -> devicePair.get(entry.getValue())
+                        ));
+            }
         } else {
             // 当前队伍没有关联任务 不生成日报
             // throw exception(IOT_PROJECT_TASK_NOT_RELATED);
@@ -147,66 +213,85 @@ public class IotRhDailyReportServiceImpl implements IotRhDailyReportService {
             iotRhDailyReport.setTransitTime(createReqVO.getDailyGasInjection().divide(capacity, 4, RoundingMode.HALF_UP));
         }
 
-        // 查询当前日报所属任务关联的设备 更新设备状态
-        /* if (CollUtil.isNotEmpty(deviceIds)) {
-            // 查询当前任务下关联的所有设备
-            IotDevicePageReqVO deviceReqVO = new IotDevicePageReqVO();
-            // deviceReqVO.setDeptId(createReqVO.getDeptId());
-            deviceReqVO.setDeviceIds(new ArrayList<>(deviceIds));
-            List<IotDeviceDO> devices = iotDeviceMapper.selectList(deviceReqVO);
-            if (CollUtil.isNotEmpty(devices)) {
-                AtomicReference<String> deviceNewStatus = new AtomicReference<>(StrUtil.EMPTY);
-                // 日报状态 与 设备状态 对应关系
-                // 动迁 施工 现场待命/驻地待命(待命) pms_device_status
-                List<DictDataDO> dictDatas = dictDataService.getDictDataListByDictType("constructionStatus");
-                AtomicReference<String> dailyDictLabel = new AtomicReference<>(StrUtil.EMPTY);
-                List<DictDataDO> deviceDictDatas = dictDataService.getDictDataListByDictType("pms_device_status");
-                if (CollUtil.isNotEmpty(dictDatas)) {
-                    dictDatas.forEach(data -> {
-                        if (createReqVO.getConstructionStatus().equals(Integer.valueOf(data.getValue()))) {
-                            dailyDictLabel.set(data.getLabel());
-                        }
-                    });
-                    if (CollUtil.isNotEmpty(deviceDictDatas)) {
-                        deviceDictDatas.forEach(data -> {
-                            if (dailyDictLabel.equals(data.getLabel())) {
-                                // 动迁 施工
-                                deviceNewStatus.set(data.getValue());
-                            }
-                            if (data.getLabel().contains(dailyDictLabel.get())) {
-                                // 现场待命/驻地待命(待命)
-                                deviceNewStatus.set(data.getValue());
-                            }
-                        });
-                    }
-                }
-                // 批量更新设备状态
-                devices.forEach(device -> {
-                    device.setDeviceStatus(deviceNewStatus.get());
-                });
-                iotDeviceMapper.updateBatch(devices);
-            }
-        } */
-
         // 当天如果已经有此小队的记录 新增 当天如果没有此小队的日报记录 修改
         // deptId - taskId - createTime(yyyy-MM-dd) 确定唯一一条记录 不能使用 LocalDateTime.now() 来查询,应该使用 运行记录工单的创建日期查询
         IotRhDailyReportDO existReport = iotRhDailyReportMapper.selectExistReport(createReqVO.getDeptId(), null, reportDate);
+        // 查询日报相关的任务关联的设备油耗
+        // 获得昨天的日期
+        String yesterdayDateStr = StrUtil.EMPTY;
+        LocalDateTime yesterday = reportDate.minusDays(1);
+        yesterdayDateStr = LocalDateTimeUtil.format(yesterday, DatePattern.NORM_DATE_PATTERN);
         if (ObjUtil.isEmpty(existReport)) {
             // 今天下午4点
             LocalDateTime today4pm = reportDate.withHour(16).withMinute(0).withSecond(0).withNano(0);
             // 昨天下午4点
             LocalDateTime yesterday4pm = today4pm.minusDays(1);
+
             iotRhDailyReport.setConstructionStartDate(yesterday4pm);
             iotRhDailyReport.setConstructionEndDate(today4pm);
             iotRhDailyReport.setCreateTime(reportDate);
             iotRhDailyReport.setUpdateTime(reportDate);
             iotRhDailyReportMapper.insert(iotRhDailyReport);
+            BigDecimal totalOilUsage = BigDecimal.ZERO;
+            // 生成日报时 查询当前日报关联的任务中的车辆 查询中航北斗指定日报区间范围内的油耗数据 子表 主表
+            List<IotDailyReportFuelDO> reportFuels = new ArrayList<>();
+            if (CollUtil.isNotEmpty(zhbdCarIds)) {
+                if (StrUtil.isNotBlank(yesterdayDateStr)) {
+                    try {
+                        Map<Integer, IotDeviceCarFuelVO> carFuels = zhbdUtil.carFuels(StrUtil.join(",", zhbdCarIds),
+                                StrUtil.join(" ", yesterdayDateStr, "00:00:00"), StrUtil.join(" ", yesterdayDateStr, "23:59:59"));
+                        System.out.println("请求参数:" + zhbdCarIds.size() + " -开始时间: "
+                                + StrUtil.join(" ", yesterdayDateStr, "00:00:00") + " -开始时间: "
+                                + StrUtil.join(" ", yesterdayDateStr, "23:59:59"));
+                        if (CollUtil.isNotEmpty(carFuels)) {
+                            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
+                            Map<String, IotDeviceDO> finalCarIdDevicePair = carIdDevicePair;
+                            for (Map.Entry<Integer, IotDeviceCarFuelVO> carFuelEntry : carFuels.entrySet()) {
+                                Integer carId = carFuelEntry.getKey();
+                                IotDeviceCarFuelVO carFuel = carFuelEntry.getValue();
+                                // carId中航北斗车辆id   value车辆油耗
+                                IotDailyReportFuelDO reportFuel = new IotDailyReportFuelDO();
+                                reportFuel.setType("RH");
+                                reportFuel.setReportId(iotRhDailyReport.getId());
+                                reportFuel.setCarId(String.valueOf(carId));
+                                // 使用 carIdDeviceMap 获取对应的设备对象并设置deviceId
+                                IotDeviceDO device = finalCarIdDevicePair.get(String.valueOf(carId));
+                                reportFuel.setDeviceId(device.getId());
+                                reportFuel.setDeviceCode(device.getDeviceCode());
+                                reportFuel.setDeviceName(device.getDeviceName());
+                                BigDecimal tempOil = new BigDecimal(carFuel.getOil());
+                                totalOilUsage = totalOilUsage.add(tempOil);
+                                reportFuel.setZhbdFuel(tempOil);
+                                // 将字符串转换为LocalDateTime
+                                try {
+                                    LocalDateTime queryDate = LocalDate.parse(carFuel.getCreatetime(), formatter).atStartOfDay();;
+                                    reportFuel.setQueryDate(queryDate);
+                                } catch (DateTimeParseException e) {
+                                    log.error("瑞恒日报-中航北斗油耗-日期格式解析失败: {}", e);
+                                    // 根据业务需求设置默认值或抛出异常
+                                    reportFuel.setQueryDate(null);
+                                }
+                                reportFuels.add(reportFuel);
+                            }
+                        }
+                    } catch (Exception e) {
+                        log.info("获取油耗数据失败!");
+                    }
+                    if (CollUtil.isNotEmpty(reportFuels)) {
+                        // 生成瑞恒日报时 同步新增日报关联的任务车辆油耗
+                        iotDailyReportFuelMapper.insertBatch(reportFuels);
+                    }
+                }
+            }
+            // 先插入记录再更新 因为需要获取日报id
+            iotRhDailyReport.setDailyOilUsage(totalOilUsage);
+            // 根据日报关联任务车辆油耗 计算总油耗 后保存日报
+            iotRhDailyReportMapper.updateById(iotRhDailyReport);
         } else {
             // 修改现有记录
             iotRhDailyReport.setId(existReport.getId());
             iotRhDailyReportMapper.updateById(iotRhDailyReport);
         }
-        // 返回
         return iotRhDailyReport.getId();
     }
 
@@ -499,6 +584,8 @@ public class IotRhDailyReportServiceImpl implements IotRhDailyReportService {
         Map<Long, BigDecimal> cumulativeWaterInjectionPair = new HashMap<>();
         // key队伍id/项目部id   value累计用电
         Map<Long, BigDecimal> cumulativePowerConsumptionPair = new HashMap<>();
+        // key队伍id/项目部id   value累计油耗
+        Map<Long, BigDecimal> cumulativeOilConsumptionPair = new HashMap<>();
         // key队伍id/项目部id   value对应项目部的总产能
         Map<Long, BigDecimal> cumulativeCapacityPair = new HashMap<>();
         // key队伍id/项目部id   value累计运行时效   累计注气量/累计产能
@@ -537,6 +624,8 @@ public class IotRhDailyReportServiceImpl implements IotRhDailyReportService {
                         cumulativeWaterInjectionPair.merge(projectDeptId, report.getDailyWaterInjection(), BigDecimal::add);
                         // 累计用电量
                         cumulativePowerConsumptionPair.merge(projectDeptId, report.getDailyPowerUsage(), BigDecimal::add);
+                        // 累计油耗
+                        cumulativeOilConsumptionPair.merge(projectDeptId, report.getDailyOilUsage(), BigDecimal::add);
                         if (teamCapacityPair.containsKey(report.getDeptId())) {
                             BigDecimal tempCapacity = teamCapacityPair.get(report.getDeptId());
                             cumulativeCapacityPair.merge(projectDeptId, tempCapacity, BigDecimal::add);
@@ -571,6 +660,7 @@ public class IotRhDailyReportServiceImpl implements IotRhDailyReportService {
             statistics.setCumulativeGasInjection(cumulativeGasInjectionPair.get(deptId));
             statistics.setCumulativeWaterInjection(cumulativeWaterInjectionPair.get(deptId));
             statistics.setCumulativePowerConsumption(cumulativePowerConsumptionPair.get(deptId));
+            statistics.setCumulativeFuelConsumption(cumulativeOilConsumptionPair.get(deptId));
             statistics.setTransitTime(cumulativeTransitTimePair.get(deptId));
             result.add(statistics);
         });
@@ -641,7 +731,8 @@ public class IotRhDailyReportServiceImpl implements IotRhDailyReportService {
                 dateWaterInjectionPair.merge(reportDateStr, report.getDailyWaterInjection(), BigDecimal::add);
                 // 累计用电量
                 datePowerConsumptionPair.merge(reportDateStr, report.getDailyPowerUsage(), BigDecimal::add);
-                // todo 累计油耗
+                // 累计油耗
+                dateFuelConsumptionPair.merge(reportDateStr, report.getDailyOilUsage(), BigDecimal::add);
                 // 累计产能
                 if (teamCapacityPair.containsKey(report.getDeptId())) {
                     BigDecimal tempCapacity = teamCapacityPair.get(report.getDeptId());
@@ -686,6 +777,7 @@ public class IotRhDailyReportServiceImpl implements IotRhDailyReportService {
                 statistics.setCumulativeGasInjection(dateGasInjectionPair.get(date));
                 statistics.setCumulativeWaterInjection(dateWaterInjectionPair.get(date));
                 statistics.setCumulativePowerConsumption(datePowerConsumptionPair.get(date));
+                statistics.setCumulativeFuelConsumption(dateFuelConsumptionPair.get(date));
                 statistics.setTransitTime(dateTransitTimePair.get(date));
                 result.add(statistics);
             });
@@ -716,6 +808,8 @@ public class IotRhDailyReportServiceImpl implements IotRhDailyReportService {
         Map<Long, BigDecimal> cumulativeWaterInjectionPair = new HashMap<>();
         // key队伍id   value累计用电
         Map<Long, BigDecimal> cumulativePowerConsumptionPair = new HashMap<>();
+        // key队伍id   value累计油耗
+        Map<Long, BigDecimal> cumulativeOilConsumptionPair = new HashMap<>();
         // key队伍id/项目部id   value对应项目部的总产能
         Map<Long, BigDecimal> cumulativeCapacityPair = new HashMap<>();
         // key队伍id/项目部id   value累计运行时效   累计注气量/累计产能
@@ -753,6 +847,8 @@ public class IotRhDailyReportServiceImpl implements IotRhDailyReportService {
                     cumulativeWaterInjectionPair.merge(report.getDeptId(), report.getDailyWaterInjection(), BigDecimal::add);
                     // 累计用电量
                     cumulativePowerConsumptionPair.merge(report.getDeptId(), report.getDailyPowerUsage(), BigDecimal::add);
+                    // 累计油耗
+                    cumulativeOilConsumptionPair.merge(report.getDeptId(), report.getDailyOilUsage(), BigDecimal::add);
                     if (teamCapacityPair.containsKey(report.getDeptId())) {
                         BigDecimal tempCapacity = teamCapacityPair.get(report.getDeptId());
                         cumulativeCapacityPair.merge(report.getDeptId(), tempCapacity, BigDecimal::add);
@@ -784,6 +880,7 @@ public class IotRhDailyReportServiceImpl implements IotRhDailyReportService {
             statistics.setCumulativeGasInjection(cumulativeGasInjectionPair.get(teamDeptId));
             statistics.setCumulativeWaterInjection(cumulativeWaterInjectionPair.get(teamDeptId));
             statistics.setCumulativePowerConsumption(cumulativePowerConsumptionPair.get(teamDeptId));
+            statistics.setCumulativeFuelConsumption(cumulativeOilConsumptionPair.get(teamDeptId));
             statistics.setTransitTime(cumulativeTransitTimePair.get(teamDeptId));
             result.add(statistics);
         });
@@ -808,17 +905,6 @@ public class IotRhDailyReportServiceImpl implements IotRhDailyReportService {
         // key部门id   value部门parentId
         Map<Long, Long> teamProjectIdPair = new HashMap<>();
 
-        // key队伍id   value累计注气量
-        Map<Long, BigDecimal> cumulativeGasInjectionPair = new HashMap<>();
-        // key队伍id   value累计注水量
-        Map<Long, BigDecimal> cumulativeWaterInjectionPair = new HashMap<>();
-        // key队伍id   value累计用电
-        Map<Long, BigDecimal> cumulativePowerConsumptionPair = new HashMap<>();
-        // key队伍id/项目部id   value对应项目部的总产能
-        Map<Long, BigDecimal> cumulativeCapacityPair = new HashMap<>();
-        // key队伍id/项目部id   value累计运行时效   累计注气量/累计产能
-        Map<Long, BigDecimal> cumulativeTransitTimePair = new HashMap<>();
-
         // 按照日期维度统计各工作量数据
         // key日期yyyy-MM-dd   value累计注气量
         Map<String, BigDecimal> dateGasInjectionPair = new HashMap<>();
@@ -868,25 +954,13 @@ public class IotRhDailyReportServiceImpl implements IotRhDailyReportService {
                 dateWaterInjectionPair.merge(reportDateStr, report.getDailyWaterInjection(), BigDecimal::add);
                 // 累计用电量
                 datePowerConsumptionPair.merge(reportDateStr, report.getDailyPowerUsage(), BigDecimal::add);
-                // todo 累计油耗
+                // 累计油耗
+                dateFuelConsumptionPair.merge(reportDateStr, report.getDailyOilUsage(), BigDecimal::add);
                 // 累计产能
                 if (teamCapacityPair.containsKey(report.getDeptId())) {
                     BigDecimal tempCapacity = teamCapacityPair.get(report.getDeptId());
                     dateCapacityPair.merge(reportDateStr, tempCapacity, BigDecimal::add);
                 }
-
-                if (ObjUtil.isNotEmpty(report.getDeptId())) {
-                    // 累计注气量
-                    cumulativeGasInjectionPair.merge(report.getDeptId(), report.getDailyGasInjection(), BigDecimal::add);
-                    // 累计注水量
-                    cumulativeWaterInjectionPair.merge(report.getDeptId(), report.getDailyWaterInjection(), BigDecimal::add);
-                    // 累计用电量
-                    cumulativePowerConsumptionPair.merge(report.getDeptId(), report.getDailyPowerUsage(), BigDecimal::add);
-                    if (teamCapacityPair.containsKey(report.getDeptId())) {
-                        BigDecimal tempCapacity = teamCapacityPair.get(report.getDeptId());
-                        cumulativeCapacityPair.merge(report.getDeptId(), tempCapacity, BigDecimal::add);
-                    }
-                }
             });
             // 根据 累计注气量 累计产能 计算指定队伍下的平均产能
             if (CollUtil.isNotEmpty(dateGasInjectionPair) && CollUtil.isNotEmpty(dateCapacityPair)) {
@@ -923,6 +997,7 @@ public class IotRhDailyReportServiceImpl implements IotRhDailyReportService {
                 statistics.setCumulativeGasInjection(dateGasInjectionPair.get(date));
                 statistics.setCumulativeWaterInjection(dateWaterInjectionPair.get(date));
                 statistics.setCumulativePowerConsumption(datePowerConsumptionPair.get(date));
+                statistics.setCumulativeFuelConsumption(dateFuelConsumptionPair.get(date));
                 statistics.setTransitTime(dateTransitTimePair.get(date));
                 result.add(statistics);
             });

+ 8 - 0
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/service/iotrydailyreport/IotRyDailyReportService.java

@@ -134,4 +134,12 @@ public interface IotRyDailyReportService {
      * @return 未填报队伍明细
      */
     List<IotRyDailyReportStatisticsVO> ryUnReportedDetails(IotRyDailyReportPageReqVO pageReqVO);
+
+    /**
+     * 瑞鹰日报汇总 折线图
+     *
+     * @param
+     * @return
+     */
+    List<IotRyDailyReportPolylineVO> polylineStatistics(IotRyDailyReportPageReqVO pageReqVO);
 }

+ 416 - 0
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/service/iotrydailyreport/IotRyDailyReportServiceImpl.java

@@ -1,6 +1,8 @@
 package cn.iocoder.yudao.module.pms.service.iotrydailyreport;
 
 import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.date.DatePattern;
+import cn.hutool.core.date.LocalDateTimeUtil;
 import cn.hutool.core.util.ObjUtil;
 import cn.hutool.core.util.StrUtil;
 import cn.iocoder.yudao.framework.common.pojo.PageParam;
@@ -581,6 +583,58 @@ public class IotRyDailyReportServiceImpl implements IotRyDailyReportService {
         return results;
     }
 
+    @Override
+    public List<IotRyDailyReportPolylineVO> polylineStatistics(IotRyDailyReportPageReqVO pageReqVO) {
+        List<IotRyDailyReportPolylineVO> result = new ArrayList<>();
+        // 不分页统计所有数据
+        pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
+        Set<Long> ids = new HashSet<>();
+        if (Objects.nonNull(pageReqVO.getDeptId())) {
+            ids = deptService.getChildDeptIdListFromCache(pageReqVO.getDeptId());
+            // 找到所有子部门对象集合
+            ids.add(pageReqVO.getDeptId());
+            pageReqVO.setDeptIds(ids);
+        }
+        // 检查contractName不为空但projectIds为空的情况
+        if (StrUtil.isNotBlank(pageReqVO.getContractName()) && (CollUtil.isEmpty(pageReqVO.getProjectIds()))) {
+            return new ArrayList<>();
+        }
+        // 检查taskName不为空但taskIds为空的情况
+        if (StrUtil.isNotBlank(pageReqVO.getTaskName()) && (CollUtil.isEmpty(pageReqVO.getTaskIds()))) {
+            return new ArrayList<>();
+        }
+        PageResult<IotRyDailyReportDO> page = iotRyDailyReportMapper.selectPage(pageReqVO);
+        List<IotRyDailyReportDO> dailyReports = page.getList();
+        if (CollUtil.isEmpty(dailyReports)) {
+            return result;
+        }
+        // 默认显示所有项目部的汇总数据
+        // 点击项目部 显示 下属队伍的数据
+        // 首先判断点击的部门是属于 公司 还是 队伍 如果没有点击任何部门 默认查询所有项目部数据
+        if (ObjUtil.isEmpty(pageReqVO.getDeptId())) {
+            result = polylineStatisticsByProjectDept(pageReqVO, dailyReports, 158L, pageReqVO.getCreateTime());
+        } else {
+            // 判断点击的组织树中的部门类型 类型(公司级1 项目部2 队伍3)
+            DeptDO selectedDept = deptService.getDept(pageReqVO.getDeptId());
+            if ("1".equals(selectedDept.getType())) {
+                // 以项目部为维度汇总数据
+                result = polylineStatisticsByProjectDept(pageReqVO, dailyReports, pageReqVO.getDeptId(), pageReqVO.getCreateTime());
+            } else if ("2".equals(selectedDept.getType())) {
+                // 以队伍为维度汇总数据
+                result = polylineStatisticsByProjectDepartment(pageReqVO, dailyReports, pageReqVO.getDeptId(), pageReqVO.getCreateTime());
+            } else if ("3".equals(selectedDept.getType())) {
+                // 显示单个队伍的汇总数据
+                result = polylineStatisticsByProjectDepartment(pageReqVO, dailyReports, pageReqVO.getDeptId(), pageReqVO.getCreateTime());
+            } else {
+                // 点击的部门没有类型 判断部门下的是否包含 项目部类型部门 新疆分公司
+                // 以项目部为维度汇总数据
+                result = polylineStatisticsByProjectDept(pageReqVO, dailyReports, pageReqVO.getDeptId(), pageReqVO.getCreateTime());
+            }
+        }
+        // 根据result集合内对象的 日期 属性正序排列
+        return result;
+    }
+
     private List<IotDeviceDO> devices() {
         // 查询 瑞鹰158l 所有存在设备的队伍
         // 查询 瑞鹰 下所有部门
@@ -770,6 +824,186 @@ public class IotRyDailyReportServiceImpl implements IotRyDailyReportService {
         return result;
     }
 
+    /**
+     * 按项目部维度统计数据 折线图
+     * @param pageReqVO 日报查询对象
+     * @param dailyReports 日报数据列表
+     * @param rootDeptId 根部门ID(如158L为 瑞鹰 根部门,或其他公司级部门ID)
+     * @return 项目部维度统计结果折线图  钻井 修井
+     */
+    private List<IotRyDailyReportPolylineVO> polylineStatisticsByProjectDept(IotRyDailyReportPageReqVO pageReqVO,
+                                                                           List<IotRyDailyReportDO> dailyReports, Long rootDeptId, LocalDateTime[] createTimes) {
+        List<IotRyDailyReportPolylineVO> result = new ArrayList<>();
+
+        Set<Long> projectDeptIds = new HashSet<>();
+        // key项目部id    value项目部名称
+        Map<Long, DeptDO> projectDeptPair = new HashMap<>();
+        // key部门id   value部门parentId
+        Map<Long, Long> teamProjectIdPair = new HashMap<>();
+
+        // 按照日期维度统计各工作量数据
+        // key日期yyyy-MM-dd   value累计进尺
+        Map<String, BigDecimal> dateFootagePair = new HashMap<>();
+        // key日期yyy-MM-dd    value去重后的施工任务集合
+        Map<String, Set<Long>> dateConstructTaskPair = new HashMap<>();
+        // key日期yyy-MM-dd    value去重后的完工任务集合
+        Map<String, Set<Long>> dateFinishTaskPair = new HashMap<>();
+        // key日期yyyy-MM-dd   value累计用电量
+        Map<String, BigDecimal> datePowerConsumptionPair = new HashMap<>();
+        // key日期yyyy-MM-dd   value累计油耗
+        Map<String, BigDecimal> dateFuelConsumptionPair = new HashMap<>();
+        // key日期yyyy-MM-dd   value累计运行时效   累计注气量/累计产能
+        Map<String, BigDecimal> dateTransitTimePair = new HashMap<>();
+        // key日期yyyy-MM-dd   value生产时间(H)
+        Map<String, BigDecimal> dateProductTimePair = new HashMap<>();
+        // key日期yyyy-MM-dd   value额定生产时间(H)
+        Map<String, BigDecimal> dateRatedTimePair = new HashMap<>();
+
+        // 以项目部为维度统计数据
+        // 找到所有项目部与队伍的对应关系
+        // 查询指定根部门下的所有子部门
+        Set<Long> allRhChildDeptIds = deptService.getChildDeptIdListFromCache(rootDeptId);
+        DeptListReqVO reqVO = new DeptListReqVO();
+        reqVO.setDeptIds(allRhChildDeptIds);
+        List<DeptDO> depts = deptService.getDeptList(reqVO);
+
+        // 构建项目部映射和父子部门关系
+        depts.forEach(dept -> {
+            // 筛选出所有项目部
+            if ("2".equals(dept.getType())) {
+                projectDeptIds.add(dept.getId());
+                projectDeptPair.put(dept.getId(), dept);
+            }
+            teamProjectIdPair.put(dept.getId(), dept.getParentId());
+        });
+
+        // key施工队伍id    value施工井数量
+        Map<Long, Integer> totalTasksPair = new HashMap<>();
+        // key施工队伍id    value完工井数量
+        Map<Long, Integer> completedTasksPair = new HashMap<>();
+        // key任务id   value额定生产时间
+        Map<Long, BigDecimal> taskRatedProductionTimePair = new HashMap<>();
+        if ("2".equals(pageReqVO.getProjectClassification())) {
+            // 查询 指定时间范围内的 修井 累计施工井数 累计完工井数
+            // 每天的任务数量 taskId 去重后的数量
+            // 每天完工任务数量 taskId 去重后 状态为 wg 的数量
+            dailyReports.forEach(report -> {
+                String dateStr = LocalDateTimeUtil.format(report.getCreateTime(), DatePattern.NORM_DATE_PATTERN);
+                if (dateConstructTaskPair.containsKey(dateStr)) {
+                    Set<Long> tempUniqueTaskIds = dateConstructTaskPair.get(dateStr);
+                    tempUniqueTaskIds.add(report.getTaskId());
+                    dateConstructTaskPair.put(dateStr, tempUniqueTaskIds);
+                } else {
+                    Set<Long> tempUniqueTaskIds = new HashSet<>();
+                    tempUniqueTaskIds.add(report.getTaskId());
+                    dateConstructTaskPair.put(dateStr, tempUniqueTaskIds);
+                }
+                // 组装完工任务集合
+                if ("wg".equals(report.getRepairStatus())) {
+                    if (dateFinishTaskPair.containsKey(dateStr)) {
+                        Set<Long> tempUniqueTaskIds = dateFinishTaskPair.get(dateStr);
+                        tempUniqueTaskIds.add(report.getTaskId());
+                        dateFinishTaskPair.put(dateStr, tempUniqueTaskIds);
+                    } else {
+                        Set<Long> tempUniqueTaskIds = new HashSet<>();
+                        tempUniqueTaskIds.add(report.getTaskId());
+                        dateFinishTaskPair.put(dateStr, tempUniqueTaskIds);
+                    }
+                }
+            });
+
+            // 计算 运行时效 累计生产时间/累计额定生产时间
+            // 查询日报关联的任务信息
+            IotProjectTaskPageReqVO taskReqVO = new IotProjectTaskPageReqVO();
+            taskReqVO.setTaskIds(convertList(dailyReports, IotRyDailyReportDO::getTaskId));
+            List<IotProjectTaskDO> tasks = iotProjectTaskMapper.selectList(taskReqVO);
+            if (CollUtil.isNotEmpty(tasks)) {
+                tasks.forEach(task -> {
+                    if (CollUtil.isNotEmpty(task.getExtProperty())) {
+                        List<IotTaskAttrModelProperty> taskAttrs = task.getExtProperty();
+                        if (CollUtil.isNotEmpty(taskAttrs)) {
+                            // 找到 额定生产时间 属性 对应的值
+                            taskAttrs.forEach(attr -> {
+                                if ("额定生产时间".equals(attr.getName()) && StrUtil.isNotBlank(attr.getActualValue())) {
+                                    taskRatedProductionTimePair.put(task.getId(), new BigDecimal(attr.getActualValue()));
+                                }
+                            });
+                        }
+                    }
+                });
+            }
+        }
+
+        // 累计计算各项指标
+        if (CollUtil.isNotEmpty(dailyReports)) {
+            dailyReports.forEach(report -> {
+                // 按照日期维度统计各 工作量数据 累计用电量 累计油耗 累计注气量 累计注水量
+                LocalDateTime reportLocalDate = report.getCreateTime();
+                // 将日期格式转换成 字符串
+                String reportDateStr = LocalDateTimeUtil.format(reportLocalDate, DatePattern.NORM_DATE_PATTERN);
+                // 累计进尺
+                dateFootagePair.merge(reportDateStr, report.getDailyFootage(), BigDecimal::add);
+                // 累计用电量
+                datePowerConsumptionPair.merge(reportDateStr, report.getDailyPowerUsage(), BigDecimal::add);
+                // 累计油耗
+                dateFuelConsumptionPair.merge(reportDateStr, report.getDailyFuel(), BigDecimal::add);
+                // 生产时间
+                dateProductTimePair.merge(reportDateStr, report.getProductionTime(), BigDecimal::add);
+                // 额定生产时间
+                if (taskRatedProductionTimePair.containsKey(report.getTaskId())) {
+                    BigDecimal ratedTime = taskRatedProductionTimePair.get(report.getTaskId());
+                    dateRatedTimePair.merge(reportDateStr, ratedTime, BigDecimal::add);
+                }
+            });
+
+            // 根据 生产时间 额定生产时间 计算指定日期范围的 平均运行时效
+            if (CollUtil.isNotEmpty(dateProductTimePair) && CollUtil.isNotEmpty(dateRatedTimePair)) {
+                dateProductTimePair.forEach((reportDateStr, productTime) -> {
+                    if (dateRatedTimePair.containsKey(reportDateStr)) {
+                        BigDecimal ratedTime = dateRatedTimePair.get(reportDateStr);
+                        if (ratedTime.compareTo(BigDecimal.ZERO) > 0) {
+                            // 指日期范围的累计运行时效
+                            BigDecimal tempTransitTime = productTime.divide(ratedTime, 4, RoundingMode.HALF_UP);
+                            dateTransitTimePair.put(reportDateStr, tempTransitTime);
+                        } else {
+                            dateTransitTimePair.put(reportDateStr, BigDecimal.ZERO);
+                        }
+                    }
+                });
+            }
+        }
+
+        // 日期字符串集合
+        List<String> dateRangeList = new ArrayList<>();
+
+        if (createTimes.length >= 2) {
+            LocalDate startDate = createTimes[0].toLocalDate();
+            LocalDate endDate = createTimes[1].toLocalDate();
+            // 生成从起始日期到结束日期的所有日期
+            for (LocalDate date = startDate;
+                 !date.isAfter(endDate);  // 使用 isAfter 而不是 <= 判断
+                 date = date.plusDays(1)) {
+                dateRangeList.add(date.format(DateTimeFormatter.ofPattern(DatePattern.NORM_DATE_PATTERN)));
+            }
+        }
+
+        if (CollUtil.isNotEmpty(dateRangeList)) {
+            dateRangeList.forEach(date -> {
+                IotRyDailyReportPolylineVO statistics = new IotRyDailyReportPolylineVO();
+                statistics.setReportDate(date);
+                statistics.setCumulativeFootage(dateFootagePair.get(date));
+                statistics.setCumulativeConstructWells(dateConstructTaskPair.containsKey(date) ? dateConstructTaskPair.get(date).size() : 0);
+                statistics.setCumulativeCompletedWells(dateFinishTaskPair.containsKey(date) ? dateFinishTaskPair.get(date).size() : 0);
+                statistics.setCumulativePowerConsumption(datePowerConsumptionPair.get(date));
+                statistics.setCumulativeFuelConsumption(dateFuelConsumptionPair.get(date));
+                statistics.setTransitTime(dateTransitTimePair.get(date));
+                result.add(statistics);
+            });
+        }
+
+        return result;
+    }
+
     /**
      * 按 队伍 维度统计数据
      * @param pageReqVO 日报数据请求对象
@@ -924,4 +1158,186 @@ public class IotRyDailyReportServiceImpl implements IotRyDailyReportService {
         return result;
     }
 
+    /**
+     * 按 队伍 维度统计数据 折线图
+     * @param pageReqVO 日报数据请求对象
+     * @param dailyReports 日报数据列表
+     * @param deptId 项目部ID 或 队伍id(新疆项目部 7009队)
+     * @return 队伍 维度统计结果 折线图
+     */
+    private List<IotRyDailyReportPolylineVO> polylineStatisticsByProjectDepartment(IotRyDailyReportPageReqVO pageReqVO,
+                                                                                 List<IotRyDailyReportDO> dailyReports, Long deptId, LocalDateTime[] createTimes) {
+        List<IotRyDailyReportPolylineVO> result = new ArrayList<>();
+
+        Set<Long> projectDeptIds = new HashSet<>();
+        // key队伍id    value队伍名称
+        Map<Long, DeptDO> teamDeptPair = new HashMap<>();
+        // key部门id   value部门parentId
+        Map<Long, Long> teamProjectIdPair = new HashMap<>();
+
+        // 按照日期维度统计各工作量数据
+        // key日期yyyy-MM-dd   value累计进尺
+        Map<String, BigDecimal> dateFootagePair = new HashMap<>();
+        // key日期yyy-MM-dd    value去重后的施工任务集合
+        Map<String, Set<Long>> dateConstructTaskPair = new HashMap<>();
+        // key日期yyy-MM-dd    value去重后的完工任务集合
+        Map<String, Set<Long>> dateFinishTaskPair = new HashMap<>();
+        // key日期yyyy-MM-dd   value累计用电量
+        Map<String, BigDecimal> datePowerConsumptionPair = new HashMap<>();
+        // key日期yyyy-MM-dd   value累计油耗
+        Map<String, BigDecimal> dateFuelConsumptionPair = new HashMap<>();
+        // key日期yyyy-MM-dd   value累计运行时效   累计注气量/累计产能
+        Map<String, BigDecimal> dateTransitTimePair = new HashMap<>();
+        // key日期yyyy-MM-dd   value生产时间(H)
+        Map<String, BigDecimal> dateProductTimePair = new HashMap<>();
+        // key日期yyyy-MM-dd   value额定生产时间(H)
+        Map<String, BigDecimal> dateRatedTimePair = new HashMap<>();
+
+
+        // 以 队伍 为维度统计数据
+        // 找到所有项目部与队伍的对应关系
+        // 查询指定根部门下的所有子部门
+        Set<Long> allRhChildDeptIds = deptService.getChildDeptIdListFromCache(deptId);
+        DeptListReqVO reqVO = new DeptListReqVO();
+        allRhChildDeptIds.add(deptId);  // 查询某支队伍
+        reqVO.setDeptIds(allRhChildDeptIds);
+        List<DeptDO> depts = deptService.getDeptList(reqVO);
+
+        // 构建项目部映射和父子部门关系
+        depts.forEach(dept -> {
+            if ("3".equals(dept.getType())) {
+                projectDeptIds.add(dept.getId());
+                teamDeptPair.put(dept.getId(), dept);
+            }
+            teamProjectIdPair.put(dept.getId(), dept.getParentId());
+        });
+
+        // key施工队伍id    value施工井数量
+        Map<Long, Integer> totalTasksPair = new HashMap<>();
+        // key施工队伍id    value完工井数量
+        Map<Long, Integer> completedTasksPair = new HashMap<>();
+        // key任务id   value额定生产时间
+        Map<Long, BigDecimal> taskRatedProductionTimePair = new HashMap<>();
+        if ("2".equals(pageReqVO.getProjectClassification())) {
+            // 查询 指定时间范围内的 修井 累计施工井数 累计完工井数
+            // 每天的任务数量 taskId 去重后的数量
+            // 每天完工任务数量 taskId 去重后 状态为 wg 的数量
+            dailyReports.forEach(report -> {
+                String dateStr = LocalDateTimeUtil.format(report.getCreateTime(), DatePattern.NORM_DATE_PATTERN);
+                if (dateConstructTaskPair.containsKey(dateStr)) {
+                    Set<Long> tempUniqueTaskIds = dateConstructTaskPair.get(dateStr);
+                    tempUniqueTaskIds.add(report.getTaskId());
+                    dateConstructTaskPair.put(dateStr, tempUniqueTaskIds);
+                } else {
+                    Set<Long> tempUniqueTaskIds = new HashSet<>();
+                    tempUniqueTaskIds.add(report.getTaskId());
+                    dateConstructTaskPair.put(dateStr, tempUniqueTaskIds);
+                }
+                // 组装完工任务集合
+                if ("wg".equals(report.getRepairStatus())) {
+                    if (dateFinishTaskPair.containsKey(dateStr)) {
+                        Set<Long> tempUniqueTaskIds = dateFinishTaskPair.get(dateStr);
+                        tempUniqueTaskIds.add(report.getTaskId());
+                        dateFinishTaskPair.put(dateStr, tempUniqueTaskIds);
+                    } else {
+                        Set<Long> tempUniqueTaskIds = new HashSet<>();
+                        tempUniqueTaskIds.add(report.getTaskId());
+                        dateFinishTaskPair.put(dateStr, tempUniqueTaskIds);
+                    }
+                }
+            });
+
+            // 计算 运行时效 累计生产时间/累计额定生产时间
+            // 查询日报关联的任务信息
+            IotProjectTaskPageReqVO taskReqVO = new IotProjectTaskPageReqVO();
+            taskReqVO.setTaskIds(convertList(dailyReports, IotRyDailyReportDO::getTaskId));
+            List<IotProjectTaskDO> tasks = iotProjectTaskMapper.selectList(taskReqVO);
+            if (CollUtil.isNotEmpty(tasks)) {
+                tasks.forEach(task -> {
+                    if (CollUtil.isNotEmpty(task.getExtProperty())) {
+                        List<IotTaskAttrModelProperty> taskAttrs = task.getExtProperty();
+                        if (CollUtil.isNotEmpty(taskAttrs)) {
+                            // 找到 额定生产时间 属性 对应的值
+                            taskAttrs.forEach(attr -> {
+                                if ("额定生产时间".equals(attr.getName()) && StrUtil.isNotBlank(attr.getActualValue())) {
+                                    taskRatedProductionTimePair.put(task.getId(), new BigDecimal(attr.getActualValue()));
+                                }
+                            });
+                        }
+                    }
+                });
+            }
+        }
+
+        // 累计计算各项指标
+        if (CollUtil.isNotEmpty(dailyReports)) {
+            dailyReports.forEach(report -> {
+                if (ObjUtil.isNotEmpty(report.getCreateTime())) {
+                    // 按照日期维度统计各 工作量数据 累计用电量 累计油耗 累计注气量 累计注水量
+                    LocalDateTime reportLocalDate = report.getCreateTime();
+                    // 将日期格式转换成 字符串
+                    String reportDateStr = LocalDateTimeUtil.format(reportLocalDate, DatePattern.NORM_DATE_PATTERN);
+                    // 累计进尺
+                    dateFootagePair.merge(reportDateStr, report.getDailyFootage(), BigDecimal::add);
+                    // 累计用电量
+                    datePowerConsumptionPair.merge(reportDateStr, report.getDailyPowerUsage(), BigDecimal::add);
+                    // 累计油耗
+                    dateFuelConsumptionPair.merge(reportDateStr, report.getDailyFuel(), BigDecimal::add);
+                    // 生产时间
+                    dateProductTimePair.merge(reportDateStr, report.getProductionTime(), BigDecimal::add);
+                    // 额定生产时间
+                    if (taskRatedProductionTimePair.containsKey(report.getTaskId())) {
+                        BigDecimal ratedTime = taskRatedProductionTimePair.get(report.getTaskId());
+                        dateRatedTimePair.merge(reportDateStr, ratedTime, BigDecimal::add);
+                    }
+                }
+            });
+            // 根据 生产时间 额定生产时间 计算指定日期范围的 平均运行时效
+            if (CollUtil.isNotEmpty(dateProductTimePair) && CollUtil.isNotEmpty(dateRatedTimePair)) {
+                dateProductTimePair.forEach((reportDateStr, productTime) -> {
+                    if (dateRatedTimePair.containsKey(reportDateStr)) {
+                        BigDecimal ratedTime = dateRatedTimePair.get(reportDateStr);
+                        if (ratedTime.compareTo(BigDecimal.ZERO) > 0) {
+                            // 指日期范围的累计运行时效
+                            BigDecimal tempTransitTime = productTime.divide(ratedTime, 4, RoundingMode.HALF_UP);
+                            dateTransitTimePair.put(reportDateStr, tempTransitTime);
+                        } else {
+                            dateTransitTimePair.put(reportDateStr, BigDecimal.ZERO);
+                        }
+                    }
+                });
+            }
+        }
+
+        // 日期字符串集合
+        List<String> dateRangeList = new ArrayList<>();
+
+        if (createTimes.length >= 2) {
+            LocalDate startDate = createTimes[0].toLocalDate();
+            LocalDate endDate = createTimes[1].toLocalDate();
+            // 生成从起始日期到结束日期的所有日期
+            for (LocalDate date = startDate;
+                 !date.isAfter(endDate);  // 使用 isAfter 而不是 <= 判断
+                 date = date.plusDays(1)) {
+                dateRangeList.add(date.format(DateTimeFormatter.ofPattern(DatePattern.NORM_DATE_PATTERN)));
+            }
+        }
+
+        if (CollUtil.isNotEmpty(dateRangeList)) {
+            dateRangeList.forEach(date -> {
+                IotRyDailyReportPolylineVO statistics = new IotRyDailyReportPolylineVO();
+                statistics.setReportDate(date);
+                statistics.setCumulativeFootage(dateFootagePair.get(date));
+                statistics.setCumulativeConstructWells(dateConstructTaskPair.containsKey(date) ? dateConstructTaskPair.get(date).size() : 0);
+                statistics.setCumulativeCompletedWells(dateFinishTaskPair.containsKey(date) ? dateFinishTaskPair.get(date).size() : 0);
+                statistics.setCumulativePowerConsumption(datePowerConsumptionPair.get(date));
+                statistics.setCumulativeFuelConsumption(dateFuelConsumptionPair.get(date));
+                statistics.setTransitTime(dateTransitTimePair.get(date));
+                result.add(statistics);
+            });
+        }
+
+        return result;
+    }
+
 }

+ 134 - 0
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/util/ZHBDUtil.java

@@ -0,0 +1,134 @@
+package cn.iocoder.yudao.module.pms.util;
+
+import cn.hutool.core.util.StrUtil;
+import cn.iocoder.yudao.module.pms.job.IotDeviceCarFuelVO;
+import cn.iocoder.yudao.module.pms.job.httpEntity.ApiOilResponse;
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONObject;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import lombok.extern.log4j.Log4j;
+import okhttp3.OkHttpClient;
+import okhttp3.Request;
+import okhttp3.Response;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.redis.core.StringRedisTemplate;
+import org.springframework.stereotype.Service;
+import org.springframework.web.client.RestTemplate;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * @author suiyy
+ * @date 20230602
+ * @desc 钉钉API接口工具类
+ */
+@Service
+@Log4j
+public class ZHBDUtil {
+    private static final Logger logger = LoggerFactory.getLogger(ZHBDUtil.class);
+
+    private static final String ID = "NjI1LjUyNS42ODg";
+    private static final String SECRET = "3897865b70d7bf29fcca5029147f7d0a";
+    private static final String TOKEN_URL = "https://zhbdgps.cn/video/webapi/user/login";
+    private static final String LOCATION_URL="https://zhbdgps.cn/video/webapi/report/fuel/daily/detail";
+    private static final String parameter = "lng,lat,today_distance,distance,todayoil,totaloil,online,oil1,oil2,oil3,oil4,vehicle_name";
+
+    @Autowired
+    private StringRedisTemplate redisTemplate;
+    @Autowired
+    private RestTemplate restTemplate;
+
+    /**
+     * 获取油耗数据
+     * @param carIds 中航北斗 逗号分隔的车辆id
+     * @return
+     * @throws Exception
+     */
+    public Map<Integer, IotDeviceCarFuelVO> carFuels(String carIds, String startDate, String endDate) throws Exception {
+        String zhbdtoken = redisTemplate.opsForValue().get("zhbdtoken");
+        if (StrUtil.isBlank(zhbdtoken)) {
+            Map<String, String> map = new HashMap<>();
+            map.put("id", ID);
+            map.put("secret", SECRET);
+            JSONObject entries = restTemplate.postForObject(TOKEN_URL, map, JSONObject.class);
+            if (Objects.nonNull(entries)&&entries.get("code") != null&&Integer.parseInt(String.valueOf(entries.get("code")))==200) {
+                JSONObject jsonObject = JSON.parseObject(JSON.toJSONString(entries.get("data")));
+                zhbdtoken = jsonObject.get("token").toString();
+                redisTemplate.opsForValue().set("zhbdtoken", zhbdtoken, 80000, TimeUnit.SECONDS);
+            }
+        }
+        // 构建请求JSON
+        Map<String, Object> requestMap = new HashMap<>();
+        requestMap.put("client_ids", ID);
+        requestMap.put("vehicle_ids", carIds);
+        requestMap.put("begin_time", startDate);
+        requestMap.put("end_time", endDate);
+        requestMap.put("page_num", 1);
+        requestMap.put("page_size", 10);
+        // key车辆carId   value油耗值
+        Map<Integer, IotDeviceCarFuelVO> carOilFuelPair = new HashMap<>();
+        if (StrUtil.isNotBlank(zhbdtoken)) {
+            try {
+                String jsonResponse = sendPostRequest(requestMap, zhbdtoken);
+                ApiOilResponse response = parseResponse(jsonResponse);
+                if (response != null && response.code == 200) {
+                    List<Map<String, Object>> details = response.data.pageList;
+                    // 组装某辆车 某天的油耗
+                    for (Map<String, Object> detail : details) {
+                        IotDeviceCarFuelVO carFuel = new IotDeviceCarFuelVO();
+                        Integer carId = Integer.valueOf(detail.get("vehicle_id").toString());
+                        Double oil = Double.valueOf(detail.get("oil").toString());
+                        String vehicleName = String.valueOf(detail.get("vehicle_name"));
+                        String createtime = String.valueOf(detail.get("createtime"));
+                        carFuel.setVehicleId(carId);
+                        carFuel.setVehicleName(vehicleName);
+                        carFuel.setOil(oil);
+                        carFuel.setCreatetime(createtime);
+                        carOilFuelPair.put(carId, carFuel);
+                    }
+                }
+            } catch (Exception e) {
+                log.info("获取油耗数据失败!");
+            }
+        }
+        return carOilFuelPair;
+    }
+
+    private String sendPostRequest(Map<String, Object> requestData,String token) throws IOException {
+
+        OkHttpClient client = new OkHttpClient();
+        ObjectMapper objectMapper = new ObjectMapper();
+        String json = objectMapper.writeValueAsString(requestData);
+        okhttp3.RequestBody body = okhttp3.RequestBody.create(json, okhttp3.MediaType.parse("application/json"));
+
+        Request request = new Request.Builder()
+                .url(LOCATION_URL)
+                .post(body)
+                .addHeader("Content-Type", "application/json")
+                .addHeader("Authorization", "Bearer " + token)// 关键头信息
+                .build();
+        String responseData = "";
+        try (Response response = client.newCall(request).execute()) {
+            if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);
+            responseData = response.body().string();
+            System.out.println(responseData);
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+
+        return responseData;
+    }
+
+    private ApiOilResponse parseResponse(String json) throws IOException {
+        ObjectMapper mapper = new ObjectMapper();
+        return mapper.readValue(json, ApiOilResponse.class);
+    }
+
+}