paper
parent
688d7e14b0
commit
8bc4e87607
|
|
@ -56,8 +56,4 @@ public class QuestionDO extends BaseEntity {
|
||||||
|
|
||||||
@ApiModelProperty("关联课件管理id")
|
@ApiModelProperty("关联课件管理id")
|
||||||
private Long coursewareManagementId;
|
private Long coursewareManagementId;
|
||||||
|
|
||||||
@ApiModelProperty("试题选项列表")
|
|
||||||
@TableField(exist = false)
|
|
||||||
private List<QuestionOptionDO> options;
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -205,7 +205,7 @@ public class PaperServiceImpl extends ServiceImpl<PaperMapper, PaperDO> implemen
|
||||||
@Override
|
@Override
|
||||||
@Transactional(rollbackFor = Exception.class)
|
@Transactional(rollbackFor = Exception.class)
|
||||||
public boolean bindQuestions(Long paperId, List<Long> questionIds) {
|
public boolean bindQuestions(Long paperId, List<Long> questionIds) {
|
||||||
paperQuestionRelService.remove(Wrappers.<PaperQuestionRelDO>lambdaQuery()
|
Db.remove(Wrappers.<PaperQuestionRelDO>lambdaQuery()
|
||||||
.eq(PaperQuestionRelDO::getPaperId, paperId));
|
.eq(PaperQuestionRelDO::getPaperId, paperId));
|
||||||
if (CollectionUtils.isEmpty(questionIds)) {
|
if (CollectionUtils.isEmpty(questionIds)) {
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -219,7 +219,7 @@ public class PaperServiceImpl extends ServiceImpl<PaperMapper, PaperDO> implemen
|
||||||
rel.setUpdateTime(now);
|
rel.setUpdateTime(now);
|
||||||
return rel;
|
return rel;
|
||||||
}).collect(Collectors.toList());
|
}).collect(Collectors.toList());
|
||||||
return paperQuestionRelService.saveBatch(rels);
|
return Db.saveBatch(rels);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -237,8 +237,8 @@ public class PaperServiceImpl extends ServiceImpl<PaperMapper, PaperDO> implemen
|
||||||
@Transactional(rollbackFor = Exception.class)
|
@Transactional(rollbackFor = Exception.class)
|
||||||
public PaperImportVO importQuestions(PaperImportDTO importDTO) {
|
public PaperImportVO importQuestions(PaperImportDTO importDTO) {
|
||||||
QuestionExcelImporter.ParseResult parseResult = questionExcelImporter.parse(importDTO.getFile());
|
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());
|
return new PaperImportVO(0, parseResult.getErrors());
|
||||||
}
|
}
|
||||||
|
|
@ -252,22 +252,10 @@ public class PaperServiceImpl extends ServiceImpl<PaperMapper, PaperDO> implemen
|
||||||
this.savePaper(paper);
|
this.savePaper(paper);
|
||||||
|
|
||||||
// 保存试题和选项(id已预置雪花id)
|
// 保存试题和选项(id已预置雪花id)
|
||||||
LocalDateTime now = LocalDateTime.now();
|
Db.saveBatch(parseResult.getQuestions());
|
||||||
List<QuestionOptionDO> options = new ArrayList<>();
|
Db.saveBatch(parseResult.getOptions());
|
||||||
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);
|
|
||||||
|
|
||||||
|
List<QuestionDO> questions = parseResult.getQuestions();
|
||||||
// 绑定试卷试题
|
// 绑定试卷试题
|
||||||
this.bindQuestions(paper.getId(), questions.stream()
|
this.bindQuestions(paper.getId(), questions.stream()
|
||||||
.map(QuestionDO::getId)
|
.map(QuestionDO::getId)
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,6 @@ import com.alibaba.excel.EasyExcel;
|
||||||
import com.alibaba.excel.ExcelReader;
|
import com.alibaba.excel.ExcelReader;
|
||||||
import com.alibaba.excel.read.metadata.ReadSheet;
|
import com.alibaba.excel.read.metadata.ReadSheet;
|
||||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
import lombok.AllArgsConstructor;
|
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
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.QuestionDO;
|
||||||
import org.qinan.cedu.model.entity.QuestionOptionDO;
|
import org.qinan.cedu.model.entity.QuestionOptionDO;
|
||||||
import org.qinan.cedu.model.vo.PaperImportErrorVO;
|
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.stereotype.Component;
|
||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
import org.springframework.web.multipart.MultipartFile;
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
@ -86,38 +85,40 @@ public class QuestionExcelImporter {
|
||||||
Map<Integer, String> sheetNames = readSheetNames(bytes);
|
Map<Integer, String> sheetNames = readSheetNames(bytes);
|
||||||
|
|
||||||
List<PaperImportErrorVO> errors = new ArrayList<>();
|
List<PaperImportErrorVO> errors = new ArrayList<>();
|
||||||
List<ChoiceQuestionImportRow> singleRows;
|
List<ChoiceQuestionImportRow> singleRows = new ArrayList<>();
|
||||||
List<ChoiceQuestionImportRow> multipleRows;
|
List<ChoiceQuestionImportRow> multipleRows = new ArrayList<>();
|
||||||
List<JudgeQuestionImportRow> judgeRows;
|
List<JudgeQuestionImportRow> judgeRows = new ArrayList<>();
|
||||||
try {
|
try {
|
||||||
singleRows = readSheet(bytes, SINGLE_SHEET_NO, ChoiceQuestionImportRow.class);
|
singleRows = readSheet(bytes, SINGLE_SHEET_NO, ChoiceQuestionImportRow.class);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
singleRows = new ArrayList<>();
|
|
||||||
errors.add(new PaperImportErrorVO(null, sheetName(sheetNames, SINGLE_SHEET_NO)
|
errors.add(new PaperImportErrorVO(null, sheetName(sheetNames, SINGLE_SHEET_NO)
|
||||||
, READ_SINGLE_SHEET_FAIL_PREFIX + e.getMessage()));
|
, READ_SINGLE_SHEET_FAIL_PREFIX + e.getMessage()));
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
multipleRows = readSheet(bytes, MULTIPLE_SHEET_NO, ChoiceQuestionImportRow.class);
|
multipleRows = readSheet(bytes, MULTIPLE_SHEET_NO, ChoiceQuestionImportRow.class);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
multipleRows = new ArrayList<>();
|
|
||||||
errors.add(new PaperImportErrorVO(null, sheetName(sheetNames, MULTIPLE_SHEET_NO)
|
errors.add(new PaperImportErrorVO(null, sheetName(sheetNames, MULTIPLE_SHEET_NO)
|
||||||
, READ_MULTIPLE_SHEET_FAIL_PREFIX + e.getMessage()));
|
, READ_MULTIPLE_SHEET_FAIL_PREFIX + e.getMessage()));
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
judgeRows = readSheet(bytes, JUDGE_SHEET_NO, JudgeQuestionImportRow.class);
|
judgeRows = readSheet(bytes, JUDGE_SHEET_NO, JudgeQuestionImportRow.class);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
judgeRows = new ArrayList<>();
|
|
||||||
errors.add(new PaperImportErrorVO(null, sheetName(sheetNames, JUDGE_SHEET_NO)
|
errors.add(new PaperImportErrorVO(null, sheetName(sheetNames, JUDGE_SHEET_NO)
|
||||||
, READ_JUDGE_SHEET_FAIL_PREFIX + e.getMessage()));
|
, READ_JUDGE_SHEET_FAIL_PREFIX + e.getMessage()));
|
||||||
}
|
}
|
||||||
|
|
||||||
Map<String, Long> coursewareManagementIdByName = loadCoursewareIdByName(singleRows, multipleRows, judgeRows);
|
Map<String, Long> coursewareManagementIdByName = loadCoursewareIdByName(singleRows, multipleRows, judgeRows);
|
||||||
|
|
||||||
|
ParseResult parseResult = new ParseResult();
|
||||||
List<QuestionDO> questions = new ArrayList<>();
|
List<QuestionDO> questions = new ArrayList<>();
|
||||||
convertChoiceRows(singleRows, sheetName(sheetNames, SINGLE_SHEET_NO), QuestionTypeEnum.SINGLE, coursewareManagementIdByName, questions, errors);
|
List<QuestionOptionDO> options = new ArrayList<>();
|
||||||
convertChoiceRows(multipleRows, sheetName(sheetNames, MULTIPLE_SHEET_NO), QuestionTypeEnum.MULTIPLE, coursewareManagementIdByName, questions, errors);
|
convertChoiceRows(singleRows, sheetName(sheetNames, SINGLE_SHEET_NO)
|
||||||
convertJudgeRows(judgeRows, sheetName(sheetNames, JUDGE_SHEET_NO), coursewareManagementIdByName, questions, errors);
|
, QuestionTypeEnum.SINGLE, coursewareManagementIdByName, questions, options, errors);
|
||||||
return new ParseResult(questions, 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) {
|
private byte[] readBytes(MultipartFile file) {
|
||||||
|
|
@ -188,7 +189,7 @@ public class QuestionExcelImporter {
|
||||||
*/
|
*/
|
||||||
private void convertChoiceRows(List<ChoiceQuestionImportRow> rows, String sheetName, QuestionTypeEnum questionType,
|
private void convertChoiceRows(List<ChoiceQuestionImportRow> rows, String sheetName, QuestionTypeEnum questionType,
|
||||||
Map<String, Long> coursewareManagementIdByName, List<QuestionDO> questions,
|
Map<String, Long> coursewareManagementIdByName, List<QuestionDO> questions,
|
||||||
List<PaperImportErrorVO> errors) {
|
List<QuestionOptionDO> queOptions, List<PaperImportErrorVO> errors) {
|
||||||
boolean single = questionType == QuestionTypeEnum.SINGLE;
|
boolean single = questionType == QuestionTypeEnum.SINGLE;
|
||||||
for (int i = 0; i < rows.size(); i++) {
|
for (int i = 0; i < rows.size(); i++) {
|
||||||
ChoiceQuestionImportRow row = rows.get(i);
|
ChoiceQuestionImportRow row = rows.get(i);
|
||||||
|
|
@ -251,13 +252,15 @@ public class QuestionExcelImporter {
|
||||||
continue;
|
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,
|
private QuestionDO buildChoiceQuestion(ChoiceQuestionImportRow row, QuestionTypeEnum questionType,
|
||||||
Map<String, String> optionTexts, List<String> answerLetters,
|
List<String> answerLetters, Long coursewareManagementId) {
|
||||||
Long coursewareManagementId) {
|
|
||||||
QuestionDO question = new QuestionDO();
|
QuestionDO question = new QuestionDO();
|
||||||
question.setId(IdUtil.getSnowflakeNextId());
|
question.setId(IdUtil.getSnowflakeNextId());
|
||||||
question.setTitle(row.getTitle().trim());
|
question.setTitle(row.getTitle().trim());
|
||||||
|
|
@ -267,8 +270,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.setOptions(buildOptions(question.getId(), optionTexts, answerLetters));
|
InsertFieldDefaults.applyIgnoreOrgId(question);
|
||||||
question.setAnswerQuestionOptionIds(joinCorrectOptionIds(question.getOptions()));
|
|
||||||
return question;
|
return question;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -277,7 +279,7 @@ public class QuestionExcelImporter {
|
||||||
*/
|
*/
|
||||||
private void convertJudgeRows(List<JudgeQuestionImportRow> rows, String sheetName,
|
private void convertJudgeRows(List<JudgeQuestionImportRow> rows, String sheetName,
|
||||||
Map<String, Long> coursewareManagementIdByName, List<QuestionDO> questions,
|
Map<String, Long> coursewareManagementIdByName, List<QuestionDO> questions,
|
||||||
List<PaperImportErrorVO> errors) {
|
List<QuestionOptionDO> options, List<PaperImportErrorVO> errors) {
|
||||||
for (int i = 0; i < rows.size(); i++) {
|
for (int i = 0; i < rows.size(); i++) {
|
||||||
JudgeQuestionImportRow row = rows.get(i);
|
JudgeQuestionImportRow row = rows.get(i);
|
||||||
int rowIndex = i + HEAD_ROW_NUMBER + 1;
|
int rowIndex = i + HEAD_ROW_NUMBER + 1;
|
||||||
|
|
@ -318,9 +320,10 @@ public class QuestionExcelImporter {
|
||||||
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);
|
||||||
optionTexts.put(OPTION_KEY_B, JUDGE_WRONG_OPTION_TEXT);
|
optionTexts.put(OPTION_KEY_B, JUDGE_WRONG_OPTION_TEXT);
|
||||||
question.setOptions(buildOptions(question.getId(), optionTexts,
|
List<QuestionOptionDO> questionOptionDOS = buildOptions(question.getId(), optionTexts,
|
||||||
Collections.singletonList(correct ? OPTION_KEY_A : OPTION_KEY_B)));
|
Collections.singletonList(correct ? OPTION_KEY_A : OPTION_KEY_B));
|
||||||
question.setAnswerQuestionOptionIds(joinCorrectOptionIds(question.getOptions()));
|
options.addAll(questionOptionDOS);
|
||||||
|
question.setAnswerQuestionOptionIds(joinCorrectOptionIds(questionOptionDOS));
|
||||||
questions.add(question);
|
questions.add(question);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -338,6 +341,7 @@ public class QuestionExcelImporter {
|
||||||
option.setOptionText(entry.getValue());
|
option.setOptionText(entry.getValue());
|
||||||
option.setIsCorrect(answerLetters.contains(entry.getKey()));
|
option.setIsCorrect(answerLetters.contains(entry.getKey()));
|
||||||
option.setSortOrder(sortOrder++);
|
option.setSortOrder(sortOrder++);
|
||||||
|
InsertFieldDefaults.applyIgnoreOrgId(option);
|
||||||
options.add(option);
|
options.add(option);
|
||||||
}
|
}
|
||||||
return options;
|
return options;
|
||||||
|
|
@ -390,7 +394,6 @@ public class QuestionExcelImporter {
|
||||||
* 解析结果
|
* 解析结果
|
||||||
*/
|
*/
|
||||||
@Getter
|
@Getter
|
||||||
@AllArgsConstructor
|
|
||||||
public static class ParseResult {
|
public static class ParseResult {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -398,9 +401,26 @@ public class QuestionExcelImporter {
|
||||||
*/
|
*/
|
||||||
private final List<QuestionDO> questions;
|
private final List<QuestionDO> questions;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 校验通过的试题(含选项)
|
||||||
|
*/
|
||||||
|
private final List<QuestionOptionDO> options;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 异常明细
|
* 异常明细
|
||||||
*/
|
*/
|
||||||
private final List<PaperImportErrorVO> errors;
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue