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

feat(game-event): 新增报名限制功能并优化赛事数据结构

- 添加 ExEnrollLimitVo 数据传输对象用于报名限制信息
- 新增报名限制人数查询接口 /enrollLimit 返回项目报名限制设置
- 更新 ExperienceGameEventVo 添加当前赛事每人限制报名项目数字段
- 修改 AppEventMdVo 类型字典注释内容并添加富文本id注解说明
- 优化 GameEventMapper 查询SQL添加 limit_application 字段映射
- 在 GameEventProjectMapper 中新增 selectLimit 方法查询项目限制信息
- 配置 application.yml 添加 /app/** 路径到系统白名单
- 调整体验版控制器接口序号将赛事直播链接接口改为第14个,报名限制接口为第15个
zhou пре 1 недеља
родитељ
комит
cbf26d6e46

+ 1 - 0
ruoyi-admin/src/main/resources/application.yml

@@ -228,6 +228,7 @@ xss:
     - /system/notice
     - /system/article
     - /system/markdown
+    - /app/**
 
 # 全局线程池相关配置
 # 如使用JDK21请直接使用虚拟线程 不要开启此配置

+ 13 - 6
ruoyi-modules/ruoyi-game-event/src/main/java/org/dromara/system/controller/app/ExperienceVersionController.java

@@ -177,12 +177,7 @@ public class ExperienceVersionController {
     }
 
     /**
-     * 14、富文本统一查询接口
-     */
-//    @GetMapping("/richText")
-
-    /**
-     * 15、赛事直播链接--liveUrl
+     * 14、赛事直播链接--liveUrl
      */
     @GetMapping("/live")
     public R<String> getLiveUrl(@RequestParam("eventId") Long eventId) {
@@ -196,4 +191,16 @@ public class ExperienceVersionController {
         return R.ok("操作成功", liveUrl);
     }
 
+    /**
+     * 15、报名限制人数接口
+     */
+    @GetMapping("/enrollLimit")
+    public R<ExEnrollLimitVo> getEnrollLimit(@RequestParam("projectId") Long projectId) {
+        if (projectId == null) {
+            return R.fail("项目Id不能为空");
+        }
+        ExEnrollLimitVo limit = TenantHelper.ignore(() -> projectMapper.selectLimit(projectId));
+        return R.ok("操作成功", limit);
+    }
+
 }

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

@@ -29,9 +29,8 @@ public class AppEventMdVo implements Serializable {
     private static final long serialVersionUID = 1L;
 
     /**
-     *
+     * 富文本id
      */
-    @ExcelProperty(value = "")
     private Long id;
 
     /**
@@ -53,11 +52,9 @@ public class AppEventMdVo implements Serializable {
     private String content;
 
     /**
-     * 类型 1:竞赛流程 2:竞赛项目 3:活动议程 4:项目介绍 5:竞赛流程
-  6:赛事分组 7:运动员号码簿 8:项目场地 9:交通指示
+     * 类型 5:竞赛规程 7:队员号码 8:项目分布图 9:开闭幕式 10:组织机构
      */
-    @ExcelProperty(value = "类型 1:竞赛流程 2:竞赛项目 3:活动议程 4:项目介绍 5:竞赛流程 " +
-        "6:赛事分组 7:运动员号码簿 8:项目场地 9:交通指示", converter = ExcelDictConvert.class)
+    @ExcelProperty(value = "类型", converter = ExcelDictConvert.class)
     @ExcelDictFormat(dictType = "markdown_location")
     private Integer type;
 

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

@@ -0,0 +1,32 @@
+package org.dromara.system.domain.vo.app;
+
+import lombok.Data;
+
+import java.io.Serial;
+import java.io.Serializable;
+
+@Data
+public class ExEnrollLimitVo implements Serializable {
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 个人项目限制报名的人数---0表示无限制
+     */
+    private Integer limitPerson;
+
+    /**
+     * 当前项目限制报名的队伍数
+     */
+    private Integer limitTeam;
+
+    /**
+     * 当前项目限制报名的男生人数(个人项目总计/团体项目每队)
+     */
+    private Integer limitMale;
+
+    /**
+     * 当前项目限制报名的女生人数(个人项目总计/团体项目每队)
+     */
+    private Integer limitFemale;
+}

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

@@ -51,4 +51,9 @@ public class ExperienceGameEventVo implements Serializable {
      */
     @Translation(type = TransConstant.OSS_ID_TO_URL, mapper = "hallImage")
     private String hallImageUrl;
+
+    /**
+     * 当前赛事每个人限制报名的项目数
+     */
+    private Integer projectNum;
 }

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

@@ -69,7 +69,7 @@ public interface GameEventMapper extends BaseMapperPlus<GameEvent, GameEventVo>
      * 小程序体验端获取赛事列表,并关联查询配置项
      */
     @Select("<script>" +
-            "SELECT e.event_id, e.location, e.event_name, e.start_time, e.end_time, ec.config_value as hallImage " +
+            "SELECT e.event_id, e.location, e.event_name, e.start_time, e.end_time, ec.config_value as hallImage, e.limit_application as projectNum " +
             "from game_event e " +
             "left join game_event_config ec on e.event_id = ec.event_id and ec.config_key = 'hall_image' " +
             "where e.del_flag = '0' and e.status = '0' " +

+ 135 - 129
ruoyi-modules/ruoyi-game-event/src/main/java/org/dromara/system/mapper/GameEventProjectMapper.java

@@ -4,18 +4,19 @@ import com.baomidou.mybatisplus.core.conditions.Wrapper;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import org.apache.ibatis.annotations.Mapper;
 import org.apache.ibatis.annotations.Param;
+import org.apache.ibatis.annotations.Select;
 import org.dromara.common.mybatis.annotation.DataColumn;
 import org.dromara.common.mybatis.annotation.DataPermission;
 import org.dromara.system.domain.GameEventProject;
 import org.dromara.system.domain.bo.GameEventProjectBo;
 import org.dromara.system.domain.vo.GameEventProjectVo;
 import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
+import org.dromara.system.domain.vo.app.ExEnrollLimitVo;
 import org.dromara.system.domain.vo.app.ExGameScheduleVo;
 import org.dromara.system.domain.vo.app.ExGameGroupDetailVo;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 
 import java.math.BigDecimal;
-import java.math.RoundingMode;
 import java.text.SimpleDateFormat;
 import java.util.ArrayList;
 import java.util.Calendar;
@@ -31,153 +32,158 @@ import java.util.List;
  */
 @Mapper
 public interface GameEventProjectMapper extends BaseMapperPlus<GameEventProject, GameEventProjectVo> {
-        /**
-         * 分页查询项目列表,并进行数据权限控制
-         *
-         * @param page         分页参数
-         * @param queryWrapper 查询条件
-         * @return 分页的赛事信息
-         */
-        @DataPermission({
-                        @DataColumn(key = "deptName", value = "create_dept"),
-                        @DataColumn(key = "userName", value = "create_by")
-        })
-        default Page<GameEventProjectVo> selectPageEventProjectList(Page<GameEventProject> page,
-                        Wrapper<GameEventProject> queryWrapper) {
-                return this.selectVoPage(page, queryWrapper);
-        }
+    /**
+     * 分页查询项目列表,并进行数据权限控制
+     *
+     * @param page         分页参数
+     * @param queryWrapper 查询条件
+     * @return 分页的赛事信息
+     */
+    @DataPermission({
+                    @DataColumn(key = "deptName", value = "create_dept"),
+                    @DataColumn(key = "userName", value = "create_by")
+    })
+    default Page<GameEventProjectVo> selectPageEventProjectList(Page<GameEventProject> page,
+                    Wrapper<GameEventProject> queryWrapper) {
+            return this.selectVoPage(page, queryWrapper);
+    }
 
-        /**
-         * 获取项目列表,并进行数据权限控制
-         *
-         * @param queryWrapper 筛选条件
-         * @return 项目列表
-         */
-        @DataPermission({
-                        @DataColumn(key = "deptName", value = "create_dept"),
-                        @DataColumn(key = "userName", value = "create_by")
-        })
-        default List<GameEventProjectVo> selectEventProjectList(Wrapper<GameEventProject> queryWrapper) {
-                return this.selectVoList(queryWrapper);
-        }
+    /**
+     * 获取项目列表,并进行数据权限控制
+     *
+     * @param queryWrapper 筛选条件
+     * @return 项目列表
+     */
+    @DataPermission({
+                    @DataColumn(key = "deptName", value = "create_dept"),
+                    @DataColumn(key = "userName", value = "create_by")
+    })
+    default List<GameEventProjectVo> selectEventProjectList(Wrapper<GameEventProject> queryWrapper) {
+            return this.selectVoList(queryWrapper);
+    }
 
-        /**
-         * 分页查询项目列表并包含实时统计(XML 实现)
-         */
-        @DataPermission({
-                        @DataColumn(key = "deptName", value = "create_dept"),
-                        @DataColumn(key = "userName", value = "create_by")
-        })
-        Page<GameEventProjectVo> selectPageWithStats(@Param("page") Page<GameEventProjectVo> page,
-                        @Param("query") GameEventProjectBo bo);
+    /**
+     * 分页查询项目列表并包含实时统计(XML 实现)
+     */
+    @DataPermission({
+                    @DataColumn(key = "deptName", value = "create_dept"),
+                    @DataColumn(key = "userName", value = "create_by")
+    })
+    Page<GameEventProjectVo> selectPageWithStats(@Param("page") Page<GameEventProjectVo> page,
+                    @Param("query") GameEventProjectBo bo);
 
-        /**
-         * 查询赛事日程信息(按时间排序)
-         */
-        default List<ExGameScheduleVo> selectSchedule(@Param("eventId") Long eventId) {
-            List<GameEventProject> projects = this.selectList(
-                Wrappers.lambdaQuery(GameEventProject.class)
-                    .eq(GameEventProject::getEventId, eventId)
-                    .orderByAsc(GameEventProject::getStartTime)
-                    .select(GameEventProject::getStartTime, GameEventProject::getEndTime, GameEventProject::getProjectName, GameEventProject::getLocation)
-            );
+    /**
+     * 查询赛事日程信息(按时间排序)
+     */
+    default List<ExGameScheduleVo> selectSchedule(@Param("eventId") Long eventId) {
+        List<GameEventProject> projects = this.selectList(
+            Wrappers.lambdaQuery(GameEventProject.class)
+                .eq(GameEventProject::getEventId, eventId)
+                .orderByAsc(GameEventProject::getStartTime)
+                .select(GameEventProject::getStartTime, GameEventProject::getEndTime, GameEventProject::getProjectName, GameEventProject::getLocation)
+        );
 
-            List<ExGameScheduleVo> scheduleList = new ArrayList<>();
-            SimpleDateFormat dateFmt = new SimpleDateFormat("yyyy-MM-dd");
-            SimpleDateFormat timeFmt = new SimpleDateFormat("HH:mm");
-            for (GameEventProject project : projects) {
-                ExGameScheduleVo vo = new ExGameScheduleVo();
-                // 格式化日期 (yyyy-MM-dd)
-                Date startTime = project.getStartTime();
-                Date endTime = project.getEndTime();
-                String dateStr = "";
-                if (startTime != null) {
-                        dateStr = dateFmt.format(startTime);
-                }
-                vo.setDate(dateStr);
-                // 格式化时间 (如果跨天,显示 (dd) 后缀)
-                String timeStr = "00:00 - 00:00";
-                if (startTime != null && endTime != null) {
-                    String startFmt = timeFmt.format(startTime);
-                    String endFmt = timeFmt.format(endTime);
+        List<ExGameScheduleVo> scheduleList = new ArrayList<>();
+        SimpleDateFormat dateFmt = new SimpleDateFormat("yyyy-MM-dd");
+        SimpleDateFormat timeFmt = new SimpleDateFormat("HH:mm");
+        for (GameEventProject project : projects) {
+            ExGameScheduleVo vo = new ExGameScheduleVo();
+            // 格式化日期 (yyyy-MM-dd)
+            Date startTime = project.getStartTime();
+            Date endTime = project.getEndTime();
+            String dateStr = "";
+            if (startTime != null) {
+                    dateStr = dateFmt.format(startTime);
+            }
+            vo.setDate(dateStr);
+            // 格式化时间 (如果跨天,显示 (dd) 后缀)
+            String timeStr = "00:00 - 00:00";
+            if (startTime != null && endTime != null) {
+                String startFmt = timeFmt.format(startTime);
+                String endFmt = timeFmt.format(endTime);
 
-                    Calendar startCal = Calendar.getInstance();
-                    startCal.setTime(startTime);
-                    Calendar endCal = Calendar.getInstance();
-                    endCal.setTime(endTime);
+                Calendar startCal = Calendar.getInstance();
+                startCal.setTime(startTime);
+                Calendar endCal = Calendar.getInstance();
+                endCal.setTime(endTime);
 
-                    // 跨天判断:年、月、日中有任意一个不同即为跨天
-                    if (startCal.get(Calendar.YEAR) != endCal.get(Calendar.YEAR) ||
-                                    startCal.get(Calendar.MONTH) != endCal.get(Calendar.MONTH) ||
-                                    startCal.get(Calendar.DAY_OF_MONTH) != endCal.get(Calendar.DAY_OF_MONTH)) {
-                        int endDay = endCal.get(Calendar.DAY_OF_MONTH);
-                        timeStr = startFmt + " - " + endFmt + " (" + String.format("%02d", endDay) + ")";
-                    } else {
-                        timeStr = startFmt + " - " + endFmt;
-                    }
-                } else if (startTime != null) {
-                    timeStr = timeFmt.format(startTime) + " - 00:00";
+                // 跨天判断:年、月、日中有任意一个不同即为跨天
+                if (startCal.get(Calendar.YEAR) != endCal.get(Calendar.YEAR) ||
+                                startCal.get(Calendar.MONTH) != endCal.get(Calendar.MONTH) ||
+                                startCal.get(Calendar.DAY_OF_MONTH) != endCal.get(Calendar.DAY_OF_MONTH)) {
+                    int endDay = endCal.get(Calendar.DAY_OF_MONTH);
+                    timeStr = startFmt + " - " + endFmt + " (" + String.format("%02d", endDay) + ")";
+                } else {
+                    timeStr = startFmt + " - " + endFmt;
                 }
-                vo.setTime(timeStr);
-                // 项目名称
-                vo.setProjectName(project.getProjectName());
-                // 比赛场地
-                vo.setLocation(project.getLocation());
-                scheduleList.add(vo);
+            } else if (startTime != null) {
+                timeStr = timeFmt.format(startTime) + " - 00:00";
             }
-            return scheduleList;
+            vo.setTime(timeStr);
+            // 项目名称
+            vo.setProjectName(project.getProjectName());
+            // 比赛场地
+            vo.setLocation(project.getLocation());
+            scheduleList.add(vo);
         }
+        return scheduleList;
+    }
 
-        /**
-         * 查询分组内所有运动员的原始信息
-         */
-        List<ExGameGroupDetailVo> selectGroupDetailRaw(@Param("groupId") Long groupId);
+    /**
+     * 查询分组内所有运动员的原始信息
+     */
+    List<ExGameGroupDetailVo> selectGroupDetailRaw(@Param("groupId") Long groupId);
 
-        /**
-         * 根据分组ID查询该分组详情,包括各组次下各运动员的姓名、编号、队伍、格式化后的成绩、排名和道次。
-         */
-        default List<ExGameGroupDetailVo> selectGroupDetail(@Param("groupId") Long groupId) {
-            List<ExGameGroupDetailVo> list = this.selectGroupDetailRaw(groupId);
-            if (list == null || list.isEmpty()) {
-                return new ArrayList<>();
+    /**
+     * 根据分组ID查询该分组详情,包括各组次下各运动员的姓名、编号、队伍、格式化后的成绩、排名和道次。
+     */
+    default List<ExGameGroupDetailVo> selectGroupDetail(@Param("groupId") Long groupId) {
+        List<ExGameGroupDetailVo> list = this.selectGroupDetailRaw(groupId);
+        if (list == null || list.isEmpty()) {
+            return new ArrayList<>();
+        }
+        for (ExGameGroupDetailVo vo : list) {
+            // 1. 根据项目归类获取原始成绩
+            BigDecimal rawScore = null;
+            if ("0".equals(vo.getClassification())) {
+                rawScore = vo.getIndividualPerformance();
+            } else if ("1".equals(vo.getClassification())) {
+                rawScore = vo.getTeamPerformance();
             }
-            for (ExGameGroupDetailVo vo : list) {
-                // 1. 根据项目归类获取原始成绩
-                BigDecimal rawScore = null;
-                if ("0".equals(vo.getClassification())) {
-                    rawScore = vo.getIndividualPerformance();
-                } else if ("1".equals(vo.getClassification())) {
-                    rawScore = vo.getTeamPerformance();
-                }
 
-                // 2. 处理成绩显示和单位
-                if (rawScore != null) {
-                    // 去除尾随零
-                    String scoreStr = rawScore.stripTrailingZeros().toPlainString();
-                    String rule = vo.getScoreRule();
+            // 2. 处理成绩显示和单位
+            if (rawScore != null) {
+                // 去除尾随零
+                String scoreStr = rawScore.stripTrailingZeros().toPlainString();
+                String rule = vo.getScoreRule();
 
-                    if ("1".equals(rule)) {
-                        // 计时类附加 s
-                        vo.setScore(scoreStr + "s");
-                    } else if ("2".equals(rule) || "6".equals(rule) || "7".equals(rule)) {
-                        // 距离类、远度距离类、高度距离类附加 m
-                        vo.setScore(scoreStr + "m");
-                    } else if ("3".equals(rule) || "4".equals(rule)) {
-                        // 计数类附加项目配置的计数单位
-                        String unit = vo.getCountUnit();
-                        if (unit != null && !unit.isEmpty()) {
-                            vo.setScore(scoreStr + unit);
-                        } else {
-                            vo.setScore(scoreStr);
-                        }
+                if ("1".equals(rule)) {
+                    // 计时类附加 s
+                    vo.setScore(scoreStr + "s");
+                } else if ("2".equals(rule) || "6".equals(rule) || "7".equals(rule)) {
+                    // 距离类、远度距离类、高度距离类附加 m
+                    vo.setScore(scoreStr + "m");
+                } else if ("3".equals(rule) || "4".equals(rule)) {
+                    // 计数类附加项目配置的计数单位
+                    String unit = vo.getCountUnit();
+                    if (unit != null && !unit.isEmpty()) {
+                        vo.setScore(scoreStr + unit);
                     } else {
-                        // 其他类型直接显示
                         vo.setScore(scoreStr);
                     }
                 } else {
-                    vo.setScore("");
+                    // 其他类型直接显示
+                    vo.setScore(scoreStr);
                 }
+            } else {
+                vo.setScore("");
             }
-            return list;
         }
+        return list;
+    }
+
+    @Select("select limit_person, limit_team, limit_male, limit_female " +
+        "from game_event_project " +
+        "where project_id = #{projectId}")
+    ExEnrollLimitVo selectLimit(Long projectId);
 }