4 次代码提交 07d0971446 ... 74cca057ba

作者 SHA1 备注 提交日期
  wenkai 74cca057ba fix:增加校验 13 小时之前
  wenkai 5e98545d50 Merge branch 'dev' into wk-dev-8-13 13 小时之前
  wenkai a781b9a959 fix:增加NPE检查 1 天之前
  wenkai 42761d811a fix:添加文件校验 2 天之前

+ 0 - 1
ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/service/impl/TestDemoServiceImpl.java

@@ -94,7 +94,6 @@ public class TestDemoServiceImpl implements ITestDemoService {
      * @param entity 实体类数据
      */
     private void validEntityBeforeSave(TestDemo entity) {
-        //TODO 做一些数据校验,如唯一约束
     }
 
     @Override

+ 0 - 2
ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/service/impl/TestTreeServiceImpl.java

@@ -75,13 +75,11 @@ public class TestTreeServiceImpl implements ITestTreeService {
      * @param entity 实体类数据
      */
     private void validEntityBeforeSave(TestTree entity) {
-        //TODO 做一些数据校验,如唯一约束
     }
 
     @Override
     public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
         if (isValid) {
-            //TODO 做一些业务上的校验,判断是否需要校验
         }
         return baseMapper.deleteByIds(ids) > 0;
     }

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

@@ -58,7 +58,7 @@ public class NumberController {
     @PostMapping("/generateBib")
     public void generateNumberBib(HttpServletResponse response,
                                   @RequestPart("bgImage") MultipartFile bgImage,
-                                  @RequestPart("logo") MultipartFile logo,
+                                  @RequestPart(name = "logo") MultipartFile logo,
                                   GenerateBibBo bibParam) {
         gameEventService.generateNumberBib(response, bgImage, logo, bibParam);
     }

+ 16 - 14
ruoyi-modules/ruoyi-game-event/src/main/java/org/dromara/system/service/impl/AdviceServiceImpl.java

@@ -1,31 +1,30 @@
 package org.dromara.system.service.impl;
 
 import cn.hutool.core.util.StrUtil;
-import org.dromara.common.core.utils.MapstructUtils;
-import org.dromara.common.core.utils.StringUtils;
-import org.dromara.common.mybatis.core.page.TableDataInfo;
-import org.dromara.common.mybatis.core.page.PageQuery;
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
+import org.dromara.common.core.utils.MapstructUtils;
+import org.dromara.common.core.utils.StringUtils;
+import org.dromara.common.mybatis.core.page.PageQuery;
+import org.dromara.common.mybatis.core.page.TableDataInfo;
 import org.dromara.common.redis.utils.RedisUtils;
+import org.dromara.system.domain.Advice;
+import org.dromara.system.domain.bo.AdviceBo;
 import org.dromara.system.domain.bo.GameTeamBo;
 import org.dromara.system.domain.constant.GameEventConstant;
-import org.dromara.system.domain.vo.GameTeamVo;
-import org.dromara.system.service.IGameTeamService;
-import org.springframework.stereotype.Service;
-import org.dromara.system.domain.bo.AdviceBo;
 import org.dromara.system.domain.vo.AdviceVo;
-import org.dromara.system.domain.Advice;
+import org.dromara.system.domain.vo.GameTeamVo;
 import org.dromara.system.mapper.AdviceMapper;
 import org.dromara.system.service.IAdviceService;
+import org.dromara.system.service.IGameTeamService;
+import org.springframework.stereotype.Service;
 
+import java.util.Collection;
 import java.util.Collections;
 import java.util.List;
-import java.util.Map;
-import java.util.Collection;
 import java.util.stream.Collectors;
 
 /**
@@ -67,10 +66,13 @@ public class AdviceServiceImpl implements IAdviceService {
         bo.setEventId(defaultEventId);
         LambdaQueryWrapper<Advice> lqw = buildQueryWrapper(bo);
         Page<AdviceVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
-        result.getRecords().stream()
+        result.getRecords()
+            .stream()
             .map(vo -> {
                 GameTeamVo gameTeamVo = gameTeamService.queryById(vo.getTeamId());
-                vo.setTeamName(gameTeamVo.getTeamName());
+                if(gameTeamVo!=null) {
+                    vo.setTeamName(gameTeamVo.getTeamName());
+                }
                 return vo;
             })
             .collect(Collectors.toList());

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

@@ -83,7 +83,15 @@ public class GameEventServiceImpl implements IGameEventService {
     private IGameEventGroupService gameEventGroupService;
     private static final ExecutorService PDF_GENERATION_EXECUTOR =
         Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors() * 2);
-
+    // 常见图片类型的文件头(前几个字节)
+    private static final String[] IMAGE_HEADER_PREFIXES = {
+        "FFD8FF", // JPEG
+        "89504E47", // PNG
+        "47494638", // GIF
+        "49492A00", // TIFF (little endian)
+        "4D4D002A", // TIFF (big endian)
+        "424D"      // BMP
+    };
     /**
      * 查询赛事基本信息
      *
@@ -578,7 +586,15 @@ public class GameEventServiceImpl implements IGameEventService {
     }
 
     @Override
-    public void generateNumberBib(HttpServletResponse response, MultipartFile bgImage, MultipartFile logo, GenerateBibBo bibParam) {
+    public void generateNumberBib(HttpServletResponse response,
+                                  MultipartFile bgImage, MultipartFile logo,
+                                  GenerateBibBo bibParam) {
+        if (bgImage!=null&&!isImage(bgImage)) {
+            throw new ServiceException("背景图不是图片格式");
+        }
+        if (logo!=null&&!isImage(logo)) {
+            throw new ServiceException("logo不是图片格式");
+        }
         //1.查询当前赛事所有队员数据
         GameAthleteBo gameAthleteBo = new GameAthleteBo();
         Object cacheObject = RedisUtils.getCacheObject(GameEventConstant.DEFAULT_EVENT_ID);
@@ -603,6 +619,41 @@ public class GameEventServiceImpl implements IGameEventService {
         generateBib(response, bgImage, logo, eventVo.getEventName(), gameEventGroup.getGroupName(), athleteVoList, teamNameMap, projectMap, bibParam);
     }
 
+    /**
+     * 判断是否为图片
+     * @param file
+     * @return
+     */
+    public static boolean isImage(MultipartFile file) {
+        if (file == null || file.isEmpty()) {
+            return false;
+        }
+
+        try (InputStream is = file.getInputStream()) {
+            byte[] header = new byte[8]; // 读取前8字节足够判断大部分图片
+            int bytesRead = is.read(header);
+            if (bytesRead < 4) {
+                return false;
+            }
+
+            StringBuilder hexHeader = new StringBuilder();
+            for (int i = 0; i < bytesRead; i++) {
+                hexHeader.append(String.format("%02X", header[i] & 0xFF));
+            }
+
+            String headerStr = hexHeader.toString();
+            for (String prefix : IMAGE_HEADER_PREFIXES) {
+                if (headerStr.startsWith(prefix)) {
+                    return true;
+                }
+            }
+
+            return false;
+
+        } catch (IOException e) {
+            return false;
+        }
+    }
     /**
      * 生成号码布并直接通过 HttpServletResponse 返回 ZIP 文件
      *
@@ -786,7 +837,7 @@ public class GameEventServiceImpl implements IGameEventService {
         StringBuilder joinProject = new StringBuilder();
         StringJoiner joiner = new StringJoiner("、"); // 指定分隔符
         athlete.getProjectList().forEach(projectId -> {
-            String projectName = projectMap.get(Long.valueOf(projectId));
+            String projectName = projectMap.getOrDefault(Long.valueOf(projectId),"");
             if (projectName != null) {
                 joiner.add(projectName);
             }
@@ -808,7 +859,7 @@ public class GameEventServiceImpl implements IGameEventService {
                     }
                 """,
             eventName, athlete.getAthleteId(), athlete.getAthleteCode(),
-            joinProject, teamNameMap.get(athlete.getTeamId()), athlete.getName(),
+            joinProject, teamNameMap.getOrDefault(athlete.getTeamId(),""), athlete.getName(),
             athlete.getGender(), athlete.getAge(), groupName
         );
         return qrData;
@@ -1081,19 +1132,19 @@ public class GameEventServiceImpl implements IGameEventService {
             // 没有组别,直接返回项目开始时间
             return project.getStartTime();
         }
-        
+
         // 有组别,找到最早的组别开始时间
         Date earliestGroupTime = project.getGroups().stream()
             .map(GroupProgressVo::getBeginTime)
             .filter(Objects::nonNull)
             .min(Date::compareTo)
             .orElse(null);
-        
+
         // 如果组别时间存在,与项目时间比较,返回较早的时间
         if (earliestGroupTime != null && project.getStartTime() != null) {
             return earliestGroupTime.before(project.getStartTime()) ? earliestGroupTime : project.getStartTime();
         }
-        
+
         // 如果组别时间不存在,返回项目时间
         return earliestGroupTime != null ? earliestGroupTime : project.getStartTime();
     }