Browse Source

feat: 新增还原赛事
perf:优化用户建议、预热活动关联默认赛事、导航菜单

wenkai 1 week ago
parent
commit
2e8adb3209
18 changed files with 474 additions and 13 deletions
  1. 2 2
      ruoyi-admin/src/main/resources/application-dev.yml
  2. 4 0
      ruoyi-admin/src/main/resources/application.yml
  3. 6 0
      ruoyi-common/ruoyi-common-doc/pom.xml
  4. 5 1
      ruoyi-common/ruoyi-common-mybatis/pom.xml
  5. 66 0
      ruoyi-modules/ruoyi-game-event/src/main/java/org/dromara/system/controller/DatabaseBackupRestoreController.java
  6. 2 2
      ruoyi-modules/ruoyi-game-event/src/main/java/org/dromara/system/controller/MarkdownController.java
  7. 3 1
      ruoyi-modules/ruoyi-game-event/src/main/java/org/dromara/system/controller/app/ActivityController.java
  8. 6 0
      ruoyi-modules/ruoyi-game-event/src/main/java/org/dromara/system/controller/app/AdviceController.java
  9. 16 5
      ruoyi-modules/ruoyi-game-event/src/main/java/org/dromara/system/controller/app/AppIndexController.java
  10. 39 0
      ruoyi-modules/ruoyi-game-event/src/main/java/org/dromara/system/controller/app/AppMarkdownController.java
  11. 5 0
      ruoyi-modules/ruoyi-game-event/src/main/java/org/dromara/system/controller/app/ProjectController.java
  12. 3 2
      ruoyi-modules/ruoyi-game-event/src/main/java/org/dromara/system/controller/app/ScoreController.java
  13. 8 0
      ruoyi-modules/ruoyi-game-event/src/main/java/org/dromara/system/service/IGameNavigatorService.java
  14. 171 0
      ruoyi-modules/ruoyi-game-event/src/main/java/org/dromara/system/service/dbbackup/DatabaseBackupRestoreService.java
  15. 10 0
      ruoyi-modules/ruoyi-game-event/src/main/java/org/dromara/system/service/impl/ArticleServiceImpl.java
  16. 23 0
      ruoyi-modules/ruoyi-game-event/src/main/java/org/dromara/system/service/impl/IGameNavigatorServiceImpl.java
  17. 94 0
      ruoyi-modules/ruoyi-game-event/src/main/java/org/dromara/system/util/FilteredCommentInputStream.java
  18. 11 0
      本周改动.md

+ 2 - 2
ruoyi-admin/src/main/resources/application-dev.yml

@@ -50,7 +50,7 @@ spring:
           # jdbc 所有参数配置参考 https://lionli.blog.csdn.net/article/details/122018562
           # rewriteBatchedStatements=true 批处理优化 大幅提升批量插入更新删除性能(对数据库有性能损耗 使用批量操作应考虑性能问题)
 #          url: jdbc:mysql://192.168.1.146:3306/game_event?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true
-          url: jdbc:mysql://localhost:3306/ry-vue?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true
+          url: jdbc:mysql://localhost:3306/game_event?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true
           username: root
 #          password: P@ssw0rd
           password: 123456
@@ -100,7 +100,7 @@ spring:
 spring.data:
   redis:
     # 地址
-    host: 192.168.1.146
+    host: 127.0.0.1
     # 端口,默认为6379
     port: 6379
     # 数据库索引

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

@@ -178,6 +178,9 @@ springdoc:
   api-docs:
     # 是否开启接口文档
     enabled: true
+  swagger-ui:
+    enabled: true
+    path: /swagger-ui.html
   info:
     # 标题
     title: '标题:RuoYi-Vue-Plus多租户管理系统_接口文档'
@@ -218,6 +221,7 @@ xss:
   excludeUrls:
     - /system/notice
     - /system/article
+    - /system/markdown
 
 # 全局线程池相关配置
 # 如使用JDK21请直接使用虚拟线程 不要开启此配置

+ 6 - 0
ruoyi-common/ruoyi-common-doc/pom.xml

@@ -26,6 +26,12 @@
             <artifactId>springdoc-openapi-starter-webmvc-api</artifactId>
         </dependency>
 
+        <dependency>
+            <groupId>org.springdoc</groupId>
+            <artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
+            <version>2.8.9</version>
+        </dependency>
+
         <dependency>
             <groupId>com.github.therapi</groupId>
             <artifactId>therapi-runtime-javadoc</artifactId>

+ 5 - 1
ruoyi-common/ruoyi-common-mybatis/pom.xml

@@ -41,7 +41,11 @@
             <groupId>com.baomidou</groupId>
             <artifactId>mybatis-plus-jsqlparser</artifactId>
         </dependency>
-
+        <dependency>
+            <groupId>org.mybatis</groupId>
+            <artifactId>mybatis</artifactId>
+            <version>3.5.13</version> <!-- 推荐使用较新版本 -->
+        </dependency>
         <!-- sql性能分析插件 -->
         <dependency>
             <groupId>p6spy</groupId>

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

@@ -0,0 +1,66 @@
+package org.dromara.system.controller;
+
+import jakarta.servlet.http.HttpServletResponse;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.dromara.common.core.domain.R;
+import org.dromara.common.core.exception.ServiceException;
+import org.dromara.common.web.core.BaseController;
+import org.dromara.system.service.dbbackup.DatabaseBackupRestoreService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.multipart.MultipartFile;
+
+/**
+ * 还原赛事(导入导出sql)
+ */
+
+@Slf4j
+@Validated
+@RequiredArgsConstructor
+@RestController
+@RequestMapping("/system/backup")
+public class DatabaseBackupRestoreController extends BaseController {
+
+    private final DatabaseBackupRestoreService backupRestoreService;
+
+    /**
+     * 备份数据库:直接返回 SQL 文件供下载
+     */
+    @PostMapping("/backup")
+    public void backup(HttpServletResponse response) {
+        try {
+            backupRestoreService.backupDatabaseToResponse(response);
+        } catch (Exception e) {
+            log.error("数据库备份下载失败", e);
+            response.reset();
+            throw new ServiceException("备份失败:" + e.getMessage());
+        }
+    }
+
+    /**
+     * 恢复数据库:通过上传 SQL 文件进行导入
+     */
+    @PostMapping("/restore")
+    public R<String> restore(@RequestParam("file") MultipartFile file) {
+        if (file.isEmpty()) {
+            return R.fail("上传文件不能为空");
+        }
+        if (!file.getOriginalFilename().endsWith(".sql")) {
+            return R.fail("仅支持 .sql 文件导入");
+        }
+
+        try {
+            String result = backupRestoreService.restoreFromMultipartFile(file);
+            if (result.contains("成功")) {
+                return R.ok("恢复成功");
+            } else {
+                return R.fail("恢复失败: " + result);
+            }
+        } catch (Exception e) {
+            log.error("数据库恢复失败", e);
+            return R.fail("恢复失败: " + e.getMessage());
+        }
+    }
+}

+ 2 - 2
ruoyi-modules/ruoyi-game-event/src/main/java/org/dromara/system/controller/MarkdownController.java

@@ -20,7 +20,7 @@ import org.springframework.web.bind.annotation.*;
 import java.util.List;
 
 /**
- * app markdown
+ * 赛事富文本
  *
  * @author Lion Li
  * @date 2025-08-18
@@ -54,7 +54,7 @@ public class MarkdownController extends BaseController {
     @GetMapping("/{eventId}/{type}")
     public R<AppEventMdVo> getInfoByEventAndType(@NotNull(message = "赛事id不能为空")
                                    @PathVariable Long eventId,
-                                   @NotNull(message = "赛事id不能为空")
+                                   @NotNull(message = "文本类型不能为空")
                                    @PathVariable Integer type) {
         return R.ok(appEventMdService.queryByEventIdAndType(eventId, type));
     }

+ 3 - 1
ruoyi-modules/ruoyi-game-event/src/main/java/org/dromara/system/controller/app/ActivityController.java

@@ -1,5 +1,6 @@
 package org.dromara.system.controller.app;
 
+import cn.dev33.satoken.annotation.SaIgnore;
 import lombok.RequiredArgsConstructor;
 import org.dromara.system.domain.bo.ArticleBo;
 import org.dromara.system.domain.constant.GameEventConstant;
@@ -12,9 +13,10 @@ import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RestController;
 
 /**
- * 用户活动预热
+ * app-用户活动预热
  */
 
+@SaIgnore
 @Validated
 @RequiredArgsConstructor
 @RestController

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

@@ -1,5 +1,6 @@
 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.common.core.validate.AddGroup;
@@ -14,6 +15,11 @@ import org.springframework.web.bind.annotation.*;
 
 import java.util.Map;
 
+/**
+ * app-意见反馈
+ */
+
+@SaIgnore
 @Validated
 @RequiredArgsConstructor
 @RestController

+ 16 - 5
ruoyi-modules/ruoyi-game-event/src/main/java/org/dromara/system/controller/app/AppIndexController.java

@@ -1,10 +1,16 @@
 package org.dromara.system.controller.app;
 
 import cn.dev33.satoken.annotation.SaCheckPermission;
+import cn.dev33.satoken.annotation.SaIgnore;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.dromara.common.core.domain.R;
+import org.dromara.common.mybatis.core.page.PageQuery;
+import org.dromara.common.mybatis.core.page.TableDataInfo;
+import org.dromara.system.domain.bo.EventMenuBo;
+import org.dromara.system.domain.vo.GameNavigatorVo;
 import org.dromara.system.domain.vo.VsNavBottomMainVo;
+import org.dromara.system.service.IGameNavigatorService;
 import org.dromara.system.service.IVsNavBottomMainService;
 import org.springframework.validation.annotation.Validated;
 import org.springframework.web.bind.annotation.GetMapping;
@@ -14,6 +20,10 @@ import org.springframework.web.bind.annotation.RestController;
 
 import java.util.List;
 
+/**
+ * app-首页菜单
+ */
+@SaIgnore
 @Slf4j
 @Validated
 @RequiredArgsConstructor
@@ -21,13 +31,14 @@ import java.util.List;
 @RequestMapping("/app/index")
 public class AppIndexController {
 
-    private final IVsNavBottomMainService vsNavBottomMainService;
+    private final IGameNavigatorService gameNavigatorService;
+
 
     /**
-     * 根据类型获取导航列表
+     * 获取赛事导航关联菜单列表
      */
-    @GetMapping
-    public R<List<VsNavBottomMainVo>> getNavListByType() {
-        return R.ok(vsNavBottomMainService.getNavListByType("4"));
+    @GetMapping("/{eventId}")
+    public List<GameNavigatorVo> listRelateMenu(@PathVariable Long eventId) {
+        return gameNavigatorService.listAppNavByEventId(eventId);
     }
 }

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

@@ -1,4 +1,43 @@
 package org.dromara.system.controller.app;
 
+
+import cn.dev33.satoken.annotation.SaCheckPermission;
+import cn.dev33.satoken.annotation.SaIgnore;
+import jakarta.validation.constraints.NotNull;
+import lombok.RequiredArgsConstructor;
+import org.dromara.common.core.domain.R;
+import org.dromara.system.domain.vo.AppEventMdVo;
+import org.dromara.system.service.IAppEventMdService;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * app-富文本相关
+ * type:1:竞赛流程 2:竞赛项目 3:活动议程 4:项目介绍 5:竞赛流程 6:赛事分组 7:运动员号码簿 8:项目场地
+ */
+@SaIgnore
+@Validated
+@RequiredArgsConstructor
+@RestController
+@RequestMapping("/app/markdown")
 public class AppMarkdownController {
+    private final IAppEventMdService appEventMdService;
+
+    /**
+     * 根据赛事id和类型获取移动端富文本详细信息
+     *
+     * @param eventId 赛事id
+     * @param type    类型
+     */
+    // @SaCheckPermission("system:eventMd:query")
+    @GetMapping("/{eventId}/{type}")
+    public R<AppEventMdVo> getInfoByEventAndType(@NotNull(message = "赛事id不能为空")
+                                                 @PathVariable Long eventId,
+                                                 @NotNull(message = "文本类型不能为空")
+                                                 @PathVariable Integer type) {
+        return R.ok(appEventMdService.queryByEventIdAndType(eventId, type));
+    }
 }

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

@@ -1,6 +1,7 @@
 package org.dromara.system.controller.app;
 
 
+import cn.dev33.satoken.annotation.SaIgnore;
 import lombok.RequiredArgsConstructor;
 import org.dromara.system.domain.vo.GameEventProjectVo;
 import org.dromara.system.service.IGameEventProjectService;
@@ -12,6 +13,10 @@ import org.springframework.web.bind.annotation.RestController;
 
 import java.util.List;
 
+/**
+ * app-赛事项目
+ */
+@SaIgnore
 @Validated
 @RequiredArgsConstructor
 @RestController

+ 3 - 2
ruoyi-modules/ruoyi-game-event/src/main/java/org/dromara/system/controller/app/ScoreController.java

@@ -1,5 +1,6 @@
 package org.dromara.system.controller.app;
 
+import cn.dev33.satoken.annotation.SaIgnore;
 import lombok.RequiredArgsConstructor;
 import org.dromara.system.domain.vo.GameScoreVo;
 import org.dromara.system.domain.vo.GameTeamVo;
@@ -14,9 +15,9 @@ import java.util.List;
 import java.util.Map;
 
 /**
- * 获奖名单
+ * app-获奖名单
  */
-
+@SaIgnore
 @Validated
 @RequiredArgsConstructor
 @RestController

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

@@ -81,4 +81,12 @@ public interface IGameNavigatorService {
      * @return
      */
     TableDataInfo<GameNavigatorVo> queryPageListByEventId(Long eventId, PageQuery pageQuery);
+
+
+    /**
+     * app获取赛事对应的菜单
+     * @param eventId
+     * @return
+     */
+    List<GameNavigatorVo> listAppNavByEventId(Long eventId);
 }

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

@@ -0,0 +1,171 @@
+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.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Service;
+import org.springframework.web.multipart.MultipartFile;
+
+import javax.sql.DataSource;
+import java.io.*;
+import java.net.URLEncoder;
+import java.nio.charset.StandardCharsets;
+import java.sql.Connection;
+import java.sql.SQLException;
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+
+@Slf4j
+@Service
+public class DatabaseBackupRestoreService {
+
+    @Value("${spring.datasource.dynamic.datasource.master.url}")
+    private String url;
+    @Value("${spring.datasource.dynamic.datasource.master.username}")
+    private String username;
+    @Value("${spring.datasource.dynamic.datasource.master.password}")
+    private String password;
+    @Autowired
+    private DataSource dataSource;
+    private String getDatabaseName() {
+        return url.split("/")[3].split("\\?")[0];
+    }
+
+    /**
+     * 备份数据库并写入 HttpServletResponse,触发文件下载
+     */
+    public void backupDatabaseToResponse(HttpServletResponse response) throws IOException {
+        String dbName = getDatabaseName();
+
+        // 生成文件名
+        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd_HHmmss");
+        String filename = "db_backup_" + LocalDateTime.now().format(formatter) + ".sql";
+
+        response.reset();
+        response.setContentType("application/octet-stream");
+        String encodedFilename = URLEncoder.encode(filename, StandardCharsets.UTF_8);
+        response.setHeader("Content-Disposition", "attachment; filename*=UTF-8''" + encodedFilename);
+
+        ProcessBuilder pb = new ProcessBuilder(
+            "mysqldump",
+            "-u" + username,
+            "--password=" + password,
+            "--replace",
+            dbName
+        );
+        pb.redirectErrorStream(true);
+
+        Process process;
+        try {
+            process = pb.start();
+        } catch (Exception e) {
+            log.error("启动 mysqldump 失败", e);
+            throw new IOException("无法启动备份进程: " + e.getMessage(), e);
+        }
+
+        try (OutputStream out = response.getOutputStream();
+             InputStream in = process.getInputStream()) {
+
+            ByteArrayOutputStream buffer = new ByteArrayOutputStream();
+            byte[] data = new byte[4096];
+            int len, total = 0;
+
+            while ((len = in.read(data)) != -1) {
+                buffer.write(data, 0, len);
+                out.write(data, 0, len);
+                total += len;
+            }
+            int exitCode = process.waitFor();
+            if (exitCode != 0) {
+                String errorOutput = buffer.toString(StandardCharsets.UTF_8);
+                log.error("mysqldump 失败,退出码: {}, 错误: {}", exitCode, errorOutput);
+                throw new RuntimeException("备份失败: " + errorOutput);
+            }
+            out.flush();
+
+            log.info("备份完成,共输出 {} 字节,文件名: {}", total, filename);
+
+        } catch (Exception e) {
+            log.error("备份失败", e);
+            throw new IOException("备份失败: " + e.getMessage(), e);
+        } finally {
+            process.destroyForcibly();
+        }
+    }
+
+    /**
+     * 从 MultipartFile 恢复数据库
+     */
+
+    public String restoreFromMultipartFile(MultipartFile file) throws IOException {
+        try (
+            Connection conn = dataSource.getConnection();
+            InputStream rawInputStream = file.getInputStream();
+            InputStream filteredStream = new FilteredCommentInputStream(rawInputStream, StandardCharsets.UTF_8);
+            InputStreamReader reader = new InputStreamReader(filteredStream, StandardCharsets.UTF_8)
+        ) {
+            boolean autoCommit = conn.getAutoCommit();
+            conn.setAutoCommit(false);
+
+            try {
+                ScriptRunner scriptRunner = new ScriptRunner(conn);
+                scriptRunner.setLogWriter(null);        // 不打印每条 SQL
+                scriptRunner.setStopOnError(true);      // 遇错停止
+                scriptRunner.setEscapeProcessing(false); // 提高性能,如果你的 SQL 不含 \n \t 转义
+
+                scriptRunner.runScript(reader);
+
+                conn.commit();
+                return "恢复成功";
+
+            } catch (Exception e) {
+                try {
+                    conn.rollback();
+                } catch (SQLException rollbackEx) {
+                    throw new IOException("恢复失败且回滚异常: " + rollbackEx.getMessage(), rollbackEx);
+                }
+                throw new IOException("SQL 脚本执行失败: " + e.getMessage(), e);
+            } finally {
+                try {
+                    conn.setAutoCommit(autoCommit);
+                } catch (SQLException e) {
+                    log.warn("恢复 AutoCommit 状态失败", e);
+                }
+            }
+
+        } catch (SQLException e) {
+            throw new IOException("数据库连接失败: " + e.getMessage(), e);
+        }
+    }
+    /**
+     * 执行系统命令
+     */
+    private String executeCommand(String command, String operation) {
+        try {
+            ProcessBuilder processBuilder = new ProcessBuilder("bash", "-c", command);
+            processBuilder.redirectErrorStream(true);
+
+            Process process = processBuilder.start();
+
+            BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
+            StringBuilder output = new StringBuilder();
+            String line;
+            while ((line = reader.readLine()) != null) {
+                output.append(line).append("\n");
+            }
+
+            int exitCode = process.waitFor();
+            if (exitCode == 0) {
+                return operation + "成功: " + output.toString();
+            } else {
+                return operation + "失败,退出码: " + exitCode + ",输出: " + output.toString();
+            }
+        } catch (Exception e) {
+            log.error(operation + "异常", e);
+            return operation + "异常: " + e.getMessage();
+        }
+    }
+}

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

@@ -68,6 +68,9 @@ public class ArticleServiceImpl implements IArticleService {
      */
     @Override
     public TableDataInfo<ArticleVo> queryPageList(ArticleBo bo, PageQuery pageQuery) {
+        Object cacheObject = RedisUtils.getCacheObject(GameEventConstant.DEFAULT_EVENT_ID);
+        Long defaultEventId = Long.valueOf(cacheObject.toString());
+        bo.setEventId(defaultEventId);
         LambdaQueryWrapper<Article> lqw = buildQueryWrapper(bo);
         Page<ArticleVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
         // 查询赛事相关信息
@@ -133,6 +136,9 @@ public class ArticleServiceImpl implements IArticleService {
     public Boolean insertByBo(ArticleBo bo) {
         Article add = MapstructUtils.convert(bo, Article.class);
         validEntityBeforeSave(add);
+        Object cacheObject = RedisUtils.getCacheObject(GameEventConstant.DEFAULT_EVENT_ID);
+        Long defaultEventId = Long.valueOf(cacheObject.toString());
+        add.setEventId(defaultEventId);
         boolean flag = baseMapper.insert(add) > 0;
         if (flag) {
             bo.setId(add.getId());
@@ -150,6 +156,9 @@ public class ArticleServiceImpl implements IArticleService {
     public Boolean updateByBo(ArticleBo bo) {
         Article update = MapstructUtils.convert(bo, Article.class);
         validEntityBeforeSave(update);
+        Object cacheObject = RedisUtils.getCacheObject(GameEventConstant.DEFAULT_EVENT_ID);
+        Long defaultEventId = Long.valueOf(cacheObject.toString());
+        update.setEventId(defaultEventId);
         return baseMapper.updateById(update) > 0;
     }
 
@@ -199,6 +208,7 @@ public class ArticleServiceImpl implements IArticleService {
             Wrappers.lambdaQuery(Article.class)
                 .eq(Article::getEventId, eventId)
                 .eq(Article::getType, articleTypeIntroduce)
+                .eq(Article::getIsDefault, 1)
         );
     }
 

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

@@ -178,4 +178,27 @@ public class IGameNavigatorServiceImpl implements IGameNavigatorService {
         );
         return TableDataInfo.build(result);
     }
+
+    /**
+     * app获取赛事对应的菜单
+     *
+     * @param eventId
+     * @return
+     */
+    @Override
+    public List<GameNavigatorVo> listAppNavByEventId(Long eventId) {
+        EventMenuVo vo = eventMenuService.queryByEventId(eventId);
+        List<Long> navIdList = Optional.ofNullable(vo)
+            .map(v -> JSONUtil.toList(v.getMenuList(), Long.class))
+            .orElse(Collections.emptyList());
+        // 如果 navIdList 为空,直接返回空分页
+        if (navIdList.isEmpty()) {
+            return List.of();
+        }
+        List<GameNavigatorVo> result = baseMapper.selectVoList(
+            Wrappers.lambdaQuery(GameNavigator.class)
+                .in(GameNavigator::getNavId, navIdList)
+        );
+        return result;
+    }
 }

+ 94 - 0
ruoyi-modules/ruoyi-game-event/src/main/java/org/dromara/system/util/FilteredCommentInputStream.java

@@ -0,0 +1,94 @@
+package org.dromara.system.util;
+
+import java.io.*;
+import java.nio.charset.Charset;
+
+/**
+ * 过滤掉 SQL 文件中的注释行和 mysqldump 提示行
+ */
+public class FilteredCommentInputStream extends InputStream {
+
+    private final BufferedReader bufferedReader;
+    private String currentLine;
+    private byte[] buffer;
+    private int bufferPos = 0;
+    private boolean closed = false;
+
+    public FilteredCommentInputStream(InputStream in, Charset charset) {
+        this.bufferedReader = new BufferedReader(new InputStreamReader(in, charset));
+    }
+
+    private void fillBuffer() throws IOException {
+        if (closed) return;
+
+        StringBuilder sb = new StringBuilder();
+        while (true) {
+            currentLine = bufferedReader.readLine();
+            if (currentLine == null) {
+                if (sb.length() == 0) {
+                    buffer = null;
+                } else {
+                    buffer = sb.toString().getBytes();
+                }
+                break;
+            }
+
+            String trimmed = currentLine.trim();
+            if (trimmed.isEmpty() ||
+                trimmed.startsWith("--") ||
+                trimmed.startsWith("mysqldump:") ||
+                (trimmed.startsWith("/*") && trimmed.endsWith("*/") && !trimmed.contains("SET"))) {
+                continue;
+            }
+
+            sb.append(currentLine).append("\n");
+            // 继续读,直到遇到分号或完成一个语句块(可扩展)
+            if (trimmed.endsWith(";")) {
+                break;
+            }
+        }
+
+        buffer = sb.length() > 0 ? sb.toString().getBytes() : null;
+        bufferPos = 0;
+    }
+
+    @Override
+    public int read() throws IOException {
+        if (buffer == null || bufferPos >= buffer.length) {
+            fillBuffer();
+            if (buffer == null) return -1;
+        }
+        return buffer[bufferPos++] & 0xFF;
+    }
+
+    @Override
+    public int read(byte[] b, int off, int len) throws IOException {
+        if (b == null) throw new NullPointerException();
+        if (off < 0 || len < 0 || len > b.length - off) {
+            throw new IndexOutOfBoundsException();
+        }
+        if (len == 0) return 0;
+
+        int total = 0;
+        while (total < len) {
+            if (buffer == null || bufferPos >= buffer.length) {
+                fillBuffer();
+                if (buffer == null) break;
+            }
+
+            int remaining = buffer.length - bufferPos;
+            int toCopy = Math.min(remaining, len - total);
+            System.arraycopy(buffer, bufferPos, b, off + total, toCopy);
+            bufferPos += toCopy;
+            total += toCopy;
+        }
+
+        return total == 0 ? -1 : total;
+    }
+
+    @Override
+    public void close() throws IOException {
+        closed = true;
+        bufferedReader.close();
+    }
+}

+ 11 - 0
本周改动.md

@@ -12,4 +12,15 @@
 <li>美化赛事操作列样式</li>
 
 
+<h2>8.19</h2>
 
+<li>完成用户反馈</li>
+<li>完成app端赛事相关的富文本编辑</li>
+<li>完善app端部分接口</li>
+<li>修改赛事列表操作列位置</li>
+<li>修改菜单栏图标显示</li>
+<li>还原赛事-备份、恢复</li>
+<li>活动预热与默认赛事关联</li>
+<li>补充数据测试功能</li>
+<li>修改各模块列表项映射格式,方便后期维护</li>
+<li>修复成绩模块显示逻辑bug</li>