Преглед на файлове

非干部职能部门统计

wangxx преди 1 месец
родител
ревизия
e882c92fab

+ 406 - 8
airport-admin/src/main/java/com/sundot/airport/web/controller/personnel/PersonnelNonCadreMonthlyAssessmentScoreSummaryController.java

@@ -5,6 +5,9 @@ import com.sundot.airport.common.core.domain.AjaxResult;
5 5
 import com.sundot.airport.common.core.domain.entity.SysDept;
6 6
 import com.sundot.airport.common.core.domain.entity.SysUser;
7 7
 import com.sundot.airport.personnel.dto.AssessmentSummaryDto;
8
+import com.sundot.airport.personnel.dto.FunctionalDeptSummaryDto;
9
+import com.sundot.airport.personnel.dto.FunctionalDeptPersonnelDistributionDto;
10
+import com.sundot.airport.personnel.dto.FunctionalDeptDistributionPieDto;
8 11
 import com.sundot.airport.personnel.dto.AssessmentTeamActualImprovementDistributionDto;
9 12
 import com.sundot.airport.personnel.dto.AssessmentTeamActualIncompetentDistributionDto;
10 13
 import com.sundot.airport.personnel.dto.DeptActualImprovementDistributionDto;
@@ -147,12 +150,19 @@ public class PersonnelNonCadreMonthlyAssessmentScoreSummaryController extends Ba
147 150
             // 构建大队到其所有子部门ID的映射
148 151
             Map<Long, Set<Long>> brigadeSubDeptsMap = buildBrigadeSubDeptsMap(deptMap);
149 152
 
153
+            // 批量查询用户部门映射
154
+            Set<Long> userIds = list.stream()
155
+                    .map(PersonnelNonCadreMonthlyAssessment::getUserId)
156
+                    .filter(Objects::nonNull)
157
+                    .collect(Collectors.toSet());
158
+            Map<Long, Long> userDeptIdMap = buildUserDeptIdMap(userIds);
159
+
150 160
             // 按大队统计人数
151 161
             Map<Long, Integer> brigadeCountMap = new HashMap<>();
152 162
             int totalCount = list.size();
153 163
 
154 164
             for (PersonnelNonCadreMonthlyAssessment item : list) {
155
-                Long userDeptId = getUserDeptId(item.getUserId());
165
+                Long userDeptId = userDeptIdMap.get(item.getUserId());
156 166
                 if (userDeptId != null) {
157 167
                     // 查找该用户所属的大队
158 168
                     Long brigadeId = findUserBrigade(userDeptId, brigadeSubDeptsMap);
@@ -223,6 +233,13 @@ public class PersonnelNonCadreMonthlyAssessmentScoreSummaryController extends Ba
223 233
             // 构建大队到其所有子部门ID的映射
224 234
             Map<Long, Set<Long>> brigadeSubDeptsMap = buildBrigadeSubDeptsMap(deptMap);
225 235
 
236
+            // 批量查询用户部门映射
237
+            Set<Long> userIds = list.stream()
238
+                    .map(PersonnelNonCadreMonthlyAssessment::getUserId)
239
+                    .filter(Objects::nonNull)
240
+                    .collect(Collectors.toSet());
241
+            Map<Long, Long> userDeptIdMap = buildUserDeptIdMap(userIds);
242
+
226 243
             // 定义6个分数段
227 244
             String[] rangeKeys = {"below70", "70-75", "75-80", "80-85", "85-90", "above90"};
228 245
             String[] rangeLabels = {"低于70", "[70-75)", "[75-80)", "[80-85)", "[85-90)", "90以上"};
@@ -234,7 +251,7 @@ public class PersonnelNonCadreMonthlyAssessmentScoreSummaryController extends Ba
234 251
 
235 252
             // 统计每个分数段下各大队的人数
236 253
             for (PersonnelNonCadreMonthlyAssessment item : list) {
237
-                Long userDeptId = getUserDeptId(item.getUserId());
254
+                Long userDeptId = userDeptIdMap.get(item.getUserId());
238 255
                 if (userDeptId == null) {
239 256
                     continue;
240 257
                 }
@@ -581,7 +598,7 @@ public class PersonnelNonCadreMonthlyAssessmentScoreSummaryController extends Ba
581 598
                 return success(Collections.emptyList());
582 599
             }
583 600
     
584
-            // 批量查询用户部门信息,避免N+1问题
601
+            // 批量查询用户部门信息
585 602
             Set<Long> userIds = actualIncompetentList.stream()
586 603
                     .map(PersonnelNonCadreMonthlyAssessment::getUserId)
587 604
                     .filter(Objects::nonNull)
@@ -630,16 +647,24 @@ public class PersonnelNonCadreMonthlyAssessmentScoreSummaryController extends Ba
630 647
     }
631 648
 
632 649
     /**
633
-     * 批量构建用户到部门的映射
650
+     * 批量构建用户到部门的映射(批量查询,避免N+1问题)
634 651
      */
635 652
     private Map<Long, Long> buildUserDeptIdMap(Set<Long> userIds) {
636 653
         Map<Long, Long> userDeptIdMap = new HashMap<>();
637
-        for (Long userId : userIds) {
638
-            Long deptId = getUserDeptId(userId);
639
-            if (deptId != null) {
640
-                userDeptIdMap.put(userId, deptId);
654
+        
655
+        if (userIds == null || userIds.isEmpty()) {
656
+            return userDeptIdMap;
657
+        }
658
+        
659
+        // 批量查询用户信息
660
+        List<SysUser> users = sysUserService.selectByUserIdList(new ArrayList<>(userIds));
661
+        
662
+        for (SysUser user : users) {
663
+            if (user != null && user.getDeptId() != null) {
664
+                userDeptIdMap.put(user.getUserId(), user.getDeptId());
641 665
             }
642 666
         }
667
+        
643 668
         return userDeptIdMap;
644 669
     }
645 670
 
@@ -893,6 +918,8 @@ public class PersonnelNonCadreMonthlyAssessmentScoreSummaryController extends Ba
893 918
         }
894 919
     }
895 920
 
921
+
922
+
896 923
     /**
897 924
      * 大队考核组统计
898 925
      * 先按大队筛选,再按考核组统计,应用汇总统计规则
@@ -1247,4 +1274,375 @@ public class PersonnelNonCadreMonthlyAssessmentScoreSummaryController extends Ba
1247 1274
             return error("统计失败:" + e.getMessage());
1248 1275
         }
1249 1276
     }
1277
+
1278
+    /**
1279
+     * 各职能大队汇总
1280
+     * 统计所有职能部门
1281
+     *
1282
+     * @param assessmentMonth 考核月份(格式:YYYYMM)
1283
+     * @return 各职能大队汇总数据,包含小计
1284
+     */
1285
+    @PreAuthorize("@ss.hasPermi('personnel:assessment:query')")
1286
+    @GetMapping("/functional-dept-summary")
1287
+    public AjaxResult getFunctionalDeptSummary(@RequestParam String assessmentMonth) {
1288
+        try {
1289
+            List<PersonnelNonCadreMonthlyAssessment> allList = queryByMonth(assessmentMonth);
1290
+
1291
+            if (allList == null || allList.isEmpty()) {
1292
+                return success(Collections.emptyList());
1293
+            }
1294
+
1295
+            // 获取所有部门信息
1296
+            Map<Long, SysDept> deptMap = getDeptMap();
1297
+
1298
+            // 查询用户部门映射
1299
+            Set<Long> userIds = allList.stream()
1300
+                    .map(PersonnelNonCadreMonthlyAssessment::getUserId)
1301
+                    .filter(Objects::nonNull)
1302
+                    .collect(Collectors.toSet());
1303
+            Map<Long, Long> userDeptIdMap = buildUserDeptIdMap(userIds);
1304
+
1305
+            // 筛选所有职能部门(is_functional_dept='1')
1306
+            List<SysDept> functionalDepts = deptMap.values().stream()
1307
+                    .filter(dept -> "1".equals(dept.getIsFunctionalDept()))
1308
+                    .collect(Collectors.toList());
1309
+
1310
+            if (functionalDepts.isEmpty()) {
1311
+                return success(Collections.emptyList());
1312
+            }
1313
+
1314
+            // 用于累加小计数据
1315
+            int totalAssessmentTeamCount = 0;
1316
+            int totalEstimatedImprovementCount = 0;
1317
+            int totalImprovementTotalCount = 0;
1318
+            int totalImprovementExemptedCount = 0;
1319
+            int totalActualImprovementCount = 0;
1320
+            int totalIncompetentTotalCount = 0;
1321
+            int totalIncompetentExemptedCount = 0;
1322
+            int totalActualIncompetentCount = 0;
1323
+
1324
+            // 构建返回结果
1325
+            List<FunctionalDeptSummaryDto> result = new ArrayList<>();
1326
+
1327
+            for (SysDept functionalDept : functionalDepts) {
1328
+                Long deptId = functionalDept.getDeptId();
1329
+                String deptName = functionalDept.getDeptName();
1330
+
1331
+                // 获取该职能部门及其所有子部门的ID集合
1332
+                Set<Long> functionalSubDeptIds = getAllSubDeptIds(deptId, deptMap);
1333
+
1334
+                // 筛选属于该职能部门的人员(包括子部门)
1335
+                List<PersonnelNonCadreMonthlyAssessment> deptRecords = allList.stream()
1336
+                        .filter(item -> {
1337
+                            Long userDeptId = userDeptIdMap.get(item.getUserId());
1338
+                            return userDeptId != null && functionalSubDeptIds.contains(userDeptId);
1339
+                        })
1340
+                        .collect(Collectors.toList());
1341
+
1342
+                if (deptRecords.isEmpty()) {
1343
+                    continue;
1344
+                }
1345
+
1346
+                // 按考核组分组
1347
+                Map<String, List<PersonnelNonCadreMonthlyAssessment>> teamGroupMap = deptRecords.stream()
1348
+                        .filter(item -> item.getAssessmentTeam() != null && !item.getAssessmentTeam().isEmpty())
1349
+                        .collect(Collectors.groupingBy(PersonnelNonCadreMonthlyAssessment::getAssessmentTeam));
1350
+
1351
+                List<FunctionalDeptSummaryDto.FunctionalTeamStatisticsDto> teamStatsList = new ArrayList<>();
1352
+
1353
+                for (Map.Entry<String, List<PersonnelNonCadreMonthlyAssessment>> teamEntry : teamGroupMap.entrySet()) {
1354
+                    String assessmentTeam = teamEntry.getKey();
1355
+                    List<PersonnelNonCadreMonthlyAssessment> teamRecords = teamEntry.getValue();
1356
+
1357
+                    // 统计该考核组的数据
1358
+                    int assessmentTeamCount = teamRecords.size();
1359
+                    int estimatedImprovementCount = (int) Math.ceil(assessmentTeamCount * 0.05);
1360
+
1361
+                    int improvementTotalCount = 0;
1362
+                    int improvementExemptedCount = 0;
1363
+                    int incompetentTotalCount = 0;
1364
+                    int incompetentExemptedCount = 0;
1365
+
1366
+                    for (PersonnelNonCadreMonthlyAssessment item : teamRecords) {
1367
+                        String assessmentResult = item.getAssessmentResult();
1368
+                        String exemption = item.getExemption();
1369
+
1370
+                        if (RESULT_IMPROVEMENT.equals(assessmentResult)) {
1371
+                            improvementTotalCount++;
1372
+                            if (EXEMPTION_YES.equals(exemption)) {
1373
+                                improvementExemptedCount++;
1374
+                            }
1375
+                        } else if (RESULT_INCOMPETENT.equals(assessmentResult)) {
1376
+                            incompetentTotalCount++;
1377
+                            if (EXEMPTION_YES.equals(exemption)) {
1378
+                                incompetentExemptedCount++;
1379
+                            }
1380
+                        }
1381
+                    }
1382
+
1383
+                    int actualImprovementCount = Math.max(0, improvementTotalCount - improvementExemptedCount);
1384
+                    int actualIncompetentCount = Math.max(0, incompetentTotalCount - incompetentExemptedCount);
1385
+
1386
+                    // 构建考核组统计数据
1387
+                    FunctionalDeptSummaryDto.FunctionalTeamStatisticsDto teamDto =
1388
+                            new FunctionalDeptSummaryDto.FunctionalTeamStatisticsDto();
1389
+                    teamDto.setAssessmentTeam(assessmentTeam);
1390
+                    teamDto.setAssessmentTeamCount(assessmentTeamCount);
1391
+                    teamDto.setEstimatedImprovementCount(estimatedImprovementCount);
1392
+                    teamDto.setImprovementTotalCount(improvementTotalCount);
1393
+                    teamDto.setImprovementExemptedCount(improvementExemptedCount);
1394
+                    teamDto.setActualImprovementCount(actualImprovementCount);
1395
+                    teamDto.setIncompetentTotalCount(incompetentTotalCount);
1396
+                    teamDto.setIncompetentExemptedCount(incompetentExemptedCount);
1397
+                    teamDto.setActualIncompetentCount(actualIncompetentCount);
1398
+
1399
+                    teamStatsList.add(teamDto);
1400
+
1401
+                    // 累加到小计
1402
+                    totalAssessmentTeamCount += assessmentTeamCount;
1403
+                    totalEstimatedImprovementCount += estimatedImprovementCount;
1404
+                    totalImprovementTotalCount += improvementTotalCount;
1405
+                    totalImprovementExemptedCount += improvementExemptedCount;
1406
+                    totalActualImprovementCount += actualImprovementCount;
1407
+                    totalIncompetentTotalCount += incompetentTotalCount;
1408
+                    totalIncompetentExemptedCount += incompetentExemptedCount;
1409
+                    totalActualIncompetentCount += actualIncompetentCount;
1410
+                }
1411
+
1412
+                // 构建职能部门统计数据
1413
+                FunctionalDeptSummaryDto deptDto = new FunctionalDeptSummaryDto();
1414
+                deptDto.setDeptId(deptId);
1415
+                deptDto.setDeptName(deptName);
1416
+                deptDto.setAssessmentTeams(teamStatsList);
1417
+                result.add(deptDto);
1418
+            }
1419
+
1420
+            // 添加小计行(合并所有考核组的数据)
1421
+            FunctionalDeptSummaryDto.FunctionalTeamStatisticsDto summaryDto =
1422
+                    new FunctionalDeptSummaryDto.FunctionalTeamStatisticsDto();
1423
+            summaryDto.setAssessmentTeam("小计");
1424
+            summaryDto.setAssessmentTeamCount(totalAssessmentTeamCount);
1425
+            summaryDto.setEstimatedImprovementCount(totalEstimatedImprovementCount);
1426
+            summaryDto.setImprovementTotalCount(totalImprovementTotalCount);
1427
+            summaryDto.setImprovementExemptedCount(totalImprovementExemptedCount);
1428
+            summaryDto.setActualImprovementCount(totalActualImprovementCount);
1429
+            summaryDto.setIncompetentTotalCount(totalIncompetentTotalCount);
1430
+            summaryDto.setIncompetentExemptedCount(totalIncompetentExemptedCount);
1431
+            summaryDto.setActualIncompetentCount(totalActualIncompetentCount);
1432
+
1433
+            // 将小计作为一个单独的部门添加到结果中
1434
+            FunctionalDeptSummaryDto summaryDept = new FunctionalDeptSummaryDto();
1435
+            summaryDept.setDeptName("小计");
1436
+            summaryDept.setAssessmentTeams(Collections.singletonList(summaryDto));
1437
+            result.add(summaryDept);
1438
+
1439
+            return success(result);
1440
+        } catch (Exception e) {
1441
+            logger.error("各职能大队汇总统计异常", e);
1442
+            return error("统计失败:" + e.getMessage());
1443
+        }
1444
+    }
1445
+
1446
+
1447
+    /**
1448
+     * 各职能部门待改进、不称职人员分布
1449
+     *
1450
+     * @param assessmentMonth 考核月份(格式:YYYYMM)
1451
+     * @return 各职能部门人员分布数据
1452
+     */
1453
+    @PreAuthorize("@ss.hasPermi('personnel:assessment:query')")
1454
+    @GetMapping("/functional-dept-personnel-distribution")
1455
+    public AjaxResult getFunctionalDeptPersonnelDistribution(@RequestParam String assessmentMonth) {
1456
+        try {
1457
+            List<PersonnelNonCadreMonthlyAssessment> allList = queryByMonth(assessmentMonth);
1458
+
1459
+            if (allList == null || allList.isEmpty()) {
1460
+                return success(Collections.emptyList());
1461
+            }
1462
+
1463
+            // 获取所有部门信息
1464
+            Map<Long, SysDept> deptMap = getDeptMap();
1465
+
1466
+            // 查询用户部门映射
1467
+            Set<Long> userIds = allList.stream()
1468
+                    .map(PersonnelNonCadreMonthlyAssessment::getUserId)
1469
+                    .filter(Objects::nonNull)
1470
+                    .collect(Collectors.toSet());
1471
+            Map<Long, Long> userDeptIdMap = buildUserDeptIdMap(userIds);
1472
+
1473
+            // 筛选所有职能部门(is_functional_dept='1')
1474
+            List<SysDept> functionalDepts = deptMap.values().stream()
1475
+                    .filter(dept -> "1".equals(dept.getIsFunctionalDept()))
1476
+                    .collect(Collectors.toList());
1477
+
1478
+            if (functionalDepts.isEmpty()) {
1479
+                return success(Collections.emptyList());
1480
+            }
1481
+
1482
+            // 构建返回结果
1483
+            List<FunctionalDeptPersonnelDistributionDto> result = new ArrayList<>();
1484
+
1485
+            for (SysDept functionalDept : functionalDepts) {
1486
+                Long deptId = functionalDept.getDeptId();
1487
+                String deptName = functionalDept.getDeptName();
1488
+
1489
+                // 获取该职能部门及其所有子部门的ID集合
1490
+                Set<Long> functionalSubDeptIds = getAllSubDeptIds(deptId, deptMap);
1491
+
1492
+                // 筛选属于该职能部门的人员(包括子部门)
1493
+                List<PersonnelNonCadreMonthlyAssessment> deptRecords = allList.stream()
1494
+                        .filter(item -> {
1495
+                            Long userDeptId = userDeptIdMap.get(item.getUserId());
1496
+                            return userDeptId != null && functionalSubDeptIds.contains(userDeptId);
1497
+                        })
1498
+                        .filter(item -> item.getAssessmentTeam() != null && !item.getAssessmentTeam().isEmpty())
1499
+                        .collect(Collectors.toList());
1500
+
1501
+                if (deptRecords.isEmpty()) {
1502
+                    continue;
1503
+                }
1504
+
1505
+                // 统计考核组人数
1506
+                int assessmentTeamCount = deptRecords.size();
1507
+
1508
+                // 统计实际待改进人数:考核结果为"待改进"且未被豁免
1509
+                long actualImprovementCount = deptRecords.stream()
1510
+                        .filter(item -> RESULT_IMPROVEMENT.equals(item.getAssessmentResult()))
1511
+                        .filter(item -> !EXEMPTION_YES.equals(item.getExemption()))
1512
+                        .count();
1513
+
1514
+                // 统计实际不称职人数:考核结果为"不称职"且未被豁免
1515
+                long actualIncompetentCount = deptRecords.stream()
1516
+                        .filter(item -> RESULT_INCOMPETENT.equals(item.getAssessmentResult()))
1517
+                        .filter(item -> !EXEMPTION_YES.equals(item.getExemption()))
1518
+                        .count();
1519
+
1520
+                // 构建DTO
1521
+                FunctionalDeptPersonnelDistributionDto dto = new FunctionalDeptPersonnelDistributionDto();
1522
+                dto.setDeptId(deptId);
1523
+                dto.setDeptName(deptName);
1524
+                dto.setAssessmentTeamCount(assessmentTeamCount);
1525
+                dto.setActualImprovementCount((int) actualImprovementCount);
1526
+                dto.setActualIncompetentCount((int) actualIncompetentCount);
1527
+
1528
+                result.add(dto);
1529
+            }
1530
+
1531
+            // 按考核组人数降序排序
1532
+            result.sort((a, b) -> b.getAssessmentTeamCount().compareTo(a.getAssessmentTeamCount()));
1533
+
1534
+            return success(result);
1535
+        } catch (Exception e) {
1536
+            logger.error("各职能部门人员分布统计异常", e);
1537
+            return error("统计失败:" + e.getMessage());
1538
+        }
1539
+    }
1540
+
1541
+    /**
1542
+     * 各职能考核人员分布(饼图数据)
1543
+     * 统计所有职能部门(is_functional_dept='1')的考核组人数及占比
1544
+     *
1545
+     * @param assessmentMonth 考核月份(格式:YYYYMM)
1546
+     * @return 各职能考核人员分布数据
1547
+     */
1548
+    @PreAuthorize("@ss.hasPermi('personnel:assessment:query')")
1549
+    @GetMapping("/functional-dept-distribution-pie")
1550
+    public AjaxResult getFunctionalDeptDistributionPie(@RequestParam String assessmentMonth) {
1551
+        try {
1552
+            List<PersonnelNonCadreMonthlyAssessment> allList = queryByMonth(assessmentMonth);
1553
+
1554
+            if (allList == null || allList.isEmpty()) {
1555
+                return success(Collections.emptyList());
1556
+            }
1557
+
1558
+            // 获取所有部门信息
1559
+            Map<Long, SysDept> deptMap = getDeptMap();
1560
+
1561
+            // 查询用户部门映射
1562
+            Set<Long> userIds = allList.stream()
1563
+                    .map(PersonnelNonCadreMonthlyAssessment::getUserId)
1564
+                    .filter(Objects::nonNull)
1565
+                    .collect(Collectors.toSet());
1566
+            Map<Long, Long> userDeptIdMap = buildUserDeptIdMap(userIds);
1567
+
1568
+            // 筛选所有职能部门(is_functional_dept='1')
1569
+            List<SysDept> functionalDepts = deptMap.values().stream()
1570
+                    .filter(dept -> "1".equals(dept.getIsFunctionalDept()))
1571
+                    .collect(Collectors.toList());
1572
+
1573
+            if (functionalDepts.isEmpty()) {
1574
+                return success(Collections.emptyList());
1575
+            }
1576
+
1577
+            // 统计总人数
1578
+            int totalCount = 0;
1579
+
1580
+            // 先统计各职能部门人数
1581
+            Map<Long, Integer> deptCountMap = new HashMap<>();
1582
+            Map<Long, String> deptNameMap = new HashMap<>();
1583
+            Map<Long, String> deptTeamMap = new HashMap<>();
1584
+
1585
+            for (SysDept functionalDept : functionalDepts) {
1586
+                Long deptId = functionalDept.getDeptId();
1587
+                String deptName = functionalDept.getDeptName();
1588
+
1589
+                // 获取该职能部门及其所有子部门的ID集合
1590
+                Set<Long> functionalSubDeptIds = getAllSubDeptIds(deptId, deptMap);
1591
+
1592
+                // 筛选属于该职能部门的人员(包括子部门)
1593
+                List<PersonnelNonCadreMonthlyAssessment> deptRecords = allList.stream()
1594
+                        .filter(item -> {
1595
+                            Long userDeptId = userDeptIdMap.get(item.getUserId());
1596
+                            return userDeptId != null && functionalSubDeptIds.contains(userDeptId);
1597
+                        })
1598
+                        .filter(item -> item.getAssessmentTeam() != null && !item.getAssessmentTeam().isEmpty())
1599
+                        .collect(Collectors.toList());
1600
+
1601
+                if (!deptRecords.isEmpty()) {
1602
+                    int count = deptRecords.size();
1603
+                    deptCountMap.put(deptId, count);
1604
+                    deptNameMap.put(deptId, deptName);
1605
+                    // 获取考核组名称(取第一个非空考核组)
1606
+                    String assessmentTeam = deptRecords.get(0).getAssessmentTeam();
1607
+                    deptTeamMap.put(deptId, assessmentTeam);
1608
+                    totalCount += count;
1609
+                }
1610
+            }
1611
+
1612
+            // 构建返回结果
1613
+            List<FunctionalDeptDistributionPieDto> result = new ArrayList<>();
1614
+            for (Map.Entry<Long, Integer> entry : deptCountMap.entrySet()) {
1615
+                Long deptId = entry.getKey();
1616
+                Integer count = entry.getValue();
1617
+
1618
+                FunctionalDeptDistributionPieDto dto = new FunctionalDeptDistributionPieDto();
1619
+                dto.setDeptId(deptId);
1620
+                dto.setDeptName(deptNameMap.get(deptId));
1621
+                dto.setAssessmentTeam(deptTeamMap.get(deptId));
1622
+                dto.setCount(count);
1623
+
1624
+                // 计算占比
1625
+                if (totalCount > 0) {
1626
+                    BigDecimal percentage = new BigDecimal(count)
1627
+                            .divide(new BigDecimal(totalCount), 4, BigDecimal.ROUND_HALF_UP)
1628
+                            .multiply(HUNDRED);
1629
+                    dto.setPercentage(percentage.setScale(1, BigDecimal.ROUND_HALF_UP));
1630
+                } else {
1631
+                    dto.setPercentage(BigDecimal.ZERO);
1632
+                }
1633
+
1634
+                result.add(dto);
1635
+            }
1636
+
1637
+            // 按人数降序排序
1638
+            result.sort((a, b) -> b.getCount().compareTo(a.getCount()));
1639
+
1640
+            return success(result);
1641
+        } catch (Exception e) {
1642
+            logger.error("各职能考核人员分布统计异常", e);
1643
+            return error("统计失败:" + e.getMessage());
1644
+        }
1645
+    }
1646
+
1647
+
1250 1648
 }

+ 76 - 0
airport-personnel/src/main/java/com/sundot/airport/personnel/dto/FunctionalDeptDistributionPieDto.java

@@ -0,0 +1,76 @@
1
+package com.sundot.airport.personnel.dto;
2
+
3
+import java.math.BigDecimal;
4
+
5
+/**
6
+ * 各职能考核人员分布DTO(饼图数据)
7
+ *
8
+ * @author wangxx
9
+ * @date 2026-05-11
10
+ */
11
+public class FunctionalDeptDistributionPieDto {
12
+    /**
13
+     * 部门ID
14
+     */
15
+    private Long deptId;
16
+
17
+    /**
18
+     * 部门名称
19
+     */
20
+    private String deptName;
21
+
22
+    /**
23
+     * 考核组名称(简称)
24
+     */
25
+    private String assessmentTeam;
26
+
27
+    /**
28
+     * 考核人数
29
+     */
30
+    private Integer count;
31
+
32
+    /**
33
+     * 占比(百分比)
34
+     */
35
+    private BigDecimal percentage;
36
+
37
+    public Long getDeptId() {
38
+        return deptId;
39
+    }
40
+
41
+    public void setDeptId(Long deptId) {
42
+        this.deptId = deptId;
43
+    }
44
+
45
+    public String getDeptName() {
46
+        return deptName;
47
+    }
48
+
49
+    public void setDeptName(String deptName) {
50
+        this.deptName = deptName;
51
+    }
52
+
53
+    public String getAssessmentTeam() {
54
+        return assessmentTeam;
55
+    }
56
+
57
+    public void setAssessmentTeam(String assessmentTeam) {
58
+        this.assessmentTeam = assessmentTeam;
59
+    }
60
+
61
+    public Integer getCount() {
62
+        return count;
63
+    }
64
+
65
+    public void setCount(Integer count) {
66
+        this.count = count;
67
+    }
68
+
69
+    public BigDecimal getPercentage() {
70
+        return percentage;
71
+    }
72
+
73
+    public void setPercentage(BigDecimal percentage) {
74
+        this.percentage = percentage;
75
+    }
76
+}

+ 74 - 0
airport-personnel/src/main/java/com/sundot/airport/personnel/dto/FunctionalDeptPersonnelDistributionDto.java

@@ -0,0 +1,74 @@
1
+package com.sundot.airport.personnel.dto;
2
+
3
+/**
4
+ * 各职能部门待改进/不称职人员分布DTO
5
+ *
6
+ * @author wangxx
7
+ * @date 2026-05-11
8
+ */
9
+public class FunctionalDeptPersonnelDistributionDto {
10
+    /**
11
+     * 部门ID
12
+     */
13
+    private Long deptId;
14
+
15
+    /**
16
+     * 职能部门名称
17
+     */
18
+    private String deptName;
19
+
20
+    /**
21
+     * 考核组人数
22
+     */
23
+    private Integer assessmentTeamCount;
24
+
25
+    /**
26
+     * 实际待改进人数
27
+     */
28
+    private Integer actualImprovementCount;
29
+
30
+    /**
31
+     * 实际不称职人数
32
+     */
33
+    private Integer actualIncompetentCount;
34
+
35
+    public Long getDeptId() {
36
+        return deptId;
37
+    }
38
+
39
+    public void setDeptId(Long deptId) {
40
+        this.deptId = deptId;
41
+    }
42
+
43
+    public String getDeptName() {
44
+        return deptName;
45
+    }
46
+
47
+    public void setDeptName(String deptName) {
48
+        this.deptName = deptName;
49
+    }
50
+
51
+    public Integer getAssessmentTeamCount() {
52
+        return assessmentTeamCount;
53
+    }
54
+
55
+    public void setAssessmentTeamCount(Integer assessmentTeamCount) {
56
+        this.assessmentTeamCount = assessmentTeamCount;
57
+    }
58
+
59
+    public Integer getActualImprovementCount() {
60
+        return actualImprovementCount;
61
+    }
62
+
63
+    public void setActualImprovementCount(Integer actualImprovementCount) {
64
+        this.actualImprovementCount = actualImprovementCount;
65
+    }
66
+
67
+    public Integer getActualIncompetentCount() {
68
+        return actualIncompetentCount;
69
+    }
70
+
71
+    public void setActualIncompetentCount(Integer actualIncompetentCount) {
72
+        this.actualIncompetentCount = actualIncompetentCount;
73
+    }
74
+}

+ 172 - 0
airport-personnel/src/main/java/com/sundot/airport/personnel/dto/FunctionalDeptSummaryDto.java

@@ -0,0 +1,172 @@
1
+package com.sundot.airport.personnel.dto;
2
+
3
+import java.util.List;
4
+
5
+/**
6
+ * 各职能大队汇总DTO
7
+ *
8
+ * @author wangxx
9
+ * @date 2026-05-11
10
+ */
11
+public class FunctionalDeptSummaryDto {
12
+    /**
13
+     * 部门ID
14
+     */
15
+    private Long deptId;
16
+
17
+    /**
18
+     * 职能部门名称
19
+     */
20
+    private String deptName;
21
+
22
+    /**
23
+     * 考核组列表
24
+     */
25
+    private List<FunctionalTeamStatisticsDto> assessmentTeams;
26
+
27
+    /**
28
+     * 考核组统计数据
29
+     */
30
+    public static class FunctionalTeamStatisticsDto {
31
+        /**
32
+         * 考核组名称
33
+         */
34
+        private String assessmentTeam;
35
+
36
+        /**
37
+         * 考核组人数
38
+         */
39
+        private Integer assessmentTeamCount;
40
+
41
+        /**
42
+         * 测算待改进人数
43
+         */
44
+        private Integer estimatedImprovementCount;
45
+
46
+        /**
47
+         * 待改进总人数
48
+         */
49
+        private Integer improvementTotalCount;
50
+
51
+        /**
52
+         * 待改进豁免人数
53
+         */
54
+        private Integer improvementExemptedCount;
55
+
56
+        /**
57
+         * 实际待改进人数
58
+         */
59
+        private Integer actualImprovementCount;
60
+
61
+        /**
62
+         * 不称职总人数
63
+         */
64
+        private Integer incompetentTotalCount;
65
+
66
+        /**
67
+         * 不称职豁免人数
68
+         */
69
+        private Integer incompetentExemptedCount;
70
+
71
+        /**
72
+         * 实际不称职人数
73
+         */
74
+        private Integer actualIncompetentCount;
75
+
76
+        public String getAssessmentTeam() {
77
+            return assessmentTeam;
78
+        }
79
+
80
+        public void setAssessmentTeam(String assessmentTeam) {
81
+            this.assessmentTeam = assessmentTeam;
82
+        }
83
+
84
+        public Integer getAssessmentTeamCount() {
85
+            return assessmentTeamCount;
86
+        }
87
+
88
+        public void setAssessmentTeamCount(Integer assessmentTeamCount) {
89
+            this.assessmentTeamCount = assessmentTeamCount;
90
+        }
91
+
92
+        public Integer getEstimatedImprovementCount() {
93
+            return estimatedImprovementCount;
94
+        }
95
+
96
+        public void setEstimatedImprovementCount(Integer estimatedImprovementCount) {
97
+            this.estimatedImprovementCount = estimatedImprovementCount;
98
+        }
99
+
100
+        public Integer getImprovementTotalCount() {
101
+            return improvementTotalCount;
102
+        }
103
+
104
+        public void setImprovementTotalCount(Integer improvementTotalCount) {
105
+            this.improvementTotalCount = improvementTotalCount;
106
+        }
107
+
108
+        public Integer getImprovementExemptedCount() {
109
+            return improvementExemptedCount;
110
+        }
111
+
112
+        public void setImprovementExemptedCount(Integer improvementExemptedCount) {
113
+            this.improvementExemptedCount = improvementExemptedCount;
114
+        }
115
+
116
+        public Integer getActualImprovementCount() {
117
+            return actualImprovementCount;
118
+        }
119
+
120
+        public void setActualImprovementCount(Integer actualImprovementCount) {
121
+            this.actualImprovementCount = actualImprovementCount;
122
+        }
123
+
124
+        public Integer getIncompetentTotalCount() {
125
+            return incompetentTotalCount;
126
+        }
127
+
128
+        public void setIncompetentTotalCount(Integer incompetentTotalCount) {
129
+            this.incompetentTotalCount = incompetentTotalCount;
130
+        }
131
+
132
+        public Integer getIncompetentExemptedCount() {
133
+            return incompetentExemptedCount;
134
+        }
135
+
136
+        public void setIncompetentExemptedCount(Integer incompetentExemptedCount) {
137
+            this.incompetentExemptedCount = incompetentExemptedCount;
138
+        }
139
+
140
+        public Integer getActualIncompetentCount() {
141
+            return actualIncompetentCount;
142
+        }
143
+
144
+        public void setActualIncompetentCount(Integer actualIncompetentCount) {
145
+            this.actualIncompetentCount = actualIncompetentCount;
146
+        }
147
+    }
148
+
149
+    public Long getDeptId() {
150
+        return deptId;
151
+    }
152
+
153
+    public void setDeptId(Long deptId) {
154
+        this.deptId = deptId;
155
+    }
156
+
157
+    public String getDeptName() {
158
+        return deptName;
159
+    }
160
+
161
+    public void setDeptName(String deptName) {
162
+        this.deptName = deptName;
163
+    }
164
+
165
+    public List<FunctionalTeamStatisticsDto> getAssessmentTeams() {
166
+        return assessmentTeams;
167
+    }
168
+
169
+    public void setAssessmentTeams(List<FunctionalTeamStatisticsDto> assessmentTeams) {
170
+        this.assessmentTeams = assessmentTeams;
171
+    }
172
+}