xiaofei 2 lat temu
rodzic
commit
f52905bb31
19 zmienionych plików z 806 dodań i 186 usunięć
  1. 278 0
      distributed-print-business/src/main/java/com/qmth/distributed/print/business/entity/TSyncExamLog.java
  2. 17 0
      distributed-print-business/src/main/java/com/qmth/distributed/print/business/mapper/TSyncExamLogMapper.java
  3. 3 1
      distributed-print-business/src/main/java/com/qmth/distributed/print/business/service/ExamTaskDetailService.java
  4. 20 0
      distributed-print-business/src/main/java/com/qmth/distributed/print/business/service/TSyncExamLogService.java
  5. 32 5
      distributed-print-business/src/main/java/com/qmth/distributed/print/business/service/impl/ExamTaskDetailServiceImpl.java
  6. 6 0
      distributed-print-business/src/main/java/com/qmth/distributed/print/business/service/impl/ExamTaskServiceImpl.java
  7. 120 0
      distributed-print-business/src/main/java/com/qmth/distributed/print/business/service/impl/TSyncExamLogServiceImpl.java
  8. 9 0
      distributed-print-business/src/main/java/com/qmth/distributed/print/business/service/impl/TSyncExamStudentScoreServiceImpl.java
  9. 35 12
      distributed-print-business/src/main/java/com/qmth/distributed/print/business/templete/execute/AsyncScorePushService.java
  10. 14 15
      distributed-print-business/src/main/java/com/qmth/distributed/print/business/templete/push/AsyncPushTaskTemplate.java
  11. 4 2
      distributed-print-business/src/main/java/com/qmth/distributed/print/business/templete/service/PushLogicService.java
  12. 67 73
      distributed-print-business/src/main/java/com/qmth/distributed/print/business/templete/service/impl/PushLogicServiceImpl.java
  13. 1 2
      distributed-print-business/src/main/resources/mapper/ExamCardMapper.xml
  14. 2 1
      distributed-print-business/src/main/resources/mapper/ExamDetailMapper.xml
  15. 2 1
      distributed-print-business/src/main/resources/mapper/ExamStudentMapper.xml
  16. 53 0
      distributed-print-business/src/main/resources/mapper/TSyncExamLogMapper.xml
  17. 78 15
      distributed-print/src/main/java/com/qmth/distributed/print/api/ExamPrintPlanController.java
  18. 58 0
      distributed-print/src/main/java/com/qmth/distributed/print/api/TSyncExamLogController.java
  19. 7 59
      distributed-print/src/main/java/com/qmth/distributed/print/api/TSyncExamStudentScoreController.java

+ 278 - 0
distributed-print-business/src/main/java/com/qmth/distributed/print/business/entity/TSyncExamLog.java

@@ -0,0 +1,278 @@
+package com.qmth.distributed.print.business.entity;
+
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
+import com.qmth.teachcloud.common.contant.SystemConstant;
+import com.qmth.teachcloud.common.enums.TaskResultEnum;
+import com.qmth.teachcloud.common.enums.TaskStatusEnum;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+
+import java.io.File;
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+
+/**
+ * <p>
+ * 同步考生成绩汇总表
+ * </p>
+ */
+@ApiModel(value = "TSyncExamLog对象", description = "同步考生成绩汇总表")
+public class TSyncExamLog implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    @ApiModelProperty(value = "主键")
+    @JsonSerialize(using = ToStringSerializer.class)
+    private Long id;
+
+    @ApiModelProperty(value = "学校id")
+    @JsonSerialize(using = ToStringSerializer.class)
+    private Long schoolId;
+
+    @ApiModelProperty(value = "云阅卷考试id")
+    @JsonSerialize(using = ToStringSerializer.class)
+    private Long examId;
+
+    @ApiModelProperty(value = "学期id")
+    @JsonSerialize(using = ToStringSerializer.class)
+    private Long semesterId;
+
+    @ApiModelProperty(value = "云阅卷考试名称")
+    private String examName;
+
+    @ApiModelProperty(value = "任务状态,INIT:未开始,RUNNING:进行中,FINISH:已完成")
+    @TableField(value = "status")
+    private TaskStatusEnum status;
+
+    @ApiModelProperty(value = "数据结果,SUCCESS:成功,ERROR:失败")
+    @TableField(value = "result")
+    private TaskResultEnum result;
+
+    @ApiModelProperty(value = "开始同步时间")
+    private Long startTime;
+
+    @ApiModelProperty(value = "结束同步时间")
+    private Long endTime;
+
+    @ApiModelProperty(value = "时实信息")
+    private String summary;
+
+    @ApiModelProperty(value = "总课程数")
+    private Integer totalCourses;
+
+    @ApiModelProperty(value = "总命题任务数")
+    private Integer totalExamTasks;
+
+    @ApiModelProperty(value = "总考生数")
+    private Integer totalStudents;
+
+    @ApiModelProperty(value = "成功考生数")
+    private Integer successStudents;
+
+    @ApiModelProperty(value = "失败考生数")
+    private Integer failStudents;
+
+    @ApiModelProperty(value = "错误数据文件路径")
+    @TableField(value = "error_file_path")
+    private String errorFilePath;
+    @ApiModelProperty(value = "创建人id")
+    @JsonSerialize(using = ToStringSerializer.class)
+    private Long createId;
+
+    @ApiModelProperty(value = "创建时间")
+    private Long createTime;
+
+    @TableField(exist = false)
+    @ApiModelProperty(value = "错误文件访问地址")
+    String errorFileUrl;
+
+    @TableField(exist = false)
+    @ApiModelProperty(value = "状态")
+    String statusStr;
+
+    @TableField(exist = false)
+    @ApiModelProperty(value = "结果")
+    String resultStr;
+
+    public TSyncExamLog() {
+    }
+
+    public TSyncExamLog(Long id, Long schoolId, Long examId, Long semesterId, String examName, TaskStatusEnum status, Long createId, Long createTime) {
+        this.id = id;
+        this.schoolId = schoolId;
+        this.examId = examId;
+        this.semesterId = semesterId;
+        this.examName = examName;
+        this.status = status;
+        this.createId = createId;
+        this.createTime = createTime;
+    }
+
+    public Long getId() {
+        return id;
+    }
+
+    public void setId(Long id) {
+        this.id = id;
+    }
+
+    public Long getSchoolId() {
+        return schoolId;
+    }
+
+    public void setSchoolId(Long schoolId) {
+        this.schoolId = schoolId;
+    }
+
+    public Long getSemesterId() {
+        return semesterId;
+    }
+
+    public void setSemesterId(Long semesterId) {
+        this.semesterId = semesterId;
+    }
+
+    public Long getExamId() {
+        return examId;
+    }
+
+    public void setExamId(Long examId) {
+        this.examId = examId;
+    }
+
+    public String getExamName() {
+        return examName;
+    }
+
+    public void setExamName(String examName) {
+        this.examName = examName;
+    }
+
+    public TaskStatusEnum getStatus() {
+        return status;
+    }
+
+    public void setStatus(TaskStatusEnum status) {
+        this.status = status;
+    }
+
+    public TaskResultEnum getResult() {
+        return result;
+    }
+
+    public void setResult(TaskResultEnum result) {
+        this.result = result;
+    }
+
+    public Long getStartTime() {
+        return startTime;
+    }
+
+    public void setStartTime(Long startTime) {
+        this.startTime = startTime;
+    }
+
+    public Long getEndTime() {
+        return endTime;
+    }
+
+    public void setEndTime(Long endTime) {
+        this.endTime = endTime;
+    }
+
+    public String getSummary() {
+        return summary;
+    }
+
+    public void setSummary(String summary) {
+        this.summary = summary;
+    }
+
+    public Integer getTotalCourses() {
+        return totalCourses;
+    }
+
+    public void setTotalCourses(Integer totalCourses) {
+        this.totalCourses = totalCourses;
+    }
+
+    public Integer getTotalExamTasks() {
+        return totalExamTasks;
+    }
+
+    public void setTotalExamTasks(Integer totalExamTasks) {
+        this.totalExamTasks = totalExamTasks;
+    }
+
+    public Integer getTotalStudents() {
+        return totalStudents;
+    }
+
+    public Integer getSuccessStudents() {
+        return successStudents;
+    }
+
+    public void setSuccessStudents(Integer successStudents) {
+        this.successStudents = successStudents;
+    }
+
+    public Integer getFailStudents() {
+        return failStudents;
+    }
+
+    public void setFailStudents(Integer failStudents) {
+        this.failStudents = failStudents;
+    }
+
+    public void setTotalStudents(Integer totalStudents) {
+        this.totalStudents = totalStudents;
+    }
+
+    public String getErrorFilePath() {
+        return errorFilePath;
+    }
+
+    public void setErrorFilePath(String errorFilePath) {
+        this.errorFilePath = errorFilePath;
+    }
+
+    public Long getCreateId() {
+        return createId;
+    }
+
+    public void setCreateId(Long createId) {
+        this.createId = createId;
+    }
+
+    public Long getCreateTime() {
+        return createTime;
+    }
+
+    public void setCreateTime(Long createTime) {
+        this.createTime = createTime;
+    }
+
+    public String getErrorFileUrl() {
+        return errorFileUrl;
+    }
+
+    public void setErrorFileUrl(String errorFileUrl) {
+        this.errorFileUrl = errorFileUrl;
+    }
+
+    public String getStatusStr() {
+        return this.status == null ? null : this.status.getTitle();
+    }
+
+    public String getResultStr() {
+        return this.result == null ? null : this.result.getTitle();
+    }
+
+}

+ 17 - 0
distributed-print-business/src/main/java/com/qmth/distributed/print/business/mapper/TSyncExamLogMapper.java

@@ -0,0 +1,17 @@
+package com.qmth.distributed.print.business.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.qmth.distributed.print.business.entity.TSyncExamLog;
+import org.apache.ibatis.annotations.Param;
+
+/**
+ * <p>
+ * 同步考生成绩汇总表 Mapper 接口
+ * </p>
+ */
+public interface TSyncExamLogMapper extends BaseMapper<TSyncExamLog> {
+
+    IPage<TSyncExamLog> list(Page<TSyncExamLog> iPage, @Param("semesterId") Long semesterId, @Param("examId") Long examId);
+}

+ 3 - 1
distributed-print-business/src/main/java/com/qmth/distributed/print/business/service/ExamTaskDetailService.java

@@ -26,7 +26,7 @@ public interface ExamTaskDetailService extends IService<ExamTaskDetail> {
 
     boolean updatePaper(RelatePaperParam paperParam) throws IOException;
 
-    IPage<ExamTaskDetailDto> list(Long semesterId, Long examId, String relateType, List<Long> printPlanId, String courseCode, String paperNumber, String userName, Long cardRuleId, Integer pageNumber, Integer pageSize);
+    List<ExamTaskDetailDto> list(Long semesterId, Long examId, String relateType, List<Long> printPlanId, String courseCode, String paperNumber, String userName, Long cardRuleId);
     Map listTotal(Long semesterId, Long examId, String relateType, List<Long> printPlanId, String courseCode, String paperNumber, String userName, Long cardRuleId);
 
     List<ExamTaskDetail> listByCardId(Long cardId);
@@ -56,4 +56,6 @@ public interface ExamTaskDetailService extends IService<ExamTaskDetail> {
      * @return
      */
     ExamTaskDetailPdfDownloadDto findPdfDownload(Long examTaskId);
+
+    List<String> listRelateCommonTypes(Long semesterId, Long examId, String relateType, List<Long> idList, String courseCode, String paperNumber, String userName, Long cardRuleId);
 }

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

@@ -0,0 +1,20 @@
+package com.qmth.distributed.print.business.service;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.qmth.distributed.print.business.entity.TSyncExamLog;
+
+/**
+ * <p>
+ * 同步考生成绩汇总表 服务类
+ * </p>
+ */
+public interface TSyncExamLogService extends IService<TSyncExamLog> {
+
+    IPage<TSyncExamLog> list(Page<TSyncExamLog> iPage, Long semesterId, Long examId);
+
+    void syncExam(Long semesterId, Long examId);
+
+    TSyncExamLog selectBySchoolIdAndSemesterIdAndExamId(Long schoolId, Long semesterId, Long examId);
+}

+ 32 - 5
distributed-print-business/src/main/java/com/qmth/distributed/print/business/service/impl/ExamTaskDetailServiceImpl.java

@@ -173,7 +173,7 @@ public class ExamTaskDetailServiceImpl extends ServiceImpl<ExamTaskDetailMapper,
 
     @Transactional
     @Override
-    public boolean updatePaper(RelatePaperParam paperParam) throws IOException {
+    public boolean updatePaper(RelatePaperParam paperParam) {
         ExamPrintPlan examPrintPlan = examPrintPlanService.getById(paperParam.getPrintPlanId());
         if (PrintPlanStatusEnum.END.equals(examPrintPlan.getStatus())) {
             throw ExceptionResultEnum.ERROR.exception("印刷计划已结束,不能修改");
@@ -252,14 +252,13 @@ public class ExamTaskDetailServiceImpl extends ServiceImpl<ExamTaskDetailMapper,
     }
 
     @Override
-    public IPage<ExamTaskDetailDto> list(Long semesterId, Long examId, String relateType, List<Long> printPlanIdList, String courseCode, String paperNumber, String userName, Long cardRuleId, Integer pageNumber, Integer pageSize) {
+    public List<ExamTaskDetailDto> list(Long semesterId, Long examId, String relateType, List<Long> printPlanIdList, String courseCode, String paperNumber, String userName, Long cardRuleId) {
         userName = SystemConstant.translateSpecificSign(userName);
         Long schoolId = Long.valueOf(ServletUtil.getRequestHeaderSchoolId().toString());
         SysUser requestUser = (SysUser) ServletUtil.getRequestUser();
         DataPermissionRule dpr = basicRoleDataPermissionService.findDataPermission(schoolId, requestUser.getId(), ServletUtil.getRequest().getServletPath());
-        Page<ExamTaskDetailDto> page = new Page<>(pageNumber, pageSize);
-        IPage<ExamTaskDetailDto> examDetailDtoIPage = this.baseMapper.listPage(page, schoolId, semesterId, examId, relateType, printPlanIdList, courseCode, paperNumber, userName, cardRuleId, dpr);
-        examDetailDtoIPage.getRecords().stream().map(m -> {
+        List<ExamTaskDetailDto> examDetailDtoIPage = this.baseMapper.listPage(schoolId, semesterId, examId, relateType, printPlanIdList, courseCode, paperNumber, userName, cardRuleId, dpr);
+        examDetailDtoIPage.stream().map(m -> {
             String paperType = StringUtils.isBlank(m.getRelatePaperType()) ? null : m.getRelatePaperType();
             Long printPlanIdT = Long.valueOf(m.getPrintPlanId());
             String courseCodeT = m.getCourseCode();
@@ -502,6 +501,34 @@ public class ExamTaskDetailServiceImpl extends ServiceImpl<ExamTaskDetailMapper,
         return examTaskDetailMapper.findPdfDownload(examTaskId);
     }
 
+    @Override
+    public List<String> listRelateCommonTypes(Long semesterId, Long examId, String relateType, List<Long> idList, String courseCode, String paperNumber, String userName, Long cardRuleId) {
+        userName = SystemConstant.translateSpecificSign(userName);
+        Long schoolId = Long.valueOf(ServletUtil.getRequestHeaderSchoolId().toString());
+        SysUser requestUser = (SysUser) ServletUtil.getRequestUser();
+        DataPermissionRule dpr = basicRoleDataPermissionService.findDataPermission(schoolId, requestUser.getId(), ServletUtil.getRequest().getServletPath());
+        List<ExamTaskDetailDto> examDetailDtoList = this.baseMapper.listPage(schoolId, semesterId, examId, relateType, idList, courseCode, paperNumber, userName, cardRuleId, dpr);
+        List<String> commonPaperTypes = new ArrayList<>();
+        if (!examDetailDtoList.isEmpty()) {
+            // 所有未曝光类型不为空的数据
+            List<String> unposedPaperList = examDetailDtoList.stream().filter(m -> StringUtils.isNotBlank(m.getUnexposedPaperType())).map(m -> m.getUnexposedPaperType()).collect(Collectors.toList());
+            if(examDetailDtoList.size() == unposedPaperList.size()){
+                // 取所有命题任务未曝光类型的交集
+                List<String> basePaperTypes = Arrays.asList(unposedPaperList.get(0).split(","));
+                for (String basePaperType : basePaperTypes) {
+                    for (String s : unposedPaperList) {
+                        List<String> particPaperTypes = Arrays.asList(s.split(","));
+                        if(!particPaperTypes.contains(basePaperType)){
+                            break;
+                        }
+                    }
+                    commonPaperTypes.add(basePaperType);
+                }
+            }
+        }
+        return commonPaperTypes;
+    }
+
     /**
      * 卷库校验
      *

+ 6 - 0
distributed-print-business/src/main/java/com/qmth/distributed/print/business/service/impl/ExamTaskServiceImpl.java

@@ -644,6 +644,12 @@ public class ExamTaskServiceImpl extends ServiceImpl<ExamTaskMapper, ExamTask> i
             }
         }
 
+        // 异常抛出 by 20230214
+        String errorMsg = stringJoiner.toString();
+        if(errorMsg.length()>0){
+            throw ExceptionResultEnum.ERROR.exception(errorMsg);
+        }
+
         // 设置重复信息,页面做二次校验
         examTaskImportDto.setErrorMsg(stringJoiner.toString());
         examTaskImportDto.setTasks(tasks);

+ 120 - 0
distributed-print-business/src/main/java/com/qmth/distributed/print/business/service/impl/TSyncExamLogServiceImpl.java

@@ -0,0 +1,120 @@
+package com.qmth.distributed.print.business.service.impl;
+
+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.qmth.distributed.print.business.entity.TSyncExamLog;
+import com.qmth.distributed.print.business.entity.TSyncStmmsExam;
+import com.qmth.distributed.print.business.mapper.TSyncExamLogMapper;
+import com.qmth.distributed.print.business.service.TSyncExamLogService;
+import com.qmth.distributed.print.business.service.TSyncStmmsExamService;
+import com.qmth.distributed.print.business.templete.execute.AsyncScorePushService;
+import com.qmth.teachcloud.common.contant.SystemConstant;
+import com.qmth.teachcloud.common.entity.SysUser;
+import com.qmth.teachcloud.common.enums.ExceptionResultEnum;
+import com.qmth.teachcloud.common.enums.TaskStatusEnum;
+import com.qmth.teachcloud.common.service.TeachcloudCommonService;
+import com.qmth.teachcloud.common.util.ServletUtil;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.BeanUtils;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.Resource;
+import java.util.List;
+import java.util.stream.Collectors;
+
+@Service
+public class TSyncExamLogServiceImpl extends ServiceImpl<TSyncExamLogMapper, TSyncExamLog> implements TSyncExamLogService {
+
+    @Resource
+    AsyncScorePushService asyncScorePushService;
+
+    @Resource
+    private TSyncStmmsExamService tSyncStmmsExamService;
+
+    @Resource
+    private TeachcloudCommonService teachcloudCommonService;
+
+    @Override
+    public IPage<TSyncExamLog> list(Page<TSyncExamLog> iPage, Long semesterId, Long examId) {
+        if (semesterId == null) {
+            throw ExceptionResultEnum.ERROR.exception("请选择学期");
+        }
+        if (examId == null) {
+            throw ExceptionResultEnum.ERROR.exception("请选择考试");
+        }
+
+        Long schoolId = Long.parseLong(ServletUtil.getRequestHeaderSchoolId().toString());
+        IPage<TSyncExamLog> examLogResultIPage = this.baseMapper.list(iPage, semesterId, examId);
+        for (TSyncExamLog record : examLogResultIPage.getRecords()) {
+            TSyncExamLog tSyncExamLog = this.selectBySchoolIdAndSemesterIdAndExamId(schoolId, semesterId, record.getExamId());
+            if (tSyncExamLog == null) {
+                TSyncStmmsExam tSyncStmmsExam = tSyncStmmsExamService.getBySchoolIdAndExamId(schoolId, examId);
+                if (tSyncStmmsExam != null) {
+                    record.setExamName(tSyncStmmsExam.getExamName());
+                }
+            } else {
+                BeanUtils.copyProperties(tSyncExamLog, record);
+            }
+            // 拼接错误日志访问url
+            if (StringUtils.isNotBlank(record.getErrorFilePath())) {
+                record.setErrorFileUrl(teachcloudCommonService.filePreview(record.getErrorFilePath()));
+            }
+        }
+        return examLogResultIPage;
+    }
+
+    @Override
+    public void syncExam(Long semesterId, Long examId) {
+        if (semesterId == null) {
+            throw ExceptionResultEnum.ERROR.exception("请选择学期");
+        }
+        if (examId == null) {
+            throw ExceptionResultEnum.ERROR.exception("请选择考试");
+        }
+
+        SysUser sysUser = (SysUser) ServletUtil.getRequestUser();
+
+        // 校验任务是否进行中
+        QueryWrapper<TSyncExamLog> queryWrapper = new QueryWrapper<>();
+        queryWrapper.lambda().eq(TSyncExamLog::getSemesterId, semesterId)
+                .eq(TSyncExamLog::getExamId, examId);
+        List<TSyncExamLog> tSyncExamLogList = this.list(queryWrapper);
+        if (!tSyncExamLogList.isEmpty()) {
+            List<TSyncExamLog> notFinishTsyncExamLogList = tSyncExamLogList.stream().filter(m -> !TaskStatusEnum.FINISH.equals(m.getStatus())).collect(Collectors.toList());
+            if (!notFinishTsyncExamLogList.isEmpty()) {
+                throw ExceptionResultEnum.ERROR.exception("当前考试有同步任务未结束,请稍候再试");
+            }
+
+            // 刪除历史数据
+            List<TSyncExamLog> finishTsyncExamLogList = tSyncExamLogList.stream().filter(m -> TaskStatusEnum.FINISH.equals(m.getStatus())).collect(Collectors.toList());
+            if (!finishTsyncExamLogList.isEmpty()) {
+                UpdateWrapper<TSyncExamLog> updateWrapper = new UpdateWrapper<>();
+                updateWrapper.lambda().eq(TSyncExamLog::getSchoolId, sysUser.getSchoolId())
+                        .eq(TSyncExamLog::getSemesterId, semesterId)
+                        .eq(TSyncExamLog::getExamId, examId);
+                this.remove(updateWrapper);
+            }
+        }
+
+        TSyncStmmsExam tSyncStmmsExam = tSyncStmmsExamService.getBySchoolIdAndExamId(sysUser.getSchoolId(), examId);
+        String examName = tSyncStmmsExam == null ? null : tSyncStmmsExam.getExamName();
+        TSyncExamLog tSyncExamLog = new TSyncExamLog(SystemConstant.getDbUuid(), sysUser.getSchoolId(), examId, semesterId, examName, TaskStatusEnum.INIT, sysUser.getId(), System.currentTimeMillis());
+        boolean isSave = this.save(tSyncExamLog);
+        if (!isSave) {
+            throw ExceptionResultEnum.ERROR.exception("创建同步任务失败,请联系管理员");
+        }
+        asyncScorePushService.pushTask(tSyncExamLog);
+    }
+
+    @Override
+    public TSyncExamLog selectBySchoolIdAndSemesterIdAndExamId(Long schoolId, Long semesterId, Long examId) {
+        QueryWrapper<TSyncExamLog> queryWrapper = new QueryWrapper<>();
+        queryWrapper.lambda().eq(TSyncExamLog::getSchoolId, schoolId)
+                .eq(TSyncExamLog::getSemesterId, semesterId)
+                .eq(TSyncExamLog::getExamId, examId);
+        return this.getOne(queryWrapper);
+    }
+}

+ 9 - 0
distributed-print-business/src/main/java/com/qmth/distributed/print/business/service/impl/TSyncExamStudentScoreServiceImpl.java

@@ -63,6 +63,15 @@ public class TSyncExamStudentScoreServiceImpl extends ServiceImpl<TSyncExamStude
      */
     @Override
     public IPage<TSyncExamStudentScoreResult> list(IPage<Map> iPage, Long semesterId, Long examId, Long clazzId, String courseCode) {
+        if(semesterId == null){
+            throw ExceptionResultEnum.ERROR.exception("请选择学期");
+        }
+        if(examId == null){
+            throw ExceptionResultEnum.ERROR.exception("请选择考试");
+        }
+        if(StringUtils.isBlank(courseCode)){
+            throw ExceptionResultEnum.ERROR.exception("请选择课程");
+        }
         SysUser sysUser = (SysUser) ServletUtil.getRequestUser();
         IPage<TSyncExamStudentScoreResult> list = tSyncExamStudentScoreMapper.list(iPage, sysUser.getSchoolId(), semesterId, examId, clazzId, courseCode);
         list.getRecords().stream().map(m -> {

+ 35 - 12
distributed-print-business/src/main/java/com/qmth/distributed/print/business/templete/execute/AsyncScorePushService.java

@@ -3,7 +3,9 @@ package com.qmth.distributed.print.business.templete.execute;
 import cn.hutool.core.date.DateUtil;
 import com.qmth.boot.api.exception.ApiException;
 import com.qmth.distributed.print.business.entity.TBSyncTask;
+import com.qmth.distributed.print.business.entity.TSyncExamLog;
 import com.qmth.distributed.print.business.service.TBSyncTaskService;
+import com.qmth.distributed.print.business.service.TSyncExamLogService;
 import com.qmth.distributed.print.business.templete.push.AsyncPushTaskTemplate;
 import com.qmth.distributed.print.business.templete.service.PushLogicService;
 import com.qmth.teachcloud.common.contant.SpringContextHolder;
@@ -37,31 +39,52 @@ public class AsyncScorePushService extends AsyncPushTaskTemplate {
     public static final String OBJ_TITLE = "成绩信息";
 
     @Override
-    public Result pushTask(Map<String, Object> map) {
-        TBSyncTask tbSyncTask = (TBSyncTask) map.get(SystemConstant.TB_SYNC_TASK);
+    public Result pushTask(TSyncExamLog tSyncExamLog) {
         StringJoiner stringJoinerSummary = new StringJoiner("\n")
                 .add(MessageFormat.format("{0}{1}{2}", DateUtil.format(new Date(), SystemConstant.DEFAULT_DATE_PATTERN), BEGIN_TITLE, OBJ_TITLE));
-        tbSyncTask.setStatus(TaskStatusEnum.RUNNING);
-        TBSyncTaskService tbSyncTaskService = SpringContextHolder.getBean(TBSyncTaskService.class);
-        tbSyncTaskService.updateById(tbSyncTask);
+        tSyncExamLog.setStatus(TaskStatusEnum.RUNNING);
+        tSyncExamLog.setStartTime(System.currentTimeMillis());
+        TSyncExamLogService tSyncExamLogService = SpringContextHolder.getBean(TSyncExamLogService.class);
+        tSyncExamLogService.updateById(tSyncExamLog);
         try {
             PushLogicService pushLogicService = SpringContextHolder.getBean(PushLogicService.class);
-            Map<String, Object> result = pushLogicService.executeScorePushLogic(map);
-            stringJoinerSummary.add(MessageFormat.format("{0}{1}{2}{3}{4}{5}{6}", DateUtil.format(new Date(), SystemConstant.DEFAULT_DATE_PATTERN), FINISH_TITLE, Integer.parseInt(String.valueOf(result.get("count"))), SUCCESS_TITLE, Integer.parseInt(String.valueOf(result.get("correct"))), FINISH_SIZE, Objects.nonNull(result.get("error")) ? (String) result.get("error") : ""));
-            tbSyncTask.setResult(TaskResultEnum.SUCCESS);
+            Map<String, Object> result = pushLogicService.executeScorePushLogic(tSyncExamLog);
+            // 总考生数
+            Integer count = Integer.parseInt(String.valueOf(result.get("count")));
+            tSyncExamLog.setTotalStudents(count);
+
+            // 成功考生数
+            Integer correct = Integer.parseInt(String.valueOf(result.get("correct")));
+            tSyncExamLog.setSuccessStudents(correct);
+            // 失败考生数
+            if(result.containsKey("errorCount")){
+                Integer errorCount = Integer.parseInt(String.valueOf(result.get("errorCount")));
+                tSyncExamLog.setFailStudents(errorCount);
+            } else {
+                tSyncExamLog.setFailStudents(0);
+            }
+
+            // 总课程数
+            Integer courses = Integer.parseInt(String.valueOf(result.get("courses")));
+            tSyncExamLog.setTotalCourses(courses);
+
+            stringJoinerSummary.add(MessageFormat.format("{0}{1}{2}{3}{4}{5}{6}", DateUtil.format(new Date(), SystemConstant.DEFAULT_DATE_PATTERN), FINISH_TITLE, count, SUCCESS_TITLE, Integer.parseInt(String.valueOf(result.get("correct"))), FINISH_SIZE, Objects.nonNull(result.get("error")) ? (String) result.get("error") : ""));
+            tSyncExamLog.setEndTime(System.currentTimeMillis());
+            tSyncExamLog.setResult(TaskResultEnum.SUCCESS);
         } catch (Exception e) {
             log.error(SystemConstant.LOG_ERROR, e);
             stringJoinerSummary.add(MessageFormat.format("{0}{1}{2}{3}", DateUtil.format(new Date(), SystemConstant.DEFAULT_DATE_PATTERN), EXCEPTION_TITLE, EXCEPTION_DATA, e.getMessage()));
-            tbSyncTask.setResult(TaskResultEnum.ERROR);
+            tSyncExamLog.setEndTime(System.currentTimeMillis());
+            tSyncExamLog.setResult(TaskResultEnum.ERROR);
             if (e instanceof ApiException) {
                 ResultUtil.error((ApiException) e, e.getMessage());
             } else {
                 ResultUtil.error(e.getMessage());
             }
         } finally {//生成txt文件
-            tbSyncTask.setSummary(stringJoinerSummary.toString());
-            super.createTxt(tbSyncTask);
+            tSyncExamLog.setSummary(stringJoinerSummary.toString());
+            super.createTxt(tSyncExamLog);
         }
-        return ResultUtil.ok(map);
+        return ResultUtil.ok(tSyncExamLog);
     }
 }

+ 14 - 15
distributed-print-business/src/main/java/com/qmth/distributed/print/business/templete/push/AsyncPushTaskTemplate.java

@@ -3,8 +3,8 @@ package com.qmth.distributed.print.business.templete.push;
 import cn.hutool.core.date.DateUtil;
 import com.alibaba.fastjson.JSONObject;
 import com.qmth.boot.api.exception.ApiException;
-import com.qmth.distributed.print.business.entity.TBSyncTask;
-import com.qmth.distributed.print.business.service.TBSyncTaskService;
+import com.qmth.distributed.print.business.entity.TSyncExamLog;
+import com.qmth.distributed.print.business.service.TSyncExamLogService;
 import com.qmth.teachcloud.common.contant.SpringContextHolder;
 import com.qmth.teachcloud.common.contant.SystemConstant;
 import com.qmth.teachcloud.common.enums.TaskResultEnum;
@@ -18,7 +18,6 @@ import org.springframework.scheduling.annotation.Async;
 import java.io.IOException;
 import java.text.MessageFormat;
 import java.util.Date;
-import java.util.Map;
 import java.util.StringJoiner;
 
 /**
@@ -39,37 +38,37 @@ public abstract class AsyncPushTaskTemplate {
     /**
      * 异步导入任务
      *
-     * @param map
+     * @param tSyncExamLog
      * @return
      * @throws IOException
      */
     @Async
-    public abstract Result pushTask(Map<String, Object> map) throws IOException, Exception;
+    public abstract Result pushTask(TSyncExamLog tSyncExamLog) throws Exception;
 
     /**
      * 创建txt文件
      *
-     * @param tbSyncTask
+     * @param tSyncExamLog
      */
-    public void createTxt(TBSyncTask tbSyncTask) {
+    public void createTxt(TSyncExamLog tSyncExamLog) {
         try {
-            JSONObject json = SystemConstant.createTxt(tbSyncTask.getSummary());
-            tbSyncTask.setReportFilePath(json.toJSONString());
+            JSONObject json = SystemConstant.createTxt(tSyncExamLog.getSummary());
+            tSyncExamLog.setErrorFilePath(json.toJSONString());
         } catch (Exception e) {
             log.error(SystemConstant.LOG_ERROR, e);
-            StringJoiner stringJoinerSummary = new StringJoiner("").add(tbSyncTask.getSummary()).add("\n");
+            StringJoiner stringJoinerSummary = new StringJoiner("").add(tSyncExamLog.getSummary()).add("\n");
             stringJoinerSummary.add(MessageFormat.format("{0}{1}{2}{3}", DateUtil.format(new Date(), SystemConstant.DEFAULT_DATE_PATTERN), EXCEPTION_CREATE_TXT_TITLE, EXCEPTION_DATA, e.getMessage()));
-            tbSyncTask.setSummary(stringJoinerSummary.toString());
-            tbSyncTask.setResult(TaskResultEnum.ERROR);
+            tSyncExamLog.setSummary(stringJoinerSummary.toString());
+            tSyncExamLog.setResult(TaskResultEnum.ERROR);
             if (e instanceof ApiException) {
                 ResultUtil.error((ApiException) e, e.getMessage());
             } else {
                 ResultUtil.error(e.getMessage());
             }
         } finally {
-            TBSyncTaskService tbSyncTaskService = SpringContextHolder.getBean(TBSyncTaskService.class);
-            tbSyncTask.setStatus(TaskStatusEnum.FINISH);
-            tbSyncTaskService.updateById(tbSyncTask);
+            TSyncExamLogService tSyncExamLogService = SpringContextHolder.getBean(TSyncExamLogService.class);
+            tSyncExamLog.setStatus(TaskStatusEnum.FINISH);
+            tSyncExamLogService.updateById(tSyncExamLog);
         }
     }
 }

+ 4 - 2
distributed-print-business/src/main/java/com/qmth/distributed/print/business/templete/service/PushLogicService.java

@@ -1,5 +1,7 @@
 package com.qmth.distributed.print.business.templete.service;
 
+import com.qmth.distributed.print.business.entity.TSyncExamLog;
+
 import java.util.Map;
 
 /**
@@ -12,8 +14,8 @@ public interface PushLogicService {
     /**
      * 成绩查询推送异步任务处理方法
      *
-     * @param map 任务源
+     * @param tSyncExamLog 任务源
      * @return 结果
      */
-    Map<String, Object> executeScorePushLogic(Map<String, Object> map) throws Exception;
+    Map<String, Object> executeScorePushLogic(TSyncExamLog tSyncExamLog) throws Exception;
 }

+ 67 - 73
distributed-print-business/src/main/java/com/qmth/distributed/print/business/templete/service/impl/PushLogicServiceImpl.java

@@ -1,21 +1,17 @@
 package com.qmth.distributed.print.business.templete.service.impl;
 
-import com.alibaba.fastjson.JSONObject;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.qmth.distributed.print.business.entity.TSyncExamLog;
 import com.qmth.distributed.print.business.entity.TSyncExamStudentScore;
-import com.qmth.distributed.print.business.entity.TeachClazz;
 import com.qmth.distributed.print.business.enums.ImageTrajectoryEnum;
 import com.qmth.distributed.print.business.service.ExamStudentService;
 import com.qmth.distributed.print.business.service.TSyncExamStudentScoreService;
 import com.qmth.distributed.print.business.service.TeachClazzService;
 import com.qmth.distributed.print.business.templete.service.PushLogicService;
 import com.qmth.teachcloud.common.contant.SystemConstant;
-import com.qmth.teachcloud.common.entity.BasicClazz;
-import com.qmth.teachcloud.common.entity.BasicMajor;
 import com.qmth.teachcloud.common.entity.SysUser;
 import com.qmth.teachcloud.common.enums.ExceptionResultEnum;
 import com.qmth.teachcloud.common.service.BasicClazzService;
-import com.qmth.teachcloud.common.service.BasicMajorService;
 import com.qmth.teachcloud.common.sync.CloudMarkingTaskUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -24,10 +20,8 @@ import org.springframework.transaction.annotation.Transactional;
 import org.springframework.util.LinkedMultiValueMap;
 
 import javax.annotation.Resource;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
+import java.util.*;
+import java.util.concurrent.Semaphore;
 import java.util.concurrent.atomic.AtomicInteger;
 
 /**
@@ -54,85 +48,85 @@ public class PushLogicServiceImpl implements PushLogicService {
     @Resource
     ExamStudentService examStudentService;
 
-    @Resource
-    BasicMajorService basicMajorService;
-
     /**
      * 成绩查询推送异步任务处理方法
      *
-     * @param map 任务源
+     * @param tSyncExamLog 任务源
      * @return
-     * @throws IllegalAccessException
      */
     @Override
     @Transactional
-    public Map<String, Object> executeScorePushLogic(Map<String, Object> map) throws Exception {
-        SysUser sysUser = (SysUser) map.get(SystemConstant.USER);
-        Long schoolId = sysUser.getSchoolId();
-        LinkedMultiValueMap<Long, Integer> semesterExamIdMap = (LinkedMultiValueMap<Long, Integer>) map.get("semesterExamIdMap");
+    public Map<String, Object> executeScorePushLogic(TSyncExamLog tSyncExamLog) {
+        Long schoolId = tSyncExamLog.getSchoolId();
+        Long semesterId = tSyncExamLog.getSemesterId();
+        Integer examId = Math.toIntExact(tSyncExamLog.getExamId());
         List<TSyncExamStudentScore> tSyncExamStudentScoreList = new ArrayList<>();
         List<String> errorTSyncExamStudentScoreList = new ArrayList<>();
-        AtomicInteger count = new AtomicInteger(0);
+        Set<String> courseList = new HashSet<>();
+        Map<String, Object> map = new HashMap<>();
         try {
-            semesterExamIdMap.forEach((k, v) -> {
-                for (Integer examId : v) {
-                    int totalCount = stmmsUtils.getStudentCount(schoolId, examId, null, null, null, null, null, null, null, true);
-                    count.set(count.get() + totalCount);
-                    log.info("云阅卷:考试成绩考生数量查询接口调用,返回数量:{}", totalCount);
-                    if (totalCount > 0) {
-                        int pageSize = stmmsUtils.getDefaultPageSize();
-                        int mod = totalCount % pageSize;
-                        int pageNos = mod == 0 ? totalCount / pageSize : totalCount / pageSize + 1;
-                        for (int i = 1; i <= pageNos; i++) {
-                            List<Map> students = stmmsUtils.getStudentScore(schoolId, examId, null, null, null, null, null, null, null, true, i, pageSize);
-                            for (Map student : students) {
-                                try {
-                                    Long orgId = null, clazzId = null;
-                                    String clazzName = "";
-                                    String majorName = "";
-                                    if (Objects.nonNull(student.get("studentCode")) && !Objects.equals("无", student.get("studentCode"))) {
-                                        String studentCode = String.valueOf(student.get("studentCode"));
-                                        String subjectCode = String.valueOf(student.get("subjectCode"));
-                                        String examNumber = String.valueOf(student.get("examNumber"));
-//                                        Long printPlanId = Long.valueOf(student.get("examCode").toString()); // 计划ID
-
-                                        // 分布式印刷系统内部考生信息
-                                        List<Map> studentInfos = examStudentService.listStudentScoreSync(schoolId, studentCode, examNumber, subjectCode);
-                                        if (studentInfos == null || studentInfos.size() == 0) {
-                                            throw ExceptionResultEnum.ERROR.exception("未找到此考生信息");
-                                        }
-                                        Map dpsPrintStuMap = studentInfos.get(0);
-
-                                        // 组装本系统内考生信息
-                                        clazzId = dpsPrintStuMap.get("clazzId") == null || "".equals(dpsPrintStuMap.get("clazzId")) ? null : Long.parseLong(String.valueOf(dpsPrintStuMap.get("clazzId")));
-                                        clazzName = String.valueOf(dpsPrintStuMap.get("clazzName"));
-                                        majorName = String.valueOf(dpsPrintStuMap.get("majorName"));
-                                        student.put("clazzId",clazzId);
-                                        student.put("clazzName",clazzName);
-                                        student.put("majorName",majorName);
-                                    }
-
-                                    student.put(SystemConstant.SCHOOL_ID, schoolId);
-                                    student.put("semesterId", k);
-                                    student.put("orgId", orgId);
-                                    student.put("userId", sysUser.getId());
-                                    tSyncExamStudentScoreList.add(new TSyncExamStudentScore(student));
-                                } catch (Exception e) {
-                                    log.info("同步学生成绩信息失败:{}", e.getMessage());
-                                    errorTSyncExamStudentScoreList.add(student.get("name") + "," + student.get("examNumber") + "\r\n");
+            int totalCount = stmmsUtils.getStudentCount(schoolId, examId, null, null, null, null, null, null, null, true);
+            log.info("云阅卷:考试成绩考生数量查询接口调用,返回数量:{}", totalCount);
+            if (totalCount > 0) {
+                int pageSize = stmmsUtils.getDefaultPageSize();
+                int mod = totalCount % pageSize;
+                int pageNos = mod == 0 ? totalCount / pageSize : totalCount / pageSize + 1;
+                for (int i = 1; i <= pageNos; i++) {
+                    List<Map> students = stmmsUtils.getStudentScore(schoolId, examId, null, null, null, null, null, null, null, true, i, pageSize);
+                    for (Map student : students) {
+                        try {
+                            Long orgId = null, clazzId = null;
+                            String clazzName = "";
+                            String majorName = "";
+                            if (Objects.nonNull(student.get("studentCode")) && !Objects.equals("无", student.get("studentCode"))) {
+                                String studentCode = String.valueOf(student.get("studentCode"));
+                                String subjectCode = String.valueOf(student.get("subjectCode"));
+                                String examNumber = String.valueOf(student.get("examNumber"));
+
+                                courseList.add(subjectCode);
+
+                                // 分布式印刷系统内部考生信息
+                                List<Map> studentInfos = examStudentService.listStudentScoreSync(schoolId, studentCode, examNumber, subjectCode);
+                                if (studentInfos == null || studentInfos.size() == 0) {
+                                    throw ExceptionResultEnum.ERROR.exception("未找到此考生信息");
                                 }
+                                Map dpsPrintStuMap = studentInfos.get(0);
+
+                                // 组装本系统内考生信息
+                                clazzId = dpsPrintStuMap.get("clazzId") == null || "".equals(dpsPrintStuMap.get("clazzId")) ? null : Long.parseLong(String.valueOf(dpsPrintStuMap.get("clazzId")));
+                                clazzName = String.valueOf(dpsPrintStuMap.get("clazzName"));
+                                majorName = String.valueOf(dpsPrintStuMap.get("majorName"));
+                                student.put("clazzId", clazzId);
+                                student.put("clazzName", clazzName);
+                                student.put("majorName", majorName);
                             }
-                        }
-                        if (tSyncExamStudentScoreList.size() > 0) {
-                            tSyncExamStudentScoreService.remove(new QueryWrapper<TSyncExamStudentScore>().lambda().eq(TSyncExamStudentScore::getSchoolId, schoolId).eq(TSyncExamStudentScore::getExamId, Long.parseLong(String.valueOf(examId))));
-                            tSyncExamStudentScoreService.saveOrUpdateBatch(tSyncExamStudentScoreList);
+
+                            student.put(SystemConstant.SCHOOL_ID, schoolId);
+                            student.put("semesterId", semesterId);
+                            student.put("orgId", orgId);
+                            student.put("userId", tSyncExamLog.getCreateId());
+                            // 成功数据
+                            tSyncExamStudentScoreList.add(new TSyncExamStudentScore(student));
+                        } catch (Exception e) {
+                            log.info("同步学生成绩信息失败:{}", e.getMessage());
+                            // 失败数据
+                            errorTSyncExamStudentScoreList.add(student.get("name") + "," + student.get("examNumber") + "\r\n");
                         }
                     }
                 }
-            });
-            map.computeIfAbsent("count", e -> count.get());
+                if (tSyncExamStudentScoreList.size() > 0) {
+                    tSyncExamStudentScoreService.remove(new QueryWrapper<TSyncExamStudentScore>().lambda().eq(TSyncExamStudentScore::getSchoolId, schoolId)
+                            .eq(TSyncExamStudentScore::getSemesterId, semesterId)
+                            .eq(TSyncExamStudentScore::getExamId, Long.parseLong(String.valueOf(examId))));
+                    tSyncExamStudentScoreService.saveOrUpdateBatch(tSyncExamStudentScoreList);
+                }
+            }
+
+            map.putIfAbsent("count", totalCount);
+            map.putIfAbsent("courses", courseList.size());
             map.computeIfAbsent("correct", e -> tSyncExamStudentScoreList.size());
             if (Objects.nonNull(errorTSyncExamStudentScoreList) && errorTSyncExamStudentScoreList.size() > 0) {
+                map.computeIfAbsent("errorCount", e -> errorTSyncExamStudentScoreList.size());
                 map.computeIfAbsent("error", e -> "未同步成功数据" + errorTSyncExamStudentScoreList.size() + "条:\r\n" + errorTSyncExamStudentScoreList.toString());
             }
         } catch (Exception e) {
@@ -140,10 +134,10 @@ public class PushLogicServiceImpl implements PushLogicService {
             throw new RuntimeException("云阅卷:接口调用失败:" + e.getMessage());
         }
 
-        if(!tSyncExamStudentScoreList.isEmpty()){
+        if (!tSyncExamStudentScoreList.isEmpty()) {
             try {
                 for (TSyncExamStudentScore tSyncExamStudentScore : tSyncExamStudentScoreList) {
-                    tSyncExamStudentScoreService.createImageTrajectory(tSyncExamStudentScore, ImageTrajectoryEnum.PREVIEW, true, sysUser.getId());
+                    tSyncExamStudentScoreService.createImageTrajectory(tSyncExamStudentScore, ImageTrajectoryEnum.PREVIEW, true, tSyncExamLog.getCreateId());
                 }
             } catch (Exception e) {
 

+ 1 - 2
distributed-print-business/src/main/resources/mapper/ExamCardMapper.xml

@@ -105,8 +105,7 @@
                 LEFT JOIN
             exam_card_detail b ON a.id = b.card_id
                 LEFT JOIN
-            exam_task_detail c ON FIND_IN_SET(a.id, REPLACE(substring_index(substring_index(CONVERT((c.paper_attachment_ids ->>'$[*].cardId')
-                                                                                                    USING utf8), ']', 1), '[',-1),'"',''))
+            exam_task_detail c ON FIND_IN_SET(a.id, REPLACE(REPLACE(substring_index(substring_index(CONVERT((c.paper_attachment_ids ->>'$[*].cardId') USING utf8), ']', 1), '[',-1),' "','"'),'"',''))
         where a.id = #{cardId}
     </select>
     <select id="listGenericCard" resultType="com.qmth.distributed.print.business.entity.ExamCard">

+ 2 - 1
distributed-print-business/src/main/resources/mapper/ExamDetailMapper.xml

@@ -212,7 +212,7 @@
                 </if>
             </if>
         </where>
-        GROUP BY det.id order by det.id desc
+        GROUP BY det.id
         <trim prefix="having" suffixOverrides="and">
             <if test="courseCode != null and courseCode != ''">
                 find_in_set(#{courseCode},courseCodes) and
@@ -221,6 +221,7 @@
                 find_in_set(#{paperNumber},paperNumbers) and
             </if>
         </trim>
+         order by det.id desc
     </select>
     <select id="findDetailPage"
             resultType="com.qmth.distributed.print.business.bean.result.ExaminationDetailResult">

+ 2 - 1
distributed-print-business/src/main/resources/mapper/ExamStudentMapper.xml

@@ -262,7 +262,8 @@
                 AND b.course_code = d.course_code
                 AND b.paper_number = d.paper_number
         WHERE
-            a.school_id = #{schoolId} AND a.student_code = #{studentCode}
+            a.school_id = #{schoolId}
+          AND a.student_code = #{studentCode}
           AND a.ticket_number = #{examNumber}
           AND CONCAT(b.course_code, a.paper_type, d.sequence) = #{subjectCode}
     </select>

+ 53 - 0
distributed-print-business/src/main/resources/mapper/TSyncExamLogMapper.xml

@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
+<mapper namespace="com.qmth.distributed.print.business.mapper.TSyncExamLogMapper">
+    <!-- 通用查询映射结果 -->
+    <resultMap id="BaseResultMap" type="com.qmth.distributed.print.business.entity.TSyncExamLog">
+        <result column="id" property="id"/>
+        <result column="school_id" property="schoolId"/>
+        <result column="semester_id" property="semesterId"/>
+        <result column="exam_id" property="examId"/>
+        <result column="exam_name" property="examName"/>
+        <result column="start_time" property="startTime"/>
+        <result column="end_time" property="endTime"/>
+        <result column="status" property="status"/>
+        <result column="result" property="result"/>
+        <result column="total_courses" property="totalCourses"/>
+        <result column="total_exam_tasks" property="totalExamTasks"/>
+        <result column="total_students" property="totalStudents"/>
+        <result column="success_students" property="successStudents"/>
+        <result column="fail_students" property="failStudents"/>
+        <result column="error_file_path" property="errorFilePath"/>
+        <result column="create_id" property="createId"/>
+        <result column="create_time" property="createTime"/>
+    </resultMap>
+
+    <!-- 通用查询结果列 -->
+    <sql id="Base_Column_List">
+        id, school_id, exam_id, exam_name, start_time, end_time, status, `result`, total_courses, total_exam_tasks, total_students,success_students,fail_students, error_file_path, create_id, create_time
+    </sql>
+
+    <select id="list" resultType="com.qmth.distributed.print.business.entity.TSyncExamLog">
+        SELECT DISTINCT
+            edc.third_relate_id examId
+        FROM
+            exam_detail_course edc
+        WHERE
+            edc.sync_status = 'FINISH'
+          AND edc.third_relate_id IS NOT NULL
+          AND EXISTS( SELECT
+                          1
+                      FROM
+                          exam_detail ed
+                              JOIN
+                          exam_print_plan epp ON ed.school_id = epp.school_id
+                              AND ed.print_plan_id = epp.id
+                              JOIN
+                          basic_exam be ON epp.school_id = be.school_id
+                              AND epp.exam_id = be.id
+                      WHERE
+                          edc.exam_detail_id = ed.id
+                        AND be.semester_id = #{semesterId}
+                        AND be.id = #{examId})
+    </select>
+</mapper>

+ 78 - 15
distributed-print/src/main/java/com/qmth/distributed/print/api/ExamPrintPlanController.java

@@ -143,8 +143,6 @@ public class ExamPrintPlanController {
      * @param courseCode
      * @param paperNumber
      * @param userName        命题老师
-     * @param pageNumber
-     * @param pageSize
      * @return
      */
     @ApiOperation(value = "关联试卷管理-查询")
@@ -157,33 +155,98 @@ public class ExamPrintPlanController {
                              @RequestParam(value = "courseCode", required = false) String courseCode,
                              @RequestParam(value = "paperNumber", required = false) String paperNumber,
                              @RequestParam(value = "userName", required = false) String userName,
-                             @RequestParam(value = "cardRuleId", required = false) Long cardRuleId,
-                             @RequestParam @Min(SystemConstant.PAGE_NUMBER_MIN) Integer pageNumber,
-                             @RequestParam @Min(SystemConstant.PAGE_SIZE_MIN) @Max(SystemConstant.PAGE_SIZE_MAX) Integer pageSize) {
+                             @RequestParam(value = "cardRuleId", required = false) Long cardRuleId) {
         if (Objects.isNull(printPlanIdList)) {
             printPlanIdList = new ArrayList<>();
         }
         List<Long> idList = printPlanIdList.stream().map(SystemConstant::convertIdToLong).collect(Collectors.toList());
-        IPage<ExamTaskDetailDto> examTasks = examTaskDetailService.list(SystemConstant.convertIdToLong(semesterId),SystemConstant.convertIdToLong(examId),relateType, idList, courseCode, paperNumber, userName, cardRuleId, pageNumber, pageSize);
+        List<ExamTaskDetailDto> examTasks = examTaskDetailService.list(SystemConstant.convertIdToLong(semesterId), SystemConstant.convertIdToLong(examId), relateType, idList, courseCode, paperNumber, userName, cardRuleId);
         return ResultUtil.ok(examTasks);
     }
 
+    /**
+     * 关联试卷管理-查询计划下命题任务共有的未曝光卷型
+     *
+     * @param relateType
+     * @param printPlanIdList 印刷计划id集合
+     * @param courseCode
+     * @param paperNumber
+     * @param userName        命题老师
+     * @return
+     */
+    @ApiOperation(value = "关联试卷管理-查询计划下命题任务共有的未曝光卷型")
+    @RequestMapping(value = "/list_relate_common_types", method = RequestMethod.POST)
+    @OperationLogDetail(customizedOperationType = CustomizedOperationTypeEnum.SEARCH)
+    public Result relateCommonTypes(@ApiParam(value = "学期ID") @RequestParam(required = false) String semesterId,
+                                    @ApiParam(value = "考试id") @RequestParam(required = false) String examId,
+                                    @RequestParam(value = "relateType", required = false) String relateType,
+                                    @RequestParam(value = "printPlanIdList", required = false) List<String> printPlanIdList,
+                                    @RequestParam(value = "courseCode", required = false) String courseCode,
+                                    @RequestParam(value = "paperNumber", required = false) String paperNumber,
+                                    @RequestParam(value = "userName", required = false) String userName,
+                                    @RequestParam(value = "cardRuleId", required = false) Long cardRuleId) {
+        if (Objects.isNull(printPlanIdList)) {
+            printPlanIdList = new ArrayList<>();
+        }
+        List<Long> idList = printPlanIdList.stream().map(SystemConstant::convertIdToLong).collect(Collectors.toList());
+        List<String> examTasks = examTaskDetailService.listRelateCommonTypes(SystemConstant.convertIdToLong(semesterId), SystemConstant.convertIdToLong(examId), relateType, idList, courseCode, paperNumber, userName, cardRuleId);
+        return ResultUtil.ok(examTasks);
+    }
+
+    /**
+     * 关联试卷管理-批量关联
+     *
+     * @param relateType
+     * @param printPlanIdList 印刷计划id集合
+     * @param courseCode
+     * @param paperNumber
+     * @param userName        命题老师
+     * @return
+     */
+    @ApiOperation(value = "关联试卷管理-批量关联")
+    @RequestMapping(value = "/relate_update_batch", method = RequestMethod.POST)
+    @OperationLogDetail(customizedOperationType = CustomizedOperationTypeEnum.UPDATE)
+    public Result relateUpdateBatch(@ApiParam(value = "学期ID") @RequestParam(required = false) String semesterId,
+                                    @ApiParam(value = "考试id") @RequestParam(required = false) String examId,
+                                    @RequestParam(value = "relateType", required = false) String relateType,
+                                    @RequestParam(value = "printPlanIdList", required = false) List<String> printPlanIdList,
+                                    @RequestParam(value = "courseCode", required = false) String courseCode,
+                                    @RequestParam(value = "paperNumber", required = false) String paperNumber,
+                                    @RequestParam(value = "userName", required = false) String userName,
+                                    @RequestParam(value = "cardRuleId", required = false) Long cardRuleId) throws IOException {
+        if (Objects.isNull(printPlanIdList)) {
+            printPlanIdList = new ArrayList<>();
+        }
+        List<Long> idList = printPlanIdList.stream().map(SystemConstant::convertIdToLong).collect(Collectors.toList());
+        List<ExamTaskDetailDto> examTasks = examTaskDetailService.list(SystemConstant.convertIdToLong(semesterId), SystemConstant.convertIdToLong(examId), relateType, idList, courseCode, paperNumber, userName, cardRuleId);
+        for (ExamTaskDetailDto examTask : examTasks) {
+            RelatePaperParam relatePaperParam = new RelatePaperParam();
+            relatePaperParam.setExamDetailCourseIds(examTask.getExamDetailCourseIds());
+            relatePaperParam.setExamTaskId(Long.valueOf(examTask.getId()));
+            relatePaperParam.setPaperNumber(examTask.getPaperNumber());
+            relatePaperParam.setPrintPlanId(Long.valueOf(examTask.getPrintPlanId()));
+            relatePaperParam.setRelatePaperType(relateType);
+            examTaskDetailService.updatePaper(relatePaperParam);
+        }
+        return ResultUtil.ok("true");
+    }
+
     @ApiOperation(value = "关联试卷管理-查询-汇总数据")
     @RequestMapping(value = "/relate_total", method = RequestMethod.POST)
     @OperationLogDetail(customizedOperationType = CustomizedOperationTypeEnum.SEARCH)
     public Result relateTotal(@ApiParam(value = "学期ID") @RequestParam(required = false) String semesterId,
-                             @ApiParam(value = "考试ID") @RequestParam(required = false) String examId,
-                             @RequestParam(value = "relateType", required = false) String relateType,
-                             @RequestParam(value = "printPlanIdList", required = false) List<String> printPlanIdList,
-                             @RequestParam(value = "courseCode", required = false) String courseCode,
-                             @RequestParam(value = "paperNumber", required = false) String paperNumber,
-                             @RequestParam(value = "userName", required = false) String userName,
-                             @RequestParam(value = "cardRuleId", required = false) Long cardRuleId) {
+                              @ApiParam(value = "考试ID") @RequestParam(required = false) String examId,
+                              @RequestParam(value = "relateType", required = false) String relateType,
+                              @RequestParam(value = "printPlanIdList", required = false) List<String> printPlanIdList,
+                              @RequestParam(value = "courseCode", required = false) String courseCode,
+                              @RequestParam(value = "paperNumber", required = false) String paperNumber,
+                              @RequestParam(value = "userName", required = false) String userName,
+                              @RequestParam(value = "cardRuleId", required = false) Long cardRuleId) {
         if (Objects.isNull(printPlanIdList)) {
             printPlanIdList = new ArrayList<>();
         }
         List<Long> idList = printPlanIdList.stream().map(SystemConstant::convertIdToLong).collect(Collectors.toList());
-        Map map = examTaskDetailService.listTotal(SystemConstant.convertIdToLong(semesterId),SystemConstant.convertIdToLong(examId),relateType, idList, courseCode, paperNumber, userName, cardRuleId);
+        Map map = examTaskDetailService.listTotal(SystemConstant.convertIdToLong(semesterId), SystemConstant.convertIdToLong(examId), relateType, idList, courseCode, paperNumber, userName, cardRuleId);
         return ResultUtil.ok(map);
     }
 
@@ -250,7 +313,7 @@ public class ExamPrintPlanController {
                            @RequestParam(value = "printHouseId", required = false) String printHouseId,
                            @RequestParam @Min(SystemConstant.PAGE_NUMBER_MIN) Integer pageNumber,
                            @RequestParam @Min(SystemConstant.PAGE_SIZE_MIN) @Max(SystemConstant.PAGE_SIZE_MAX) Integer pageSize) {
-        IPage<PrintTaskDto> examTasks = examDetailService.listPrintTask(SystemConstant.convertIdToLong(semesterId),SystemConstant.convertIdToLong(examId),printPlanId, status, courseCode, paperNumber, examPlace, examRoom, examStartTime, examEndTime, printStartTime, printEndTime, SystemConstant.convertIdToLong(printHouseId), pageNumber, pageSize);
+        IPage<PrintTaskDto> examTasks = examDetailService.listPrintTask(SystemConstant.convertIdToLong(semesterId), SystemConstant.convertIdToLong(examId), printPlanId, status, courseCode, paperNumber, examPlace, examRoom, examStartTime, examEndTime, printStartTime, printEndTime, SystemConstant.convertIdToLong(printHouseId), pageNumber, pageSize);
         return ResultUtil.ok(examTasks);
     }
 

+ 58 - 0
distributed-print/src/main/java/com/qmth/distributed/print/api/TSyncExamLogController.java

@@ -0,0 +1,58 @@
+package com.qmth.distributed.print.api;
+
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.qmth.boot.api.constant.ApiConstant;
+import com.qmth.distributed.print.business.entity.TSyncExamLog;
+import com.qmth.distributed.print.business.service.TSyncExamLogService;
+import com.qmth.teachcloud.common.annotation.OperationLogDetail;
+import com.qmth.teachcloud.common.contant.SystemConstant;
+import com.qmth.teachcloud.common.enums.log.CustomizedOperationTypeEnum;
+import com.qmth.teachcloud.common.util.Result;
+import com.qmth.teachcloud.common.util.ResultUtil;
+import io.swagger.annotations.*;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.annotation.Resource;
+import javax.validation.constraints.Max;
+import javax.validation.constraints.Min;
+
+/**
+ * <p>
+ * 同步考生成绩汇总表 前端控制器
+ * </p>
+ */
+@Api(tags = "成绩归档Controller")
+@RestController
+@RequestMapping(ApiConstant.DEFAULT_URI_PREFIX + SystemConstant.PREFIX_URL_SYNC)
+@Validated
+public class TSyncExamLogController {
+
+    @Resource
+    TSyncExamLogService tSyncExamLogService;
+
+    @ApiOperation(value = "成绩归档查询学汇总列表")
+    @ApiResponses({@ApiResponse(code = 200, message = "成绩查询汇总信息", response = TSyncExamLog.class)})
+    @RequestMapping(value = "/log/list", method = RequestMethod.POST)
+    @OperationLogDetail(customizedOperationType = CustomizedOperationTypeEnum.SEARCH)
+    public Result list(@ApiParam(value = "学期ID", required = false) @RequestParam(required = false) String semesterId,
+                       @ApiParam(value = "考试ID", required = false) @RequestParam(required = false) String examId,
+                       @ApiParam(value = "页码", required = true) @RequestParam @Min(SystemConstant.PAGE_NUMBER_MIN) Integer pageNumber,
+                       @ApiParam(value = "数量", required = true) @RequestParam @Min(SystemConstant.PAGE_SIZE_MIN) @Max(SystemConstant.PAGE_SIZE_MAX) Integer pageSize) {
+        return ResultUtil.ok(tSyncExamLogService.list(new Page<>(pageNumber, pageSize), SystemConstant.convertIdToLong(semesterId), SystemConstant.convertIdToLong(examId)));
+    }
+
+
+    @ApiOperation(value = "同步")
+    @ApiResponses({@ApiResponse(code = 200, message = "同步异步任务信息", response = TSyncExamLog.class)})
+    @RequestMapping(value = "/log/sync", method = RequestMethod.POST)
+    @OperationLogDetail(customizedOperationType = CustomizedOperationTypeEnum.SEARCH)
+    public Result sync(@ApiParam(value = "学期ID", required = true) @RequestParam Long semesterId,
+                       @ApiParam(value = "考试ID", required = true) @RequestParam Long examId) {
+        tSyncExamLogService.syncExam(semesterId, examId);
+        return ResultUtil.ok();
+    }
+}

+ 7 - 59
distributed-print/src/main/java/com/qmth/distributed/print/api/TSyncExamStudentScoreController.java

@@ -1,30 +1,21 @@
 package com.qmth.distributed.print.api;
 
-import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.qmth.boot.api.constant.ApiConstant;
-import com.qmth.distributed.print.business.bean.dto.ExamDetailCourseDto;
 import com.qmth.distributed.print.business.bean.result.EditResult;
 import com.qmth.distributed.print.business.bean.result.TSyncExamStudentScoreResult;
-import com.qmth.distributed.print.business.entity.ExamPrintPlan;
-import com.qmth.distributed.print.business.entity.TBSyncTask;
 import com.qmth.distributed.print.business.entity.TSyncExamStudentScore;
-import com.qmth.distributed.print.business.enums.ExamPrintPlanSyncStatusEnum;
 import com.qmth.distributed.print.business.enums.ImageTrajectoryEnum;
-import com.qmth.distributed.print.business.service.ExamDetailCourseService;
-import com.qmth.distributed.print.business.service.ExamPrintPlanService;
 import com.qmth.distributed.print.business.service.PrintCommonService;
 import com.qmth.distributed.print.business.service.TSyncExamStudentScoreService;
 import com.qmth.distributed.print.business.templete.execute.AsyncScoreBatchDownloadService;
 import com.qmth.distributed.print.business.templete.execute.AsyncScoreExportService;
-import com.qmth.distributed.print.business.templete.execute.AsyncScorePushService;
 import com.qmth.teachcloud.common.annotation.OperationLogDetail;
 import com.qmth.teachcloud.common.config.DictionaryConfig;
 import com.qmth.teachcloud.common.contant.SystemConstant;
 import com.qmth.teachcloud.common.entity.SysUser;
 import com.qmth.teachcloud.common.entity.TBTask;
 import com.qmth.teachcloud.common.enums.ExceptionResultEnum;
-import com.qmth.teachcloud.common.enums.PushTypeEnum;
 import com.qmth.teachcloud.common.enums.TaskTypeEnum;
 import com.qmth.teachcloud.common.enums.log.CustomizedOperationTypeEnum;
 import com.qmth.teachcloud.common.util.Result;
@@ -32,15 +23,16 @@ import com.qmth.teachcloud.common.util.ResultUtil;
 import com.qmth.teachcloud.common.util.ServletUtil;
 import io.swagger.annotations.*;
 import org.springframework.transaction.annotation.Transactional;
-import org.springframework.util.LinkedMultiValueMap;
 import org.springframework.validation.annotation.Validated;
 import org.springframework.web.bind.annotation.*;
 
 import javax.annotation.Resource;
 import javax.validation.constraints.Max;
 import javax.validation.constraints.Min;
-import java.util.*;
-import java.util.stream.Collectors;
+import java.util.ArrayList;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Optional;
 
 /**
  * <p>
@@ -69,26 +61,17 @@ public class TSyncExamStudentScoreController {
     @Resource
     DictionaryConfig dictionaryConfig;
 
-    @Resource
-    AsyncScorePushService asyncScorePushService;
-
     @Resource
     AsyncScoreBatchDownloadService asyncScoreBatchDownloadService;
 
-    @Resource
-    ExamPrintPlanService examPrintPlanService;
-
-    @Resource
-    ExamDetailCourseService examDetailCourseService;
-
     @ApiOperation(value = "成绩归档查询列表")
     @ApiResponses({@ApiResponse(code = 200, message = "成绩查询信息", response = TSyncExamStudentScoreResult.class)})
     @RequestMapping(value = "/score/list", method = RequestMethod.POST)
     @OperationLogDetail(customizedOperationType = CustomizedOperationTypeEnum.SEARCH)
-    public Result list(@ApiParam(value = "学期ID", required = true) @RequestParam String semesterId,
-                       @ApiParam(value = "考试ID", required = true) @RequestParam(required = true) String examId,
+    public Result list(@ApiParam(value = "学期ID", required = false) @RequestParam(required=false) String semesterId,
+                       @ApiParam(value = "考试ID", required = false) @RequestParam(required = false) String examId,
                        @ApiParam(value = "班级id", required = false) @RequestParam(required = false) String clazzId,
-                       @ApiParam(value = "课程编码", required = true) @RequestParam String courseCode,
+                       @ApiParam(value = "课程编码", required = false) @RequestParam(required = false) String courseCode,
                        @ApiParam(value = "页码", required = true) @RequestParam @Min(SystemConstant.PAGE_NUMBER_MIN) Integer pageNumber,
                        @ApiParam(value = "数量", required = true) @RequestParam @Min(SystemConstant.PAGE_SIZE_MIN) @Max(SystemConstant.PAGE_SIZE_MAX) Integer pageSize) {
         return ResultUtil.ok(tSyncExamStudentScoreService.list(new Page<>(pageNumber, pageSize), SystemConstant.convertIdToLong(semesterId), SystemConstant.convertIdToLong(examId), SystemConstant.convertIdToLong(clazzId), courseCode));
@@ -105,41 +88,6 @@ public class TSyncExamStudentScoreController {
         return createScoreTbTask(TaskTypeEnum.SCORE_EXPORT, semesterId, examId, clazzId, courseCode);
     }
 
-    @ApiOperation(value = "成绩查询同步")
-    @ApiResponses({@ApiResponse(code = 200, message = "同步异步任务信息", response = TBSyncTask.class)})
-    @RequestMapping(value = "/score/sync", method = RequestMethod.POST)
-    @OperationLogDetail(customizedOperationType = CustomizedOperationTypeEnum.SEARCH)
-    public Result sync(@ApiParam(value = "学期ID", required = true) @RequestParam String semesterId,
-                       @ApiParam(value = "考试ID", required = true) @RequestParam String examId,
-                       @ApiParam(value = "课程编码", required = false) @RequestParam(required = false) String courseCode) {
-        SysUser sysUser = (SysUser) ServletUtil.getRequestUser();
-        QueryWrapper<ExamPrintPlan> examPrintPlanQueryWrapper = new QueryWrapper<ExamPrintPlan>();
-        examPrintPlanQueryWrapper.eq("school_id", sysUser.getSchoolId())
-                .eq("exam_id", examId);
-        List<ExamPrintPlan> examPrintPlanList = examPrintPlanService.list(examPrintPlanQueryWrapper);
-        if (Objects.isNull(examPrintPlanList) || examPrintPlanList.size() == 0) {
-            throw ExceptionResultEnum.ERROR.exception("此学期学院下未找到需要同步的考试记录");
-        }
-        LinkedMultiValueMap<Long, Integer> semesterExamIdMap = new LinkedMultiValueMap<>();
-        List<Long> printPlanIds = examPrintPlanList.stream().map(ExamPrintPlan::getId).collect(Collectors.toList());
-        List<ExamDetailCourseDto> examDetailCourseList = examDetailCourseService.listByPrintPlanIdAndExamTaskId(printPlanIds, null);
-        for (ExamDetailCourseDto examDetailCourseDto : examDetailCourseList) {
-            if (examDetailCourseDto.getSyncStatus().equals(ExamPrintPlanSyncStatusEnum.FINISH)) {
-                Integer thirdExamId = Integer.parseInt(String.valueOf(examDetailCourseDto.getThirdRelateId()));
-                List<Integer> values = semesterExamIdMap.get(Long.valueOf(semesterId));
-                if (values == null || values.size() == 0) {
-                    semesterExamIdMap.add(Long.valueOf(semesterId), thirdExamId);
-                } else if (!values.contains(thirdExamId)) {
-                    semesterExamIdMap.add(Long.valueOf(semesterId), thirdExamId);
-                }
-            }
-        }
-        Map<String, Object> map = printCommonService.savePush(PushTypeEnum.SCORE_PUSH, Long.valueOf(examId));
-        map.computeIfAbsent("semesterExamIdMap", v -> semesterExamIdMap);
-        asyncScorePushService.pushTask(map);
-        TBSyncTask tbSyncTask = Objects.nonNull(map.get(SystemConstant.TB_SYNC_TASK)) ? (TBSyncTask) map.get(SystemConstant.TB_SYNC_TASK) : null;
-        return Objects.nonNull(tbSyncTask) ? ResultUtil.ok(tbSyncTask.getId()) : ResultUtil.error("创建同步推送任务失败");
-    }
 
     @CrossOrigin(maxAge = 3600) //支持跨域
     @ApiOperation(value = "成绩动态轨迹图下载")