dev-tmp1
luotaiqian 2026-08-18 09:52:58 +08:00
parent 688d7e14b0
commit 8bc4e87607
3 changed files with 50 additions and 46 deletions

View File

@ -56,8 +56,4 @@ public class QuestionDO extends BaseEntity {
@ApiModelProperty("关联课件管理id")
private Long coursewareManagementId;
@ApiModelProperty("试题选项列表")
@TableField(exist = false)
private List<QuestionOptionDO> options;
}

View File

@ -205,7 +205,7 @@ public class PaperServiceImpl extends ServiceImpl<PaperMapper, PaperDO> implemen
@Override
@Transactional(rollbackFor = Exception.class)
public boolean bindQuestions(Long paperId, List<Long> questionIds) {
paperQuestionRelService.remove(Wrappers.<PaperQuestionRelDO>lambdaQuery()
Db.remove(Wrappers.<PaperQuestionRelDO>lambdaQuery()
.eq(PaperQuestionRelDO::getPaperId, paperId));
if (CollectionUtils.isEmpty(questionIds)) {
return true;
@ -219,7 +219,7 @@ public class PaperServiceImpl extends ServiceImpl<PaperMapper, PaperDO> implemen
rel.setUpdateTime(now);
return rel;
}).collect(Collectors.toList());
return paperQuestionRelService.saveBatch(rels);
return Db.saveBatch(rels);
}
@Override
@ -237,8 +237,8 @@ public class PaperServiceImpl extends ServiceImpl<PaperMapper, PaperDO> implemen
@Transactional(rollbackFor = Exception.class)
public PaperImportVO importQuestions(PaperImportDTO importDTO) {
QuestionExcelImporter.ParseResult parseResult = questionExcelImporter.parse(importDTO.getFile());
List<QuestionDO> questions = parseResult.getQuestions();
if (CollectionUtils.isEmpty(questions)) {
if (!CollectionUtils.isEmpty(parseResult.getErrors())) {
// 没有任何校验通过的试题,不创建试卷,直接返回异常明细
return new PaperImportVO(0, parseResult.getErrors());
}
@ -252,22 +252,10 @@ public class PaperServiceImpl extends ServiceImpl<PaperMapper, PaperDO> implemen
this.savePaper(paper);
// 保存试题和选项id已预置雪花id
LocalDateTime now = LocalDateTime.now();
List<QuestionOptionDO> options = new ArrayList<>();
for (QuestionDO question : questions) {
question.setCreateTime(now);
question.setUpdateTime(now);
question.setVersion(0);
options.addAll(question.getOptions());
}
for (QuestionOptionDO option : options) {
option.setCreateTime(now);
option.setUpdateTime(now);
option.setVersion(0);
}
Db.saveBatch(questions);
Db.saveBatch(options);
Db.saveBatch(parseResult.getQuestions());
Db.saveBatch(parseResult.getOptions());
List<QuestionDO> questions = parseResult.getQuestions();
// 绑定试卷试题
this.bindQuestions(paper.getId(), questions.stream()
.map(QuestionDO::getId)

View File

@ -5,7 +5,6 @@ import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelReader;
import com.alibaba.excel.read.metadata.ReadSheet;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
@ -16,7 +15,7 @@ import org.qinan.cedu.model.entity.CoursewareManagementDO;
import org.qinan.cedu.model.entity.QuestionDO;
import org.qinan.cedu.model.entity.QuestionOptionDO;
import org.qinan.cedu.model.vo.PaperImportErrorVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.qinan.safetyeval.infrastructure.support.InsertFieldDefaults;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;
@ -86,38 +85,40 @@ public class QuestionExcelImporter {
Map<Integer, String> sheetNames = readSheetNames(bytes);
List<PaperImportErrorVO> errors = new ArrayList<>();
List<ChoiceQuestionImportRow> singleRows;
List<ChoiceQuestionImportRow> multipleRows;
List<JudgeQuestionImportRow> judgeRows;
List<ChoiceQuestionImportRow> singleRows = new ArrayList<>();
List<ChoiceQuestionImportRow> multipleRows = new ArrayList<>();
List<JudgeQuestionImportRow> judgeRows = new ArrayList<>();
try {
singleRows = readSheet(bytes, SINGLE_SHEET_NO, ChoiceQuestionImportRow.class);
} catch (Exception e) {
singleRows = new ArrayList<>();
errors.add(new PaperImportErrorVO(null, sheetName(sheetNames, SINGLE_SHEET_NO)
, READ_SINGLE_SHEET_FAIL_PREFIX + e.getMessage()));
}
try {
multipleRows = readSheet(bytes, MULTIPLE_SHEET_NO, ChoiceQuestionImportRow.class);
} catch (Exception e) {
multipleRows = new ArrayList<>();
errors.add(new PaperImportErrorVO(null, sheetName(sheetNames, MULTIPLE_SHEET_NO)
, READ_MULTIPLE_SHEET_FAIL_PREFIX + e.getMessage()));
}
try {
judgeRows = readSheet(bytes, JUDGE_SHEET_NO, JudgeQuestionImportRow.class);
} catch (Exception e) {
judgeRows = new ArrayList<>();
errors.add(new PaperImportErrorVO(null, sheetName(sheetNames, JUDGE_SHEET_NO)
, READ_JUDGE_SHEET_FAIL_PREFIX + e.getMessage()));
}
Map<String, Long> coursewareManagementIdByName = loadCoursewareIdByName(singleRows, multipleRows, judgeRows);
ParseResult parseResult = new ParseResult();
List<QuestionDO> questions = new ArrayList<>();
convertChoiceRows(singleRows, sheetName(sheetNames, SINGLE_SHEET_NO), QuestionTypeEnum.SINGLE, coursewareManagementIdByName, questions, errors);
convertChoiceRows(multipleRows, sheetName(sheetNames, MULTIPLE_SHEET_NO), QuestionTypeEnum.MULTIPLE, coursewareManagementIdByName, questions, errors);
convertJudgeRows(judgeRows, sheetName(sheetNames, JUDGE_SHEET_NO), coursewareManagementIdByName, questions, errors);
return new ParseResult(questions, errors);
List<QuestionOptionDO> options = new ArrayList<>();
convertChoiceRows(singleRows, sheetName(sheetNames, SINGLE_SHEET_NO)
, QuestionTypeEnum.SINGLE, coursewareManagementIdByName, questions, options, errors);
convertChoiceRows(multipleRows, sheetName(sheetNames, MULTIPLE_SHEET_NO)
, QuestionTypeEnum.MULTIPLE, coursewareManagementIdByName, questions, options, errors);
convertJudgeRows(judgeRows, sheetName(sheetNames, JUDGE_SHEET_NO)
, coursewareManagementIdByName, questions, options, errors);
return new ParseResult(questions, options, errors);
}
private byte[] readBytes(MultipartFile file) {
@ -188,7 +189,7 @@ public class QuestionExcelImporter {
*/
private void convertChoiceRows(List<ChoiceQuestionImportRow> rows, String sheetName, QuestionTypeEnum questionType,
Map<String, Long> coursewareManagementIdByName, List<QuestionDO> questions,
List<PaperImportErrorVO> errors) {
List<QuestionOptionDO> queOptions, List<PaperImportErrorVO> errors) {
boolean single = questionType == QuestionTypeEnum.SINGLE;
for (int i = 0; i < rows.size(); i++) {
ChoiceQuestionImportRow row = rows.get(i);
@ -251,13 +252,15 @@ public class QuestionExcelImporter {
continue;
}
questions.add(buildChoiceQuestion(row, questionType, options, answerLetters, coursewareManagementId));
QuestionDO questionDO = buildChoiceQuestion(row, questionType, answerLetters, coursewareManagementId);
List<QuestionOptionDO> questionOptionDOS = buildOptions(questionDO.getId(), options, answerLetters);
questions.add(questionDO);
queOptions.addAll(questionOptionDOS);
}
}
private QuestionDO buildChoiceQuestion(ChoiceQuestionImportRow row, QuestionTypeEnum questionType,
Map<String, String> optionTexts, List<String> answerLetters,
Long coursewareManagementId) {
List<String> answerLetters, Long coursewareManagementId) {
QuestionDO question = new QuestionDO();
question.setId(IdUtil.getSnowflakeNextId());
question.setTitle(row.getTitle().trim());
@ -267,8 +270,7 @@ public class QuestionExcelImporter {
question.setAnalysis(row.getAnalysis().trim());
question.setTagType(row.getTagType().trim());
question.setCoursewareManagementId(coursewareManagementId);
question.setOptions(buildOptions(question.getId(), optionTexts, answerLetters));
question.setAnswerQuestionOptionIds(joinCorrectOptionIds(question.getOptions()));
InsertFieldDefaults.applyIgnoreOrgId(question);
return question;
}
@ -277,7 +279,7 @@ public class QuestionExcelImporter {
*/
private void convertJudgeRows(List<JudgeQuestionImportRow> rows, String sheetName,
Map<String, Long> coursewareManagementIdByName, List<QuestionDO> questions,
List<PaperImportErrorVO> errors) {
List<QuestionOptionDO> options, List<PaperImportErrorVO> errors) {
for (int i = 0; i < rows.size(); i++) {
JudgeQuestionImportRow row = rows.get(i);
int rowIndex = i + HEAD_ROW_NUMBER + 1;
@ -318,9 +320,10 @@ public class QuestionExcelImporter {
Map<String, String> optionTexts = new LinkedHashMap<>();
optionTexts.put(OPTION_KEY_A, JUDGE_CORRECT_OPTION_TEXT);
optionTexts.put(OPTION_KEY_B, JUDGE_WRONG_OPTION_TEXT);
question.setOptions(buildOptions(question.getId(), optionTexts,
Collections.singletonList(correct ? OPTION_KEY_A : OPTION_KEY_B)));
question.setAnswerQuestionOptionIds(joinCorrectOptionIds(question.getOptions()));
List<QuestionOptionDO> questionOptionDOS = buildOptions(question.getId(), optionTexts,
Collections.singletonList(correct ? OPTION_KEY_A : OPTION_KEY_B));
options.addAll(questionOptionDOS);
question.setAnswerQuestionOptionIds(joinCorrectOptionIds(questionOptionDOS));
questions.add(question);
}
}
@ -338,6 +341,7 @@ public class QuestionExcelImporter {
option.setOptionText(entry.getValue());
option.setIsCorrect(answerLetters.contains(entry.getKey()));
option.setSortOrder(sortOrder++);
InsertFieldDefaults.applyIgnoreOrgId(option);
options.add(option);
}
return options;
@ -390,7 +394,6 @@ public class QuestionExcelImporter {
*
*/
@Getter
@AllArgsConstructor
public static class ParseResult {
/**
@ -398,9 +401,26 @@ public class QuestionExcelImporter {
*/
private final List<QuestionDO> questions;
/**
*
*/
private final List<QuestionOptionDO> options;
/**
*
*/
private final List<PaperImportErrorVO> errors;
public ParseResult(List<QuestionDO> questions, List<QuestionOptionDO> options, List<PaperImportErrorVO> errors) {
this.questions = questions;
this.options = options;
this.errors = errors;
}
public ParseResult() {
this.questions = new ArrayList<>(64);
this.options = new ArrayList<>(256);
this.errors = new ArrayList<>(64);
}
}
}