package com.mindskip.xzs.controller.admin; import com.alibaba.excel.EasyExcel; import com.alibaba.fastjson.JSON; import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper; 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.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.domain.vo.DeptQuestionVO; import com.mindskip.xzs.excel.CurrencyDataListener; import com.mindskip.xzs.excel.SelectExcel; 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 com.mindskip.xzs.vo.QuestionSubjectVO; import org.apache.commons.lang3.StringUtils; 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.io.IOException; import java.math.BigDecimal; import java.net.URLEncoder; import java.util.*; import java.util.function.Consumer; 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).stream().map(Subject::getName).collect(Collectors.joining(SPLIT))); 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); QuestionImportVO questionImportVO = new QuestionImportVO(); questionImportVO.setQuestionType("单选题"); questionImportVO.setDifficult(2); questionImportVO.setCorrect("B"); questionImportVO.setScore("2"); questionImportVO.setSubjectName("测试课目"); questionImportVO.setAnalyze("B是对的"); questionImportVO.setTitle("这是一道测试题目,使用该模板请删除或替换这道题"); questionImportVO.setOptionA("选我"); questionImportVO.setOptionB("选我"); questionImportVO.setOptionC("选我"); questionImportVO.setOptionD("选我"); data.add(questionImportVO); // 查出所有的课目(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 FixedMergeCellStrategy(2, 4, Arrays.asList(1, 2, 3, 6, 7, 8, 9))) .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("/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); // 判断题干是否重复,重复不添加 Integer questionId = questionService.countQuestionByTitle(excelQuestion.getTitle()); if (Objects.isNull(questionId)) { // 该题的选项 List options = new ArrayList<>(4); // 选项内容 QuestionItemObject optionA = new QuestionItemObject(); optionA.setPrefix("A"); optionA.setContent(excelQuestion.getOptionA()); options.add(optionA); QuestionItemObject optionB = new QuestionItemObject(); optionB.setPrefix("B"); optionB.setContent(excelQuestion.getOptionB()); options.add(optionB); if (StringUtils.isNotBlank(excelQuestion.getOptionC())) { QuestionItemObject optionC = new QuestionItemObject(); optionC.setPrefix("C"); optionC.setContent(excelQuestion.getOptionC()); options.add(optionC); } if (StringUtils.isNotBlank(excelQuestion.getOptionD())) { QuestionItemObject optionD = new QuestionItemObject(); optionD.setPrefix("D"); optionD.setContent(excelQuestion.getOptionD()); options.add(optionD); } // 保存题目内容 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 rightAnswer = excelQuestion.getCorrect().replaceAll("\\s+", ""); // 答案(多选需要用,分割保存字符串到数据库) String[] corrects = rightAnswer.split(SPLIT); if (corrects.length > 1) { question.setCorrect(Arrays.asList(corrects).stream().collect(Collectors.joining(","))); } else { question.setCorrect(rightAnswer); } // 难度 question.setDifficult(excelQuestion.getDifficult()); // 分数 if (StringUtils.isBlank(excelQuestion.getScore())) { question.setScore(ExamUtil.scoreFromVM(QuestionSourceEnum.fromType(question.getQuestionType()) + "")); } else { 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 subjectNames = Arrays.asList(excelQuestion.getSubjectName().split(SPLIT)); List subjects = subjectNames.stream().map(name -> { // 判断课目是否存在于数据库,如果不存在则自动新增课目 Subject byName = subjectMapper.getByName(name); if (Objects.isNull(byName)) { byName = new Subject(); byName.setName(name); byName.setDeleted(false); subjectMapper.insert(byName); } return byName; }).collect(Collectors.toList()); // 构建课目-题目信息 questionSubjectsList = subjects.stream() .filter(subject -> { // 去重题目:题干+课目相同才算同一题 List lists = questionService.countQuestionByTitleAndSubject(excelQuestion.getTitle(), subject.getId()); return 0 == lists.size(); }) .map(subject -> { QuestionSubject questionSubject = new QuestionSubject(); questionSubject.setQuestionId(question.getId()); questionSubject.setSubjectId(subject.getId()); questionSubject.setDeleted(0); return questionSubject; }).collect(Collectors.toList()); // 批量保存题目-课目信息 if (! CollectionUtils.isEmpty(questionSubjectsList)) { questionSubjectService.saves(questionSubjectsList); } } else { question.setId(questionId); this.updateQuestion(question, excelQuestion); List subjectNames = Arrays.asList(excelQuestion.getSubjectName().split(SPLIT)); List subjects = subjectNames.stream().map(name -> { // 判断课目是否存在于数据库,如果不存在则自动新增课目 Subject byName = subjectMapper.getByName(name); if (Objects.isNull(byName)) { byName = new Subject(); byName.setName(name); byName.setDeleted(false); subjectMapper.insert(byName); } return byName; }).collect(Collectors.toList()); // 构建课目-题目信息 questionSubjectsList = subjects.stream() .filter(subject -> { // 去重题目:题干+课目相同才算同一题(题干相同:但有新增的课目时才做保存) List lists = questionService.countQuestionByTitleAndSubject(excelQuestion.getTitle(), subject.getId()); return 0 == lists.size(); }) .map(subject -> { QuestionSubject questionSubject = new QuestionSubject(); questionSubject.setQuestionId(questionId); questionSubject.setSubjectId(subject.getId()); questionSubject.setDeleted(0); return questionSubject; }).collect(Collectors.toList()); // 批量保存题目-课目信息 if (! CollectionUtils.isEmpty(questionSubjectsList)) { questionSubjectService.saves(questionSubjectsList); } } } }; EasyExcel.read(file.getInputStream(), QuestionImportVO.class, new CurrencyDataListener(consumer)).sheet("模板").doRead(); return RestResponse.ok(); } /** * 导入时,如果题干重复,那么更新题目信息(该方法不会更新题目的题库信息) * * @param question * @param excelQuestion */ private void updateQuestion(Question question, QuestionImportVO excelQuestion) { Question question1 = questionService.selectById(question.getId()); // 该题的选项 List options = new ArrayList<>(4); // 选项内容 QuestionItemObject optionA = new QuestionItemObject(); optionA.setPrefix("A"); optionA.setContent(excelQuestion.getOptionA()); options.add(optionA); QuestionItemObject optionB = new QuestionItemObject(); optionB.setPrefix("B"); optionB.setContent(excelQuestion.getOptionB()); options.add(optionB); if (StringUtils.isNotBlank(excelQuestion.getOptionC())) { QuestionItemObject optionC = new QuestionItemObject(); optionC.setPrefix("C"); optionC.setContent(excelQuestion.getOptionC()); options.add(optionC); } if (StringUtils.isNotBlank(excelQuestion.getOptionD())) { QuestionItemObject optionD = new QuestionItemObject(); optionD.setPrefix("D"); optionD.setContent(excelQuestion.getOptionD()); options.add(optionD); } // 更新题目内容 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()); textContent.setId(question1.getInfoTextContentId()); textContentService.updateByIdFilter(textContent); // 保存题目信息 // 设置题型 question.setQuestionType(QuestionTypeEnum.get(excelQuestion.getQuestionType())); // 答案去掉空格 String rightAnswer = excelQuestion.getCorrect().replaceAll("\\s+", ""); // 答案(多选需要用,分割保存字符串到数据库) String[] corrects = rightAnswer.split(SPLIT); if (corrects.length > 1) { question.setCorrect(Arrays.asList(corrects).stream().collect(Collectors.joining(","))); } else { question.setCorrect(rightAnswer); } // 难度 question.setDifficult(excelQuestion.getDifficult()); // 分数 if (StringUtils.isBlank(excelQuestion.getScore())) { question.setScore(ExamUtil.scoreFromVM(QuestionSourceEnum.fromType(question.getQuestionType()) + "")); } else { 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.updateByIdFilter(question); } // @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.getQuestionContent())) { QuestionObject questionContent = JSON.parseObject(question.getQuestionContent(), 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.setScore(BigDecimal.valueOf(Double.valueOf(question.getScore())).divide(BigDecimal.TEN).toString()); // 设置题干、解析 question.setAnalyze(questionContent.getAnalyze()); question.setTitle(questionContent.getTitleContent()); // 设置课目 question.setSubjectName(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下拉数据) List subjects = subjectMapper.allSubject(new ArrayList<>(), Boolean.TRUE); List subjectNameList = subjects.stream().map(Subject::getName).collect(Collectors.toList()); // 查出所有的课目(excel下拉数据) EasyExcel.write(response.getOutputStream(), QuestionImportVO.class) .sheet("题目导出数据") .registerWriteHandler(new SelectExcel(subjectNameList)) .doWrite(exportData); } }