From 20fbd20b1f2f72b403da7c1ac399aaa9f37b955d Mon Sep 17 00:00:00 2001 From: luoweijian <1329394916@qq.com> Date: Mon, 6 Jul 2026 16:17:19 +0800 Subject: [PATCH 1/4] =?UTF-8?q?bug=E4=BF=AE=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/impl/AdminSearchExamRecordDomainServiceImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/project/exam/domain/service/impl/AdminSearchExamRecordDomainServiceImpl.java b/src/main/java/com/project/exam/domain/service/impl/AdminSearchExamRecordDomainServiceImpl.java index baa22f3..7391f97 100644 --- a/src/main/java/com/project/exam/domain/service/impl/AdminSearchExamRecordDomainServiceImpl.java +++ b/src/main/java/com/project/exam/domain/service/impl/AdminSearchExamRecordDomainServiceImpl.java @@ -147,7 +147,7 @@ public class AdminSearchExamRecordDomainServiceImpl implements AdminSearchExamRe private ExamRecordPictureDTO buildPictureDTO(ExamRecordPictureEntity entity) { ExamRecordPictureDTO dto = entity.toDTO(ExamRecordPictureDTO::new); - dto.setPreviewUrl(minIoUtils.getPreviewUrl(entity.getFilePath())); + dto.setPreviewUrl(minIoUtils.getPublicUrl(entity.getFilePath())); return dto; } } From f2906607d669b970ccfb32512ab2c577edee59fb Mon Sep 17 00:00:00 2001 From: luoweijian <1329394916@qq.com> Date: Mon, 6 Jul 2026 16:26:02 +0800 Subject: [PATCH 2/4] =?UTF-8?q?bug=E4=BF=AE=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../task/domain/service/strategy/ClassicTaskConfigStrategy.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/project/task/domain/service/strategy/ClassicTaskConfigStrategy.java b/src/main/java/com/project/task/domain/service/strategy/ClassicTaskConfigStrategy.java index 67a381d..094b227 100644 --- a/src/main/java/com/project/task/domain/service/strategy/ClassicTaskConfigStrategy.java +++ b/src/main/java/com/project/task/domain/service/strategy/ClassicTaskConfigStrategy.java @@ -119,7 +119,7 @@ public class ClassicTaskConfigStrategy implements TaskConfigStrategy { dto.setVagueGraspNum(0); } if (dto.getTotalScore() == null) { - dto.setTotalScore(0); + dto.setTotalScore(100); } } } From 3f233aa469ee55e5dcd750614412c02afe901857 Mon Sep 17 00:00:00 2001 From: luoweijian <1329394916@qq.com> Date: Mon, 6 Jul 2026 19:35:43 +0800 Subject: [PATCH 3/4] =?UTF-8?q?bug=E4=BF=AE=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ClassicPaperSetApplicationService.java | 4 +- ...ClassicPaperSetApplicationServiceImpl.java | 10 +++- .../controller/ClassicPaperSetController.java | 2 +- .../ImportClassicPaperDomainServiceImpl.java | 23 ++++++++ .../strategy/ClassicTaskConfigStrategy.java | 59 ++++++++++++++++++- 5 files changed, 90 insertions(+), 8 deletions(-) diff --git a/src/main/java/com/project/classicpaper/application/ClassicPaperSetApplicationService.java b/src/main/java/com/project/classicpaper/application/ClassicPaperSetApplicationService.java index 152d84d..df814fe 100644 --- a/src/main/java/com/project/classicpaper/application/ClassicPaperSetApplicationService.java +++ b/src/main/java/com/project/classicpaper/application/ClassicPaperSetApplicationService.java @@ -6,8 +6,6 @@ import com.project.classicpaper.domain.dto.ClassicPaperSetDTO; import com.project.classicpaper.domain.param.ClassicPaperSetParam; import org.springframework.web.multipart.MultipartFile; -import java.util.List; - public interface ClassicPaperSetApplicationService { /** @@ -30,7 +28,7 @@ public interface ClassicPaperSetApplicationService { /** * 废弃套题组(连带所有版本) */ - Result delete(List ids) throws Exception; + Result delete(String ids) throws Exception; /** * 更新分值比例,同时计算每道题的分值 diff --git a/src/main/java/com/project/classicpaper/application/impl/ClassicPaperSetApplicationServiceImpl.java b/src/main/java/com/project/classicpaper/application/impl/ClassicPaperSetApplicationServiceImpl.java index 4b2f61a..68fee9b 100644 --- a/src/main/java/com/project/classicpaper/application/impl/ClassicPaperSetApplicationServiceImpl.java +++ b/src/main/java/com/project/classicpaper/application/impl/ClassicPaperSetApplicationServiceImpl.java @@ -22,6 +22,7 @@ import com.project.classicpaper.domain.entity.ClassicCategoryEntity; import com.project.classicpaper.domain.service.*; import com.project.question.domain.entity.QuestionEntity; import com.project.question.domain.service.QuestionBaseService; +import org.apache.commons.lang3.StringUtils; import org.springframework.web.multipart.MultipartFile; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @@ -229,8 +230,13 @@ public class ClassicPaperSetApplicationServiceImpl implements ClassicPaperSetApp @Override @Transactional(rollbackFor = Exception.class) - public Result delete(List ids) throws Exception { - classicPaperSetBaseService.removeBatchByIds(ids); + public Result delete(String ids) throws Exception { + + if (StringUtils.isBlank(ids)) { + throw new BusinessErrorException("ids is empty"); + } + List idList = Arrays.asList(ids.split(",")).stream().map(id -> Long.valueOf(id)).collect(Collectors.toList()); + classicPaperSetBaseService.removeBatchByIds(idList); return Result.success("删除成功"); } diff --git a/src/main/java/com/project/classicpaper/controller/ClassicPaperSetController.java b/src/main/java/com/project/classicpaper/controller/ClassicPaperSetController.java index 0ddd55b..2c2251b 100644 --- a/src/main/java/com/project/classicpaper/controller/ClassicPaperSetController.java +++ b/src/main/java/com/project/classicpaper/controller/ClassicPaperSetController.java @@ -52,7 +52,7 @@ public class ClassicPaperSetController { } @PostMapping("/delete") - public Result delete(List ids) throws Exception { + public Result delete(String ids) throws Exception { return classicPaperSetApplicationService.delete(ids); } diff --git a/src/main/java/com/project/classicpaper/domain/service/impl/ImportClassicPaperDomainServiceImpl.java b/src/main/java/com/project/classicpaper/domain/service/impl/ImportClassicPaperDomainServiceImpl.java index 9c5cb7e..51af7cd 100644 --- a/src/main/java/com/project/classicpaper/domain/service/impl/ImportClassicPaperDomainServiceImpl.java +++ b/src/main/java/com/project/classicpaper/domain/service/impl/ImportClassicPaperDomainServiceImpl.java @@ -1,5 +1,6 @@ package com.project.classicpaper.domain.service.impl; +import com.fasterxml.jackson.databind.ObjectMapper; import com.project.classicpaper.domain.dto.ClassicPaperDTO; import com.project.classicpaper.domain.dto.ClassicPaperQuestionDTO; import com.project.classicpaper.domain.dto.ClassicPaperSetDTO; @@ -19,6 +20,7 @@ import com.project.question.domain.entity.QuestionEntity; import com.project.question.domain.enums.QuestionSourceTypeEnum; import com.project.question.domain.service.QuestionBaseService; import com.project.question.domain.service.SaveQuestionDomainService; +import com.project.task.config.ExamScoreRatioConfig; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @@ -27,6 +29,7 @@ import org.springframework.web.multipart.MultipartFile; import java.util.ArrayList; import java.util.HashMap; +import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.TreeMap; @@ -62,6 +65,11 @@ public class ImportClassicPaperDomainServiceImpl implements ImportClassicPaperDo @Autowired private MinIoUtils minIoUtils; + @Autowired + private ExamScoreRatioConfig examScoreRatioConfig; + + private final ObjectMapper objectMapper = new ObjectMapper(); + @Override @Transactional(rollbackFor = Exception.class) public ClassicPaperSetDTO importFromWord(MultipartFile file, Long classicCategoryId, String paperName) throws Exception { @@ -115,6 +123,21 @@ public class ImportClassicPaperDomainServiceImpl implements ImportClassicPaperDo paperSet.setTrueFalseNum(trueFalseNum); paperSet.setShortAnswerNum(shortAnswerNum); paperSet.setStatus(ClassicPaperStatusEnum.DRAFT.getValue()); + + // 设置默认分值比例(只包含数量 > 0 的题型) + Map ratioMap = new LinkedHashMap<>(); + if (singleChoiceNum > 0) ratioMap.put("single", examScoreRatioConfig.getSingle()); + if (multipleChoiceNum > 0) ratioMap.put("multiple", examScoreRatioConfig.getMultiple()); + if (trueFalseNum > 0) ratioMap.put("trueFalse", examScoreRatioConfig.getTrueFalse()); + if (shortAnswerNum > 0) ratioMap.put("shortAnswer", examScoreRatioConfig.getShortAnswer()); + if (!ratioMap.isEmpty()) { + try { + paperSet.setScoreRatio(objectMapper.writeValueAsString(ratioMap)); + } catch (Exception e) { + log.warn(">>> [历史导入] scoreRatio 序列化失败", e); + } + } + classicPaperSetBaseService.save(paperSet); // 3. 创建套卷(版本1) diff --git a/src/main/java/com/project/task/domain/service/strategy/ClassicTaskConfigStrategy.java b/src/main/java/com/project/task/domain/service/strategy/ClassicTaskConfigStrategy.java index 094b227..b90d46d 100644 --- a/src/main/java/com/project/task/domain/service/strategy/ClassicTaskConfigStrategy.java +++ b/src/main/java/com/project/task/domain/service/strategy/ClassicTaskConfigStrategy.java @@ -6,25 +6,37 @@ import cn.hutool.core.date.DateUtil; import cn.hutool.core.lang.Validator; import cn.hutool.core.util.StrUtil; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.fasterxml.jackson.databind.ObjectMapper; import com.project.base.domain.exception.BusinessErrorException; +import com.project.classicpaper.domain.entity.ClassicPaperSetEntity; +import com.project.classicpaper.domain.service.ClassicPaperSetBaseService; import com.project.task.domain.dto.TaskDTO; import com.project.task.domain.entity.TaskEntity; import com.project.task.domain.service.TaskBaseService; +import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.util.Map; import java.util.Objects; /** * 经典套题模式:校验 + 字段默认值 - * 赋分来自套卷本身,此处不做赋分计算 */ +@Slf4j @Component public class ClassicTaskConfigStrategy implements TaskConfigStrategy { @Autowired private TaskBaseService taskBaseService; + @Autowired + private ClassicPaperSetBaseService classicPaperSetBaseService; + + private final ObjectMapper objectMapper = new ObjectMapper(); + @Override public void validateAndConfigure(TaskDTO dto) throws Exception { validate(dto); @@ -85,7 +97,7 @@ public class ClassicTaskConfigStrategy implements TaskConfigStrategy { } /** - * 经典模式下题目数量和分数来自套卷,DTO 中可能为 null,赋默认值 0 避免 NPE + * 经典模式下题目数量和分数来自套卷,DTO 中可能为 null,赋默认值避免 NPE */ private void fillDefaults(TaskDTO dto) { if (dto.getSingleChoiceNum() == null) { @@ -100,6 +112,10 @@ public class ClassicTaskConfigStrategy implements TaskConfigStrategy { if (dto.getShortAnswerNum() == null) { dto.setShortAnswerNum(0); } + + // 从套题组的分值比例计算每题分值(保留2位小数) + calculateScoresFromRatio(dto); + if (dto.getSingleChoiceScore() == null) { dto.setSingleChoiceScore(0.0); } @@ -122,4 +138,43 @@ public class ClassicTaskConfigStrategy implements TaskConfigStrategy { dto.setTotalScore(100); } } + + /** + * 从 ClassicPaperSet.scoreRatio 解析比例,计算每题分值 + * 公式:每题分值 = 100 × 题型比例 / 总比例 / 该题型数量 + */ + private void calculateScoresFromRatio(TaskDTO dto) { + if (dto.getClassicPaperSetId() == null) { + return; + } + ClassicPaperSetEntity paperSet = classicPaperSetBaseService.getById(dto.getClassicPaperSetId()); + if (paperSet == null || StrUtil.isBlank(paperSet.getScoreRatio())) { + return; + } + try { + Map ratioMap = objectMapper.readValue(paperSet.getScoreRatio(), Map.class); + int totalRatio = ratioMap.values().stream().mapToInt(Integer::intValue).sum(); + if (totalRatio <= 0) { + return; + } + if (paperSet.getSingleChoiceNum() != null && paperSet.getSingleChoiceNum() > 0) { + double perScore = 100.0 * ratioMap.getOrDefault("single", 0) / totalRatio / paperSet.getSingleChoiceNum(); + dto.setSingleChoiceScore(BigDecimal.valueOf(perScore).setScale(2, RoundingMode.HALF_UP).doubleValue()); + } + if (paperSet.getMultipleChoiceNum() != null && paperSet.getMultipleChoiceNum() > 0) { + double perScore = 100.0 * ratioMap.getOrDefault("multiple", 0) / totalRatio / paperSet.getMultipleChoiceNum(); + dto.setMultipleChoiceScore(BigDecimal.valueOf(perScore).setScale(2, RoundingMode.HALF_UP).doubleValue()); + } + if (paperSet.getTrueFalseNum() != null && paperSet.getTrueFalseNum() > 0) { + double perScore = 100.0 * ratioMap.getOrDefault("trueFalse", 0) / totalRatio / paperSet.getTrueFalseNum(); + dto.setTrueFalseScore(BigDecimal.valueOf(perScore).setScale(2, RoundingMode.HALF_UP).doubleValue()); + } + if (paperSet.getShortAnswerNum() != null && paperSet.getShortAnswerNum() > 0) { + double perScore = 100.0 * ratioMap.getOrDefault("shortAnswer", 0) / totalRatio / paperSet.getShortAnswerNum(); + dto.setShortAnswerScore(BigDecimal.valueOf(perScore).setScale(2, RoundingMode.HALF_UP).doubleValue()); + } + } catch (Exception e) { + log.warn(">>> [经典模式] scoreRatio 解析失败, paperSetId={}", dto.getClassicPaperSetId(), e); + } + } } From 860e8569a5ec44566d6f4507404630e93d981dc0 Mon Sep 17 00:00:00 2001 From: luoweijian <1329394916@qq.com> Date: Tue, 7 Jul 2026 09:30:58 +0800 Subject: [PATCH 4/4] =?UTF-8?q?bug=E4=BF=AE=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ding/domain/service/impl/AuthDomainServiceImpl.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/project/ding/domain/service/impl/AuthDomainServiceImpl.java b/src/main/java/com/project/ding/domain/service/impl/AuthDomainServiceImpl.java index e2db61e..f9e90ce 100644 --- a/src/main/java/com/project/ding/domain/service/impl/AuthDomainServiceImpl.java +++ b/src/main/java/com/project/ding/domain/service/impl/AuthDomainServiceImpl.java @@ -15,6 +15,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.core.Authentication; import org.springframework.security.core.AuthenticationException; +import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.stereotype.Service; import org.springframework.security.core.GrantedAuthority; @@ -92,7 +93,9 @@ public class AuthDomainServiceImpl implements AuthDomainService { if (Objects.nonNull(adminWhiteListEntity)) { roles.add("ROLE_ADMIN"); } - + if (adminWhiteListEntity.getAdminType() != null && adminWhiteListEntity.getAdminType() == 1) { + roles.add("ROLE_SUPER_ADMIN"); + } // 3. 生成 JWT String token = jwtUtils.createToken(user.getId(), roles);