Ver Fonte

feat(game-event): 添加项目统计功能

- 在GameEventProjectVo中新增totalParticipants、completedParticipants、incompleteParticipants字段
- 创建GameProjectStatsVo用于项目成绩统计
- 在GameEventProjectServiceImpl中注入GameScoreMapper并添加calculateProjectStats方法
- 实现批量计算项目统计数据(参赛总数、完赛数、未完赛数)
- 优化refereeGroup判断逻辑使用isEmpty()方法
- 移动GameEvent查询到循环外部提高性能
- 添加selectStatsByProjectIds数据库查询方法统计项目参赛和完赛情况
zhou há 8 horas atrás
pai
commit
f06c67dcfb

+ 14 - 0
ruoyi-modules/ruoyi-game-event/src/main/java/org/dromara/system/domain/vo/GameEventProjectVo.java

@@ -185,5 +185,19 @@ public class GameEventProjectVo implements Serializable {
     @ExcelProperty(value = "备注")
     private String remark;
 
+    /**
+     * 参赛总人/队数
+     */
+    private Integer totalParticipants;
+
+    /**
+     * 完赛人/队数
+     */
+    private Integer completedParticipants;
+
+    /**
+     * 未完赛人/队数
+     */
+    private Integer incompleteParticipants;
 
 }

+ 18 - 0
ruoyi-modules/ruoyi-game-event/src/main/java/org/dromara/system/domain/vo/GameProjectStatsVo.java

@@ -0,0 +1,18 @@
+package org.dromara.system.domain.vo;
+
+import lombok.Data;
+import java.io.Serializable;
+
+/**
+ * 项目成绩统计对象
+ */
+@Data
+public class GameProjectStatsVo implements Serializable {
+    private Long projectId;
+    /** 运动员数量 */
+    private Integer athleteCount;
+    /** 队伍数量 */
+    private Integer teamCount;
+    /** 完赛数量 */
+    private Integer completedCount;
+}

+ 6 - 2
ruoyi-modules/ruoyi-game-event/src/main/java/org/dromara/system/mapper/GameScoreMapper.java

@@ -3,14 +3,13 @@ package org.dromara.system.mapper;
 import org.apache.ibatis.annotations.Mapper;
 import org.apache.ibatis.annotations.Param;
 import org.apache.ibatis.annotations.Select;
+import org.dromara.system.domain.vo.GameProjectStatsVo;
 import org.dromara.system.domain.GameScore;
 import org.dromara.system.domain.vo.GameScoreVo;
 import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
 
-import java.math.BigDecimal;
 import java.util.Collection;
 import java.util.List;
-import java.util.Map;
 
 /**
  * 成绩Mapper接口
@@ -21,6 +20,11 @@ import java.util.Map;
 @Mapper
 public interface GameScoreMapper extends BaseMapperPlus<GameScore, GameScoreVo> {
 
+    /**
+     * 批量统计项目的参赛和完赛情况
+     */
+    List<GameProjectStatsVo> selectStatsByProjectIds(@Param("projectIds") List<Long> projectIds);
+
     /**
      * 获取赛事下每个项目成绩最高的前三名
      * @param eventId

+ 54 - 5
ruoyi-modules/ruoyi-game-event/src/main/java/org/dromara/system/service/impl/GameEventProjectServiceImpl.java

@@ -27,6 +27,7 @@ import org.springframework.stereotype.Service;
 import org.dromara.system.domain.bo.GameEventProjectBo;
 import org.dromara.system.domain.bo.GameRefereeBo;
 import org.dromara.system.domain.vo.GameEventProjectVo;
+import org.dromara.system.domain.vo.GameProjectStatsVo;
 import org.dromara.system.service.IGameEventProjectService;
 import org.springframework.transaction.annotation.Transactional;
 
@@ -50,6 +51,7 @@ public class GameEventProjectServiceImpl implements IGameEventProjectService {
     private final GameTeamMapper gameTeamMapper;
     private final GameAthleteMapper gameAthleteMapper;
     private final GameEventGroupMapper gameEventGroupMapper;
+    private final GameScoreMapper gameScoreMapper;
 
     @Autowired
     @Lazy
@@ -61,13 +63,14 @@ public class GameEventProjectServiceImpl implements IGameEventProjectService {
 
     public GameEventProjectServiceImpl(GameEventProjectMapper baseMapper, GameEventMapper gameEventMapper,
         ISysDictTypeService sysDictTypeService, GameTeamMapper gameTeamMapper, GameAthleteMapper gameAthleteMapper,
-        GameEventGroupMapper gameEventGroupMapper) {
+        GameEventGroupMapper gameEventGroupMapper, GameScoreMapper gameScoreMapper) {
         this.baseMapper = baseMapper;
         this.gameEventMapper = gameEventMapper;
         this.sysDictTypeService = sysDictTypeService;
         this.gameTeamMapper = gameTeamMapper;
         this.gameAthleteMapper = gameAthleteMapper;
         this.gameEventGroupMapper = gameEventGroupMapper;
+        this.gameScoreMapper = gameScoreMapper;
     }
 
     /**
@@ -82,7 +85,7 @@ public class GameEventProjectServiceImpl implements IGameEventProjectService {
         if (vo == null) {
             return null;
         }
-        if (vo.getRefereeGroup() != null && !"".equals(vo.getRefereeGroup())){
+        if (vo.getRefereeGroup() != null && !vo.getRefereeGroup().isEmpty()){
             vo.setRefereeGroups(JSONUtil.toList(vo.getRefereeGroup(), Long.class));
         }else{
             vo.setRefereeGroups(new ArrayList<>());
@@ -110,14 +113,12 @@ public class GameEventProjectServiceImpl implements IGameEventProjectService {
         LambdaQueryWrapper<GameEventProject> lqw = buildQueryWrapper(bo);
 //        Page<GameEventProjectVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
         Page<GameEventProjectVo> result = baseMapper.selectPageEventProjectList(pageQuery.build(), lqw);
-
-        // 使用 forEach 直接修改原对象
+        GameEvent gameEvent = gameEventMapper.selectById(bo.getEventId());
         result.getRecords()
             .forEach(vo -> {
                 Optional.ofNullable(vo.getEventId())
                     .filter(ObjectUtil::isNotEmpty)
                     .ifPresent(eventId -> {
-                        GameEvent gameEvent = gameEventMapper.selectById(eventId);
                         if (gameEvent != null) {
                             vo.setEventName(gameEvent.getEventName());
                         }
@@ -131,9 +132,57 @@ public class GameEventProjectServiceImpl implements IGameEventProjectService {
                     });
             });
 
+        // 批量计算统计数据
+        calculateProjectStats(result.getRecords());
+
         return TableDataInfo.build(result);
     }
 
+    /**
+     * 批量计算项目的统计数据(参赛总数、完赛数、未完赛数)
+     */
+    private void calculateProjectStats(List<GameEventProjectVo> projectList) {
+        if (CollectionUtils.isEmpty(projectList)) {
+            return;
+        }
+
+        List<Long> projectIds = projectList.stream()
+            .map(GameEventProjectVo::getProjectId)
+            .filter(Objects::nonNull)
+            .collect(Collectors.toList());
+
+        if (projectIds.isEmpty()) {
+            return;
+        }
+
+        // 数据库聚合查询统计数据
+        List<GameProjectStatsVo> statsList = gameScoreMapper.selectStatsByProjectIds(projectIds);
+
+        // 转换为 Map 方便查找
+        Map<Long, GameProjectStatsVo> statsMap = statsList.stream()
+            .collect(Collectors.toMap(GameProjectStatsVo::getProjectId, s -> s));
+
+        // 回填统计数据
+        projectList.forEach(vo -> {
+            GameProjectStatsVo stats = statsMap.get(vo.getProjectId());
+            if (stats != null) {
+                // 根据归类决定总数
+                if ("0".equals(vo.getClassification())) {
+                    // 个人项目
+                    vo.setTotalParticipants(stats.getAthleteCount());
+                } else {
+                    // 团体项目
+                    vo.setTotalParticipants(stats.getTeamCount());
+                }
+                vo.setCompletedParticipants(stats.getCompletedCount());
+            } else {
+                vo.setTotalParticipants(0);
+                vo.setCompletedParticipants(0);
+            }
+            vo.setIncompleteParticipants(vo.getTotalParticipants() - vo.getCompletedParticipants());
+        });
+    }
+
     @Override
     public TableDataInfo<GameEventProjectVo> queryAllProjectList(GameEventProjectBo bo, PageQuery pageQuery) {
         // 获取默认赛事ID

+ 18 - 0
ruoyi-modules/ruoyi-game-event/src/main/resources/mapper/system/GameScoreMapper.xml

@@ -4,6 +4,24 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
 "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
 <mapper namespace="org.dromara.system.mapper.GameScoreMapper">
 
+    <!--- 根据项目Id统计该项目参赛运动员和参赛队伍的数量以及完/未完赛数-->
+    <select id="selectStatsByProjectIds" resultType="org.dromara.system.domain.vo.GameProjectStatsVo">
+        SELECT
+            project_id as projectId,
+            COUNT(DISTINCT athlete_id) as athleteCount,
+            COUNT(DISTINCT team_id) as teamCount,
+            SUM(CASE WHEN (individual_performance > 0) OR (team_performance > 0) THEN 1 ELSE 0 END) as completedCount
+        FROM game_score
+        WHERE del_flag = '0'
+        <if test="projectIds != null and projectIds.size > 0">
+            AND project_id IN
+            <foreach item="projectId" collection="projectIds" separator="," open="(" close=")">
+                #{projectId}
+            </foreach>
+        </if>
+        GROUP BY project_id
+    </select>
+
     <select id="listAppScoreByEventIdGroupProjectId" resultType="org.dromara.system.domain.GameScore">
         SELECT *
         FROM (