archive file
parent
1fb5839a02
commit
5004254c45
|
|
@ -73,7 +73,7 @@ public class PaperController {
|
|||
|
||||
@ApiOperation("新建试卷-导入试题")
|
||||
@PostMapping("/import")
|
||||
public SingleResponse<PaperImportVO> importQuestions(@Validated PaperImportDTO paperImportDTO) {
|
||||
public SingleResponse<QuestionImportVO> importQuestions(@Validated PaperImportDTO paperImportDTO) {
|
||||
return SingleResponse.success(paperService.importQuestions(paperImportDTO));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import io.swagger.annotations.ApiOperation;
|
|||
import io.swagger.annotations.ApiParam;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.qinan.cedu.model.dto.*;
|
||||
import org.qinan.cedu.model.vo.QuestionImportVO;
|
||||
import org.qinan.cedu.model.vo.QuestionCoursewareVO;
|
||||
import org.qinan.cedu.model.vo.QuestionTypeCountVO;
|
||||
import org.qinan.cedu.model.vo.QuestionVO;
|
||||
|
|
@ -94,4 +95,10 @@ public class QuestionController {
|
|||
return PageResponse.of(page.getRecords(), page.getTotal());
|
||||
}
|
||||
|
||||
@ApiOperation("导入试题")
|
||||
@PostMapping("/import")
|
||||
public SingleResponse<QuestionImportVO> importQuestions(@Validated QuestionImportDTO questionImportDTO) {
|
||||
return SingleResponse.success(questionService.importQuestions(questionImportDTO));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,23 @@
|
|||
package org.qinan.cedu.model.dto;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
/**
|
||||
* 新建试卷-导入试题 请求对象
|
||||
*/
|
||||
@Data
|
||||
@ApiModel(value = "PaperImportDTO", description = "新建试卷-导入试题请求")
|
||||
public class QuestionImportDTO {
|
||||
|
||||
@ApiModelProperty("关联课件管理id")
|
||||
private Long coursewareManagementId;
|
||||
|
||||
@ApiModelProperty(value = "试题Excel文件(第一个sheet单选题,第二个sheet多选题,第三个sheet判断题)", required = true)
|
||||
@NotNull(message = "请上传试题Excel文件")
|
||||
private MultipartFile file;
|
||||
}
|
||||
|
|
@ -11,7 +11,7 @@ import lombok.NoArgsConstructor;
|
|||
*/
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
public class PaperImportErrorVO {
|
||||
public class QuestionImportErrorVO {
|
||||
|
||||
@ApiModelProperty(value = "Excel行号(从1开始的物理行号)")
|
||||
private Integer rowIndex;
|
||||
|
|
@ -22,7 +22,7 @@ public class PaperImportErrorVO {
|
|||
@ApiModelProperty(value = "异常原因")
|
||||
private String errorMessage;
|
||||
|
||||
public PaperImportErrorVO(Integer rowIndex, String sheetName, String errorMessage) {
|
||||
public QuestionImportErrorVO(Integer rowIndex, String sheetName, String errorMessage) {
|
||||
this.rowIndex = rowIndex;
|
||||
this.sheetName = sheetName;
|
||||
this.errorMessage = errorMessage;
|
||||
|
|
@ -14,15 +14,15 @@ import java.util.List;
|
|||
*/
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
public class PaperImportVO {
|
||||
public class QuestionImportVO {
|
||||
|
||||
@ApiModelProperty(value = "成功导入条数")
|
||||
private Integer successCount;
|
||||
|
||||
@ApiModelProperty(value = "异常明细")
|
||||
private List<PaperImportErrorVO> errors = new ArrayList<>();
|
||||
private List<QuestionImportErrorVO> errors = new ArrayList<>();
|
||||
|
||||
public PaperImportVO(Integer successCount, List<PaperImportErrorVO> errors) {
|
||||
public QuestionImportVO(Integer successCount, List<QuestionImportErrorVO> errors) {
|
||||
this.successCount = successCount;
|
||||
this.errors = errors;
|
||||
}
|
||||
|
|
@ -10,7 +10,7 @@ import org.qinan.cedu.model.dto.PaperPageQueryDTO;
|
|||
import org.qinan.cedu.model.dto.PaperUpdateDTO;
|
||||
import org.qinan.cedu.model.entity.PaperDO;
|
||||
import org.qinan.cedu.model.vo.PaperBasicInfoVO;
|
||||
import org.qinan.cedu.model.vo.PaperImportVO;
|
||||
import org.qinan.cedu.model.vo.QuestionImportVO;
|
||||
import org.qinan.cedu.model.vo.PaperExamInfoVO;
|
||||
import org.qinan.cedu.model.vo.PaperPageVO;
|
||||
|
||||
|
|
@ -91,7 +91,7 @@ public interface PaperService extends IService<PaperDO> {
|
|||
* @param importDTO 试卷信息+试题Excel文件
|
||||
* @return 导入结果(成功条数+异常明细)
|
||||
*/
|
||||
PaperImportVO importQuestions(PaperImportDTO importDTO);
|
||||
QuestionImportVO importQuestions(PaperImportDTO importDTO);
|
||||
|
||||
/**
|
||||
* importQuestionsTemplate
|
||||
|
|
|
|||
|
|
@ -5,10 +5,7 @@ import com.baomidou.mybatisplus.extension.service.IService;
|
|||
import org.qinan.cedu.model.dto.*;
|
||||
import org.qinan.cedu.model.entity.QuestionDO;
|
||||
import org.qinan.cedu.model.entity.QuestionOptionDO;
|
||||
import org.qinan.cedu.model.vo.PaperQuestionVO;
|
||||
import org.qinan.cedu.model.vo.QuestionCoursewareVO;
|
||||
import org.qinan.cedu.model.vo.QuestionTypeCountVO;
|
||||
import org.qinan.cedu.model.vo.QuestionVO;
|
||||
import org.qinan.cedu.model.vo.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
|
@ -122,4 +119,12 @@ public interface QuestionService extends IService<QuestionDO> {
|
|||
* @param dto dto
|
||||
*/
|
||||
void addQuestion(QuestionAddDTO dto);
|
||||
|
||||
/**
|
||||
* 导入试题
|
||||
*
|
||||
* @param questionImportDTO questionImportDTO
|
||||
* @return QuestionImportVO
|
||||
*/
|
||||
QuestionImportVO importQuestions(QuestionImportDTO questionImportDTO);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,12 +8,7 @@ import com.baomidou.mybatisplus.core.metadata.IPage;
|
|||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.baomidou.mybatisplus.extension.toolkit.Db;
|
||||
import com.lowagie.text.Document;
|
||||
import com.lowagie.text.DocumentException;
|
||||
import com.lowagie.text.Element;
|
||||
import com.lowagie.text.Font;
|
||||
import com.lowagie.text.PageSize;
|
||||
import com.lowagie.text.Paragraph;
|
||||
import com.lowagie.text.*;
|
||||
import com.lowagie.text.pdf.BaseFont;
|
||||
import com.lowagie.text.pdf.PdfWriter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
|
@ -28,23 +23,12 @@ 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.PaperConfigRuleDTO;
|
||||
import org.qinan.cedu.model.dto.PaperCopyDTO;
|
||||
import org.qinan.cedu.model.dto.PaperCoursewareQuestionRuleDTO;
|
||||
import org.qinan.cedu.model.dto.PaperImportDTO;
|
||||
import org.qinan.cedu.model.dto.PaperOrgPageQueryDTO;
|
||||
import org.qinan.cedu.model.dto.PaperPageQueryDTO;
|
||||
import org.qinan.cedu.model.dto.PaperUpdateDTO;
|
||||
import org.qinan.cedu.model.dto.*;
|
||||
import org.qinan.cedu.model.entity.PaperDO;
|
||||
import org.qinan.cedu.model.entity.PaperQuestionRelDO;
|
||||
import org.qinan.cedu.model.entity.QuestionDO;
|
||||
import org.qinan.cedu.model.entity.QuestionOptionDO;
|
||||
import org.qinan.cedu.model.vo.PaperBasicInfoVO;
|
||||
import org.qinan.cedu.model.vo.PaperExamInfoVO;
|
||||
import org.qinan.cedu.model.vo.PaperImportVO;
|
||||
import org.qinan.cedu.model.vo.PaperPageVO;
|
||||
import org.qinan.cedu.model.vo.QuestionOptionVO;
|
||||
import org.qinan.cedu.model.vo.QuestionVO;
|
||||
import org.qinan.cedu.model.vo.*;
|
||||
import org.qinan.cedu.service.PaperService;
|
||||
import org.qinan.cedu.service.support.QuestionExcelImporter;
|
||||
import org.qinan.safetyeval.infrastructure.support.InsertFieldDefaults;
|
||||
|
|
@ -276,12 +260,13 @@ public class PaperServiceImpl extends ServiceImpl<PaperMapper, PaperDO> implemen
|
|||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public PaperImportVO importQuestions(PaperImportDTO importDTO) {
|
||||
QuestionExcelImporter.ParseResult parseResult = questionExcelImporter.parse(importDTO.getFile());
|
||||
public QuestionImportVO importQuestions(PaperImportDTO importDTO) {
|
||||
QuestionExcelImporter.ParseResult parseResult = questionExcelImporter.parse(
|
||||
importDTO.getFile(), null);
|
||||
|
||||
if (!CollectionUtils.isEmpty(parseResult.getErrors())) {
|
||||
// 没有任何校验通过的试题,不创建试卷,直接返回异常明细
|
||||
return new PaperImportVO(0, parseResult.getErrors());
|
||||
return new QuestionImportVO(0, parseResult.getErrors());
|
||||
}
|
||||
|
||||
// 创建试卷
|
||||
|
|
@ -311,7 +296,7 @@ public class PaperServiceImpl extends ServiceImpl<PaperMapper, PaperDO> implemen
|
|||
rels.add(rel);
|
||||
}
|
||||
Db.saveBatch(rels);
|
||||
return new PaperImportVO(questions.size(), parseResult.getErrors());
|
||||
return new QuestionImportVO(questions.size(), parseResult.getErrors());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -16,11 +16,9 @@ import org.qinan.cedu.mapper.QuestionOptionMapper;
|
|||
import org.qinan.cedu.model.dto.*;
|
||||
import org.qinan.cedu.model.entity.QuestionDO;
|
||||
import org.qinan.cedu.model.entity.QuestionOptionDO;
|
||||
import org.qinan.cedu.model.vo.PaperQuestionVO;
|
||||
import org.qinan.cedu.model.vo.QuestionCoursewareVO;
|
||||
import org.qinan.cedu.model.vo.QuestionTypeCountVO;
|
||||
import org.qinan.cedu.model.vo.QuestionVO;
|
||||
import org.qinan.cedu.model.vo.*;
|
||||
import org.qinan.cedu.service.QuestionService;
|
||||
import org.qinan.cedu.service.support.QuestionExcelImporter;
|
||||
import org.qinan.safetyeval.infrastructure.support.InsertFieldDefaults;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
|
@ -43,6 +41,7 @@ public class QuestionServiceImpl extends ServiceImpl<QuestionMapper, QuestionDO>
|
|||
|
||||
private final QuestionOptionMapper questionOptionMapper;
|
||||
private final QuestionConvertor questionConvertor;
|
||||
private final QuestionExcelImporter questionExcelImporter;
|
||||
|
||||
@Override
|
||||
public IPage<PaperQuestionVO> pagePaperQuestions(PaperQuestionPageQueryDTO query) {
|
||||
|
|
@ -274,6 +273,23 @@ public class QuestionServiceImpl extends ServiceImpl<QuestionMapper, QuestionDO>
|
|||
Db.saveBatch(options);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public QuestionImportVO importQuestions(QuestionImportDTO importDTO) {
|
||||
QuestionExcelImporter.ParseResult parseResult = questionExcelImporter.parse(
|
||||
importDTO.getFile(), importDTO.getCoursewareManagementId());
|
||||
|
||||
if (!CollectionUtils.isEmpty(parseResult.getErrors())) {
|
||||
// 没有任何校验通过的试题,不创建试卷,直接返回异常明细
|
||||
return new QuestionImportVO(0, parseResult.getErrors());
|
||||
}
|
||||
|
||||
// 保存试题和选项(id已预置雪花id)
|
||||
Db.saveBatch(parseResult.getQuestions());
|
||||
Db.saveBatch(parseResult.getOptions());
|
||||
return new QuestionImportVO(parseResult.getQuestions().size(), parseResult.getErrors());
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存试题选项(重置id并绑定试题id、统一填充时间后批量插入)
|
||||
*
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package org.qinan.cedu.service.support;
|
||||
|
||||
import cn.hutool.core.util.IdUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.alibaba.excel.EasyExcel;
|
||||
import com.alibaba.excel.ExcelReader;
|
||||
import com.alibaba.excel.read.metadata.ReadSheet;
|
||||
|
|
@ -14,7 +15,7 @@ import org.qinan.cedu.mapper.CoursewareManagementMapper;
|
|||
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.qinan.cedu.model.vo.QuestionImportErrorVO;
|
||||
import org.qinan.safetyeval.infrastructure.support.InsertFieldDefaults;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
|
@ -71,6 +72,8 @@ public class QuestionExcelImporter {
|
|||
private static final String COMMA_DELIMITER = ",";
|
||||
private static final String VIOLATION_DELIMITER = ";";
|
||||
|
||||
public static final String DEFAULT_IMPORT_COURSEWARE_NAME = "默认使用导入试题关联的课件_id";
|
||||
|
||||
private final CoursewareManagementMapper coursewareManagementMapper;
|
||||
private final Validator validator;
|
||||
|
||||
|
|
@ -78,47 +81,49 @@ public class QuestionExcelImporter {
|
|||
* 解析上传的试题Excel,返回校验通过的试题(含选项,已预置雪花id)和异常明细
|
||||
*
|
||||
* @param file 上传的试题Excel文件
|
||||
* @param coursewareManagementId coursewareManagementId
|
||||
* @return 解析结果(试题、选项、异常明细)
|
||||
*/
|
||||
public ParseResult parse(MultipartFile file) {
|
||||
public ParseResult parse(MultipartFile file, Long coursewareManagementId) {
|
||||
if (file == null || file.isEmpty()) {
|
||||
throw new IllegalArgumentException(UPLOAD_EMPTY_MESSAGE);
|
||||
}
|
||||
byte[] bytes = readBytes(file);
|
||||
Map<Integer, String> sheetNames = readSheetNames(bytes);
|
||||
|
||||
List<PaperImportErrorVO> errors = new ArrayList<>();
|
||||
List<QuestionImportErrorVO> errors = new ArrayList<>();
|
||||
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) {
|
||||
errors.add(new PaperImportErrorVO(null, sheetName(sheetNames, SINGLE_SHEET_NO)
|
||||
errors.add(new QuestionImportErrorVO(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) {
|
||||
errors.add(new PaperImportErrorVO(null, sheetName(sheetNames, MULTIPLE_SHEET_NO)
|
||||
errors.add(new QuestionImportErrorVO(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) {
|
||||
errors.add(new PaperImportErrorVO(null, sheetName(sheetNames, JUDGE_SHEET_NO)
|
||||
errors.add(new QuestionImportErrorVO(null, sheetName(sheetNames, JUDGE_SHEET_NO)
|
||||
, READ_JUDGE_SHEET_FAIL_PREFIX + e.getMessage()));
|
||||
}
|
||||
|
||||
Map<String, Long> coursewareManagementIdByName = loadCoursewareIdByName(singleRows, multipleRows, judgeRows);
|
||||
Map<String, Long> coursewareManagementIdByName = loadCoursewareIdByName(
|
||||
singleRows, multipleRows, judgeRows, coursewareManagementId);
|
||||
|
||||
ParseResult parseResult = new ParseResult(errors);
|
||||
convertChoiceRows(singleRows, sheetName(sheetNames, SINGLE_SHEET_NO)
|
||||
, QuestionTypeEnum.SINGLE, coursewareManagementIdByName, parseResult);
|
||||
, QuestionTypeEnum.SINGLE, coursewareManagementIdByName, parseResult, coursewareManagementId);
|
||||
convertChoiceRows(multipleRows, sheetName(sheetNames, MULTIPLE_SHEET_NO)
|
||||
, QuestionTypeEnum.MULTIPLE, coursewareManagementIdByName, parseResult);
|
||||
, QuestionTypeEnum.MULTIPLE, coursewareManagementIdByName, parseResult, coursewareManagementId);
|
||||
convertJudgeRows(judgeRows, sheetName(sheetNames, JUDGE_SHEET_NO)
|
||||
, coursewareManagementIdByName, parseResult);
|
||||
, coursewareManagementIdByName, parseResult, coursewareManagementId);
|
||||
return parseResult;
|
||||
}
|
||||
|
||||
|
|
@ -188,18 +193,21 @@ public class QuestionExcelImporter {
|
|||
* @param singleRows 单选题行数据
|
||||
* @param multipleRows 多选题行数据
|
||||
* @param judgeRows 判断题行数据
|
||||
* @param coursewareManagementId coursewareManagementId
|
||||
* @return 课件名称到课件id的映射
|
||||
*/
|
||||
private Map<String, Long> loadCoursewareIdByName(List<ChoiceQuestionImportRow> singleRows,
|
||||
List<ChoiceQuestionImportRow> multipleRows,
|
||||
List<JudgeQuestionImportRow> judgeRows) {
|
||||
private Map<String, Long> loadCoursewareIdByName(List<ChoiceQuestionImportRow> singleRows
|
||||
, List<ChoiceQuestionImportRow> multipleRows, List<JudgeQuestionImportRow> judgeRows, Long coursewareManagementId) {
|
||||
Set<String> names = new HashSet<>();
|
||||
singleRows.forEach(row -> addCoursewareName(names, row.getCoursewareName()));
|
||||
multipleRows.forEach(row -> addCoursewareName(names, row.getCoursewareName()));
|
||||
judgeRows.forEach(row -> addCoursewareName(names, row.getCoursewareName()));
|
||||
if (names.isEmpty()) {
|
||||
if (coursewareManagementId == null) {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
return Collections.singletonMap(DEFAULT_IMPORT_COURSEWARE_NAME, coursewareManagementId);
|
||||
}
|
||||
List<CoursewareManagementDO> coursewares = coursewareManagementMapper.selectList(
|
||||
new LambdaQueryWrapper<CoursewareManagementDO>()
|
||||
.select(CoursewareManagementDO::getId, CoursewareManagementDO::getCoursewareName)
|
||||
|
|
@ -209,6 +217,9 @@ public class QuestionExcelImporter {
|
|||
for (CoursewareManagementDO courseware : coursewares) {
|
||||
idByName.putIfAbsent(courseware.getCoursewareName(), courseware.getId());
|
||||
}
|
||||
if (coursewareManagementId != null) {
|
||||
idByName.putIfAbsent(DEFAULT_IMPORT_COURSEWARE_NAME, coursewareManagementId);
|
||||
}
|
||||
return idByName;
|
||||
}
|
||||
|
||||
|
|
@ -232,10 +243,11 @@ public class QuestionExcelImporter {
|
|||
* @param questionType 题目类型(单选/多选)
|
||||
* @param coursewareManagementIdByName 课件名称到课件id的映射
|
||||
* @param parseResult 解析结果(写入试题、选项和异常明细)
|
||||
* @param formCoursewareManagementId formCoursewareManagementId
|
||||
*/
|
||||
private void convertChoiceRows(List<ChoiceQuestionImportRow> rows, String sheetName, QuestionTypeEnum questionType,
|
||||
Map<String, Long> coursewareManagementIdByName, ParseResult parseResult) {
|
||||
List<PaperImportErrorVO> errors = parseResult.getErrors();
|
||||
Map<String, Long> coursewareManagementIdByName, ParseResult parseResult, Long formCoursewareManagementId) {
|
||||
List<QuestionImportErrorVO> errors = parseResult.getErrors();
|
||||
boolean single = questionType == QuestionTypeEnum.SINGLE;
|
||||
for (int i = 0; i < rows.size(); i++) {
|
||||
ChoiceQuestionImportRow row = rows.get(i);
|
||||
|
|
@ -244,11 +256,15 @@ public class QuestionExcelImporter {
|
|||
continue;
|
||||
}
|
||||
row.setRowIndex(rowIndex);
|
||||
String coursewareName = StrUtil.trim(row.getCoursewareName());
|
||||
if (!StringUtils.hasText(coursewareName) && formCoursewareManagementId != null) {
|
||||
row.setCoursewareName(DEFAULT_IMPORT_COURSEWARE_NAME);
|
||||
}
|
||||
|
||||
// JSR-303 校验(必填、数据库长度限制),不通过则跳过该行
|
||||
Set<ConstraintViolation<ChoiceQuestionImportRow>> violations = validator.validate(row);
|
||||
if (!violations.isEmpty()) {
|
||||
errors.add(new PaperImportErrorVO(rowIndex, sheetName, joinViolationMessages(violations)));
|
||||
errors.add(new QuestionImportErrorVO(rowIndex, sheetName, joinViolationMessages(violations)));
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
@ -262,14 +278,14 @@ public class QuestionExcelImporter {
|
|||
}
|
||||
}
|
||||
if (options.size() < 2) {
|
||||
errors.add(new PaperImportErrorVO(rowIndex, sheetName, OPTION_AT_LEAST_TWO_MESSAGE));
|
||||
errors.add(new QuestionImportErrorVO(rowIndex, sheetName, OPTION_AT_LEAST_TWO_MESSAGE));
|
||||
continue;
|
||||
}
|
||||
|
||||
// 校验答案:必须有答案且答案必须能找到对应的选项
|
||||
String answerRaw = row.getAnswer().trim().toUpperCase();
|
||||
if (!answerRaw.chars().allMatch(c -> c >= 'A' && c <= 'F')) {
|
||||
errors.add(new PaperImportErrorVO(rowIndex, sheetName, CHOICE_ANSWER_LETTER_MESSAGE));
|
||||
errors.add(new QuestionImportErrorVO(rowIndex, sheetName, CHOICE_ANSWER_LETTER_MESSAGE));
|
||||
continue;
|
||||
}
|
||||
List<String> answerLetters = answerRaw.chars()
|
||||
|
|
@ -278,23 +294,22 @@ public class QuestionExcelImporter {
|
|||
.sorted()
|
||||
.collect(Collectors.toList());
|
||||
if (single && answerLetters.size() != 1) {
|
||||
errors.add(new PaperImportErrorVO(rowIndex, sheetName, SINGLE_ANSWER_LETTER_MESSAGE));
|
||||
errors.add(new QuestionImportErrorVO(rowIndex, sheetName, SINGLE_ANSWER_LETTER_MESSAGE));
|
||||
continue;
|
||||
}
|
||||
List<String> notMatched = answerLetters.stream()
|
||||
.filter(letter -> !options.containsKey(letter))
|
||||
.collect(Collectors.toList());
|
||||
if (!notMatched.isEmpty()) {
|
||||
errors.add(new PaperImportErrorVO(rowIndex, sheetName,
|
||||
errors.add(new QuestionImportErrorVO(rowIndex, sheetName,
|
||||
String.format(ANSWER_NOT_MATCH_OPTION_TEMPLATE, String.join("", notMatched))));
|
||||
continue;
|
||||
}
|
||||
|
||||
// 校验关联课件名称,查询到后回填coursewareManagementId
|
||||
String coursewareName = row.getCoursewareName().trim();
|
||||
Long coursewareManagementId = coursewareManagementIdByName.get(coursewareName);
|
||||
if (coursewareManagementId == null) {
|
||||
errors.add(new PaperImportErrorVO(rowIndex, sheetName, String.format(COURSEWARE_NOT_EXIST_TEMPLATE, coursewareName)));
|
||||
errors.add(new QuestionImportErrorVO(rowIndex, sheetName, String.format(COURSEWARE_NOT_EXIST_TEMPLATE, coursewareName)));
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
@ -339,10 +354,11 @@ public class QuestionExcelImporter {
|
|||
* @param sheetName sheet名称(用于异常提示定位)
|
||||
* @param coursewareManagementIdByName 课件名称到课件id的映射
|
||||
* @param parseResult 解析结果(写入试题、选项和异常明细)
|
||||
* @param formCoursewareManagementId formCoursewareManagementId
|
||||
*/
|
||||
private void convertJudgeRows(List<JudgeQuestionImportRow> rows, String sheetName,
|
||||
Map<String, Long> coursewareManagementIdByName, ParseResult parseResult) {
|
||||
List<PaperImportErrorVO> errors = parseResult.getErrors();
|
||||
Map<String, Long> coursewareManagementIdByName, ParseResult parseResult, Long formCoursewareManagementId) {
|
||||
List<QuestionImportErrorVO> errors = parseResult.getErrors();
|
||||
for (int i = 0; i < rows.size(); i++) {
|
||||
JudgeQuestionImportRow row = rows.get(i);
|
||||
int rowIndex = i + HEAD_ROW_NUMBER + 1;
|
||||
|
|
@ -350,23 +366,26 @@ public class QuestionExcelImporter {
|
|||
continue;
|
||||
}
|
||||
row.setRowIndex(rowIndex);
|
||||
String coursewareName = StrUtil.trim(row.getCoursewareName());
|
||||
if (!StringUtils.hasText(coursewareName) && formCoursewareManagementId != null) {
|
||||
row.setCoursewareName(DEFAULT_IMPORT_COURSEWARE_NAME);
|
||||
}
|
||||
|
||||
Set<ConstraintViolation<JudgeQuestionImportRow>> violations = validator.validate(row);
|
||||
if (!violations.isEmpty()) {
|
||||
errors.add(new PaperImportErrorVO(rowIndex, sheetName, joinViolationMessages(violations)));
|
||||
errors.add(new QuestionImportErrorVO(rowIndex, sheetName, joinViolationMessages(violations)));
|
||||
continue;
|
||||
}
|
||||
|
||||
String answerRaw = row.getAnswer().trim().toUpperCase();
|
||||
if (!JUDGE_ANSWER_TRUE.equals(answerRaw) && !JUDGE_ANSWER_FALSE.equals(answerRaw)) {
|
||||
errors.add(new PaperImportErrorVO(rowIndex, sheetName, JUDGE_ANSWER_LETTER_MESSAGE));
|
||||
errors.add(new QuestionImportErrorVO(rowIndex, sheetName, JUDGE_ANSWER_LETTER_MESSAGE));
|
||||
continue;
|
||||
}
|
||||
|
||||
String coursewareName = row.getCoursewareName().trim();
|
||||
Long coursewareManagementId = coursewareManagementIdByName.get(coursewareName);
|
||||
if (coursewareManagementId == null) {
|
||||
errors.add(new PaperImportErrorVO(rowIndex, sheetName, String.format(COURSEWARE_NOT_EXIST_TEMPLATE, coursewareName)));
|
||||
errors.add(new QuestionImportErrorVO(rowIndex, sheetName, String.format(COURSEWARE_NOT_EXIST_TEMPLATE, coursewareName)));
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
@ -517,7 +536,7 @@ public class QuestionExcelImporter {
|
|||
/**
|
||||
* 异常明细
|
||||
*/
|
||||
private final List<PaperImportErrorVO> errors;
|
||||
private final List<QuestionImportErrorVO> errors;
|
||||
|
||||
/**
|
||||
* 全参构造
|
||||
|
|
@ -526,7 +545,7 @@ public class QuestionExcelImporter {
|
|||
* @param options 校验通过的试题选项列表
|
||||
* @param errors 异常明细列表
|
||||
*/
|
||||
public ParseResult(List<QuestionDO> questions, List<QuestionOptionDO> options, List<PaperImportErrorVO> errors) {
|
||||
public ParseResult(List<QuestionDO> questions, List<QuestionOptionDO> options, List<QuestionImportErrorVO> errors) {
|
||||
this.questions = questions;
|
||||
this.options = options;
|
||||
this.questionNumByQuestionId = new HashMap<>();
|
||||
|
|
@ -548,7 +567,7 @@ public class QuestionExcelImporter {
|
|||
*
|
||||
* @param errors 异常明细列表
|
||||
*/
|
||||
public ParseResult(List<PaperImportErrorVO> errors) {
|
||||
public ParseResult(List<QuestionImportErrorVO> errors) {
|
||||
this.questions = new ArrayList<>(64);
|
||||
this.options = new ArrayList<>(256);
|
||||
this.questionNumByQuestionId = new HashMap<>();
|
||||
|
|
|
|||
Loading…
Reference in New Issue