Kaynağa Gözat

pms 瑞都日报 按照年月日汇总

zhangcl 2 hafta önce
ebeveyn
işleme
e451933f19

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

@@ -918,6 +918,51 @@ public class IotRdDailyReportController {
         return success(new PageResult<>(buildDailyReportList(pageResult.getList()), pageResult.getTotal()));
     }
 
+    @GetMapping("/reportSummary")
+    @Operation(summary = "移动端 瑞都日报汇总 分别按照 年 月 日 汇总")
+    @PreAuthorize("@ss.hasPermission('pms:iot-rd-daily-report:query')")
+    public CommonResult<List<IotRdDailyReportSummaryYearRespVO>> reportSummary(@Valid IotRdDailyReportPageReqVO pageReqVO) {
+        // 根据查询参数筛选出 符合条件 的记录id 再传入 分页查询
+        Set<Long> projectIds = new HashSet<>();
+        Set<Long> taskIds = new HashSet<>();
+        // 移动端搜索条件 标识 合同名称 任务井号 ... 移动端兼容:searchKey 不为空时 自动填充未填的 contractName / taskName
+        String searchKey = pageReqVO.getSearchKey();
+        if (StrUtil.isNotBlank(searchKey)) {
+            if (StrUtil.isBlank(pageReqVO.getContractName())) {
+                pageReqVO.setContractName(searchKey);
+            }
+            if (StrUtil.isBlank(pageReqVO.getTaskName())) {
+                pageReqVO.setTaskName(searchKey);
+            }
+        }
+
+        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<IotRdDailyReportSummaryYearRespVO> reportSummaries = iotRdDailyReportService.reportSummary(pageReqVO);
+        // 设置日报的关联信息 部门(施工队伍) 项目 任务 带班干部 日报填报人
+        return success(reportSummaries);
+    }
+
     @GetMapping("/statistics")
     @Operation(summary = "瑞都日报 统计")
     @PreAuthorize("@ss.hasPermission('pms:iot-rd-daily-report:query')")

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

@@ -0,0 +1,20 @@
+package cn.iocoder.yudao.module.pms.controller.admin.iotrddailyreport.vo;
+
+import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
+import com.alibaba.excel.annotation.ExcelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+@Schema(description = "管理后台 - 瑞都日报 Response VO")
+@Data
+@ExcelIgnoreUnannotated
+public class IotRdDailyReportShortRespVO {
+
+    @Schema(description = "主键id", requiredMode = Schema.RequiredMode.REQUIRED, example = "13853")
+    private Long id;
+
+    @Schema(description = "日报名称", example = "西南压裂项目部/2025-10-17日报填报")
+    @ExcelProperty("日报名称")
+    private String reportName;
+
+}

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

@@ -0,0 +1,35 @@
+package cn.iocoder.yudao.module.pms.controller.admin.iotrddailyreport.vo;
+
+import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.util.List;
+
+@Schema(description = "管理后台 - 瑞都日报 移动端汇总日报 天维度 Response VO")
+@Data
+@ExcelIgnoreUnannotated
+public class IotRdDailyReportSummaryDayRespVO {
+
+    @Schema(description = "等级 年 月 日 ")
+    private String level;
+
+    @Schema(description = "星期几")
+    private String weekDay;
+
+    @Schema(description = "天 几号", example = "15")
+    private String day;
+
+    @Schema(description = "天下包含已填写日报数量")
+    private String filledCount;
+
+    @Schema(description = "天下包含未填写日报数量")
+    private String unfilledCount;
+
+    @Schema(description = "天下包含多少份日报")
+    private Integer reportCount;
+
+    @Schema(description = "日报列表")
+    private List<IotRdDailyReportShortRespVO> reports;
+
+}

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

@@ -0,0 +1,29 @@
+package cn.iocoder.yudao.module.pms.controller.admin.iotrddailyreport.vo;
+
+import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.util.List;
+
+@Schema(description = "管理后台 - 瑞都日报 移动端汇总日报 月维度 Response VO")
+@Data
+@ExcelIgnoreUnannotated
+public class IotRdDailyReportSummaryMonthRespVO {
+
+    @Schema(description = "等级 年 月 日 ")
+    private String level;
+
+    @Schema(description = "月")
+    private String month;
+
+    @Schema(description = "月下包含日报的天个数")
+    private Integer dayCount;
+
+    @Schema(description = "月下包含多少份日报")
+    private Integer reportCount;
+
+    @Schema(description = "月下包含日报的天汇总列表")
+    private List<IotRdDailyReportSummaryDayRespVO> days;
+
+}

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

@@ -0,0 +1,29 @@
+package cn.iocoder.yudao.module.pms.controller.admin.iotrddailyreport.vo;
+
+import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.util.List;
+
+@Schema(description = "管理后台 - 瑞都日报 移动端汇总日报 年维度 Response VO")
+@Data
+@ExcelIgnoreUnannotated
+public class IotRdDailyReportSummaryYearRespVO {
+
+    @Schema(description = "年")
+    private String year;
+
+    @Schema(description = "年下包含日报的月份个数")
+    private Integer monthCount;
+
+    @Schema(description = "年下包含日报的个数")
+    private Integer reportCount;
+
+    @Schema(description = "等级 年 月 日 ")
+    private String level;
+
+    @Schema(description = "年下包含日报的月份列表")
+    private List<IotRdDailyReportSummaryMonthRespVO> months;
+
+}

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

@@ -188,4 +188,12 @@ public interface IotRdDailyReportService {
      * @return 瑞都日报 非生产时效分析 列表
      */
     List<IotRdDailyReportNptStatisticsRespVO> nptStatistics(IotRdDailyReportPageReqVO pageReqVO);
+
+    /**
+     * 瑞都日报 按照 年 月 日 汇总
+     *
+     * @param pageReqVO 无分页查询
+     * @return 瑞都日报 按照年 月 日 列表
+     */
+    List<IotRdDailyReportSummaryYearRespVO> reportSummary(IotRdDailyReportPageReqVO pageReqVO);
 }

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

@@ -3578,6 +3578,143 @@ public class IotRdDailyReportServiceImpl implements IotRdDailyReportService {
         return result;
     }
 
+    @Override
+    public List<IotRdDailyReportSummaryYearRespVO> reportSummary(IotRdDailyReportPageReqVO pageReqVO) {
+        // 查询选择部门下面所有子部门
+        Set<Long> ids = new HashSet<>();
+        if (Objects.nonNull(pageReqVO.getDeptId())) {
+            ids = deptService.getChildDeptIdListFromCache(pageReqVO.getDeptId());
+            ids.add(pageReqVO.getDeptId());
+            pageReqVO.setDeptIds(ids);
+        }
+        // searchKey 兼容移动端查询的情况
+        if (StrUtil.isNotBlank(pageReqVO.getSearchKey())) {
+            if (CollUtil.isEmpty(pageReqVO.getProjectIds()) && CollUtil.isEmpty(pageReqVO.getTaskIds())) {
+                return new ArrayList<>();
+            }
+        } else {
+            // PC 端 AND 检查:各自条件必须匹配到对应 ID
+            if (StrUtil.isNotBlank(pageReqVO.getContractName()) && CollUtil.isEmpty(pageReqVO.getProjectIds())) {
+                return new ArrayList<>();
+            }
+            if (StrUtil.isNotBlank(pageReqVO.getTaskName()) && CollUtil.isEmpty(pageReqVO.getTaskIds())) {
+                return new ArrayList<>();
+            }
+        }
+        pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
+        PageResult<IotRdDailyReportDO> pageReports = iotRdDailyReportMapper.selectPage(pageReqVO);
+        List<IotRdDailyReportDO> dailyReports = pageReports.getList();
+        if (CollUtil.isEmpty(dailyReports)) {
+            return Collections.emptyList();
+        }
+        // 按照 年 月 日 汇总统计 日报数据
+        List<IotRdDailyReportSummaryYearRespVO> result = new ArrayList<>();
+        // 1. 按年 -> 月 -> 日 分组,过滤 createTime 为空的数据
+        Map<String, Map<String, Map<String, List<IotRdDailyReportDO>>>> grouped = dailyReports.stream()
+                .filter(r -> r.getCreateTime() != null)
+                .collect(Collectors.groupingBy(
+                        r -> String.valueOf(r.getCreateTime().getYear()),
+                        Collectors.groupingBy(
+                                r -> String.valueOf(r.getCreateTime().getMonthValue()),
+                                Collectors.groupingBy(
+                                        r -> String.valueOf(r.getCreateTime().getDayOfMonth())
+                                )
+                        )
+                ));
+        // 2. 遍历年份
+        for (Map.Entry<String, Map<String, Map<String, List<IotRdDailyReportDO>>>> yearEntry : grouped.entrySet()) {
+            String year = yearEntry.getKey();
+            Map<String, Map<String, List<IotRdDailyReportDO>>> monthMap = yearEntry.getValue();
+
+            IotRdDailyReportSummaryYearRespVO yearVO = new IotRdDailyReportSummaryYearRespVO();
+            yearVO.setYear(year);
+            yearVO.setLevel("year");
+            List<IotRdDailyReportSummaryMonthRespVO> monthVOList = new ArrayList<>();
+            int yearReportCount = 0;
+
+            // 3. 遍历月份
+            for (Map.Entry<String, Map<String, List<IotRdDailyReportDO>>> monthEntry : monthMap.entrySet()) {
+                String month = monthEntry.getKey();
+                Map<String, List<IotRdDailyReportDO>> dayMap = monthEntry.getValue();
+
+                IotRdDailyReportSummaryMonthRespVO monthVO = new IotRdDailyReportSummaryMonthRespVO();
+                monthVO.setMonth(month);
+                monthVO.setLevel("month");
+                List<IotRdDailyReportSummaryDayRespVO> dayVOList = new ArrayList<>();
+                int monthReportCount = 0;
+
+                // 4. 遍历日
+                for (Map.Entry<String, List<IotRdDailyReportDO>> dayEntry : dayMap.entrySet()) {
+                    String day = dayEntry.getKey();
+                    List<IotRdDailyReportDO> dayReports = dayEntry.getValue();
+
+                    IotRdDailyReportSummaryDayRespVO dayVO = new IotRdDailyReportSummaryDayRespVO();
+                    dayVO.setDay(day);
+                    dayVO.setLevel("day");
+
+                    // 统计已填报(status=1)和未填报(status=0)数量
+                    long filled = dayReports.stream()
+                            .filter(r -> r.getStatus() != null && r.getStatus() == 1)
+                            .count();
+                    long unfilled = dayReports.stream()
+                            .filter(r -> r.getStatus() != null && r.getStatus() == 0)
+                            .count();
+                    dayVO.setFilledCount(String.valueOf(filled));
+                    dayVO.setUnfilledCount(String.valueOf(unfilled));
+                    dayVO.setReportCount(dayReports.size());
+
+                    // 计算星期几(基于该天第一个日报的 createTime)
+                    if (!dayReports.isEmpty()) {
+                        LocalDateTime dateTime = dayReports.get(0).getCreateTime();
+                        // 转换为中文星期几,如 "星期一"
+                        String weekDay = dateTime.getDayOfWeek().getDisplayName(java.time.format.TextStyle.FULL, java.util.Locale.CHINESE);
+                        dayVO.setWeekDay(weekDay);
+                    }
+
+                    // 构建日报简要列表(仅 id 和 reportName)
+                    List<IotRdDailyReportShortRespVO> reportVOList = dayReports.stream()
+                            .map(r -> {
+                                IotRdDailyReportShortRespVO respVO = new IotRdDailyReportShortRespVO();
+                                respVO.setId(r.getId());
+                                respVO.setReportName(r.getReportName());
+                                return respVO;
+                            })
+                            .collect(Collectors.toList());
+                    dayVO.setReports(reportVOList);
+
+                    dayVOList.add(dayVO);
+                    monthReportCount += dayReports.size();
+                }
+
+                monthVO.setDays(dayVOList);
+                monthVO.setDayCount(dayVOList.size());      // 该月下有日报的天数
+                monthVO.setReportCount(monthReportCount);   // 该月日报总数
+                monthVOList.add(monthVO);
+                yearReportCount += monthReportCount;
+            }
+
+            yearVO.setMonths(monthVOList);
+            yearVO.setMonthCount(monthVOList.size());       // 该年下有日报的月份数
+            yearVO.setReportCount(yearReportCount);         // 该年日报总数
+            result.add(yearVO);
+        }
+
+        // 5. 排序:年份降序、月份降序、日降序(最新在前)—— 使用数字比较
+        result.sort((y1, y2) -> Integer.compare(Integer.parseInt(y2.getYear()), Integer.parseInt(y1.getYear())));
+        for (IotRdDailyReportSummaryYearRespVO yearVO : result) {
+            if (CollUtil.isNotEmpty(yearVO.getMonths())) {
+                yearVO.getMonths().sort((m1, m2) -> Integer.compare(Integer.parseInt(m2.getMonth()), Integer.parseInt(m1.getMonth())));
+                for (IotRdDailyReportSummaryMonthRespVO monthVO : yearVO.getMonths()) {
+                    if (CollUtil.isNotEmpty(monthVO.getDays())) {
+                        // 日排序:降序,数字比较
+                        monthVO.getDays().sort((d1, d2) -> Integer.compare(Integer.parseInt(d2.getDay()), Integer.parseInt(d1.getDay())));
+                    }
+                }
+            }
+        }
+        return result;
+    }
+
     /**
      * 按项目部维度 汇总 统计数据
      * @param dailyReports 日报数据列表