3 Commits 46fa28eac2 ... 960edec204

Author SHA1 Message Date
  wenkai 960edec204 feat:增加字体 6 days ago
  wenkai 72ec77637a Merge branch 'dev' into wk-dev-8-13 6 days ago
  zhou bf3b1d8375 feat(game-event): 优化数据结构和功能 6 days ago
24 changed files with 814 additions and 60 deletions
  1. 52 0
      ruoyi-modules/ruoyi-game-event/src/main/java/org/dromara/system/controller/GameScoreController.java
  2. 2 2
      ruoyi-modules/ruoyi-game-event/src/main/java/org/dromara/system/domain/GameEventProject.java
  3. 9 4
      ruoyi-modules/ruoyi-game-event/src/main/java/org/dromara/system/domain/GameScore.java
  4. 3 5
      ruoyi-modules/ruoyi-game-event/src/main/java/org/dromara/system/domain/bo/GameEventProjectBo.java
  5. 8 7
      ruoyi-modules/ruoyi-game-event/src/main/java/org/dromara/system/domain/bo/GameScoreBo.java
  6. 3 3
      ruoyi-modules/ruoyi-game-event/src/main/java/org/dromara/system/domain/vo/AthleteScoreVo.java
  7. 2 1
      ruoyi-modules/ruoyi-game-event/src/main/java/org/dromara/system/domain/vo/GameAthleteVo.java
  8. 6 6
      ruoyi-modules/ruoyi-game-event/src/main/java/org/dromara/system/domain/vo/GameEventGroupVo.java
  9. 8 6
      ruoyi-modules/ruoyi-game-event/src/main/java/org/dromara/system/domain/vo/GameEventProjectVo.java
  10. 6 4
      ruoyi-modules/ruoyi-game-event/src/main/java/org/dromara/system/domain/vo/GameScoreVo.java
  11. 8 0
      ruoyi-modules/ruoyi-game-event/src/main/java/org/dromara/system/mapper/GameScoreMapper.java
  12. 9 0
      ruoyi-modules/ruoyi-game-event/src/main/java/org/dromara/system/service/IGameAthleteService.java
  13. 34 0
      ruoyi-modules/ruoyi-game-event/src/main/java/org/dromara/system/service/IGameScoreService.java
  14. 55 2
      ruoyi-modules/ruoyi-game-event/src/main/java/org/dromara/system/service/impl/GameAthleteServiceImpl.java
  15. 1 1
      ruoyi-modules/ruoyi-game-event/src/main/java/org/dromara/system/service/impl/GameEventProjectServiceImpl.java
  16. 24 13
      ruoyi-modules/ruoyi-game-event/src/main/java/org/dromara/system/service/impl/GameEventServiceImpl.java
  17. 560 0
      ruoyi-modules/ruoyi-game-event/src/main/java/org/dromara/system/service/impl/GameScoreServiceImpl.java
  18. 4 0
      ruoyi-modules/ruoyi-game-event/src/main/java/org/dromara/system/service/impl/GameTeamServiceImpl.java
  19. BIN
      ruoyi-modules/ruoyi-game-event/src/main/resources/fonts/msyh.ttc
  20. BIN
      ruoyi-modules/ruoyi-game-event/src/main/resources/fonts/simsun.ttc
  21. BIN
      ruoyi-modules/ruoyi-game-event/src/main/resources/fonts/simsun.ttf
  22. BIN
      ruoyi-modules/ruoyi-game-event/src/main/resources/fonts/yahei.ttf
  23. 6 0
      ruoyi-modules/ruoyi-game-event/src/main/resources/mapper/system/GameScoreMapper.xml
  24. 14 6
      本周改动.md

+ 52 - 0
ruoyi-modules/ruoyi-game-event/src/main/java/org/dromara/system/controller/GameScoreController.java

@@ -1,6 +1,7 @@
 package org.dromara.system.controller;
 
 import java.util.List;
+import java.util.Map;
 
 import lombok.RequiredArgsConstructor;
 import jakarta.servlet.http.HttpServletResponse;
@@ -102,4 +103,55 @@ public class GameScoreController extends BaseController {
                           @PathVariable Long[] scoreIds) {
         return toAjax(gameScoreService.deleteWithValidByIds(List.of(scoreIds), true));
     }
+
+    /**
+     * 根据运动员ID和项目ID查询成绩
+     */
+    @SaCheckPermission("system:gameScore:query")
+    @GetMapping("/getScoreByAthleteIdAndProjectId")
+    public R<GameScoreVo> getScoreByAthleteIdAndProjectId(@RequestParam("athleteId") Long athleteId, @RequestParam("projectId") Long projectId) {
+        return R.ok(gameScoreService.getScoreByAthleteIdAndProjectId(athleteId, projectId));
+    }
+
+    /**
+     * 获取项目成绩综合数据(包含运动员/队伍信息)
+     */
+    @SaCheckPermission("system:gameScore:list")
+    @GetMapping("/getProjectScoreData")
+    public TableDataInfo<Map<String, Object>> getProjectScoreData(
+            @RequestParam("eventId") Long eventId,
+            @RequestParam("projectId") Long projectId,
+            @RequestParam("classification") String classification,
+            @RequestParam(value = "searchValue", required = false) String searchValue,
+            @RequestParam(value = "pageNum", defaultValue = "1") Integer pageNum,
+            @RequestParam(value = "pageSize", defaultValue = "10") Integer pageSize) {
+        // 手动构建PageQuery对象
+        PageQuery pageQuery = new PageQuery(pageSize, pageNum);
+//        pageQuery.setPageNum(pageNum);
+//        pageQuery.setPageSize(pageSize);
+
+        return gameScoreService.getProjectScoreData(eventId, projectId, classification, searchValue, pageQuery);
+    }
+
+    /**
+     * 更新成绩并重新计算排名积分
+     */
+    @SaCheckPermission("system:gameScore:edit")
+    @Log(title = "成绩更新", businessType = BusinessType.UPDATE)
+    @PutMapping("/updateScoreAndRecalculate")
+    public R<Void> updateScoreAndRecalculate(@Validated(EditGroup.class) @RequestBody GameScoreBo bo) {
+        return toAjax(gameScoreService.updateScoreAndRecalculate(bo));
+    }
+
+    /**
+     * 重新计算项目排名和积分
+     */
+    @SaCheckPermission("system:gameScore:edit")
+    @Log(title = "重新计算排名积分", businessType = BusinessType.UPDATE)
+    @PostMapping("/recalculateRankingsAndPoints")
+    public R<Void> recalculateRankingsAndPoints(
+            @RequestParam("eventId") Long eventId,
+            @RequestParam("projectId") Long projectId) {
+        return toAjax(gameScoreService.recalculateRankingsAndPoints(eventId, projectId));
+    }
 }

+ 2 - 2
ruoyi-modules/ruoyi-game-event/src/main/java/org/dromara/system/domain/GameEventProject.java

@@ -45,9 +45,9 @@ public class GameEventProject extends TenantEntity {
     private String projectType;
 
     /**
-     * 项目组别
+     * 归类(0个人项目/1团体项目)
      */
-    private String groupType;
+    private String classification;
 
     /**
      * 裁判组

+ 9 - 4
ruoyi-modules/ruoyi-game-event/src/main/java/org/dromara/system/domain/GameScore.java

@@ -49,9 +49,14 @@ public class GameScore extends TenantEntity {
     private Long teamId;
 
     /**
-     * 成绩
+     * 个人成绩
      */
-    private BigDecimal scoreValue;
+    private BigDecimal individualPerformance;
+
+    /**
+     * 团队成绩
+     */
+    private BigDecimal teamPerformance;
 
     /**
      * 成绩类型
@@ -61,12 +66,12 @@ public class GameScore extends TenantEntity {
     /**
      * 名次
      */
-    private Long scoreRank;
+    private Integer scoreRank;
 
     /**
      * 积分
      */
-    private Long scorePoint;
+    private Integer scorePoint;
 
     /**
      * 奖项

+ 3 - 5
ruoyi-modules/ruoyi-game-event/src/main/java/org/dromara/system/domain/bo/GameEventProjectBo.java

@@ -49,16 +49,14 @@ public class GameEventProjectBo extends BaseEntity {
     private String projectName;
 
     /**
-     * 项目类型(个人/团体)
+     * 项目类型
      */
-//    @NotBlank(message = "项目类型(个人/团体)不能为空", groups = { AddGroup.class, EditGroup.class })
     private String projectType;
 
     /**
-     * 项目组别
+     * 归类(0个人/1团体)
      */
-//    @NotBlank(message = "项目组别不能为空", groups = { AddGroup.class, EditGroup.class })
-    private String groupType;
+    private String classification;
 
     /**
      * 裁判组

+ 8 - 7
ruoyi-modules/ruoyi-game-event/src/main/java/org/dromara/system/domain/bo/GameScoreBo.java

@@ -31,32 +31,33 @@ public class GameScoreBo extends BaseEntity {
     /**
      * 赛事ID
      */
-    @NotNull(message = "赛事ID不能为空", groups = { AddGroup.class, EditGroup.class })
+//    @NotNull(message = "赛事ID不能为空", groups = { AddGroup.class, EditGroup.class })
     private Long eventId;
 
     /**
      * 项目ID
      */
-    @NotNull(message = "项目ID不能为空", groups = { AddGroup.class, EditGroup.class })
+//    @NotNull(message = "项目ID不能为空", groups = { AddGroup.class, EditGroup.class })
     private Long projectId;
 
     /**
      * 运动员ID
      */
-    @NotNull(message = "运动员ID不能为空", groups = { AddGroup.class, EditGroup.class })
+//    @NotNull(message = "运动员ID不能为空", groups = { AddGroup.class, EditGroup.class })
     private Long athleteId;
 
     /**
      * 队伍ID
      */
-    @NotNull(message = "队伍ID不能为空", groups = { AddGroup.class, EditGroup.class })
+//    @NotNull(message = "队伍ID不能为空", groups = { AddGroup.class, EditGroup.class })
     private Long teamId;
 
     /**
      * 成绩值
      */
 //    @NotBlank(message = "成绩值不能为空", groups = { AddGroup.class, EditGroup.class })
-    private BigDecimal scoreValue;
+    private BigDecimal individualPerformance;
+    private BigDecimal teamPerformance;
 
     /**
      * 成绩类型
@@ -67,12 +68,12 @@ public class GameScoreBo extends BaseEntity {
     /**
      * 名次
      */
-    private Long scoreRank;
+    private Integer scoreRank;
 
     /**
      * 积分
      */
-    private Long scorePoint;
+    private Integer scorePoint;
 
     /**
      * 奖项

+ 3 - 3
ruoyi-modules/ruoyi-game-event/src/main/java/org/dromara/system/domain/vo/AthleteScoreVo.java

@@ -32,7 +32,7 @@ public class AthleteScoreVo implements Serializable {
     /**
      * 总积分
      */
-    private Long totalScore;
+    private Integer totalScore;
 
     @Data
     public static class ScoreDetail {
@@ -44,11 +44,11 @@ public class AthleteScoreVo implements Serializable {
         /**
          * 项目积分
          */
-        private Long scorePoint;
+        private Integer scorePoint;
 
         /**
          * 名次
          */
-        private Long rank;
+        private Integer rank;
     }
 }

+ 2 - 1
ruoyi-modules/ruoyi-game-event/src/main/java/org/dromara/system/domain/vo/GameAthleteVo.java

@@ -74,6 +74,7 @@ public class GameAthleteVo implements Serializable {
      * 性别
      */
     @ExcelProperty(value = "性别")
+    @ExcelDictFormat(dictType = "sys_user_sex")
     private String gender;
 
     /**
@@ -136,7 +137,7 @@ public class GameAthleteVo implements Serializable {
      * 状态(0正常 1停用)
      */
     @ExcelProperty(value = "状态", converter = ExcelDictConvert.class)
-    @ExcelDictFormat(readConverterExp = "0=正常,1=停用")
+    @ExcelDictFormat(dictType = "game_event_status")
     private String status;
 
     /**

+ 6 - 6
ruoyi-modules/ruoyi-game-event/src/main/java/org/dromara/system/domain/vo/GameEventGroupVo.java

@@ -52,7 +52,7 @@ public class GameEventGroupVo implements Serializable {
     /**
      * 包含项目列表
      */
-    @ExcelProperty(value = "包含项目列表")
+//    @ExcelProperty(value = "包含项目列表")
     private String projectList;
 
     /**
@@ -65,7 +65,7 @@ public class GameEventGroupVo implements Serializable {
     /**
      * 包含组数
      */
-    @ExcelProperty(value = "包含组数")
+    @ExcelProperty(value = "组数")
     private Long includeGroupNum;
 
     /**
@@ -77,13 +77,13 @@ public class GameEventGroupVo implements Serializable {
     /**
      * 组别比赛开始时间
      */
-    @ExcelProperty(value = "组别比赛开始时间")
+    @ExcelProperty(value = "组开始时间")
     private Date beginTime;
 
     /**
      * 组别比赛结束时间
      */
-    @ExcelProperty(value = "组别比赛结束时间")
+    @ExcelProperty(value = "组结束时间")
     private Date endTime;
 
     /**
@@ -107,13 +107,13 @@ public class GameEventGroupVo implements Serializable {
     /**
      * 排序字段
      */
-    @ExcelProperty(value = "排序字段")
+//    @ExcelProperty(value = "排序字段")
     private String sortOrder;
 
     /**
      * 排序规则(0升序1降序)
      */
-    @ExcelProperty(value = "排序规则(0升序1降序)")
+//    @ExcelProperty(value = "排序规则(0升序1降序)")
     private Long sortRule;
 
     /**

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

@@ -55,14 +55,15 @@ public class GameEventProjectVo implements Serializable {
      * 项目类型(个人/团体)
      */
     @ExcelProperty(value = "项目类型", converter = ExcelDictConvert.class)
-    @ExcelDictFormat(readConverterExp = "0=个人,1=团体")
+    @ExcelDictFormat(dictType = "game_project_type")
     private String projectType;
 
     /**
-     * 项目组别
+     * 归类(0个人项目/1团体项目)
      */
-    @ExcelProperty(value = "项目组别")
-    private String groupType;
+    @ExcelProperty(value = "归类")
+    @ExcelDictFormat(dictType = "game_project_classification")
+    private String classification;
 
     /**
      * 裁判组
@@ -119,13 +120,14 @@ public class GameEventProjectVo implements Serializable {
     /**
      * 排序方式
      */
-    @ExcelProperty(value = "排序方式")
+//    @ExcelProperty(value = "排序方式")
     private String orderType;
 
     /**
      * 计算规则
      */
     @ExcelProperty(value = "计算规则")
+    @ExcelDictFormat(dictType = "game_score_type")
     private String scoreRule;
 
     /**
@@ -156,7 +158,7 @@ public class GameEventProjectVo implements Serializable {
      * 状态(0正常 1停用)
      */
     @ExcelProperty(value = "状态", converter = ExcelDictConvert.class)
-    @ExcelDictFormat(readConverterExp = "0=正常,1=停用")
+    @ExcelDictFormat(dictType = "game_event_status")
     private String status;
 
     /**

+ 6 - 4
ruoyi-modules/ruoyi-game-event/src/main/java/org/dromara/system/domain/vo/GameScoreVo.java

@@ -64,8 +64,10 @@ public class GameScoreVo implements Serializable {
     /**
      * 成绩值
      */
-    @ExcelProperty(value = "成绩值")
-    private BigDecimal scoreValue;
+    @ExcelProperty(value = "个人成绩")
+    private BigDecimal individualPerformance;
+    @ExcelProperty(value = "团队成绩")
+    private BigDecimal teamPerformance;
 
     /**
      * 成绩类型
@@ -77,13 +79,13 @@ public class GameScoreVo implements Serializable {
      * 名次
      */
     @ExcelProperty(value = "名次")
-    private Long scoreRank;
+    private Integer scoreRank;
 
     /**
      * 积分
      */
     @ExcelProperty(value = "积分")
-    private Long scorePoint;
+    private Integer scorePoint;
 
     /**
      * 奖项

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

@@ -22,4 +22,12 @@ public interface GameScoreMapper extends BaseMapperPlus<GameScore, GameScoreVo>
      * @return
      */
     List<GameScore> listAppScoreByEventIdGroupProjectId(Long eventId);
+
+    /**
+     * 获取运动员某个项目成绩
+     * @param athleteId
+     * @param projectId
+     * @return
+     */
+    GameScoreVo selectVoByAthleteIdAndProjectId(Long athleteId, Long projectId);
 }

+ 9 - 0
ruoyi-modules/ruoyi-game-event/src/main/java/org/dromara/system/service/IGameAthleteService.java

@@ -88,4 +88,13 @@ public interface IGameAthleteService {
     List<GameAthleteVo> listByIds(Collection<Long> athleteIds);
 
     Long countByEventId(Long eventId);
+
+    /**
+     * 根据赛事ID、项目ID和搜索条件查询运动员列表
+     * @param eventId 赛事ID
+     * @param projectId 项目ID
+     * @param searchValue 搜索值(运动员姓名)
+     * @return 运动员列表
+     */
+    List<GameAthleteVo> queryListByEventIdAndProjectId(Long eventId, Long projectId, String searchValue);
 }

+ 34 - 0
ruoyi-modules/ruoyi-game-event/src/main/java/org/dromara/system/service/IGameScoreService.java

@@ -74,4 +74,38 @@ public interface IGameScoreService {
      * @return 获奖名单 key:项目 list:获奖信息
      */
     Map<String, List<GameScoreVo>> getAppScore(Long eventId);
+
+    /**
+     * 根据运动员ID和项目ID查询成绩
+     * @param athleteId
+     * @param projectId
+     * @return
+     */
+    GameScoreVo getScoreByAthleteIdAndProjectId(Long athleteId, Long projectId);
+
+    /**
+     * 获取项目成绩综合数据(包含运动员/队伍信息)
+     * @param eventId 赛事ID
+     * @param projectId 项目ID
+     * @param classification 项目分类(0个人项目,1团体项目)
+     * @param searchValue 搜索值
+     * @param pageQuery 分页参数
+     * @return 综合数据
+     */
+    TableDataInfo<Map<String, Object>> getProjectScoreData(Long eventId, Long projectId, String classification, String searchValue, PageQuery pageQuery);
+
+    /**
+     * 更新成绩并重新计算排名积分
+     * @param bo 成绩信息
+     * @return 是否成功
+     */
+    Boolean updateScoreAndRecalculate(GameScoreBo bo);
+
+    /**
+     * 重新计算项目排名和积分
+     * @param eventId 赛事ID
+     * @param projectId 项目ID
+     * @return 是否成功
+     */
+    Boolean recalculateRankingsAndPoints(Long eventId, Long projectId);
 }

+ 55 - 2
ruoyi-modules/ruoyi-game-event/src/main/java/org/dromara/system/service/impl/GameAthleteServiceImpl.java

@@ -122,10 +122,10 @@ public class GameAthleteServiceImpl implements IGameAthleteService {
             }).collect(Collectors.toList());
 
             vo.setScoreDetails(scoreDetails);
-            Long totalScore = scoreDetails.stream()
+            Integer totalScore = scoreDetails.stream()
                 .map(AthleteScoreVo.ScoreDetail::getScorePoint)
                 .filter(Objects::nonNull)
-                .reduce(0L, Long::sum);
+                .reduce(0, Integer::sum);
             vo.setTotalScore(totalScore);
 
             return vo;
@@ -417,6 +417,59 @@ public class GameAthleteServiceImpl implements IGameAthleteService {
         return list;
     }
 
+    /**
+     * 根据赛事ID、项目ID和搜索条件查询运动员列表
+     */
+    @Override
+    public List<GameAthleteVo> queryListByEventIdAndProjectId(Long eventId, Long projectId, String searchValue) {
+        log.info("查询运动员列表: eventId={}, projectId={}, searchValue={}", eventId, projectId, searchValue);
+
+        LambdaQueryWrapper<GameAthlete> lqw = Wrappers.lambdaQuery();
+        lqw.eq(GameAthlete::getEventId, eventId);
+
+        // 如果提供了搜索值,添加姓名搜索条件
+        if (StringUtils.isNotBlank(searchValue)) {
+            lqw.like(GameAthlete::getName, searchValue);
+        }
+
+        List<GameAthleteVo> allAthletes = baseMapper.selectVoList(lqw);
+        log.info("查询到总运动员数量: {}", allAthletes.size());
+
+        // 先转换所有运动员的projectList字段
+        allAthletes.forEach(athlete -> {
+            if (athlete.getProjectValue() != null) {
+                try {
+                    athlete.setProjectList(JSONUtil.toList(athlete.getProjectValue(), String.class));
+                    log.debug("运动员 {} 的项目列表转换成功: {}", athlete.getName(), athlete.getProjectList());
+                } catch (Exception e) {
+                    log.warn("转换运动员 {} 的项目列表失败: {}", athlete.getName(), e);
+                    athlete.setProjectList(new ArrayList<>());
+                }
+            } else {
+                athlete.setProjectList(new ArrayList<>());
+                log.debug("运动员 {} 的项目值为空,设置为空列表", athlete.getName());
+            }
+        });
+
+        // 直接使用projectList字段进行过滤
+        List<GameAthleteVo> filteredAthletes = allAthletes.stream()
+            .filter(athlete -> {
+                if (CollectionUtils.isNotEmpty(athlete.getProjectList())) {
+                    boolean containsProject = athlete.getProjectList().contains(projectId.toString());
+                    log.debug("运动员 {} 的项目列表: {}, 包含项目 {}: {}",
+                            athlete.getName(), athlete.getProjectList(), projectId, containsProject);
+                    return containsProject;
+                } else {
+                    log.debug("运动员 {} 的项目列表为空", athlete.getName());
+                    return false;
+                }
+            })
+            .collect(Collectors.toList());
+
+        log.info("过滤后参与项目 {} 的运动员数量: {}", projectId, filteredAthletes.size());
+        return filteredAthletes;
+    }
+
     @Override
     public Long countByEventId(Long eventId) {
         return baseMapper.selectCount(

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

@@ -166,7 +166,7 @@ public class GameEventProjectServiceImpl implements IGameEventProjectService {
             });
         lqw.like(StringUtils.isNotBlank(bo.getProjectName()), GameEventProject::getProjectName, bo.getProjectName());
         lqw.eq(StringUtils.isNotBlank(bo.getProjectType()), GameEventProject::getProjectType, bo.getProjectType());
-        lqw.eq(StringUtils.isNotBlank(bo.getGroupType()), GameEventProject::getGroupType, bo.getGroupType());
+        lqw.eq(StringUtils.isNotBlank(bo.getClassification()), GameEventProject::getClassification, bo.getClassification());
         lqw.eq(bo.getStartTime() != null, GameEventProject::getStartTime, bo.getStartTime());
         lqw.eq(StringUtils.isNotBlank(bo.getOrderType()), GameEventProject::getOrderType, bo.getOrderType());
         lqw.eq(StringUtils.isNotBlank(bo.getStatus()), GameEventProject::getStatus, bo.getStatus());

+ 24 - 13
ruoyi-modules/ruoyi-game-event/src/main/java/org/dromara/system/service/impl/GameEventServiceImpl.java

@@ -1,5 +1,6 @@
 package org.dromara.system.service.impl;
 
+import cn.hutool.core.img.FontUtil;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
@@ -19,6 +20,7 @@ import jakarta.annotation.Resource;
 import jakarta.servlet.http.HttpServletRequest;
 import jakarta.servlet.http.HttpServletResponse;
 import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.io.IOUtils;
 import org.apache.commons.io.output.ByteArrayOutputStream;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.poi.ss.usermodel.*;
@@ -50,7 +52,7 @@ import org.springframework.web.multipart.MultipartFile;
 
 import javax.imageio.ImageIO;
 import java.awt.image.BufferedImage;
-import java.io.IOException;
+import java.io.*;
 import java.util.*;
 import java.util.concurrent.atomic.AtomicLong;
 import java.util.stream.Collectors;
@@ -708,9 +710,13 @@ public class GameEventServiceImpl implements IGameEventService {
                         cb.endText();
                     }
                     StringBuilder joinProject = new StringBuilder();
-                    athlete.getProjectList().forEach(
-                        projectId -> joinProject.append(projectMap.get(Long.valueOf(projectId))).append(" ")
-                    );
+                    StringJoiner joiner = new StringJoiner("、"); // 指定分隔符
+                    athlete.getProjectList().forEach(projectId -> {
+                        String projectName = projectMap.get(Long.valueOf(projectId));
+                        if (projectName != null) {
+                            joiner.add(projectName);
+                        }
+                    });
 
                     // 生成二维码 - 更精确的位置调整
                     String qrData = String.format(
@@ -720,11 +726,11 @@ public class GameEventServiceImpl implements IGameEventService {
                             运动员编号:%s,
                             参与项目:%s,
                             队伍id:%d,
-                            队伍名称:%s
-                            运动员姓名:%s
+                            队伍名称:%s,
+                            运动员姓名:%s,
                             性别:%s,
                             年龄:%d
-                            """,
+                        """,
                         eventName, athlete.getAthleteId(), athlete.getAthleteCode(),
                         joinProject.toString(),
                         athlete.getTeamId(), teamNameMap.get(athlete.getTeamId()), athlete.getName(), athlete.getGender(), athlete.getAge()
@@ -812,13 +818,18 @@ public class GameEventServiceImpl implements IGameEventService {
     private static BaseFont getChineseFont(String fontName) throws Exception {
         // 方式1:使用系统字体(Windows)
         // return BaseFont.createFont("C:/Windows/Fonts/simhei.ttf", BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
+        String filePath;
         switch (fontName) {
-            case "simhei":
-                return BaseFont.createFont("classpath:fonts/simhei.ttf", BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
-            case "simsun":
-                return BaseFont.createFont("classpath:fonts/simsun.ttc", BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
-            default:
-                return BaseFont.createFont("classpath:fonts/msyhbd.ttc", BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
+            case "simhei" -> filePath = "fonts/simhei.ttf";
+            case "simsun" -> filePath = "fonts/simsun.ttf";
+            default -> filePath = "fonts/yahei.ttf";
+        }
+        try (InputStream in = FontUtil.class.getClassLoader().getResourceAsStream(filePath)) {
+            if (in == null) throw new FileNotFoundException(filePath);
+            File temp = File.createTempFile("font_", ".ttf");
+            temp.deleteOnExit();
+            IOUtils.copy(in, new FileOutputStream(temp));
+            return BaseFont.createFont(temp.getAbsolutePath(), BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
         }
     }
 }

+ 560 - 0
ruoyi-modules/ruoyi-game-event/src/main/java/org/dromara/system/service/impl/GameScoreServiceImpl.java

@@ -252,4 +252,564 @@ public class GameScoreServiceImpl implements IGameScoreService {
         return result;
     }
 
+    /**
+     * 根据运动员ID和项目ID查询成绩
+     * @param athleteId
+     * @param projectId
+     * @return
+     */
+    @Override
+    public GameScoreVo getScoreByAthleteIdAndProjectId(Long athleteId, Long projectId) {
+        return baseMapper.selectVoByAthleteIdAndProjectId(athleteId, projectId);
+    }
+
+    /**
+     * 获取项目成绩综合数据(包含运动员/队伍信息)
+     */
+    @Override
+    public TableDataInfo<Map<String, Object>> getProjectScoreData(Long eventId, Long projectId, String classification, String searchValue, PageQuery pageQuery) {
+        log.info("开始获取项目成绩数据: eventId={}, projectId={}, classification={}, searchValue={}, pageNum={}, pageSize={}",
+                eventId, projectId, classification, searchValue, pageQuery.getPageNum(), pageQuery.getPageSize());
+
+        List<Map<String, Object>> allDataList = new ArrayList<>();
+
+        if ("0".equals(classification)) {
+            // 个人项目:获取运动员数据
+            log.info("处理个人项目数据");
+            allDataList = getIndividualProjectData(eventId, projectId, searchValue, pageQuery);
+        } else {
+            // 团体项目:获取队伍数据
+            log.info("处理团体项目数据");
+            allDataList = getTeamProjectData(eventId, projectId, searchValue, pageQuery);
+        }
+
+        log.info("获取到总数据量: {}", allDataList.size());
+
+        // 计算总数
+        int total = allDataList.size();
+
+        // 手动分页处理
+        int pageNum = pageQuery.getPageNum();
+        int pageSize = pageQuery.getPageSize();
+        int startIndex = (pageNum - 1) * pageSize;
+        int endIndex = Math.min(startIndex + pageSize, total);
+
+        log.info("分页参数: pageNum={}, pageSize={}, startIndex={}, endIndex={}", pageNum, pageSize, startIndex, endIndex);
+
+        // 获取当前页的数据
+        List<Map<String, Object>> pageData = new ArrayList<>();
+        if (startIndex < total) {
+            pageData = allDataList.subList(startIndex, endIndex);
+            log.info("当前页数据量: {}", pageData.size());
+        } else {
+            log.warn("分页索引超出范围: startIndex={}, total={}", startIndex, total);
+        }
+
+        // 构建分页结果
+        Page<Map<String, Object>> page = new Page<>(pageNum, pageSize);
+        page.setRecords(pageData);
+        page.setTotal(total);
+
+        log.info("分页结果: 总数={}, 当前页数据量={}", total, pageData.size());
+        return TableDataInfo.build(page);
+    }
+
+    /**
+     * 获取个人项目数据
+     */
+    private List<Map<String, Object>> getIndividualProjectData(Long eventId, Long projectId, String searchValue, PageQuery pageQuery) {
+        log.info("开始获取个人项目数据: eventId={}, projectId={}, searchValue={}", eventId, projectId, searchValue);
+
+        List<Map<String, Object>> resultList = new ArrayList<>();
+
+        // 查询参与该项目的运动员
+        List<GameAthleteVo> athletes = gameAthleteService.queryListByEventIdAndProjectId(eventId, projectId, searchValue);
+        log.info("查询到运动员数量: {}", athletes.size());
+
+        for (GameAthleteVo athlete : athletes) {
+            log.info("处理运动员: athleteId={}, name={}, teamId={}", athlete.getAthleteId(), athlete.getName(), athlete.getTeamId());
+
+            Map<String, Object> data = new HashMap<>();
+            data.put("id", athlete.getAthleteId());
+            data.put("athleteId", athlete.getAthleteId());
+            data.put("userId", athlete.getUserId());
+            data.put("eventId", eventId);
+            data.put("projectId", projectId);
+            data.put("teamId", athlete.getTeamId());
+            data.put("athleteCode", athlete.getAthleteCode());
+            data.put("name", athlete.getName());
+            data.put("unit", athlete.getUnit());
+            data.put("groupType", athlete.getGroupType());
+//            data.put("number", athlete.getNumber());
+
+            // 查询队伍信息,获取队伍名称
+            String teamName = "";
+            if (athlete.getTeamId() != null) {
+                GameTeamVo team = gameTeamService.queryById(athlete.getTeamId());
+                if (team != null) {
+                    teamName = team.getTeamName();
+                    log.debug("获取到队伍名称: teamId={}, teamName={}", athlete.getTeamId(), teamName);
+                }
+            }
+            data.put("teamName", teamName); // 添加teamName字段
+
+            // 查询成绩信息
+            GameScoreVo score = getScoreByAthleteIdAndProjectId(athlete.getAthleteId(), projectId);
+            if (score != null) {
+                data.put("scoreId", score.getScoreId());
+                data.put("scorePoint", score.getScorePoint());
+                data.put("individualPerformance", score.getIndividualPerformance());
+                data.put("teamPerformance", score.getTeamPerformance());
+                data.put("scoreRank", score.getScoreRank());
+                data.put("updateTime", score.getUpdateTime());
+                log.info("获取到成绩信息: scoreId={}, scorePoint={}", score.getScoreId(), score.getScorePoint());
+            } else {
+                data.put("scoreId", 0);
+                data.put("scorePoint", 0);
+                data.put("individualPerformance", 0.0);
+                data.put("teamPerformance", 0.0);
+                data.put("scoreRank", 0);
+                data.put("updateTime", "");
+                log.info("未找到成绩信息,使用默认值");
+            }
+
+            resultList.add(data);
+        }
+
+        log.info("个人项目数据处理完成,返回数据量: {}", resultList.size());
+        return resultList;
+    }
+
+    /**
+     * 获取团体项目数据
+     */
+    private List<Map<String, Object>> getTeamProjectData(Long eventId, Long projectId, String searchValue, PageQuery pageQuery) {
+        List<Map<String, Object>> resultList = new ArrayList<>();
+        Set<Long> processedTeamIds = new HashSet<>();
+
+        // 查询参与该项目的运动员
+        List<GameAthleteVo> athletes = gameAthleteService.queryListByEventIdAndProjectId(eventId, projectId, searchValue);
+
+        for (GameAthleteVo athlete : athletes) {
+            if (athlete.getTeamId() == null || processedTeamIds.contains(athlete.getTeamId())) {
+                continue;
+            }
+
+            processedTeamIds.add(athlete.getTeamId());
+
+            // 查询队伍信息
+            GameTeamVo team = gameTeamService.queryById(athlete.getTeamId());
+            if (team == null) {
+                continue;
+            }
+
+            Map<String, Object> data = new HashMap<>();
+            data.put("id", team.getTeamId());
+            data.put("teamId", team.getTeamId());
+            data.put("teamName", team.getTeamName());
+            data.put("teamCode", team.getTeamCode());
+            data.put("eventId", eventId);
+            data.put("projectId", projectId);
+
+            // 查询成绩信息(使用第一个运动员的成绩作为队伍成绩)
+            GameScoreVo score = getScoreByAthleteIdAndProjectId(athlete.getAthleteId(), projectId);
+            if (score != null) {
+                data.put("scoreId", score.getScoreId());
+                data.put("scorePoint", score.getScorePoint());
+                data.put("individualPerformance", score.getIndividualPerformance());
+                data.put("teamPerformance", score.getTeamPerformance());
+                data.put("scoreRank", score.getScoreRank());
+                data.put("updateTime", score.getUpdateTime());
+            } else {
+                data.put("scoreId", 0);
+                data.put("scorePoint", 0);
+                data.put("individualPerformance", 0.0);
+                data.put("teamPerformance", 0.0);
+                data.put("scoreRank", 0);
+                data.put("updateTime", "");
+            }
+
+            resultList.add(data);
+        }
+
+        return resultList;
+    }
+
+    /**
+     * 更新成绩并重新计算排名积分
+     */
+    @Override
+    public Boolean updateScoreAndRecalculate(GameScoreBo bo) {
+        log.info("开始处理成绩更新,scoreId: {}, eventId: {}, projectId: {}, teamId: {}",
+        bo.getScoreId(), bo.getEventId(), bo.getProjectId(), bo.getTeamId());
+
+        // 判断是否是手动排名计算(没有具体成绩数据,只有基本信息)
+        boolean isManualRankingCalculation = (bo.getScoreId() == null &&
+                                            bo.getAthleteId() == null &&
+                                            bo.getTeamId() == null &&
+                                            bo.getIndividualPerformance() == null &&
+                                            bo.getTeamPerformance() == null);
+
+        log.info("手动排名计算判断: scoreId={}, athleteId={}, teamId={}, individualPerformance={}, teamPerformance={}, isManualRanking={}",
+                bo.getScoreId(), bo.getAthleteId(), bo.getTeamId(), bo.getIndividualPerformance(), bo.getTeamPerformance(), isManualRankingCalculation);
+
+        if (isManualRankingCalculation) {
+            // 手动排名计算:直接重新计算排名和积分
+            log.info("检测到手动排名计算请求,跳过成绩更新,直接计算排名");
+            Boolean result = recalculateRankingsAndPoints(bo.getEventId(), bo.getProjectId());
+            log.info("手动排名计算完成,结果: {}", result);
+            return result;
+        }
+
+        // 获取项目信息,判断是个人项目还是团体项目
+        GameEventProjectVo project = gameEventProjectService.queryById(bo.getProjectId());
+        log.info("项目信息: projectId: {}, classification: {}", bo.getProjectId(),
+        project != null ? project.getClassification() : "null");
+
+        Boolean result = false;
+
+        if (project != null && "1".equals(project.getClassification())) {
+            // 团体项目:为队伍中的所有运动员创建或更新成绩记录
+            log.info("处理团体项目成绩更新");
+            result = handleTeamScoreUpdate(bo);
+        } else {
+            // 个人项目:直接更新或插入
+            log.info("处理个人项目成绩更新,scoreId: {}", bo.getScoreId());
+            if (bo.getScoreId() != null && bo.getScoreId() > 0) {
+                result = updateByBo(bo);
+                log.info("更新现有成绩记录,结果: {}", result);
+            } else {
+                result = insertByBo(bo);
+                log.info("插入新成绩记录,结果: {}", result);
+            }
+        }
+
+        if (result) {
+            // 重新计算排名和积分
+            log.info("开始重新计算排名和积分");
+            recalculateRankingsAndPoints(bo.getEventId(), bo.getProjectId());
+        }
+
+        log.info("成绩更新处理完成,结果: {}", result);
+        return result;
+    }
+
+    /**
+     * 处理团体项目成绩更新
+     */
+    private Boolean handleTeamScoreUpdate(GameScoreBo bo) {
+        try {
+            log.info("开始处理团体项目成绩更新,teamId: {}", bo.getTeamId());
+
+            // 获取队伍中的所有运动员
+            List<GameAthleteVo> teamAthletes = gameAthleteService.queryListByEventIdAndProjectId(
+                bo.getEventId(), bo.getProjectId(), null);
+
+            log.info("找到参与项目的运动员数量: {}", teamAthletes.size());
+
+            // 过滤出属于指定队伍的运动员
+            List<GameAthleteVo> relevantAthletes = teamAthletes.stream()
+                .filter(athlete -> athlete.getTeamId() != null && athlete.getTeamId().equals(bo.getTeamId()))
+                .collect(Collectors.toList());
+
+            log.info("队伍 {} 的运动员数量: {}", bo.getTeamId(), relevantAthletes.size());
+
+            if (relevantAthletes.isEmpty()) {
+                log.warn("未找到队伍 {} 的运动员", bo.getTeamId());
+                return false;
+            }
+
+            // 为每个运动员创建或更新成绩记录
+            for (GameAthleteVo athlete : relevantAthletes) {
+                log.info("处理运动员 {} 的成绩记录", athlete.getAthleteId());
+
+                GameScoreBo athleteScoreBo = new GameScoreBo();
+                athleteScoreBo.setEventId(bo.getEventId());
+                athleteScoreBo.setProjectId(bo.getProjectId());
+                athleteScoreBo.setAthleteId(athlete.getAthleteId());
+                athleteScoreBo.setTeamId(bo.getTeamId());
+                athleteScoreBo.setIndividualPerformance(BigDecimal.ZERO); // 团体项目个人成绩为0
+                athleteScoreBo.setTeamPerformance(bo.getTeamPerformance());
+                athleteScoreBo.setScoreType("team");
+                athleteScoreBo.setStatusFlag("0");
+                athleteScoreBo.setStatus("0");
+                athleteScoreBo.setRemark("团体项目成绩");
+
+                // 查找是否已有该运动员的成绩记录
+                GameScoreVo existingScore = getScoreByAthleteIdAndProjectId(athlete.getAthleteId(), bo.getProjectId());
+                if (existingScore != null) {
+                    // 更新现有记录
+                    log.info("更新运动员 {} 的现有成绩记录", athlete.getAthleteId());
+                    athleteScoreBo.setScoreId(existingScore.getScoreId());
+                    Boolean updateResult = updateByBo(athleteScoreBo);
+                    log.info("更新结果: {}", updateResult);
+                } else {
+                    // 插入新记录
+                    log.info("为运动员 {} 插入新成绩记录", athlete.getAthleteId());
+                    Boolean insertResult = insertByBo(athleteScoreBo);
+                    log.info("插入结果: {}", insertResult);
+                }
+            }
+
+            log.info("团体项目成绩更新处理完成");
+            return true;
+        } catch (Exception e) {
+            log.error("处理团体项目成绩更新失败", e);
+            return false;
+        }
+    }
+
+    /**
+     * 重新计算项目排名和积分
+     */
+    @Override
+    public Boolean recalculateRankingsAndPoints(Long eventId, Long projectId) {
+        try {
+            // 获取项目配置信息
+            GameEventProjectVo project = gameEventProjectService.queryById(projectId);
+            if (project == null) {
+                log.error("项目不存在,projectId: {}", projectId);
+                return false;
+            }
+
+            String classification = project.getClassification();
+            String scoreValue = project.getScoreValue();
+
+            // 获取所有相关成绩记录
+            GameScoreBo queryBo = new GameScoreBo();
+            queryBo.setEventId(eventId);
+            queryBo.setProjectId(projectId);
+            List<GameScoreVo> allScores = queryList(queryBo);
+
+            if ("0".equals(classification)) {
+                // 个人项目:按个人成绩排序
+                return handleIndividualProjectRanking(allScores, scoreValue, eventId, projectId);
+            } else {
+                // 团体项目:按队伍汇总积分后排序
+                return handleTeamProjectRanking(allScores, scoreValue, eventId, projectId);
+            }
+        } catch (Exception e) {
+            log.error("重新计算排名和积分失败", e);
+            return false;
+        }
+    }
+
+    /**
+     * 处理个人项目排名和积分计算
+     */
+    private Boolean handleIndividualProjectRanking(List<GameScoreVo> allScores, String scoreValue, Long eventId, Long projectId) {
+        // 获取项目信息,确定排序方式
+        GameEventProjectVo project = gameEventProjectService.queryById(projectId);
+        if (project == null) {
+            log.error("项目不存在,projectId: {}", projectId);
+            return false;
+        }
+
+        String orderType = project.getOrderType();
+        log.info("个人项目排名计算,projectId: {}, orderType: {}", projectId, orderType);
+
+        // 根据orderType决定排序方式
+        // orderType: 0-升序(成绩越小越好),1-降序(成绩越大越好)
+        List<GameScoreVo> sortedScores = allScores.stream()
+            .sorted((a, b) -> {
+                BigDecimal aIndividualPerformance = a.getIndividualPerformance() != null ? a.getIndividualPerformance() : BigDecimal.ZERO;
+                BigDecimal bIndividualPerformance = b.getIndividualPerformance() != null ? b.getIndividualPerformance() : BigDecimal.ZERO;
+                
+                if ("0".equals(orderType)) {
+                    // 升序:成绩越小越好
+                    return aIndividualPerformance.compareTo(bIndividualPerformance);
+                } else {
+                    // 降序:成绩越大越好(默认)
+                    return bIndividualPerformance.compareTo(aIndividualPerformance);
+                }
+            })
+            .toList();
+
+        // 解析积分分值
+        List<Integer> pointValues = Arrays.stream(scoreValue.split(","))
+            .map(String::trim)
+            .map(Integer::parseInt)
+            .toList();
+
+        // 根据orderType决定积分分配方式
+        if ("0".equals(orderType)) {
+            // 升序项目:成绩越小,积分分配越多
+            for (int i = 0; i < sortedScores.size(); i++) {
+                GameScoreVo score = sortedScores.get(i);
+                int points = i < pointValues.size() ? pointValues.get(i) : 0;
+
+                // 更新成绩记录
+                GameScoreBo updateBo = new GameScoreBo();
+                updateBo.setScoreId(score.getScoreId());
+                updateBo.setScorePoint(points);
+                updateBo.setEventId(eventId);
+                updateBo.setProjectId(projectId);
+
+                updateByBo(updateBo);
+            }
+        } else {
+            // 降序项目:成绩越大,积分分配越多
+            for (int i = 0; i < sortedScores.size(); i++) {
+                GameScoreVo score = sortedScores.get(i);
+                int points = i < pointValues.size() ? pointValues.get(i) : 0;
+
+                // 更新成绩记录
+                GameScoreBo updateBo = new GameScoreBo();
+                updateBo.setScoreId(score.getScoreId());
+                updateBo.setScorePoint(points);
+                updateBo.setEventId(eventId);
+                updateBo.setProjectId(projectId);
+
+                updateByBo(updateBo);
+            }
+        }
+
+        // 然后按积分重新排序确定排名
+        List<GameScoreVo> scoresWithPoints = queryList(new GameScoreBo() {{
+            setEventId(eventId);
+            setProjectId(projectId);
+        }});
+
+        // 按积分排序(降序,积分越高排名越靠前)
+        List<GameScoreVo> sortedByPoints = scoresWithPoints.stream()
+            .sorted((a, b) -> {
+                Integer aPoints = a.getScorePoint() != null ? a.getScorePoint() : 0;
+                Integer bPoints = b.getScorePoint() != null ? b.getScorePoint() : 0;
+                return Integer.compare(bPoints, aPoints);
+            })
+            .toList();
+
+        // 更新排名
+        for (int i = 0; i < sortedByPoints.size(); i++) {
+            GameScoreVo score = sortedByPoints.get(i);
+            int rank = i + 1;
+
+            // 更新排名
+            GameScoreBo updateBo = new GameScoreBo();
+            updateBo.setScoreId(score.getScoreId());
+            updateBo.setScoreRank(rank);
+            updateBo.setEventId(eventId);
+            updateBo.setProjectId(projectId);
+
+            updateByBo(updateBo);
+        }
+
+        return true;
+    }
+
+    /**
+     * 处理团体项目排名和积分计算
+     */
+    private Boolean handleTeamProjectRanking(List<GameScoreVo> allScores, String scoreValue, Long eventId, Long projectId) {
+        // 获取项目信息,确定排序方式
+        GameEventProjectVo project = gameEventProjectService.queryById(projectId);
+        if (project == null) {
+            log.error("项目不存在,projectId: {}", projectId);
+            return false;
+        }
+
+        String orderType = project.getOrderType();
+        log.info("团体项目排名计算,projectId: {}, orderType: {}", projectId, orderType);
+
+        // 按队伍ID分组,汇总每个队伍的积分
+        Map<Long, Integer> teamTotalPoints = new HashMap<>();
+        Map<Long, BigDecimal> teamBestPerformance = new HashMap<>();
+        Map<Long, String> teamNames = new HashMap<>();
+//        Map<Long, String> teamCodes = new HashMap<>();
+
+        for (GameScoreVo score : allScores) {
+            Long teamId = score.getTeamId();
+            if (teamId != null) {
+                // 累计队伍积分,处理null值
+                Integer currentPoints = score.getScorePoint() != null ? score.getScorePoint() : 0;
+                teamTotalPoints.merge(teamId, currentPoints, Integer::sum);
+
+                // 记录队伍最佳成绩
+                if (score.getTeamPerformance() != null && score.getTeamPerformance().compareTo(BigDecimal.ZERO) > 0) {
+                    BigDecimal currentBest = teamBestPerformance.get(teamId);
+                    if (currentBest == null || score.getTeamPerformance().compareTo(currentBest) > 0) {
+                        teamBestPerformance.put(teamId, score.getTeamPerformance());
+                    }
+                }
+
+                // 记录队伍信息
+                if (score.getTeamName() != null) {
+                    teamNames.put(teamId, score.getTeamName());
+                }
+//                if (score.getTeamCode() != null) {
+//                    teamCodes.put(teamId, score.getTeamCode());
+//                }
+            }
+        }
+
+        // 根据orderType决定队伍总积分排序方式
+        // orderType: 0-升序(积分越高排名越靠前),1-降序(积分越高排名越靠前)
+        List<Map.Entry<Long, Integer>> sortedTeams;
+        if ("0".equals(orderType)) {
+            // 升序:积分越高排名越靠前
+            sortedTeams = teamTotalPoints.entrySet().stream()
+                .sorted(Map.Entry.comparingByValue())
+                .collect(Collectors.toList());
+        } else {
+            // 降序:积分越高排名越靠前(默认)
+            sortedTeams = teamTotalPoints.entrySet().stream()
+                .sorted(Map.Entry.<Long, Integer>comparingByValue().reversed())
+                .collect(Collectors.toList());
+        }
+
+        // 解析积分分值
+        List<Integer> pointValues = Arrays.stream(scoreValue.split(","))
+            .map(String::trim)
+            .map(Integer::parseInt)
+            .collect(Collectors.toList());
+
+        // 根据orderType决定积分分配方式
+        if ("0".equals(orderType)) {
+            // 升序项目:成绩越小,积分分配越多
+            for (int i = 0; i < sortedTeams.size(); i++) {
+                Map.Entry<Long, Integer> teamEntry = sortedTeams.get(i);
+                Long teamId = teamEntry.getKey();
+                int rank = i + 1;
+                int points = i < pointValues.size() ? pointValues.get(i) : 0;
+
+                // 更新该队伍所有运动员的成绩记录
+                for (GameScoreVo score : allScores) {
+                    if (teamId.equals(score.getTeamId())) {
+                        GameScoreBo updateBo = new GameScoreBo();
+                        updateBo.setScoreId(score.getScoreId());
+                        updateBo.setScoreRank(rank);
+                        updateBo.setScorePoint(points); // 使用队伍排名对应的积分
+                        updateBo.setEventId(eventId);
+                        updateBo.setProjectId(projectId);
+
+                        updateByBo(updateBo);
+                    }
+                }
+            }
+        } else {
+            // 降序项目:成绩越大,积分分配越多
+            for (int i = 0; i < sortedTeams.size(); i++) {
+                Map.Entry<Long, Integer> teamEntry = sortedTeams.get(i);
+                Long teamId = teamEntry.getKey();
+                int rank = i + 1;
+                int points = i < pointValues.size() ? pointValues.get(i) : 0;
+
+                // 更新该队伍所有运动员的成绩记录
+                for (GameScoreVo score : allScores) {
+                    if (teamId.equals(score.getTeamId())) {
+                        GameScoreBo updateBo = new GameScoreBo();
+                        updateBo.setScoreId(score.getScoreId());
+                        updateBo.setScoreRank(rank);
+                        updateBo.setScorePoint(points); // 使用队伍排名对应的积分
+                        updateBo.setEventId(eventId);
+                        updateBo.setProjectId(projectId);
+
+                        updateByBo(updateBo);
+                    }
+                }
+            }
+        }
+
+        return true;
+    }
 }

+ 4 - 0
ruoyi-modules/ruoyi-game-event/src/main/java/org/dromara/system/service/impl/GameTeamServiceImpl.java

@@ -54,7 +54,11 @@ public class GameTeamServiceImpl implements IGameTeamService {
     @Override
     public GameTeamVo queryById(Long teamId) {
         GameTeamVo vo = baseMapper.selectVoById(teamId);
+        if(vo==null){
+            return null;
+        }
         if(vo.getAthleteValue()!=null){
+            log.info("teamId:{}, athleteValue:{}", teamId, vo.getAthleteValue());
             vo.setAthleteList(JSONUtil.toList(vo.getAthleteValue(), String.class));
         }
         return vo;

BIN
ruoyi-modules/ruoyi-game-event/src/main/resources/fonts/msyh.ttc


BIN
ruoyi-modules/ruoyi-game-event/src/main/resources/fonts/simsun.ttc


BIN
ruoyi-modules/ruoyi-game-event/src/main/resources/fonts/msyhl.ttc → ruoyi-modules/ruoyi-game-event/src/main/resources/fonts/simsun.ttf


BIN
ruoyi-modules/ruoyi-game-event/src/main/resources/fonts/msyhbd.ttc → ruoyi-modules/ruoyi-game-event/src/main/resources/fonts/yahei.ttf


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

@@ -12,4 +12,10 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         WHERE rank_score &lt;= 3
         ORDER BY ranked.project_id, ranked.score_value DESC;
     </select>
+
+    <select id="selectVoByAthleteIdAndProjectId" resultType="GameScoreVo">
+        SELECT *
+        FROM game_score
+        WHERE athlete_id = #{athleteId} AND project_id = #{projectId}
+    </select>
 </mapper>

+ 14 - 6
本周改动.md

@@ -1,7 +1,5 @@
 <h1>本周改动</h1>
 
-<h2>8.18</h2>
-
 <li>完成赛事与菜单的关联</li>
 <li>完成部分App端查询接口</li>
 <li>完成App端用户建议相关接口</li>
@@ -10,10 +8,6 @@
 <li>完善活动菜单管理的搜索条件区域功能</li>
 <li>增加全局默认赛事显示功能</li>
 <li>美化赛事操作列样式</li>
-
-
-<h2>8.19</h2>
-
 <li>完成用户反馈</li>
 <li>完成app端赛事相关的富文本编辑</li>
 <li>完善app端部分接口</li>
@@ -23,6 +17,20 @@
 <li>补充数据测试功能</li>
 <li>修改各模块列表项映射格式,方便后期维护</li>
 <li>修复成绩模块显示逻辑bug</li>
+<li>完善运动员模块与队伍的关联</li>
+<li>优化赛事界面布局和操作流程</li>
+<li>添加组别详细信息,如人数、组数、道数等</li>
+<li>实现分组自动计算和时间验证功能</li>
+<li>增加报名表导入校验-仅允许无报名数据的赛事进行导入</li>
+<li>号码对照表生成</li>
+<li>号码布开发</li>
+<li>优化成绩编辑界面,适配不同项目类型</li>
+<li>重构个人和团体项目的排名和积分计算方法</li>
+<li>生成二维码</li>
+<li>完成号码布开发导出zip</li>
+<li>增加权限校验</li>
+<li>修复部分bug</li>
+<li>增加字体</li>