diff --git a/web/filesystem/template/批量题库导入模板.xlsx b/web/filesystem/template/批量题库导入模板.xlsx index 087f2fbb..ea8ff70c 100644 Binary files a/web/filesystem/template/批量题库导入模板.xlsx and b/web/filesystem/template/批量题库导入模板.xlsx differ diff --git a/web/src/main/java/com/ibeetl/jlw/service/TeacherOpenCourseMergeResourcesQuestionService.java b/web/src/main/java/com/ibeetl/jlw/service/TeacherOpenCourseMergeResourcesQuestionService.java index bd91f522..9fccf53b 100644 --- a/web/src/main/java/com/ibeetl/jlw/service/TeacherOpenCourseMergeResourcesQuestionService.java +++ b/web/src/main/java/com/ibeetl/jlw/service/TeacherOpenCourseMergeResourcesQuestionService.java @@ -10,6 +10,7 @@ import cn.hutool.core.util.NumberUtil; import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.StrUtil; import cn.jlw.util.ToolUtils; +import cn.jlw.util.excel.ExcelFailRecord; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import com.ibeetl.admin.core.entity.CoreUser; @@ -26,9 +27,7 @@ import com.ibeetl.jlw.entity.*; import com.ibeetl.jlw.entity.dto.QuestionSettingDTO; import com.ibeetl.jlw.entity.vo.QuestionTypeCountVO; import com.ibeetl.jlw.entity.vo.ResourcesCourseInfoAuthDetailsVO; -import com.ibeetl.jlw.enums.CopyFromEnum; -import com.ibeetl.jlw.enums.GlobalUpStatusEnum; -import com.ibeetl.jlw.enums.ResourcesQuestionTypeEnum; +import com.ibeetl.jlw.enums.*; import com.ibeetl.jlw.web.query.*; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; @@ -104,7 +103,7 @@ public class TeacherOpenCourseMergeResourcesQuestionService extends CoreBaseServ return ret; } - public PageQuery queryByConditionQuery(PageQuery query) { + public PageQuery queryByConditionQuery(PageQuery query) { PageQuery ret = teacherOpenCourseMergeResourcesQuestionDao.queryByConditionQuery(query); queryListAfter(ret.getList()); return ret; @@ -210,6 +209,310 @@ public class TeacherOpenCourseMergeResourcesQuestionService extends CoreBaseServ return JsonResult.failMessage("添加失败"); } + + /** + * 教师端导入实体 + * @param fileEntity + * @param coreUser + * @return + */ + @Transactional + public JsonResult importTemplate(FileEntity fileEntity, CoreUser coreUser) { + if (null != fileEntity) { + File file = new File(fileEntity.getAbsoluteUrl()); + if (file.exists() && file.isFile() && file.canRead() && ToolUtils.findInSet("xls,xlsx", fileEntity.getFormat())) { + Workbook wb = null; + InputStream is = null; + try { + is = Files.newInputStream(Paths.get(fileEntity.getAbsoluteUrl())); + if ("xls".equals(fileEntity.getFormat())) { + wb = new HSSFWorkbook(is); + } else if ("xlsx".equals(fileEntity.getFormat())) { + wb = new XSSFWorkbook(is); + } + } catch (IOException e) { + e.printStackTrace(); + } + try { + if (null != is) { + is.close(); + } + } catch (Exception e) { + e.printStackTrace(); + } + + if (wb != null) { + List errMsg = new ArrayList<>(); + + //获取Sheet1 + Sheet sheet = wb.getSheet("Sheet1"); + //获取最大行数 + int rowNum = sheet.getPhysicalNumberOfRows(); + //获取第一行 + Row firstRow = sheet.getRow(0); + //获取最大列数 + int colNum = firstRow.getPhysicalNumberOfCells(); + + String[] columns = {"归属课程", "归属章节", "题型", "分值", "题干", "选项A", "选项B", "选项C", "选项D", "选项E", "答案 单选是一个 多选是多个 判断是对错", "解析"}; + + Map map = new HashMap<>();//获取需要的表头的列 + + //从第一列找到需要的表头 + for (int i = 0; i < colNum; i++) { + String cellData = getCellFormatValue(firstRow.getCell(i)); + for (int j = 0; j < columns.length; j++) { + if (columns[j].equals(cellData)) { + map.put(columns[j], i); + } + } + } + + //验证所需要的表头是否全 + Integer flag = 0; + for (int i = 0; i < columns.length; i++) { + if (null != map.get(columns[i])) { + flag++; + } + } + if (flag != columns.length) { + return JsonResult.failMessage("导入失败,表格表头应包含 \"归属课程\",\"归属章节\",\"题型\",\"分值\",\"题干\",\"选项A\",\"选项B\",\"选项C\",\"选项D\",\"选项E\",\"答案 单选是一个 多选是多个 判断是对错\",\"解析\""); + } + + int count = 0; + + Date now = new Date(); + + for (int i = 1; i < rowNum; i++) { + Row row = sheet.getRow(i); + if (null == row) { + ExcelFailRecord excelFailRecord = new ExcelFailRecord(); + excelFailRecord.setFailMessage("第" + (i + 1) + "数据为空"); + excelFailRecord.setRow(i); + errMsg.add(excelFailRecord); + continue; + } + String courseInfoName = getCellFormatValue(row.getCell(map.get(columns[0]))); + String chapterName = getCellFormatValue(row.getCell(map.get(columns[1]))); + String questionType = getCellFormatValue(row.getCell(map.get(columns[2]))); + + if (StringUtils.isNotBlank(questionType)) { + questionType = questionType.replace("题", "").trim(); + } + + String questionScore = getCellFormatValue(row.getCell(map.get(columns[3]))); + String questionStem = getCellFormatValue(row.getCell(map.get(columns[4]))); + + String questionOptionA = getCellFormatValue(row.getCell(map.get(columns[5]))); + String questionOptionB = getCellFormatValue(row.getCell(map.get(columns[6]))); + String questionOptionC = getCellFormatValue(row.getCell(map.get(columns[7]))); + String questionOptionD = getCellFormatValue(row.getCell(map.get(columns[8]))); + String questionOptionE = getCellFormatValue(row.getCell(map.get(columns[9]))); + + String questionAnswer = getCellFormatValue(row.getCell(map.get(columns[10]))); + questionAnswer = resourcesQuestionService.answerFormat(questionType, questionAnswer);//格式化 + String questionAnalysis = getCellFormatValue(row.getCell(map.get(columns[11]))); + + if (StringUtils.isBlank(questionScore)) { + questionScore = "1";//默认一分 + } + + + String m = ""; + if (StringUtils.isNotBlank(questionAnswer)) { + m = resourcesQuestionService.judge(questionType, questionOptionA, questionOptionB, questionOptionC, questionOptionD, questionOptionE, questionAnswer); + } + if (StringUtils.isBlank(courseInfoName)) { + ExcelFailRecord excelFailRecord = new ExcelFailRecord(); + excelFailRecord.setFailMessage("第" + ToolUtils.numberToLetter(map.get(columns[0]) + 1) + "列,第" + (i + 1) + "行课程为空"); + excelFailRecord.setColumn(map.get(columns[0]) + 1); + excelFailRecord.setRow((i + 1)); + errMsg.add(excelFailRecord); + + } else if (StringUtils.isBlank(chapterName)) { + ExcelFailRecord excelFailRecord = new ExcelFailRecord(); + excelFailRecord.setFailMessage("第" + ToolUtils.numberToLetter(map.get(columns[1]) + 1) + "列,第" + (i + 1) + "行归属章节为空"); + excelFailRecord.setColumn(map.get(columns[1]) + 1); + excelFailRecord.setRow((i + 1)); + errMsg.add(excelFailRecord); + } else if (StringUtils.isBlank(questionType)) { + ExcelFailRecord excelFailRecord = new ExcelFailRecord(); + excelFailRecord.setFailMessage("第" + ToolUtils.numberToLetter(map.get(columns[2]) + 1) + "列,第" + (i + 1) + "行题型为空"); + excelFailRecord.setColumn(map.get(columns[2]) + 1); + excelFailRecord.setRow((i + 1)); + errMsg.add(excelFailRecord); + + } else if (!ToolUtils.findInSet("单选,多选,判断", questionType)) { + ExcelFailRecord excelFailRecord = new ExcelFailRecord(); + excelFailRecord.setFailMessage("第" + ToolUtils.numberToLetter(map.get(columns[2]) + 1) + "列,第" + (i + 1) + "行题型异常"); + excelFailRecord.setColumn(map.get(columns[2]) + 1); + excelFailRecord.setRow((i + 1)); + errMsg.add(excelFailRecord); + + } else if (StringUtils.isBlank(questionScore)) { + ExcelFailRecord excelFailRecord = new ExcelFailRecord(); + excelFailRecord.setFailMessage("第" + ToolUtils.numberToLetter(map.get(columns[3]) + 1) + "列,第" + (i + 1) + "行分值为空"); + excelFailRecord.setColumn(map.get(columns[3]) + 1); + excelFailRecord.setRow((i + 1)); + errMsg.add(excelFailRecord); + + } else if (StringUtils.isBlank(questionStem)) { + ExcelFailRecord excelFailRecord = new ExcelFailRecord(); + excelFailRecord.setFailMessage("第" + ToolUtils.numberToLetter(map.get(columns[4]) + 1) + "列,第" + (i + 1) + "行题干为空"); + excelFailRecord.setColumn(map.get(columns[4]) + 1); + excelFailRecord.setRow((i + 1)); + errMsg.add(excelFailRecord); + + } else if (StringUtils.isBlank(questionAnswer)) { + ExcelFailRecord excelFailRecord = new ExcelFailRecord(); + excelFailRecord.setFailMessage("第" + ToolUtils.numberToLetter(map.get(columns[10]) + 1) + "列,第" + (i + 1) + "行答案为空"); + excelFailRecord.setColumn(map.get(columns[10]) + 1); + excelFailRecord.setRow((i + 1)); + errMsg.add(excelFailRecord); + + } else if (StringUtils.isNotBlank(m)) { + ExcelFailRecord excelFailRecord = new ExcelFailRecord(); + excelFailRecord.setFailMessage("第" + (i + 1) + "行" + m); + excelFailRecord.setRow((i + 1)); + errMsg.add(excelFailRecord); + + } else if (!NumberUtil.isNumber(questionScore)) { + ExcelFailRecord excelFailRecord = new ExcelFailRecord(); + excelFailRecord.setFailMessage("第" + ToolUtils.numberToLetter(map.get(columns[3]) + 1) + "列,第" + (i + 1) + "行分值数值格式错误"); + excelFailRecord.setColumn(map.get(columns[3]) + 1); + excelFailRecord.setRow((i + 1)); + errMsg.add(excelFailRecord); + + } else { + questionAnswer = questionAnswer.trim(); + courseInfoName = courseInfoName.trim(); + chapterName = chapterName.trim(); + questionType = questionType.trim(); + questionScore = questionScore.trim(); + questionStem = questionStem.trim(); + questionAnswer = questionAnswer.trim(); + + //去掉最后一个逗号 + if (StringUtils.isNotBlank(questionAnswer)) { + if (questionAnswer.lastIndexOf(",") == questionAnswer.length() - 1) { + questionAnswer = questionAnswer.substring(0, questionAnswer.length() - 1); + } + } + + //查课程 + TeacherOpenCourseQuery course = new TeacherOpenCourseQuery(); + course.setTeacherOpenCourseStatus(1); + course.setOrgId(course.getOrgId()); + course.setUserId(course.getUserId()); + course.setTeacherOpenCourseTitle(courseInfoName); + //调现有的接口去查 + List teacherOpenCourseList = teacherOpenCourseDao.getValuesByQuery(course); + + if (CollectionUtils.isEmpty(teacherOpenCourseList)) { + ExcelFailRecord excelFailRecord = new ExcelFailRecord(); + excelFailRecord.setFailMessage("第" + ToolUtils.numberToLetter(map.get(columns[0]) + 1) + "列,第" + (i + 1) + "课程不存在"); + excelFailRecord.setColumn(map.get(columns[0]) + 1); + excelFailRecord.setRow((i + 1)); + errMsg.add(excelFailRecord); + } else { + TeacherOpenCourseMergeCourseInfoQuery teacherOpenCourseMergeCourseInfo = new TeacherOpenCourseMergeCourseInfoQuery(); + teacherOpenCourseMergeCourseInfo.setTeacherOpenCourseId(teacherOpenCourseList.get(0).getTeacherOpenCourseId()); + teacherOpenCourseMergeCourseInfo.setCourseInfoStatus(1); + teacherOpenCourseMergeCourseInfo.setCourseInfoType(1); + List courseInfoList = teacherOpenCourseMergeCourseInfoDao.getValuesByQuery(teacherOpenCourseMergeCourseInfo); + + if (CollectionUtils.isEmpty(courseInfoList)) { + ExcelFailRecord excelFailRecord = new ExcelFailRecord(); + excelFailRecord.setFailMessage("第" + ToolUtils.numberToLetter(map.get(columns[0]) + 1) + "列,第" + (i + 1) + "课程不存在"); + excelFailRecord.setColumn(map.get(columns[0]) + 1); + excelFailRecord.setRow((i + 1)); + errMsg.add(excelFailRecord); + } else { + + TeacherOpenCourseMergeCourseInfoQuery chapterCourseInfoQuery = new TeacherOpenCourseMergeCourseInfoQuery(); + chapterCourseInfoQuery.setTeacherOpenCourseId(teacherOpenCourseList.get(0).getTeacherOpenCourseId()); + chapterCourseInfoQuery.setCourseInfoStatus(1); + chapterCourseInfoQuery.setCourseInfoType(2); + chapterCourseInfoQuery.setCourseInfoName(chapterName); + List chapterCourseInfoList = teacherOpenCourseMergeCourseInfoDao.getValuesByQuery(chapterCourseInfoQuery); + if (CollectionUtils.isEmpty(chapterCourseInfoList)){ + ExcelFailRecord excelFailRecord = new ExcelFailRecord(); + excelFailRecord.setFailMessage("第" + ToolUtils.numberToLetter(map.get(columns[0]) + 1) + "列,第" + (i + 1) + "章节不存在"); + excelFailRecord.setColumn(map.get(columns[0]) + 1); + excelFailRecord.setRow((i + 1)); + errMsg.add(excelFailRecord); + }else { + TeacherOpenCourseMergeCourseInfo chapterCourseInfo = chapterCourseInfoList.get(0); + TeacherOpenCourseMergeResourcesQuestion rq = new TeacherOpenCourseMergeResourcesQuestion(); + rq.setQuestionStem(questionStem); + rq.setTeacherOpenCourseMergeCourseInfoId(chapterCourseInfo.getTeacherOpenCourseMergeCourseInfoId()); + rq.setTeacherOpenCourseId(chapterCourseInfo.getTeacherOpenCourseId()); + List collect = teacherOpenCourseMergeResourcesQuestionDao.template(rq).stream().filter(item -> !Objects.equals(item.getQuestionStatus(), 0)).collect(toList()); + if (collect.size() > 0) { + ExcelFailRecord excelFailRecord = new ExcelFailRecord(); + excelFailRecord.setFailMessage("第" + (i + 1) + "行题目重复"); + excelFailRecord.setRow((i + 1)); + errMsg.add(excelFailRecord); + continue; + } + + + //插入题目 + TeacherOpenCourseMergeResourcesQuestion pojo = new TeacherOpenCourseMergeResourcesQuestion(); + pojo.setTeacherOpenCourseId(chapterCourseInfo.getTeacherOpenCourseId()); + pojo.setTeacherOpenCourseMergeCourseInfoId(chapterCourseInfo.getTeacherOpenCourseMergeCourseInfoId()); + pojo.setQuestionType("单选".equals(questionType) ? 1 : "多选".equals(questionType) ? 2 : 3); + pojo.setQuestionScore(StringUtils.isNotBlank(questionScore) ? new BigDecimal(questionScore) : BigDecimal.ONE); + pojo.setQuestionStem(questionStem); + if (((Integer) 3).equals(pojo.getQuestionType())) { + pojo.setQuestionAnswer(questionAnswer); + } else { + pojo.setQuestionOptionA(questionOptionA); + pojo.setQuestionOptionB(questionOptionB); + pojo.setQuestionOptionC(questionOptionC); + pojo.setQuestionOptionD(questionOptionD); + pojo.setQuestionOptionE(questionOptionE); + pojo.setQuestionAnswer(questionAnswer); + } + pojo.setQuestionAnalysis(questionAnalysis); + // 默认导入上架状态 + pojo.setQuestionStatus(1); + pojo.setFromType(CopyFromEnum.FROM_OPEN_COURSE); + pojo.setUserId(coreUser.getId()); + pojo.setOrgId(coreUser.getOrgId()); + pojo.setSourceFromId(-1L); + insert(pojo); + + forceInsertChapterTestByMergeResourcesQuestion(pojo); + count ++; + } + } + } + } + } + + if (count > 0) { + JsonResult jsonResult = new JsonResult(); + jsonResult.setCode(JsonReturnCode.SUCCESS.getCode()); + jsonResult.setData(errMsg); + jsonResult.setMsg("导入成功,共导入" + count + "条。"); + return jsonResult; + } else { + JsonResult jsonResult = new JsonResult(); + jsonResult.setCode(JsonReturnCode.FAIL.getCode()); + jsonResult.setData(errMsg); + jsonResult.setMsg("导入全部失败,请查看下面的失败列表"); + return jsonResult; + } + } + return JsonResult.failMessage("导入失败"); + } else { + return JsonResult.failMessage("上传失败"); + } + } else { + return JsonResult.failMessage("上传失败"); + } + } + /** * 不会删除章节练习中的快照题目信息的方式,插入到章节练习库中。 * diff --git a/web/src/main/java/com/ibeetl/jlw/web/TeacherOpenCourseMergeResourcesQuestionController.java b/web/src/main/java/com/ibeetl/jlw/web/TeacherOpenCourseMergeResourcesQuestionController.java index 405fd072..c55509f5 100644 --- a/web/src/main/java/com/ibeetl/jlw/web/TeacherOpenCourseMergeResourcesQuestionController.java +++ b/web/src/main/java/com/ibeetl/jlw/web/TeacherOpenCourseMergeResourcesQuestionController.java @@ -510,7 +510,8 @@ public class TeacherOpenCourseMergeResourcesQuestionController extends BaseContr response.setContentType("application/octet-stream"); //这后面可以设置导出Excel的名称,此例中名为template.xls - response.setHeader("Content-disposition", "attachment;filename=resourcesQuestionTemplate(" + TimeTool.getNowTime("YMD") + ").xlsx"); + String excelName = new String(("批量题库导入模板").getBytes("GB2312"), "ISO8859-1") + ".xlsx"; + response.setHeader("Content-disposition", "attachment;filename=" +excelName); //刷新缓冲 response.flushBuffer(); @@ -545,31 +546,33 @@ public class TeacherOpenCourseMergeResourcesQuestionController extends BaseContr */ @SneakyThrows @PostMapping(API + "/importBatchTemplate.do") - public JsonResult importBatchTemplate(@NotNull(message = "导入的文件不能为空!") MultipartFile file, TeacherOpenCourseQuery teacherOpenCourseQuery, @SCoreUser CoreUser coreUser) { - - try { - Assert.isNull(getStudent(), "学生无法访问该接口"); - - // 输出 Excel - MyValidateExcelCellDataListener listener = new MyValidateExcelCellDataListener<>(); - - ExcelUtil.readExcelNotContainHeader(file, TeacherOpenCourseMergeResourcesQuestionImport.class, listener); - // 判断错误的结果集 - Assert.isTrue(CollectionUtil.isEmpty(listener.getFailMessage()), JSONUtil.toJsonStr(listener.getFailMessage())); - // 类型转换 - List options = listener.getData().stream() - .map(TeacherOpenCourseMergeResourcesQuestionImport::pojo).collect(Collectors.toList()); - - // 只复制用户ID和组织ID。 当前导入到开课题库的用户,基本上是学生管理员,或者教师,所以直接获取当前的登录人userId和orgId就好 - BeanUtil.beanPropertyCopyToList(coreUser, options, MapUtil.of("id", "userId"), "userId", "orgId"); - - // 循环插入吧,这样支持插入到测试章节题库中 - options.forEach(teacherOpenCourseMergeResourcesQuestionService::addByObject); - } - catch (IllegalArgumentException exception) { - return JsonResult.failMessage(exception.getMessage()).setCode(DIY_ERROR.getCode()); - } - - return JsonResult.successMessage("导入成功!"); + public JsonResult importBatchTemplate(@NotNull(message = "导入的文件不能为空!") @RFile FileEntity fileEntity, @SCoreUser CoreUser coreUser) { + +// try { +// Assert.isNull(getStudent(), "学生无法访问该接口"); +// +// // 输出 Excel +// MyValidateExcelCellDataListener listener = new MyValidateExcelCellDataListener<>(); +// +// ExcelUtil.readExcelNotContainHeader(file, TeacherOpenCourseMergeResourcesQuestionImport.class, listener); +// // 判断错误的结果集 +// Assert.isTrue(CollectionUtil.isEmpty(listener.getFailMessage()), JSONUtil.toJsonStr(listener.getFailMessage())); +// // 类型转换 +// List options = listener.getData().stream() +// .map(TeacherOpenCourseMergeResourcesQuestionImport::pojo).collect(Collectors.toList()); +// +// // 只复制用户ID和组织ID。 当前导入到开课题库的用户,基本上是学生管理员,或者教师,所以直接获取当前的登录人userId和orgId就好 +// BeanUtil.beanPropertyCopyToList(coreUser, options, MapUtil.of("id", "userId"), "userId", "orgId"); +// +// // 循环插入吧,这样支持插入到测试章节题库中 +// options.forEach(teacherOpenCourseMergeResourcesQuestionService::addByObject); +// } +// catch (IllegalArgumentException exception) { +// return JsonResult.failMessage(exception.getMessage()).setCode(DIY_ERROR.getCode()); +// } +// +// return JsonResult.successMessage("导入成功!"); + Assert.isNull(getStudent(), "学生无法访问该接口"); + return teacherOpenCourseMergeResourcesQuestionService.importTemplate(fileEntity,coreUser); } }