diff --git a/src/main/java/com/project/classicpaper/application/ClassicPaperApplicationService.java b/src/main/java/com/project/classicpaper/application/ClassicPaperApplicationService.java index 998c751..caede53 100644 --- a/src/main/java/com/project/classicpaper/application/ClassicPaperApplicationService.java +++ b/src/main/java/com/project/classicpaper/application/ClassicPaperApplicationService.java @@ -9,7 +9,7 @@ public interface ClassicPaperApplicationService { /** * 单题重抽(仅 DRAFT 状态的版本可操作) */ - Result regenerateQuestion(Long paperId, Long questionId) throws Exception; + Result regenerateQuestion(Long paperId, Long paperQuestionId) throws Exception; /** * 切tab暂存:保存单个版本的编辑(名称、描述、题目排序/替换) diff --git a/src/main/java/com/project/classicpaper/application/ClassicPaperSetApplicationService.java b/src/main/java/com/project/classicpaper/application/ClassicPaperSetApplicationService.java index 2b874ec..4742002 100644 --- a/src/main/java/com/project/classicpaper/application/ClassicPaperSetApplicationService.java +++ b/src/main/java/com/project/classicpaper/application/ClassicPaperSetApplicationService.java @@ -19,8 +19,10 @@ public interface ClassicPaperSetApplicationService { /** * 套题组详情(含所有版本及其题目列表) + * @param setId 套题组ID + * @param paperId 可选,指定版本ID,传则只返回该版本,不传返回整组 */ - Result getDetail(Long setId); + Result getDetail(Long setId, Long paperId); /** * 废弃套题组(连带所有版本) diff --git a/src/main/java/com/project/classicpaper/application/impl/ClassicPaperApplicationServiceImpl.java b/src/main/java/com/project/classicpaper/application/impl/ClassicPaperApplicationServiceImpl.java index 9fd9d45..9ec6e87 100644 --- a/src/main/java/com/project/classicpaper/application/impl/ClassicPaperApplicationServiceImpl.java +++ b/src/main/java/com/project/classicpaper/application/impl/ClassicPaperApplicationServiceImpl.java @@ -19,8 +19,8 @@ public class ClassicPaperApplicationServiceImpl implements ClassicPaperApplicati private DraftPaperDomainService draftPaperDomainService; @Override - public Result regenerateQuestion(Long paperId, Long questionId) throws Exception { - return regenerateQuestionDomainService.regenerate(paperId, questionId); + public Result regenerateQuestion(Long paperId, Long paperQuestionId) throws Exception { + return regenerateQuestionDomainService.regenerate(paperId, paperQuestionId); } @Override 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 1f8ea55..3b87588 100644 --- a/src/main/java/com/project/classicpaper/application/impl/ClassicPaperSetApplicationServiceImpl.java +++ b/src/main/java/com/project/classicpaper/application/impl/ClassicPaperSetApplicationServiceImpl.java @@ -2,6 +2,7 @@ package com.project.classicpaper.application.impl; import cn.hutool.core.util.StrUtil; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.project.base.domain.exception.BusinessErrorException; import com.project.base.domain.result.PageResult; @@ -24,9 +25,13 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.util.ArrayList; +import java.util.LinkedHashMap; import java.util.List; +import java.util.Map; import java.util.stream.Collectors; +import com.fasterxml.jackson.databind.ObjectMapper; + @Service public class ClassicPaperSetApplicationServiceImpl implements ClassicPaperSetApplicationService { @@ -48,6 +53,9 @@ public class ClassicPaperSetApplicationServiceImpl implements ClassicPaperSetApp @Autowired private SavePaperSetDomainService savePaperSetDomainService; + @Autowired + private com.project.task.config.ExamScoreRatioConfig examScoreRatioConfig; + @Override public Result generate(ClassicPaperSetDTO request) throws Exception { return generateClassicPaperDomainService.generate(request); @@ -76,16 +84,41 @@ public class ClassicPaperSetApplicationServiceImpl implements ClassicPaperSetApp classicPaperSetBaseService.page(page, wrapper); - PageResult pageResult = new PageResult<>(page.convert(entity -> { + IPage dtoPage = page.convert(entity -> { ClassicPaperSetDTO dto = entity.toDTO(ClassicPaperSetDTO::new); dto.setStatusText(ClassicPaperStatusEnum.findByValue(entity.getStatus())); + + // 填充版本精简信息 + List papers = classicPaperBaseService.list( + new LambdaQueryWrapper() + .select(ClassicPaperEntity::getId, ClassicPaperEntity::getName, + ClassicPaperEntity::getSetIndex, ClassicPaperEntity::getStatus) + .eq(ClassicPaperEntity::getSetId, entity.getId()) + .orderByAsc(ClassicPaperEntity::getSetIndex) + ); + if (!papers.isEmpty()) { + List versions = papers.stream() + .map(p -> { + ClassicPaperDTO v = new ClassicPaperDTO(); + v.setId(p.getId()); + v.setName(p.getName()); + v.setSetIndex(p.getSetIndex()); + v.setStatus(p.getStatus()); + v.setStatusText(ClassicPaperStatusEnum.findByValue(p.getStatus())); + return v; + }) + .toList(); + dto.setVersions(versions); + } + return dto; - })); - return Result.success(pageResult); + }); + + return Result.success(new PageResult<>(dtoPage)); } @Override - public Result getDetail(Long setId) { + public Result getDetail(Long setId, Long paperId) { ClassicPaperSetEntity paperSet = classicPaperSetBaseService.getById(setId); if (paperSet == null) { return Result.fail(ResultCodeEnum.RESOURCE_NOT_EXIST, "套题组不存在"); @@ -94,49 +127,42 @@ public class ClassicPaperSetApplicationServiceImpl implements ClassicPaperSetApp ClassicPaperSetDTO setDTO = paperSet.toDTO(ClassicPaperSetDTO::new); setDTO.setStatusText(ClassicPaperStatusEnum.findByValue(paperSet.getStatus())); - List papers = classicPaperBaseService.list( - new LambdaQueryWrapper() - .eq(ClassicPaperEntity::getSetId, setId) - .orderByAsc(ClassicPaperEntity::getSetIndex) - ); + // 设置分值比例:优先取实体已存储的值,否则根据题型数量从配置计算 + computeScoreRatio(paperSet, setDTO); - List paperDTOs = new ArrayList<>(); - for (ClassicPaperEntity paper : papers) { - ClassicPaperDTO paperDTO = paper.toDTO(ClassicPaperDTO::new); - paperDTO.setStatusText(ClassicPaperStatusEnum.findByValue(paper.getStatus())); + if (paperId == null) { + return Result.success(setDTO); + } - List paperQuestions = classicPaperQuestionBaseService.list( - new LambdaQueryWrapper() - .eq(ClassicPaperQuestionEntity::getPaperId, paper.getId()) - .orderByAsc(ClassicPaperQuestionEntity::getSortOrder) - ); + // 查询该版本的题目列表 + List paperQuestions = classicPaperQuestionBaseService.list( + new LambdaQueryWrapper() + .eq(ClassicPaperQuestionEntity::getPaperId, paperId) + .orderByAsc(ClassicPaperQuestionEntity::getSortOrder) + ); - if (!paperQuestions.isEmpty()) { - List questionIds = paperQuestions.stream() - .map(ClassicPaperQuestionEntity::getQuestionId).collect(Collectors.toList()); - List questions = questionBaseService.listByIds(questionIds); - - List questionDTOs = new ArrayList<>(); - for (ClassicPaperQuestionEntity pq : paperQuestions) { - ClassicPaperQuestionDTO qDto = new ClassicPaperQuestionDTO(); - qDto.setId(pq.getId()); - qDto.setPaperId(pq.getPaperId()); - qDto.setQuestionId(pq.getQuestionId()); - qDto.setSortOrder(pq.getSortOrder()); - qDto.setQuestionType(pq.getQuestionType()); - questions.stream() - .filter(q -> q.getId().equals(pq.getQuestionId())) - .findFirst() - .ifPresent(q -> qDto.setQuestionDetail(q.getQuestionDetail())); - questionDTOs.add(qDto); - } - paperDTO.setQuestionList(questionDTOs); + if (!paperQuestions.isEmpty()) { + List questionIds = paperQuestions.stream() + .map(ClassicPaperQuestionEntity::getQuestionId).collect(Collectors.toList()); + List questions = questionBaseService.listByIds(questionIds); + + List questionDTOs = new ArrayList<>(); + for (ClassicPaperQuestionEntity pq : paperQuestions) { + ClassicPaperQuestionDTO qDto = new ClassicPaperQuestionDTO(); + qDto.setId(pq.getId()); + qDto.setPaperId(pq.getPaperId()); + qDto.setQuestionId(pq.getQuestionId()); + qDto.setSortOrder(pq.getSortOrder()); + qDto.setQuestionType(pq.getQuestionType()); + questions.stream() + .filter(q -> q.getId().equals(pq.getQuestionId())) + .findFirst() + .ifPresent(q -> qDto.setQuestionDetail(q.getQuestionDetail())); + questionDTOs.add(qDto); } - - paperDTOs.add(paperDTO); + setDTO.setQuestionList(questionDTOs); } - setDTO.setPaperList(paperDTOs); return Result.success(setDTO); } @@ -166,6 +192,43 @@ public class ClassicPaperSetApplicationServiceImpl implements ClassicPaperSetApp @Transactional(rollbackFor = Exception.class) public Result save(ClassicPaperSetDTO request) throws Exception { savePaperSetDomainService.save(request); - return getDetail(request.getId()); + return getDetail(request.getId(), null); + } + + /** + * 计算分值比例并填充到 DTO 的四个独立字段 + * 优先取实体已存储的 scoreRatio JSON,否则从 ExamScoreRatioConfig 计算 + * 题型数量为 0 时对应字段设为 null + */ + private void computeScoreRatio(ClassicPaperSetEntity paperSet, ClassicPaperSetDTO dto) { + Map ratioMap = null; + if (StrUtil.isNotBlank(paperSet.getScoreRatio())) { + try { + ratioMap = new ObjectMapper().readValue(paperSet.getScoreRatio(), + Map.class); + } catch (Exception e) { + // 解析失败时使用配置默认值 + } + } + if (ratioMap == null) { + ratioMap = new LinkedHashMap<>(); + } + + dto.setSingleChoiceScoreRatio( + paperSet.getSingleChoiceNum() != null && paperSet.getSingleChoiceNum() > 0 + ? ratioMap.getOrDefault("single", examScoreRatioConfig.getSingle()) + : null); + dto.setMultipleChoiceScoreRatio( + paperSet.getMultipleChoiceNum() != null && paperSet.getMultipleChoiceNum() > 0 + ? ratioMap.getOrDefault("multiple", examScoreRatioConfig.getMultiple()) + : null); + dto.setTrueFalseScoreRatio( + paperSet.getTrueFalseNum() != null && paperSet.getTrueFalseNum() > 0 + ? ratioMap.getOrDefault("trueFalse", examScoreRatioConfig.getTrueFalse()) + : null); + dto.setShortAnswerScoreRatio( + paperSet.getShortAnswerNum() != null && paperSet.getShortAnswerNum() > 0 + ? ratioMap.getOrDefault("shortAnswer", examScoreRatioConfig.getShortAnswer()) + : null); } } diff --git a/src/main/java/com/project/classicpaper/controller/ClassicPaperController.java b/src/main/java/com/project/classicpaper/controller/ClassicPaperController.java index 346d7ba..9991dc8 100644 --- a/src/main/java/com/project/classicpaper/controller/ClassicPaperController.java +++ b/src/main/java/com/project/classicpaper/controller/ClassicPaperController.java @@ -19,8 +19,8 @@ public class ClassicPaperController { @PostMapping("/regenerateQuestion") @OperationLog(module = "经典套题") - public Result regenerateQuestion(Long paperId, Long questionId) throws Exception { - return classicPaperApplicationService.regenerateQuestion(paperId, questionId); + public Result regenerateQuestion(Long paperId, Long paperQuestionId) throws Exception { + return classicPaperApplicationService.regenerateQuestion(paperId, paperQuestionId); } /** diff --git a/src/main/java/com/project/classicpaper/controller/ClassicPaperSetController.java b/src/main/java/com/project/classicpaper/controller/ClassicPaperSetController.java index cc383f9..30915c8 100644 --- a/src/main/java/com/project/classicpaper/controller/ClassicPaperSetController.java +++ b/src/main/java/com/project/classicpaper/controller/ClassicPaperSetController.java @@ -30,8 +30,8 @@ public class ClassicPaperSetController { } @GetMapping("/detail") - public Result detail(Long setId) { - return classicPaperSetApplicationService.getDetail(setId); + public Result detail(ClassicPaperSetParam param) { + return classicPaperSetApplicationService.getDetail(param.getId(), param.getPaperId()); } @PostMapping("/delete") diff --git a/src/main/java/com/project/classicpaper/domain/dto/ClassicPaperDTO.java b/src/main/java/com/project/classicpaper/domain/dto/ClassicPaperDTO.java index e05cf88..fe1c6df 100644 --- a/src/main/java/com/project/classicpaper/domain/dto/ClassicPaperDTO.java +++ b/src/main/java/com/project/classicpaper/domain/dto/ClassicPaperDTO.java @@ -31,8 +31,6 @@ public class ClassicPaperDTO extends BaseDTO { private Integer questionCount; - private Long paperGroupId; - private Long setId; private Integer setIndex; diff --git a/src/main/java/com/project/classicpaper/domain/dto/ClassicPaperQuestionDTO.java b/src/main/java/com/project/classicpaper/domain/dto/ClassicPaperQuestionDTO.java index 4b0f45c..b2dffef 100644 --- a/src/main/java/com/project/classicpaper/domain/dto/ClassicPaperQuestionDTO.java +++ b/src/main/java/com/project/classicpaper/domain/dto/ClassicPaperQuestionDTO.java @@ -5,14 +5,19 @@ import lombok.Data; @Data public class ClassicPaperQuestionDTO { + /** 关联记录ID(ClassicPaperQuestionEntity 主键),编辑暂存时用于定位要修改的排序/替换关系 */ private Long id; + /** 套卷ID */ private Long paperId; + /** 题目ID(QuestionEntity 主键),标识具体题目内容,重抽题目时传入此字段 */ private Long questionId; + /** 题目在套卷中的排序序号 */ private Integer sortOrder; + /** 题型:0-单选,1-多选,2-判断,4-简答 */ private Integer questionType; /** diff --git a/src/main/java/com/project/classicpaper/domain/dto/ClassicPaperSetDTO.java b/src/main/java/com/project/classicpaper/domain/dto/ClassicPaperSetDTO.java index 8b17bec..09dc17e 100644 --- a/src/main/java/com/project/classicpaper/domain/dto/ClassicPaperSetDTO.java +++ b/src/main/java/com/project/classicpaper/domain/dto/ClassicPaperSetDTO.java @@ -50,8 +50,30 @@ public class ClassicPaperSetDTO extends BaseDTO { private String statusText; + /** 单选题分值比例(数量为0时null,未设置时取配置默认值) */ + private Integer singleChoiceScoreRatio; + + /** 多选题分值比例 */ + private Integer multipleChoiceScoreRatio; + + /** 判断题分值比例 */ + private Integer trueFalseScoreRatio; + + /** 简答题分值比例 */ + private Integer shortAnswerScoreRatio; + /** - * 详情接口返回时填充:该套题组下所有版本 + * 保存固化请求时使用:各版本的题目列表(用于全量更新) */ private List paperList; + + /** + * detail 接口且 paperId 不为空时填充:单个版本的题目列表(避免前端从 paperList 中二次取值) + */ + private List questionList; + + /** + * list 接口返回时填充:版本精简信息(id、name、setIndex、status),用于前端直接跳转 detail + */ + private List versions; } diff --git a/src/main/java/com/project/classicpaper/domain/entity/ClassicPaperEntity.java b/src/main/java/com/project/classicpaper/domain/entity/ClassicPaperEntity.java index 282165f..364a0e2 100644 --- a/src/main/java/com/project/classicpaper/domain/entity/ClassicPaperEntity.java +++ b/src/main/java/com/project/classicpaper/domain/entity/ClassicPaperEntity.java @@ -13,8 +13,7 @@ import org.hibernate.annotations.Comment; @Data @Table(name = "evaluator_classic_paper", indexes = {@Index(name = "Idx_sub_line_id", columnList = "sub_line_id"), - @Index(name = "Idx_status", columnList = "status"), - @Index(name = "Idx_paper_group_id", columnList = "paper_group_id")}) + @Index(name = "Idx_status", columnList = "status")}) @Entity @TableName(value = "evaluator_classic_paper") @EqualsAndHashCode(callSuper = true) @@ -41,10 +40,9 @@ public class ClassicPaperEntity extends BaseEntity { @Comment("来源子产品线ID") private Long subLineId; - @Column(name = "information_id") - @TableField("information_id") - @Comment("关联资料ID") - private Long informationId; + @Column(name = "information_ids", columnDefinition = "json comment '关联资料ID列表'") + @TableField("information_ids") + private String informationIds; @Column(name = "status") @TableField("status") @@ -56,11 +54,6 @@ public class ClassicPaperEntity extends BaseEntity { @Comment("题目总数") private Integer questionCount; - @Column(name = "paper_group_id") - @TableField("paper_group_id") - @Comment("套题组ID,N个版本共享") - private Long paperGroupId; - @Column(name = "set_id") @TableField("set_id") @Comment("关联套题组ID") diff --git a/src/main/java/com/project/classicpaper/domain/entity/ClassicPaperSetEntity.java b/src/main/java/com/project/classicpaper/domain/entity/ClassicPaperSetEntity.java index fdd4bf9..734014a 100644 --- a/src/main/java/com/project/classicpaper/domain/entity/ClassicPaperSetEntity.java +++ b/src/main/java/com/project/classicpaper/domain/entity/ClassicPaperSetEntity.java @@ -76,6 +76,10 @@ public class ClassicPaperSetEntity extends BaseEntity { @Comment("简答题数量") private Integer shortAnswerNum; + @Column(name = "score_ratio", columnDefinition = "json comment '分值比例配置'") + @TableField("score_ratio") + private String scoreRatio; + @Column(name = "status") @TableField("status") @Comment("状态:0-生成中,1-草稿,2-已确认,3-已废弃") diff --git a/src/main/java/com/project/classicpaper/domain/param/ClassicPaperSetParam.java b/src/main/java/com/project/classicpaper/domain/param/ClassicPaperSetParam.java index ba06cb6..ac62a45 100644 --- a/src/main/java/com/project/classicpaper/domain/param/ClassicPaperSetParam.java +++ b/src/main/java/com/project/classicpaper/domain/param/ClassicPaperSetParam.java @@ -5,6 +5,12 @@ import lombok.Data; @Data public class ClassicPaperSetParam extends BaseParam { + /** 套题组ID */ + private Long id; + + /** 指定版本ID,传则只返回该版本,不传返回整组 */ + private Long paperId; + /** 子产品线ID */ private Long subLineId; diff --git a/src/main/java/com/project/classicpaper/domain/service/DraftPaperDomainService.java b/src/main/java/com/project/classicpaper/domain/service/DraftPaperDomainService.java new file mode 100644 index 0000000..6b0540f --- /dev/null +++ b/src/main/java/com/project/classicpaper/domain/service/DraftPaperDomainService.java @@ -0,0 +1,12 @@ +package com.project.classicpaper.domain.service; + +import com.project.base.domain.result.Result; +import com.project.classicpaper.domain.dto.ClassicPaperDTO; + +public interface DraftPaperDomainService { + + /** + * 切tab暂存:更新套卷名称、描述和题目关联 + */ + Result draft(ClassicPaperDTO request) throws Exception; +} diff --git a/src/main/java/com/project/classicpaper/domain/service/RegenerateQuestionDomainService.java b/src/main/java/com/project/classicpaper/domain/service/RegenerateQuestionDomainService.java index 3b82f5a..f6cb812 100644 --- a/src/main/java/com/project/classicpaper/domain/service/RegenerateQuestionDomainService.java +++ b/src/main/java/com/project/classicpaper/domain/service/RegenerateQuestionDomainService.java @@ -8,9 +8,9 @@ public interface RegenerateQuestionDomainService { /** * 单题重抽:替换套卷中的某道题 * - * @param paperId 套卷ID - * @param questionId 原题目ID + * @param paperId 套卷ID + * @param paperQuestionId 关联记录ID(ClassicPaperQuestionEntity 主键) * @return 新题目信息 */ - Result regenerate(Long paperId, Long questionId) throws Exception; + Result regenerate(Long paperId, Long paperQuestionId) throws Exception; } diff --git a/src/main/java/com/project/classicpaper/domain/service/SavePaperSetDomainService.java b/src/main/java/com/project/classicpaper/domain/service/SavePaperSetDomainService.java new file mode 100644 index 0000000..36e0612 --- /dev/null +++ b/src/main/java/com/project/classicpaper/domain/service/SavePaperSetDomainService.java @@ -0,0 +1,13 @@ +package com.project.classicpaper.domain.service; + +import com.project.base.domain.result.Result; +import com.project.classicpaper.domain.dto.ClassicPaperSetDTO; + +public interface SavePaperSetDomainService { + + /** + * 保存固化:全量保存套题组所有版本,校验通过后锁定为CONFIRMED + * 返回 setId,由调用方自行查询详情组装返回 + */ + Result save(ClassicPaperSetDTO request) throws Exception; +} diff --git a/src/main/java/com/project/classicpaper/domain/service/impl/DraftPaperDomainServiceImpl.java b/src/main/java/com/project/classicpaper/domain/service/impl/DraftPaperDomainServiceImpl.java new file mode 100644 index 0000000..e43b2a4 --- /dev/null +++ b/src/main/java/com/project/classicpaper/domain/service/impl/DraftPaperDomainServiceImpl.java @@ -0,0 +1,113 @@ +package com.project.classicpaper.domain.service.impl; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.project.base.domain.exception.BusinessErrorException; +import com.project.base.domain.result.Result; +import com.project.classicpaper.domain.dto.ClassicPaperDTO; +import com.project.classicpaper.domain.dto.ClassicPaperQuestionDTO; +import com.project.classicpaper.domain.entity.ClassicPaperEntity; +import com.project.classicpaper.domain.entity.ClassicPaperQuestionEntity; +import com.project.classicpaper.domain.enums.ClassicPaperStatusEnum; +import com.project.classicpaper.domain.service.ClassicPaperBaseService; +import com.project.classicpaper.domain.service.ClassicPaperQuestionBaseService; +import com.project.classicpaper.domain.service.DraftPaperDomainService; +import com.project.question.domain.entity.QuestionEntity; +import com.project.question.domain.service.QuestionBaseService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +@Service +@Slf4j +public class DraftPaperDomainServiceImpl implements DraftPaperDomainService { + + @Autowired + private ClassicPaperBaseService classicPaperBaseService; + + @Autowired + private ClassicPaperQuestionBaseService classicPaperQuestionBaseService; + + @Autowired + private QuestionBaseService questionBaseService; + + @Override + public Result draft(ClassicPaperDTO request) throws Exception { + Long paperId = request.getId(); + // 1. 校验套卷存在且为草稿状态 + ClassicPaperEntity paper = classicPaperBaseService.getById(paperId); + if (paper == null) { + throw new BusinessErrorException("套卷不存在"); + } + if (!ClassicPaperStatusEnum.DRAFT.getValue().equals(paper.getStatus())) { + throw new BusinessErrorException("只有草稿状态的套卷才能编辑"); + } + + // 2. 更新套卷名称和描述 + if (StrUtil.isNotBlank(request.getName())) { + paper.setName(request.getName()); + } + if (StrUtil.isNotBlank(request.getDescription())) { + paper.setDescription(request.getDescription()); + } + classicPaperBaseService.updateById(paper); + + // 3. 更新题目关联(排序、替换的题目ID) + if (CollUtil.isNotEmpty(request.getQuestionList())) { + for (ClassicPaperQuestionDTO qDto : request.getQuestionList()) { + if (qDto.getId() != null) { + ClassicPaperQuestionEntity relation = classicPaperQuestionBaseService.getById(qDto.getId()); + if (relation != null) { + if (qDto.getSortOrder() != null) { + relation.setSortOrder(qDto.getSortOrder()); + } + if (qDto.getQuestionId() != null) { + relation.setQuestionId(qDto.getQuestionId()); + } + classicPaperQuestionBaseService.updateById(relation); + } + } + } + } + + // 4. 组装返回 DTO(含题目详情) + ClassicPaperDTO dto = paper.toDTO(ClassicPaperDTO::new); + dto.setStatusText(ClassicPaperStatusEnum.findByValue(paper.getStatus())); + + List relations = classicPaperQuestionBaseService.list( + new LambdaQueryWrapper() + .eq(ClassicPaperQuestionEntity::getPaperId, paperId) + .orderByAsc(ClassicPaperQuestionEntity::getSortOrder) + ); + + if (!relations.isEmpty()) { + List questionIds = relations.stream() + .map(ClassicPaperQuestionEntity::getQuestionId) + .collect(Collectors.toList()); + List questions = questionBaseService.listByIds(questionIds); + + List questionDTOs = new ArrayList<>(); + for (ClassicPaperQuestionEntity rel : relations) { + ClassicPaperQuestionDTO qDto = new ClassicPaperQuestionDTO(); + qDto.setId(rel.getId()); + qDto.setPaperId(rel.getPaperId()); + qDto.setQuestionId(rel.getQuestionId()); + qDto.setSortOrder(rel.getSortOrder()); + qDto.setQuestionType(rel.getQuestionType()); + questions.stream() + .filter(q -> q.getId().equals(rel.getQuestionId())) + .findFirst() + .ifPresent(q -> qDto.setQuestionDetail(q.getQuestionDetail())); + questionDTOs.add(qDto); + } + dto.setQuestionList(questionDTOs); + } + + return Result.success(dto); + } +} diff --git a/src/main/java/com/project/classicpaper/domain/service/impl/FallbackClassicPaperQuestionGenerator.java b/src/main/java/com/project/classicpaper/domain/service/impl/FallbackClassicPaperQuestionGenerator.java index 903ab60..6edc825 100644 --- a/src/main/java/com/project/classicpaper/domain/service/impl/FallbackClassicPaperQuestionGenerator.java +++ b/src/main/java/com/project/classicpaper/domain/service/impl/FallbackClassicPaperQuestionGenerator.java @@ -9,6 +9,7 @@ import com.project.question.domain.service.SaveQuestionDomainService; import com.project.task.domain.enums.QuestionTypeEnum; import com.project.classicpaper.domain.service.ClassicPaperQuestionGenerator; import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @@ -83,6 +84,14 @@ public class FallbackClassicPaperQuestionGenerator implements ClassicPaperQuesti savedEntity.setId(saved.getId()); savedEntity.setQuestionType(questionType.getValue()); savedEntity.setKpIdList(saved.getKpIdList()); + + // 复制 questionDetail(QuestionDTO.QuestionDetailDTO → QuestionEntity.QuestionDetail) + if (saved.getQuestionDetailDTO() != null) { + QuestionEntity.QuestionDetail detail = new QuestionEntity.QuestionDetail(); + BeanUtils.copyProperties(saved.getQuestionDetailDTO(), detail); + savedEntity.setQuestionDetail(detail); + } + return savedEntity; } diff --git a/src/main/java/com/project/classicpaper/domain/service/impl/GenerateClassicPaperDomainServiceImpl.java b/src/main/java/com/project/classicpaper/domain/service/impl/GenerateClassicPaperDomainServiceImpl.java index 2039d4b..6968e5e 100644 --- a/src/main/java/com/project/classicpaper/domain/service/impl/GenerateClassicPaperDomainServiceImpl.java +++ b/src/main/java/com/project/classicpaper/domain/service/impl/GenerateClassicPaperDomainServiceImpl.java @@ -4,9 +4,9 @@ import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.RandomUtil; import cn.hutool.core.util.StrUtil; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; -import com.project.base.config.SnowflakeIdWorker; import com.project.base.domain.exception.BusinessErrorException; import com.project.base.domain.result.Result; +import com.fasterxml.jackson.databind.ObjectMapper; import com.project.classicpaper.domain.dto.ClassicPaperDTO; import com.project.classicpaper.domain.dto.ClassicPaperSetDTO; import com.project.classicpaper.domain.entity.ClassicPaperEntity; @@ -68,7 +68,10 @@ public class GenerateClassicPaperDomainServiceImpl implements GenerateClassicPap @Autowired private TaskKnowledgePointBaseService taskKnowledgePointBaseService; - private final SnowflakeIdWorker snowflakeIdWorker = new SnowflakeIdWorker(0, 0); + @Autowired + private com.project.task.config.ExamScoreRatioConfig examScoreRatioConfig; + + private final ObjectMapper objectMapper = new ObjectMapper(); @Override @Transactional(rollbackFor = Exception.class) @@ -142,6 +145,9 @@ public class GenerateClassicPaperDomainServiceImpl implements GenerateClassicPap throw new BusinessErrorException("多选题数量(" + multipleChoiceNum + ")不能超过知识点簇(大小>1)个数(" + allClusters.size() + ")"); } + // 收集关联的资料ID列表(JSON数组) + String informationIdsJson = toJsonArray(informationIds); + int setCount = request.getSetCount(); // 6. 创建套题组(Set) @@ -160,26 +166,27 @@ public class GenerateClassicPaperDomainServiceImpl implements GenerateClassicPap paperSet.setStatus(ClassicPaperStatusEnum.GENERATING.getValue()); classicPaperSetBaseService.save(paperSet); - // 7. 创建 paperGroupId(N个版本共享,用于知识点模板数据关联) - Long paperGroupId = snowflakeIdWorker.nextId(); + // 初始化分值比例(只包含数量 > 0 的题型) + paperSet.setScoreRatio(buildScoreRatio(request)); + classicPaperSetBaseService.updateById(paperSet); - // 8. 循环生成 N 个版本(每套独立采样) + // 7. 循环生成 N 个版本(每套独立采样),用 setId 关联模板数据 List paperDTOs = new ArrayList<>(); for (int i = 1; i <= setCount; i++) { - ClassicPaperDTO paperDTO = generateOnePaper(paperSet.getId(), paperGroupId, i, request, allKps, allClusters, informationIds); + ClassicPaperDTO paperDTO = generateOnePaper(paperSet.getId(), i, request, allKps, allClusters, informationIdsJson); paperDTOs.add(paperDTO); } - // 9. 所有子套题生成完成,将状态从"生成中"改为"草稿" + // 8. 所有子套题生成完成,将状态从"生成中"改为"草稿" classicPaperBaseService.lambdaUpdate() - .eq(ClassicPaperEntity::getPaperGroupId, paperGroupId) + .eq(ClassicPaperEntity::getSetId, paperSet.getId()) .set(ClassicPaperEntity::getStatus, ClassicPaperStatusEnum.DRAFT.getValue()) .update(); paperSet.setStatus(ClassicPaperStatusEnum.DRAFT.getValue()); classicPaperSetBaseService.updateById(paperSet); - log.info(">>> [经典套题] 批量生成完成, setId={}, paperGroupId={}, 版本数={}, 每套题数={}", - paperSet.getId(), paperGroupId, setCount, totalPerSet); + log.info(">>> [经典套题] 批量生成完成, setId={}, 版本数={}, 每套题数={}", + paperSet.getId(), setCount, totalPerSet); // 10. 构建返回 DTO ClassicPaperSetDTO setDTO = paperSet.toDTO(ClassicPaperSetDTO::new); @@ -215,11 +222,11 @@ public class GenerateClassicPaperDomainServiceImpl implements GenerateClassicPap /** * 生成一个版本的套卷 */ - private ClassicPaperDTO generateOnePaper(Long setId, Long paperGroupId, int setIndex, + private ClassicPaperDTO generateOnePaper(Long setId, int setIndex, ClassicPaperSetDTO request, List allKps, List allClusters, - List informationIds) throws Exception { + String informationIdsJson) throws Exception { // 创建套卷实体 ClassicPaperEntity paper = new ClassicPaperEntity(); paper.setName(request.getName() + "-V" + setIndex); @@ -227,8 +234,8 @@ public class GenerateClassicPaperDomainServiceImpl implements GenerateClassicPap paper.setSourceType(ClassicPaperSourceTypeEnum.AI_GENERATED.getValue()); paper.setSubLineId(request.getSubLineId()); paper.setClassicCategoryId(request.getClassicCategoryId()); - paper.setStatus(ClassicPaperStatusEnum.GENERATING.getValue()); // 初始状态:生成中 - paper.setPaperGroupId(paperGroupId); + paper.setInformationIds(informationIdsJson); + paper.setStatus(ClassicPaperStatusEnum.GENERATING.getValue()); paper.setSetId(setId); paper.setSetIndex(setIndex); paper.setQuestionCount(0); @@ -253,14 +260,13 @@ public class GenerateClassicPaperDomainServiceImpl implements GenerateClassicPap int singleChoiceNum = Optional.ofNullable(request.getSingleChoiceNum()).orElse(0); if (singleChoiceNum > 0) { List sampledKps = sampleKps(shuffledKps, singleChoiceNum); - // 创建 TaskKnowledgePointEntity - // 注意:taskId 为 null,后续任务绑定套卷时通过 groupId 赋值 taskId + // 创建 TaskKnowledgePointEntity(groupId = setId,taskId 为 null,后续任务绑定时赋值) for (KnowledgePointEntity kp : sampledKps) { TaskKnowledgePointEntity taskKp = new TaskKnowledgePointEntity(); - taskKp.setGroupId(paperGroupId); + taskKp.setGroupId(setId); taskKp.setAtomId(kp.getId()); taskKp.setContent(kp.getContent()); - taskKp.setClusterSize(1); // 单知识点维度 + taskKp.setClusterSize(1); taskPointEntities.add(taskKp); } // 调用生成器生成题目 @@ -290,7 +296,7 @@ public class GenerateClassicPaperDomainServiceImpl implements GenerateClassicPap List sampledKps = sampleKps(availableKps, trueFalseNum); for (KnowledgePointEntity kp : sampledKps) { TaskKnowledgePointEntity taskKp = new TaskKnowledgePointEntity(); - taskKp.setGroupId(paperGroupId); + taskKp.setGroupId(setId); taskKp.setAtomId(kp.getId()); taskKp.setContent(kp.getContent()); taskKp.setClusterSize(1); @@ -316,9 +322,9 @@ public class GenerateClassicPaperDomainServiceImpl implements GenerateClassicPap for (KnowledgeClusterEntity cluster : sampledClusters) { // 记录已使用的资料级簇ID usedSourceClusterIds.add(cluster.getId()); - // 创建 TaskKnowledgeClusterEntity(groupId = paperGroupId,taskId 后续任务绑定时赋值) + // 创建 TaskKnowledgeClusterEntity(groupId = setId,taskId 后续任务绑定时赋值) TaskKnowledgeClusterEntity taskCluster = new TaskKnowledgeClusterEntity(); - taskCluster.setGroupId(paperGroupId); + taskCluster.setGroupId(setId); taskCluster.setClusterTopic(cluster.getClusterTopic()); taskCluster.setClusterSize(cluster.getClusterSize()); taskCluster.setInformationId(cluster.getInformationId()); @@ -334,7 +340,7 @@ public class GenerateClassicPaperDomainServiceImpl implements GenerateClassicPap // 创建 TaskKnowledgePointEntity for (KnowledgePointEntity kp : clusterKps) { TaskKnowledgePointEntity taskKp = new TaskKnowledgePointEntity(); - taskKp.setGroupId(paperGroupId); + taskKp.setGroupId(setId); taskKp.setClusterId(taskCluster.getId()); taskKp.setAtomId(kp.getId()); taskKp.setContent(kp.getContent()); @@ -368,9 +374,9 @@ public class GenerateClassicPaperDomainServiceImpl implements GenerateClassicPap List sampledClusters = sampleClusters(availableClusters, multipleChoiceNum); for (KnowledgeClusterEntity cluster : sampledClusters) { - // 创建 TaskKnowledgeClusterEntity(taskId 后续任务绑定时赋值) + // 创建 TaskKnowledgeClusterEntity(groupId = setId,taskId 后续任务绑定时赋值) TaskKnowledgeClusterEntity taskCluster = new TaskKnowledgeClusterEntity(); - taskCluster.setGroupId(paperGroupId); + taskCluster.setGroupId(setId); taskCluster.setClusterTopic(cluster.getClusterTopic()); taskCluster.setClusterSize(cluster.getClusterSize()); taskCluster.setInformationId(cluster.getInformationId()); @@ -389,7 +395,7 @@ public class GenerateClassicPaperDomainServiceImpl implements GenerateClassicPap // 创建 TaskKnowledgePointEntity for (KnowledgePointEntity kp : subSampledKps) { TaskKnowledgePointEntity taskKp = new TaskKnowledgePointEntity(); - taskKp.setGroupId(paperGroupId); + taskKp.setGroupId(setId); taskKp.setClusterId(taskCluster.getId()); taskKp.setAtomId(kp.getId()); taskKp.setContent(kp.getContent()); @@ -430,6 +436,43 @@ public class GenerateClassicPaperDomainServiceImpl implements GenerateClassicPap return dto; } + /** + * 构建分值比例 JSON(只包含数量 > 0 的题型) + */ + private String buildScoreRatio(ClassicPaperSetDTO request) { + Map ratioMap = new LinkedHashMap<>(); + if (Optional.ofNullable(request.getSingleChoiceNum()).orElse(0) > 0) { + ratioMap.put("single", examScoreRatioConfig.getSingle()); + } + if (Optional.ofNullable(request.getMultipleChoiceNum()).orElse(0) > 0) { + ratioMap.put("multiple", examScoreRatioConfig.getMultiple()); + } + if (Optional.ofNullable(request.getTrueFalseNum()).orElse(0) > 0) { + ratioMap.put("trueFalse", examScoreRatioConfig.getTrueFalse()); + } + if (Optional.ofNullable(request.getShortAnswerNum()).orElse(0) > 0) { + ratioMap.put("shortAnswer", examScoreRatioConfig.getShortAnswer()); + } + try { + return objectMapper.writeValueAsString(ratioMap); + } catch (Exception e) { + log.warn(">>> [经典套题] scoreRatio 序列化失败", e); + return "{}"; + } + } + + /** + * 将资料ID列表转为JSON数组字符串 + */ + private String toJsonArray(List ids) { + try { + return objectMapper.writeValueAsString(ids); + } catch (Exception e) { + log.warn(">>> [经典套题] informationIds JSON序列化失败", e); + return "[]"; + } + } + /** * 从知识点池中采样指定数量的知识点 */ diff --git a/src/main/java/com/project/classicpaper/domain/service/impl/RegenerateQuestionDomainServiceImpl.java b/src/main/java/com/project/classicpaper/domain/service/impl/RegenerateQuestionDomainServiceImpl.java index 0830921..e864c70 100644 --- a/src/main/java/com/project/classicpaper/domain/service/impl/RegenerateQuestionDomainServiceImpl.java +++ b/src/main/java/com/project/classicpaper/domain/service/impl/RegenerateQuestionDomainServiceImpl.java @@ -51,7 +51,7 @@ public class RegenerateQuestionDomainServiceImpl implements RegenerateQuestionDo @Override @Transactional(rollbackFor = Exception.class) - public Result regenerate(Long paperId, Long questionId) throws Exception { + public Result regenerate(Long paperId, Long paperQuestionId) throws Exception { // 1. 校验套卷存在且为草稿状态 ClassicPaperEntity paper = classicPaperBaseService.getById(paperId); if (paper == null) { @@ -61,17 +61,18 @@ public class RegenerateQuestionDomainServiceImpl implements RegenerateQuestionDo throw new BusinessErrorException("只有草稿状态的套卷才能重抽题目"); } - // 2. 校验题目属于该套卷 - ClassicPaperQuestionEntity paperQuestion = classicPaperQuestionBaseService.getOne( - new LambdaQueryWrapper() - .eq(ClassicPaperQuestionEntity::getPaperId, paperId) - .eq(ClassicPaperQuestionEntity::getQuestionId, questionId) - ); + // 2. 直接用 paperQuestionId 查关联记录 + ClassicPaperQuestionEntity paperQuestion = classicPaperQuestionBaseService.getById(paperQuestionId); if (paperQuestion == null) { throw new BusinessErrorException("该题目不属于此套卷"); } + // 二次校验:关联记录确实属于该套卷 + if (!paperId.equals(paperQuestion.getPaperId())) { + throw new BusinessErrorException("该题目不属于此套卷"); + } - // 3. 查询原题目信息 + // 3. 查询原题目信息(从关联记录获取 questionId) + Long questionId = paperQuestion.getQuestionId(); QuestionEntity originalQuestion = questionBaseService.getById(questionId); if (originalQuestion == null) { throw new BusinessErrorException("原题目不存在"); @@ -107,7 +108,7 @@ public class RegenerateQuestionDomainServiceImpl implements RegenerateQuestionDo paperQuestion.setQuestionId(newQuestion.getId()); classicPaperQuestionBaseService.updateById(paperQuestion); - log.info(">>> [经典套题-重抽] 套卷{} 题目{} -> 新题目{}", paperId, questionId, newQuestion.getId()); + log.info(">>> [经典套题-重抽] 套卷{} 关联记录{} 原题{} -> 新题{}", paperId, paperQuestionId, questionId, newQuestion.getId()); // 8. 构建返回 ClassicPaperQuestionDTO dto = new ClassicPaperQuestionDTO(); diff --git a/src/main/java/com/project/classicpaper/domain/service/impl/SavePaperSetDomainServiceImpl.java b/src/main/java/com/project/classicpaper/domain/service/impl/SavePaperSetDomainServiceImpl.java new file mode 100644 index 0000000..bf8ce78 --- /dev/null +++ b/src/main/java/com/project/classicpaper/domain/service/impl/SavePaperSetDomainServiceImpl.java @@ -0,0 +1,150 @@ +package com.project.classicpaper.domain.service.impl; + +import cn.hutool.core.collection.CollUtil; +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.base.domain.result.Result; +import com.project.classicpaper.domain.dto.ClassicPaperDTO; +import com.project.classicpaper.domain.dto.ClassicPaperQuestionDTO; +import com.project.classicpaper.domain.dto.ClassicPaperSetDTO; +import com.project.classicpaper.domain.entity.ClassicPaperEntity; +import com.project.classicpaper.domain.entity.ClassicPaperSetEntity; +import com.project.classicpaper.domain.enums.ClassicPaperStatusEnum; +import com.project.classicpaper.domain.service.ClassicPaperBaseService; +import com.project.classicpaper.domain.service.ClassicPaperQuestionBaseService; +import com.project.classicpaper.domain.service.ClassicPaperSetBaseService; +import com.project.classicpaper.domain.service.SavePaperSetDomainService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.LinkedHashMap; +import java.util.Map; + +@Service +@Slf4j +public class SavePaperSetDomainServiceImpl implements SavePaperSetDomainService { + + @Autowired + private ClassicPaperSetBaseService classicPaperSetBaseService; + + @Autowired + private ClassicPaperBaseService classicPaperBaseService; + + @Autowired + private ClassicPaperQuestionBaseService classicPaperQuestionBaseService; + + @Override + @Transactional(rollbackFor = Exception.class) + public Result save(ClassicPaperSetDTO request) throws Exception { + Long setId = request.getId(); + // 1. 校验套题组存在且为草稿状态 + ClassicPaperSetEntity paperSet = classicPaperSetBaseService.getById(setId); + if (paperSet == null) { + throw new BusinessErrorException("套题组不存在"); + } + if (!ClassicPaperStatusEnum.DRAFT.getValue().equals(paperSet.getStatus())) { + throw new BusinessErrorException("只有草稿状态的套题组才能保存固化"); + } + + // 2. 更新套题组基本信息 + if (StrUtil.isNotBlank(request.getName())) { + paperSet.setName(request.getName()); + } + if (StrUtil.isNotBlank(request.getDescription())) { + paperSet.setDescription(request.getDescription()); + } + if (request.getClassicCategoryId() != null) { + paperSet.setClassicCategoryId(request.getClassicCategoryId()); + } + // 从四个独立字段重建 scoreRatio JSON + String scoreRatio = buildScoreRatioFromFields(request); + if (scoreRatio != null) { + paperSet.setScoreRatio(scoreRatio); + } + classicPaperSetBaseService.updateById(paperSet); + + // 3. 全量更新各版本及其题目关联 + if (CollUtil.isNotEmpty(request.getPaperList())) { + for (ClassicPaperDTO paperDto : request.getPaperList()) { + if (paperDto.getId() != null) { + // 更新已有套卷 + ClassicPaperEntity paper = classicPaperBaseService.getById(paperDto.getId()); + if (paper != null) { + if (StrUtil.isNotBlank(paperDto.getName())) { + paper.setName(paperDto.getName()); + } + if (StrUtil.isNotBlank(paperDto.getDescription())) { + paper.setDescription(paperDto.getDescription()); + } + classicPaperBaseService.updateById(paper); + } + + // 更新题目关联(排序、替换的题目ID) + if (CollUtil.isNotEmpty(paperDto.getQuestionList())) { + for (ClassicPaperQuestionDTO qDto : paperDto.getQuestionList()) { + if (qDto.getId() != null) { + com.project.classicpaper.domain.entity.ClassicPaperQuestionEntity relation = + classicPaperQuestionBaseService.getById(qDto.getId()); + if (relation != null) { + if (qDto.getSortOrder() != null) { + relation.setSortOrder(qDto.getSortOrder()); + } + if (qDto.getQuestionId() != null) { + relation.setQuestionId(qDto.getQuestionId()); + } + classicPaperQuestionBaseService.updateById(relation); + } + } + } + } + } + } + } + + // 4. 全部校验通过,锁定为 CONFIRMED + classicPaperBaseService.lambdaUpdate() + .eq(ClassicPaperEntity::getSetId, setId) + .set(ClassicPaperEntity::getStatus, ClassicPaperStatusEnum.CONFIRMED.getValue()) + .update(); + + paperSet.setStatus(ClassicPaperStatusEnum.CONFIRMED.getValue()); + classicPaperSetBaseService.updateById(paperSet); + + log.info(">>> [经典套题] 套题组已固化, setId={}", setId); + + return Result.success(setId); + } + + /** + * 从 DTO 的四个独立分值比例字段构建 JSON + * 只包含非 null 的字段(对应数量 > 0 的题型) + */ + private String buildScoreRatioFromFields(ClassicPaperSetDTO request) { + Map ratioMap = new LinkedHashMap<>(); + if (request.getSingleChoiceScoreRatio() != null) { + ratioMap.put("single", request.getSingleChoiceScoreRatio()); + } + if (request.getMultipleChoiceScoreRatio() != null) { + ratioMap.put("multiple", request.getMultipleChoiceScoreRatio()); + } + if (request.getTrueFalseScoreRatio() != null) { + ratioMap.put("trueFalse", request.getTrueFalseScoreRatio()); + } + if (request.getShortAnswerScoreRatio() != null) { + ratioMap.put("shortAnswer", request.getShortAnswerScoreRatio()); + } + if (ratioMap.isEmpty()) { + return null; + } + try { + return new ObjectMapper().writeValueAsString(ratioMap); + } catch (Exception e) { + log.warn(">>> [经典套题] scoreRatio 序列化失败", e); + return null; + } + } +} diff --git a/src/main/java/com/project/question/domain/entity/TaskKnowledgeClusterEntity.java b/src/main/java/com/project/question/domain/entity/TaskKnowledgeClusterEntity.java index 964b428..c64268b 100644 --- a/src/main/java/com/project/question/domain/entity/TaskKnowledgeClusterEntity.java +++ b/src/main/java/com/project/question/domain/entity/TaskKnowledgeClusterEntity.java @@ -44,6 +44,6 @@ public class TaskKnowledgeClusterEntity extends BaseEntity { @Column(name = "group_id") @TableField("group_id") - @Comment("套题组ID(经典套题时绑定paperGroupId,待taskId赋值)") + @Comment("套题组ID(经典套题时绑定setId,待taskId赋值)") private Long groupId; } diff --git a/src/main/java/com/project/question/domain/entity/TaskKnowledgePointEntity.java b/src/main/java/com/project/question/domain/entity/TaskKnowledgePointEntity.java index 549d6a7..95c3ba8 100644 --- a/src/main/java/com/project/question/domain/entity/TaskKnowledgePointEntity.java +++ b/src/main/java/com/project/question/domain/entity/TaskKnowledgePointEntity.java @@ -47,6 +47,6 @@ public class TaskKnowledgePointEntity extends BaseEntity { @Column(name = "group_id") @TableField("group_id") - @Comment("套题组ID(经典套题时绑定paperGroupId,待taskId赋值)") + @Comment("套题组ID(经典套题时绑定setId,待taskId赋值)") private Long groupId; } diff --git a/src/main/java/com/project/task/domain/service/impl/SaveOrUpdateTaskDomainServiceImpl.java b/src/main/java/com/project/task/domain/service/impl/SaveOrUpdateTaskDomainServiceImpl.java index bbcd9a7..146b0a8 100644 --- a/src/main/java/com/project/task/domain/service/impl/SaveOrUpdateTaskDomainServiceImpl.java +++ b/src/main/java/com/project/task/domain/service/impl/SaveOrUpdateTaskDomainServiceImpl.java @@ -186,19 +186,11 @@ public class SaveOrUpdateTaskDomainServiceImpl implements SaveOrUpdateTaskDomain } /** - * 经典模式:从套题组的 groupId 模板复制任务级知识点/簇数据 + * 经典模式:从套题组的 setId 模板复制任务级知识点/簇数据 * 支持多任务绑定同一套题组,每个任务有自己独立的副本 */ private void copyTaskKnowledgeFromPaper(Long taskId, Long classicPaperSetId) { - // 通过 setId 查找任意一个版本获取 paperGroupId - ClassicPaperEntity paper = classicPaperBaseService.getOne( - new LambdaQueryWrapper() - .eq(ClassicPaperEntity::getSetId, classicPaperSetId) - .last("LIMIT 1")); - if (paper == null || paper.getPaperGroupId() == null) { - return; - } - Long paperGroupId = paper.getPaperGroupId(); + // 直接用 setId 查询模板数据(taskId 为 null 的原始数据) // 1. 删除该任务已有的任务级数据(如果存在,防止重复绑定时数据翻倍) taskKnowledgePointBaseService.remove(new LambdaQueryWrapper() @@ -206,15 +198,15 @@ public class SaveOrUpdateTaskDomainServiceImpl implements SaveOrUpdateTaskDomain taskKnowledgeClusterBaseService.remove(new LambdaQueryWrapper() .eq(TaskKnowledgeClusterEntity::getTaskId, taskId)); - // 2. 查询 groupId 模板(taskId 为 null 的原始数据) + // 2. 查询 setId 模板(taskId 为 null 的原始数据) List templateClusters = taskKnowledgeClusterBaseService.list( new LambdaQueryWrapper() - .eq(TaskKnowledgeClusterEntity::getGroupId, paperGroupId) + .eq(TaskKnowledgeClusterEntity::getGroupId, classicPaperSetId) .isNull(TaskKnowledgeClusterEntity::getTaskId)); List templatePoints = taskKnowledgePointBaseService.list( new LambdaQueryWrapper() - .eq(TaskKnowledgePointEntity::getGroupId, paperGroupId) + .eq(TaskKnowledgePointEntity::getGroupId, classicPaperSetId) .isNull(TaskKnowledgePointEntity::getTaskId)); if (templateClusters.isEmpty() && templatePoints.isEmpty()) { @@ -229,7 +221,7 @@ public class SaveOrUpdateTaskDomainServiceImpl implements SaveOrUpdateTaskDomain newCluster.setInformationId(template.getInformationId()); newCluster.setClusterTopic(template.getClusterTopic()); newCluster.setClusterSize(template.getClusterSize()); - newCluster.setGroupId(paperGroupId); + newCluster.setGroupId(classicPaperSetId); taskKnowledgeClusterBaseService.save(newCluster); clusterIdMapping.put(template.getId(), newCluster.getId()); } @@ -242,7 +234,7 @@ public class SaveOrUpdateTaskDomainServiceImpl implements SaveOrUpdateTaskDomain newPoint.setAtomId(template.getAtomId()); newPoint.setContent(template.getContent()); newPoint.setClusterSize(template.getClusterSize()); - newPoint.setGroupId(paperGroupId); + newPoint.setGroupId(classicPaperSetId); // 更新 clusterId 到新创建的簇 if (template.getClusterId() != null && clusterIdMapping.containsKey(template.getClusterId())) { newPoint.setClusterId(clusterIdMapping.get(template.getClusterId()));