Browse Source

实体类注释修改

master
luoweijian 2 months ago
parent
commit
d6be0d0044
  1. 51
      src/main/java/com/project/classicpaper/application/impl/ClassicCategoryApplicationServiceImpl.java
  2. 18
      src/main/java/com/project/classicpaper/application/impl/ClassicPaperSetApplicationServiceImpl.java
  3. 3
      src/main/java/com/project/classicpaper/domain/dto/ClassicCategoryDTO.java
  4. 3
      src/main/java/com/project/classicpaper/domain/entity/ClassicPaperEntity.java
  5. 11
      src/main/java/com/project/classicpaper/domain/entity/ClassicPaperSetEntity.java
  6. 58
      src/main/java/com/project/classicpaper/domain/service/PaperGenerationTracker.java
  7. 8
      src/main/java/com/project/classicpaper/domain/service/impl/ClassicPaperQuestionCallbackServiceImpl.java
  8. 33
      src/main/java/com/project/classicpaper/domain/service/impl/GenerateClassicPaperDomainServiceImpl.java
  9. 4
      src/main/java/com/project/ding/domain/entity/DepartmentEntity.java
  10. 3
      src/main/java/com/project/ding/domain/entity/UserEntity.java
  11. 4
      src/main/java/com/project/exam/domain/entity/AiGradingLogEntity.java
  12. 65
      src/main/java/com/project/information/application/impl/DraftReviewApplicationServiceImpl.java
  13. 4
      src/main/java/com/project/information/domain/entity/KnowledgePointEntity.java
  14. 6
      src/main/java/com/project/question/domain/entity/QuestionEntity.java
  15. 7
      src/main/java/com/project/statistics/domain/entity/ErrorProneStatisticsEntity.java
  16. 4
      src/main/java/com/project/task/domain/entity/TaskEntity.java
  17. 3
      src/main/java/com/project/task/domain/entity/TaskPaperSnapshotEntity.java

51
src/main/java/com/project/classicpaper/application/impl/ClassicCategoryApplicationServiceImpl.java

@ -8,11 +8,15 @@ import com.project.base.domain.utils.TreeUtils;
import com.project.classicpaper.application.ClassicCategoryApplicationService; import com.project.classicpaper.application.ClassicCategoryApplicationService;
import com.project.classicpaper.domain.dto.ClassicCategoryDTO; import com.project.classicpaper.domain.dto.ClassicCategoryDTO;
import com.project.classicpaper.domain.entity.ClassicCategoryEntity; import com.project.classicpaper.domain.entity.ClassicCategoryEntity;
import com.project.classicpaper.domain.entity.ClassicPaperSetEntity;
import com.project.classicpaper.domain.service.ClassicCategoryBaseService; import com.project.classicpaper.domain.service.ClassicCategoryBaseService;
import com.project.classicpaper.domain.service.ClassicPaperSetBaseService;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.Objects; import java.util.Objects;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@ -22,16 +26,59 @@ public class ClassicCategoryApplicationServiceImpl implements ClassicCategoryApp
@Autowired @Autowired
private ClassicCategoryBaseService classicCategoryBaseService; private ClassicCategoryBaseService classicCategoryBaseService;
@Autowired
private ClassicPaperSetBaseService classicPaperSetBaseService;
@Override @Override
public Result<List<ClassicCategoryDTO>> treeList() { public Result<List<ClassicCategoryDTO>> treeList() {
// 1. 查所有分类 → DTO
List<ClassicCategoryDTO> list = classicCategoryBaseService.list( List<ClassicCategoryDTO> list = classicCategoryBaseService.list(
new LambdaQueryWrapper<ClassicCategoryEntity>().orderByAsc(ClassicCategoryEntity::getSort) new LambdaQueryWrapper<ClassicCategoryEntity>().orderByAsc(ClassicCategoryEntity::getSort)
).stream().map(entity -> entity.toDTO(ClassicCategoryDTO::new)) ).stream().map(entity -> entity.toDTO(ClassicCategoryDTO::new))
.collect(Collectors.toList()); .collect(Collectors.toList());
return Result.success(TreeUtils.buildLongTree(list,
// 2. 构建树
List<ClassicCategoryDTO> tree = TreeUtils.buildLongTree(list,
ClassicCategoryDTO::getId, ClassicCategoryDTO::getId,
ClassicCategoryDTO::getParentId, ClassicCategoryDTO::getParentId,
ClassicCategoryDTO::setChildrenList)); ClassicCategoryDTO::setChildrenList);
// 3. 统计各分类下的套题组数量
List<ClassicPaperSetEntity> allSets = classicPaperSetBaseService.lambdaQuery()
.select(ClassicPaperSetEntity::getClassicCategoryId)
.list();
Map<Long, Integer> countMap = new HashMap<>();
for (ClassicPaperSetEntity set : allSets) {
Long catId = set.getClassicCategoryId();
if (catId != null) {
countMap.merge(catId, 1, Integer::sum);
}
}
// 4. 注入 paperSetCount 到树节点
injectPaperSetCount(tree, countMap);
return Result.success(tree);
}
/**
* 递归注入 paperSetCount
* 二级节点取直接统计值一级节点累加子节点
*/
private void injectPaperSetCount(List<ClassicCategoryDTO> nodes, Map<Long, Integer> countMap) {
for (ClassicCategoryDTO node : nodes) {
if (node.getChildrenList() != null && !node.getChildrenList().isEmpty()) {
// 一级分类:先递归处理子节点,再累加
injectPaperSetCount(node.getChildrenList(), countMap);
int sum = node.getChildrenList().stream()
.mapToInt(c -> c.getPaperSetCount() != null ? c.getPaperSetCount() : 0)
.sum();
node.setPaperSetCount(sum);
} else {
// 二级分类:直接取统计值
node.setPaperSetCount(countMap.getOrDefault(node.getId(), 0));
}
}
} }
@Override @Override

18
src/main/java/com/project/classicpaper/application/impl/ClassicPaperSetApplicationServiceImpl.java

@ -18,6 +18,7 @@ import com.project.classicpaper.domain.entity.ClassicPaperSetEntity;
import com.project.classicpaper.domain.entity.RegenerateQuestionTaskEntity; import com.project.classicpaper.domain.entity.RegenerateQuestionTaskEntity;
import com.project.classicpaper.domain.enums.ClassicPaperStatusEnum; import com.project.classicpaper.domain.enums.ClassicPaperStatusEnum;
import com.project.classicpaper.domain.param.ClassicPaperSetParam; import com.project.classicpaper.domain.param.ClassicPaperSetParam;
import com.project.classicpaper.domain.entity.ClassicCategoryEntity;
import com.project.classicpaper.domain.service.*; import com.project.classicpaper.domain.service.*;
import com.project.question.domain.entity.QuestionEntity; import com.project.question.domain.entity.QuestionEntity;
import com.project.question.domain.service.QuestionBaseService; import com.project.question.domain.service.QuestionBaseService;
@ -58,6 +59,9 @@ public class ClassicPaperSetApplicationServiceImpl implements ClassicPaperSetApp
@Autowired @Autowired
private ImportClassicPaperDomainService importClassicPaperDomainService; private ImportClassicPaperDomainService importClassicPaperDomainService;
@Autowired
private ClassicCategoryBaseService classicCategoryBaseService;
@Autowired @Autowired
private com.project.task.config.ExamScoreRatioConfig examScoreRatioConfig; private com.project.task.config.ExamScoreRatioConfig examScoreRatioConfig;
@ -77,7 +81,19 @@ public class ClassicPaperSetApplicationServiceImpl implements ClassicPaperSetApp
wrapper.eq(ClassicPaperSetEntity::getSubLineId, param.getSubLineId()); wrapper.eq(ClassicPaperSetEntity::getSubLineId, param.getSubLineId());
} }
if (param.getClassicCategoryId() != null) { if (param.getClassicCategoryId() != null) {
wrapper.eq(ClassicPaperSetEntity::getClassicCategoryId, param.getClassicCategoryId()); Set<Long> catIds = new HashSet<>();
catIds.add(param.getClassicCategoryId());
// 如果是一级分类,查找所有二级子分类
ClassicCategoryEntity cat = classicCategoryBaseService.getById(param.getClassicCategoryId());
if (cat != null && cat.getLevel() != null && cat.getLevel() == 1) {
List<ClassicCategoryEntity> children = classicCategoryBaseService.lambdaQuery()
.eq(ClassicCategoryEntity::getParentId, param.getClassicCategoryId())
.list();
for (ClassicCategoryEntity child : children) {
catIds.add(child.getId());
}
}
wrapper.in(ClassicPaperSetEntity::getClassicCategoryId, catIds);
} }
if (param.getStatus() != null) { if (param.getStatus() != null) {
wrapper.eq(ClassicPaperSetEntity::getStatus, param.getStatus()); wrapper.eq(ClassicPaperSetEntity::getStatus, param.getStatus());

3
src/main/java/com/project/classicpaper/domain/dto/ClassicCategoryDTO.java

@ -18,5 +18,8 @@ public class ClassicCategoryDTO extends BaseDTO {
private Integer sort = 0; private Integer sort = 0;
/** 该分类下的套题组数量(一级=下属二级总和,二级=直接数量) */
private Integer paperSetCount = 0;
private List<ClassicCategoryDTO> childrenList = new ArrayList<>(); private List<ClassicCategoryDTO> childrenList = new ArrayList<>();
} }

3
src/main/java/com/project/classicpaper/domain/entity/ClassicPaperEntity.java

@ -40,8 +40,9 @@ public class ClassicPaperEntity extends BaseEntity {
@Comment("来源子产品线ID") @Comment("来源子产品线ID")
private Long subLineId; private Long subLineId;
@Column(name = "information_ids", columnDefinition = "json comment '关联资料ID列表'") @Column(name = "information_ids")
@TableField("information_ids") @TableField("information_ids")
@Comment("关联资料ID列表")
private String informationIds; private String informationIds;
@Column(name = "status") @Column(name = "status")

11
src/main/java/com/project/classicpaper/domain/entity/ClassicPaperSetEntity.java

@ -4,11 +4,13 @@ import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName; import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;
import com.project.base.domain.entity.BaseEntity; import com.project.base.domain.entity.BaseEntity;
import jakarta.persistence.*; import jakarta.persistence.*;
import lombok.Data; import lombok.Data;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
import org.hibernate.annotations.Comment; import org.hibernate.annotations.Comment;
import org.hibernate.annotations.JdbcTypeCode;
@Data @Data
@Table(name = "evaluator_classic_paper_set", @Table(name = "evaluator_classic_paper_set",
@ -76,14 +78,15 @@ public class ClassicPaperSetEntity extends BaseEntity {
@Comment("简答题数量") @Comment("简答题数量")
private Integer shortAnswerNum; private Integer shortAnswerNum;
@Column(name = "score_ratio", columnDefinition = "json comment '分值比例配置'") @Column(name = "score_ratio") // 移除 columnDefinition
@TableField("score_ratio") @Comment("分值比例配置") // 使用专门的注解来定义注释
@JdbcTypeCode(org.hibernate.type.SqlTypes.JSON) // 明确告知 Hibernate 这是 JSON 类型
@TableField(value = "score_ratio", typeHandler = JacksonTypeHandler.class) // MyBatis-Plus 配置
private String scoreRatio; private String scoreRatio;
@Column(name = "status") @Column(name = "status")
@TableField("status") @TableField("status")
@Comment("状态:0-生成中,1-草稿,2-已确认,3-已废弃") @Comment("状态:0-生成中,1-草稿,2-已确认,3-已废弃") private Integer status;
private Integer status;
@Column(name = "source_file_name", columnDefinition = "varchar(500) comment '导入原始文件MinIO路径(Word导入时记录)'") @Column(name = "source_file_name", columnDefinition = "varchar(500) comment '导入原始文件MinIO路径(Word导入时记录)'")
@TableField("source_file_name") @TableField("source_file_name")

58
src/main/java/com/project/classicpaper/domain/service/PaperGenerationTracker.java

@ -1,58 +0,0 @@
package com.project.classicpaper.domain.service;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CountDownLatch;
/**
* 经典套卷生题等待跟踪器
* generate() 通过它等待所有异步回调完成后才返回
*/
@Component
@Slf4j
public class PaperGenerationTracker {
private final ConcurrentHashMap<Long, CountDownLatch> latches = new ConcurrentHashMap<>();
/**
* 开始跟踪某个 paper 的生成进度
* @param paperId 套卷ID
* @param totalCount 需要生成的题目总数
*/
public void track(Long paperId, int totalCount) {
latches.put(paperId, new CountDownLatch(totalCount));
log.info(">>> [生题跟踪] 开始跟踪 paperId={}, 总题数={}", paperId, totalCount);
}
/**
* 某道题回调完成countDown
*/
public void onQuestionGenerated(Long paperId) {
CountDownLatch latch = latches.get(paperId);
if (latch != null) {
latch.countDown();
log.debug(">>> [生题跟踪] paperId={}, 剩余={}", paperId, latch.getCount());
}
}
/**
* 等待所有题目生成完成一直等待无超时
*/
public void waitForCompletion(Long paperId) {
CountDownLatch latch = latches.get(paperId);
if (latch == null) {
return;
}
try {
latch.await();
log.info(">>> [生题跟踪] paperId={} 所有题目生成完成", paperId);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
log.warn(">>> [生题跟踪] paperId={} 等待被中断", paperId);
} finally {
latches.remove(paperId);
}
}
}

8
src/main/java/com/project/classicpaper/domain/service/impl/ClassicPaperQuestionCallbackServiceImpl.java

@ -40,9 +40,6 @@ public class ClassicPaperQuestionCallbackServiceImpl implements ClassicPaperQues
@Autowired @Autowired
private ClassicPaperSetBaseService classicPaperSetBaseService; private ClassicPaperSetBaseService classicPaperSetBaseService;
@Autowired
private PaperGenerationTracker paperGenerationTracker;
@Override @Override
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public void handleCallback(QuestionCallBackDTO callback) { public void handleCallback(QuestionCallBackDTO callback) {
@ -105,10 +102,7 @@ public class ClassicPaperQuestionCallbackServiceImpl implements ClassicPaperQues
log.info(">>> [经典套题-回调] 处理完成, paperQuestionId={}, promotedQuestionId={}", log.info(">>> [经典套题-回调] 处理完成, paperQuestionId={}, promotedQuestionId={}",
paperQuestionId, promoted.getId()); paperQuestionId, promoted.getId());
// 5. 通知跟踪器(释放 generate() 的等待) // 检查当前 paper 的所有题目是否都已生成完成
paperGenerationTracker.onQuestionGenerated(paperId);
// 6. 检查当前 paper 的所有题目是否都已生成完成
boolean paperAllDone = classicPaperQuestionBaseService.count( boolean paperAllDone = classicPaperQuestionBaseService.count(
new LambdaQueryWrapper<ClassicPaperQuestionEntity>() new LambdaQueryWrapper<ClassicPaperQuestionEntity>()
.eq(ClassicPaperQuestionEntity::getPaperId, paperId) .eq(ClassicPaperQuestionEntity::getPaperId, paperId)

33
src/main/java/com/project/classicpaper/domain/service/impl/GenerateClassicPaperDomainServiceImpl.java

@ -72,9 +72,6 @@ public class GenerateClassicPaperDomainServiceImpl implements GenerateClassicPap
@Autowired @Autowired
private com.project.task.config.ExamScoreRatioConfig examScoreRatioConfig; private com.project.task.config.ExamScoreRatioConfig examScoreRatioConfig;
@Autowired
private PaperGenerationTracker paperGenerationTracker;
@Value("${classicpaper.spare.per-question:2}") @Value("${classicpaper.spare.per-question:2}")
private int sparePerQuestion; private int sparePerQuestion;
@ -184,20 +181,16 @@ public class GenerateClassicPaperDomainServiceImpl implements GenerateClassicPap
paperDTOs.add(paperDTO); paperDTOs.add(paperDTO);
} }
// 8. 所有子套题生成完成,将状态从"生成中"改为"草稿" // 注意:生题为异步流程,此处不等待完成
classicPaperBaseService.lambdaUpdate() // paper 状态会在回调中逐步更新为 DRAFT
.eq(ClassicPaperEntity::getSetId, paperSet.getId()) // paperSet 状态会在所有 paper 都完成后更新为 DRAFT
.set(ClassicPaperEntity::getStatus, ClassicPaperStatusEnum.DRAFT.getValue())
.update();
paperSet.setStatus(ClassicPaperStatusEnum.DRAFT.getValue());
classicPaperSetBaseService.updateById(paperSet);
log.info(">>> [经典套题] 批量生成完成, setId={}, 版本数={}, 每套题数={}", log.info(">>> [经典套题] 生成任务已提交, setId={}, 版本数={}, 每套题数={}",
paperSet.getId(), setCount, totalPerSet); paperSet.getId(), setCount, totalPerSet);
// 10. 构建返回 DTO // 8. 构建返回 DTO(套题组状态为 GENERATING,等待异步完成)
ClassicPaperSetDTO setDTO = paperSet.toDTO(ClassicPaperSetDTO::new); ClassicPaperSetDTO setDTO = paperSet.toDTO(ClassicPaperSetDTO::new);
setDTO.setStatusText(ClassicPaperStatusEnum.DRAFT.getDesc()); setDTO.setStatusText(ClassicPaperStatusEnum.GENERATING.getDesc());
setDTO.setPaperList(paperDTOs); setDTO.setPaperList(paperDTOs);
return Result.success(setDTO); return Result.success(setDTO);
} }
@ -363,9 +356,6 @@ public class GenerateClassicPaperDomainServiceImpl implements GenerateClassicPap
// ============ Phase 2: 提交异步生题任务 ============ // ============ Phase 2: 提交异步生题任务 ============
// 注册等待跟踪
paperGenerationTracker.track(paper.getId(), totalQuestions);
// 逐个提交异步任务(使用 Phase 1 采样好的 KPs) // 逐个提交异步任务(使用 Phase 1 采样好的 KPs)
for (PaperQuestionTask task : paperQuestionTasks) { for (PaperQuestionTask task : paperQuestionTasks) {
classicPaperQuestionGenerator.generateAsync( classicPaperQuestionGenerator.generateAsync(
@ -373,15 +363,12 @@ public class GenerateClassicPaperDomainServiceImpl implements GenerateClassicPap
1 + sparePerQuestion); 1 + sparePerQuestion);
} }
// ============ Phase 3: 等待所有回调完成 ============ // ============ Phase 3: 立即返回 ============
// 生题为异步流程,回调会逐步填充 questionId 并更新状态
paperGenerationTracker.waitForCompletion(paper.getId()); // 此处不阻塞等待,立即返回
// ============ Phase 4: 构建返回 DTO ============
// 回调已填充 questionId,paper 状态已在回调中更新为 DRAFT
ClassicPaperDTO dto = paper.toDTO(ClassicPaperDTO::new); ClassicPaperDTO dto = paper.toDTO(ClassicPaperDTO::new);
dto.setStatusText(ClassicPaperStatusEnum.DRAFT.getDesc()); dto.setStatusText(ClassicPaperStatusEnum.GENERATING.getDesc());
return dto; return dto;
} }

4
src/main/java/com/project/ding/domain/entity/DepartmentEntity.java

@ -9,6 +9,7 @@ import com.project.base.domain.entity.BaseEntity;
import jakarta.persistence.*; import jakarta.persistence.*;
import lombok.Data; import lombok.Data;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
import org.hibernate.annotations.Comment;
import org.hibernate.annotations.JdbcTypeCode; import org.hibernate.annotations.JdbcTypeCode;
import org.hibernate.type.SqlTypes; import org.hibernate.type.SqlTypes;
@ -35,7 +36,8 @@ public class DepartmentEntity extends BaseEntity {
@TableField(value = "dept_id_path" , typeHandler = JacksonTypeHandler.class) @TableField(value = "dept_id_path" , typeHandler = JacksonTypeHandler.class)
@Column(name = "dept_id_path", columnDefinition = "json comment '部门ID全路径'") @Column(name = "dept_id_path")
@JdbcTypeCode(SqlTypes.JSON) @JdbcTypeCode(SqlTypes.JSON)
@Comment("部门ID全路径")
private List<Long> deptIdPath; private List<Long> deptIdPath;
} }

3
src/main/java/com/project/ding/domain/entity/UserEntity.java

@ -61,8 +61,9 @@ public class UserEntity extends BaseEntity {
* 存储为 JSON 数组: [1, 10, 101] * 存储为 JSON 数组: [1, 10, 101]
*/ */
@TableField(value = "dept_id_list" , typeHandler = JacksonTypeHandler.class) @TableField(value = "dept_id_list" , typeHandler = JacksonTypeHandler.class)
@Column(name = "dept_id_list", columnDefinition = "json comment '部门ID列表'") @Column(name = "dept_id_list")
@JdbcTypeCode(SqlTypes.JSON) @JdbcTypeCode(SqlTypes.JSON)
@Comment("部门ID列表")
private List<Long> deptIdList; private List<Long> deptIdList;
@Column(name = "dept_path_name_str" , columnDefinition="varchar(1000) comment '部门全路径集合'") @Column(name = "dept_path_name_str" , columnDefinition="varchar(1000) comment '部门全路径集合'")

4
src/main/java/com/project/exam/domain/entity/AiGradingLogEntity.java

@ -62,7 +62,9 @@ public class AiGradingLogEntity extends BaseEntity {
/** 命中的得分点index列表 */ /** 命中的得分点index列表 */
@TableField(value = "hit_points", typeHandler = JacksonTypeHandler.class) @TableField(value = "hit_points", typeHandler = JacksonTypeHandler.class)
@JdbcTypeCode(SqlTypes.JSON) @JdbcTypeCode(SqlTypes.JSON)
@Column(name = "hit_points", columnDefinition = "json comment '命中得分点列表'") @Column(name = "hit_points")
@Comment("命中得分点列表")
private List<Integer> hitPoints; private List<Integer> hitPoints;
/** 总得分点数 */ /** 总得分点数 */

65
src/main/java/com/project/information/application/impl/DraftReviewApplicationServiceImpl.java

@ -24,7 +24,11 @@ import org.springframework.stereotype.Service;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.Objects; import java.util.Objects;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
@ -154,23 +158,25 @@ public class DraftReviewApplicationServiceImpl implements DraftReviewApplication
throw new BusinessErrorException("该资料不在待审核状态"); throw new BusinessErrorException("该资料不在待审核状态");
} }
// 2. 获取该资料下所有待审核草稿 // 2. 获取该资料下所有待审核草稿ID(仅查ID,减少数据传输)
List<KnowledgePointDraftEntity> existingDrafts = knowledgePointDraftBaseService.list( List<Long> existingIds = knowledgePointDraftBaseService.lambdaQuery()
new LambdaQueryWrapper<KnowledgePointDraftEntity>() .select(KnowledgePointDraftEntity::getId)
.eq(KnowledgePointDraftEntity::getInformationId, informationId) .eq(KnowledgePointDraftEntity::getInformationId, informationId)
.eq(KnowledgePointDraftEntity::getAuditStatus, AuditStatusEnum.PENDING.getValue())); .eq(KnowledgePointDraftEntity::getAuditStatus, AuditStatusEnum.PENDING.getValue())
List<Long> existingIds = existingDrafts.stream() .list()
.map(KnowledgePointDraftEntity::getId).toList(); .stream()
.map(KnowledgePointDraftEntity::getId)
.toList();
// 3. 用户传来的草稿ID集合 // 3. 用户传来的草稿ID集合(用Set,O(1)查找)
List<Long> incomingIds = draftList.stream() Set<Long> incomingIdSet = draftList.stream()
.map(DraftSaveDTO::getId) .map(DraftSaveDTO::getId)
.filter(Objects::nonNull) .filter(Objects::nonNull)
.toList(); .collect(Collectors.toSet());
// 4. 计算用户删除的草稿ID // 4. 计算用户删除的草稿ID
List<Long> deletedIds = existingIds.stream() List<Long> deletedIds = existingIds.stream()
.filter(id -> !incomingIds.contains(id)) .filter(id -> !incomingIdSet.contains(id))
.toList(); .toList();
// 5. 逻辑删除(deleted=1),保留审计记录 // 5. 逻辑删除(deleted=1),保留审计记录
@ -181,21 +187,32 @@ public class DraftReviewApplicationServiceImpl implements DraftReviewApplication
.update(); .update();
} }
// 6. 更新/编辑草稿 // 6. 批量查现存草稿,批量更新确认(替代逐个 getById + updateById)
List<Long> toConfirmIds = incomingIdSet.stream()
.filter(existingIds::contains)
.toList();
List<KnowledgePointDraftEntity> confirmedDrafts = new ArrayList<>(); List<KnowledgePointDraftEntity> confirmedDrafts = new ArrayList<>();
for (DraftSaveDTO dto : draftList) { if (!toConfirmIds.isEmpty()) {
if (dto.getId() != null) { // 构建 dto 映射,O(1) 查找
// 编辑现有草稿 Map<Long, DraftSaveDTO> dtoMap = draftList.stream()
KnowledgePointDraftEntity oldDraft = knowledgePointDraftBaseService.getById(dto.getId()); .filter(d -> d.getId() != null)
if (oldDraft != null && AuditStatusEnum.PENDING.getValue().equals(oldDraft.getAuditStatus())) { .collect(Collectors.toMap(DraftSaveDTO::getId, d -> d));
oldDraft.setContent(dto.getContent()); List<KnowledgePointDraftEntity> existingDrafts = knowledgePointDraftBaseService.listByIds(toConfirmIds);
oldDraft.setKnowledgeType(dto.getKnowledgeType() != null ? dto.getKnowledgeType() : oldDraft.getKnowledgeType()); for (KnowledgePointDraftEntity draft : existingDrafts) {
// aiContent 保留不动(AI原始返回用于审计对比) if (!AuditStatusEnum.PENDING.getValue().equals(draft.getAuditStatus())) {
oldDraft.setAuditStatus(AuditStatusEnum.APPROVED.getValue()); continue;
knowledgePointDraftBaseService.updateById(oldDraft); }
confirmedDrafts.add(oldDraft); DraftSaveDTO dto = dtoMap.get(draft.getId());
if (dto == null) {
continue;
} }
draft.setContent(dto.getContent());
draft.setKnowledgeType(dto.getKnowledgeType() != null ? dto.getKnowledgeType() : draft.getKnowledgeType());
// aiContent 保留不动(AI原始返回用于审计对比)
draft.setAuditStatus(AuditStatusEnum.APPROVED.getValue());
confirmedDrafts.add(draft);
} }
knowledgePointDraftBaseService.updateBatchById(confirmedDrafts);
} }
// 7. 复制草稿content到正式知识点表 // 7. 复制草稿content到正式知识点表
@ -218,7 +235,7 @@ public class DraftReviewApplicationServiceImpl implements DraftReviewApplication
.update(); .update();
// 9. 触发聚类 // 9. 触发聚类
triggerClustering(informationId, knowledgePoints); CompletableFuture.runAsync(() -> triggerClustering(informationId, knowledgePoints));
log.info(">>> [草稿审核] 批量保存并确认完成, informationId={}, 草稿数={}", informationId, confirmedDrafts.size()); log.info(">>> [草稿审核] 批量保存并确认完成, informationId={}, 草稿数={}", informationId, confirmedDrafts.size());
return Result.success("保存成功,已审核通过"); return Result.success("保存成功,已审核通过");

4
src/main/java/com/project/information/domain/entity/KnowledgePointEntity.java

@ -55,7 +55,9 @@ public class KnowledgePointEntity extends BaseEntity {
@TableField(value = "exam_focus_list" , typeHandler = JacksonTypeHandler.class) @TableField(value = "exam_focus_list" , typeHandler = JacksonTypeHandler.class)
@JdbcTypeCode(SqlTypes.JSON) @JdbcTypeCode(SqlTypes.JSON)
@Column(name = "exam_focus_list", columnDefinition = "json comment '考点集合'") @Column(name = "exam_focus_list")
@Comment("考点集合")
private List<ExamFocus> examFocusList; private List<ExamFocus> examFocusList;

6
src/main/java/com/project/question/domain/entity/QuestionEntity.java

@ -47,7 +47,8 @@ public class QuestionEntity extends BaseEntity {
@TableField(value = "kp_id_list" , typeHandler = JacksonTypeHandler.class) @TableField(value = "kp_id_list" , typeHandler = JacksonTypeHandler.class)
@JdbcTypeCode(SqlTypes.JSON) @JdbcTypeCode(SqlTypes.JSON)
@Column(name = "kp_id_list", columnDefinition = "json comment '覆盖知识点ID列表'") @Column(name = "kp_id_list")
@Comment("覆盖知识点ID列表")
private List<Long> kpIdList; private List<Long> kpIdList;
@ -63,7 +64,8 @@ public class QuestionEntity extends BaseEntity {
@TableField(value = "question_detail" , typeHandler = JacksonTypeHandler.class) @TableField(value = "question_detail" , typeHandler = JacksonTypeHandler.class)
@JdbcTypeCode(SqlTypes.JSON) @JdbcTypeCode(SqlTypes.JSON)
@Column(name = "question_detail", columnDefinition = "json comment '题目内容'") @Column(name = "question_detail")
@Comment("题目内容")
private QuestionDetail questionDetail; private QuestionDetail questionDetail;
@Data @Data

7
src/main/java/com/project/statistics/domain/entity/ErrorProneStatisticsEntity.java

@ -46,8 +46,9 @@ public class ErrorProneStatisticsEntity extends BaseEntity {
* 生成式多个题目ID经典套题只有一个题目ID * 生成式多个题目ID经典套题只有一个题目ID
*/ */
@TableField(value = "question_id_list" , typeHandler = JacksonTypeHandler.class) @TableField(value = "question_id_list" , typeHandler = JacksonTypeHandler.class)
@Column(name = "question_id_list", columnDefinition = "json comment '关联题目列表'") @Column(name = "question_id_list")
@JdbcTypeCode(SqlTypes.JSON) @JdbcTypeCode(SqlTypes.JSON)
@Comment("关联题目列表")
private List<Long> questionIdList; private List<Long> questionIdList;
@Column(name = "kp_id") @Column(name = "kp_id")
@ -75,7 +76,9 @@ public class ErrorProneStatisticsEntity extends BaseEntity {
@TableField(value = "option_detail" , typeHandler = JacksonTypeHandler.class) @TableField(value = "option_detail" , typeHandler = JacksonTypeHandler.class)
@JdbcTypeCode(SqlTypes.JSON) @JdbcTypeCode(SqlTypes.JSON)
@Column(name = "option_detail", columnDefinition = "json comment '选项内容'") @Column(name = "option_detail")
@Comment("选项内容")
private List<OptionDetail> optionDetails; private List<OptionDetail> optionDetails;
@Data @Data

4
src/main/java/com/project/task/domain/entity/TaskEntity.java

@ -99,8 +99,10 @@ public class TaskEntity extends BaseEntity {
* 存储为 JSON 数组: [1, 10, 101] * 存储为 JSON 数组: [1, 10, 101]
*/ */
@TableField(value = "related_document_list" , typeHandler = JacksonTypeHandler.class) @TableField(value = "related_document_list" , typeHandler = JacksonTypeHandler.class)
@Column(name = "related_document_list", columnDefinition = "json comment '关联文档列表'") @Column(name = "related_document_list")
@JdbcTypeCode(SqlTypes.JSON) @JdbcTypeCode(SqlTypes.JSON)
@Comment("关联文档列表")
private List<Long> relatedDocumentList; private List<Long> relatedDocumentList;

3
src/main/java/com/project/task/domain/entity/TaskPaperSnapshotEntity.java

@ -57,6 +57,7 @@ public class TaskPaperSnapshotEntity extends BaseEntity {
@TableField(value = "question_detail", typeHandler = JacksonTypeHandler.class) @TableField(value = "question_detail", typeHandler = JacksonTypeHandler.class)
@JdbcTypeCode(SqlTypes.JSON) @JdbcTypeCode(SqlTypes.JSON)
@Column(name = "question_detail", columnDefinition = "json comment '题目内容快照(题干+选项+答案+解析,含图片URL)'") @Column(name = "question_detail")
@Comment("题目内容快照(题干+选项+答案+解析,含图片URL)")
private QuestionEntity.QuestionDetail questionDetail; private QuestionEntity.QuestionDetail questionDetail;
} }

Loading…
Cancel
Save