Kaynağa Gözat

add:阅卷数据导入

caozixuan 1 yıl önce
ebeveyn
işleme
b441ca48ee

+ 187 - 0
distributed-print-business/src/main/java/com/qmth/distributed/print/business/bean/dto/MarkStudentImportDto.java

@@ -0,0 +1,187 @@
+package com.qmth.distributed.print.business.bean.dto;
+
+import com.qmth.teachcloud.common.annotation.ExcelNote;
+import com.qmth.teachcloud.common.annotation.ExcelProperty;
+import io.swagger.annotations.ApiModelProperty;
+
+import javax.validation.constraints.NotNull;
+
+/**
+ * @Description: 阅卷导入
+ * @Author: CaoZixuan
+ * @Date: 2024-03-09
+ */
+public class MarkStudentImportDto {
+
+    @ApiModelProperty("课程名称")
+    @ExcelProperty(name = "课程名称", width = 10, index = 1)
+    @ExcelNote(value = "课程名称")
+    @NotNull
+    private String courseName;
+
+    @ApiModelProperty("课程编号")
+    @ExcelProperty(name = "课程编号", width = 10, index = 2)
+    @ExcelNote(value = "课程编号")
+    @NotNull
+    private String courseCode;
+
+    @ApiModelProperty("试卷编号")
+    @ExcelProperty(name = "试卷编号", width = 10, index = 3)
+    @ExcelNote(value = "试卷编号")
+    @NotNull
+    private String paperNumber;
+
+    @ApiModelProperty("姓名")
+    @ExcelProperty(name = "姓名", width = 10, index = 4)
+    @ExcelNote(value = "姓名")
+    @NotNull
+    private String studentName;
+
+    @ApiModelProperty("学号")
+    @ExcelProperty(name = "学号", width = 10, index = 5)
+    @ExcelNote(value = "学号")
+    @NotNull
+    private String studentCode;
+
+    @ApiModelProperty("学院")
+    @ExcelProperty(name = "学院", width = 10, index = 6)
+    @ExcelNote(value = "学院")
+    private String college;
+
+    @ApiModelProperty("专业")
+    @ExcelProperty(name = "专业", width = 10, index = 7)
+    @ExcelNote(value = "专业")
+    private String major;
+
+    @ApiModelProperty("班级")
+    @ExcelProperty(name = "班级", width = 10, index = 8)
+    @ExcelNote(value = "班级")
+    private String clazz;
+
+    @ApiModelProperty("考试日期")
+    @ExcelProperty(name = "考试日期", width = 10, index = 9)
+    @ExcelNote(value = "考试日期")
+    private String examDate;
+
+    @ApiModelProperty("考试时间")
+    @ExcelProperty(name = "考试时间", width = 10, index = 10)
+    @ExcelNote(value = "考试时间")
+    private String examTime;
+
+    @ApiModelProperty("考点")
+    @ExcelProperty(name = "考点", width = 10, index = 11)
+    @ExcelNote(value = "考点")
+    private String examPlace;
+
+    @ApiModelProperty("考场")
+    @ExcelProperty(name = "考场", width = 10, index = 12)
+    @ExcelNote(value = "考场")
+    private String examRoom;
+
+    @ApiModelProperty("异常信息")
+    private String errorMsg;
+
+    public String getCourseName() {
+        return courseName;
+    }
+
+    public void setCourseName(String courseName) {
+        this.courseName = courseName;
+    }
+
+    public String getCourseCode() {
+        return courseCode;
+    }
+
+    public void setCourseCode(String courseCode) {
+        this.courseCode = courseCode;
+    }
+
+    public String getPaperNumber() {
+        return paperNumber;
+    }
+
+    public void setPaperNumber(String paperNumber) {
+        this.paperNumber = paperNumber;
+    }
+
+    public String getStudentName() {
+        return studentName;
+    }
+
+    public void setStudentName(String studentName) {
+        this.studentName = studentName;
+    }
+
+    public String getStudentCode() {
+        return studentCode;
+    }
+
+    public void setStudentCode(String studentCode) {
+        this.studentCode = studentCode;
+    }
+
+    public String getCollege() {
+        return college;
+    }
+
+    public void setCollege(String college) {
+        this.college = college;
+    }
+
+    public String getMajor() {
+        return major;
+    }
+
+    public void setMajor(String major) {
+        this.major = major;
+    }
+
+    public String getClazz() {
+        return clazz;
+    }
+
+    public void setClazz(String clazz) {
+        this.clazz = clazz;
+    }
+
+    public String getExamDate() {
+        return examDate;
+    }
+
+    public void setExamDate(String examDate) {
+        this.examDate = examDate;
+    }
+
+    public String getExamTime() {
+        return examTime;
+    }
+
+    public void setExamTime(String examTime) {
+        this.examTime = examTime;
+    }
+
+    public String getExamPlace() {
+        return examPlace;
+    }
+
+    public void setExamPlace(String examPlace) {
+        this.examPlace = examPlace;
+    }
+
+    public String getExamRoom() {
+        return examRoom;
+    }
+
+    public void setExamRoom(String examRoom) {
+        this.examRoom = examRoom;
+    }
+
+    public String getErrorMsg() {
+        return errorMsg;
+    }
+
+    public void setErrorMsg(String errorMsg) {
+        this.errorMsg = errorMsg;
+    }
+}

+ 19 - 12
distributed-print-business/src/main/java/com/qmth/distributed/print/business/service/PrintCommonService.java

@@ -49,10 +49,13 @@ public interface PrintCommonService {
      * @return
      * @throws IOException
      */
-    BasicAttachment saveAttachmentPdf(ClassifyEnum classifyEnum, ExamDetail examDetail, BasicAttachment basicAttachment, List<PdfDto> pdfList, Integer printCount, Integer sequence) throws IOException, DocumentException;
+    BasicAttachment saveAttachmentPdf(ClassifyEnum classifyEnum, ExamDetail examDetail, BasicAttachment basicAttachment,
+            List<PdfDto> pdfList, Integer printCount, Integer sequence) throws IOException, DocumentException;
 
-    void saveAttachmentSignPdf(PdfSignDto pdfFillDto, ExamDetail examDetail, List<PdfDto> pdfList, Integer printCount, List<File> fileTempList, BasicTemplate basicTemplate);
-    void saveAttachmentSignPdf(PdfSignDto pdfFillDto, ExamDetail examDetail,  Integer printCount, BasicTemplate basicTemplate);
+    void saveAttachmentSignPdf(PdfSignDto pdfFillDto, ExamDetail examDetail, List<PdfDto> pdfList, Integer printCount,
+            List<File> fileTempList, BasicTemplate basicTemplate);
+
+    void saveAttachmentSignPdf(PdfSignDto pdfFillDto, ExamDetail examDetail, Integer printCount, BasicTemplate basicTemplate);
 
     /**
      * 保存html附件
@@ -65,9 +68,13 @@ public interface PrintCommonService {
      * @return
      * @throws IOException
      */
-    BasicAttachment saveAttachmentHtml(String fileName, String htmlContent, Long userId, List<PdfDto> localFileList, List<File> fileTempList) throws IOException;
+    BasicAttachment saveAttachmentHtml(String fileName, String htmlContent, Long userId, List<PdfDto> localFileList,
+            List<File> fileTempList) throws IOException;
+
     BasicAttachment saveAttachmentPdfFromHtml(String fileName, String htmlContent, Long userId, List<PdfDto> localFileList) throws IOException;
-    BasicAttachment saveAttachmentPdfFromHtml(String fileName, File file, Long userId, List<PdfDto> localFileList) throws IOException;
+
+    BasicAttachment saveAttachmentPdfFromHtml(String fileName, File file, Long userId, List<PdfDto> localFileList)
+            throws IOException;
 
     /**
      * 保存html附件和该html转成pdf的附件
@@ -100,7 +107,6 @@ public interface PrintCommonService {
      */
     BasicAttachment saveAttachment(MultipartFile file, String md5, UploadFileEnum type);
 
-
     /**
      * 科目删除
      *
@@ -159,7 +165,6 @@ public interface PrintCommonService {
      */
     void resetCreatePdfTask() throws IOException;
 
-
     /**
      * 保存任务
      *
@@ -176,7 +181,7 @@ public interface PrintCommonService {
      * @param taskTypeEnum
      * @return
      */
-    Map<String, Object> saveTask(MultipartFile file,Long semesterId,Long examId, TaskTypeEnum taskTypeEnum);
+    Map<String, Object> saveTask(MultipartFile file, Long examId, TaskTypeEnum taskTypeEnum);
 
     /**
      * 保存任务
@@ -204,7 +209,6 @@ public interface PrintCommonService {
      */
     Map<String, Object> saveTask(Long printPlanId, TaskTypeEnum taskTypeEnum);
 
-
     /**
      * 校验课程关联考场是否提交打印
      *
@@ -249,7 +253,8 @@ public interface PrintCommonService {
      * @param sysUser                        请求用户
      * @return 结果
      */
-    List<ExamStudent> createBatchStudentByStudentList(Long schoolId, Long examId, String semesterId, ExamTask examTask, String extendFields, List<ExamTaskStudentObjectParam> examTaskStudentObjectParamList, Long examDetailCourseId, Long cardRuleId, SysUser sysUser);
+    List<ExamStudent> createBatchStudentByStudentList(Long schoolId, Long examId, String semesterId, ExamTask examTask,
+            String extendFields, List<ExamTaskStudentObjectParam> examTaskStudentObjectParamList, Long examDetailCourseId, Long cardRuleId, SysUser sysUser);
 
     /**
      * 保存任务附件(导出)
@@ -279,8 +284,10 @@ public interface PrintCommonService {
      */
     public void updateGradeBatchStatus(Long schoolId, Long examId, String paperNumber, String paperType);
 
-    void saveAttachmentPackagePdf(PdfPackageDto pdfPackageDto, ExamDetail examDetail, List<PdfDto> variablePdfList, Integer printCount, List<File> fileTempList);
-    void saveAttachmentPackagePdf(PdfPackageDto pdfPackageDto, ExamDetail examDetail,Integer printCount);
+    void saveAttachmentPackagePdf(PdfPackageDto pdfPackageDto, ExamDetail examDetail, List<PdfDto> variablePdfList,
+            Integer printCount, List<File> fileTempList);
+
+    void saveAttachmentPackagePdf(PdfPackageDto pdfPackageDto, ExamDetail examDetail, Integer printCount);
 
     String parseAttachmentPath(String attachmentPath, PrintPathVo printPathVo);
 

+ 6 - 1
distributed-print-business/src/main/java/com/qmth/distributed/print/business/service/impl/PrintCommonServiceImpl.java

@@ -1136,11 +1136,16 @@ public class PrintCommonServiceImpl implements PrintCommonService {
     }
 
     @Override
-    public Map<String, Object> saveTask(MultipartFile file, Long semesterId, Long examId, TaskTypeEnum taskTypeEnum) {
+    public Map<String, Object> saveTask(MultipartFile file, Long examId, TaskTypeEnum taskTypeEnum) {
         BasicAttachment basicAttachment = null;
         Map<String, Object> map = null;
         try {
             PrintCommonService printCommonService = SpringContextHolder.getBean(PrintCommonService.class);
+            BasicExam basicExam = basicExamService.getById(examId);
+            if (Objects.isNull(basicExam)) {
+                throw ExceptionResultEnum.ERROR.exception("考试不存在");
+            }
+            Long semesterId = SystemConstant.convertIdToLong(basicExam.getSemesterId());
             basicAttachment = printCommonService.saveAttachment(file, ServletUtil.getRequestMd5(), UploadFileEnum.FILE);
             if (Objects.isNull(basicAttachment)) {
                 throw ExceptionResultEnum.ATTACHMENT_ERROR.exception();

+ 224 - 0
distributed-print-business/src/main/java/com/qmth/distributed/print/business/templete/execute/SyncMarkStudentImportService.java

@@ -0,0 +1,224 @@
+package com.qmth.distributed.print.business.templete.execute;
+
+import cn.hutool.core.date.DateUtil;
+import com.alibaba.fastjson.JSON;
+import com.qmth.distributed.print.business.bean.dto.MarkStudentImportDto;
+import com.qmth.distributed.print.business.templete.importData.SyncImportTaskTemplate;
+import com.qmth.distributed.print.business.templete.service.TaskLogicService;
+import com.qmth.teachcloud.common.annotation.ExcelNote;
+import com.qmth.teachcloud.common.bean.vo.FilePathVo;
+import com.qmth.teachcloud.common.contant.SpringContextHolder;
+import com.qmth.teachcloud.common.contant.SystemConstant;
+import com.qmth.teachcloud.common.entity.TBTask;
+import com.qmth.teachcloud.common.enums.ExceptionResultEnum;
+import com.qmth.teachcloud.common.enums.TaskResultEnum;
+import com.qmth.teachcloud.common.enums.TaskStatusEnum;
+import com.qmth.teachcloud.common.enums.UploadFileEnum;
+import com.qmth.teachcloud.common.service.FileUploadService;
+import com.qmth.teachcloud.common.service.TBTaskService;
+import com.qmth.teachcloud.common.util.Result;
+import com.qmth.teachcloud.common.util.ResultUtil;
+import org.apache.commons.collections4.CollectionUtils;
+import org.apache.poi.ss.usermodel.FillPatternType;
+import org.apache.poi.ss.usermodel.Font;
+import org.apache.poi.ss.usermodel.HorizontalAlignment;
+import org.apache.poi.ss.usermodel.IndexedColors;
+import org.apache.poi.ss.util.CellRangeAddress;
+import org.apache.poi.xssf.usermodel.*;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.Resource;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.text.MessageFormat;
+import java.util.*;
+
+/**
+ * @Description: 阅卷数据导入同步任务
+ * @Author: CaoZixuan
+ * @Date: 2024-03-09
+ */
+@Service
+public class SyncMarkStudentImportService extends SyncImportTaskTemplate {
+
+    private final static Logger log = LoggerFactory.getLogger(SyncMarkStudentImportService.class);
+
+    public static final String OBJ_TITLE = "阅卷数据";
+
+    @Resource
+    private FileUploadService fileUploadService;
+
+    @Override
+    public Result importTask(Map<String, Object> map) throws Exception {
+        TBTask tbTask = (TBTask) map.get(SystemConstant.TASK);
+        InputStream inputStream = super.getUploadFileInputStream(tbTask);
+        map.put("inputStream", inputStream);
+
+        StringJoiner stringJoinerSummary = new StringJoiner("\n").add(
+                MessageFormat.format("{0}{1}{2}", DateUtil.format(new Date(), SystemConstant.DEFAULT_DATE_PATTERN),
+                        BEGIN_TITLE, OBJ_TITLE));
+        tbTask.setStatus(TaskStatusEnum.RUNNING);
+        TBTaskService tbTaskService = SpringContextHolder.getBean(TBTaskService.class);
+        tbTaskService.updateById(tbTask);
+        int dataCount = 0;
+        int successCount = 0;
+        int errorCount = 0;
+        List<MarkStudentImportDto> errorDataList = new ArrayList<>();
+        boolean importResult = true;
+
+        try {
+            TaskLogicService taskLogicService = SpringContextHolder.getBean(TaskLogicService.class);
+
+            // 执行导入阅卷数据
+            Map<String, Object> result = taskLogicService.executeImportMarkStudentLogic(map);
+            dataCount = Integer.parseInt(String.valueOf(result.get(SystemConstant.DATA_COUNT)));
+            successCount = Integer.parseInt(String.valueOf(result.get(SystemConstant.SUCCESS_DATA_COUNT)));
+            errorCount = Integer.parseInt(String.valueOf(result.get(SystemConstant.ERROR_DATA_COUNT)));
+
+            // 无异常数据
+            if (result.containsKey(SystemConstant.DATASOURCE)) {
+                List<MarkStudentImportDto> markStudentImportDtoList = JSON.parseArray(JSON.toJSONString(result.get(SystemConstant.DATASOURCE)), MarkStudentImportDto.class);
+                taskLogicService.saveMarkStudent(tbTask.getExamId(), markStudentImportDtoList);
+
+            } else if (result.containsKey(SystemConstant.ERROR_DATA_LIST)) {
+                // 有异常数据
+                errorDataList = JSON.parseArray(JSON.toJSONString(result.get(SystemConstant.ERROR_DATA_LIST)),
+                        MarkStudentImportDto.class);
+            }
+
+        } catch (Exception e) {
+            log.error(SystemConstant.LOG_ERROR, e.getMessage());
+            throw ExceptionResultEnum.ERROR.exception("导入考生字典失败");
+        } finally {//生成文件
+            stringJoinerSummary.add(MessageFormat.format("{0}{1}{2}{3}{4}{5}{6}{7}",
+                    DateUtil.format(new Date(), SystemConstant.DEFAULT_DATE_PATTERN), FINISH_TITLE, dataCount,
+                    FINISH_TOTAL_SIZE, successCount, FINISH_SUCCESS_SIZE, errorCount, FINISH_ERROR_SIZE));
+            if (CollectionUtils.isNotEmpty(errorDataList)) {
+                tbTask.setResult(TaskResultEnum.ERROR);
+                try {
+                    File excelFileTemp = SystemConstant.getFileTempVar(SystemConstant.EXCEL_PREFIX);
+                    this.createLocalErrorExcel(errorDataList, excelFileTemp);
+                    String fileName = SystemConstant.getNanoId() + SystemConstant.EXCEL_PREFIX;
+                    FilePathVo filePathVo = fileUploadService.uploadFile(excelFileTemp, UploadFileEnum.FILE, fileName);
+                    tbTask.setErrorFilePath(JSON.toJSONString(filePathVo));
+                } catch (Exception e) {
+                    log.error("创建考生字典导入错误数据文件失败");
+                } finally {
+                    tbTask.setSummary("创建考生字典导入错误数据文件失败" + stringJoinerSummary);
+                }
+                importResult = false;
+            } else {
+                tbTask.setSummary(stringJoinerSummary.toString());
+                tbTask.setResult(TaskResultEnum.SUCCESS);
+            }
+            tbTask.setStatus(TaskStatusEnum.FINISH);
+            super.createTxt(tbTask);
+        }
+        return ResultUtil.ok(importResult);
+    }
+
+    private void createLocalErrorExcel(List<MarkStudentImportDto> markStudentImportDtoList, File excelFileTemp)
+            throws NoSuchMethodException, InvocationTargetException, IllegalAccessException, IOException {
+
+        List<Field> fields = Arrays.asList(MarkStudentImportDto.class.getDeclaredFields());
+
+        log.debug("导出Excel开始...");
+        XSSFWorkbook wb = new XSSFWorkbook();
+        XSSFSheet sheet = wb.createSheet("考生字典导入");
+
+        Font defaultFont = wb.createFont();
+        defaultFont.setFontHeightInPoints((short) 12);
+        defaultFont.setFontName("宋体");
+
+        int cellCount = fields.size();
+        // 说明
+        XSSFCellStyle describeStyle = wb.createCellStyle();
+        describeStyle.setAlignment(HorizontalAlignment.LEFT);
+        Font describeFont = wb.createFont();
+        describeFont.setFontHeightInPoints((short) 12);
+        describeFont.setFontName("宋体");
+        describeFont.setColor(IndexedColors.RED.getIndex());
+        describeStyle.setFont(describeFont);
+        String describe = SystemConstant.BASIC_EXAM_STUDENT;
+        describe = describe.trim();
+        XSSFRow rowDescribe = sheet.createRow(0);
+        rowDescribe.setHeightInPoints(195); //行高设置成195px
+        for (int i = 0; i < cellCount; i++) {
+            XSSFCell cell = rowDescribe.createCell(i);
+            if (i == 0) {
+                cell.setCellValue(describe);
+                cell.setCellStyle(describeStyle);
+            }
+        }
+        CellRangeAddress region = new CellRangeAddress(0, 0, 0, cellCount - 1);
+        sheet.addMergedRegion(region);
+
+        // 表头行
+        XSSFCellStyle headerStyle = wb.createCellStyle();
+        headerStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
+        headerStyle.setAlignment(HorizontalAlignment.CENTER);
+        headerStyle.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex());
+        headerStyle.setFont(defaultFont);
+        XSSFRow rowHead = sheet.createRow(1);
+        for (int i = 0; i < fields.size(); i++) {
+            XSSFCell cell = rowHead.createCell(i);
+            Field field = fields.get(i);
+            String title = "";
+            ExcelNote excelNote = field.getAnnotation(ExcelNote.class);
+
+            if (Objects.isNull(excelNote)) {
+                if (i == fields.size() - 1) {
+                    title = "异常信息";
+                } else {
+                    throw ExceptionResultEnum.ERROR.exception("未能获取dto属性注解");
+                }
+            } else {
+                title = excelNote.value();
+            }
+            cell.setCellValue(title);
+            cell.setCellStyle(headerStyle);
+        }
+        XSSFCell lastCell = rowHead.createCell(cellCount - 1);
+        lastCell.setCellValue("异常信息");
+        lastCell.setCellStyle(headerStyle);
+
+        // 内容行
+        XSSFCellStyle exampleStyle = wb.createCellStyle();
+        exampleStyle.setAlignment(HorizontalAlignment.LEFT);
+        exampleStyle.setFont(defaultFont);
+
+        for (int i = 0; i < markStudentImportDtoList.size(); i++) {
+            MarkStudentImportDto markStudentImportDto = markStudentImportDtoList.get(i);
+            XSSFRow row = sheet.createRow(i + 2);
+            for (int j = 0; j < fields.size(); j++) {
+                XSSFCell cell = row.createCell(j);
+                Field head = fields.get(j);
+                String methodName = "get" + SystemConstant.initCap(head.getName());
+                Method getMethod = markStudentImportDto.getClass().getDeclaredMethod(methodName);
+                String value = String.valueOf(getMethod.invoke(markStudentImportDto));
+                if (SystemConstant.strNotNull(value)) {
+                    cell.setCellValue(value);
+                } else {
+                    cell.setCellValue("");
+                }
+                cell.setCellStyle(exampleStyle);
+            }
+        }
+        for (int i = 0; i < cellCount; i++) {
+            sheet.autoSizeColumn(i);
+            sheet.setColumnWidth(i, sheet.getColumnWidth(i) * 17 / 10);
+        }
+
+        FileOutputStream outputStream = new FileOutputStream(excelFileTemp);
+        wb.write(outputStream);
+        outputStream.flush();
+        outputStream.close();
+    }
+}

+ 20 - 0
distributed-print-business/src/main/java/com/qmth/distributed/print/business/templete/service/TaskLogicService.java

@@ -1,6 +1,9 @@
 package com.qmth.distributed.print.business.templete.service;
 
+import com.qmth.distributed.print.business.bean.dto.MarkStudentImportDto;
+
 import java.io.IOException;
+import java.util.List;
 import java.util.Map;
 
 /**
@@ -125,4 +128,21 @@ public interface TaskLogicService {
      * @throws Exception 异常
      */
     Map<String, Object> executeImportBasicExamStudentLogic(Map<String, Object> map) throws Exception;
+
+    /**
+     * 处理阅卷数据导入
+     *
+     * @param map 数据源
+     * @return 结果
+     * @throws Exception 异常
+     */
+    Map<String, Object> executeImportMarkStudentLogic(Map<String, Object> map) throws Exception;
+
+    /**
+     * 保存阅卷数据
+     *
+     * @param examId                   考试id
+     * @param markStudentImportDtoList 阅卷数据
+     */
+    void saveMarkStudent(Long examId, List<MarkStudentImportDto> markStudentImportDtoList);
 }

+ 190 - 2
distributed-print-business/src/main/java/com/qmth/distributed/print/business/templete/service/impl/TaskLogicServiceImpl.java

@@ -37,6 +37,10 @@ import com.qmth.teachcloud.common.enums.*;
 import com.qmth.teachcloud.common.service.*;
 import com.qmth.teachcloud.common.util.*;
 import com.qmth.teachcloud.common.util.excel.ExcelError;
+import com.qmth.teachcloud.mark.entity.MarkPaper;
+import com.qmth.teachcloud.mark.entity.MarkStudent;
+import com.qmth.teachcloud.mark.service.MarkPaperService;
+import com.qmth.teachcloud.mark.service.MarkStudentService;
 import org.apache.commons.codec.digest.DigestUtils;
 import org.apache.commons.collections4.CollectionUtils;
 import org.apache.commons.io.FileUtils;
@@ -65,6 +69,7 @@ import java.nio.charset.StandardCharsets;
 import java.util.*;
 import java.util.concurrent.atomic.AtomicInteger;
 import java.util.stream.Collectors;
+import java.util.stream.Stream;
 
 /**
  * @Description: 任务处理逻辑impl
@@ -141,6 +146,10 @@ public class TaskLogicServiceImpl implements TaskLogicService {
     FileUploadService fileUploadService;
     @Resource
     BasicExamStudentService basicExamStudentService;
+    @Resource
+    MarkPaperService markPaperService;
+    @Resource
+    MarkStudentService markStudentService;
 
     /**
      * 创建pdf前置条件
@@ -2076,14 +2085,18 @@ public class TaskLogicServiceImpl implements TaskLogicService {
 
         SysUser requestUser = (SysUser) map.get(SystemConstant.USER);
         InputStream inputStream = (InputStream) map.get("inputStream");
-        Long semesterId = SystemConstant.convertIdToLong(String.valueOf(map.get("semesterId")));
         Long examId = SystemConstant.convertIdToLong(String.valueOf(map.get("examId")));
         Long schoolId = requestUser.getSchoolId();
+        BasicExam basicExam = basicExamService.getById(examId);
+        if (Objects.isNull(basicExam)){
+            throw ExceptionResultEnum.ERROR.exception("考试不存在");
+        }
+        Long semesterId = SystemConstant.convertIdToLong(basicExam.getSemesterId());
 
         List<BasicExamStudent> dbData = basicExamStudentService.list(new QueryWrapper<BasicExamStudent>().lambda()
                 .select(BasicExamStudent::getId, BasicExamStudent::getExamId, BasicExamStudent::getCourseCode,
                         BasicExamStudent::getStudentCode).eq(BasicExamStudent::getSchoolId, schoolId)
-                .eq(BasicExamStudent::getSemesterId, semesterId).eq(BasicExamStudent::getExamId, examId));
+                .eq(BasicExamStudent::getExamId, examId));
 
         // 数据库中学生学号和id对应关系
         Map<String, Long> studentCodeIdMap = dbData.stream().collect(Collectors.toMap(
@@ -2198,6 +2211,181 @@ public class TaskLogicServiceImpl implements TaskLogicService {
         return map;
     }
 
+    @Transactional
+    @Override
+    public Map<String, Object> executeImportMarkStudentLogic(Map<String, Object> map) throws Exception {
+        SysUser requestUser = (SysUser) map.get(SystemConstant.USER);
+        InputStream inputStream = (InputStream) map.get("inputStream");
+        Long examId = SystemConstant.convertIdToLong(String.valueOf(map.get("examId")));
+        // 检验课程编号和课程名称对应
+        Map<String, String> courseCodeNameCheckMap = new HashMap<>();
+        // 检验学号在课程下唯一
+        Map<String, List<String>> checkStudentCodeMap = new HashMap<>();
+        // 检验同一个课程、试卷下的班级信息要么全填要么全不填
+        Map<String, Boolean> checkClazzMap = new HashMap<>();
+
+        List<MarkStudentImportDto> datasource = new ArrayList<>();
+        AtomicInteger successInteger = new AtomicInteger(0);
+        AtomicInteger exceptionInteger = new AtomicInteger(0);
+
+        ExcelUtil.excelReader(inputStream, Lists.newArrayList(MarkStudentImportDto.class),
+                (finalExcelList, finalColumnNameList, finalExcelErrorList) -> {
+
+                    for (int i = 0; i < finalExcelList.size(); i++) {
+                        LinkedMultiValueMap<Integer, Object> excelMap = finalExcelList.get(i);
+                        List<Object> MarkStudentImportDtoList = excelMap.get(i);
+                        // 无数据,跳过
+                        if (CollectionUtils.isEmpty(MarkStudentImportDtoList)) {
+                            continue;
+                        }
+                        for (int y = 0; y < Objects.requireNonNull(MarkStudentImportDtoList).size(); y++) {
+                            List<String> errorMsgList = new ArrayList<>();
+                            // 行索引
+                            MarkStudentImportDto markStudentImportDto = (MarkStudentImportDto) MarkStudentImportDtoList.get(
+                                    y);
+                            String courseName = StringUtils.trimToNull(markStudentImportDto.getCourseName());
+                            String courseCode = StringUtils.trimToNull(markStudentImportDto.getCourseCode());
+                            String paperNumber = StringUtils.trimToNull(markStudentImportDto.getPaperNumber());
+                            String studentName = StringUtils.trimToNull(markStudentImportDto.getStudentName());
+                            String studentCode = StringUtils.trimToNull(markStudentImportDto.getStudentCode());
+                            String college = StringUtils.trimToNull(markStudentImportDto.getCollege());
+                            String major = StringUtils.trimToNull(markStudentImportDto.getMajor());
+                            String clazz = StringUtils.trimToNull(markStudentImportDto.getClazz());
+                            String examDate = StringUtils.trimToNull(markStudentImportDto.getExamDate());
+                            String examTime = StringUtils.trimToNull(markStudentImportDto.getExamTime());
+                            String examPlace = StringUtils.trimToNull(markStudentImportDto.getExamPlace());
+                            String examRoom = StringUtils.trimToNull(markStudentImportDto.getExamRoom());
+
+                            // 本行全部列为空,跳过
+                            if (StringUtils.isAllBlank(courseName, courseCode, paperNumber, studentName, studentCode,
+                                    college, major, clazz, examDate, examTime, examDate, examPlace, examRoom)) {
+                                continue;
+                            }
+                            // 课程编号和课程名称一致
+                            if (courseCodeNameCheckMap.containsKey(courseCode)) {
+                                if (!courseCodeNameCheckMap.get(courseCode).equals(courseName)) {
+                                    errorMsgList.add("同一个课程编号对应了多个课程名称");
+                                }
+                            } else {
+                                courseCodeNameCheckMap.put(courseCode, courseName);
+                            }
+
+                            // 学号在课程下唯一
+                            if (checkStudentCodeMap.containsKey(courseCode)) {
+                                List<String> studentCodeList = checkStudentCodeMap.get(courseCode);
+                                if (studentCodeList.contains(studentCode)) {
+                                    errorMsgList.add("学号重复(学号需要在课程下唯一)");
+                                } else {
+                                    studentCodeList.add(studentCode);
+                                }
+                            } else {
+                                List<String> studentCodeList = new ArrayList<>();
+                                studentCodeList.add(studentCode);
+                                checkStudentCodeMap.put(courseCode, studentCodeList);
+                            }
+
+                            // 同一个课程、试卷下的班级信息要么全填要么全不填
+                            String clazzCheckKey = courseCode + SystemConstant.HYPHEN + paperNumber;
+                            if (checkClazzMap.containsKey(clazzCheckKey)) {
+                                Boolean hasData = checkClazzMap.get(clazzCheckKey);
+                                if (SystemConstant.strNotNull(clazz) != hasData) {
+                                    errorMsgList.add("班级信息异常(同一个课程、试卷下的班级信息要么全填要么全不填)");
+                                }
+                            } else {
+                                checkClazzMap.put(clazzCheckKey, SystemConstant.strNotNull(clazz));
+                            }
+
+                            try {
+                                if (SystemConstant.strNotNull(examDate) && SystemConstant.strNotNull(examTime)) {
+                                    ConvertUtil.analyzeStartAndEndTime(examDate, examTime);
+                                }
+                            } catch (Exception e) {
+                                errorMsgList.add(e.getMessage());
+                            }
+
+                            if (CollectionUtils.isNotEmpty(errorMsgList)) {
+                                markStudentImportDto.setErrorMsg(String.join(";", errorMsgList));
+                                exceptionInteger.getAndIncrement();
+                            } else {
+                                successInteger.getAndIncrement();
+                            }
+                            datasource.add(markStudentImportDto);
+                        }
+                    }
+
+                    if (datasource.stream().anyMatch(e -> SystemConstant.strNotNull(e.getErrorMsg()))) {
+                        map.put(SystemConstant.ERROR_DATA_LIST, datasource);
+                    } else {
+                        map.put(SystemConstant.DATASOURCE, datasource);
+                    }
+                    map.put(SystemConstant.DATA_COUNT, datasource.size());
+                    map.put(SystemConstant.SUCCESS_DATA_COUNT, successInteger.get());
+                    map.put(SystemConstant.ERROR_DATA_COUNT, exceptionInteger.get());
+                    return finalExcelList;
+                }, 2);
+        return map;
+    }
+
+    @Transactional
+    @Override
+    public void saveMarkStudent(Long examId, List<MarkStudentImportDto> markStudentImportDtoList) {
+        SysUser requestUser = (SysUser) ServletUtil.getRequestUser();
+        Long requestUserId = requestUser.getId();
+        final String paperType = "A";
+
+        markPaperService.remove(new QueryWrapper<MarkPaper>().lambda().eq(MarkPaper::getExamId, examId));
+        markStudentService.remove(new QueryWrapper<MarkStudent>().lambda().eq(MarkStudent::getExamId, examId));
+
+        List<Map<String, String>> paperInfo = markStudentImportDtoList.stream().flatMap(e -> {
+            Map<String, String> map = new HashMap<>();
+            map.put("courseCode", e.getCourseCode());
+            map.put("courseName", e.getCourseName());
+            map.put("paperNumber", e.getPaperNumber());
+            return Stream.of(map);
+        }).distinct().collect(Collectors.toList());
+
+        // 新增mark_paper信息
+        for (Map<String, String> paperMap : paperInfo) {
+            String courseCode = paperMap.get("courseCode");
+            String courseName = paperMap.get("courseName");
+            String paperNumber = paperMap.get("paperNumber");
+
+            MarkPaper markPaper = new MarkPaper(examId, courseCode, courseName, paperNumber, null, requestUserId,
+                    paperType);
+            markPaperService.save(markPaper);
+        }
+        // 新增mark_student信息
+        Map<String, Map<String, Object>> examTimeMap = new HashMap<>();
+        List<MarkStudent> markStudentList = markStudentImportDtoList.stream().flatMap(e -> {
+            String examDate = e.getExamDate();
+            String examTime = e.getExamTime();
+            Long examStartTime = null;
+            Long examEndTime = null;
+            if (SystemConstant.strNotNull(examDate) && SystemConstant.strNotNull(examTime)) {
+                String key = examDate + SystemConstant.HYPHEN + examTime;
+                Map<String, Object> timeMap = new HashMap<>();
+                if (examTimeMap.containsKey(key)) {
+                    timeMap = examTimeMap.get(key);
+                } else {
+                    timeMap = ConvertUtil.analyzeStartAndEndTime(examDate, examTime);
+                    examTimeMap.put(key, timeMap);
+                }
+                examStartTime = SystemConstant.convertIdToLong(String.valueOf(timeMap.get("startTime")));
+                examEndTime = SystemConstant.convertIdToLong(String.valueOf(timeMap.get("endTime")));
+            }
+            MarkStudent markStudent = new MarkStudent(null, examId, e.getCourseCode(), e.getCourseName(), e.getPaperNumber(),
+                    null, paperType, e.getStudentCode(), e.getStudentName(), null, e.getExamPlace(), e.getExamRoom(), e.getCollege(),
+                    e.getMajor(), e.getClazz(), examStartTime, examEndTime, requestUserId);
+            return Stream.of(markStudent);
+        }).collect(Collectors.toList());
+
+        if (CollectionUtils.isNotEmpty(markStudentList)) {
+            markStudentService.saveBatch(markStudentList);
+            // 更新mark_paper表student_count字段
+            paperInfo.stream().map(e -> e.get("paperNumber")).forEach(e -> markPaperService.updateStudentCountByExamIdAndPaperNumberAndPaperType(examId, e, paperType));
+        }
+    }
+
     /**
      * 验证机构是否存在
      *

+ 2 - 4
distributed-print/src/main/java/com/qmth/distributed/print/api/BasicExamStudentController.java

@@ -86,10 +86,8 @@ public class BasicExamStudentController {
     @ApiResponses({ @ApiResponse(code = 200, message = "返回信息", response = Result.class) })
     @OperationLogDetail(customizedOperationType = CustomizedOperationTypeEnum.IMPORT)
     public Result basicExamStudentImportSync(@ApiParam(value = "上传文件", required = true) @RequestParam MultipartFile file,
-            @ApiParam(value = "学期id", required = true) @RequestParam String semesterId, @ApiParam(value = "考试id", required = true) @RequestParam String examId) throws Exception {
-        Map<String, Object> map = printCommonService.saveTask(file, SystemConstant.convertIdToLong(semesterId),
-                SystemConstant.convertIdToLong(examId), TaskTypeEnum.STUDENT_IMPORT);
-        map.put("semesterId", SystemConstant.convertIdToLong(semesterId));
+            @ApiParam(value = "考试id", required = true) @RequestParam String examId) throws Exception {
+        Map<String, Object> map = printCommonService.saveTask(SystemConstant.convertIdToLong(examId), TaskTypeEnum.STUDENT_IMPORT);
         map.put("examId", SystemConstant.convertIdToLong(examId));
         return syncBasicExamStudentImportService.importTask(map);
     }

+ 43 - 29
distributed-print/src/main/java/com/qmth/distributed/print/api/mark/MarkSettingController.java

@@ -5,8 +5,11 @@ import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.qmth.boot.api.constant.ApiConstant;
 import com.qmth.distributed.print.business.entity.ExamTaskDetail;
 import com.qmth.distributed.print.business.service.ExamTaskDetailService;
+import com.qmth.distributed.print.business.service.PrintCommonService;
+import com.qmth.distributed.print.business.templete.execute.SyncMarkStudentImportService;
 import com.qmth.teachcloud.common.annotation.OperationLogDetail;
 import com.qmth.teachcloud.common.bean.vo.PaperInfoVo;
+import com.qmth.teachcloud.common.enums.TaskTypeEnum;
 import com.qmth.teachcloud.common.util.ExamTaskUtil;
 import com.qmth.teachcloud.common.util.ServletUtil;
 import com.qmth.teachcloud.mark.dto.mark.manage.MarkManageDto;
@@ -19,17 +22,17 @@ import com.qmth.teachcloud.mark.service.MarkPaperService;
 import com.qmth.teachcloud.common.util.Result;
 import com.qmth.teachcloud.common.util.ResultUtil;
 import com.qmth.teachcloud.mark.service.MarkTaskService;
-import io.swagger.annotations.Api;
-import io.swagger.annotations.ApiOperation;
-import io.swagger.annotations.ApiParam;
+import io.swagger.annotations.*;
 import org.apache.commons.collections4.CollectionUtils;
 import org.springframework.web.bind.annotation.*;
+import org.springframework.web.multipart.MultipartFile;
 
 import javax.annotation.Resource;
 import javax.servlet.http.HttpServletResponse;
 import javax.validation.constraints.Max;
 import javax.validation.constraints.Min;
 import java.util.List;
+import java.util.Map;
 
 /**
  * <p>
@@ -46,24 +49,30 @@ public class MarkSettingController {
 
     @Resource
     private MarkPaperService markPaperService;
+
     @Resource
     private MarkTaskService markTaskService;
+
     @Resource
     private ExamTaskDetailService examTaskDetailService;
 
+    @Resource
+    private PrintCommonService printCommonService;
+
+    @Resource
+    private SyncMarkStudentImportService syncMarkStudentImportService;
+
     /**
      * 评卷设置数据列表
      */
     @ApiOperation(value = "评卷设置数据列表")
     @RequestMapping(value = "/list", method = RequestMethod.POST)
-    public Result list(@ApiParam(value = "考试ID", required = true) @RequestParam Long examId,
-                       @ApiParam(value = "课程代码") @RequestParam(required = false) String courseCode,
-                       @ApiParam(value = "试卷编号") @RequestParam(required = false) String paperNumber,
-                       @ApiParam(value = "提交状态") @RequestParam(required = false) Boolean groupStatus,
-                       @RequestParam @Min(SystemConstant.PAGE_NUMBER_MIN) Integer pageNumber,
-                       @RequestParam @Min(SystemConstant.PAGE_SIZE_MIN) @Max(SystemConstant.PAGE_SIZE_MAX) Integer pageSize) {
+    public Result list(@ApiParam(value = "考试ID", required = true) @RequestParam Long examId, @ApiParam(value = "课程代码") @RequestParam(required = false) String courseCode,
+            @ApiParam(value = "试卷编号") @RequestParam(required = false) String paperNumber, @ApiParam(value = "提交状态") @RequestParam(required = false) Boolean groupStatus,
+            @RequestParam @Min(SystemConstant.PAGE_NUMBER_MIN) Integer pageNumber, @RequestParam @Min(SystemConstant.PAGE_SIZE_MIN) @Max(SystemConstant.PAGE_SIZE_MAX) Integer pageSize) {
         Long schoolId = Long.parseLong(ServletUtil.getRequestHeaderSchoolId().toString());
-        IPage<MarkSettingDto> markSettingDtoIPage = markPaperService.listPaperSetting(examId, courseCode, paperNumber, groupStatus, pageNumber, pageSize);
+        IPage<MarkSettingDto> markSettingDtoIPage = markPaperService.listPaperSetting(examId, courseCode, paperNumber,
+                groupStatus, pageNumber, pageSize);
         for (MarkSettingDto record : markSettingDtoIPage.getRecords()) {
             ExamTaskDetail examTaskDetail = examTaskDetailService.findByExamIdAndCourseCodeAndPaperNumber(record.getExamId(), record.getCourseCode(), record.getPaperNumber());
             List<PaperInfoVo> paperInfoVos = ExamTaskUtil.parsePaperAttachmentPath(examTaskDetail.getPaperAttachmentIds(), record.getPaperType());
@@ -79,8 +88,7 @@ public class MarkSettingController {
      */
     @ApiOperation(value = "评卷设置数据获取")
     @RequestMapping(value = "/paper/get", method = RequestMethod.POST)
-    public Result paperGet(@ApiParam(value = "考试ID", required = true) @RequestParam Long examId,
-                           @ApiParam(value = "试卷编号", required = true) @RequestParam String paperNumber) {
+    public Result paperGet(@ApiParam(value = "考试ID", required = true) @RequestParam Long examId, @ApiParam(value = "试卷编号", required = true) @RequestParam String paperNumber) {
         return ResultUtil.ok(markPaperService.getByExamIdAndPaperNumber(examId, paperNumber));
     }
 
@@ -100,13 +108,11 @@ public class MarkSettingController {
      */
     @ApiOperation(value = "评卷管理数据列表")
     @RequestMapping(value = "/summary", method = RequestMethod.POST)
-    public Result summary(@ApiParam(value = "考试ID", required = true) @RequestParam Long examId,
-                          @ApiParam(value = "课程代码") @RequestParam(required = false) String courseCode,
-                          @ApiParam(value = "试卷编号") @RequestParam(required = false) String paperNumber,
-                          @ApiParam(value = "完成进度") @RequestParam(required = false) Boolean progressStatus,
-                          @RequestParam @Min(SystemConstant.PAGE_NUMBER_MIN) Integer pageNumber,
-                          @RequestParam @Min(SystemConstant.PAGE_SIZE_MIN) @Max(SystemConstant.PAGE_SIZE_MAX) Integer pageSize) {
-        IPage<MarkManageDto> markManageDtoIPage = markTaskService.listPaperManage(examId, courseCode, paperNumber, progressStatus, pageNumber, pageSize);
+    public Result summary(@ApiParam(value = "考试ID", required = true) @RequestParam Long examId, @ApiParam(value = "课程代码") @RequestParam(required = false) String courseCode,
+            @ApiParam(value = "试卷编号") @RequestParam(required = false) String paperNumber, @ApiParam(value = "完成进度") @RequestParam(required = false) Boolean progressStatus,
+            @RequestParam @Min(SystemConstant.PAGE_NUMBER_MIN) Integer pageNumber, @RequestParam @Min(SystemConstant.PAGE_SIZE_MIN) @Max(SystemConstant.PAGE_SIZE_MAX) Integer pageSize) {
+        IPage<MarkManageDto> markManageDtoIPage = markTaskService.listPaperManage(examId, courseCode, paperNumber,
+                progressStatus, pageNumber, pageSize);
         return ResultUtil.ok(markManageDtoIPage);
     }
 
@@ -115,10 +121,8 @@ public class MarkSettingController {
      */
     @ApiOperation(value = "导出评卷员工作量")
     @RequestMapping(value = "/export_marker", method = RequestMethod.POST)
-    public void exportMarker(@ApiParam(value = "考试ID", required = true) @RequestParam Long examId,
-                             @ApiParam(value = "课程代码") @RequestParam(required = false) String courseCode,
-                             @ApiParam(value = "试卷编号") @RequestParam(required = false) String paperNumber,
-                             HttpServletResponse response) {
+    public void exportMarker(@ApiParam(value = "考试ID", required = true) @RequestParam Long examId, @ApiParam(value = "课程代码") @RequestParam(required = false) String courseCode,
+            @ApiParam(value = "试卷编号") @RequestParam(required = false) String paperNumber, HttpServletResponse response) {
         markTaskService.exportMarker(examId, courseCode, paperNumber, response);
     }
 
@@ -127,12 +131,22 @@ public class MarkSettingController {
      */
     @ApiOperation(value = "成绩检查数据列表")
     @RequestMapping(value = "/scoreList", method = RequestMethod.POST)
-    public Result scoreList(@ApiParam(value = "考试ID", required = true) @RequestParam Long examId,
-                            @ApiParam(value = "课程代码") @RequestParam(required = false) String courseCode,
-                            @ApiParam(value = "试卷编号") @RequestParam(required = false) String paperNumber,
-                            @RequestParam @Min(SystemConstant.PAGE_NUMBER_MIN) Integer pageNumber,
-                            @RequestParam @Min(SystemConstant.PAGE_SIZE_MIN) @Max(SystemConstant.PAGE_SIZE_MAX) Integer pageSize) {
-        IPage<CheckScoreListDto> scoreListDtoIPage = markPaperService.listStudentScoreList(examId, courseCode, paperNumber, pageNumber, pageSize);
+    public Result scoreList(@ApiParam(value = "考试ID", required = true) @RequestParam Long examId, @ApiParam(value = "课程代码") @RequestParam(required = false) String courseCode,
+            @ApiParam(value = "试卷编号") @RequestParam(required = false) String paperNumber, @RequestParam @Min(SystemConstant.PAGE_NUMBER_MIN) Integer pageNumber,
+            @RequestParam @Min(SystemConstant.PAGE_SIZE_MIN) @Max(SystemConstant.PAGE_SIZE_MAX) Integer pageSize) {
+        IPage<CheckScoreListDto> scoreListDtoIPage = markPaperService.listStudentScoreList(examId, courseCode,
+                paperNumber, pageNumber, pageSize);
         return ResultUtil.ok(scoreListDtoIPage);
     }
+
+    @ApiOperation(value = "阅卷数据批量导入(同步)")
+    @RequestMapping(value = "/mark_student_import", method = RequestMethod.POST)
+    @ApiResponses({ @ApiResponse(code = 200, message = "返回信息", response = Result.class) })
+    @OperationLogDetail(customizedOperationType = CustomizedOperationTypeEnum.IMPORT)
+    public Result markStudentImport(@ApiParam(value = "上传文件", required = true) @RequestParam MultipartFile file,
+            @ApiParam(value = "考试id", required = true) @RequestParam String examId) throws Exception {
+        Map<String, Object> map = printCommonService.saveTask(file, SystemConstant.convertIdToLong(examId), TaskTypeEnum.MARK_STUDENT_IMPORT);
+        map.put("examId", SystemConstant.convertIdToLong(examId));
+        return syncMarkStudentImportService.importTask(map);
+    }
 }

BIN
distributed-print/src/main/resources/temps/markStudent.xlsx


+ 2 - 0
teachcloud-common/src/main/java/com/qmth/teachcloud/common/enums/TaskTypeEnum.java

@@ -16,6 +16,8 @@ public enum TaskTypeEnum {
 
     STUDENT_IMPORT("学生导入"),
 
+    MARK_STUDENT_IMPORT("阅卷数据导入"),
+
     COURSE_DIMENSION_IMPORT("课程知识点导入"),
 
     CLAZZ_IMPORT("班级导入"),