From 5004254c4577cb13374a2e3d068d4c5342943b55 Mon Sep 17 00:00:00 2001 From: luotaiqian <1147642922@qq.com> Date: Thu, 27 Aug 2026 10:58:11 +0800 Subject: [PATCH] archive file --- .../cedu/controller/PaperController.java | 2 +- .../cedu/controller/QuestionController.java | 7 ++ .../cedu/model/dto/QuestionImportDTO.java | 23 +++++ ...rrorVO.java => QuestionImportErrorVO.java} | 4 +- ...perImportVO.java => QuestionImportVO.java} | 6 +- .../org/qinan/cedu/service/PaperService.java | 4 +- .../qinan/cedu/service/QuestionService.java | 13 ++- .../cedu/service/impl/PaperServiceImpl.java | 31 ++----- .../service/impl/QuestionServiceImpl.java | 24 ++++- .../support/QuestionExcelImporter.java | 91 +++++++++++-------- 10 files changed, 130 insertions(+), 75 deletions(-) create mode 100644 safety-cedu-service/src/main/java/org/qinan/cedu/model/dto/QuestionImportDTO.java rename safety-cedu-service/src/main/java/org/qinan/cedu/model/vo/{PaperImportErrorVO.java => QuestionImportErrorVO.java} (82%) rename safety-cedu-service/src/main/java/org/qinan/cedu/model/vo/{PaperImportVO.java => QuestionImportVO.java} (72%) diff --git a/safety-cedu-service/src/main/java/org/qinan/cedu/controller/PaperController.java b/safety-cedu-service/src/main/java/org/qinan/cedu/controller/PaperController.java index 39506a37..8907a40f 100644 --- a/safety-cedu-service/src/main/java/org/qinan/cedu/controller/PaperController.java +++ b/safety-cedu-service/src/main/java/org/qinan/cedu/controller/PaperController.java @@ -73,7 +73,7 @@ public class PaperController { @ApiOperation("新建试卷-导入试题") @PostMapping("/import") - public SingleResponse importQuestions(@Validated PaperImportDTO paperImportDTO) { + public SingleResponse importQuestions(@Validated PaperImportDTO paperImportDTO) { return SingleResponse.success(paperService.importQuestions(paperImportDTO)); } diff --git a/safety-cedu-service/src/main/java/org/qinan/cedu/controller/QuestionController.java b/safety-cedu-service/src/main/java/org/qinan/cedu/controller/QuestionController.java index e5c90a94..37710c83 100644 --- a/safety-cedu-service/src/main/java/org/qinan/cedu/controller/QuestionController.java +++ b/safety-cedu-service/src/main/java/org/qinan/cedu/controller/QuestionController.java @@ -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 importQuestions(@Validated QuestionImportDTO questionImportDTO) { + return SingleResponse.success(questionService.importQuestions(questionImportDTO)); + } + } diff --git a/safety-cedu-service/src/main/java/org/qinan/cedu/model/dto/QuestionImportDTO.java b/safety-cedu-service/src/main/java/org/qinan/cedu/model/dto/QuestionImportDTO.java new file mode 100644 index 00000000..99892fae --- /dev/null +++ b/safety-cedu-service/src/main/java/org/qinan/cedu/model/dto/QuestionImportDTO.java @@ -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; +} diff --git a/safety-cedu-service/src/main/java/org/qinan/cedu/model/vo/PaperImportErrorVO.java b/safety-cedu-service/src/main/java/org/qinan/cedu/model/vo/QuestionImportErrorVO.java similarity index 82% rename from safety-cedu-service/src/main/java/org/qinan/cedu/model/vo/PaperImportErrorVO.java rename to safety-cedu-service/src/main/java/org/qinan/cedu/model/vo/QuestionImportErrorVO.java index af1681f3..ebdcaffe 100644 --- a/safety-cedu-service/src/main/java/org/qinan/cedu/model/vo/PaperImportErrorVO.java +++ b/safety-cedu-service/src/main/java/org/qinan/cedu/model/vo/QuestionImportErrorVO.java @@ -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; diff --git a/safety-cedu-service/src/main/java/org/qinan/cedu/model/vo/PaperImportVO.java b/safety-cedu-service/src/main/java/org/qinan/cedu/model/vo/QuestionImportVO.java similarity index 72% rename from safety-cedu-service/src/main/java/org/qinan/cedu/model/vo/PaperImportVO.java rename to safety-cedu-service/src/main/java/org/qinan/cedu/model/vo/QuestionImportVO.java index fe5c2ca7..fa070899 100644 --- a/safety-cedu-service/src/main/java/org/qinan/cedu/model/vo/PaperImportVO.java +++ b/safety-cedu-service/src/main/java/org/qinan/cedu/model/vo/QuestionImportVO.java @@ -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 errors = new ArrayList<>(); + private List errors = new ArrayList<>(); - public PaperImportVO(Integer successCount, List errors) { + public QuestionImportVO(Integer successCount, List errors) { this.successCount = successCount; this.errors = errors; } diff --git a/safety-cedu-service/src/main/java/org/qinan/cedu/service/PaperService.java b/safety-cedu-service/src/main/java/org/qinan/cedu/service/PaperService.java index 9b00c76f..a9f0f56f 100644 --- a/safety-cedu-service/src/main/java/org/qinan/cedu/service/PaperService.java +++ b/safety-cedu-service/src/main/java/org/qinan/cedu/service/PaperService.java @@ -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 { * @param importDTO 试卷信息+试题Excel文件 * @return 导入结果(成功条数+异常明细) */ - PaperImportVO importQuestions(PaperImportDTO importDTO); + QuestionImportVO importQuestions(PaperImportDTO importDTO); /** * importQuestionsTemplate diff --git a/safety-cedu-service/src/main/java/org/qinan/cedu/service/QuestionService.java b/safety-cedu-service/src/main/java/org/qinan/cedu/service/QuestionService.java index 569fba2f..fe3b2c31 100644 --- a/safety-cedu-service/src/main/java/org/qinan/cedu/service/QuestionService.java +++ b/safety-cedu-service/src/main/java/org/qinan/cedu/service/QuestionService.java @@ -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 { * @param dto dto */ void addQuestion(QuestionAddDTO dto); + + /** + * 导入试题 + * + * @param questionImportDTO questionImportDTO + * @return QuestionImportVO + */ + QuestionImportVO importQuestions(QuestionImportDTO questionImportDTO); } diff --git a/safety-cedu-service/src/main/java/org/qinan/cedu/service/impl/PaperServiceImpl.java b/safety-cedu-service/src/main/java/org/qinan/cedu/service/impl/PaperServiceImpl.java index abcec674..f62cf2a0 100644 --- a/safety-cedu-service/src/main/java/org/qinan/cedu/service/impl/PaperServiceImpl.java +++ b/safety-cedu-service/src/main/java/org/qinan/cedu/service/impl/PaperServiceImpl.java @@ -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 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 implemen rels.add(rel); } Db.saveBatch(rels); - return new PaperImportVO(questions.size(), parseResult.getErrors()); + return new QuestionImportVO(questions.size(), parseResult.getErrors()); } @Override diff --git a/safety-cedu-service/src/main/java/org/qinan/cedu/service/impl/QuestionServiceImpl.java b/safety-cedu-service/src/main/java/org/qinan/cedu/service/impl/QuestionServiceImpl.java index 2a403d71..fa699bb9 100644 --- a/safety-cedu-service/src/main/java/org/qinan/cedu/service/impl/QuestionServiceImpl.java +++ b/safety-cedu-service/src/main/java/org/qinan/cedu/service/impl/QuestionServiceImpl.java @@ -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 private final QuestionOptionMapper questionOptionMapper; private final QuestionConvertor questionConvertor; + private final QuestionExcelImporter questionExcelImporter; @Override public IPage pagePaperQuestions(PaperQuestionPageQueryDTO query) { @@ -274,6 +273,23 @@ public class QuestionServiceImpl extends ServiceImpl 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、统一填充时间后批量插入) * diff --git a/safety-cedu-service/src/main/java/org/qinan/cedu/service/support/QuestionExcelImporter.java b/safety-cedu-service/src/main/java/org/qinan/cedu/service/support/QuestionExcelImporter.java index 1c0edcc3..3edf963e 100644 --- a/safety-cedu-service/src/main/java/org/qinan/cedu/service/support/QuestionExcelImporter.java +++ b/safety-cedu-service/src/main/java/org/qinan/cedu/service/support/QuestionExcelImporter.java @@ -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,54 +72,58 @@ 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; /** * 解析上传的试题Excel,返回校验通过的试题(含选项,已预置雪花id)和异常明细 * - * @param file 上传的试题Excel文件 + * @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 sheetNames = readSheetNames(bytes); - List errors = new ArrayList<>(); + List errors = new ArrayList<>(); List singleRows = new ArrayList<>(); List multipleRows = new ArrayList<>(); List 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 coursewareManagementIdByName = loadCoursewareIdByName(singleRows, multipleRows, judgeRows); + Map 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; } @@ -185,20 +190,23 @@ public class QuestionExcelImporter { /** * 批量查询关联课件名称对应的id(名称 -> id) * - * @param singleRows 单选题行数据 - * @param multipleRows 多选题行数据 - * @param judgeRows 判断题行数据 + * @param singleRows 单选题行数据 + * @param multipleRows 多选题行数据 + * @param judgeRows 判断题行数据 + * @param coursewareManagementId coursewareManagementId * @return 课件名称到课件id的映射 */ - private Map loadCoursewareIdByName(List singleRows, - List multipleRows, - List judgeRows) { + private Map loadCoursewareIdByName(List singleRows + , List multipleRows, List judgeRows, Long coursewareManagementId) { Set 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()) { - return Collections.emptyMap(); + if (coursewareManagementId == null) { + return Collections.emptyMap(); + } + return Collections.singletonMap(DEFAULT_IMPORT_COURSEWARE_NAME, coursewareManagementId); } List coursewares = coursewareManagementMapper.selectList( new LambdaQueryWrapper() @@ -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 rows, String sheetName, QuestionTypeEnum questionType, - Map coursewareManagementIdByName, ParseResult parseResult) { - List errors = parseResult.getErrors(); + Map coursewareManagementIdByName, ParseResult parseResult, Long formCoursewareManagementId) { + List 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> 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 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 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 rows, String sheetName, - Map coursewareManagementIdByName, ParseResult parseResult) { - List errors = parseResult.getErrors(); + Map coursewareManagementIdByName, ParseResult parseResult, Long formCoursewareManagementId) { + List 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> 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 errors; + private final List errors; /** * 全参构造 @@ -526,7 +545,7 @@ public class QuestionExcelImporter { * @param options 校验通过的试题选项列表 * @param errors 异常明细列表 */ - public ParseResult(List questions, List options, List errors) { + public ParseResult(List questions, List options, List errors) { this.questions = questions; this.options = options; this.questionNumByQuestionId = new HashMap<>(); @@ -548,7 +567,7 @@ public class QuestionExcelImporter { * * @param errors 异常明细列表 */ - public ParseResult(List errors) { + public ParseResult(List errors) { this.questions = new ArrayList<>(64); this.options = new ArrayList<>(256); this.questionNumByQuestionId = new HashMap<>();