package com.mindskip.xzs.controller.admin; import com.alibaba.excel.EasyExcel; import com.alibaba.fastjson.JSON; import com.github.pagehelper.PageInfo; import com.mindskip.xzs.base.BaseApiController; import com.mindskip.xzs.base.RestResponse; import com.mindskip.xzs.base.SystemCode; import com.mindskip.xzs.domain.Question; import com.mindskip.xzs.domain.Subject; import com.mindskip.xzs.domain.TextContent; import com.mindskip.xzs.domain.enums.QuestionSourceEnum; import com.mindskip.xzs.domain.enums.QuestionTypeEnum; import com.mindskip.xzs.domain.question.QuestionItemObject; import com.mindskip.xzs.domain.question.QuestionObject; import com.mindskip.xzs.domain.vo.DeptQuestionVO; import com.mindskip.xzs.repository.DepartmentMapper; import com.mindskip.xzs.repository.DeptQuestionMapper; import com.mindskip.xzs.repository.SubjectMapper; import com.mindskip.xzs.service.QuestionService; import com.mindskip.xzs.service.QuestionSubjectService; import com.mindskip.xzs.service.TextContentService; import com.mindskip.xzs.utility.*; import com.mindskip.xzs.utility.convert.QuestionClassConvert; import com.mindskip.xzs.utility.excel.ExcelUtils; import com.mindskip.xzs.viewmodel.admin.education.SubjectPageRequestVM; import com.mindskip.xzs.viewmodel.admin.question.*; import com.mindskip.xzs.vo.QuestionExportData; import com.mindskip.xzs.vo.QuestionExportVO; import com.mindskip.xzs.vo.QuestionImportVO; import org.apache.commons.lang3.StringUtils; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; import javax.servlet.http.HttpServletResponse; import javax.validation.Valid; import java.io.IOException; import java.net.URLEncoder; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Objects; import java.util.stream.Collectors; @RestController("AdminQuestionController") @RequestMapping(value = "/api/admin/question") public class QuestionController extends BaseApiController { private final QuestionService questionService; private final TextContentService textContentService; private final SubjectMapper subjectMapper; private final DepartmentMapper departmentMapper; private final QuestionSubjectService questionSubjectService; private final DeptQuestionMapper deptQuestionMapper; private static final String SPLIT = ","; public QuestionController(QuestionService questionService, TextContentService textContentService, SubjectMapper subjectMapper, DepartmentMapper departmentMapper, QuestionSubjectService questionSubjectService, DeptQuestionMapper deptQuestionMapper) { this.questionService = questionService; this.textContentService = textContentService; this.subjectMapper = subjectMapper; this.departmentMapper = departmentMapper; this.questionSubjectService = questionSubjectService; this.deptQuestionMapper = deptQuestionMapper; } @RequestMapping(value = "/page", method = RequestMethod.POST) public RestResponse> pageList(@RequestBody @Valid QuestionPageRequestVM model) { PageInfo pageInfo = questionService.page(model); PageInfo page = PageInfoHelper.copyMap(pageInfo, q -> { QuestionResponseVM vm = modelMapper.map(q, QuestionResponseVM.class); vm.setCreateTime(DateTimeUtil.dateFormat(q.getCreateTime())); vm.setScore(ExamUtil.scoreToVM(q.getScore())); TextContent textContent = textContentService.selectById(q.getInfoTextContentId()); QuestionObject questionObject = JsonUtil.toJsonObject(textContent.getContent(), QuestionObject.class); String clearHtml = HtmlUtil.clear(questionObject.getTitleContent()); vm.setShortTitle(clearHtml); vm.setQuestionSubjects(questionSubjectService.getQuestion(vm.getId()).stream().map(e -> { SubjectPageRequestVM subjectPageRequestVM = new SubjectPageRequestVM(); subjectPageRequestVM.setId(e.getSubjectId()); e.setSubName(subjectMapper.page(subjectPageRequestVM).get(0).getName()); return e; }).collect(Collectors.toList())); // 查询题目所属部门 String deptNames = deptQuestionMapper.deptByQuestionId(q.getId()).stream().map(DeptQuestionVO::getDeptName).collect(Collectors.joining("、")); vm.setDeptNames(deptNames); return vm; }); return RestResponse.ok(page); } @RequestMapping(value = "/edit", method = RequestMethod.POST) public RestResponse edit(@RequestBody @Valid QuestionEditRequestVM model) { RestResponse validQuestionEditRequestResult = validQuestionEditRequestVM(model); if (validQuestionEditRequestResult.getCode() != SystemCode.OK.getCode()) { return validQuestionEditRequestResult; } if (null == model.getId()) { questionService.insertFullQuestion(model, getCurrentUser().getId()); } else { questionService.updateFullQuestion(model); } return RestResponse.ok(); } @RequestMapping(value = "/select/{id}", method = RequestMethod.POST) public RestResponse select(@PathVariable Integer id) { return RestResponse.ok(questionService.getQuestionEditRequestVM(id)); } @RequestMapping(value = "/delete/{id}", method = RequestMethod.POST) public RestResponse delete(@PathVariable Integer id) { return RestResponse.ok(questionService.remove(id)); } private RestResponse validQuestionEditRequestVM(QuestionEditRequestVM model) { int qType = model.getQuestionType().intValue(); boolean requireCorrect = qType == QuestionTypeEnum.SingleChoice.getCode() || qType == QuestionTypeEnum.TrueFalse.getCode(); if (requireCorrect) { if (StringUtils.isBlank(model.getCorrect())) { String errorMsg = ErrorUtil.parameterErrorFormat("correct", "不能为空"); return new RestResponse<>(SystemCode.ParameterValidError.getCode(), errorMsg); } } if (qType == QuestionTypeEnum.GapFilling.getCode()) { Integer fillSumScore = model.getItems().stream().mapToInt(d -> ExamUtil.scoreFromVM(d.getScore())).sum(); Integer questionScore = ExamUtil.scoreFromVM(model.getScore()); if (!fillSumScore.equals(questionScore)) { String errorMsg = ErrorUtil.parameterErrorFormat("score", "空分数和与题目总分不相等"); return new RestResponse<>(SystemCode.ParameterValidError.getCode(), errorMsg); } } return RestResponse.ok(); } /** * 下载题目导入模板 * * @param response * @throws IOException */ @GetMapping("/download/question/import/temp") public void getImportTemp(HttpServletResponse response) throws IOException { String fileName = URLEncoder.encode("题目导入模板", "UTF-8").replaceAll("\\+", "%20"); response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx"); // 构建模板样例数据 List data = new ArrayList<>(4); EasyExcel.write(response.getOutputStream(), QuestionExportData.class) .sheet("模板") .doWrite(data); } // @PostMapping("/question/export") // public void exportQuestion(@RequestBody QuestionExportVO query, HttpServletResponse response) throws IOException { // // 查询导出数据 // List exportData = questionService.export(query); // // 构建数据 // List exportList = new ArrayList<>(exportData.size() * 4); // // 行合并规则 // List mergeRowList = new ArrayList<>(exportData.size()); // int j = 2; // for (QuestionImportVO data : exportData) { // QuestionObject questionContent = JSON.parseObject(data.getQuestionContent(), QuestionObject.class); // // RowItem rowItem = new RowItem(); // rowItem.setStart(j); // int end = j + questionContent.getQuestionItemObjects().size() - 1; // rowItem.setEnd(end); // mergeRowList.add(rowItem); // j = end + 1; // int i = 0; // for (QuestionItemObject option : questionContent.getQuestionItemObjects()) { // if (i == 0) { // QuestionImportVO master = new QuestionImportVO(); // BeanUtils.copyProperties(data, master); // if (org.springframework.util.StringUtils.hasText(data.getQuestionType())) { // master.setQuestionType(QuestionTypeEnum.fromCode(Integer.valueOf(data.getQuestionType())).getName()); // } // master.setOptionName(option.getPrefix()); // master.setOptionValue(option.getContent()); // master.setTitle(questionContent.getTitleContent()); // master.setAnalyze(questionContent.getAnalyze()); // master.setSubjectName(data.getSubjectList().stream().collect(Collectors.joining("、"))); // master.setCorrect(data.getCorrect().replaceAll(",", "、")); // BigDecimal score = BigDecimal.valueOf(master.getScore()); // master.setScore(score.divide(BigDecimal.TEN).intValue()); // exportList.add(master); // } else { // QuestionImportVO optionItem = new QuestionImportVO(); // optionItem.setOptionName(option.getPrefix()); // optionItem.setOptionValue(option.getContent()); // exportList.add(optionItem); // } // i++; // } // } // response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"); // response.setCharacterEncoding("utf-8"); // // 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系 // String fileName = URLEncoder.encode("题目导出数据", "UTF-8").replaceAll("\\+", "%20"); // response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx"); // // // 查出所有的课目(excel下拉数据) // List subjects = subjectMapper.allSubject(new ArrayList<>(), Boolean.TRUE); // List subjectNameList = subjects.stream().map(Subject::getName).collect(Collectors.toList()); // EasyExcel.write(response.getOutputStream(), QuestionImportVO.class) // .sheet("题目导出数据") // .registerWriteHandler(new SelectExcel(subjectNameList)) // .registerWriteHandler(new DynamicMergeCellStrategy(mergeRowList, Arrays.asList(0, 1, 2, 5, 6, 7, 8))) // .doWrite(exportList); // } /** * 题目导入 * * easyexcel导入一对多,比如一个题目,四个选项。那么读取到的数据就有四条,第一条数据是齐全的。后面三条只有选项有值 * @param file * @throws IOException */ // @PostMapping("/question/import") // @Transactional(rollbackFor = Exception.class) // public RestResponse importQuestion(@RequestPart("file") MultipartFile file) throws IOException { // Consumer> consumer = (data) -> { // // 题目的课目信息 // List questionSubjectsList = new ArrayList<>(48); // for (int i = 0; i < data.size(); i++) { // // 题目实体 // Question question = new Question(); // // 读取的题目 // QuestionImportVO excelQuestion = data.get(i); // // // 如果是第一条完整数据,那么继续往后读取选项内容 // if (excelQuestion.master()) { // // 该题的选项 // List options = new ArrayList<>(4); // // 选项内容 // QuestionItemObject option = new QuestionItemObject(); // option.setPrefix(excelQuestion.getOptionName()); // option.setContent(excelQuestion.getOptionValue()); // options.add(option); // int next = 1; // // 继续往后读选项 // while (Boolean.TRUE) { // // 判断是否是最后一条 // if (next + i == data.size()) { // break; // } // QuestionImportVO nextQuestion = data.get(next + i); // if (nextQuestion.master()) { // break; // } // QuestionItemObject nextOption = new QuestionItemObject(); // nextOption.setPrefix(nextQuestion.getOptionName()); // nextOption.setContent(nextQuestion.getOptionValue()); // options.add(nextOption); // next++; // } // i += next; // // // 保存题目内容 // QuestionObject questionObject = new QuestionObject(); // questionObject.setQuestionItemObjects(options); // questionObject.setAnalyze(excelQuestion.getAnalyze()); // questionObject.setTitleContent(excelQuestion.getTitle()); // questionObject.setCorrect(excelQuestion.getCorrect()); // // TextContent textContent = new TextContent(); // textContent.setContent(JSON.toJSONString(questionObject)); // textContent.setCreateTime(new Date()); // textContentService.insert(textContent); // // // 保存题目信息 // // 设置题型 // question.setQuestionType(QuestionTypeEnum.get(excelQuestion.getQuestionType())); // // 答案(多选需要用,分割保存字符串到数据库) // String[] corrects = excelQuestion.getCorrect().split(SPLIT); // if (corrects.length > 1) { // question.setCorrect(Arrays.asList(corrects).stream().collect(Collectors.joining(","))); // } else { // question.setCorrect(excelQuestion.getCorrect()); // } // // // 难度 // question.setDifficult(excelQuestion.getDifficult()); // // 分数 // question.setScore(ExamUtil.scoreFromVM(String.valueOf(excelQuestion.getScore()))); // // 创建人 // question.setCreateUser(1); // question.setStatus(QuestionStatusEnum.OK.getCode()); // question.setCreateTime(new Date()); // question.setDeleted(Boolean.FALSE); // question.setInfoTextContentId(textContent.getId()); // questionService.insert(question); // // // // 查出所有的课目 // List subjects = subjectMapper.allSubject(new ArrayList<>(), Boolean.TRUE); // List subjectNames = Arrays.asList(excelQuestion.getSubjectName().split(SPLIT)); // List targetSubject = subjects.stream() // .filter(subject -> subjectNames.contains(subject.getName())) // .collect(Collectors.toList()); // if (CollectionUtils.isEmpty(targetSubject)) { // // todo 记录这个错误 // continue; // } // // 构建课目-题目信息 // questionSubjectsList = targetSubject.stream().map(subject -> { // QuestionSubject questionSubject = new QuestionSubject(); // questionSubject.setQuestionId(question.getId()); // questionSubject.setSubjectId(subject.getId()); // questionSubject.setDeleted(0); // return questionSubject; // }).collect(Collectors.toList()); // } // System.out.println(question); // } // // 批量保存题目-课目信息 // if (! CollectionUtils.isEmpty(questionSubjectsList)) { // questionSubjectService.saves(questionSubjectsList); // } // }; // EasyExcel.read(file.getInputStream(), QuestionImportVO.class, new CurrencyDataListener(consumer)).sheet("模板").doRead(); // return RestResponse.ok(); // } @PostMapping("/import") public RestResponse importQuestion(@RequestPart("file") MultipartFile file) throws Exception { List questionEditVOS = ExcelUtils.readMultipartFile(file, QuestionEditVO.class) .stream().map(e -> { e.setQuestionType(QuestionTypeEnum.get(e.getType())); // e.setSubjectId(subjectMapper.getName(e.getSbNames()).getId()); // e.setGradeLevel(departmentMapper.getName(e.getDepartment()).getId()); return e; }).collect(Collectors.toList()); List list = QuestionClassConvert.INSTANCE.QuestionEditVOListToQuestionEditRequestVMList(questionEditVOS); List questionEditItemVMS = new ArrayList<>(); QuestionEditItemVM questionEditItemVM = new QuestionEditItemVM(); //组装题目 for (QuestionEditRequestVM vm : list) { // 判断题干是否重复,重复不添加 Integer num = questionService.countQuestionByTitle(vm.getTitle()); if (num > 0) { continue; } questionEditItemVM.setPrefix("A"); questionEditItemVM.setContent(vm.getA()); questionEditItemVMS.add(questionEditItemVM); questionEditItemVM = new QuestionEditItemVM(); questionEditItemVM.setPrefix("B"); questionEditItemVM.setContent(vm.getB()); questionEditItemVMS.add(questionEditItemVM); if(!"".equals(vm.getC()) && vm.getC()!=null){ questionEditItemVM = new QuestionEditItemVM(); questionEditItemVM.setPrefix("C"); questionEditItemVM.setContent(vm.getC()); questionEditItemVMS.add(questionEditItemVM); } if(!"".equals(vm.getD()) && vm.getD()!=null){ questionEditItemVM = new QuestionEditItemVM(); questionEditItemVM.setPrefix("D"); questionEditItemVM.setContent(vm.getD()); questionEditItemVMS.add(questionEditItemVM); } vm.setItems(questionEditItemVMS); // 清空前后的逗号,以免后续作答判断为错误 String s = vm.getCorrect().replaceAll("^,+|,+$", ""); if (Objects.equals(s, "正确")) s = "A"; if (Objects.equals(s, "错误")) s = "B"; vm.setCorrect(s); List str = Arrays.asList(s.split(SPLIT)); List subjectList = subjectMapper.getNames(vm.getSbNames().split(SPLIT)); Integer[] arr =subjectList.stream() .map(Subject::getId).toArray(Integer[]::new); vm.setSubjectIds(arr); //多选 if (str.size() > 1) { vm.setCorrectArray(str); vm.setCorrect(null); } vm.setScore(QuestionSourceEnum.fromType(vm.getQuestionType()).toString()); vm.setDifficult(4); questionService.insertFullQuestion(vm, getCurrentUser().getId()); questionEditItemVMS.clear(); } return RestResponse.ok(); } @PostMapping("/question/export") public void exportQuestion(@RequestBody QuestionExportVO query, HttpServletResponse response) throws IOException { // 查询导出数据 List exportData = questionService.exportData(query); // 处理完善数据 exportData.stream().forEach(question -> { if (StringUtils.isNotBlank(question.getContent())) { QuestionObject questionContent = JSON.parseObject(question.getContent(), QuestionObject.class); // 设置选项 for (QuestionItemObject option : questionContent.getQuestionItemObjects()) { String optionContent = option.getContent(); if ("A".equals(option.getPrefix())) { question.setOptionA(optionContent); } else if ("B".equals(option.getPrefix())) { question.setOptionB(optionContent); } else if ("C".equals(option.getPrefix())) { question.setOptionC(optionContent); } else if ("D".equals(option.getPrefix())) { question.setOptionD(optionContent); } } // 设置题干、解析 question.setAnalyze(questionContent.getAnalyze()); question.setTitle(questionContent.getTitleContent()); // 设置课目 question.setSubject(question.getSubjectList().stream().collect(Collectors.joining(","))); // 设置题型 question.setQuestionType(QuestionTypeEnum.fromCode(Integer.valueOf(question.getQuestionType())).getName()); } }); response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"); response.setCharacterEncoding("utf-8"); // 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系 String fileName = URLEncoder.encode("题目导出数据", "UTF-8").replaceAll("\\+", "%20"); response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx"); // 查出所有的课目(excel下拉数据) EasyExcel.write(response.getOutputStream(), QuestionExportData.class) .sheet("题目导出数据") .doWrite(exportData); } }