Эх сурвалжийг харах

feat(game-event): 添加澳亚特设备成绩上传接口

- 新增 DistanceScoreUploadVo、ElectrometerDataItemVo、ElectrometerScoreUploadVo 等数据传输对象
- 实现 ElectrometerController、ElectrometerServiceImpl 和 IElectrometerService 接口
- 添加成绩上传和比赛信息获取的相关方法
- 优化成绩解析和验证逻辑,提高数据准确性
zhou 15 цаг өмнө
parent
commit
185fe19450

+ 1 - 0
pom.xml

@@ -105,6 +105,7 @@
                 <monitor.username>ruoyi</monitor.username>
                 <monitor.password>123456</monitor.password>
             </properties>
+
         </profile>
     </profiles>
 

+ 86 - 0
ruoyi-modules/ruoyi-game-event/src/main/java/org/dromara/system/controller/app/ElectrometerController.java

@@ -0,0 +1,86 @@
+package org.dromara.system.controller.app;
+
+import cn.dev33.satoken.annotation.SaIgnore;
+import lombok.RequiredArgsConstructor;
+import org.dromara.common.core.domain.R;
+import org.dromara.system.domain.vo.app.DistanceScoreUploadVo;
+import org.dromara.system.domain.vo.app.ElectrometerDataItemVo;
+import org.dromara.system.domain.vo.app.ElectrometerScoreUploadVo;
+import org.dromara.system.service.app.IElectrometerService;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+/**
+ * 澳亚特设备API
+ *
+ * @author zlt
+ * @date 2025-09-01
+ */
+@SaIgnore
+@Validated
+@RequiredArgsConstructor
+@RestController
+@RequestMapping("/api/electrometer")
+public class ElectrometerController {
+
+    private final IElectrometerService electrometerService;
+
+    /**
+     * 下载数据
+     *
+     * @param tjsdm 项目类型(1-径赛, 2-田赛)
+     * @param eventId 赛事ID (通过请求头 X-Dbname 传递)
+     * @return R<List<ElectrometerDataItemVo>>
+     */
+    @GetMapping("/aytmatchroadinfo")
+    public R<List<ElectrometerDataItemVo>> getMatchRoadInfo(
+            @RequestParam(value = "tjsdm", defaultValue = "1") String tjsdm,
+            @RequestHeader(value = "X-Dbname") Long eventId) {
+        try {
+            List<ElectrometerDataItemVo> result = electrometerService.getMatchRoadInfo(eventId, tjsdm);
+            return R.ok(result);
+        } catch (Exception e) {
+            return R.fail("下载数据失败:" + e.getMessage());
+        }
+    }
+
+    /**
+     * 计时类项目成绩上传(径赛)
+     *
+     * @param scoreUpload 成绩上传数据
+     * @param eventId 赛事ID (通过请求头 X-Dbname 传递)
+     * @return R<String> 上传结果
+     */
+    @PostMapping("/aytuploadscore/timer")
+    public R<String> uploadScore(
+        @RequestBody List<ElectrometerScoreUploadVo> scoreUpload,
+        @RequestHeader(value = "X-Dbname") Long eventId) {
+        try {
+            String result = electrometerService.uploadScore(eventId, scoreUpload);
+            return R.ok(result);
+        } catch (Exception e) {
+            return R.fail("计时类项目成绩上传失败:" + e.getMessage());
+        }
+    }
+
+    /**
+     * 远度距离类项目成绩上传
+     *
+     * @param scoreUpload 成绩上传数据
+     * @param eventId 赛事ID (通过请求头 X-Dbname 传递)
+     * @return R<String> 上传结果
+     */
+    @PostMapping("/aytuploadscore/distance")
+    public R<String> uploadScore(
+        @RequestBody DistanceScoreUploadVo scoreUpload,
+        @RequestHeader(value = "X-Dbname") Long eventId) {
+        try {
+            String result = electrometerService.uploadDistanceScore(eventId, scoreUpload);
+            return R.ok(result);
+        } catch (Exception e) {
+            return R.fail("远度距离类项目成绩上传失败:" + e.getMessage());
+        }
+    }
+}

+ 48 - 0
ruoyi-modules/ruoyi-game-event/src/main/java/org/dromara/system/domain/vo/app/DistanceScoreUploadVo.java

@@ -0,0 +1,48 @@
+package org.dromara.system.domain.vo.app;
+
+import lombok.Data;
+
+import java.math.BigDecimal;
+import java.util.List;
+
+/**
+ * 澳亚特设备成绩上传请求视图对象
+ *
+ * @author zlt
+ * @date 2025-09-01
+ */
+@Data
+public class DistanceScoreUploadVo {
+    /**
+     * 场次代码(分组ID)
+     */
+    private Long ccdm;
+
+    /**
+     * 组次
+     */
+    private Long groupIndex;
+
+    /**
+     * 成绩数据(格式:序号,后三轮序号,号码,姓名,成绩1,风速1,成绩2,风速2,成绩3,风速3,成绩4,风速4,成绩5,风速5,成绩6,风速6,名次|......)
+     */
+    private String cj;
+
+    @Data
+    public static class ScoreItem{
+        //序号列表
+        private List<String> indexList;
+
+        //运动员名称
+        private String athleteName;
+
+        //运动员编号
+        private String athleteCode;
+
+        //成绩列表
+        private List<BigDecimal> scoreList;
+
+        //名次
+        private Integer rank;
+    }
+}

+ 86 - 0
ruoyi-modules/ruoyi-game-event/src/main/java/org/dromara/system/domain/vo/app/ElectrometerDataItemVo.java

@@ -0,0 +1,86 @@
+package org.dromara.system.domain.vo.app;
+
+import lombok.Data;
+import java.io.Serializable;
+import java.util.Date;
+
+/**
+ * 澳亚特设备数据项视图对象
+ *
+ * @author zlt
+ * @date 2025-01-20
+ */
+@Data
+public class ElectrometerDataItemVo implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 项目类型(计算规则), 对应 game_event_project.score_rule
+     */
+    private String tjsDm;
+
+    /**
+     * 项目属性, 1-径赛, 2-田赛, 对应 score_rule 的计算规则
+     */
+    private String sx;
+
+    /**
+     * 号码(编号), 对应 game_athlete.athlete_code
+     */
+    private String hm;
+
+    /**
+     * 姓名, 对应 game_athlete.name
+     */
+    private String xm;
+
+    /**
+     * 性别, 男女, 对应 game_athlete.gender
+     */
+    private String xb;
+
+    /**
+     * 单位, 对应 game_athlete.unit
+     */
+    private String dw;
+
+    /**
+     * 组别名称, 甲组, 对应分组名称
+     */
+    private String zbMc;
+
+    /**
+     * 项目名称, 对应 game_event_project.project_name
+     */
+    private String xmMc;
+
+    /**
+     * 赛次名称(预赛, 复赛, 半决赛, 决赛), 对应比赛轮次
+     */
+    private String scMc;
+
+    /**
+     * 场次代码, 编排给的比赛分组唯一标识, 对应 game_athlete_competition_group.group_id
+     */
+    private String ccDm;
+
+    /**
+     * 组次, 比赛项目分组号, 对应分组信息
+     */
+    private String zc;
+
+    /**
+     * 道次, 对应分组中的道次
+     */
+    private String dc;
+
+    /**
+     * 比赛时间, 对应比赛时间
+     */
+    private Date tm;
+
+    /**
+     * 比赛单元, 对应比赛单元
+     */
+    private String bsDm;
+}

+ 62 - 0
ruoyi-modules/ruoyi-game-event/src/main/java/org/dromara/system/domain/vo/app/ElectrometerScoreUploadVo.java

@@ -0,0 +1,62 @@
+package org.dromara.system.domain.vo.app;
+
+import lombok.Data;
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.util.List;
+
+/**
+ * 澳亚特设备成绩上传请求视图对象
+ *
+ * @author zlt
+ * @date 2025-09-01
+ */
+@Data
+public class ElectrometerScoreUploadVo implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 场次代码(分组ID)
+     */
+    private Long ccdm;
+
+    /**
+     * 运动员编号
+     */
+    private String athleteCode;
+
+    /**
+     * 风速
+     */
+    private String windSpeed;
+
+    /**
+     * 反应时
+     */
+    private String reactionTime;
+
+    /**
+     * 组次
+     */
+    private Long groupIndex;
+
+    /**
+     * 道次
+     */
+    private Long trackIndex;
+
+    /**
+     * 成绩(以分钟为单位)
+     */
+    private BigDecimal score;
+
+    /**
+     * 名次
+     */
+    private Integer rank;
+
+    /**
+     * 状态
+     */
+    private String status;
+}

+ 14 - 0
ruoyi-modules/ruoyi-game-event/src/main/java/org/dromara/system/mapper/app/ElectrometerMapper.java

@@ -0,0 +1,14 @@
+package org.dromara.system.mapper.app;
+
+import org.dromara.system.domain.vo.app.ElectrometerDataItemVo;
+import org.apache.ibatis.annotations.Param;
+import java.util.List;
+
+/**
+ * 澳亚特设备数据Mapper接口
+ *
+ * @author zlt
+ * @date 2025-01-20
+ */
+public interface ElectrometerMapper {
+}

+ 43 - 0
ruoyi-modules/ruoyi-game-event/src/main/java/org/dromara/system/service/app/IElectrometerService.java

@@ -0,0 +1,43 @@
+package org.dromara.system.service.app;
+
+import org.dromara.system.domain.vo.app.DistanceScoreUploadVo;
+import org.dromara.system.domain.vo.app.ElectrometerDataItemVo;
+import org.dromara.system.domain.vo.app.ElectrometerScoreUploadVo;
+
+import java.util.List;
+
+/**
+ * 澳亚特设备服务接口
+ *
+ * @author zlt
+ * @date 2025-01-20
+ */
+public interface IElectrometerService {
+
+    /**
+     * 获取比赛道路信息
+     *
+     * @param eventId 赛事ID
+     * @param tjsdm 项目类型(1-径赛, 2-田赛)
+     * @return 比赛道路信息列表
+     */
+    List<ElectrometerDataItemVo> getMatchRoadInfo(Long eventId, String tjsdm);
+
+    /**
+     * 上传计时类项目成绩
+     *
+     * @param eventId 赛事ID
+     * @param scoreUpload 成绩上传数据
+     * @return 上传结果
+     */
+    String uploadScore(Long eventId, List<ElectrometerScoreUploadVo> scoreUpload);
+
+    /**
+     * 上传远度距离类项目成绩
+     *
+     * @param eventId 赛事ID
+     * @param scoreUpload 成绩上传数据
+     * @return 上传结果
+     */
+    String uploadDistanceScore(Long eventId, DistanceScoreUploadVo scoreUpload);
+}

+ 414 - 0
ruoyi-modules/ruoyi-game-event/src/main/java/org/dromara/system/service/impl/app/ElectrometerServiceImpl.java

@@ -0,0 +1,414 @@
+package org.dromara.system.service.impl.app;
+
+import com.esotericsoftware.minlog.Log;
+import lombok.RequiredArgsConstructor;
+import org.dromara.system.domain.*;
+import org.dromara.system.domain.vo.GameAthleteVo;
+import org.dromara.system.domain.vo.app.DistanceScoreUploadVo;
+import org.dromara.system.domain.vo.app.ElectrometerDataItemVo;
+import org.dromara.system.domain.vo.app.ElectrometerScoreUploadVo;
+import org.dromara.system.mapper.*;
+import org.dromara.system.service.app.IElectrometerService;
+import org.springframework.stereotype.Service;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.math.BigDecimal;
+import java.util.*;
+import java.util.stream.Collectors;
+
+/**
+ * 澳亚特设备服务实现
+ *
+ * @author zlt
+ * @date 2025-01-20
+ */
+@RequiredArgsConstructor
+@Service
+public class ElectrometerServiceImpl implements IElectrometerService {
+
+    private final GameAthleteMapper gameAthleteMapper;
+    private final GameEventProjectMapper gameEventProjectMapper;
+    private final GameAthleteCompetitionGroupMapper gameAthleteCompetitionGroupMapper;
+    private final GameEventGroupMapper gameEventGroupMapper;
+    private final GameScoreMapper gameScoreMapper;
+
+    /**
+     * 获取比赛道路信息
+     *
+     * @param eventId 赛事ID
+     * @param tjsdm 项目类型(1-径赛, 2-田赛)
+     * @return 比赛道路信息列表
+     */
+    @Override
+    public List<ElectrometerDataItemVo> getMatchRoadInfo(Long eventId, String tjsdm) {
+        // 1. 查询运动员信息
+        LambdaQueryWrapper<GameAthlete> athleteWrapper = Wrappers.lambdaQuery(GameAthlete.class)
+                .eq(GameAthlete::getEventId, eventId)
+                .eq(GameAthlete::getStatus, "0")
+                .eq(GameAthlete::getDelFlag, "0");
+        List<GameAthlete> athletes = gameAthleteMapper.selectList(athleteWrapper);
+
+        if (athletes.isEmpty()) {
+            return List.of();
+        }
+
+        // 2. 查询项目信息
+        LambdaQueryWrapper<GameEventProject> projectWrapper = Wrappers.lambdaQuery(GameEventProject.class)
+                .eq(GameEventProject::getEventId, eventId)
+                .eq(GameEventProject::getScoreRule,tjsdm);
+
+        List<GameEventProject> projects = gameEventProjectMapper.selectList(projectWrapper);
+        Map<Long, GameEventProject> projectMap = projects.stream()
+                .collect(Collectors.toMap(GameEventProject::getProjectId, p -> p));
+
+        // 3. 查询运动员比赛分组信息
+        List<Long> athleteIds = athletes.stream().map(GameAthlete::getAthleteId).collect(Collectors.toList());
+        LambdaQueryWrapper<GameAthleteCompetitionGroup> groupWrapper = Wrappers.lambdaQuery(GameAthleteCompetitionGroup.class)
+                .in(GameAthleteCompetitionGroup::getAthleteId, athleteIds);
+        List<GameAthleteCompetitionGroup> competitionGroups = gameAthleteCompetitionGroupMapper.selectList(groupWrapper);
+        Map<Long, GameAthleteCompetitionGroup> groupMap = competitionGroups.stream()
+                .collect(Collectors.toMap(GameAthleteCompetitionGroup::getAthleteId, g -> g));
+
+        // 4. 查询分组信息
+        List<Long> groupIds = competitionGroups.stream().map(GameAthleteCompetitionGroup::getGroupId).collect(Collectors.toList());
+        Map<Long, GameEventGroup> eventGroupMap;
+        if (!groupIds.isEmpty()) {
+            LambdaQueryWrapper<GameEventGroup> eventGroupWrapper = Wrappers.lambdaQuery(GameEventGroup.class)
+                    .in(GameEventGroup::getGroupId, groupIds);
+            List<GameEventGroup> eventGroups = gameEventGroupMapper.selectList(eventGroupWrapper);
+            eventGroupMap = eventGroups.stream()
+                    .collect(Collectors.toMap(GameEventGroup::getGroupId, g -> g));
+        } else {
+            eventGroupMap = Map.of();
+        }
+
+        // 5. 组装数据
+//        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMddHHmmss");
+        return athletes.stream().map(athlete -> {
+            ElectrometerDataItemVo item = new ElectrometerDataItemVo();
+
+            // 基本信息
+            item.setHm(athlete.getAthleteCode());
+            item.setXm(athlete.getName());
+            item.setXb(athlete.getGender());
+            item.setDw(athlete.getUnit());
+
+            // 获取比赛分组信息
+            GameAthleteCompetitionGroup competitionGroup = groupMap.get(athlete.getAthleteId());
+            if (competitionGroup != null) {
+                item.setCcDm(String.valueOf(competitionGroup.getGroupId()));
+                item.setZc(String.valueOf(competitionGroup.getGroupIndex()));
+                item.setDc(String.valueOf(competitionGroup.getTrackIndex()));
+
+                // 组别信息
+                if (!eventGroupMap.isEmpty()) {
+                    GameEventGroup eventGroup = eventGroupMap.get(competitionGroup.getGroupId());
+                    if (eventGroup != null) {
+                        item.setZbMc(eventGroup.getGroupName());
+                        if (eventGroup.getBeginTime() != null) {
+                            item.setTm(eventGroup.getBeginTime());
+                        }
+                    }
+                }
+
+                // 项目信息 - 根据比赛分组中的项目ID查找对应项目
+                GameEventProject project = projectMap.get(competitionGroup.getProjectId());
+                if (project != null) {
+                    item.setXmMc(project.getProjectName());
+                    item.setTjsDm(project.getProjectType());
+                    item.setSx(project.getScoreRule()); // 计算规则-项目属性
+                    if (project.getStartTime() != null) {
+                        item.setTm(project.getStartTime());
+                    }
+                }
+            }
+
+            return item;
+        }).collect(Collectors.toList());
+    }
+
+    /**
+     * 上传计时类项目成绩
+     *
+     * @param eventId 赛事ID
+     * @param scoreUpload 成绩上传数据
+     * @return 上传结果
+     */
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public String uploadScore(Long eventId, List<ElectrometerScoreUploadVo> scoreUpload) {
+        try {
+//            Log.info("开始上传成绩,赛事ID: {}, 场次代码: {}", eventId, scoreUpload.getCcDm());
+            // 5. 保存成绩数据
+            int successCount = 0;
+            for (ElectrometerScoreUploadVo scoreItem : scoreUpload) {
+                // 2. 根据场次代码获取分组信息
+                GameAthleteCompetitionGroup groupInfo = gameAthleteCompetitionGroupMapper.selectById(scoreItem.getCcdm());
+                if (groupInfo == null) {
+                    return "未找到对应的比赛分组信息";
+                }
+                // 3. 获取项目信息
+                GameEventProject project = gameEventProjectMapper.selectById(groupInfo.getProjectId());
+                if (project == null) {
+                    return "未找到对应的项目信息";
+                }
+                // 4. 验证成绩数据与分组信息的一致性
+                String validationResult = validateScoreData(scoreItem, groupInfo);
+                if (!"OK".equals(validationResult)) {
+                    return validationResult;
+                }
+                if (saveScoreRecord(eventId, project, scoreItem)) {
+                    successCount++;
+                }
+            }
+//            Log.info("成绩上传完成,成功保存 {} 条记录", successCount);
+            return String.format("成绩上传成功,共保存 %d 条记录", successCount);
+
+        } catch (Exception e) {
+            Log.error("成绩上传失败", e);
+            throw new RuntimeException("成绩上传失败: " + e.getMessage());
+        }
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public String uploadDistanceScore(Long eventId, DistanceScoreUploadVo scoreUpload) {
+        try{
+            //根据场次代码获取分组信息
+            GameAthleteCompetitionGroup groupInfo = gameAthleteCompetitionGroupMapper.selectById(scoreUpload.getCcdm());
+            if (groupInfo == null) {
+                return "未找到对应的比赛分组信息";
+            }
+            //根据分组信息获取项目信息
+            GameEventProject project = gameEventProjectMapper.selectById(groupInfo.getProjectId());
+            if (project == null) {
+                return "未找到对应的项目";
+            }
+            //根据分组信息获取运动员信息
+            List<DistanceScoreUploadVo.ScoreItem> scoreList = parseScoreData(scoreUpload.getCj());
+            GameAthlete athlete = gameAthleteMapper.selectById(groupInfo.getAthleteId());
+            if (athlete == null) {
+                return "未找到对应运动员";
+            }
+            int successCount = saveScoreRecord(eventId, project, scoreList);
+            if(successCount > 0){
+                return String.format("成绩上传成功,共保存 %d 条记录", successCount);
+            }else{
+                return "成绩上传失败";
+            }
+
+        } catch (Exception e) {
+            throw new RuntimeException("成绩上传失败: " + e.getMessage());
+        }
+    }
+
+
+    /**
+     * 解析成绩数据字符串
+     */
+    private List<DistanceScoreUploadVo.ScoreItem> parseScoreData(String scoreData) {
+        List<DistanceScoreUploadVo.ScoreItem> scoreList = new ArrayList<>();
+
+        if (scoreData == null || scoreData.trim().isEmpty()) {
+            return scoreList;
+        }
+
+        String[] items = scoreData.split("\\|");
+        for (String item : items) {
+            if (item.trim().isEmpty()) {
+                continue;
+            }
+
+            String[] fields = item.split(",");
+            // 添加更严格的数据验证
+            if (fields.length >= 15 && !fields[2].trim().isEmpty() && !fields[3].trim().isEmpty()) {
+                try {
+                    DistanceScoreUploadVo.ScoreItem scoreItem = new DistanceScoreUploadVo.ScoreItem();
+                    List<String> indexList = new ArrayList<>();
+                    indexList.add(fields[0]); // 组次
+                    indexList.add(fields[1]); // 道次
+                    scoreItem.setIndexList(indexList);
+                    scoreItem.setAthleteCode(fields[2]); // 运动员编号
+                    scoreItem.setAthleteName(fields[3]); // 姓名
+
+                    // 安全地解析成绩数据
+                    List<BigDecimal> scores = new ArrayList<>();
+                    for (int i = 4; i < fields.length - 1; i += 2) {
+                        if (i < fields.length && !fields[i].trim().isEmpty()) {
+                            try {
+                                scores.add(BigDecimal.valueOf(Double.parseDouble(fields[i])));
+                            } catch (NumberFormatException e) {
+                                // 忽略无效的成绩数据
+                                Log.warn("解析成绩数据失败: {}", fields[i], e);
+                            }
+                        }
+                    }
+                    scoreItem.setScoreList(scores);
+
+                    // 安全地解析排名
+                    try {
+                        scoreItem.setRank(Integer.valueOf(fields[fields.length-1]));
+                    } catch (NumberFormatException e) {
+                        Log.warn("解析排名失败: {}", fields[fields.length-1], e);
+                        scoreItem.setRank(0); // 默认排名
+                    }
+
+                    scoreList.add(scoreItem);
+                } catch (Exception e) {
+                    // 记录错误但继续处理其他数据
+                    Log.warn("解析成绩数据失败: {}", item, e);
+                }
+            }
+        }
+
+        return scoreList;
+    }
+
+    /**
+     * 验证成绩数据与分组信息的一致性
+     */
+    private String validateScoreData(ElectrometerScoreUploadVo scoreItem, GameAthleteCompetitionGroup groupInfo) {
+        // 验证场次代码是否一致
+        if (!scoreItem.getTrackIndex().equals(groupInfo.getTrackIndex())) {
+            return "场次代码不一致";
+        }
+        // 验证组次是否一致
+        if (!scoreItem.getGroupIndex().equals(groupInfo.getGroupIndex())) {
+            return "组次不一致";
+        }
+        // 验证运动员编号是否一致
+        if (!scoreItem.getAthleteCode().equals(groupInfo.getAthleteCode())) {
+            return "运动员编号不一致";
+        }
+        return "OK";
+    }
+
+
+    /**
+     * 保存计时类项目成绩记录
+     */
+    private boolean saveScoreRecord(Long eventId, GameEventProject project, ElectrometerScoreUploadVo scoreItem) {
+        try {
+            // 根据运动员编号查找运动员ID
+            LambdaQueryWrapper<GameAthlete> athleteWrapper = Wrappers.lambdaQuery(GameAthlete.class)
+                .eq(GameAthlete::getEventId, eventId)
+                .eq(GameAthlete::getAthleteCode, scoreItem.getAthleteCode())
+                .eq(GameAthlete::getStatus, "0")
+                .eq(GameAthlete::getDelFlag, "0");
+            GameAthlete athlete = gameAthleteMapper.selectOne(athleteWrapper);
+
+            if (athlete == null) {
+               Log.warn("未找到运动员: {}", scoreItem.getAthleteCode());
+                return false;
+            }
+
+            // 检查是否已存在成绩记录
+            LambdaQueryWrapper<GameScore> scoreWrapper = Wrappers.lambdaQuery(GameScore.class)
+                .eq(GameScore::getEventId, eventId)
+                .eq(GameScore::getProjectId, project.getProjectId())
+                .eq(GameScore::getAthleteId, athlete.getAthleteId());
+
+            GameScore existingScore = gameScoreMapper.selectOne(scoreWrapper);
+
+            if (existingScore != null) {
+                // 更新现有记录
+                existingScore.setIndividualPerformance(scoreItem.getScore());
+                existingScore.setScoreRank(scoreItem.getRank());
+                existingScore.setStatusFlag("1"); // 已处理
+                existingScore.setRemark("电计设备上传");
+
+                return gameScoreMapper.updateById(existingScore) > 0;
+            } else {
+                // 创建新记录
+                GameScore newScore = new GameScore();
+                newScore.setEventId(eventId);
+                newScore.setProjectId(project.getProjectId());
+                newScore.setAthleteId(athlete.getAthleteId());
+                newScore.setTeamId(athlete.getTeamId());
+                newScore.setIndividualPerformance(scoreItem.getScore());
+                newScore.setScoreRank(scoreItem.getRank());
+                newScore.setScoreType("individual");
+                newScore.setStatusFlag("1"); // 已处理
+                newScore.setStatus("0"); // 正常
+                newScore.setRemark("电计设备上传");
+                return gameScoreMapper.insert(newScore) > 0;
+            }
+
+        } catch (Exception e) {
+//            log.error("保存成绩记录失败: {}", e.getMessage(), e);
+            return false;
+        }
+    }
+
+    /**
+     * 保存远度距离类项目成绩记录
+     */
+    private int saveScoreRecord(Long eventId, GameEventProject project, List<DistanceScoreUploadVo.ScoreItem> scoreList) {
+        try {
+            int successCount = 0;
+            for (DistanceScoreUploadVo.ScoreItem scoreItem : scoreList) {
+                // 根据运动员编号查找运动员ID
+                LambdaQueryWrapper<GameAthlete> athleteWrapper = Wrappers.lambdaQuery(GameAthlete.class)
+                    .eq(GameAthlete::getEventId, eventId)
+                    .eq(GameAthlete::getAthleteCode, scoreItem.getAthleteCode())
+                    .eq(GameAthlete::getStatus, "0")
+                    .eq(GameAthlete::getDelFlag, "0");
+                GameAthlete athlete = gameAthleteMapper.selectOne(athleteWrapper);
+
+                if (athlete == null) {
+                    continue;
+                }
+
+                // 检查是否已存在成绩记录
+                LambdaQueryWrapper<GameScore> scoreWrapper = Wrappers.lambdaQuery(GameScore.class)
+                    .eq(GameScore::getEventId, eventId)
+                    .eq(GameScore::getProjectId, project.getProjectId())
+                    .eq(GameScore::getAthleteId, athlete.getAthleteId());
+
+                GameScore existingScore = gameScoreMapper.selectOne(scoreWrapper);
+
+                if (existingScore != null) {
+                    // 更新现有记录 - 远度距离类项目可能有多次成绩,取最好成绩
+                    BigDecimal bestScore = scoreItem.getScoreList().stream()
+                        .max(BigDecimal::compareTo)
+                        .orElse(BigDecimal.ZERO);
+                    existingScore.setIndividualPerformance(bestScore);
+                    existingScore.setScoreRank(scoreItem.getRank());
+                    existingScore.setStatusFlag("1");
+                    existingScore.setRemark("电计设备上传-田赛");
+
+                    if (gameScoreMapper.updateById(existingScore) > 0) {
+                        successCount++;
+                    }
+                } else {
+                    // 创建新记录
+                    GameScore newScore = new GameScore();
+                    newScore.setEventId(eventId);
+                    newScore.setProjectId(project.getProjectId());
+                    newScore.setAthleteId(athlete.getAthleteId());
+                    newScore.setTeamId(athlete.getTeamId());
+
+                    // 远度距离类项目取最好成绩
+                    BigDecimal bestScore = scoreItem.getScoreList().stream()
+                        .max(BigDecimal::compareTo)
+                        .orElse(BigDecimal.ZERO);
+                    newScore.setIndividualPerformance(bestScore);
+                    newScore.setScoreRank(scoreItem.getRank());
+                    newScore.setScoreType("individual");
+                    newScore.setStatusFlag("1");
+                    newScore.setStatus("0");
+                    newScore.setRemark("电计设备上传-田赛");
+
+                    if (gameScoreMapper.insert(newScore) > 0) {
+                        successCount++;
+                    }
+                }
+            }
+            return successCount;
+        } catch (Exception e) {
+            return 0;
+        }
+    }
+}