chenshudong il y a 2 mois
Parent
commit
9c1176afd5
20 fichiers modifiés avec 1244 ajouts et 0 suppressions
  1. 620 0
      airport-admin/src/main/java/com/sundot/airport/web/controller/system/SysHomeReportController.java
  2. 11 0
      airport-attendance/src/main/java/com/sundot/airport/attendance/mapper/AttendancePostRecordMapper.java
  3. 11 0
      airport-attendance/src/main/java/com/sundot/airport/attendance/service/IAttendancePostRecordService.java
  4. 6 0
      airport-attendance/src/main/java/com/sundot/airport/attendance/service/impl/AttendancePostRecordServiceImpl.java
  5. 15 0
      airport-attendance/src/main/resources/mapper/attendance/AttendancePostRecordMapper.xml
  6. 9 0
      airport-check/src/main/java/com/sundot/airport/check/service/ICheckLargeScreenService.java
  7. 77 0
      airport-check/src/main/java/com/sundot/airport/check/service/impl/CheckLargeScreenServiceImpl.java
  8. 32 0
      airport-common/src/main/java/com/sundot/airport/common/core/domain/SysHomeReportDetailAnswerExcelDto.java
  9. 32 0
      airport-common/src/main/java/com/sundot/airport/common/core/domain/SysHomeReportDetailCheckExcelDto.java
  10. 32 0
      airport-common/src/main/java/com/sundot/airport/common/core/domain/SysHomeReportDetailLearningExcelDto.java
  11. 35 0
      airport-common/src/main/java/com/sundot/airport/common/core/domain/SysHomeReportDetailSeizureExcelDto.java
  12. 28 0
      airport-common/src/main/java/com/sundot/airport/common/core/domain/SysHomeReportDetailWorkingExcelDto.java
  13. 41 0
      airport-common/src/main/java/com/sundot/airport/common/core/domain/SysHomeReportDto.java
  14. 26 0
      airport-common/src/main/java/com/sundot/airport/common/dto/AttendanceWorkDurationDto.java
  15. 31 0
      airport-item/src/main/java/com/sundot/airport/item/domain/ItemLargeScreenHomePageSeizureReportSqlDto.java
  16. 8 0
      airport-item/src/main/java/com/sundot/airport/item/mapper/SeizureReportMapper.java
  17. 121 0
      airport-item/src/main/java/com/sundot/airport/item/service/SeizureReportService.java
  18. 13 0
      airport-item/src/main/resources/mapper/item/SeizureReportMapper.xml
  19. 9 0
      airport-system/src/main/java/com/sundot/airport/system/service/ISysLearningGrowthService.java
  20. 87 0
      airport-system/src/main/java/com/sundot/airport/system/service/impl/SysLearningGrowthServiceImpl.java

+ 620 - 0
airport-admin/src/main/java/com/sundot/airport/web/controller/system/SysHomeReportController.java

@@ -0,0 +1,620 @@
1
+package com.sundot.airport.web.controller.system;
2
+
3
+import cn.hutool.core.collection.CollUtil;
4
+import cn.hutool.core.util.ObjectUtil;
5
+import cn.hutool.core.util.StrUtil;
6
+import com.alibaba.excel.EasyExcel;
7
+import com.alibaba.excel.ExcelWriter;
8
+import com.alibaba.excel.write.metadata.WriteSheet;
9
+import com.alibaba.excel.write.metadata.style.WriteCellStyle;
10
+import com.alibaba.excel.write.metadata.style.WriteFont;
11
+import com.alibaba.excel.write.style.HorizontalCellStyleStrategy;
12
+import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
13
+import com.sundot.airport.attendance.service.IAttendancePostRecordService;
14
+import com.sundot.airport.check.service.ICheckLargeScreenService;
15
+import com.sundot.airport.common.core.controller.BaseController;
16
+import com.sundot.airport.common.core.domain.*;
17
+import com.sundot.airport.common.core.domain.entity.SysDept;
18
+import com.sundot.airport.common.core.domain.entity.SysUser;
19
+import com.sundot.airport.common.dto.AttendanceWorkDurationDto;
20
+import com.sundot.airport.common.enums.DeptType;
21
+import com.sundot.airport.common.enums.HomePageQueryEnum;
22
+import com.sundot.airport.common.enums.RoleTypeEnum;
23
+import com.sundot.airport.common.exception.ServiceException;
24
+import com.sundot.airport.common.utils.DateUtils;
25
+import com.sundot.airport.exam.service.IAccuracyStatisticsService;
26
+import com.sundot.airport.item.service.SeizureReportService;
27
+import com.sundot.airport.system.service.ISysDeptService;
28
+import com.sundot.airport.system.service.ISysLearningGrowthService;
29
+import com.sundot.airport.system.service.ISysUserService;
30
+import lombok.SneakyThrows;
31
+import org.apache.poi.ss.usermodel.BorderStyle;
32
+import org.apache.poi.ss.usermodel.FillPatternType;
33
+import org.apache.poi.ss.usermodel.HorizontalAlignment;
34
+import org.apache.poi.ss.usermodel.IndexedColors;
35
+import org.apache.poi.ss.usermodel.VerticalAlignment;
36
+import org.springframework.beans.factory.annotation.Autowired;
37
+import org.springframework.web.bind.annotation.GetMapping;
38
+import org.springframework.web.bind.annotation.PostMapping;
39
+import org.springframework.web.bind.annotation.RequestBody;
40
+import org.springframework.web.bind.annotation.RequestMapping;
41
+import org.springframework.web.bind.annotation.RestController;
42
+
43
+import javax.servlet.http.HttpServletResponse;
44
+import java.math.BigDecimal;
45
+import java.math.RoundingMode;
46
+import java.net.URLEncoder;
47
+import java.util.*;
48
+import java.util.stream.Collectors;
49
+
50
+/**
51
+ * 首页报表控制器
52
+ *
53
+ * @author ruoyi
54
+ */
55
+@RestController
56
+@RequestMapping("/system/homeReport")
57
+public class SysHomeReportController extends BaseController {
58
+
59
+    @Autowired
60
+    private ISysDeptService deptService;
61
+
62
+    @Autowired
63
+    private ICheckLargeScreenService checkLargeScreenService;
64
+
65
+    @Autowired
66
+    private ISysLearningGrowthService sysLearningGrowthService;
67
+
68
+    @Autowired
69
+    private IAccuracyStatisticsService accuracyStatisticsService;
70
+
71
+    @Autowired
72
+    private SeizureReportService seizureReportService;
73
+
74
+    @Autowired
75
+    private IAttendancePostRecordService attendancePostRecordService;
76
+
77
+    @Autowired
78
+    private ISysUserService sysUserService;
79
+
80
+    /**
81
+     * 首页报表-下载
82
+     */
83
+    @SneakyThrows
84
+    @GetMapping("/download")
85
+    public void downloadHomeReport(HttpServletResponse response, BaseLargeScreenQueryParamDto dto) {
86
+        // 获取首页报表-整体
87
+        SysHomeReportDto result = getHomeReportDto(dto);
88
+        // 设置响应头
89
+        String fileName = URLEncoder.encode("首页报表", "UTF-8");
90
+        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
91
+        response.setCharacterEncoding("UTF-8");
92
+        response.setHeader("Content-Disposition", "attachment;filename=" + fileName + ".xlsx");
93
+
94
+        // 1. 创建表头样式
95
+        WriteCellStyle headWriteCellStyle = new WriteCellStyle();
96
+
97
+        // 设置表头字体
98
+        WriteFont headWriteFont = new WriteFont();
99
+        headWriteFont.setFontHeightInPoints((short) 11);  // 字体大小
100
+        headWriteFont.setBold(true);                      // 加粗
101
+        headWriteFont.setFontName("宋体");                // 字体类型
102
+        headWriteFont.setColor(IndexedColors.BLACK.getIndex()); // 字体颜色
103
+        headWriteCellStyle.setWriteFont(headWriteFont);
104
+
105
+        // 设置表头单元格样式
106
+        headWriteCellStyle.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex()); // 背景色
107
+        headWriteCellStyle.setFillPatternType(FillPatternType.SOLID_FOREGROUND); // 填充模式
108
+        headWriteCellStyle.setHorizontalAlignment(HorizontalAlignment.CENTER);    // 水平居中
109
+        headWriteCellStyle.setVerticalAlignment(VerticalAlignment.CENTER);      // 垂直居中
110
+        headWriteCellStyle.setWrapped(true);  // 自动换行
111
+
112
+        // 设置表头边框 - 细实线
113
+        headWriteCellStyle.setBorderLeft(BorderStyle.THIN);
114
+        headWriteCellStyle.setBorderRight(BorderStyle.THIN);
115
+        headWriteCellStyle.setBorderTop(BorderStyle.THIN);
116
+        headWriteCellStyle.setBorderBottom(BorderStyle.THIN);
117
+
118
+        // 设置边框颜色
119
+        headWriteCellStyle.setTopBorderColor(IndexedColors.BLACK.getIndex());
120
+        headWriteCellStyle.setBottomBorderColor(IndexedColors.BLACK.getIndex());
121
+        headWriteCellStyle.setLeftBorderColor(IndexedColors.BLACK.getIndex());
122
+        headWriteCellStyle.setRightBorderColor(IndexedColors.BLACK.getIndex());
123
+
124
+        // 2. 创建内容样式
125
+        WriteCellStyle contentWriteCellStyle = new WriteCellStyle();
126
+
127
+        // 设置内容字体
128
+        WriteFont contentWriteFont = new WriteFont();
129
+        contentWriteFont.setFontHeightInPoints((short) 11);  // 内容字体大小
130
+        contentWriteFont.setFontName("宋体");
131
+        contentWriteFont.setColor(IndexedColors.BLACK.getIndex());
132
+        contentWriteCellStyle.setWriteFont(contentWriteFont);
133
+
134
+        // 设置内容单元格样式
135
+        contentWriteCellStyle.setHorizontalAlignment(HorizontalAlignment.CENTER);
136
+        contentWriteCellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
137
+        contentWriteCellStyle.setWrapped(true);
138
+
139
+        // 设置内容边框 - 细实线
140
+        contentWriteCellStyle.setBorderLeft(BorderStyle.THIN);
141
+        contentWriteCellStyle.setBorderRight(BorderStyle.THIN);
142
+        contentWriteCellStyle.setBorderTop(BorderStyle.THIN);
143
+        contentWriteCellStyle.setBorderBottom(BorderStyle.THIN);
144
+
145
+        // 设置边框颜色
146
+        contentWriteCellStyle.setTopBorderColor(IndexedColors.BLACK.getIndex());
147
+        contentWriteCellStyle.setBottomBorderColor(IndexedColors.BLACK.getIndex());
148
+        contentWriteCellStyle.setLeftBorderColor(IndexedColors.BLACK.getIndex());
149
+        contentWriteCellStyle.setRightBorderColor(IndexedColors.BLACK.getIndex());
150
+
151
+        HorizontalCellStyleStrategy horizontalCellStyleStrategy = new HorizontalCellStyleStrategy(headWriteCellStyle, contentWriteCellStyle);
152
+
153
+        // 创建ExcelWriter
154
+        ExcelWriter excelWriter = EasyExcel.write(response.getOutputStream())
155
+                .registerWriteHandler(horizontalCellStyleStrategy)
156
+                .build();
157
+
158
+        try {
159
+            // 第一个sheet:巡检合格率
160
+            WriteSheet checkSheet = EasyExcel.writerSheet(0, "巡检合格率")
161
+                    .head(SysHomeReportDetailCheckExcelDto.class)
162
+                    .build();
163
+            List<SysHomeReportDetailCheckExcelDto> checkExcelData = getCheckExcelDtoData(result.getCheckList());
164
+            excelWriter.write(checkExcelData, checkSheet);
165
+
166
+            // 第二个sheet:培训答题分数
167
+            WriteSheet learningSheet = EasyExcel.writerSheet(1, "培训答题分数")
168
+                    .head(SysHomeReportDetailLearningExcelDto.class)
169
+                    .build();
170
+            List<SysHomeReportDetailLearningExcelDto> learningExcelData = getLearningExcelDtoData(result.getLearningList());
171
+            excelWriter.write(learningExcelData, learningSheet);
172
+
173
+            // 第三个sheet:抽问抽答正确率
174
+            WriteSheet answerSheet = EasyExcel.writerSheet(2, "抽问抽答正确率")
175
+                    .head(SysHomeReportDetailAnswerExcelDto.class)
176
+                    .build();
177
+            List<SysHomeReportDetailAnswerExcelDto> answerExcelData = getAnswerExcelDtoData(result.getAnswerList());
178
+            excelWriter.write(answerExcelData, answerSheet);
179
+
180
+            // 第四个sheet:查获数量
181
+            WriteSheet seizureSheet = EasyExcel.writerSheet(3, "查获数量")
182
+                    .head(SysHomeReportDetailSeizureExcelDto.class)
183
+                    .build();
184
+            List<SysHomeReportDetailSeizureExcelDto> seizureExcelData = getSeizureExcelDtoData(result.getSeizureList());
185
+            excelWriter.write(seizureExcelData, seizureSheet);
186
+
187
+            // 第五个sheet:工作时长
188
+            WriteSheet workingSheet = EasyExcel.writerSheet(4, "工作时长")
189
+                    .head(SysHomeReportDetailWorkingExcelDto.class)
190
+                    .build();
191
+            List<SysHomeReportDetailWorkingExcelDto> workingExcelData = getWorkingExcelDtoData(result.getWorkingList());
192
+            excelWriter.write(workingExcelData, workingSheet);
193
+        } catch (Exception e) {
194
+            throw new RuntimeException("导出报表失败", e);
195
+        } finally {
196
+            if (excelWriter != null) {
197
+                excelWriter.finish();
198
+            }
199
+        }
200
+    }
201
+
202
+    /**
203
+     * 获取首页报表下载数据-工作时长
204
+     *
205
+     * @param workingList
206
+     * @return
207
+     */
208
+    private List<SysHomeReportDetailWorkingExcelDto> getWorkingExcelDtoData(List<SysHomeReportDetailDto> workingList) {
209
+        List<SysHomeReportDetailWorkingExcelDto> result = new ArrayList<>();
210
+        workingList.forEach(item -> {
211
+            SysHomeReportDetailWorkingExcelDto excelDto = new SysHomeReportDetailWorkingExcelDto();
212
+            excelDto.setName(item.getName());
213
+            excelDto.setTotalNumber(item.getTotalNumber());
214
+            excelDto.setAverageNumber(item.getAverageNumber());
215
+            excelDto.setMedianNumber(item.getMedianNumber());
216
+            excelDto.setMaxNumber(item.getMaxNumber());
217
+            excelDto.setMinNumber(item.getMinNumber());
218
+            result.add(excelDto);
219
+        });
220
+        return result;
221
+    }
222
+
223
+    /**
224
+     * 获取首页报表下载数据-巡检合格率
225
+     */
226
+    private List<SysHomeReportDetailCheckExcelDto> getCheckExcelDtoData(List<SysHomeReportDetailDto> checkList) {
227
+        List<SysHomeReportDetailCheckExcelDto> result = new ArrayList<>();
228
+        checkList.forEach(item -> {
229
+            SysHomeReportDetailCheckExcelDto excelDto = new SysHomeReportDetailCheckExcelDto();
230
+            excelDto.setName(item.getName());
231
+            excelDto.setAverageNumber(item.getAverageNumber().multiply(BigDecimal.valueOf(100)));
232
+            excelDto.setMedianNumber(item.getMedianNumber().multiply(BigDecimal.valueOf(100)));
233
+            excelDto.setMaxNumber(item.getMaxNumber().multiply(BigDecimal.valueOf(100)));
234
+            excelDto.setMinNumber(item.getMinNumber().multiply(BigDecimal.valueOf(100)));
235
+            result.add(excelDto);
236
+        });
237
+        return result;
238
+    }
239
+
240
+    /**
241
+     * 获取首页报表下载数据-培训答题分数
242
+     */
243
+    private List<SysHomeReportDetailLearningExcelDto> getLearningExcelDtoData(List<SysHomeReportDetailDto> learningList) {
244
+        List<SysHomeReportDetailLearningExcelDto> result = new ArrayList<>();
245
+        learningList.forEach(item -> {
246
+            SysHomeReportDetailLearningExcelDto excelDto = new SysHomeReportDetailLearningExcelDto();
247
+            excelDto.setName(item.getName());
248
+            excelDto.setAverageNumber(item.getAverageNumber());
249
+            excelDto.setMedianNumber(item.getMedianNumber());
250
+            excelDto.setMaxNumber(item.getMaxNumber());
251
+            excelDto.setMinNumber(item.getMinNumber());
252
+            result.add(excelDto);
253
+        });
254
+        return result;
255
+    }
256
+
257
+    /**
258
+     * 获取首页报表下载数据-抽问抽答正确率
259
+     */
260
+    private List<SysHomeReportDetailAnswerExcelDto> getAnswerExcelDtoData(List<SysHomeReportDetailDto> answerList) {
261
+        List<SysHomeReportDetailAnswerExcelDto> result = new ArrayList<>();
262
+        if (answerList != null) {
263
+            answerList.forEach(item -> {
264
+                SysHomeReportDetailAnswerExcelDto excelDto = new SysHomeReportDetailAnswerExcelDto();
265
+                excelDto.setName(item.getName());
266
+                excelDto.setAverageNumber(item.getAverageNumber());
267
+                excelDto.setMedianNumber(item.getMedianNumber());
268
+                excelDto.setMaxNumber(item.getMaxNumber());
269
+                excelDto.setMinNumber(item.getMinNumber());
270
+                result.add(excelDto);
271
+            });
272
+        }
273
+        return result;
274
+    }
275
+
276
+    /**
277
+     * 获取首页报表下载数据-查获数量
278
+     */
279
+    private List<SysHomeReportDetailSeizureExcelDto> getSeizureExcelDtoData(List<SysHomeReportDetailDto> learningList) {
280
+        List<SysHomeReportDetailSeizureExcelDto> result = new ArrayList<>();
281
+        learningList.forEach(item -> {
282
+            SysHomeReportDetailSeizureExcelDto excelDto = new SysHomeReportDetailSeizureExcelDto();
283
+            excelDto.setName(item.getName());
284
+            excelDto.setTotalNumber(item.getTotalNumber());
285
+            excelDto.setAverageNumber(item.getAverageNumber());
286
+            excelDto.setMedianNumber(item.getMedianNumber());
287
+            excelDto.setMaxNumber(item.getMaxNumber());
288
+            excelDto.setMinNumber(item.getMinNumber());
289
+            result.add(excelDto);
290
+        });
291
+        return result;
292
+    }
293
+
294
+    /**
295
+     * 首页报表-整体
296
+     */
297
+    @GetMapping("/homeReportWhole")
298
+    public AjaxResult homePageWhole(BaseLargeScreenQueryParamDto dto) {
299
+        SysHomeReportDto result = getHomeReportDto(dto);
300
+        return success(result);
301
+    }
302
+
303
+    /**
304
+     * 获取首页报表-整体
305
+     */
306
+    private SysHomeReportDto getHomeReportDto(BaseLargeScreenQueryParamDto dto) {
307
+        List<SysHomePageDetailQueryParamDto> dtoList = new ArrayList<>();
308
+        List<SysDept> sysDeptList = deptService.selectAllDept(getDeptId());
309
+        Collections.reverse(sysDeptList);
310
+        SysDept stationDept = sysDeptList.stream().filter(x -> StrUtil.equals(DeptType.STATION.getCode(), x.getDeptType())).findFirst().orElse(null);
311
+        if (ObjectUtil.isNull(stationDept)) {
312
+            throw new ServiceException("未查询到站级部门信息");
313
+        }
314
+        SysHomePageDetailQueryParamDto stationDto = new SysHomePageDetailQueryParamDto();
315
+        stationDto.setId(stationDept.getDeptId());
316
+        stationDto.setName(stationDept.getDeptName());
317
+        stationDto.setType(HomePageQueryEnum.DEPT.getCode());
318
+        dtoList.add(stationDto);
319
+        SysDept queryDept = new SysDept();
320
+        queryDept.setParentId(stationDept.getDeptId());
321
+        List<SysDept> deptList = deptService.selectDeptInfoAll(queryDept);
322
+        deptList.forEach(item -> {
323
+            SysHomePageDetailQueryParamDto departmentDto = new SysHomePageDetailQueryParamDto();
324
+            departmentDto.setId(item.getDeptId());
325
+            departmentDto.setName(item.getDeptName());
326
+            departmentDto.setType(HomePageQueryEnum.DEPT.getCode());
327
+            dtoList.add(departmentDto);
328
+        });
329
+
330
+        dtoList.forEach(item -> {
331
+            item.setSpecifiedDate(dto.getSpecifiedDate());
332
+            item.setStartDate(dto.getStartDate());
333
+            item.setEndDate(dto.getEndDate());
334
+        });
335
+        SysHomeReportDto result = getSysHomeReportDto(dtoList);
336
+        return result;
337
+    }
338
+
339
+    /**
340
+     * 首页报表-明细
341
+     */
342
+    @PostMapping("/homeReportDetail")
343
+    public AjaxResult homePageDetail(@RequestBody List<SysHomePageDetailQueryParamDto> dtoList) {
344
+        SysHomeReportDto result = getSysHomeReportDto(dtoList);
345
+        return success(result);
346
+    }
347
+
348
+    /**
349
+     * 获取首页报表-明细
350
+     */
351
+    private SysHomeReportDto getSysHomeReportDto(List<SysHomePageDetailQueryParamDto> dtoList) {
352
+        SysHomeReportDto result = new SysHomeReportDto();
353
+        // 培训答题分数
354
+        result.setLearningList(getLearningList(dtoList));
355
+        // 巡检合格率
356
+        result.setCheckList(getCheckList(dtoList));
357
+        // 查获数量
358
+        result.setSeizureList(getSeizureList(dtoList));
359
+        // 在岗时长
360
+        result.setWorkingList(getWorkingList(dtoList));
361
+        return result;
362
+    }
363
+
364
+
365
+    /**
366
+     * 获取首页报表-明细-查获数量
367
+     */
368
+    private List<SysHomeReportDetailDto> getSeizureList(List<SysHomePageDetailQueryParamDto> dtoList) {
369
+        List<SysHomeReportDetailDto> result = new ArrayList<>();
370
+        for (SysHomePageDetailQueryParamDto item : dtoList) {
371
+            result.add(getSeizure(item));
372
+        }
373
+        return result;
374
+    }
375
+
376
+    /**
377
+     * 获取首页报表-明细-培训答题分数
378
+     */
379
+    private List<SysHomeReportDetailDto> getLearningList(List<SysHomePageDetailQueryParamDto> dtoList) {
380
+        List<SysHomeReportDetailDto> result = new ArrayList<>();
381
+        for (SysHomePageDetailQueryParamDto item : dtoList) {
382
+            result.add(getLearning(item));
383
+        }
384
+        return result;
385
+    }
386
+
387
+    /**
388
+     * 获取首页报表-明细-巡检合格率
389
+     */
390
+    private List<SysHomeReportDetailDto> getCheckList(List<SysHomePageDetailQueryParamDto> dtoList) {
391
+        List<SysHomeReportDetailDto> result = new ArrayList<>();
392
+        for (SysHomePageDetailQueryParamDto item : dtoList) {
393
+            result.add(getCheck(item));
394
+        }
395
+        return result;
396
+    }
397
+
398
+    /**
399
+     * 获取巡检合格率数据
400
+     */
401
+    private SysHomeReportDetailDto getCheck(SysHomePageDetailQueryParamDto item) {
402
+        BaseLargeScreenQueryParamDto dto = new BaseLargeScreenQueryParamDto();
403
+        if (StrUtil.equals(HomePageQueryEnum.USER.getCode(), item.getType())) {
404
+            dto.setUserId(item.getId());
405
+        } else {
406
+            dto.setDeptId(item.getId());
407
+        }
408
+        dto.setSpecifiedDate(item.getSpecifiedDate());
409
+        dto.setStartDate(item.getStartDate());
410
+        dto.setEndDate(item.getEndDate());
411
+        return checkLargeScreenService.checkData(dto);
412
+    }
413
+
414
+    /**
415
+     * 获取培训答题分数数据
416
+     */
417
+    private SysHomeReportDetailDto getLearning(SysHomePageDetailQueryParamDto item) {
418
+        BaseLargeScreenQueryParamDto dto = new BaseLargeScreenQueryParamDto();
419
+        if (StrUtil.equals(HomePageQueryEnum.USER.getCode(), item.getType())) {
420
+            dto.setUserId(item.getId());
421
+        } else {
422
+            dto.setDeptId(item.getId());
423
+        }
424
+        dto.setSpecifiedDate(item.getSpecifiedDate());
425
+        dto.setStartDate(item.getStartDate());
426
+        dto.setEndDate(item.getEndDate());
427
+        return sysLearningGrowthService.learningGrowthData(dto);
428
+    }
429
+
430
+    /**
431
+     * 获取查获数量数据
432
+     */
433
+    private SysHomeReportDetailDto getSeizure(SysHomePageDetailQueryParamDto item) {
434
+        BaseLargeScreenQueryParamDto dto = new BaseLargeScreenQueryParamDto();
435
+        if (StrUtil.equals(HomePageQueryEnum.USER.getCode(), item.getType())) {
436
+            dto.setUserId(item.getId());
437
+        } else {
438
+            dto.setDeptId(item.getId());
439
+        }
440
+        dto.setSpecifiedDate(item.getSpecifiedDate());
441
+        dto.setStartDate(item.getStartDate());
442
+        dto.setEndDate(item.getEndDate());
443
+        return seizureReportService.seizureData(dto);
444
+    }
445
+
446
+
447
+    private List<SysHomeReportDetailDto> getWorkingList(List<SysHomePageDetailQueryParamDto> dtoList) {
448
+        List<SysHomeReportDetailDto> result = new ArrayList<>();
449
+        for (SysHomePageDetailQueryParamDto item : dtoList) {
450
+            result.add(getWorking(item));
451
+        }
452
+        return result;
453
+    }
454
+
455
+    private SysHomeReportDetailDto getWorking(SysHomePageDetailQueryParamDto item) {
456
+        // 构建查询参数
457
+        BaseLargeScreenQueryParamDto dto = new BaseLargeScreenQueryParamDto();
458
+        if (StrUtil.equals(HomePageQueryEnum.USER.getCode(), item.getType())) {
459
+            dto.setUserId(item.getId());
460
+        } else {
461
+            dto.setDeptId(item.getId());
462
+        }
463
+        dto.setSpecifiedDate(item.getSpecifiedDate());
464
+        dto.setStartDate(item.getStartDate());
465
+        dto.setEndDate(item.getEndDate());
466
+        return getWorkingHoursData(dto);
467
+    }
468
+
469
+    /**
470
+     * 获取在岗时长数据
471
+     */
472
+    public SysHomeReportDetailDto getWorkingHoursData(BaseLargeScreenQueryParamDto dto) {
473
+        if (ObjectUtils.isNull(dto.getUserId()) && ObjectUtils.isNull(dto.getDeptId())) {
474
+            throw new ServiceException("用户ID和部门ID不能同时为空");
475
+        }
476
+        // 默认筛选条件
477
+        if (ObjectUtils.isNull(dto.getStartDate()) && ObjectUtils.isNull(dto.getEndDate()) && ObjectUtils.isNull(dto.getSpecifiedDate())) {
478
+            dto.setEndDate(DateUtils.addSeconds(DateUtils.truncate(DateUtils.getNowDate(), Calendar.DAY_OF_MONTH), 86399));
479
+            dto.setStartDate(DateUtils.addDays(DateUtils.truncate(DateUtils.getNowDate(), Calendar.DAY_OF_MONTH), -6));
480
+        }
481
+
482
+        SysHomeReportDetailDto result = new SysHomeReportDetailDto();
483
+
484
+        // 全量数据 - 根据用户ID或部门ID获取对应的在岗记录
485
+        List<AttendanceWorkDurationDto> itemListAll = getAttendanceWorkDurationList(dto);
486
+
487
+        List<AttendanceWorkDurationDto> targetList;
488
+        if (ObjectUtils.isNotNull(dto.getUserId())) {
489
+            SysUser sysUser = sysUserService.selectUserById(dto.getUserId());
490
+            if (ObjectUtils.isNull(sysUser)) {
491
+                throw new ServiceException("【" + dto.getUserId() + "】用户不存在");
492
+            }
493
+            result.setId(sysUser.getUserId());
494
+            result.setName(sysUser.getNickName());
495
+            result.setType(HomePageQueryEnum.USER.getCode());
496
+            targetList = itemListAll.stream().filter(item -> ObjectUtil.equals(item.getId(), dto.getUserId())).collect(Collectors.toList());
497
+        } else {
498
+            SysDept sysDept = deptService.selectDeptById(dto.getDeptId());
499
+            if (ObjectUtils.isNull(sysDept)) {
500
+                throw new ServiceException("部门不存在");
501
+            }
502
+            result.setId(sysDept.getDeptId());
503
+            result.setName(sysDept.getDeptName());
504
+            result.setType(HomePageQueryEnum.DEPT.getCode());
505
+            // 根据部门ID查询该部门下的用户列表(这里可以根据实际角色进行调整)
506
+            List<SysUser> sysUserList = sysUserService.selectUserListByRoleKeyAndDeptId(
507
+                    Arrays.asList(RoleTypeEnum.banzuzhang.getCode(), RoleTypeEnum.SecurityCheck.getCode()),
508
+                    dto.getDeptId()
509
+            );
510
+            List<Long> userIdList = sysUserList.stream().map(SysUser::getUserId).collect(Collectors.toList());
511
+            targetList = itemListAll.stream().filter(item -> userIdList.contains(item.getId())).collect(Collectors.toList());
512
+        }
513
+
514
+        // 提取工作时长数值并排序
515
+        List<BigDecimal> targetValueList = targetList.stream()
516
+                .map(AttendanceWorkDurationDto::getWorkDuration)
517
+                .filter(Objects::nonNull)
518
+                .sorted()
519
+                .collect(Collectors.toList());
520
+
521
+        if (CollUtil.isEmpty(targetValueList)) {
522
+            return result;
523
+        }
524
+
525
+        // 最大值
526
+        result.setMaxNumber(targetValueList.get(targetValueList.size() - 1));
527
+        // 最小值
528
+        result.setMinNumber(targetValueList.get(0));
529
+        // 总和
530
+        BigDecimal sum = targetValueList.stream().reduce(BigDecimal.ZERO, BigDecimal::add);
531
+        result.setTotalNumber(sum);
532
+        // 总数
533
+        long totalCount = targetList.stream().map(AttendanceWorkDurationDto::getId).distinct().count();
534
+        // 平均值
535
+        result.setAverageNumber(sum.divide(new BigDecimal(totalCount), 2, RoundingMode.HALF_UP));
536
+        // 中位数
537
+        int size = targetValueList.size();
538
+        int middle = size / 2;
539
+        if (size % 2 == 1) {
540
+            result.setMedianNumber(targetValueList.get(middle));
541
+        } else {
542
+            result.setMedianNumber(targetValueList.get(middle - 1).add(targetValueList.get(middle)).divide(new BigDecimal(2), 2, RoundingMode.HALF_UP));
543
+        }
544
+        return result;
545
+    }
546
+
547
+    /**
548
+     * 获取在岗工作时长列表
549
+     */
550
+    private List<AttendanceWorkDurationDto> getAttendanceWorkDurationList(BaseLargeScreenQueryParamDto dto) {
551
+        List<AttendanceWorkDurationDto> result = new ArrayList<>();
552
+
553
+        if (ObjectUtils.isNotNull(dto.getUserId())) {
554
+            // 查询指定用户的总工作时长
555
+            BigDecimal workDuration = attendancePostRecordService.selectPersonalTotalWorkDurationInTimeRange(
556
+                    dto.getUserId(),
557
+                    dto.getStartDate(),
558
+                    dto.getEndDate()
559
+            );
560
+            if (workDuration != null) {
561
+                // 将分钟转换为小时
562
+                workDuration = workDuration.divide(new BigDecimal(60), 2, RoundingMode.HALF_UP);
563
+                AttendanceWorkDurationDto item = new AttendanceWorkDurationDto();
564
+                item.setId(dto.getUserId());
565
+                item.setWorkDuration(workDuration);
566
+                result.add(item);
567
+            }
568
+        } else if (ObjectUtils.isNotNull(dto.getDeptId())) {
569
+            // 根据部门查询该部门下所有用户的工作时长
570
+            SysDept sysDept = deptService.selectDeptById(dto.getDeptId());
571
+            if (sysDept != null) {
572
+                // 根据部门查询该部门下的所有用户
573
+                List<SysUser> sysUserList = sysUserService.selectUserListByRoleKeyAndDeptId(
574
+                        Arrays.asList(RoleTypeEnum.banzuzhang.getCode(), RoleTypeEnum.SecurityCheck.getCode()),
575
+                        dto.getDeptId()
576
+                );
577
+
578
+                // 提取用户ID列表
579
+                List<Long> userIds = sysUserList.stream()
580
+                        .map(SysUser::getUserId).distinct()
581
+                        .collect(Collectors.toList());
582
+
583
+                // 批量查询所有用户的工作时长
584
+                List<AttendanceWorkDurationDto> workDurationList = attendancePostRecordService.selectBatchPersonalTotalWorkDurationInTimeRange(
585
+                        userIds,
586
+                        dto.getStartDate(),
587
+                        dto.getEndDate()
588
+                );
589
+
590
+                // 将查询结果转换为Map便于查找
591
+                Map<Long, BigDecimal> workDurationMap = workDurationList.stream()
592
+                        .collect(Collectors.toMap(
593
+                                AttendanceWorkDurationDto::getId,
594
+                                AttendanceWorkDurationDto::getWorkDuration,
595
+                                (existing, replacement) -> existing
596
+                        ));
597
+
598
+                // 组装结果
599
+                for (SysUser user : sysUserList) {
600
+                    BigDecimal workDuration = workDurationMap.get(user.getUserId());
601
+                    if (workDuration == null) {
602
+                        workDuration = BigDecimal.ZERO;
603
+                    }
604
+                    if (workDuration.compareTo(BigDecimal.ZERO) > 0) {
605
+                        // 将分钟转换为小时
606
+                        workDuration = workDuration.divide(new BigDecimal(60), 2, RoundingMode.HALF_UP);
607
+                    }
608
+                    AttendanceWorkDurationDto item = new AttendanceWorkDurationDto();
609
+                    item.setId(user.getUserId());
610
+                    item.setWorkDuration(workDuration);
611
+                    result.add(item);
612
+                }
613
+            }
614
+        }
615
+
616
+        return result;
617
+    }
618
+
619
+
620
+}

+ 11 - 0
airport-attendance/src/main/java/com/sundot/airport/attendance/mapper/AttendancePostRecordMapper.java

@@ -2,6 +2,7 @@ package com.sundot.airport.attendance.mapper;
2 2
 
3 3
 import com.sundot.airport.attendance.domain.AttendancePostRecord;
4 4
 import com.sundot.airport.common.core.domain.entity.SysUser;
5
+import com.sundot.airport.common.dto.AttendanceWorkDurationDto;
5 6
 import org.apache.ibatis.annotations.Param;
6 7
 
7 8
 import java.math.BigDecimal;
@@ -187,4 +188,14 @@ public interface AttendancePostRecordMapper {
187 188
      * @return 总工作时长(分钟)
188 189
      */
189 190
     BigDecimal selectTotalWorkDurationInTimeRange(@Param("list") List<Long> list, @Param("startTime") Date startTime, @Param("endTime") Date endTime);
191
+
192
+    /**
193
+     * 批量查询多个用户在指定时间段内的总工作时长
194
+     *
195
+     * @param userIds   用户ID列表
196
+     * @param startTime 开始时间
197
+     * @param endTime   结束时间
198
+     * @return 工作时长DTO列表
199
+     */
200
+    List<AttendanceWorkDurationDto> selectBatchPersonalTotalWorkDurationInTimeRange(@Param("userIds") List<Long> userIds, @Param("startTime") Date startTime, @Param("endTime") Date endTime);
190 201
 }

+ 11 - 0
airport-attendance/src/main/java/com/sundot/airport/attendance/service/IAttendancePostRecordService.java

@@ -2,6 +2,7 @@ package com.sundot.airport.attendance.service;
2 2
 
3 3
 import com.sundot.airport.attendance.domain.AttendancePostRecord;
4 4
 import com.sundot.airport.common.core.domain.entity.SysUser;
5
+import com.sundot.airport.common.dto.AttendanceWorkDurationDto;
5 6
 
6 7
 import java.math.BigDecimal;
7 8
 import java.util.Date;
@@ -195,4 +196,14 @@ public interface IAttendancePostRecordService {
195 196
      * @return 总工作时长(分钟)
196 197
      */
197 198
     BigDecimal selectTotalWorkDurationInTimeRange(List<Long> list, Date startTime, Date endTime);
199
+
200
+    /**
201
+     * 批量查询多个用户在指定时间段内的总工作时长
202
+     *
203
+     * @param userIds   用户ID列表
204
+     * @param startTime 开始时间
205
+     * @param endTime   结束时间
206
+     * @return 工作时长DTO列表
207
+     */
208
+    List<AttendanceWorkDurationDto> selectBatchPersonalTotalWorkDurationInTimeRange(List<Long> userIds, Date startTime, Date endTime);
198 209
 }

+ 6 - 0
airport-attendance/src/main/java/com/sundot/airport/attendance/service/impl/AttendancePostRecordServiceImpl.java

@@ -5,6 +5,7 @@ import com.sundot.airport.attendance.domain.AttendancePostRecord;
5 5
 import com.sundot.airport.attendance.mapper.AttendancePostRecordMapper;
6 6
 import com.sundot.airport.attendance.service.IAttendancePostRecordService;
7 7
 import com.sundot.airport.common.core.domain.entity.SysUser;
8
+import com.sundot.airport.common.dto.AttendanceWorkDurationDto;
8 9
 import com.sundot.airport.common.utils.DateUtils;
9 10
 import com.sundot.airport.common.utils.StringUtils;
10 11
 import com.sundot.airport.system.service.ISysConfigService;
@@ -343,4 +344,9 @@ public class AttendancePostRecordServiceImpl implements IAttendancePostRecordSer
343 344
     public BigDecimal selectTotalWorkDurationInTimeRange(List<Long> list, Date startTime, Date endTime) {
344 345
         return attendancePostRecordMapper.selectTotalWorkDurationInTimeRange(list, startTime, endTime);
345 346
     }
347
+
348
+    @Override
349
+    public List<AttendanceWorkDurationDto> selectBatchPersonalTotalWorkDurationInTimeRange(List<Long> userIds, Date startTime, Date endTime) {
350
+        return attendancePostRecordMapper.selectBatchPersonalTotalWorkDurationInTimeRange(userIds, startTime, endTime);
351
+    }
346 352
 }

+ 15 - 0
airport-attendance/src/main/resources/mapper/attendance/AttendancePostRecordMapper.xml

@@ -486,4 +486,19 @@
486 486
         and work_duration > 0
487 487
     </select>
488 488
 
489
+    <select id="selectBatchPersonalTotalWorkDurationInTimeRange"
490
+            resultType="com.sundot.airport.common.dto.AttendanceWorkDurationDto">
491
+        SELECT user_id as id, COALESCE(SUM(work_duration), 0) as workDuration
492
+        FROM attendance_post_record
493
+        WHERE user_id IN
494
+        <foreach collection="userIds" item="userId" open="(" separator="," close=")">
495
+            #{userId}
496
+        </foreach>
497
+        AND check_in_time &lt;= #{endTime}
498
+        AND check_out_time >= #{startTime}
499
+        AND work_duration IS NOT NULL
500
+        AND work_duration > 0
501
+        GROUP BY user_id
502
+    </select>
503
+
489 504
 </mapper>

+ 9 - 0
airport-check/src/main/java/com/sundot/airport/check/service/ICheckLargeScreenService.java

@@ -15,6 +15,7 @@ import com.sundot.airport.check.domain.CheckTask;
15 15
 import com.sundot.airport.common.core.domain.BaseLargeScreenQueryParamDto;
16 16
 import com.sundot.airport.common.core.domain.CheckLargeScreenHomePageItemDto;
17 17
 import com.sundot.airport.common.core.domain.CheckLargeScreenHomePageRankingDto;
18
+import com.sundot.airport.common.core.domain.SysHomeReportDetailDto;
18 19
 import com.sundot.airport.common.core.domain.SysLargeScreenDetailDto;
19 20
 
20 21
 import java.math.BigDecimal;
@@ -194,4 +195,12 @@ public interface ICheckLargeScreenService {
194 195
      * @return 首页-巡检-今日巡检问题数
195 196
      */
196 197
     public Integer checkCorrectionCount(BaseLargeScreenQueryParamDto dto);
198
+
199
+    /**
200
+     * 首页报表-巡检合格率数据
201
+     *
202
+     * @param dto 首页查询参数
203
+     * @return 首页报表-巡检合格率数据
204
+     */
205
+    public SysHomeReportDetailDto checkData(BaseLargeScreenQueryParamDto dto);
197 206
 }

+ 77 - 0
airport-check/src/main/java/com/sundot/airport/check/service/impl/CheckLargeScreenServiceImpl.java

@@ -32,6 +32,7 @@ import com.sundot.airport.common.core.domain.BaseLargeScreenQueryParamDto;
32 32
 import com.sundot.airport.common.core.domain.CheckLargeScreenHomePageItemDto;
33 33
 import com.sundot.airport.common.core.domain.CheckLargeScreenHomePageRankingDto;
34 34
 import com.sundot.airport.common.core.domain.LargeScreenHomePageUserInfoSqlDto;
35
+import com.sundot.airport.common.core.domain.SysHomeReportDetailDto;
35 36
 import com.sundot.airport.common.core.domain.SysLargeScreenDetailDto;
36 37
 import com.sundot.airport.common.core.domain.entity.SysDept;
37 38
 import com.sundot.airport.common.core.domain.entity.SysDictData;
@@ -42,6 +43,7 @@ import com.sundot.airport.common.enums.CheckLargeScreenCorrectionTypeEnum;
42 43
 import com.sundot.airport.common.enums.CheckLevelEnum;
43 44
 import com.sundot.airport.common.enums.DeptType;
44 45
 import com.sundot.airport.common.enums.DeptTypeEnum;
46
+import com.sundot.airport.common.enums.HomePageQueryEnum;
45 47
 import com.sundot.airport.common.enums.MedalTypeEnum;
46 48
 import com.sundot.airport.common.enums.RoleTypeEnum;
47 49
 import com.sundot.airport.common.enums.SourceTypeEnum;
@@ -2637,4 +2639,79 @@ public class CheckLargeScreenServiceImpl implements ICheckLargeScreenService {
2637 2639
         return checkLargeScreenMapper.checkCorrectionCount(dto);
2638 2640
     }
2639 2641
 
2642
+    /**
2643
+     * 首页报表-巡检合格率数据
2644
+     *
2645
+     * @param dto 首页查询参数
2646
+     * @return 首页报表-巡检合格率数据
2647
+     */
2648
+    @Override
2649
+    public SysHomeReportDetailDto checkData(BaseLargeScreenQueryParamDto dto) {
2650
+        if (ObjUtil.isNull(dto.getUserId()) && ObjUtil.isNull(dto.getDeptId())) {
2651
+            throw new ServiceException("用户ID和部门ID不能同时为空");
2652
+        }
2653
+        // 默认筛选条件
2654
+        if (ObjUtil.isNull(dto.getStartDate()) && ObjUtil.isNull(dto.getEndDate()) && ObjUtil.isNull(dto.getSpecifiedDate())) {
2655
+            dto.setEndDate(LargeScreenDateUtils.getCurrentDate());
2656
+            dto.setStartDate(LargeScreenDateUtils.getDateBeforeYears(1));
2657
+        }
2658
+        SysHomeReportDetailDto result = new SysHomeReportDetailDto();
2659
+        // 全量数据
2660
+        List<CheckLargeScreenHomePageItemDto> itemListAll = getCheckLargeScreenHomePageItemDtoList(dto);
2661
+
2662
+        List<CheckLargeScreenHomePageItemDto> targetList;
2663
+        if (ObjUtil.isNotNull(dto.getUserId())) {
2664
+            SysUser sysUser = sysUserService.selectUserById(dto.getUserId());
2665
+            if (ObjUtil.isNull(sysUser)) {
2666
+                throw new ServiceException("【" + dto.getUserId() + "】用户不存在");
2667
+            }
2668
+            result.setId(sysUser.getUserId());
2669
+            result.setName(sysUser.getNickName());
2670
+            result.setType(HomePageQueryEnum.USER.getCode());
2671
+            targetList = itemListAll.stream().filter(item -> ObjUtil.equals(item.getId(), dto.getUserId())).collect(Collectors.toList());
2672
+        } else {
2673
+            SysDept sysDept = sysDeptService.selectDeptById(dto.getDeptId());
2674
+            if (ObjUtil.isNull(sysDept)) {
2675
+                throw new ServiceException("部门不存在");
2676
+            }
2677
+            result.setId(sysDept.getDeptId());
2678
+            result.setName(sysDept.getDeptName());
2679
+            result.setType(HomePageQueryEnum.DEPT.getCode());
2680
+            List<SysUser> sysUserList = sysUserService.selectUserListByRoleKeyAndDeptId(Arrays.asList(RoleTypeEnum.banzuzhang.getCode(), RoleTypeEnum.SecurityCheck.getCode()), sysDept.getDeptId());
2681
+            List<Long> userIdList = sysUserList.stream().map(SysUser::getUserId).collect(Collectors.toList());
2682
+            targetList = itemListAll.stream().filter(item -> userIdList.contains(item.getId())).collect(Collectors.toList());
2683
+        }
2684
+        List<BigDecimal> targetValueList = targetList.stream()
2685
+                .map(CheckLargeScreenHomePageItemDto::getPassRate)
2686
+                .filter(Objects::nonNull)
2687
+                .sorted()
2688
+                .collect(Collectors.toList());
2689
+        if (CollUtil.isEmpty(targetValueList)) {
2690
+            result.setMaxNumber(BigDecimal.ONE);
2691
+            result.setMinNumber(BigDecimal.ONE);
2692
+            result.setAverageNumber(BigDecimal.ONE);
2693
+            result.setMedianNumber(BigDecimal.ONE);
2694
+            return result;
2695
+        }
2696
+        // 最大值
2697
+        result.setMaxNumber(targetValueList.get(targetValueList.size() - 1));
2698
+        // 最小值
2699
+        result.setMinNumber(targetValueList.get(0));
2700
+        // 总和
2701
+        BigDecimal sum = targetValueList.stream().reduce(BigDecimal.ZERO, BigDecimal::add);
2702
+        // 总数
2703
+        int totalCount = targetValueList.size();
2704
+        // 平均值
2705
+        result.setAverageNumber(sum.divide(new BigDecimal(totalCount), 4, RoundingMode.HALF_UP));
2706
+        // 中位数
2707
+        int size = targetValueList.size();
2708
+        int middle = size / 2;
2709
+        if (size % 2 == 1) {
2710
+            result.setMedianNumber(targetValueList.get(middle));
2711
+        } else {
2712
+            result.setMedianNumber(targetValueList.get(middle - 1).add(targetValueList.get(middle)).divide(new BigDecimal(2), 2, RoundingMode.HALF_UP));
2713
+        }
2714
+        return result;
2715
+    }
2716
+
2640 2717
 }

+ 32 - 0
airport-common/src/main/java/com/sundot/airport/common/core/domain/SysHomeReportDetailAnswerExcelDto.java

@@ -0,0 +1,32 @@
1
+package com.sundot.airport.common.core.domain;
2
+
3
+import com.alibaba.excel.annotation.ExcelProperty;
4
+import lombok.Data;
5
+
6
+import java.math.BigDecimal;
7
+
8
+/**
9
+ * 首页报表-抽问抽答正确率数据
10
+ *
11
+ * @author Claude
12
+ * @date 2025-01-21
13
+ */
14
+@Data
15
+public class SysHomeReportDetailAnswerExcelDto {
16
+
17
+    @ExcelProperty("抽问抽答正确率(%)")
18
+    private String name;
19
+
20
+    @ExcelProperty("平均数")
21
+    private BigDecimal averageNumber;
22
+
23
+    @ExcelProperty("中位数")
24
+    private BigDecimal medianNumber;
25
+
26
+    @ExcelProperty("最大值")
27
+    private BigDecimal maxNumber;
28
+
29
+    @ExcelProperty("最小值")
30
+    private BigDecimal minNumber;
31
+
32
+}

+ 32 - 0
airport-common/src/main/java/com/sundot/airport/common/core/domain/SysHomeReportDetailCheckExcelDto.java

@@ -0,0 +1,32 @@
1
+package com.sundot.airport.common.core.domain;
2
+
3
+import com.alibaba.excel.annotation.ExcelProperty;
4
+import lombok.Data;
5
+
6
+import java.math.BigDecimal;
7
+
8
+/**
9
+ * 首页报表-巡检合格率数据
10
+ *
11
+ * @author ruoyi
12
+ * @date 2025-01-06
13
+ */
14
+@Data
15
+public class SysHomeReportDetailCheckExcelDto {
16
+
17
+    @ExcelProperty("巡检合格率(%)")
18
+    private String name;
19
+
20
+    @ExcelProperty("平均数")
21
+    private BigDecimal averageNumber;
22
+
23
+    @ExcelProperty("中位数")
24
+    private BigDecimal medianNumber;
25
+
26
+    @ExcelProperty("最大值")
27
+    private BigDecimal maxNumber;
28
+
29
+    @ExcelProperty("最小值")
30
+    private BigDecimal minNumber;
31
+
32
+}

+ 32 - 0
airport-common/src/main/java/com/sundot/airport/common/core/domain/SysHomeReportDetailLearningExcelDto.java

@@ -0,0 +1,32 @@
1
+package com.sundot.airport.common.core.domain;
2
+
3
+import com.alibaba.excel.annotation.ExcelProperty;
4
+import lombok.Data;
5
+
6
+import java.math.BigDecimal;
7
+
8
+/**
9
+ * 首页报表-培训答题分数数据
10
+ *
11
+ * @author ruoyi
12
+ * @date 2025-01-06
13
+ */
14
+@Data
15
+public class SysHomeReportDetailLearningExcelDto {
16
+
17
+    @ExcelProperty("培训答题分数")
18
+    private String name;
19
+
20
+    @ExcelProperty("平均数")
21
+    private BigDecimal averageNumber;
22
+
23
+    @ExcelProperty("中位数")
24
+    private BigDecimal medianNumber;
25
+
26
+    @ExcelProperty("最大值")
27
+    private BigDecimal maxNumber;
28
+
29
+    @ExcelProperty("最小值")
30
+    private BigDecimal minNumber;
31
+
32
+}

+ 35 - 0
airport-common/src/main/java/com/sundot/airport/common/core/domain/SysHomeReportDetailSeizureExcelDto.java

@@ -0,0 +1,35 @@
1
+package com.sundot.airport.common.core.domain;
2
+
3
+import com.alibaba.excel.annotation.ExcelProperty;
4
+import lombok.Data;
5
+
6
+import java.math.BigDecimal;
7
+
8
+/**
9
+ * 首页报表-查获数量数据
10
+ *
11
+ * @author ruoyi
12
+ * @date 2025-01-06
13
+ */
14
+@Data
15
+public class SysHomeReportDetailSeizureExcelDto {
16
+
17
+    @ExcelProperty("查获数量")
18
+    private String name;
19
+
20
+    @ExcelProperty("总数")
21
+    private BigDecimal totalNumber;
22
+
23
+    @ExcelProperty("平均数")
24
+    private BigDecimal averageNumber;
25
+
26
+    @ExcelProperty("中位数")
27
+    private BigDecimal medianNumber;
28
+
29
+    @ExcelProperty("最大值")
30
+    private BigDecimal maxNumber;
31
+
32
+    @ExcelProperty("最小值")
33
+    private BigDecimal minNumber;
34
+
35
+}

+ 28 - 0
airport-common/src/main/java/com/sundot/airport/common/core/domain/SysHomeReportDetailWorkingExcelDto.java

@@ -0,0 +1,28 @@
1
+package com.sundot.airport.common.core.domain;
2
+
3
+import com.alibaba.excel.annotation.ExcelProperty;
4
+import lombok.Data;
5
+
6
+import java.math.BigDecimal;
7
+
8
+@Data
9
+public class SysHomeReportDetailWorkingExcelDto {
10
+
11
+    @ExcelProperty("在岗时长")
12
+    private String name;
13
+
14
+    @ExcelProperty("总数")
15
+    private BigDecimal totalNumber;
16
+
17
+    @ExcelProperty("平均数")
18
+    private BigDecimal averageNumber;
19
+
20
+    @ExcelProperty("中位数")
21
+    private BigDecimal medianNumber;
22
+
23
+    @ExcelProperty("最大值")
24
+    private BigDecimal maxNumber;
25
+
26
+    @ExcelProperty("最小值")
27
+    private BigDecimal minNumber;
28
+}

+ 41 - 0
airport-common/src/main/java/com/sundot/airport/common/core/domain/SysHomeReportDto.java

@@ -0,0 +1,41 @@
1
+package com.sundot.airport.common.core.domain;
2
+
3
+import lombok.Data;
4
+
5
+import java.util.List;
6
+
7
+/**
8
+ * 首页报表
9
+ *
10
+ * @author ruoyi
11
+ * @date 2025-01-06
12
+ */
13
+@Data
14
+public class SysHomeReportDto {
15
+
16
+    /**
17
+     * 巡检合格率
18
+     */
19
+    private List<SysHomeReportDetailDto> checkList;
20
+
21
+    /**
22
+     * 培训答题分数
23
+     */
24
+    private List<SysHomeReportDetailDto> learningList;
25
+
26
+    /**
27
+     * 查获数量
28
+     */
29
+    private List<SysHomeReportDetailDto> seizureList;
30
+
31
+    /**
32
+     * 在岗时长
33
+     */
34
+    private List<SysHomeReportDetailDto> workingList;
35
+
36
+    /**
37
+     * 抽问抽答正确率
38
+     */
39
+    private List<SysHomeReportDetailDto> answerList;
40
+
41
+}

+ 26 - 0
airport-common/src/main/java/com/sundot/airport/common/dto/AttendanceWorkDurationDto.java

@@ -0,0 +1,26 @@
1
+package com.sundot.airport.common.dto;
2
+
3
+import lombok.Data;
4
+
5
+import java.math.BigDecimal;
6
+
7
+/**
8
+ * 考勤工作时长数据传输对象
9
+ *
10
+ * @author ruoyi
11
+ * @date 2026-01-22
12
+ */
13
+@Data
14
+public class AttendanceWorkDurationDto {
15
+
16
+    /**
17
+     * ID (用户ID或部门ID)
18
+     */
19
+    private Long id;
20
+
21
+    /**
22
+     * 工作时长(小时)
23
+     */
24
+    private BigDecimal workDuration;
25
+
26
+}

+ 31 - 0
airport-item/src/main/java/com/sundot/airport/item/domain/ItemLargeScreenHomePageSeizureReportSqlDto.java

@@ -0,0 +1,31 @@
1
+package com.sundot.airport.item.domain;
2
+
3
+import lombok.Data;
4
+
5
+import java.math.BigDecimal;
6
+
7
+/**
8
+ * 首页-查获上报
9
+ *
10
+ * @author ruoyi
11
+ * @date 2025-09-07
12
+ */
13
+@Data
14
+public class ItemLargeScreenHomePageSeizureReportSqlDto {
15
+
16
+    /**
17
+     * 用户ID
18
+     */
19
+    private Long userId;
20
+
21
+    /**
22
+     * 用户名称
23
+     */
24
+    private String userName;
25
+
26
+    /**
27
+     * 数量
28
+     */
29
+    private BigDecimal quantity;
30
+
31
+}

+ 8 - 0
airport-item/src/main/java/com/sundot/airport/item/mapper/SeizureReportMapper.java

@@ -1,5 +1,7 @@
1 1
 package com.sundot.airport.item.mapper;
2 2
 
3
+import com.sundot.airport.common.core.domain.BaseLargeScreenQueryParamDto;
4
+import com.sundot.airport.item.domain.ItemLargeScreenHomePageSeizureReportSqlDto;
3 5
 import com.sundot.airport.item.domain.home.SeizureReportDTO;
4 6
 import org.apache.ibatis.annotations.Mapper;
5 7
 import org.apache.ibatis.annotations.Param;
@@ -402,4 +404,10 @@ public interface SeizureReportMapper {
402 404
      */
403 405
     public BigDecimal selectAverage(@Param("list") List<Long> list, @Param("startDate") Date startDate, @Param("endDate") Date endDate);
404 406
 
407
+    /**
408
+     * 首页-查获上报
409
+     *
410
+     * @return 首页-巡检单
411
+     */
412
+    public List<ItemLargeScreenHomePageSeizureReportSqlDto> homePageSeizureReport(BaseLargeScreenQueryParamDto dto);
405 413
 }

+ 121 - 0
airport-item/src/main/java/com/sundot/airport/item/service/SeizureReportService.java

@@ -1,30 +1,46 @@
1 1
 package com.sundot.airport.item.service;
2 2
 
3
+import cn.hutool.core.collection.CollUtil;
3 4
 import cn.hutool.core.collection.CollectionUtil;
5
+import cn.hutool.core.util.ObjUtil;
4 6
 import cn.hutool.core.util.ObjectUtil;
5 7
 import cn.hutool.core.util.StrUtil;
8
+import com.sundot.airport.common.core.domain.BaseLargeScreenQueryParamDto;
6 9
 import com.sundot.airport.common.core.domain.DataPermissionResult;
10
+import com.sundot.airport.common.core.domain.LargeScreenHomePageUserInfoSqlDto;
11
+import com.sundot.airport.common.core.domain.SeizureLargeScreenHomePageItemDto;
12
+import com.sundot.airport.common.core.domain.SysHomeReportDetailDto;
7 13
 import com.sundot.airport.common.core.domain.entity.SysDept;
8 14
 import com.sundot.airport.common.core.domain.entity.SysRole;
15
+import com.sundot.airport.common.core.domain.entity.SysUser;
9 16
 import com.sundot.airport.common.core.domain.model.LoginUser;
10 17
 import com.sundot.airport.common.enums.DataPermissionType;
11 18
 import com.sundot.airport.common.enums.DeptType;
19
+import com.sundot.airport.common.enums.HomePageQueryEnum;
12 20
 import com.sundot.airport.common.enums.RoleTypeEnum;
13 21
 import com.sundot.airport.common.enums.SourceTypeEnum;
14 22
 import com.sundot.airport.common.exception.ServiceException;
15 23
 import com.sundot.airport.common.utils.DateUtils;
24
+import com.sundot.airport.common.utils.LargeScreenDateUtils;
16 25
 import com.sundot.airport.common.utils.SecurityUtils;
17 26
 import com.sundot.airport.item.domain.FailedMatchItem;
27
+import com.sundot.airport.item.domain.ItemLargeScreenHomePageSeizureReportSqlDto;
18 28
 import com.sundot.airport.item.domain.home.*;
19 29
 import com.sundot.airport.system.service.ISysDeptService;
20 30
 import com.sundot.airport.item.mapper.SeizureReportMapper;
31
+import com.sundot.airport.system.service.ISysUserService;
21 32
 import org.springframework.beans.factory.annotation.Autowired;
22 33
 import org.springframework.stereotype.Service;
23 34
 
24 35
 import java.math.BigDecimal;
36
+import java.math.RoundingMode;
37
+import java.util.ArrayList;
38
+import java.util.Arrays;
25 39
 import java.util.Calendar;
26 40
 import java.util.Collections;
27 41
 import java.util.List;
42
+import java.util.Map;
43
+import java.util.Objects;
28 44
 import java.util.stream.Collectors;
29 45
 
30 46
 import static com.sundot.airport.common.utils.SecurityUtils.getLoginUser;
@@ -44,6 +60,9 @@ public class SeizureReportService {
44 60
     @Autowired
45 61
     private IFailedMatchItemService failedMatchItemService;
46 62
 
63
+    @Autowired
64
+    private ISysUserService sysUserService;
65
+
47 66
     /**
48 67
      * 获取按角色分类的查获上报数据
49 68
      */
@@ -636,4 +655,106 @@ public class SeizureReportService {
636 655
         }
637 656
     }
638 657
 
658
+    /**
659
+     * 首页报表-查获上报数据
660
+     *
661
+     * @param dto 首页查询参数
662
+     * @return 首页报表-查获上报数据
663
+     */
664
+    public SysHomeReportDetailDto seizureData(BaseLargeScreenQueryParamDto dto) {
665
+        if (ObjUtil.isNull(dto.getUserId()) && ObjUtil.isNull(dto.getDeptId())) {
666
+            throw new ServiceException("用户ID和部门ID不能同时为空");
667
+        }
668
+        // 默认筛选条件
669
+        if (ObjUtil.isNull(dto.getStartDate()) && ObjUtil.isNull(dto.getEndDate()) && ObjUtil.isNull(dto.getSpecifiedDate())) {
670
+            dto.setEndDate(LargeScreenDateUtils.getCurrentDate());
671
+            dto.setStartDate(LargeScreenDateUtils.getDateBeforeYears(1));
672
+        }
673
+        SysHomeReportDetailDto result = new SysHomeReportDetailDto();
674
+        // 全量数据
675
+        List<SeizureLargeScreenHomePageItemDto> itemListAll = getSeizureLargeScreenHomePageItemDtoList(dto);
676
+
677
+        List<SeizureLargeScreenHomePageItemDto> targetList;
678
+        if (ObjUtil.isNotNull(dto.getUserId())) {
679
+            SysUser sysUser = sysUserService.selectUserById(dto.getUserId());
680
+            if (ObjUtil.isNull(sysUser)) {
681
+                throw new ServiceException("【" + dto.getUserId() + "】用户不存在");
682
+            }
683
+            result.setId(sysUser.getUserId());
684
+            result.setName(sysUser.getNickName());
685
+            result.setType(HomePageQueryEnum.USER.getCode());
686
+            targetList = itemListAll.stream().filter(item -> ObjUtil.equals(item.getId(), dto.getUserId())).collect(Collectors.toList());
687
+        } else {
688
+            SysDept sysDept = sysDeptService.selectDeptById(dto.getDeptId());
689
+            if (ObjUtil.isNull(sysDept)) {
690
+                throw new ServiceException("部门不存在");
691
+            }
692
+            result.setId(sysDept.getDeptId());
693
+            result.setName(sysDept.getDeptName());
694
+            result.setType(HomePageQueryEnum.DEPT.getCode());
695
+            List<SysUser> sysUserList = sysUserService.selectUserListByRoleKeyAndDeptId(Arrays.asList(RoleTypeEnum.banzuzhang.getCode(), RoleTypeEnum.SecurityCheck.getCode()), sysDept.getDeptId());
696
+            List<Long> userIdList = sysUserList.stream().map(SysUser::getUserId).collect(Collectors.toList());
697
+            targetList = itemListAll.stream().filter(item -> userIdList.contains(item.getId())).collect(Collectors.toList());
698
+        }
699
+        List<BigDecimal> targetValueList = targetList.stream()
700
+                .map(SeizureLargeScreenHomePageItemDto::getQuantity)
701
+                .filter(Objects::nonNull)
702
+                .sorted()
703
+                .collect(Collectors.toList());
704
+        if (CollUtil.isEmpty(targetValueList)) {
705
+            result.setMaxNumber(BigDecimal.ZERO);
706
+            result.setMinNumber(BigDecimal.ZERO);
707
+            result.setTotalNumber(BigDecimal.ZERO);
708
+            result.setAverageNumber(BigDecimal.ZERO);
709
+            result.setMedianNumber(BigDecimal.ZERO);
710
+            return result;
711
+        }
712
+        // 最大值
713
+        result.setMaxNumber(targetValueList.get(targetValueList.size() - 1));
714
+        // 最小值
715
+        result.setMinNumber(targetValueList.get(0));
716
+        // 总和
717
+        BigDecimal sum = targetValueList.stream().reduce(BigDecimal.ZERO, BigDecimal::add);
718
+        result.setTotalNumber(sum);
719
+        // 总数
720
+        int totalCount = targetValueList.size();
721
+        // 平均值
722
+        result.setAverageNumber(sum.divide(new BigDecimal(totalCount), 2, RoundingMode.HALF_UP));
723
+        // 中位数
724
+        int size = targetValueList.size();
725
+        int middle = size / 2;
726
+        if (size % 2 == 1) {
727
+            result.setMedianNumber(targetValueList.get(middle));
728
+        } else {
729
+            result.setMedianNumber(targetValueList.get(middle - 1).add(targetValueList.get(middle)).divide(new BigDecimal(2), 2, RoundingMode.HALF_UP));
730
+        }
731
+        return result;
732
+    }
733
+
734
+    /**
735
+     * 查获上报全量数据
736
+     *
737
+     * @param dto 查询参数
738
+     * @return 查获上报全量数据
739
+     */
740
+    public List<SeizureLargeScreenHomePageItemDto> getSeizureLargeScreenHomePageItemDtoList(BaseLargeScreenQueryParamDto dto) {
741
+        List<SeizureLargeScreenHomePageItemDto> result = new ArrayList<>();
742
+        List<LargeScreenHomePageUserInfoSqlDto> userInfoListAll = sysUserService.homePageUserInfo();
743
+        if (CollUtil.isEmpty(userInfoListAll)) {
744
+            return Collections.emptyList();
745
+        }
746
+        List<ItemLargeScreenHomePageSeizureReportSqlDto> seizureReportListAll = seizureReportMapper.homePageSeizureReport(dto);
747
+        if (CollUtil.isEmpty(seizureReportListAll)) {
748
+            return Collections.emptyList();
749
+        }
750
+        Map<Long, BigDecimal> groupingBy = seizureReportListAll.stream().collect(Collectors.groupingBy(ItemLargeScreenHomePageSeizureReportSqlDto::getUserId, Collectors.reducing(BigDecimal.ZERO, ItemLargeScreenHomePageSeizureReportSqlDto::getQuantity, BigDecimal::add)));
751
+        userInfoListAll.forEach(userInfoSqlDto -> {
752
+            SeizureLargeScreenHomePageItemDto itemDto = new SeizureLargeScreenHomePageItemDto();
753
+            itemDto.setId(userInfoSqlDto.getUserId());
754
+            itemDto.setName(userInfoSqlDto.getNickName());
755
+            itemDto.setQuantity(groupingBy.getOrDefault(userInfoSqlDto.getUserId(), BigDecimal.ZERO));
756
+            result.add(itemDto);
757
+        });
758
+        return result;
759
+    }
639 760
 }

+ 13 - 0
airport-item/src/main/resources/mapper/item/SeizureReportMapper.xml

@@ -701,4 +701,17 @@
701 701
         </if>
702 702
     </select>
703 703
 
704
+    <select id="homePageSeizureReport"
705
+            resultType="com.sundot.airport.item.domain.ItemLargeScreenHomePageSeizureReportSqlDto">
706
+        select isr.inspect_user_id userId,
707
+        isr.inspect_user_name userName,
708
+        isi.quantity quantity
709
+        from item_seizure_record isr
710
+        left join item_seizure_items isi on isr.id = isi.record_id
711
+        where 1 = 1
712
+        and isr.process_status = 3
713
+        <if test="startDate != null and endDate != null">
714
+            AND isr.create_time BETWEEN #{startDate} AND #{endDate}
715
+        </if>
716
+    </select>
704 717
 </mapper>

+ 9 - 0
airport-system/src/main/java/com/sundot/airport/system/service/ISysLearningGrowthService.java

@@ -4,6 +4,7 @@ import java.math.BigDecimal;
4 4
 import java.util.List;
5 5
 
6 6
 import com.sundot.airport.common.core.domain.BaseLargeScreenQueryParamDto;
7
+import com.sundot.airport.common.core.domain.SysHomeReportDetailDto;
7 8
 import com.sundot.airport.system.domain.SysLargeScreenLearningGrowthDto;
8 9
 import com.sundot.airport.system.domain.SysLargeScreenLearningGrowthOrganizationalSupportDto;
9 10
 import com.sundot.airport.system.domain.SysLargeScreenLearningGrowthQueryParamDto;
@@ -105,4 +106,12 @@ public interface ISysLearningGrowthService {
105 106
      * @return 首页-学习成长-平均分
106 107
      */
107 108
     public BigDecimal learningGrowthAverage(BaseLargeScreenQueryParamDto dto);
109
+
110
+    /**
111
+     * 首页报表-培训答题分数数据
112
+     *
113
+     * @param dto 上行参数
114
+     * @return 首页报表-培训答题分数数据
115
+     */
116
+    public SysHomeReportDetailDto learningGrowthData(BaseLargeScreenQueryParamDto dto);
108 117
 }

+ 87 - 0
airport-system/src/main/java/com/sundot/airport/system/service/impl/SysLearningGrowthServiceImpl.java

@@ -8,17 +8,20 @@ import java.util.Comparator;
8 8
 import java.util.HashMap;
9 9
 import java.util.List;
10 10
 import java.util.Map;
11
+import java.util.Objects;
11 12
 import java.util.stream.Collectors;
12 13
 
13 14
 import cn.hutool.core.collection.CollUtil;
14 15
 import cn.hutool.core.util.ObjUtil;
15 16
 import cn.hutool.core.util.StrUtil;
16 17
 import com.sundot.airport.common.core.domain.BaseLargeScreenQueryParamDto;
18
+import com.sundot.airport.common.core.domain.SysHomeReportDetailDto;
17 19
 import com.sundot.airport.common.core.domain.entity.SysDept;
18 20
 import com.sundot.airport.common.core.domain.entity.SysRole;
19 21
 import com.sundot.airport.common.core.domain.entity.SysUser;
20 22
 import com.sundot.airport.common.enums.DeptType;
21 23
 import com.sundot.airport.common.enums.DeptTypeEnum;
24
+import com.sundot.airport.common.enums.HomePageQueryEnum;
22 25
 import com.sundot.airport.common.enums.RoleTypeEnum;
23 26
 import com.sundot.airport.common.exception.ServiceException;
24 27
 import com.sundot.airport.common.utils.DateUtils;
@@ -1046,4 +1049,88 @@ public class SysLearningGrowthServiceImpl implements ISysLearningGrowthService {
1046 1049
         BigDecimal sum = target.stream().map(SysLargeScreenLearningGrowthSqlDto::getExamScore).reduce(BigDecimal.ZERO, BigDecimal::add);
1047 1050
         return sum.divide(BigDecimal.valueOf(target.size()), 2, RoundingMode.HALF_UP);
1048 1051
     }
1052
+
1053
+    /**
1054
+     * 首页报表-培训答题分数数据
1055
+     *
1056
+     * @param dto 上行参数
1057
+     * @return 首页报表-培训答题分数数据
1058
+     */
1059
+    @Override
1060
+    public SysHomeReportDetailDto learningGrowthData(BaseLargeScreenQueryParamDto dto) {
1061
+        if (ObjUtil.isNull(dto.getUserId()) && ObjUtil.isNull(dto.getDeptId())) {
1062
+            throw new ServiceException("用户ID和部门ID不能同时为空");
1063
+        }
1064
+        // 默认筛选条件
1065
+        if (ObjUtil.isNull(dto.getStartDate()) && ObjUtil.isNull(dto.getEndDate()) && ObjUtil.isNull(dto.getSpecifiedDate())) {
1066
+            dto.setEndDate(LargeScreenDateUtils.getCurrentDate());
1067
+            dto.setStartDate(LargeScreenDateUtils.getDateBeforeYears(1));
1068
+        }
1069
+        SysHomeReportDetailDto result = new SysHomeReportDetailDto();
1070
+        SysLargeScreenLearningGrowthQueryParamDto tempQueryParam = new SysLargeScreenLearningGrowthQueryParamDto();
1071
+        tempQueryParam.setSpecifiedDate(dto.getSpecifiedDate());
1072
+        tempQueryParam.setStartDate(dto.getStartDate());
1073
+        tempQueryParam.setEndDate(dto.getEndDate());
1074
+        if (ObjUtil.isNotNull(dto.getUserId())) {
1075
+            SysUser sysUser = sysUserService.selectUserById(dto.getUserId());
1076
+            if (ObjUtil.isNull(sysUser)) {
1077
+                throw new ServiceException("【" + dto.getUserId() + "】用户不存在");
1078
+            }
1079
+            result.setId(sysUser.getUserId());
1080
+            result.setName(sysUser.getNickName());
1081
+            result.setType(HomePageQueryEnum.USER.getCode());
1082
+            tempQueryParam.setUserId(dto.getUserId());
1083
+        } else {
1084
+            SysDept sysDept = sysDeptService.selectDeptById(dto.getDeptId());
1085
+            if (ObjUtil.isNull(sysDept)) {
1086
+                throw new ServiceException("【" + dto.getDeptId() + "】部门不存在");
1087
+            }
1088
+            result.setId(sysDept.getDeptId());
1089
+            result.setName(sysDept.getDeptName());
1090
+            result.setType(HomePageQueryEnum.DEPT.getCode());
1091
+            if (StrUtil.equals(DeptTypeEnum.STATION.getCode(), sysDept.getDeptType())) {
1092
+                tempQueryParam.setStationId(sysDept.getDeptId());
1093
+            } else if (StrUtil.equals(DeptTypeEnum.BRIGADE.getCode(), sysDept.getDeptType())) {
1094
+                tempQueryParam.setBrigadeId(sysDept.getDeptId());
1095
+            } else if (StrUtil.equals(DeptTypeEnum.MANAGER.getCode(), sysDept.getDeptType())) {
1096
+                tempQueryParam.setDepartmentId(sysDept.getDeptId());
1097
+            } else if (StrUtil.equals(DeptTypeEnum.TEAMS.getCode(), sysDept.getDeptType())) {
1098
+                tempQueryParam.setTeamId(sysDept.getDeptId());
1099
+            } else {
1100
+                throw new ServiceException("【" + dto.getDeptId() + "】部门类型异常");
1101
+            }
1102
+        }
1103
+        List<SysLargeScreenLearningGrowthSqlDto> targetList = sysLearningGrowthMapper.selectSysLearningGrowthListByCondition(tempQueryParam);
1104
+        List<BigDecimal> targetValueList = targetList.stream()
1105
+                .map(SysLargeScreenLearningGrowthSqlDto::getExamScore)
1106
+                .filter(Objects::nonNull)
1107
+                .sorted()
1108
+                .collect(Collectors.toList());
1109
+        if (CollUtil.isEmpty(targetValueList)) {
1110
+            result.setMaxNumber(BigDecimal.ZERO);
1111
+            result.setMinNumber(BigDecimal.ZERO);
1112
+            result.setAverageNumber(BigDecimal.ZERO);
1113
+            result.setMedianNumber(BigDecimal.ZERO);
1114
+            return result;
1115
+        }
1116
+        // 最大值
1117
+        result.setMaxNumber(targetValueList.get(targetValueList.size() - 1));
1118
+        // 最小值
1119
+        result.setMinNumber(targetValueList.get(0));
1120
+        // 总和
1121
+        BigDecimal sum = targetValueList.stream().reduce(BigDecimal.ZERO, BigDecimal::add);
1122
+        // 总数
1123
+        int totalCount = targetValueList.size();
1124
+        // 平均值
1125
+        result.setAverageNumber(sum.divide(new BigDecimal(totalCount), 2, RoundingMode.HALF_UP));
1126
+        // 中位数
1127
+        int size = targetValueList.size();
1128
+        int middle = size / 2;
1129
+        if (size % 2 == 1) {
1130
+            result.setMedianNumber(targetValueList.get(middle));
1131
+        } else {
1132
+            result.setMedianNumber(targetValueList.get(middle - 1).add(targetValueList.get(middle)).divide(new BigDecimal(2), 2, RoundingMode.HALF_UP));
1133
+        }
1134
+        return result;
1135
+    }
1049 1136
 }