dev-tmp1
luotaiqian 2026-08-18 18:24:55 +08:00
parent 67854c604c
commit df2d0a4399
9 changed files with 60 additions and 37 deletions

View File

@ -28,4 +28,7 @@ public class PaperQuestionRelDO extends BaseEntity {
@ApiModelProperty("试题id") @ApiModelProperty("试题id")
private Long questionId; private Long questionId;
@ApiModelProperty("试题号")
private Integer questionNum;
} }

View File

@ -51,9 +51,6 @@ public class QuestionDO extends BaseEntity {
@ApiModelProperty("标签类型") @ApiModelProperty("标签类型")
private String tagType; private String tagType;
@ApiModelProperty("试题号")
private Integer questionNum;
@ApiModelProperty("关联课件管理id") @ApiModelProperty("关联课件管理id")
private Long coursewareManagementId; private Long coursewareManagementId;
} }

View File

@ -1,21 +1,23 @@
package org.qinan.cedu.service.impl; package org.qinan.cedu.service.impl;
import cn.hutool.core.util.IdUtil; import cn.hutool.core.util.IdUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.baomidou.mybatisplus.extension.toolkit.Db;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.qinan.cedu.enums.DeleteEnum; import org.qinan.cedu.enums.DeleteEnum;
import org.qinan.cedu.enums.QuestionTypeEnum; import org.qinan.cedu.enums.QuestionTypeEnum;
import org.qinan.cedu.mapper.PaperMapper;
import org.qinan.cedu.mapper.PaperQuestionRelMapper;
import org.qinan.cedu.mapper.QuestionMapper;
import org.qinan.cedu.mapper.QuestionOptionMapper;
import org.qinan.cedu.model.dto.PaperQuestionSaveDTO; import org.qinan.cedu.model.dto.PaperQuestionSaveDTO;
import org.qinan.cedu.model.entity.PaperDO; import org.qinan.cedu.model.entity.PaperDO;
import org.qinan.cedu.model.entity.PaperQuestionRelDO; import org.qinan.cedu.model.entity.PaperQuestionRelDO;
import org.qinan.cedu.model.entity.QuestionDO; import org.qinan.cedu.model.entity.QuestionDO;
import org.qinan.cedu.model.entity.QuestionOptionDO; import org.qinan.cedu.model.entity.QuestionOptionDO;
import org.qinan.cedu.mapper.PaperQuestionRelMapper;
import org.qinan.cedu.service.PaperQuestionRelService; import org.qinan.cedu.service.PaperQuestionRelService;
import org.qinan.cedu.service.PaperService;
import org.qinan.cedu.service.QuestionOptionService;
import org.qinan.cedu.service.QuestionService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
@ -31,27 +33,22 @@ import java.util.stream.Collectors;
* *
*/ */
@Service @Service
@Slf4j
@RequiredArgsConstructor
public class PaperQuestionRelServiceImpl extends ServiceImpl<PaperQuestionRelMapper, PaperQuestionRelDO> implements PaperQuestionRelService { public class PaperQuestionRelServiceImpl extends ServiceImpl<PaperQuestionRelMapper, PaperQuestionRelDO> implements PaperQuestionRelService {
@Autowired private final PaperMapper paperMapper;
@Lazy private final QuestionMapper questionMapper;
private PaperService paperService; private final QuestionOptionMapper questionOptionMapper;
@Autowired
private QuestionService questionService;
@Autowired
private QuestionOptionService questionOptionService;
@Override @Override
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public void savePaperQuestion(PaperQuestionSaveDTO dto) { public void savePaperQuestion(PaperQuestionSaveDTO dto) {
// 校验试卷存在 // 校验试卷存在
PaperDO paper = paperService.lambdaQuery() boolean exists = paperMapper.exists(new LambdaQueryWrapper<PaperDO>()
.eq(PaperDO::getId, dto.getPaperId()) .eq(PaperDO::getId, dto.getPaperId())
.eq(PaperDO::getDeleteEnum, DeleteEnum.FALSE.getCode()) .eq(PaperDO::getDeleteEnum, DeleteEnum.FALSE.getCode()));
.one(); if (exists) {
if (paper == null) {
throw new IllegalArgumentException("试卷不存在id=" + dto.getPaperId()); throw new IllegalArgumentException("试卷不存在id=" + dto.getPaperId());
} }
@ -115,8 +112,8 @@ public class PaperQuestionRelServiceImpl extends ServiceImpl<PaperQuestionRelMap
.map(option -> String.valueOf(option.getId())) .map(option -> String.valueOf(option.getId()))
.collect(Collectors.joining(","))); .collect(Collectors.joining(",")));
questionService.save(question); questionMapper.insert(question);
questionOptionService.saveBatch(options); Db.saveBatch(options);
// 追加绑定试卷试题(不清空已有绑定) // 追加绑定试卷试题(不清空已有绑定)
PaperQuestionRelDO rel = new PaperQuestionRelDO(); PaperQuestionRelDO rel = new PaperQuestionRelDO();
@ -140,7 +137,7 @@ public class PaperQuestionRelServiceImpl extends ServiceImpl<PaperQuestionRelMap
} }
// 逻辑删除试题及其选项 // 逻辑删除试题及其选项
boolean deleted = questionService.deleteById(questionId); boolean deleted = questionMapper.deleteById(questionId) != 0;
if (!deleted) { if (!deleted) {
throw new IllegalArgumentException("试题不存在id=" + questionId); throw new IllegalArgumentException("试题不存在id=" + questionId);
} }

View File

@ -4,7 +4,6 @@ import cn.hutool.core.util.IdUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.baomidou.mybatisplus.extension.toolkit.Db; import com.baomidou.mybatisplus.extension.toolkit.Db;
@ -39,6 +38,7 @@ import java.time.LocalDateTime;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.stream.Collectors; import java.util.stream.Collectors;
/** /**
@ -137,6 +137,9 @@ public class PaperServiceImpl extends ServiceImpl<PaperMapper, PaperDO> implemen
if (questions.isEmpty()) { if (questions.isEmpty()) {
return; return;
} }
Map<Long, Integer> questionNumByQuestionId = rels.stream()
.filter(rel -> rel.getQuestionNum() != null)
.collect(Collectors.toMap(PaperQuestionRelDO::getQuestionId, PaperQuestionRelDO::getQuestionNum, (a, b) -> a));
List<QuestionOptionDO> newOptions = new ArrayList<>(); List<QuestionOptionDO> newOptions = new ArrayList<>();
List<PaperQuestionRelDO> newRels = new ArrayList<>(); List<PaperQuestionRelDO> newRels = new ArrayList<>();
for (QuestionDO question : questions) { for (QuestionDO question : questions) {
@ -173,6 +176,7 @@ public class PaperServiceImpl extends ServiceImpl<PaperMapper, PaperDO> implemen
PaperQuestionRelDO rel = new PaperQuestionRelDO(); PaperQuestionRelDO rel = new PaperQuestionRelDO();
rel.setPaperId(target.getId()); rel.setPaperId(target.getId());
rel.setQuestionId(newQuestionId); rel.setQuestionId(newQuestionId);
rel.setQuestionNum(questionNumByQuestionId.get(oldQuestionId));
rel.setCreateTime(now); rel.setCreateTime(now);
rel.setUpdateTime(now); rel.setUpdateTime(now);
newRels.add(rel); newRels.add(rel);
@ -253,11 +257,18 @@ public class PaperServiceImpl extends ServiceImpl<PaperMapper, PaperDO> implemen
Db.saveBatch(parseResult.getOptions()); Db.saveBatch(parseResult.getOptions());
List<QuestionDO> questions = parseResult.getQuestions(); List<QuestionDO> questions = parseResult.getQuestions();
// 绑定试卷试题 // 绑定试卷试题(含试题号)
this.bindQuestions(paper.getId(), questions.stream() LocalDateTime now = LocalDateTime.now();
.map(QuestionDO::getId) List<PaperQuestionRelDO> rels = new ArrayList<>(questions.size());
.collect(Collectors.toList())); for (int i = 0; i < questions.size(); i++) {
PaperQuestionRelDO rel = new PaperQuestionRelDO();
rel.setPaperId(paper.getId());
rel.setQuestionId(questions.get(0).getId());
rel.setQuestionNum(i + 1);
InsertFieldDefaults.applyIgnoreOrgId(rel);
rels.add(rel);
}
Db.saveBatch(rels);
return new PaperImportVO(questions.size(), parseResult.getErrors()); return new PaperImportVO(questions.size(), parseResult.getErrors());
} }
} }

View File

@ -1,6 +1,8 @@
package org.qinan.cedu.service.impl; package org.qinan.cedu.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.qinan.cedu.model.entity.QuestionOptionDO; import org.qinan.cedu.model.entity.QuestionOptionDO;
import org.qinan.cedu.mapper.QuestionOptionMapper; import org.qinan.cedu.mapper.QuestionOptionMapper;
import org.qinan.cedu.service.QuestionOptionService; import org.qinan.cedu.service.QuestionOptionService;
@ -10,5 +12,7 @@ import org.springframework.stereotype.Service;
* *
*/ */
@Service @Service
@Slf4j
@RequiredArgsConstructor
public class QuestionOptionServiceImpl extends ServiceImpl<QuestionOptionMapper, QuestionOptionDO> implements QuestionOptionService { public class QuestionOptionServiceImpl extends ServiceImpl<QuestionOptionMapper, QuestionOptionDO> implements QuestionOptionService {
} }

View File

@ -5,6 +5,8 @@ import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.qinan.cedu.enums.DeleteEnum; import org.qinan.cedu.enums.DeleteEnum;
import org.qinan.cedu.enums.QuestionTypeEnum; import org.qinan.cedu.enums.QuestionTypeEnum;
import org.qinan.cedu.mapper.QuestionMapper; import org.qinan.cedu.mapper.QuestionMapper;
@ -32,6 +34,8 @@ import java.util.stream.Collectors;
* *
*/ */
@Service @Service
@Slf4j
@RequiredArgsConstructor
public class QuestionServiceImpl extends ServiceImpl<QuestionMapper, QuestionDO> implements QuestionService { public class QuestionServiceImpl extends ServiceImpl<QuestionMapper, QuestionDO> implements QuestionService {
@Autowired @Autowired

View File

@ -299,7 +299,7 @@ public class QuestionExcelImporter {
} }
QuestionDO questionDO = buildChoiceQuestion(row, questionType, answerLetters, coursewareManagementId); QuestionDO questionDO = buildChoiceQuestion(row, questionType, answerLetters, coursewareManagementId);
questionDO.setQuestionNum(rowIndex - HEAD_ROW_NUMBER); parseResult.getQuestionNumByQuestionId().put(questionDO.getId(), rowIndex - HEAD_ROW_NUMBER);
List<QuestionOptionDO> questionOptionDOS = buildOptions(questionDO.getId(), options, answerLetters); List<QuestionOptionDO> questionOptionDOS = buildOptions(questionDO.getId(), options, answerLetters);
questionDO.setAnswerQuestionOptionIds(joinCorrectOptionIds(questionOptionDOS)); questionDO.setAnswerQuestionOptionIds(joinCorrectOptionIds(questionOptionDOS));
@ -380,7 +380,7 @@ public class QuestionExcelImporter {
question.setAnalysis(row.getAnalysis().trim()); question.setAnalysis(row.getAnalysis().trim());
question.setTagType(row.getTagType().trim()); question.setTagType(row.getTagType().trim());
question.setCoursewareManagementId(coursewareManagementId); question.setCoursewareManagementId(coursewareManagementId);
question.setQuestionNum(rowIndex - HEAD_ROW_NUMBER); parseResult.getQuestionNumByQuestionId().put(question.getId(), rowIndex - HEAD_ROW_NUMBER);
InsertFieldDefaults.applyIgnoreOrgId(question); InsertFieldDefaults.applyIgnoreOrgId(question);
Map<String, String> optionTexts = new LinkedHashMap<>(); Map<String, String> optionTexts = new LinkedHashMap<>();
optionTexts.put(OPTION_KEY_A, JUDGE_CORRECT_OPTION_TEXT); optionTexts.put(OPTION_KEY_A, JUDGE_CORRECT_OPTION_TEXT);
@ -509,6 +509,11 @@ public class QuestionExcelImporter {
*/ */
private final List<QuestionOptionDO> options; private final List<QuestionOptionDO> options;
/**
* id
*/
private final Map<Long, Integer> questionNumByQuestionId;
/** /**
* *
*/ */
@ -524,6 +529,7 @@ public class QuestionExcelImporter {
public ParseResult(List<QuestionDO> questions, List<QuestionOptionDO> options, List<PaperImportErrorVO> errors) { public ParseResult(List<QuestionDO> questions, List<QuestionOptionDO> options, List<PaperImportErrorVO> errors) {
this.questions = questions; this.questions = questions;
this.options = options; this.options = options;
this.questionNumByQuestionId = new HashMap<>();
this.errors = errors; this.errors = errors;
} }
@ -533,6 +539,7 @@ public class QuestionExcelImporter {
public ParseResult() { public ParseResult() {
this.questions = new ArrayList<>(64); this.questions = new ArrayList<>(64);
this.options = new ArrayList<>(256); this.options = new ArrayList<>(256);
this.questionNumByQuestionId = new HashMap<>();
this.errors = new ArrayList<>(64); this.errors = new ArrayList<>(64);
} }
@ -544,6 +551,7 @@ public class QuestionExcelImporter {
public ParseResult(List<PaperImportErrorVO> errors) { public ParseResult(List<PaperImportErrorVO> errors) {
this.questions = new ArrayList<>(64); this.questions = new ArrayList<>(64);
this.options = new ArrayList<>(256); this.options = new ArrayList<>(256);
this.questionNumByQuestionId = new HashMap<>();
this.errors = errors; this.errors = errors;
} }
} }

View File

@ -4,7 +4,7 @@
<select id="pagePaperQuestions" resultType="org.qinan.cedu.model.vo.PaperQuestionVO"> <select id="pagePaperQuestions" resultType="org.qinan.cedu.model.vo.PaperQuestionVO">
SELECT q.id, q.title, q.score, q.answer_question_option_ids, q.analysis SELECT q.id, q.title, q.score, q.answer_question_option_ids, q.analysis
, q.question_type, q.tag_type, q.question_num , q.question_type, q.tag_type, pqr.question_num
, cm.courseware_name , cm.courseware_name
FROM paper_question_rel pqr FROM paper_question_rel pqr
JOIN question q ON pqr.question_id = q.id JOIN question q ON pqr.question_id = q.id

View File

@ -81,7 +81,6 @@ CREATE TABLE `questionDO`
`score` decimal(5, 2) NOT NULL DEFAULT 0.00 COMMENT '分值', `score` decimal(5, 2) NOT NULL DEFAULT 0.00 COMMENT '分值',
`analysis` text CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL COMMENT '答案解析', `analysis` text CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL COMMENT '答案解析',
`tag_type` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '标签类型', `tag_type` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '标签类型',
`question_num` int NULL DEFAULT NULL COMMENT '试题号',
`courseware_management_id` bigint NULL DEFAULT NULL COMMENT '关联课件管理id', `courseware_management_id` bigint NULL DEFAULT NULL COMMENT '关联课件管理id',
`delete_enum` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '删除标识true false', `delete_enum` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '删除标识true false',
`remarks` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '备注', `remarks` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '备注',