|
@@ -0,0 +1,332 @@
|
|
|
+package com.qmth.distributed.print.business.service.impl;
|
|
|
+
|
|
|
+import com.alibaba.fastjson.JSONObject;
|
|
|
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
|
|
+import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
|
|
|
+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.google.common.collect.Lists;
|
|
|
+import com.qmth.boot.api.exception.ApiException;
|
|
|
+import com.qmth.distributed.print.business.bean.dto.ExamPaperObjectiveStructureDto;
|
|
|
+import com.qmth.distributed.print.business.bean.dto.ExamPaperStructureDto;
|
|
|
+import com.qmth.distributed.print.business.bean.dto.ExamPaperSubjectiveStructureDto;
|
|
|
+import com.qmth.distributed.print.business.entity.ExamPaperStructure;
|
|
|
+import com.qmth.distributed.print.business.entity.ExamTask;
|
|
|
+import com.qmth.distributed.print.business.entity.ExamTaskDetail;
|
|
|
+import com.qmth.distributed.print.business.enums.ExamPaperStructureStatusEnum;
|
|
|
+import com.qmth.distributed.print.business.mapper.ExamPaperStructureMapper;
|
|
|
+import com.qmth.distributed.print.business.service.ExamPaperStructureService;
|
|
|
+import com.qmth.distributed.print.business.service.ExamTaskDetailService;
|
|
|
+import com.qmth.distributed.print.business.service.ExamTaskService;
|
|
|
+import com.qmth.distributed.print.business.service.PrintCommonService;
|
|
|
+import com.qmth.teachcloud.common.entity.BasicAttachment;
|
|
|
+import com.qmth.teachcloud.common.entity.SysUser;
|
|
|
+import com.qmth.teachcloud.common.enums.ExceptionResultEnum;
|
|
|
+import com.qmth.teachcloud.common.enums.UploadFileEnum;
|
|
|
+import com.qmth.teachcloud.common.service.BasicAttachmentService;
|
|
|
+import com.qmth.teachcloud.common.util.ExcelUtil;
|
|
|
+import com.qmth.teachcloud.common.util.ResultUtil;
|
|
|
+import com.qmth.teachcloud.common.util.ServletUtil;
|
|
|
+import com.qmth.teachcloud.common.util.excel.ExcelError;
|
|
|
+import org.apache.commons.lang3.StringUtils;
|
|
|
+import org.springframework.beans.factory.annotation.Autowired;
|
|
|
+import org.springframework.stereotype.Service;
|
|
|
+import org.springframework.transaction.annotation.Transactional;
|
|
|
+import org.springframework.util.CollectionUtils;
|
|
|
+import org.springframework.util.LinkedMultiValueMap;
|
|
|
+import org.springframework.web.multipart.MultipartFile;
|
|
|
+
|
|
|
+import javax.annotation.Resource;
|
|
|
+import java.io.IOException;
|
|
|
+import java.util.*;
|
|
|
+import java.util.stream.Collectors;
|
|
|
+
|
|
|
+/**
|
|
|
+ * <p>
|
|
|
+ * 试卷结构 服务实现类
|
|
|
+ * </p>
|
|
|
+ */
|
|
|
+@Service
|
|
|
+public class ExamPaperStructureServiceImpl extends ServiceImpl<ExamPaperStructureMapper, ExamPaperStructure> implements ExamPaperStructureService {
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ ExamTaskService examTaskService;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ ExamTaskDetailService examTaskDetailService;
|
|
|
+
|
|
|
+ @Resource
|
|
|
+ PrintCommonService printCommonService;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ BasicAttachmentService basicAttachmentService;
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public IPage<ExamPaperStructure> listByPropositionTeacherId(Integer pageNumber, Integer pageSize) {
|
|
|
+ Long schoolId = Long.valueOf(ServletUtil.getRequestHeaderSchoolId().toString());
|
|
|
+ SysUser sysUser = (SysUser) ServletUtil.getRequestUser();
|
|
|
+ Page<ExamPaperStructure> page = new Page<>(pageNumber, pageSize);
|
|
|
+ QueryWrapper<ExamPaperStructure> queryWrapper = new QueryWrapper<>();
|
|
|
+ queryWrapper.lambda().eq(ExamPaperStructure::getSchoolId, schoolId).eq(ExamPaperStructure::getPropositionTeacherId, sysUser.getId());
|
|
|
+ return this.page(page, queryWrapper);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Transactional
|
|
|
+ @Override
|
|
|
+ public void upload(Long id, String md5, String paperType, MultipartFile[] files) {
|
|
|
+ // 组装ExamPaperStructureDto
|
|
|
+ List<ExamPaperStructureDto> examPaperStructureDtos = createExamPaperStructure(md5, paperType, files);
|
|
|
+ List<BasicAttachment> basicAttachmentList = new ArrayList<>();
|
|
|
+
|
|
|
+ List<Map<String, Object>> paperAnswerList = new ArrayList<>();
|
|
|
+ List<Map<String, Object>> subjectiveStructureList = new ArrayList<>();
|
|
|
+ List<Map<String, Object>> objectiveStructureList = new ArrayList<>();
|
|
|
+
|
|
|
+ // 试卷卷型及原卷附件ID
|
|
|
+ ExamPaperStructure examPaperStructure = this.getById(id);
|
|
|
+ Map<String, String> paperMap = createExamTaskAttachmentIds(examPaperStructure);
|
|
|
+
|
|
|
+ // 上传试卷结构、标答文件
|
|
|
+ for (ExamPaperStructureDto examPaperStructureDto : examPaperStructureDtos) {
|
|
|
+ Map<String, Object> paperAnswerMap = new HashMap<>();
|
|
|
+ paperAnswerMap.put("paperType", examPaperStructureDto.getPaperType());
|
|
|
+ Map<String, Object> subjectiveStructureMap = new HashMap<>();
|
|
|
+ subjectiveStructureMap.put("paperType", examPaperStructureDto.getPaperType());
|
|
|
+ Map<String, Object> objectiveStructureMap = new HashMap<>();
|
|
|
+ objectiveStructureMap.put("paperType", examPaperStructureDto.getPaperType());
|
|
|
+ try {
|
|
|
+ // 主观题附件
|
|
|
+ BasicAttachment subjectiveBasicAttachment = printCommonService.saveAttachment(examPaperStructureDto.getSubjectiveQuestionFile(), examPaperStructureDto.getSubjectiveQuestionMd5(), UploadFileEnum.UPLOAD);
|
|
|
+ if (Objects.isNull(subjectiveBasicAttachment)) {
|
|
|
+ throw ExceptionResultEnum.ATTACHMENT_ERROR.exception();
|
|
|
+ }
|
|
|
+ // 解析试卷结构
|
|
|
+ List<Object> subjectiveStructrue = analyzPaperSubjectiveStructure(examPaperStructureDto.getSubjectiveQuestionFile());
|
|
|
+ subjectiveStructureMap.put("content", CollectionUtils.isEmpty(subjectiveStructrue) ? null : subjectiveStructrue);
|
|
|
+ // 客观题附件
|
|
|
+ basicAttachmentList.add(subjectiveBasicAttachment);
|
|
|
+ BasicAttachment objectiveBasicAttachment = printCommonService.saveAttachment(examPaperStructureDto.getObjectiveQuestionFile(), examPaperStructureDto.getObjectiveQuestionMd5(), UploadFileEnum.UPLOAD);
|
|
|
+ if (Objects.isNull(objectiveBasicAttachment)) {
|
|
|
+ throw ExceptionResultEnum.ATTACHMENT_ERROR.exception();
|
|
|
+ }
|
|
|
+ // 解析试卷结构
|
|
|
+ List<Object> objectiveStructure = analyzPaperObjectiveStructure(examPaperStructureDto.getObjectiveQuestionFile());
|
|
|
+ objectiveStructureMap.put("content", CollectionUtils.isEmpty(objectiveStructure) ? null : objectiveStructure);
|
|
|
+ // 标答附件
|
|
|
+ basicAttachmentList.add(objectiveBasicAttachment);
|
|
|
+ BasicAttachment answerBasicAttachment = printCommonService.saveAttachment(examPaperStructureDto.getStandardAnswerFile(), examPaperStructureDto.getStandardAnswerMd5(), UploadFileEnum.UPLOAD);
|
|
|
+ if (Objects.isNull(answerBasicAttachment)) {
|
|
|
+ throw ExceptionResultEnum.ATTACHMENT_ERROR.exception();
|
|
|
+ }
|
|
|
+ paperAnswerMap.put("answer", answerBasicAttachment.getId());
|
|
|
+ basicAttachmentList.add(answerBasicAttachment);
|
|
|
+
|
|
|
+ // 试卷原卷
|
|
|
+ paperAnswerMap.put("paper", paperMap.get(examPaperStructureDto.getPaperType()));
|
|
|
+ paperAnswerList.add(paperAnswerMap);
|
|
|
+ subjectiveStructureList.add(subjectiveStructureMap);
|
|
|
+ objectiveStructureList.add(objectiveStructureMap);
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("请求出错", e);
|
|
|
+ for (BasicAttachment basicAttachment : basicAttachmentList) {
|
|
|
+ basicAttachmentService.deleteAttachment(basicAttachment);
|
|
|
+ }
|
|
|
+ if (e instanceof ApiException) {
|
|
|
+ ResultUtil.error((ApiException) e, e.getMessage());
|
|
|
+ } else {
|
|
|
+ ResultUtil.error(e.getMessage());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 保存
|
|
|
+ UpdateWrapper<ExamPaperStructure> updateWrapper = new UpdateWrapper<>();
|
|
|
+ updateWrapper.lambda().set(ExamPaperStructure::getPaperAnswer, JSONObject.toJSONString(paperAnswerList))
|
|
|
+ .set(ExamPaperStructure::getSubjectiveStructure, JSONObject.toJSONString(subjectiveStructureList))
|
|
|
+ .set(ExamPaperStructure::getObjectiveStructure, JSONObject.toJSONString(objectiveStructureList))
|
|
|
+ // 上传成功
|
|
|
+ .set(ExamPaperStructure::getStatus, ExamPaperStructureStatusEnum.UPLOAD_FINISH)
|
|
|
+ .eq(ExamPaperStructure::getId, id);
|
|
|
+ this.update(updateWrapper);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void updateStatusById(Long id, ExamPaperStructureStatusEnum status) {
|
|
|
+ UpdateWrapper<ExamPaperStructure> updateWrapper = new UpdateWrapper<>();
|
|
|
+ updateWrapper.lambda().set(ExamPaperStructure::getStatus, status).eq(ExamPaperStructure::getId, id);
|
|
|
+ this.update(updateWrapper);
|
|
|
+ }
|
|
|
+
|
|
|
+ private Map<String, String> createExamTaskAttachmentIds(ExamPaperStructure examPaperStructure) {
|
|
|
+ ExamTask examTask = examTaskService.getByCourseCodeAndPaperNumber(examPaperStructure.getSchoolId(), examPaperStructure.getCourseCode(), examPaperStructure.getPaperNumber());
|
|
|
+
|
|
|
+ QueryWrapper<ExamTaskDetail> examTaskDetailQueryWrapper = new QueryWrapper<>();
|
|
|
+ examTaskDetailQueryWrapper.lambda().eq(ExamTaskDetail::getExamTaskId, examTask.getId());
|
|
|
+ ExamTaskDetail examTaskDetail = examTaskDetailService.getOne(examTaskDetailQueryWrapper);
|
|
|
+
|
|
|
+ String paperAttachmentIds = examTaskDetail.getPaperAttachmentIds();
|
|
|
+ List<Map> list = JSONObject.parseArray(paperAttachmentIds, Map.class);
|
|
|
+ if (CollectionUtils.isEmpty(list)) {
|
|
|
+ throw ExceptionResultEnum.ERROR.exception("未找到关联的试卷文件");
|
|
|
+ }
|
|
|
+
|
|
|
+ Map<String, String> paperMap = list.stream().collect(Collectors.toMap(m -> m.get("name").toString(), m -> m.get("attachmentId").toString()));
|
|
|
+
|
|
|
+ return paperMap;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 解析excel文件内容
|
|
|
+ *
|
|
|
+ * @param file
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ private List<Object> analyzPaperSubjectiveStructure(MultipartFile file) throws IOException, NoSuchFieldException {
|
|
|
+ List<LinkedMultiValueMap<Integer, Object>> finalList = ExcelUtil.excelReader(file.getInputStream(), Lists.newArrayList(ExamPaperSubjectiveStructureDto.class), (finalExcelList, finalColumnNameList, finalExcelErrorList) -> {
|
|
|
+ List<ExcelError> excelErrorTemp = new ArrayList<>();
|
|
|
+ // 只允许导入一个sheet
|
|
|
+ if (finalExcelList.size() > 1) {
|
|
|
+ throw ExceptionResultEnum.ERROR.exception("excel中只允许有一个sheet");
|
|
|
+ }
|
|
|
+ for (int i = 0; i < finalExcelList.size(); i++) {
|
|
|
+ LinkedMultiValueMap<Integer, Object> excelMap = finalExcelList.get(i);
|
|
|
+ List<Object> examTaskTempList = excelMap.get(i);
|
|
|
+ for (int y = 0; y < examTaskTempList.size(); y++) {
|
|
|
+ ExamPaperSubjectiveStructureDto subjectiveStructureDto = (ExamPaperSubjectiveStructureDto) examTaskTempList.get(y);
|
|
|
+ if (StringUtils.isBlank(subjectiveStructureDto.getCourseCode())) {
|
|
|
+ excelErrorTemp.add(new ExcelError(y + 1, "excel第" + (i + 1) + "个sheet第" + (y + 1) + "行[课程代码]必填"));
|
|
|
+ }
|
|
|
+ if (StringUtils.isBlank(subjectiveStructureDto.getCourseName())) {
|
|
|
+ excelErrorTemp.add(new ExcelError(y + 1, "excel第" + (i + 1) + "个sheet第" + (y + 1) + "行[课程名称]必填"));
|
|
|
+ }
|
|
|
+ if (StringUtils.isBlank(subjectiveStructureDto.getMainName())) {
|
|
|
+ excelErrorTemp.add(new ExcelError(y + 1, "excel第" + (i + 1) + "个sheet第" + (y + 1) + "行[大题名称]必填"));
|
|
|
+ }
|
|
|
+ if (StringUtils.isBlank(subjectiveStructureDto.getMainNumber())) {
|
|
|
+ excelErrorTemp.add(new ExcelError(y + 1, "excel第" + (i + 1) + "个sheet第" + (y + 1) + "行[大题号]必填"));
|
|
|
+ }
|
|
|
+ if (StringUtils.isBlank(subjectiveStructureDto.getSubNumber())) {
|
|
|
+ excelErrorTemp.add(new ExcelError(y + 1, "excel第" + (i + 1) + "个sheet第" + (y + 1) + "行[小题号]必填"));
|
|
|
+ }
|
|
|
+ if (StringUtils.isBlank(subjectiveStructureDto.getScore())) {
|
|
|
+ excelErrorTemp.add(new ExcelError(y + 1, "excel第" + (i + 1) + "个sheet第" + (y + 1) + "行[小题满分]必填"));
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (excelErrorTemp.size() > 0) {
|
|
|
+ List<String> errors = excelErrorTemp.stream().map(m -> m.getExcelErrorType()).collect(Collectors.toList());
|
|
|
+ throw ExceptionResultEnum.ERROR.exception(JSONObject.toJSONString(errors));
|
|
|
+ }
|
|
|
+ return finalExcelList;
|
|
|
+ });
|
|
|
+ List<Object> list = new ArrayList<>();
|
|
|
+ for (LinkedMultiValueMap<Integer, Object> map : finalList) {
|
|
|
+ for (Map.Entry<Integer, List<Object>> entry : map.entrySet()) {
|
|
|
+ list.add(entry.getValue());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return list;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 解析excel文件内容
|
|
|
+ *
|
|
|
+ * @param file
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ private List<Object> analyzPaperObjectiveStructure(MultipartFile file) throws IOException, NoSuchFieldException {
|
|
|
+ List<LinkedMultiValueMap<Integer, Object>> finalList = ExcelUtil.excelReader(file.getInputStream(), Lists.newArrayList(ExamPaperObjectiveStructureDto.class), (finalExcelList, finalColumnNameList, finalExcelErrorList) -> {
|
|
|
+ List<ExcelError> excelErrorTemp = new ArrayList<>();
|
|
|
+ // 只允许导入一个sheet
|
|
|
+ if (finalExcelList.size() > 1) {
|
|
|
+ throw ExceptionResultEnum.ERROR.exception("excel中只允许有一个sheet");
|
|
|
+ }
|
|
|
+ for (int i = 0; i < finalExcelList.size(); i++) {
|
|
|
+ LinkedMultiValueMap<Integer, Object> excelMap = finalExcelList.get(i);
|
|
|
+ List<Object> examTaskTempList = excelMap.get(i);
|
|
|
+ for (int y = 0; y < examTaskTempList.size(); y++) {
|
|
|
+ ExamPaperObjectiveStructureDto objectiveStructureDto = (ExamPaperObjectiveStructureDto) examTaskTempList.get(y);
|
|
|
+ if (StringUtils.isBlank(objectiveStructureDto.getCourseCode())) {
|
|
|
+ excelErrorTemp.add(new ExcelError(y + 1, "excel第" + (i + 1) + "个sheet第" + (y + 1) + "行[课程代码]必填"));
|
|
|
+ }
|
|
|
+ if (StringUtils.isBlank(objectiveStructureDto.getCourseName())) {
|
|
|
+ excelErrorTemp.add(new ExcelError(y + 1, "excel第" + (i + 1) + "个sheet第" + (y + 1) + "行[课程名称]必填"));
|
|
|
+ }
|
|
|
+ if (StringUtils.isBlank(objectiveStructureDto.getPaperType())) {
|
|
|
+ excelErrorTemp.add(new ExcelError(y + 1, "excel第" + (i + 1) + "个sheet第" + (y + 1) + "行[试卷类型]必填"));
|
|
|
+ }
|
|
|
+ if (StringUtils.isBlank(objectiveStructureDto.getMainName())) {
|
|
|
+ excelErrorTemp.add(new ExcelError(y + 1, "excel第" + (i + 1) + "个sheet第" + (y + 1) + "行[大题名称]必填"));
|
|
|
+ }
|
|
|
+ if (StringUtils.isBlank(objectiveStructureDto.getMainNumber())) {
|
|
|
+ excelErrorTemp.add(new ExcelError(y + 1, "excel第" + (i + 1) + "个sheet第" + (y + 1) + "行[大题号]必填"));
|
|
|
+ }
|
|
|
+ if (StringUtils.isBlank(objectiveStructureDto.getSubNumber())) {
|
|
|
+ excelErrorTemp.add(new ExcelError(y + 1, "excel第" + (i + 1) + "个sheet第" + (y + 1) + "行[小题号]必填"));
|
|
|
+ }
|
|
|
+ if (StringUtils.isBlank(objectiveStructureDto.getAnswer())) {
|
|
|
+ excelErrorTemp.add(new ExcelError(y + 1, "excel第" + (i + 1) + "个sheet第" + (y + 1) + "行[标准答案]必填"));
|
|
|
+ }
|
|
|
+ if (StringUtils.isBlank(objectiveStructureDto.getScore())) {
|
|
|
+ excelErrorTemp.add(new ExcelError(y + 1, "excel第" + (i + 1) + "个sheet第" + (y + 1) + "行[小题满分]必填"));
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (excelErrorTemp.size() > 0) {
|
|
|
+ List<String> errors = excelErrorTemp.stream().map(m -> m.getExcelErrorType()).collect(Collectors.toList());
|
|
|
+ throw ExceptionResultEnum.ERROR.exception(JSONObject.toJSONString(errors));
|
|
|
+ }
|
|
|
+ return finalExcelList;
|
|
|
+ });
|
|
|
+ List<Object> list = new ArrayList<>();
|
|
|
+ for (LinkedMultiValueMap<Integer, Object> map : finalList) {
|
|
|
+ for (Map.Entry<Integer, List<Object>> entry : map.entrySet()) {
|
|
|
+ list.add(entry.getValue());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return list;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 组装ExamPaperStructureDto
|
|
|
+ *
|
|
|
+ * @param md5
|
|
|
+ * @param paperType
|
|
|
+ * @param files
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ private List<ExamPaperStructureDto> createExamPaperStructure(String md5, String paperType, MultipartFile[] files) {
|
|
|
+ int COUNT = 3;
|
|
|
+ if (files.length == 0) {
|
|
|
+ throw ExceptionResultEnum.ERROR.exception("请上传文件");
|
|
|
+ }
|
|
|
+ if (StringUtils.isBlank(paperType)) {
|
|
|
+ throw ExceptionResultEnum.ERROR.exception("试卷卷型有误");
|
|
|
+ }
|
|
|
+ String[] paperTypes = paperType.split(",");
|
|
|
+ if (paperTypes.length * COUNT - files.length != 0) {
|
|
|
+ throw ExceptionResultEnum.ERROR.exception("上传文件有误");
|
|
|
+ }
|
|
|
+ if (StringUtils.isBlank(md5)) {
|
|
|
+ throw ExceptionResultEnum.ERROR.exception("上传文件有误");
|
|
|
+ }
|
|
|
+ String[] md5s = md5.split(",");
|
|
|
+ if (md5s.length - files.length != 0) {
|
|
|
+ throw ExceptionResultEnum.ERROR.exception("上传文件有误");
|
|
|
+ }
|
|
|
+ List<ExamPaperStructureDto> list = new ArrayList<>();
|
|
|
+ for (int i = 0; i < paperTypes.length; i++) {
|
|
|
+ ExamPaperStructureDto examPaperStructureDto = new ExamPaperStructureDto();
|
|
|
+ examPaperStructureDto.setPaperType(paperTypes[i]);
|
|
|
+ examPaperStructureDto.setObjectiveQuestionFile(files[COUNT * i]);
|
|
|
+ examPaperStructureDto.setObjectiveQuestionMd5(md5s[COUNT * i]);
|
|
|
+ examPaperStructureDto.setSubjectiveQuestionFile(files[COUNT * i + 1]);
|
|
|
+ examPaperStructureDto.setSubjectiveQuestionMd5(md5s[COUNT * i + 1]);
|
|
|
+ examPaperStructureDto.setStandardAnswerFile(files[COUNT * i + 2]);
|
|
|
+ examPaperStructureDto.setStandardAnswerMd5(md5s[COUNT * i + 2]);
|
|
|
+ list.add(examPaperStructureDto);
|
|
|
+ }
|
|
|
+ return list;
|
|
|
+ }
|
|
|
+}
|