소스 검색

feat(system): 优化数据结构和实现裁判二维码生成

- 将多个地方的 String 类型改为 Long 类型,提升数据准确性
- 新增裁判二维码生成相关功能- 优化项目和裁判关联逻辑
- 调整包名以提高代码整洁度
zhou 1 개월 전
부모
커밋
4aa5aadf7d
22개의 변경된 파일341개의 추가작업 그리고 54개의 파일을 삭제
  1. 1 0
      pom.xml
  2. 42 1
      ruoyi-modules/ruoyi-game-event/src/main/java/org/dromara/system/controller/GameRefereeController.java
  3. 18 0
      ruoyi-modules/ruoyi-game-event/src/main/java/org/dromara/system/domain/app/QRCodeReferee.java
  4. 1 1
      ruoyi-modules/ruoyi-game-event/src/main/java/org/dromara/system/domain/bo/GameAthleteBo.java
  5. 2 2
      ruoyi-modules/ruoyi-game-event/src/main/java/org/dromara/system/domain/bo/GameEventProjectBo.java
  6. 1 1
      ruoyi-modules/ruoyi-game-event/src/main/java/org/dromara/system/domain/bo/GameRefereeBo.java
  7. 1 1
      ruoyi-modules/ruoyi-game-event/src/main/java/org/dromara/system/domain/bo/GameTeamBo.java
  8. 1 1
      ruoyi-modules/ruoyi-game-event/src/main/java/org/dromara/system/domain/vo/GameAthleteVo.java
  9. 6 2
      ruoyi-modules/ruoyi-game-event/src/main/java/org/dromara/system/domain/vo/GameEventProjectVo.java
  10. 1 1
      ruoyi-modules/ruoyi-game-event/src/main/java/org/dromara/system/domain/vo/GameRefereeVo.java
  11. 1 1
      ruoyi-modules/ruoyi-game-event/src/main/java/org/dromara/system/domain/vo/GameTeamVo.java
  12. 3 1
      ruoyi-modules/ruoyi-game-event/src/main/java/org/dromara/system/mapper/GameRefereeMapper.java
  13. 1 1
      ruoyi-modules/ruoyi-game-event/src/main/java/org/dromara/system/service/IGameEventProjectService.java
  14. 1 1
      ruoyi-modules/ruoyi-game-event/src/main/java/org/dromara/system/service/dbbackup/DatabaseBackupRestoreService.java
  15. 6 6
      ruoyi-modules/ruoyi-game-event/src/main/java/org/dromara/system/service/impl/GameAthleteServiceImpl.java
  16. 1 1
      ruoyi-modules/ruoyi-game-event/src/main/java/org/dromara/system/service/impl/GameEventGroupServiceImpl.java
  17. 5 5
      ruoyi-modules/ruoyi-game-event/src/main/java/org/dromara/system/service/impl/GameEventProjectServiceImpl.java
  18. 160 12
      ruoyi-modules/ruoyi-game-event/src/main/java/org/dromara/system/service/impl/GameRefereeServiceImpl.java
  19. 4 4
      ruoyi-modules/ruoyi-game-event/src/main/java/org/dromara/system/service/impl/GameTeamServiceImpl.java
  20. 11 11
      ruoyi-modules/ruoyi-game-event/src/main/java/org/dromara/system/service/impl/app/PhysicalTestServiceImpl.java
  21. 1 1
      ruoyi-modules/ruoyi-game-event/src/main/java/org/dromara/system/utils/FilteredCommentInputStream.java
  22. 73 0
      ruoyi-modules/ruoyi-game-event/src/main/java/org/dromara/system/utils/QRCodeUtils.java

+ 1 - 0
pom.xml

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

+ 42 - 1
ruoyi-modules/ruoyi-game-event/src/main/java/org/dromara/system/controller/GameRefereeController.java

@@ -6,6 +6,7 @@ import lombok.RequiredArgsConstructor;
 import jakarta.servlet.http.HttpServletResponse;
 import jakarta.validation.constraints.*;
 import cn.dev33.satoken.annotation.SaCheckPermission;
+import org.dromara.system.domain.app.QRCodeReferee;
 import org.springframework.web.bind.annotation.*;
 import org.springframework.validation.annotation.Validated;
 import org.dromara.common.idempotent.annotation.RepeatSubmit;
@@ -21,6 +22,8 @@ import org.dromara.system.domain.vo.GameRefereeVo;
 import org.dromara.system.domain.bo.GameRefereeBo;
 import org.dromara.system.service.IGameRefereeService;
 import org.dromara.common.mybatis.core.page.TableDataInfo;
+import org.dromara.system.utils.QRCodeUtils;
+import com.fasterxml.jackson.databind.ObjectMapper;
 
 /**
  * 裁判
@@ -35,6 +38,8 @@ import org.dromara.common.mybatis.core.page.TableDataInfo;
 public class GameRefereeController extends BaseController {
 
     private final IGameRefereeService gameRefereeService;
+    private final QRCodeUtils qrCodeUtils;
+    private final ObjectMapper objectMapper;
 
     /**
      * 查询裁判列表
@@ -103,7 +108,6 @@ public class GameRefereeController extends BaseController {
         return toAjax(gameRefereeService.deleteWithValidByIds(List.of(refereeIds), true));
     }
 
-
     /**
      * 查询裁判数量
      * @return
@@ -113,4 +117,41 @@ public class GameRefereeController extends BaseController {
         return R.ok(gameRefereeService.countReferee());
     }
 
+    /**
+     * 生成裁判二维码
+     *
+     * @param refereeId 裁判ID
+     * @return 二维码Base64数据
+     */
+    @SaCheckPermission("system:gameReferee:edit")
+    @GetMapping("/qrcode/{refereeId}")
+    public R<String> generateQRCode(@NotNull(message = "裁判ID不能为空") @PathVariable Long refereeId) {
+        try {
+            // 获取裁判信息
+            GameRefereeVo referee = gameRefereeService.queryById(refereeId);
+            if (referee == null) {
+                return R.fail("裁判信息不存在");
+            }
+
+            // 构建二维码数据
+            QRCodeReferee qrData = new QRCodeReferee();
+            qrData.setEventId(referee.getEventId());
+            qrData.setRefereeId(referee.getRefereeId());
+            qrData.setName(referee.getName());
+            qrData.setAccount(referee.getAccount());
+            qrData.setPassword(referee.getPassword());
+            qrData.setProjectList(referee.getProjectList2());
+
+            // 将数据转换为JSON字符串
+            String qrContent = objectMapper.writeValueAsString(qrData);
+
+            // 生成二维码
+            String qrCodeBase64 = qrCodeUtils.generateQRCodeBase64(qrContent);
+
+            return R.ok("二维码生成成功",qrCodeBase64);
+        } catch (Exception e) {
+            return R.fail("生成二维码失败: " + e.getMessage());
+        }
+    }
+
 }

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

@@ -0,0 +1,18 @@
+package org.dromara.system.domain.app;
+
+import lombok.Data;
+
+import java.util.List;
+
+/**
+ * 裁判二维码数据对象
+ */
+@Data
+public class QRCodeReferee {
+    private Long eventId;
+    private Long refereeId;
+    private String name;
+    private String account;
+    private String password;
+    private List<Long> projectList;
+}

+ 1 - 1
ruoyi-modules/ruoyi-game-event/src/main/java/org/dromara/system/domain/bo/GameAthleteBo.java

@@ -124,7 +124,7 @@ public class GameAthleteBo extends BaseEntity {
      */
 //    @NotBlank(message = "参与项目列表不能为空", groups = { AddGroup.class, EditGroup.class })
     private String projectValue;
-    private List<String> projectList;
+    private List<Long> projectList;
 
     /**
      * 状态(0正常 1停用)

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

@@ -23,7 +23,7 @@ import com.fasterxml.jackson.annotation.JsonFormat;
  */
 @Data
 @EqualsAndHashCode(callSuper = true)
-@AutoMapper(target = GameEventProject.class, reverseConvertGenerate = false)
+@AutoMapper(target = GameEventProject.class)
 public class GameEventProjectBo extends BaseEntity {
 
     /**
@@ -66,7 +66,7 @@ public class GameEventProjectBo extends BaseEntity {
     /**
      * 裁判组员集合
      */
-    private List<String> refereeGroups;
+    private List<Long> refereeGroups;
 
     /**
      * 比赛场地

+ 1 - 1
ruoyi-modules/ruoyi-game-event/src/main/java/org/dromara/system/domain/bo/GameRefereeBo.java

@@ -59,7 +59,7 @@ public class GameRefereeBo extends BaseEntity {
      * 负责的赛事项目
      */
     private String projectList;
-    private List<String> projectList2;
+    private List<Long> projectList2;
 
     /**
      * 裁判码

+ 1 - 1
ruoyi-modules/ruoyi-game-event/src/main/java/org/dromara/system/domain/bo/GameTeamBo.java

@@ -61,7 +61,7 @@ public class GameTeamBo extends BaseEntity {
      */
 //    @NotBlank(message = "队员列表不能为空", groups = { AddGroup.class, EditGroup.class })
     private String athleteValue;
-    private List<String> athleteList;
+    private List<Long> athleteList;
 
     /**
      * 参与项目列表

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

@@ -131,7 +131,7 @@ public class GameAthleteVo implements Serializable {
     @ExcelProperty(value = "参与项目列表")
     private String projectValue;
 
-    private List<String> projectList;
+    private List<Long> projectList;
 
     /**
      * 状态(0正常 1停用)

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

@@ -3,6 +3,7 @@ package org.dromara.system.domain.vo;
 import java.util.Date;
 import com.fasterxml.jackson.annotation.JsonFormat;
 import org.dromara.system.domain.GameEventProject;
+import org.dromara.system.domain.bo.GameEventProjectBo;
 import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
 import cn.idev.excel.annotation.ExcelProperty;
 import org.dromara.common.excel.annotation.ExcelDictFormat;
@@ -19,6 +20,9 @@ import java.util.List;
 /**
  * 赛事项目视图对象 game_event_project
  *
+ * 该类用于表示赛事项目的视图数据,包含赛事项目的基本信息、时间信息、
+ * 参赛信息、评分规则等。该类仅映射到GameEventProject实体类。
+ *
  * @author zlt
  * @date 2025-07-30
  */
@@ -73,7 +77,7 @@ public class GameEventProjectVo implements Serializable {
     /**
      * 裁判组员
      */
-    private List<String> refereeGroups;
+    private List<Long> refereeGroups;
 
     /**
      * 比赛场地
@@ -168,4 +172,4 @@ public class GameEventProjectVo implements Serializable {
     private String remark;
 
 
-}
+}

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

@@ -67,7 +67,7 @@ public class GameRefereeVo implements Serializable {
      * 负责的赛事项目
      */
     private String projectList;
-    private List<String> projectList2;
+    private List<Long> projectList2;
 
     /**
      * 裁判码

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

@@ -66,7 +66,7 @@ public class GameTeamVo implements Serializable {
      */
 //    @ExcelProperty(value = "队员列表")
     private String athleteValue;
-    private List<String> athleteList;
+    private List<Long> athleteList;
 
     /**
      * 参与项目列表

+ 3 - 1
ruoyi-modules/ruoyi-game-event/src/main/java/org/dromara/system/mapper/GameRefereeMapper.java

@@ -3,6 +3,7 @@ package org.dromara.system.mapper;
 import org.dromara.system.domain.GameReferee;
 import org.dromara.system.domain.vo.GameRefereeVo;
 import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
+import org.apache.ibatis.annotations.Mapper;
 
 /**
  * 裁判Mapper接口
@@ -10,6 +11,7 @@ import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
  * @author zlt
  * @date 2025-07-30
  */
+@Mapper
 public interface GameRefereeMapper extends BaseMapperPlus<GameReferee, GameRefereeVo> {
 
-}
+}

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

@@ -70,7 +70,7 @@ public interface IGameEventProjectService {
      */
     Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
 
-    List<GameEventProjectVo> listProjectsByEventIdAndProjectIndex(Long eventId, List<String> projectIds);
+    List<GameEventProjectVo> listProjectsByEventIdAndProjectIndex(Long eventId, List<Long> projectIds);
 
     Long countEventProject();
 

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

@@ -3,7 +3,7 @@ package org.dromara.system.service.dbbackup;
 import jakarta.servlet.http.HttpServletResponse;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.ibatis.jdbc.ScriptRunner;
-import org.dromara.system.util.FilteredCommentInputStream;
+import org.dromara.system.utils.FilteredCommentInputStream;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.stereotype.Service;

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

@@ -149,7 +149,7 @@ public class GameAthleteServiceImpl implements IGameAthleteService {
         Optional.ofNullable(vo.getProjectValue())
             .filter(StringUtils::isNotBlank)
             .ifPresent(projectValue -> {
-                List<String> projects = JSONUtil.toList(projectValue, String.class);
+                List<Long> projects = JSONUtil.toList(projectValue, Long.class);
                 vo.setProjectList(projects);
             });
         return vo;
@@ -180,7 +180,7 @@ public class GameAthleteServiceImpl implements IGameAthleteService {
                     .filter(StringUtils::isNotBlank)
                     .ifPresent(projectValue -> {
 //                        String[] projectIds = projectValue.split(",");
-                        List<String> projectIds = JSONUtil.toList(projectValue, String.class);
+                        List<Long> projectIds = JSONUtil.toList(projectValue, Long.class);
                         if (CollUtil.isNotEmpty(projectIds)) {
                             List<GameEventProjectVo> projects =
                                 gameEventProjectService.listProjectsByEventIdAndProjectIndex(
@@ -226,7 +226,7 @@ public class GameAthleteServiceImpl implements IGameAthleteService {
             Optional.ofNullable(vo.getProjectValue())
                 .filter(StringUtils::isNotBlank)
                 .ifPresent(projectValue -> {
-                    List<String> projects = JSONUtil.toList(projectValue, String.class);
+                    List<Long> projects = JSONUtil.toList(projectValue, Long.class);
                     vo.setProjectList(projects);
                 });
         });
@@ -416,7 +416,7 @@ public class GameAthleteServiceImpl implements IGameAthleteService {
         );
         list.forEach(vo -> {
             if (vo.getProjectValue() != null) {
-                vo.setProjectList(JSONUtil.toList(vo.getProjectValue(), String.class));
+                vo.setProjectList(JSONUtil.toList(vo.getProjectValue(), Long.class));
             }
         });
         return list;
@@ -444,7 +444,7 @@ public class GameAthleteServiceImpl implements IGameAthleteService {
         allAthletes.forEach(athlete -> {
             if (athlete.getProjectValue() != null) {
                 try {
-                    athlete.setProjectList(JSONUtil.toList(athlete.getProjectValue(), String.class));
+                    athlete.setProjectList(JSONUtil.toList(athlete.getProjectValue(), Long.class));
                     log.debug("运动员 {} 的项目列表转换成功: {}", athlete.getName(), athlete.getProjectList());
                 } catch (Exception e) {
                     log.warn("转换运动员 {} 的项目列表失败: {}", athlete.getName(), e);
@@ -460,7 +460,7 @@ public class GameAthleteServiceImpl implements IGameAthleteService {
         List<GameAthleteVo> filteredAthletes = allAthletes.stream()
             .filter(athlete -> {
                 if (CollectionUtils.isNotEmpty(athlete.getProjectList())) {
-                    boolean containsProject = athlete.getProjectList().contains(projectId.toString());
+                    boolean containsProject = athlete.getProjectList().contains(projectId);
                     log.debug("运动员 {} 的项目列表: {}, 包含项目 {}: {}",
                             athlete.getName(), athlete.getProjectList(), projectId, containsProject);
                     return containsProject;

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

@@ -121,7 +121,7 @@ public class GameEventGroupServiceImpl implements IGameEventGroupService {
                 Optional.ofNullable(vo.getProjectList())
                     .filter(StringUtils::isNotBlank)
                     .ifPresent(projectValue -> {
-                        List<String> projectIds = JSONUtil.toList(projectValue, String.class);
+                        List<Long> projectIds = JSONUtil.toList(projectValue, Long.class);
                         List<GameEventProjectVo> projects =
                             gameEventProjectService.listProjectsByEventIdAndProjectIndex(
                                 vo.getEventId(),

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

@@ -57,7 +57,7 @@ public class GameEventProjectServiceImpl implements IGameEventProjectService {
     @Override
     public GameEventProjectVo queryById(Long projectId) {
         GameEventProjectVo vo = baseMapper.selectVoById(projectId);
-        vo.setRefereeGroups(JSONUtil.toList(vo.getRefereeGroup(), String.class));
+        vo.setRefereeGroups(JSONUtil.toList(vo.getRefereeGroup(), Long.class));
         return vo;
     }
 
@@ -95,8 +95,8 @@ public class GameEventProjectServiceImpl implements IGameEventProjectService {
 
                 Optional.ofNullable(vo.getRefereeGroup())
                     .filter(ObjectUtil::isNotEmpty)
-                    .ifPresent(refereeIdStr -> {
-                        List<String> refereeList = JSONUtil.toList(refereeIdStr.toString(), String.class);
+                    .ifPresent(refereeId -> {
+                        List<Long> refereeList = JSONUtil.toList(refereeId, Long.class);
                         vo.setRefereeGroups(refereeList);
                     });
             });
@@ -135,7 +135,7 @@ public class GameEventProjectServiceImpl implements IGameEventProjectService {
             Optional.ofNullable(vo.getRefereeGroup())
                 .filter(ObjectUtil::isNotEmpty)
                 .ifPresent(refereeIdStr -> {
-                    List<String> refereeList = JSONUtil.toList(refereeIdStr.toString(), String.class);
+                    List<Long> refereeList = JSONUtil.toList(refereeIdStr, Long.class);
                     vo.setRefereeGroups(refereeList);
                 });
         });
@@ -248,7 +248,7 @@ public class GameEventProjectServiceImpl implements IGameEventProjectService {
     }
 
     @Override
-    public List<GameEventProjectVo> listProjectsByEventIdAndProjectIndex(Long eventId, List<String> projectIds) {
+    public List<GameEventProjectVo> listProjectsByEventIdAndProjectIndex(Long eventId, List<Long> projectIds) {
         if (CollectionUtils.isEmpty(projectIds)) {
             return Collections.emptyList();
         }

+ 160 - 12
ruoyi-modules/ruoyi-game-event/src/main/java/org/dromara/system/service/impl/GameRefereeServiceImpl.java

@@ -11,6 +11,7 @@ import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.dromara.common.redis.utils.RedisUtils;
+import org.dromara.system.domain.GameEventProject;
 import org.dromara.system.domain.constant.GameEventConstant;
 import org.jetbrains.annotations.NotNull;
 import org.springframework.stereotype.Service;
@@ -19,10 +20,17 @@ import org.dromara.system.domain.vo.GameRefereeVo;
 import org.dromara.system.domain.GameReferee;
 import org.dromara.system.mapper.GameRefereeMapper;
 import org.dromara.system.service.IGameRefereeService;
+import org.dromara.system.service.IGameEventProjectService;
+import org.dromara.system.domain.vo.GameEventProjectVo;
+import org.dromara.system.domain.bo.GameEventProjectBo;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.util.CollectionUtils;
 
 import java.util.List;
 import java.util.Map;
 import java.util.Collection;
+import java.util.ArrayList;
+import java.util.stream.Collectors;
 
 /**
  * 裁判Service业务层处理
@@ -35,7 +43,8 @@ import java.util.Collection;
 @Service
 public class GameRefereeServiceImpl implements IGameRefereeService {
 
-    private final GameRefereeMapper baseMapper;
+    private final GameRefereeMapper gameRefereeMapper;
+    private final IGameEventProjectService gameEventProjectService;
 
     /**
      * 查询裁判
@@ -45,9 +54,9 @@ public class GameRefereeServiceImpl implements IGameRefereeService {
      */
     @Override
     public GameRefereeVo queryById(Long refereeId){
-        GameRefereeVo vo = baseMapper.selectVoById(refereeId);
+        GameRefereeVo vo = gameRefereeMapper.selectVoById(refereeId);
         if (vo.getProjectList() != null) {
-            vo.setProjectList2(JSONUtil.toList(vo.getProjectList(), String.class));
+            vo.setProjectList2(JSONUtil.toList(vo.getProjectList(), Long.class));
         }
         return vo;
     }
@@ -70,10 +79,10 @@ public class GameRefereeServiceImpl implements IGameRefereeService {
             }
         }
         LambdaQueryWrapper<GameReferee> lqw = buildQueryWrapper(bo);
-        Page<GameRefereeVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
+        Page<GameRefereeVo> result = gameRefereeMapper.selectVoPage(pageQuery.build(), lqw);
         result.getRecords().forEach(vo -> {
             if (vo.getProjectList() != null) {
-                vo.setProjectList2(JSONUtil.toList(vo.getProjectList(), String.class));
+                vo.setProjectList2(JSONUtil.toList(vo.getProjectList(), Long.class));
             }
         });
         return TableDataInfo.build(result);
@@ -96,10 +105,10 @@ public class GameRefereeServiceImpl implements IGameRefereeService {
             }
         }
         LambdaQueryWrapper<GameReferee> lqw = buildQueryWrapper(bo);
-        List<GameRefereeVo> list = baseMapper.selectVoList(lqw);
+        List<GameRefereeVo> list = gameRefereeMapper.selectVoList(lqw);
         list.forEach(vo -> {
             if (vo.getProjectList() != null) {
-                vo.setProjectList2(JSONUtil.toList(vo.getProjectList(), String.class));
+                vo.setProjectList2(JSONUtil.toList(vo.getProjectList(), Long.class));
             }
         });
         return list;
@@ -122,6 +131,7 @@ public class GameRefereeServiceImpl implements IGameRefereeService {
      * @return 是否新增成功
      */
     @Override
+    @Transactional(rollbackFor = Exception.class)
     public Boolean insertByBo(GameRefereeBo bo) {
         if (bo.getEventId() == null) {
             Object cacheObject = RedisUtils.getCacheObject(GameEventConstant.DEFAULT_EVENT_ID);
@@ -136,9 +146,15 @@ public class GameRefereeServiceImpl implements IGameRefereeService {
         }
         GameReferee add = MapstructUtils.convert(bo, GameReferee.class);
         validEntityBeforeSave(add);
-        boolean flag = baseMapper.insert(add) > 0;
+        boolean flag = gameRefereeMapper.insert(add) > 0;
         if (flag) {
-            bo.setRefereeId(add.getRefereeId());
+            if (add != null) {
+                bo.setRefereeId(add.getRefereeId());
+            }else{
+                return false;
+            }
+            // 更新项目表中的裁判组关联
+            updateProjectRefereeGroups(add.getRefereeId(), bo.getProjectList2(), new ArrayList<>());
         }
         return flag;
     }
@@ -150,6 +166,7 @@ public class GameRefereeServiceImpl implements IGameRefereeService {
      * @return 是否修改成功
      */
     @Override
+    @Transactional(rollbackFor = Exception.class)
     public Boolean updateByBo(GameRefereeBo bo) {
         if (bo.getEventId() == null) {
             Object cacheObject = RedisUtils.getCacheObject(GameEventConstant.DEFAULT_EVENT_ID);
@@ -159,12 +176,118 @@ public class GameRefereeServiceImpl implements IGameRefereeService {
                 bo.setEventId((Long) cacheObject);
             }
         }
+
+        // 获取原始裁判信息
+        GameRefereeVo originalReferee = queryById(bo.getRefereeId());
+        List<Long> originalProjectList = originalReferee.getProjectList2() != null ?
+            originalReferee.getProjectList2() : new ArrayList<>();
+
         if (bo.getProjectList2() != null) {
             bo.setProjectList(JSONUtil.toJsonStr(bo.getProjectList2()));
         }
+
         GameReferee update = MapstructUtils.convert(bo, GameReferee.class);
         validEntityBeforeSave(update);
-        return baseMapper.updateById(update) > 0;
+        boolean flag = gameRefereeMapper.updateById(update) > 0;
+
+        if (flag) {
+            // 更新项目表中的裁判组关联
+            List<Long> newProjectList = bo.getProjectList2() != null ? bo.getProjectList2() : new ArrayList<>();
+            updateProjectRefereeGroups(bo.getRefereeId(), newProjectList, originalProjectList);
+        }
+        return flag;
+    }
+
+    /**
+     * 更新项目表中的裁判组关联
+     *
+     * @param refereeId 裁判ID
+     * @param newProjectList 新的项目列表
+     * @param originalProjectList 原始项目列表
+     */
+    private void updateProjectRefereeGroups(Long refereeId, List<Long> newProjectList, List<Long> originalProjectList) {
+        try {
+//            String refereeIdStr = String.valueOf(refereeId);
+
+            // 找出需要移除的项目(在原列表中但不在新列表中)
+            List<Long> removedProjects = originalProjectList.stream()
+                .filter(projectId -> !newProjectList.contains(projectId))
+                .toList();
+
+            // 找出需要添加的项目(在新列表中但不在原列表中)
+            List<Long> addedProjects = newProjectList.stream()
+                .filter(projectId -> !originalProjectList.contains(projectId))
+                .toList();
+
+            // 从移除的项目中删除该裁判
+            for (Long projectId : removedProjects) {
+                removeRefereeFromProject(projectId, refereeId);
+            }
+
+            // 向添加的项目中添加该裁判
+            for (Long projectId : addedProjects) {
+                addRefereeToProject(projectId, refereeId);
+            }
+
+        } catch (Exception e) {
+            log.error("更新项目裁判组关联失败: refereeId={}, newProjectList={}, originalProjectList={}",
+                refereeId, newProjectList, originalProjectList, e);
+            throw e;
+        }
+    }
+
+    /**
+     * 从项目中移除裁判
+     *
+     * @param projectId 项目ID
+     * @param refereeId 裁判ID
+     */
+    private void removeRefereeFromProject(Long projectId, Long refereeId) {
+        try {
+            GameEventProjectVo vo = gameEventProjectService.queryById(projectId);
+            if (vo != null && vo.getRefereeGroups() != null) {
+                List<Long> refereeGroups = new ArrayList<>(vo.getRefereeGroups());
+                refereeGroups.remove(refereeId);
+
+                GameEventProject project = MapstructUtils.convert(vo, GameEventProject.class);
+
+                GameEventProjectBo projectBo = MapstructUtils.convert(project, GameEventProjectBo.class);
+//                GameEventProjectBo projectBo = ObjectUtils.copy(vo, GameEventProjectBo.class);
+                projectBo.setRefereeGroups(refereeGroups);
+                gameEventProjectService.updateByBo(projectBo);
+            }
+        } catch (Exception e) {
+            log.error("从项目中移除裁判失败: projectId={}, refereeId={}", projectId, refereeId, e);
+            throw e;
+        }
+    }
+
+    /**
+     * 向项目中添加裁判
+     *
+     * @param projectId 项目ID
+     * @param refereeId 裁判ID
+     */
+    private void addRefereeToProject(Long projectId, Long refereeId) {
+        try {
+            GameEventProjectVo vo = gameEventProjectService.queryById(projectId);
+            if (vo != null) {
+                List<Long> refereeGroups = vo.getRefereeGroups() != null ?
+                    new ArrayList<>(vo.getRefereeGroups()) : new ArrayList<>();
+
+                if (!refereeGroups.contains(refereeId)) {
+                    refereeGroups.add(refereeId);
+
+                    GameEventProject project = MapstructUtils.convert(vo, GameEventProject.class);
+                    GameEventProjectBo projectBo = MapstructUtils.convert(project, GameEventProjectBo.class);
+                    projectBo.setRefereeGroups(refereeGroups);
+                    gameEventProjectService.updateByBo(projectBo);
+                }
+            }
+        } catch (Exception e) {
+            log.error("向项目中添加裁判失败: projectId={}, refereeId={}", projectId, refereeId, e);
+            throw e;
+        }
     }
 
     /**
@@ -186,7 +309,32 @@ public class GameRefereeServiceImpl implements IGameRefereeService {
         if(isValid){
             //TODO 做一些业务上的校验,判断是否需要校验
         }
-        return baseMapper.deleteByIds(ids) > 0;
+
+        // 删除前先从所有项目中移除该裁判
+        for (Long refereeId : ids) {
+            removeRefereeFromAllProjects(refereeId);
+        }
+
+        return gameRefereeMapper.deleteByIds(ids) > 0;
+    }
+
+    /**
+     * 从所有项目中移除裁判
+     *
+     * @param refereeId 裁判ID
+     */
+    private void removeRefereeFromAllProjects(Long refereeId) {
+        try {
+            GameRefereeVo referee = queryById(refereeId);
+            if (referee != null && referee.getProjectList2() != null) {
+                for (Long projectId : referee.getProjectList2()) {
+                    removeRefereeFromProject(projectId, refereeId);
+                }
+            }
+        } catch (Exception e) {
+            log.error("从所有项目中移除裁判失败: refereeId={}", refereeId, e);
+            throw e;
+        }
     }
 
     /**
@@ -196,7 +344,7 @@ public class GameRefereeServiceImpl implements IGameRefereeService {
      */
     @Override
     public Long countReferee() {
-        return this.baseMapper.selectCount(
+        return this.gameRefereeMapper.selectCount(
             Wrappers.lambdaQuery(GameReferee.class)
         );
     }

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

@@ -60,7 +60,7 @@ public class GameTeamServiceImpl implements IGameTeamService {
         }
         if (vo.getAthleteValue() != null) {
             log.info("teamId:{}, athleteValue:{}", teamId, vo.getAthleteValue());
-            vo.setAthleteList(JSONUtil.toList(vo.getAthleteValue(), String.class));
+            vo.setAthleteList(JSONUtil.toList(vo.getAthleteValue(), Long.class));
         }
         return vo;
     }
@@ -92,7 +92,7 @@ public class GameTeamServiceImpl implements IGameTeamService {
                     .filter(StringUtils::isNotBlank)
                     .ifPresent(athleteValue -> {
 //                        String[] projectIds = athleteValue.split(",");
-                        List<String> athleteIds = JSONUtil.toList(athleteValue, String.class);
+                        List<Long> athleteIds = JSONUtil.toList(athleteValue, Long.class);
 //                        List<GameAthlete> athletes = gameAthleteMapper.selectList(
 //                            Wrappers.<GameAthlete>lambdaQuery()
 //                                .in(GameAthlete::getAthleteId, projectIds)
@@ -153,7 +153,7 @@ public class GameTeamServiceImpl implements IGameTeamService {
         List<GameTeamVo> list = baseMapper.selectVoList(lqw);
         list.forEach(vo -> {
             if (vo.getAthleteValue() != null) {
-                vo.setAthleteList(JSONUtil.toList(vo.getAthleteValue(), String.class));
+                vo.setAthleteList(JSONUtil.toList(vo.getAthleteValue(), Long.class));
             }
         });
         return list;
@@ -327,7 +327,7 @@ public class GameTeamServiceImpl implements IGameTeamService {
                 .in(GameTeam::getTeamId, teamIds)
         );
         list.forEach(vo -> {
-            vo.setAthleteList(JSONUtil.toList(vo.getAthleteValue(), String.class));
+            vo.setAthleteList(JSONUtil.toList(vo.getAthleteValue(), Long.class));
         });
         return list;
     }

+ 11 - 11
ruoyi-modules/ruoyi-game-event/src/main/java/org/dromara/system/service/impl/app/PhysicalTestServiceImpl.java

@@ -178,7 +178,7 @@ public class PhysicalTestServiceImpl implements IPhysicalTestService {
             newAthlete.setName(result.getName());
             // 初始化项目列表并添加项目ID
             newAthlete.setProjectList(new ArrayList<>());
-            newAthlete.getProjectList().add(projectId.toString());
+            newAthlete.getProjectList().add(projectId);
             newAthlete.setStatus("0"); // 正常状态
 
             boolean res = athleteService.insertByBo(newAthlete);
@@ -294,7 +294,7 @@ public class PhysicalTestServiceImpl implements IPhysicalTestService {
             newAthlete.setName(record.getName()); // name映射到name
             // 初始化项目列表并添加项目ID
             newAthlete.setProjectList(new ArrayList<>());
-            newAthlete.getProjectList().add(projectId.toString());
+            newAthlete.getProjectList().add(projectId);
             newAthlete.setStatus("0"); // 正常状态
 
             boolean res = athleteService.insertByBo(newAthlete);
@@ -361,22 +361,22 @@ public class PhysicalTestServiceImpl implements IPhysicalTestService {
     private void updateAthleteProjectList(GameAthlete athlete, Long projectId) {
         try {
             // 解析现有的项目列表
-            List<String> projectList = new ArrayList<>();
+            List<Long> projectList = new ArrayList<>();
             if (StringUtils.isNotBlank(athlete.getProjectValue())) {
-                projectList = JSONUtil.toList(athlete.getProjectValue(), String.class);
+                projectList = JSONUtil.toList(athlete.getProjectValue(), Long.class);
             }
-            
+
             // 检查项目是否已存在
-            String projectIdStr = projectId.toString();
-            if (!projectList.contains(projectIdStr)) {
-                projectList.add(projectIdStr);
-                
+//            String projectIdStr = projectId.toString();
+            if (!projectList.contains(projectId)) {
+                projectList.add(projectId);
+
                 // 转换为Bo对象并更新
                 GameAthleteBo athleteBo = MapstructUtils.convert(athlete, GameAthleteBo.class);
                 athleteBo.setProjectList(projectList);
-                
+
                 athleteService.updateByBo(athleteBo);
-                log.info("已为运动员 {} 添加项目 {}", athlete.getName(), projectIdStr);
+                log.info("已为运动员 {} 添加项目 {}", athlete.getName(), projectId);
             }
         } catch (Exception e) {
             log.error("更新运动员项目列表失败", e);

+ 1 - 1
ruoyi-modules/ruoyi-game-event/src/main/java/org/dromara/system/util/FilteredCommentInputStream.java → ruoyi-modules/ruoyi-game-event/src/main/java/org/dromara/system/utils/FilteredCommentInputStream.java

@@ -1,4 +1,4 @@
-package org.dromara.system.util;
+package org.dromara.system.utils;
 
 import java.io.*;
 import java.nio.charset.Charset;

+ 73 - 0
ruoyi-modules/ruoyi-game-event/src/main/java/org/dromara/system/utils/QRCodeUtils.java

@@ -0,0 +1,73 @@
+package org.dromara.system.utils;
+
+import com.google.zxing.BarcodeFormat;
+import com.google.zxing.EncodeHintType;
+import com.google.zxing.WriterException;
+import com.google.zxing.client.j2se.MatrixToImageWriter;
+import com.google.zxing.common.BitMatrix;
+import com.google.zxing.qrcode.QRCodeWriter;
+import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
+import org.springframework.stereotype.Component;
+
+import java.awt.image.BufferedImage;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.util.Base64;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * 二维码生成工具类
+ *
+ * @author zlt
+ * @date 2025-01-27
+ */
+@Component
+public class QRCodeUtils {
+
+    /**
+     * 生成二维码并返回Base64编码的图片数据
+     *
+     * @param content 二维码内容
+     * @param width   图片宽度
+     * @param height  图片高度
+     * @return Base64编码的图片数据
+     */
+    public String generateQRCodeBase64(String content, int width, int height) {
+        try {
+            // 设置二维码参数
+            Map<EncodeHintType, Object> hints = new HashMap<>();
+            hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.M);
+            hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
+            hints.put(EncodeHintType.MARGIN, 1);
+
+            // 生成二维码
+            QRCodeWriter qrCodeWriter = new QRCodeWriter();
+            BitMatrix bitMatrix = qrCodeWriter.encode(content, BarcodeFormat.QR_CODE, width, height, hints);
+
+            // 转换为BufferedImage
+            BufferedImage bufferedImage = MatrixToImageWriter.toBufferedImage(bitMatrix);
+
+            // 转换为字节数组
+            ByteArrayOutputStream baos = new ByteArrayOutputStream();
+            javax.imageio.ImageIO.write(bufferedImage, "PNG", baos);
+            byte[] imageBytes = baos.toByteArray();
+
+            // 转换为Base64
+            return "data:image/png;base64," + Base64.getEncoder().encodeToString(imageBytes);
+
+        } catch (WriterException | IOException e) {
+            throw new RuntimeException("生成二维码失败", e);
+        }
+    }
+
+    /**
+     * 生成二维码并返回Base64编码的图片数据(默认尺寸200x200)
+     *
+     * @param content 二维码内容
+     * @return Base64编码的图片数据
+     */
+    public String generateQRCodeBase64(String content) {
+        return generateQRCodeBase64(content, 200, 200);
+    }
+}