Преглед изворни кода

部门画像--能里画像--雷达图代码修改

wangxx пре 3 недеља
родитељ
комит
1d2288c0cb

+ 19 - 2
airport-ledger/src/main/java/com/sundot/airport/ledger/service/impl/DeptPortraitServiceImpl.java

@@ -376,14 +376,14 @@ public class DeptPortraitServiceImpl implements IDeptPortraitService {
376 376
     public List<StationTeamStatsDTO> getStationTeamStats(DeptPortraitQueryDTO query) {
377 377
         // 1. 验证是站级别
378 378
         SysDept station = sysDeptMapper.selectDeptById(query.getDeptId());
379
-        if (station == null || !"STATION".equals(station.getDeptType())) {
379
+        if (station == null) {
380 380
             throw new RuntimeException("请选择站级别部门");
381 381
         }
382 382
 
383 383
         // 2. 查询站下所有部门(BRIGADE)
384 384
         SysDept deptQuery = new SysDept();
385 385
         deptQuery.setParentId(query.getDeptId());
386
-        deptQuery.setDeptType(DeptTypeEnum.BRIGADE.getCode());
386
+        deptQuery.setDeptType(getChildDeptType(station.getDeptType()));
387 387
         deptQuery.setStatus("0");
388 388
         List<SysDept> brigades = sysDeptMapper.selectDeptList(deptQuery);
389 389
 
@@ -403,6 +403,23 @@ public class DeptPortraitServiceImpl implements IDeptPortraitService {
403 403
         return result;
404 404
     }
405 405
 
406
+    private String getChildDeptType(String deptType) {
407
+        if (deptType == null || deptType.isEmpty()) {
408
+            return null;
409
+        }
410
+
411
+        switch (deptType) {
412
+            case "STATION":
413
+                return DeptTypeEnum.BRIGADE.getCode();
414
+            case "BRIGADE":
415
+                return DeptTypeEnum.MANAGER.getCode();
416
+            case "MANAGER":
417
+                return DeptTypeEnum.TEAMS.getCode();
418
+            default:
419
+                return null;
420
+        }
421
+    }
422
+
406 423
     @Override
407 424
     public StationTeamStatsDTO getTeamStats(DeptPortraitQueryDTO query) {
408 425
         SysDept sysDept = sysDeptMapper.selectDeptById(query.getDeptId());

+ 88 - 23
airport-ledger/src/main/java/com/sundot/airport/ledger/service/impl/GroupPortraitServiceImpl.java

@@ -109,10 +109,11 @@ public class GroupPortraitServiceImpl implements IGroupPortraitService {
109 109
         dims.sort(Comparator.comparing(d -> d.getSortOrder() == null ? 999 : d.getSortOrder()));
110 110
 
111 111
         List<GroupPortraitDTO.DimensionScore> result = new ArrayList<>();
112
-
112
+        String beginTime = query.getStartDate()+" 00:00:00";
113
+        String endTime = query.getEndDate()+" 23:59:59";
113 114
         for (ScoreDimension dim : dims) {
114 115
             // 3. 通过dimRelationship找到下级维度,计算下级平均值
115
-            BigDecimal lowerLevelAverage = calculateLowerLevelAverage(dim, query.getStartDate(), query.getEndDate());
116
+            BigDecimal lowerLevelAverage = calculateLowerLevelAverage(dim,beginTime , endTime,dept.getDeptId());
116 117
             
117 118
             // 4. 获取基础分(如果下级有值就不用基础分)
118 119
             BigDecimal baseScore = dim.getBaseScore() != null ? dim.getBaseScore() : BigDecimal.ZERO;
@@ -123,8 +124,8 @@ public class GroupPortraitServiceImpl implements IGroupPortraitService {
123 124
                     : baseScore;
124 125
 
125 126
             // 6. 计算当前层级特有加减分
126
-            Map<String, Object> specialScores = calculateSpecialScores(dim.getId(), query.getDeptId(), 
127
-                    query.getStartDate(), query.getEndDate(),org);
127
+            Map<String, Object> specialScores = calculateSpecialScores(dim.getId(), query.getDeptId(),
128
+                    beginTime, endTime,org);
128 129
             BigDecimal addScore = (BigDecimal) specialScores.getOrDefault("add", BigDecimal.ZERO);
129 130
             BigDecimal subtractScore = (BigDecimal) specialScores.getOrDefault("subtract", BigDecimal.ZERO);
130 131
             BigDecimal specialTotal = addScore.subtract(subtractScore);
@@ -194,15 +195,15 @@ public class GroupPortraitServiceImpl implements IGroupPortraitService {
194 195
     }
195 196
 
196 197
     /**
197
-     * 计算下级维度平均值(递归查找)
198
+     * 计算下级维度平均值
198 199
      * 层级关系:部门(DEPT) → 队/班组(TEAM) → 小组(GROUP) → 人员(PERSON)
199 200
      * 递进逻辑:
200
-     * - org=DEPT → 查询org=TEAM的维度 → 继续递归找org=GROUP → 继续递归找org=PERSON
201
-     * - org=TEAM → 查询org=GROUP的维度 → 继续递归找org=PERSON
201
+     * - org=DEPT → 获取子班组列表 → 计算每个班组的最终分数 → 求平均值
202
+     * - org=TEAM → 获取子小组列表 → 计算每个小组的最终分数 → 求平均值
202 203
      * - org=GROUP → 查询org=PERSON的维度 → 计算人员事件平均
203 204
      * - org=PERSON → 最底层,直接返回0
204 205
      */
205
-    private BigDecimal calculateLowerLevelAverage(ScoreDimension currentDim, String beginTime, String endTime) {
206
+    private BigDecimal calculateLowerLevelAverage(ScoreDimension currentDim, String beginTime, String endTime, Long deptId) {
206 207
         String dimRelationship = currentDim.getDimRelationship();
207 208
         String currentOrg = currentDim.getOrg();
208 209
         
@@ -217,7 +218,6 @@ public class GroupPortraitServiceImpl implements IGroupPortraitService {
217 218
             return BigDecimal.ZERO;
218 219
         }
219 220
 
220
-        
221 221
         // 3. 查询下一级维度(通过dimRelationship匹配)
222 222
         ScoreDimension query = new ScoreDimension();
223 223
         query.setDimRelationship(dimRelationship);
@@ -236,19 +236,78 @@ public class GroupPortraitServiceImpl implements IGroupPortraitService {
236 236
         // 4. 根据下一级的org决定如何处理
237 237
         if (ScoreLevelEnum.PERSON.getCode().equals(lowerOrg)) {
238 238
             // 下一级是人员维度,计算人员事件平均值
239
-            return calculatePersonDimensionAverage(lowerDim, beginTime, endTime);
239
+            return calculatePersonDimensionAverage(lowerDim, beginTime, endTime, deptId);
240 240
         } else {
241
-            // 下一级是组织维度(TEAM或GROUP),需要继续递归查找更下一级
242
-            // 例如:部门(DEPT)找队(TEAM),队(TEAM)还要继续找小组(GROUP)
243
-            return calculateLowerLevelAverage(lowerDim, beginTime, endTime);
241
+            // 下一级是 TEAM 或 GROUP 层级,需要获取子部门并计算每个子部门的最终分数
242
+            return calculateChildDeptAverage(lowerDim, beginTime, endTime, deptId);
244 243
         }
245 244
     }
246 245
 
247 246
     /**
247
+     * 计算子部门的平均分数
248
+     * 对于 TEAM 和 GROUP 层级,需要获取子部门列表,计算每个子部门的最终分数,然后求平均
249
+     */
250
+    private BigDecimal calculateChildDeptAverage(ScoreDimension lowerDim, String beginTime, String endTime, Long deptId) {
251
+        // 获取子部门列表
252
+        List<SysDept> childDepts = sysDeptMapper.selectChildrenDeptById(deptId);
253
+        
254
+        if (childDepts == null || childDepts.isEmpty()) {
255
+            log.info("部门 {} 没有子部门", deptId);
256
+            return BigDecimal.ZERO;
257
+        }
258
+
259
+        BigDecimal totalScore = BigDecimal.ZERO;
260
+        int count = 0;
261
+
262
+        for (SysDept childDept : childDepts) {
263
+            // 计算该子部门在当前维度下的最终分数
264
+            BigDecimal childScore = calculateChildDeptDimensionScore(lowerDim, beginTime, endTime, childDept.getDeptId());
265
+            if (childScore.compareTo(BigDecimal.ZERO) > 0) {
266
+                totalScore = totalScore.add(childScore);
267
+                count++;
268
+            }
269
+        }
270
+
271
+        if (count == 0) {
272
+            return BigDecimal.ZERO;
273
+        }
274
+
275
+        return totalScore.divide(BigDecimal.valueOf(count), 2, RoundingMode.HALF_UP);
276
+    }
277
+
278
+    /**
279
+     * 计算单个子部门在指定维度下的最终分数
280
+     * 最终分数 = 下级平均值(或基础分) + 特有加减分
281
+     */
282
+    private BigDecimal calculateChildDeptDimensionScore(ScoreDimension dim, String beginTime, String endTime, Long deptId) {
283
+        String currentOrg = dim.getOrg();
284
+        
285
+        // 1. 递归计算下级平均值
286
+        BigDecimal lowerLevelAverage = calculateLowerLevelAverage(dim, beginTime, endTime, deptId);
287
+        
288
+        // 2. 获取基础分(如果下级有值就不用基础分)
289
+        BigDecimal baseScore = dim.getBaseScore() != null ? dim.getBaseScore() : BigDecimal.ZERO;
290
+        
291
+        // 3. 决定使用下级平均值还是基础分
292
+        BigDecimal averageScore = lowerLevelAverage.compareTo(BigDecimal.ZERO) > 0 
293
+                ? lowerLevelAverage 
294
+                : baseScore;
295
+
296
+        // 4. 计算当前层级特有加减分
297
+        Map<String, Object> specialScores = calculateSpecialScores(dim.getId(), deptId, beginTime, endTime, currentOrg);
298
+        BigDecimal addScore = (BigDecimal) specialScores.getOrDefault("add", BigDecimal.ZERO);
299
+        BigDecimal subtractScore = (BigDecimal) specialScores.getOrDefault("subtract", BigDecimal.ZERO);
300
+        BigDecimal specialTotal = addScore.subtract(subtractScore);
301
+
302
+        // 5. 最终分值 = 下级平均值(或基础分) + 特有合计
303
+        return averageScore.add(specialTotal);
304
+    }
305
+
306
+    /**
248 307
      * 计算人员维度平均值
249 308
      * 最底层(org=4),查询该维度下的所有人员事件,计算平均分数
250 309
      */
251
-    private BigDecimal calculatePersonDimensionAverage(ScoreDimension dimension, String beginTime, String endTime) {
310
+    private BigDecimal calculatePersonDimensionAverage(ScoreDimension dimension, String beginTime, String endTime,Long deptId) {
252 311
 
253 312
         // 查询该维度下的所有事件
254 313
         ScoreEvent eventQuery = new ScoreEvent();
@@ -259,11 +318,13 @@ public class GroupPortraitServiceImpl implements IGroupPortraitService {
259 318
         if (endTime != null && !endTime.isEmpty()) {
260 319
             eventQuery.getParams().put("endTime", endTime);
261 320
         }
321
+        eventQuery.setGroupId(deptId);
262 322
         List<ScoreEvent> events = scoreEventMapper.selectList(eventQuery);
263 323
 
324
+        BigDecimal base = dimension.getBaseScore() != null ? dimension.getBaseScore() : BigDecimal.valueOf(80);
264 325
         if (events == null || events.isEmpty()) {
265 326
             log.info("人员维度无事件数据");
266
-            return BigDecimal.ZERO;
327
+            return base;
267 328
         }
268 329
 
269 330
         // 按人员分组统计总分
@@ -286,14 +347,12 @@ public class GroupPortraitServiceImpl implements IGroupPortraitService {
286 347
         if (personScores.isEmpty()) {
287 348
             return BigDecimal.ZERO;
288 349
         }
350
+        BigDecimal bigDecimal = BigDecimal.valueOf(personScores.size());
289 351
         BigDecimal sum = personScores.values().stream().reduce(BigDecimal.ZERO, BigDecimal::add);
290 352
 
291
-        BigDecimal base = dimension.getBaseScore() != null ? dimension.getBaseScore() : BigDecimal.valueOf(80);
292
-        BigDecimal dimScore = base.add(sum);
293
-        BigDecimal weight = dimension.getWeight() != null ? dimension.getWeight() : BigDecimal.ZERO;
294
-        BigDecimal contribution = dimScore.multiply(weight)
295
-                .divide(BigDecimal.valueOf(100), 2, RoundingMode.HALF_UP);
296
-        return contribution;
353
+
354
+        BigDecimal dimScore = base.multiply(bigDecimal).add(sum);
355
+        return dimScore.divide(bigDecimal, 2, RoundingMode.HALF_UP);
297 356
     }
298 357
 
299 358
     /**
@@ -328,7 +387,13 @@ public class GroupPortraitServiceImpl implements IGroupPortraitService {
328 387
         // 查询该部门在该维度的特有事件(根据org参数筛选)
329 388
         ScoreEvent eventQuery = new ScoreEvent();
330 389
         eventQuery.setDimensionId(dimensionId);
331
-        eventQuery.setDeptId(deptId);
390
+        if(ScoreLevelEnum.GROUP.getCode().equals(org)){
391
+            eventQuery.setGroupId(deptId);
392
+        }else if(ScoreLevelEnum.TEAM.getCode().equals(org)){
393
+            eventQuery.setTeamId(deptId);
394
+        }else if(ScoreLevelEnum.DEPT.getCode().equals(org)){
395
+            eventQuery.setDeptId(deptId);
396
+        }
332 397
         eventQuery.setOrg(org); // 使用传入的org参数
333 398
         if (beginTime != null && !beginTime.isEmpty()) {
334 399
             eventQuery.getParams().put("beginTime", beginTime);
@@ -411,4 +476,4 @@ public class GroupPortraitServiceImpl implements IGroupPortraitService {
411 476
                 .reduce(BigDecimal.ZERO, BigDecimal::add);
412 477
         return total.setScale(2, RoundingMode.HALF_UP);
413 478
     }
414
-}
479
+}

+ 1 - 0
airport-ledger/src/main/resources/mapper/ledger/ScoreDimensionMapper.xml

@@ -32,6 +32,7 @@
32 32
         <if test="name != null and name != ''">AND name LIKE CONCAT('%', #{name}, '%')</if>
33 33
         <if test="status != null and status != ''">AND status = #{status}</if>
34 34
         <if test="org != null and org != ''">AND org = #{org}</if>
35
+        <if test="dimRelationship != null and dimRelationship != ''">AND dim_relationship = #{dimRelationship}</if>
35 36
         ORDER BY sort_order ASC, id ASC
36 37
     </select>
37 38