xiaofei 1 سال پیش
والد
کامیت
af0f681cb1

+ 3 - 0
distributed-print-business/src/main/java/com/qmth/distributed/print/business/service/ExamDetailService.java

@@ -14,6 +14,7 @@ import com.qmth.distributed.print.business.entity.*;
 import com.qmth.distributed.print.business.enums.ExamDataSourceEnum;
 import com.qmth.distributed.print.business.enums.ExamDetailStatusEnum;
 import com.qmth.teachcloud.common.bean.dto.DataPermissionRule;
+import com.qmth.teachcloud.common.entity.BasicExamStudent;
 import com.qmth.teachcloud.common.entity.SysUser;
 import com.qmth.teachcloud.common.entity.TBTask;
 import com.qmth.teachcloud.common.enums.CreatePdfTypeEnum;
@@ -241,4 +242,6 @@ public interface ExamDetailService extends IService<ExamDetail> {
     boolean allExamDetailIsFinish(Long examId, Long courseId, String paperNumber);
 
     List<ExamDetail> listExamDetailByExamIdAndCourseIdAndPaperNumber(Long examId, Long courseId, String paperNumber);
+
+    List<Long> saveImportExamStudent(ExamPrintPlan examPrintPlan, List<BasicExamStudent> basicExamStudentList, Long createId);
 }

+ 2 - 0
distributed-print-business/src/main/java/com/qmth/distributed/print/business/service/ExamTaskService.java

@@ -189,4 +189,6 @@ public interface ExamTaskService extends IService<ExamTask> {
     List<TaskPrintHouseDto> listPrintHouse();
 
     ExamTask getByIdIncludeCourse(Long examTaskId);
+
+    List<ExamTask> listByExamId(Long examId);
 }

+ 71 - 5
distributed-print-business/src/main/java/com/qmth/distributed/print/business/service/impl/ExamDetailServiceImpl.java

@@ -14,6 +14,7 @@ import com.qmth.boot.api.exception.ApiException;
 import com.qmth.distributed.print.business.bean.dto.*;
 import com.qmth.distributed.print.business.bean.dto.initMarkData.ExamDetailCourseInitMarkDto;
 import com.qmth.distributed.print.business.bean.dto.initMarkData.InitExamDetailDto;
+import com.qmth.distributed.print.business.templete.execute.AsyncExamStudentImportService;
 import com.qmth.teachcloud.common.bean.examRule.CodeNameEnableValue;
 import com.qmth.teachcloud.common.bean.examRule.FieldsDto;
 import com.qmth.distributed.print.business.bean.result.ExaminationDetailResult;
@@ -27,10 +28,7 @@ import com.qmth.distributed.print.business.templete.execute.AsyncExaminationImpo
 import com.qmth.teachcloud.common.bean.dto.DataPermissionRule;
 import com.qmth.teachcloud.common.bean.vo.PaperInfoVo;
 import com.qmth.teachcloud.common.contant.SystemConstant;
-import com.qmth.teachcloud.common.entity.BasicAttachment;
-import com.qmth.teachcloud.common.entity.SysOrg;
-import com.qmth.teachcloud.common.entity.SysUser;
-import com.qmth.teachcloud.common.entity.TBTask;
+import com.qmth.teachcloud.common.entity.*;
 import com.qmth.teachcloud.common.enums.*;
 import com.qmth.teachcloud.common.service.*;
 import com.qmth.teachcloud.common.util.*;
@@ -128,6 +126,8 @@ public class ExamDetailServiceImpl extends ServiceImpl<ExamDetailMapper, ExamDet
 
     @Resource
     private AsyncExaminationImportTemplateService asyncExaminationImportTemplateService;
+    @Resource
+    private AsyncExamStudentImportService asyncExamStudentImportService;
 
     @Transactional(rollbackFor = Exception.class)
     @Override
@@ -984,7 +984,8 @@ public class ExamDetailServiceImpl extends ServiceImpl<ExamDetailMapper, ExamDet
             Map<String, Object> map = printCommonService.saveTask(SystemConstant.convertIdToLong(printPlanId), file, TaskTypeEnum.EXAMINATION_IMPORT);
             boolean lock = redisUtil.lock(SystemConstant.REDIS_LOCK_IMPORT_EXAM_DATA + schoolId, SystemConstant.REDIS_LOCK_IMPORT_EXAM_DATA_TIME_OUT);
             if (lock) {
-                asyncExaminationImportTemplateService.importTask(map);
+//                asyncExaminationImportTemplateService.importTask(map);
+                asyncExamStudentImportService.importTask(map);
             }
             TBTask tbTask = Objects.nonNull(map.get(SystemConstant.TASK)) ? (TBTask) map.get(SystemConstant.TASK) : null;
             return tbTask;
@@ -1187,4 +1188,69 @@ public class ExamDetailServiceImpl extends ServiceImpl<ExamDetailMapper, ExamDet
     public List<ExamDetail> listExamDetailByExamIdAndCourseIdAndPaperNumber(Long examId, Long courseId, String paperNumber) {
         return this.baseMapper.listExamDetailByExamIdAndCourseIdAndPaperNumber(examId, courseId, paperNumber);
     }
+
+    @Override
+    public List<Long> saveImportExamStudent(ExamPrintPlan examPrintPlan, List<BasicExamStudent> basicExamStudentList, Long createId) {
+        Map<String, List<BasicExamStudent>> examDetailMap = basicExamStudentList.stream().collect(Collectors.groupingBy(m -> m.getExamPlace().concat(m.getExamRoom()).concat(m.getExamStartTime().toString()).concat(m.getExamEndTime().toString())));
+        List<ExamDetail> examDetailList = new ArrayList<>();
+        List<ExamDetailCourse> examDetailCourseList = new ArrayList<>();
+        List<ExamStudent> examStudentList = new ArrayList<>();
+        // 考点
+        examDetailMap.forEach((examDetailKey, examDetailValues) -> {
+            BasicExamStudent examDetailInfo = examDetailValues.get(0);
+            ExamDetail examDetail = new ExamDetail();
+            examDetail.setId(SystemConstant.getDbUuid());
+            examDetail.setPackageCode("1" + redisCounterUtil.getCounter(examPrintPlan.getSchoolId(), 6, "packageCode"));
+            examDetail.setSchoolId(examPrintPlan.getSchoolId());
+            examDetail.setPrintPlanId(examPrintPlan.getId());
+            examDetail.setPrintPlanName(examPrintPlan.getName());
+            examDetail.setExamId(examPrintPlan.getExamId());
+            examDetail.setExamPlace(examDetailInfo.getExamPlace());
+            examDetail.setExamRoom(examDetailInfo.getExamRoom());
+            examDetail.setStatus(ExamDetailStatusEnum.NEW);
+            examDetail.setTotalSubjects(examDetailValues.size());
+            examDetail.setExamStartTime(examDetailInfo.getExamStartTime());
+            examDetail.setExamEndTime(examDetailInfo.getExamEndTime());
+            examDetail.setExamDataSource(ExamDataSourceEnum.FILE_IMPORT);
+            examDetail.setNormal(true);
+            examDetail.setCreateId(createId);
+            examDetail.setBackupCount(examPrintPlan.getBackupCount());
+            examDetailList.add(examDetail);
+            // 考点课程
+            Map<String, List<BasicExamStudent>> examDetailCourseMap = examDetailValues.stream().collect(Collectors.groupingBy(m -> m.getCourseId().toString().concat(m.getPaperNumber())));
+            examDetailCourseMap.forEach((examDetailCourseKey, examDetailCourseValues) -> {
+                BasicExamStudent examDetailCourseInfo = examDetailCourseValues.get(0);
+                ExamDetailCourse examDetailCourse = new ExamDetailCourse();
+                examDetailCourse.setId(SystemConstant.getDbUuid());
+                examDetailCourse.setSchoolId(examPrintPlan.getSchoolId());
+                examDetailCourse.setExamDetailId(examDetail.getId());
+                examDetailCourse.setCourseId(examDetailCourseInfo.getCourseId());
+                examDetailCourse.setPaperNumber(examDetailCourseInfo.getPaperNumber());
+                examDetailCourse.setCoursePaperId(examDetailCourseInfo.getCoursePaperId());
+                examDetailCourse.setTotalSubjects(examDetailCourseValues.size());
+                examDetailCourse.setCreateId(createId);
+                String clazzName = examDetailCourseValues.stream().filter(m -> StringUtils.isNotBlank(m.getTeachClassName())).map(BasicExamStudent::getTeachClassName).collect(Collectors.joining(","));
+                if (StringUtils.isNotBlank(clazzName)) {
+                    examDetailCourse.setClazzName(clazzName);
+                }
+                examDetailCourseList.add(examDetailCourse);
+
+                // 考生
+                examDetailCourseValues.forEach(s -> {
+                    ExamStudent examStudent = new ExamStudent();
+                    examStudent.setId(SystemConstant.getDbUuid());
+                    examStudent.setSchoolId(examPrintPlan.getSchoolId());
+                    examStudent.setExamId(examPrintPlan.getExamId());
+                    examStudent.setExamDetailCourseId(examDetailCourse.getId());
+                    examStudent.setPaperNumber(s.getPaperNumber());
+                    examStudent.setCoursePaperId(s.getCoursePaperId());
+                    examStudent.setBasicStudentId(s.getId());
+                    examStudent.setCreateId(createId);
+                    examStudent.setCreateTime(System.currentTimeMillis());
+                    examStudentList.add(examStudent);
+                });
+            });
+        });
+        return null;
+    }
 }

+ 7 - 2
distributed-print-business/src/main/java/com/qmth/distributed/print/business/service/impl/ExamTaskServiceImpl.java

@@ -1998,9 +1998,9 @@ public class ExamTaskServiceImpl extends ServiceImpl<ExamTaskMapper, ExamTask> i
     @Override
     public ExamTask getByIdIncludeCourse(Long examTaskId) {
         ExamTask examTask = this.getById(examTaskId);
-        if(examTask != null && examTask.getCourseId() != null){
+        if (examTask != null && examTask.getCourseId() != null) {
             BasicCourse basicCourse = basicCourseService.getById(examTask.getCourseId());
-            if(basicCourse != null){
+            if (basicCourse != null) {
                 examTask.setCourseCode(basicCourse.getCode());
                 examTask.setCourseName(basicCourse.getName());
             }
@@ -2008,6 +2008,11 @@ public class ExamTaskServiceImpl extends ServiceImpl<ExamTaskMapper, ExamTask> i
         return examTask;
     }
 
+    @Override
+    public List<ExamTask> listByExamId(Long examId) {
+        return this.list(new QueryWrapper<ExamTask>().lambda().eq(ExamTask::getExamId, examId));
+    }
+
     private ExamTaskPaperData saveTikuPaperData(Long examId, Long paperId, String uuid, File zipFile) {
         SysUser sysUser = (SysUser) ServletUtil.getRequestUser();
         String zipDestPath = null;

+ 2 - 2
distributed-print-business/src/main/java/com/qmth/distributed/print/business/templete/execute/SyncBasicExamStudentImportService.java → distributed-print-business/src/main/java/com/qmth/distributed/print/business/templete/execute/AsyncBasicExamStudentImportService.java

@@ -44,9 +44,9 @@ import java.util.*;
  * @Date: 2024-02-26
  */
 @Service
-public class SyncBasicExamStudentImportService extends AsyncImportTaskTemplete {
+public class AsyncBasicExamStudentImportService extends AsyncImportTaskTemplete {
 
-    private final static Logger log = LoggerFactory.getLogger(SyncBasicExamStudentImportService.class);
+    private final static Logger log = LoggerFactory.getLogger(AsyncBasicExamStudentImportService.class);
 
     public static final String BEGIN_TITLE = "->开始处理导入文件";
     public static final String EXCEPTION_TITLE = "->数据处理发生异常!";

+ 191 - 0
distributed-print-business/src/main/java/com/qmth/distributed/print/business/templete/execute/AsyncExamStudentImportService.java

@@ -0,0 +1,191 @@
+package com.qmth.distributed.print.business.templete.execute;
+
+import cn.hutool.core.date.DateUtil;
+import com.alibaba.fastjson.JSON;
+import com.qmth.boot.tools.excel.ExcelWriter;
+import com.qmth.boot.tools.excel.enums.ExcelType;
+import com.qmth.distributed.print.business.bean.dto.importFile.BasicExamStudentImport;
+import com.qmth.distributed.print.business.entity.ExamPrintPlan;
+import com.qmth.distributed.print.business.enums.PrintPlanStatusEnum;
+import com.qmth.distributed.print.business.service.*;
+import com.qmth.distributed.print.business.templete.importData.AsyncImportTaskTemplete;
+import com.qmth.distributed.print.business.templete.service.ImportLogicService;
+import com.qmth.teachcloud.common.bean.examRule.CodeNameEnableValue;
+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.BasicExam;
+import com.qmth.teachcloud.common.entity.BasicExamStudent;
+import com.qmth.teachcloud.common.entity.SysUser;
+import com.qmth.teachcloud.common.entity.TBTask;
+import com.qmth.teachcloud.common.enums.ExamModelEnum;
+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 com.qmth.teachcloud.mark.service.MarkPaperService;
+import org.apache.commons.lang3.StringUtils;
+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.InputStream;
+import java.text.MessageFormat;
+import java.util.*;
+
+/**
+ * @Description: 考生字典导入同步任务
+ * @Author: CaoZixuan
+ * @Date: 2024-02-26
+ */
+@Service
+public class AsyncExamStudentImportService extends AsyncImportTaskTemplete {
+
+    private final static Logger log = LoggerFactory.getLogger(AsyncExamStudentImportService.class);
+
+    public static final String BEGIN_TITLE = "->开始处理导入文件";
+    public static final String EXCEPTION_TITLE = "->数据处理发生异常!";
+    public static final String EXCEPTION_DATA = "错误信息:";
+    public static final String FINISH_TITLE = "->数据处理结束,共处理了";
+    public static final String FINISH_TOTAL_SIZE = "条数据,成功";
+    public static final String FINISH_SUCCESS_SIZE = "条数据,失败";
+    public static final String FINISH_ERROR_SIZE = "条数据";
+
+    @Resource
+    private ExamDetailService examDetailService;
+    @Resource
+    private ExamPrintPlanService examPrintPlanService;
+    @Resource
+    private ExamTaskService examTaskService;
+    @Resource
+    private BasicExamStudentService basicExamStudentService;
+    @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");
+        SystemConstant.addSummary(stringJoinerSummary, BEGIN_TITLE);
+        tbTask.setStatus(TaskStatusEnum.RUNNING);
+        TBTaskService tbTaskService = SpringContextHolder.getBean(TBTaskService.class);
+        tbTaskService.updateById(tbTask);
+        int dataCount = 0;
+        int successCount = 0;
+        int errorCount = 0;
+        boolean hasError;
+        List<BasicExamStudentImport> errorDataList;
+
+        try {
+            ImportLogicService importLogicService = SpringContextHolder.getBean(ImportLogicService.class);
+
+            // 执行导入考务数据
+            Map<String, Object> result = importLogicService.executeImportExamStudentLogic(map, tbTask, stringJoinerSummary);
+            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)));
+            hasError = Boolean.parseBoolean(String.valueOf(result.get(SystemConstant.HAS_ERROR_DATA)));
+
+            if (hasError) {
+                SystemConstant.addSummary(stringJoinerSummary, "有异常数据,开始生成错误文件");
+                tbTask.setResult(TaskResultEnum.ERROR);
+                // 有异常数据
+                errorDataList = JSON.parseArray(JSON.toJSONString(result.get(SystemConstant.ERROR_DATA_LIST)),
+                        BasicExamStudentImport.class);
+                try {
+                    String[] columnNames = (String[]) result.get(SystemConstant.COLUMN_NAMES);
+                    File excelFileTemp = SystemConstant.getFileTempVar(SystemConstant.EXCEL_PREFIX);
+                    this.createErrorExcelFile(columnNames, errorDataList, excelFileTemp);
+                    String fileName = SystemConstant.getNanoId() + SystemConstant.EXCEL_PREFIX;
+                    FilePathVo filePathVo = fileUploadService.uploadFile(excelFileTemp, UploadFileEnum.FILE, fileName);
+                    tbTask.setErrorFilePath(JSON.toJSONString(filePathVo));
+                    SystemConstant.addSummary(stringJoinerSummary, "错误文件生成生成,请到\"导入结果查询\"中,下载错误文件");
+                } catch (Exception e) {
+                    SystemConstant.addSummary(stringJoinerSummary, "错误文件生成失败," + e.getMessage());
+                }
+            } else {
+                SystemConstant.addSummary(stringJoinerSummary, "数据校验通过,开始写入数据库");
+                List<BasicExamStudent> basicExamStudentList = JSON.parseArray(JSON.toJSONString(result.get(SystemConstant.DATASOURCE)), BasicExamStudent.class);
+                basicExamStudentService.saveOrUpdateBatch(basicExamStudentList);
+                SystemConstant.addSummary(stringJoinerSummary, "写入基础考生数据库完成,开始生成印刷任务数据");
+
+                ExamPrintPlan examPrintPlan = examPrintPlanService.getById(tbTask.getPrintPlanId());
+                // 组装exam_detail数据
+                List<Long> examDetailIdList = examDetailService.saveImportExamStudent(examPrintPlan, basicExamStudentList, tbTask.getCreateId());
+                // 更改印刷计划状态
+                examPrintPlan.setStatus(PrintPlanStatusEnum.READY);
+                examPrintPlanService.updateById(examPrintPlan);
+                // 按照考场检验命题任务是否全部完成,完成生成pdf
+                SysUser user = (SysUser) map.get(SystemConstant.USER);
+
+                examTaskService.checkDataByExamination(tbTask.getPrintPlanId(), examDetailIdList, user);
+                tbTask.setResult(TaskResultEnum.SUCCESS);
+            }
+        } catch (Exception e) {
+            tbTask.setResult(TaskResultEnum.ERROR);
+            stringJoinerSummary.add(MessageFormat.format("{0}{1}{2}{3}", DateUtil.format(new Date(), SystemConstant.DEFAULT_DATE_PATTERN), EXCEPTION_TITLE, EXCEPTION_DATA, e.getMessage()));
+        } 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));
+            tbTask.setStatus(TaskStatusEnum.FINISH);
+            tbTask.setSummary(stringJoinerSummary.toString());
+            tbTaskService.updateById(tbTask);
+        }
+        return ResultUtil.ok();
+    }
+
+    private void createErrorExcelFile(String[] columnName, List<BasicExamStudentImport> basicExamStudentDtoList, File excelFileTemp) {
+        try {
+            List<String> columnNameList = new ArrayList<>(Arrays.asList(columnName));
+            columnNameList.add("错误信息");
+            String[] columnNames = columnNameList.toArray(new String[0]);
+            List<String[]> columnValues = new ArrayList<>();
+            for (BasicExamStudentImport basicExamStudentImport : basicExamStudentDtoList) {
+                List<String> valueList = new ArrayList<>();
+                for (String title : columnNameList) {
+                    if (title.equals("错误信息")) {
+                        valueList.add(basicExamStudentImport.getErrorMsg());
+                        continue;
+                    }
+                    String value = "";
+                    for (CodeNameEnableValue codeNameEnableValue : basicExamStudentImport.getRequiredFieldList()) {
+                        if (codeNameEnableValue.getName().equals(title)) {
+                            value = codeNameEnableValue.getValue();
+                        }
+                    }
+                    if (StringUtils.isBlank(value)) {
+                        for (CodeNameEnableValue codeNameEnableValue : basicExamStudentImport.getExtendFieldList()) {
+                            if (codeNameEnableValue.getName().equals(title)) {
+                                value = codeNameEnableValue.getValue();
+                            }
+                        }
+                    }
+                    valueList.add(value);
+                }
+                // 错误信息
+                String[] columnValue = valueList.toArray(new String[valueList.size()]);
+                columnValues.add(columnValue);
+            }
+
+            FileOutputStream outputStream = new FileOutputStream(excelFileTemp);
+            ExcelWriter writer = ExcelWriter.create(ExcelType.XLSX);
+            writer.writeDataArrays("考生数据", null, columnNames, columnValues.listIterator());
+            writer.output(outputStream);
+            outputStream.flush();
+            outputStream.close();
+        } catch (Exception e) {
+
+        }
+    }
+
+}

+ 2 - 0
distributed-print-business/src/main/java/com/qmth/distributed/print/business/templete/service/ImportLogicService.java

@@ -1,6 +1,7 @@
 package com.qmth.distributed.print.business.templete.service;
 
 import com.qmth.teachcloud.common.entity.BasicExamStudent;
+import com.qmth.teachcloud.common.entity.TBTask;
 
 import java.util.List;
 import java.util.Map;
@@ -20,6 +21,7 @@ public interface ImportLogicService {
      * 处理考生字典导入
      */
     Map<String, Object> executeImportBasicExamStudentLogic(Map<String, Object> map, StringJoiner stringJoinerSummary);
+    Map<String, Object> executeImportExamStudentLogic(Map<String, Object> map, TBTask tbTask, StringJoiner stringJoinerSummary);
 
     /**
      * 处理考生任课老师导入

+ 258 - 3
distributed-print-business/src/main/java/com/qmth/distributed/print/business/templete/service/impl/ImportLogicServiceImpl.java

@@ -10,10 +10,11 @@ import com.qmth.distributed.print.business.bean.dto.SubjectiveStructDto;
 import com.qmth.distributed.print.business.bean.dto.importFile.BasicExamStudentImport;
 import com.qmth.distributed.print.business.bean.dto.importFile.BasicExamStudentParseDto;
 import com.qmth.distributed.print.business.entity.BasicExamRule;
+import com.qmth.distributed.print.business.entity.ExamPrintPlan;
+import com.qmth.distributed.print.business.entity.ExamTask;
+import com.qmth.distributed.print.business.enums.PrintPlanStatusEnum;
 import com.qmth.distributed.print.business.enums.RequiredFieldsEnum;
-import com.qmth.distributed.print.business.service.BasicExamRuleService;
-import com.qmth.distributed.print.business.service.BasicExamService;
-import com.qmth.distributed.print.business.service.BasicExamStudentService;
+import com.qmth.distributed.print.business.service.*;
 import com.qmth.distributed.print.business.templete.service.ImportLogicService;
 import com.qmth.teachcloud.common.base.BaseEntity;
 import com.qmth.teachcloud.common.bean.dto.mark.MarkUser;
@@ -85,6 +86,12 @@ public class ImportLogicServiceImpl implements ImportLogicService {
     SysRoleService sysRoleService;
     @Resource
     private CommonCacheService commonCacheService;
+    @Resource
+    private TBTaskPdfService tbTaskPdfService;
+    @Resource
+    private ExamPrintPlanService examPrintPlanService;
+    @Resource
+    private ExamTaskService examTaskService;
 
 
     @Transactional
@@ -233,6 +240,194 @@ public class ImportLogicServiceImpl implements ImportLogicService {
         return map;
     }
 
+    @Transactional
+    @Override
+    public Map<String, Object> executeImportExamStudentLogic(Map<String, Object> map, TBTask tbTask, StringJoiner stringJoinerSummary) {
+        SysUser requestUser = (SysUser) map.get(SystemConstant.USER);
+        InputStream inputStream = (InputStream) map.get("inputStream");
+        Long schoolId = requestUser.getSchoolId();
+        ExamPrintPlan examPrintPlan = examPrintPlanService.getById(tbTask.getPrintPlanId());
+        if (examPrintPlan == null) {
+            throw ExceptionResultEnum.ERROR.exception("印刷计划不存在");
+        }
+
+        String printPlanName = examPrintPlan.getName();
+        if (!tbTaskPdfService.countByPrintPlanIdAndEntityId(schoolId, tbTask.getPrintPlanId())) {
+            throw ExceptionResultEnum.ERROR.exception("印刷计划[" + printPlanName + "]有数据正在生成PDF文件,无法导入考务数据");
+        }
+        PrintPlanStatusEnum printPlanStatus = examPrintPlan.getStatus();
+        if (PrintPlanStatusEnum.NEW != printPlanStatus && PrintPlanStatusEnum.READY != printPlanStatus) {
+            throw ExceptionResultEnum.ERROR.exception("印刷计划状态为[" + PrintPlanStatusEnum.NEW.getName() + "、" + PrintPlanStatusEnum.READY.getName() + "]时才可导入,当前状态[" + printPlanStatus.getName() + "]");
+        }
+
+        Long examId = examPrintPlan.getExamId();
+        BasicExam basicExam = basicExamService.getById(examId);
+        if (Objects.isNull(basicExam)) {
+            throw ExceptionResultEnum.ERROR.exception("考试不存在");
+        }
+        Long semesterId = SystemConstant.convertIdToLong(basicExam.getSemesterId());
+
+        // 解析excel文件
+        SystemConstant.addSummary(stringJoinerSummary, "开始解析文件内容");
+        BasicExamStudentParseDto basicExamStudentParseDto;
+        try {
+            basicExamStudentParseDto = this.parseExamStudent(schoolId, inputStream);
+        } catch (Exception e) {
+            SystemConstant.addSummary(stringJoinerSummary, "解析文件内容结束,解析失败。" + e.getMessage());
+            throw ExceptionResultEnum.ERROR.exception(e.getMessage());
+        }
+        SystemConstant.addSummary(stringJoinerSummary, "解析文件内容结束,开始进行数据校验");
+
+        List<BasicExamStudentImport> basicExamStudentImportList = basicExamStudentParseDto.getBasicExamStudentImportList();
+        if (CollectionUtils.isEmpty(basicExamStudentImportList)) {
+            throw ExceptionResultEnum.ERROR.exception("没有可导入数据");
+        }
+
+        List<BasicExamStudent> basicExamStudentList = basicExamStudentService.list(new QueryWrapper<BasicExamStudent>().lambda()
+                .select(BasicExamStudent::getId, BasicExamStudent::getCourseId, BasicExamStudent::getStudentCode, BasicExamStudent::getPaperNumber)
+                .eq(BasicExamStudent::getSchoolId, schoolId).eq(BasicExamStudent::getExamId, examId));
+        Map<String, Long> courseIdStudentCodeMap = basicExamStudentList.stream().collect(Collectors.toMap(k -> k.getCourseId() + SystemConstant.HYPHEN + k.getStudentCode(), BaseEntity::getId));
+
+        // 文件中试卷编号对应多个课程代码
+        Map<String, Long> paperNumberWithCourseCodeInExcelMap = new HashMap<>();
+        Map<String, Long> basicCourseIdMap = new HashMap<>();
+
+        // 课程管理中课程代码-课程名
+        Map<String, BasicCourse> courseCodeNameInBasicCourseMap = new HashMap<>();
+        List<BasicCourse> basicCourseList = basicCourseService.list(new QueryWrapper<BasicCourse>().lambda().eq(BasicCourse::getSchoolId, schoolId));
+        basicCourseList.forEach(e -> courseCodeNameInBasicCourseMap.put(e.getTeachingRoomId().toString().concat(e.getCode()), e));
+        // 是否有错误提示
+        boolean hasError = false;
+
+        List<ExamTask> examTaskList = examTaskService.listByExamId(examId);
+        Map<String, List<ExamTask>> paperNumberMap = examTaskList.stream().collect(Collectors.groupingBy(m -> m.getPaperNumber()));
+
+        List<BasicExamStudent> basicExamStudents = new ArrayList<>();
+        for (BasicExamStudentImport basicExamStudentImport : basicExamStudentImportList) {
+            BasicExamStudent basicExamStudent = new BasicExamStudent();
+            BeanUtils.copyProperties(basicExamStudentImport, basicExamStudent);
+            basicExamStudent.setSchoolId(schoolId);
+            basicExamStudent.setSemesterId(semesterId);
+            basicExamStudent.setExamId(examId);
+            basicExamStudent.setRequiredFields(CollectionUtils.isNotEmpty(basicExamStudentImport.getRequiredFieldList()) ? JSON.toJSONString(basicExamStudentImport.getRequiredFieldList()) : null);
+            basicExamStudent.setExtendFields(CollectionUtils.isNotEmpty(basicExamStudentImport.getExtendFieldList()) ? JSON.toJSONString(basicExamStudentImport.getExtendFieldList()) : null);
+
+            StringJoiner stringJoiner = new StringJoiner(";");
+            // 校验excel内容
+            basicExamStudentImport.getRequiredFieldList().forEach(m -> {
+                if (m.getEnable() && StringUtils.isBlank(m.getValue())) {
+                    stringJoiner.add(m.getName() + "必填");
+                }
+            });
+            if (StringUtils.isNotBlank(basicExamStudentImport.getTeacherCode()) && StringUtils.isBlank(basicExamStudentImport.getTeacherName())) {
+                stringJoiner.add(RequiredFieldsEnum.TEACHER_NAME.getName() + "必填");
+            }
+            if (StringUtils.isNotBlank(basicExamStudentImport.getTeacherName()) && StringUtils.isBlank(basicExamStudentImport.getTeacherCode())) {
+                stringJoiner.add(RequiredFieldsEnum.TEACHER_CODE.getName() + "必填");
+            }
+
+            try {
+                Map<String, Object> timeMap = ConvertUtil.analyzeStartAndEndTime(basicExamStudentImport.getExamDate(), basicExamStudentImport.getExamTime());
+                basicExamStudent.setExamStartTime(Long.valueOf(String.valueOf(timeMap.get("startTime"))));
+                basicExamStudent.setExamEndTime(Long.valueOf(String.valueOf(timeMap.get("endTime"))));
+            } catch (Exception e) {
+                stringJoiner.add("考试日期或考试时间格式错误");
+            }
+
+            // 校验课程
+            String key = basicExamStudentImport.getCourseCode() + SystemConstant.HYPHEN + basicExamStudentImport.getTeachingRoomName();
+            if (!basicCourseIdMap.containsKey(key)) {
+                List<SysOrg> sysOrgList = sysOrgService.getSecondOrg(schoolId, basicExamStudentImport.getTeachingRoomName());
+                if (CollectionUtils.isEmpty(sysOrgList)) {
+                    stringJoiner.add("开课学院[" + basicExamStudentImport.getTeachingRoomName() + "]在学院层级不存在");
+                } else if (sysOrgList.size() == 1) {
+                    SysOrg sysOrg = sysOrgList.get(0);
+                    // 校验课程代码和开课学院
+                    BasicCourse basicCourse = courseCodeNameInBasicCourseMap.get(sysOrg.getId().toString().concat(basicExamStudentImport.getCourseCode()));
+                    if (Objects.isNull(basicCourse)) {
+                        stringJoiner.add("课程代码[" + basicExamStudentImport.getCourseCode() + "]在开课学院[" + basicExamStudentImport.getTeachingRoomName() + "]不存在");
+                    } else {
+                        basicExamStudent.setCourseId(basicCourse.getId());
+                        basicCourseIdMap.put(key, basicCourse.getId());
+                    }
+                } else {
+                    stringJoiner.add("开课学院[" + basicExamStudentImport.getTeachingRoomName() + "]存在多个");
+                }
+            } else {
+                basicExamStudent.setCourseId(basicCourseIdMap.get(key));
+            }
+
+            // 校验试卷编号和课程代码对应关系
+            if (paperNumberWithCourseCodeInExcelMap.containsKey(basicExamStudent.getPaperNumber())) {
+                Long courseId = paperNumberWithCourseCodeInExcelMap.get(basicExamStudent.getPaperNumber());
+                if (!basicExamStudent.getCourseId().equals(courseId)) {
+                    stringJoiner.add(String.format("文件中试卷编号[%s]对应多个不同的课程代码", basicExamStudent.getPaperNumber()));
+                }
+            } else {
+                paperNumberWithCourseCodeInExcelMap.put(basicExamStudent.getPaperNumber(), basicExamStudent.getCourseId());
+            }
+
+            if (paperNumberMap.containsKey(basicExamStudent.getPaperNumber())) {
+                List<ExamTask> examTasks = paperNumberMap.get(basicExamStudent.getPaperNumber());
+                if (examTasks.size() > 1) {
+                    stringJoiner.add(String.format("试卷编号[%s]在考试[%s]下有多条命题任务,请联系管理员处理", basicExamStudent.getPaperNumber(), examId));
+                } else {
+                    Long courseId = paperNumberWithCourseCodeInExcelMap.get(basicExamStudent.getPaperNumber());
+                    ExamTask examTask = examTasks.get(0);
+                    if (!examTask.getCourseId().equals(courseId)) {
+                        stringJoiner.add(String.format("文件中试卷编号[%s]对应课程代码与命题任务中对应课程代码不一致", basicExamStudent.getPaperNumber()));
+                    } else {
+                        basicExamStudent.setCoursePaperId(String.valueOf(examTask.getId()));
+                    }
+                }
+            }
+
+            //校验任课老师
+            if (StringUtils.isNotBlank(basicExamStudentImport.getTeacherCode()) && StringUtils.isNotBlank(basicExamStudentImport.getTeacherName())) {
+                SysUser sysUser = sysUserService.getByLoginName(schoolId, basicExamStudentImport.getTeacherCode());
+                if (sysUser == null) {
+                    stringJoiner.add("任课老师工号[" + basicExamStudentImport.getTeacherCode() + "]不存在");
+                } else {
+                    if (!sysUser.getEnable()) {
+                        stringJoiner.add("任课老师工号[" + basicExamStudentImport.getTeacherCode() + "]已禁用");
+                    } else if (!sysUser.getRealName().equals(basicExamStudentImport.getTeacherName())) {
+                        stringJoiner.add("任课老师[" + basicExamStudentImport.getTeacherName() + "]与用户管理中姓名[" + sysUser.getRealName() + "]不一致");
+                    } else {
+                        basicExamStudent.setTeacherId(sysUser.getId());
+                    }
+                }
+            }
+
+            if (basicExamStudent.getCourseId() != null) {
+                if (courseIdStudentCodeMap.containsKey(basicExamStudent.getCourseId() + SystemConstant.HYPHEN + basicExamStudent.getStudentCode())) {
+                    basicExamStudent.setId(courseIdStudentCodeMap.get(basicExamStudent.getCourseId() + SystemConstant.HYPHEN + basicExamStudent.getStudentCode()));
+                }
+            }
+
+            if (stringJoiner.toString().length() > 0) {
+                basicExamStudentImport.setErrorMsg(stringJoiner.toString());
+            }
+
+            if (!hasError && stringJoiner.toString().length() > 0) {
+                hasError = true;
+            }
+
+            if (stringJoiner.toString().length() == 0) {
+                basicExamStudents.add(basicExamStudent);
+            }
+
+            map.put(SystemConstant.ERROR_DATA_LIST, basicExamStudentImportList);
+            map.put(SystemConstant.DATASOURCE, basicExamStudents);
+            map.put(SystemConstant.DATA_COUNT, basicExamStudentImportList.size());
+            map.put(SystemConstant.SUCCESS_DATA_COUNT, basicExamStudents.size());
+            map.put(SystemConstant.ERROR_DATA_COUNT, basicExamStudentImportList.size() - basicExamStudents.size());
+            map.put(SystemConstant.HAS_ERROR_DATA, hasError);
+            map.put(SystemConstant.COLUMN_NAMES, basicExamStudentParseDto.getColumnNames());
+        }
+
+        return map;
+    }
+
     private BasicExamStudentParseDto parseBasicExamStudent(Long schoolId, InputStream inputStream) {
         ExcelReader excelReader = ExcelReader.create(ExcelType.XLSX, inputStream, 1);
         List<DataMap> dataMapList = null;
@@ -293,6 +488,66 @@ public class ImportLogicServiceImpl implements ImportLogicService {
         return basicExamStudentParseDto;
     }
 
+    private BasicExamStudentParseDto parseExamStudent(Long schoolId, InputStream inputStream) {
+        ExcelReader excelReader = ExcelReader.create(ExcelType.XLSX, inputStream, 1);
+        List<DataMap> dataMapList = null;
+        try {
+            dataMapList = excelReader.getDataMapList();
+        } catch (Exception e) {
+            throw ExceptionResultEnum.ERROR.exception("读取excel内容失败");
+        }
+        BasicExamStudentParseDto basicExamStudentParseDto = new BasicExamStudentParseDto();
+        List<BasicExamStudentImport> list = new ArrayList<>();
+        if (CollectionUtils.isNotEmpty(dataMapList)) {
+            String[] columnNames = excelReader.getColumnNames();
+
+            BasicExamRule basicExamRule = basicExamRuleService.getBySchoolId(schoolId);
+            if (basicExamRule == null) {
+                throw ExceptionResultEnum.ERROR.exception("通用规则未设置");
+            }
+
+            Map<String, EnumResult> requiredMap = basicExamRule.getRequiredFieldList().stream().filter(m -> m.getEnable()).collect(Collectors.toMap(EnumResult::getName, e -> e));
+            Map<String, EnumResult> extendMap = basicExamRule.getExtendFieldList().stream().filter(m -> m.getEnable()).collect(Collectors.toMap(EnumResult::getName, e -> e));
+
+            // 通用规则表头
+            List<String> actualTitleList = Stream.concat(requiredMap.keySet().stream(), extendMap.keySet().stream()).collect(Collectors.toList());
+            if (!CollectionUtils.isEqualCollection(Arrays.asList(columnNames), actualTitleList)) {
+                throw ExceptionResultEnum.ERROR.exception("表头有误,表头字段应为【" + String.join(",", actualTitleList) + "】");
+            }
+
+            basicExamStudentParseDto.setColumnNames(columnNames);
+
+            dataMapList.forEach(m -> {
+                BasicExamStudentImport basicExamStudentImport = new BasicExamStudentImport();
+                Class<BasicExamStudentImport> aClass = (Class<BasicExamStudentImport>) basicExamStudentImport.getClass();
+                for (Map.Entry<String, String> entry : m.entrySet()) {
+                    // 必填字段
+                    if (requiredMap.containsKey(entry.getKey())) {
+                        EnumResult enumResult = requiredMap.get(entry.getKey());
+                        try {
+                            Field declaredField = aClass.getDeclaredField(enumResult.getCode());
+                            declaredField.setAccessible(true);
+                            declaredField.set(basicExamStudentImport, entry.getValue());
+                        } catch (NoSuchFieldException e) {
+                            throw ExceptionResultEnum.ERROR.exception("未获取到表头为[" + entry.getKey() + "]的属性值");
+                        } catch (IllegalAccessException e) {
+                            throw ExceptionResultEnum.ERROR.exception("表头为[" + entry.getKey() + "]的值赋值失败");
+                        }
+                        basicExamStudentImport.getRequiredFieldList().add(new CodeNameEnableDisabledValue(enumResult.getCode(), enumResult.getName(), enumResult.getEnable(), enumResult.getDisabled(), StringUtils.isNotBlank(entry.getValue()) ? entry.getValue() : ""));
+                    }
+                    // 扩展字段
+                    if (extendMap.containsKey(entry.getKey())) {
+                        EnumResult enumResult = extendMap.get(entry.getKey());
+                        basicExamStudentImport.getExtendFieldList().add(new CodeNameEnableDisabledValue(enumResult.getCode(), enumResult.getName(), enumResult.getEnable(), enumResult.getDisabled(), StringUtils.isNotBlank(entry.getValue()) ? entry.getValue() : ""));
+                    }
+                }
+                list.add(basicExamStudentImport);
+            });
+        }
+        basicExamStudentParseDto.setBasicExamStudentImportList(list);
+        return basicExamStudentParseDto;
+    }
+
     @Transactional
     @Override
     public void saveMarkStudent(Long examId, List<BasicExamStudent> basicExamStudentList) {

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

@@ -6,7 +6,7 @@ import com.qmth.distributed.print.business.bean.result.BasicExamStudentResult;
 import com.qmth.distributed.print.business.service.BasicExamStudentService;
 import com.qmth.distributed.print.business.service.PrintCommonService;
 import com.qmth.distributed.print.business.templete.execute.AsyncBasicExamStudentTeacherImportService;
-import com.qmth.distributed.print.business.templete.execute.SyncBasicExamStudentImportService;
+import com.qmth.distributed.print.business.templete.execute.AsyncBasicExamStudentImportService;
 import com.qmth.teachcloud.common.annotation.OperationLogDetail;
 import com.qmth.teachcloud.common.contant.SystemConstant;
 import com.qmth.teachcloud.common.entity.SysUser;
@@ -50,7 +50,7 @@ public class BasicExamStudentController {
     private PrintCommonService printCommonService;
 
     @Resource
-    private SyncBasicExamStudentImportService syncBasicExamStudentImportService;
+    private AsyncBasicExamStudentImportService syncBasicExamStudentImportService;
     @Resource
     private AsyncBasicExamStudentTeacherImportService asyncBasicExamStudentTeacherImportService;
 

+ 12 - 0
teachcloud-common/src/main/java/com/qmth/teachcloud/common/entity/BasicExamStudent.java

@@ -8,6 +8,7 @@ import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
 import com.qmth.teachcloud.common.base.BaseEntity;
 import com.qmth.teachcloud.common.bean.examRule.CodeNameEnableValue;
 import com.qmth.teachcloud.common.enums.BasicExamStudentStatusEnum;
+import com.qmth.teachcloud.common.enums.ExceptionResultEnum;
 import com.qmth.teachcloud.common.enums.UploadFileEnum;
 import io.swagger.annotations.ApiModel;
 import io.swagger.annotations.ApiModelProperty;
@@ -114,6 +115,9 @@ public class BasicExamStudent extends BaseEntity {
     @TableField(exist = false)
     private String statusDisplay;
 
+    @TableField(exist = false)
+    private String coursePaperId;
+
     public Long getSchoolId() {
         return schoolId;
     }
@@ -297,4 +301,12 @@ public class BasicExamStudent extends BaseEntity {
     public void setStatusDisplay(String statusDisplay) {
         this.statusDisplay = statusDisplay;
     }
+
+    public String getCoursePaperId() {
+        return coursePaperId;
+    }
+
+    public void setCoursePaperId(String coursePaperId) {
+        this.coursePaperId = coursePaperId;
+    }
 }