| | |
| | | package com.mindskip.xzs.controller.admin; |
| | | |
| | | import com.alibaba.excel.EasyExcel; |
| | | import com.alibaba.excel.enums.CellExtraTypeEnum; |
| | | import com.alibaba.excel.metadata.data.HyperlinkData; |
| | | import com.alibaba.excel.write.style.HorizontalCellStyleStrategy; |
| | | import com.alibaba.fastjson.JSON; |
| | | import com.mindskip.xzs.base.BaseApiController; |
| | | import com.mindskip.xzs.base.RestResponse; |
| | | import com.mindskip.xzs.base.SystemCode; |
| | | import com.mindskip.xzs.context.WebContext; |
| | | import com.mindskip.xzs.domain.Question; |
| | | import com.mindskip.xzs.domain.QuestionSubject; |
| | | 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.QuestionStatusEnum; |
| | | 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.excel.*; |
| | | import com.mindskip.xzs.repository.DepartmentMapper; |
| | | import com.mindskip.xzs.repository.SubjectMapper; |
| | | import com.mindskip.xzs.service.*; |
| | |
| | | import com.mindskip.xzs.viewmodel.admin.education.SubjectPageRequestVM; |
| | | import com.mindskip.xzs.viewmodel.admin.question.*; |
| | | import com.github.pagehelper.PageInfo; |
| | | import com.mindskip.xzs.vo.QuestionExportVO; |
| | | import com.mindskip.xzs.vo.QuestionImportVO; |
| | | import org.apache.commons.lang3.StringUtils; |
| | | import org.apache.poi.ss.usermodel.DataValidationHelper; |
| | | import org.springframework.beans.BeanUtils; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.transaction.annotation.Transactional; |
| | | import org.springframework.util.CollectionUtils; |
| | | import org.springframework.web.bind.annotation.*; |
| | | import org.springframework.web.multipart.MultipartFile; |
| | | |
| | | import javax.servlet.http.HttpServletResponse; |
| | | import javax.validation.Valid; |
| | | import java.util.ArrayList; |
| | | import java.util.Arrays; |
| | | import java.util.List; |
| | | import java.io.IOException; |
| | | import java.io.UnsupportedEncodingException; |
| | | import java.math.BigDecimal; |
| | | import java.net.URLEncoder; |
| | | import java.util.*; |
| | | import java.util.function.Consumer; |
| | | import java.util.stream.Collectors; |
| | | |
| | | @RestController("AdminQuestionController") |
| | |
| | | private final DepartmentMapper departmentMapper; |
| | | |
| | | private final QuestionSubjectService questionSubjectService; |
| | | |
| | | private static final String SPLIT = "、"; |
| | | |
| | | @Autowired |
| | | public QuestionController(QuestionService questionService, TextContentService textContentService, SubjectMapper subjectMapper, DepartmentMapper departmentMapper, QuestionSubjectService questionSubjectService) { |
| | |
| | | } |
| | | |
| | | @RequestMapping(value = "/select/{id}", method = RequestMethod.POST) |
| | | public RestResponse<QuestionEditRequestVM> select(@PathVariable Integer id) { |
| | | QuestionEditRequestVM newVM = questionService.getQuestionEditRequestVM(id); |
| | | return RestResponse.ok(newVM); |
| | | public RestResponse<ExamQuestionVO> select(@PathVariable Integer id) { |
| | | return RestResponse.ok(questionService.getQuestionEditRequestVM(id)); |
| | | } |
| | | |
| | | |
| | |
| | | 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<QuestionImportVO> data = new ArrayList<>(4); |
| | | QuestionImportVO questionImportVO = new QuestionImportVO(); |
| | | questionImportVO.setQuestionType("单选题"); |
| | | questionImportVO.setDifficult(2); |
| | | questionImportVO.setCorrect("B"); |
| | | questionImportVO.setScore(2); |
| | | questionImportVO.setSubjectName("测试课目"); |
| | | questionImportVO.setAnalyze("B是对的"); |
| | | questionImportVO.setTitle("这是一道测试题目,使用该模板请删除或替换这道题"); |
| | | questionImportVO.setOptionName("A"); |
| | | questionImportVO.setOptionValue("选我"); |
| | | data.add(questionImportVO); |
| | | |
| | | QuestionImportVO questionImportVO1 = new QuestionImportVO(); |
| | | questionImportVO1.setOptionName("B"); |
| | | questionImportVO1.setOptionValue("选B"); |
| | | data.add(questionImportVO1); |
| | | |
| | | QuestionImportVO questionImportVO2 = new QuestionImportVO(); |
| | | questionImportVO2.setOptionName("C"); |
| | | questionImportVO2.setOptionValue("选C"); |
| | | data.add(questionImportVO2); |
| | | |
| | | QuestionImportVO questionImportVO3 = new QuestionImportVO(); |
| | | questionImportVO3.setOptionName("D"); |
| | | questionImportVO3.setOptionValue("选D"); |
| | | data.add(questionImportVO3); |
| | | |
| | | // 查出所有的课目(excel下拉数据) |
| | | List<Subject> subjects = subjectMapper.allSubject(); |
| | | List<String> subjectNameList = subjects.stream().map(Subject::getName).collect(Collectors.toList()); |
| | | |
| | | EasyExcel.write(response.getOutputStream(), QuestionImportVO.class) |
| | | .sheet("模板") |
| | | .registerWriteHandler(new SelectExcel(subjectNameList)) |
| | | .registerWriteHandler(new FixedMergeCellStrategy(2, 4, Arrays.asList(0, 1, 2, 5, 6, 7, 8))) |
| | | .doWrite(data); |
| | | } |
| | | |
| | | @GetMapping("/question/export") |
| | | public void importQuestion(QuestionExportVO query, HttpServletResponse response) throws IOException { |
| | | query.formartTime(); |
| | | // 查询导出数据 |
| | | List<QuestionImportVO> exportData = questionService.export(query); |
| | | // 构建数据 |
| | | List<QuestionImportVO> exportList = new ArrayList<>(exportData.size() * 4); |
| | | // 行合并规则 |
| | | List<RowItem> 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<Subject> subjects = subjectMapper.allSubject(); |
| | | List<String> 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<List<QuestionImportVO>> consumer = (data) -> { |
| | | // 题目的课目信息 |
| | | List<QuestionSubject> 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<QuestionItemObject> 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<Subject> subjects = subjectMapper.allSubject(); |
| | | List<String> subjectNames = Arrays.asList(excelQuestion.getSubjectName().split(SPLIT)); |
| | | List<Subject> 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(); |
| | | } |
| | | |
| | |
| | | vm.setCorrectArray(str); |
| | | vm.setCorrect(null); |
| | | } |
| | | |
| | | vm.setScore("2"); |
| | | vm.setScore(QuestionSourceEnum.fromType(vm.getQuestionType()).toString()); |
| | | vm.setDifficult(4); |
| | | |
| | | questionService.insertFullQuestion(vm, getCurrentUser().getId()); |