소스 검색

Merge branch 'dev' of http://git.qmth.com.cn/wangliang/distributed-print-service into dev

xiaof 4 년 전
부모
커밋
6f1d8acf72
42개의 변경된 파일1178개의 추가작업 그리고 399개의 파일을 삭제
  1. 18 0
      distributed-print-business/src/main/java/com/qmth/distributed/print/business/bean/dto/ClientPrintTaskDto.java
  2. 62 0
      distributed-print-business/src/main/java/com/qmth/distributed/print/business/bean/dto/ExamStudentCourseDto.java
  3. 6 6
      distributed-print-business/src/main/java/com/qmth/distributed/print/business/bean/dto/ExaminationImportDto.java
  4. 11 0
      distributed-print-business/src/main/java/com/qmth/distributed/print/business/bean/result/TaskListResult.java
  5. 21 6
      distributed-print-business/src/main/java/com/qmth/distributed/print/business/entity/ClientStatus.java
  6. 15 2
      distributed-print-business/src/main/java/com/qmth/distributed/print/business/entity/TBTask.java
  7. 12 0
      distributed-print-business/src/main/java/com/qmth/distributed/print/business/mapper/ExamStudentMapper.java
  8. 1 1
      distributed-print-business/src/main/java/com/qmth/distributed/print/business/mapper/ExamTaskMapper.java
  9. 2 2
      distributed-print-business/src/main/java/com/qmth/distributed/print/business/service/ClientService.java
  10. 1 3
      distributed-print-business/src/main/java/com/qmth/distributed/print/business/service/ClientStatusService.java
  11. 10 0
      distributed-print-business/src/main/java/com/qmth/distributed/print/business/service/ExamStudentService.java
  12. 1 1
      distributed-print-business/src/main/java/com/qmth/distributed/print/business/service/ExamTaskDetailService.java
  13. 1 1
      distributed-print-business/src/main/java/com/qmth/distributed/print/business/service/OrgCenterDataDisposeService.java
  14. 2 2
      distributed-print-business/src/main/java/com/qmth/distributed/print/business/service/TBTaskService.java
  15. 76 32
      distributed-print-business/src/main/java/com/qmth/distributed/print/business/service/impl/BasicMessageServiceImpl.java
  16. 15 11
      distributed-print-business/src/main/java/com/qmth/distributed/print/business/service/impl/ClientServiceImpl.java
  17. 37 26
      distributed-print-business/src/main/java/com/qmth/distributed/print/business/service/impl/ClientStatusServiceImpl.java
  18. 20 0
      distributed-print-business/src/main/java/com/qmth/distributed/print/business/service/impl/ExamDetailServiceImpl.java
  19. 20 3
      distributed-print-business/src/main/java/com/qmth/distributed/print/business/service/impl/ExamStudentServiceImpl.java
  20. 24 18
      distributed-print-business/src/main/java/com/qmth/distributed/print/business/service/impl/ExamTaskDetailServiceImpl.java
  21. 4 2
      distributed-print-business/src/main/java/com/qmth/distributed/print/business/service/impl/ExamTaskServiceImpl.java
  22. 8 8
      distributed-print-business/src/main/java/com/qmth/distributed/print/business/service/impl/OrgCenterDataDisposeServiceImpl.java
  23. 28 6
      distributed-print-business/src/main/java/com/qmth/distributed/print/business/service/impl/TBTaskServiceImpl.java
  24. 20 8
      distributed-print-business/src/main/java/com/qmth/distributed/print/business/templete/execute/AsyncCreatePdfTempleteService.java
  25. 1 1
      distributed-print-business/src/main/java/com/qmth/distributed/print/business/templete/export/AsyncExportTaskTemplete.java
  26. 6 5
      distributed-print-business/src/main/java/com/qmth/distributed/print/business/templete/importData/AsyncImportTaskTemplete.java
  27. 261 166
      distributed-print-business/src/main/java/com/qmth/distributed/print/business/templete/service/impl/TaskLogicServiceImpl.java
  28. 101 50
      distributed-print-business/src/main/java/com/qmth/distributed/print/business/util/CreatePdfUtil.java
  29. 2 0
      distributed-print-business/src/main/resources/db/init-table.sql
  30. 0 4
      distributed-print-business/src/main/resources/mapper/ExamDetailCourseMapper.xml
  31. 10 4
      distributed-print-business/src/main/resources/mapper/ExamPrintPlanMapper.xml
  32. 40 0
      distributed-print-business/src/main/resources/mapper/ExamStudentMapper.xml
  33. 3 0
      distributed-print-business/src/main/resources/mapper/ExamTaskMapper.xml
  34. 2 1
      distributed-print-business/src/main/resources/mapper/TBTaskMapper.xml
  35. 16 0
      distributed-print-common/src/main/java/com/qmth/distributed/print/common/enums/ExceptionResultEnum.java
  36. 5 1
      distributed-print-task/src/main/java/com/qmth/distributed/print/task/enums/JobEnum.java
  37. 6 4
      distributed-print/src/main/java/com/qmth/distributed/print/api/ClientController.java
  38. 5 5
      distributed-print/src/main/java/com/qmth/distributed/print/api/EnumsController.java
  39. 7 8
      distributed-print/src/main/java/com/qmth/distributed/print/api/TBTaskController.java
  40. 18 9
      distributed-print/src/main/java/com/qmth/distributed/print/start/StartRunning.java
  41. 3 3
      distributed-print/src/main/resources/application.properties
  42. 277 0
      distributed-print/src/test/java/com/qmth/distributed/print/BasicUserImportTest.java

+ 18 - 0
distributed-print-business/src/main/java/com/qmth/distributed/print/business/bean/dto/ClientPrintTaskDto.java

@@ -27,10 +27,12 @@ public class ClientPrintTaskDto {
     private String examRoom;
     @ExcelProperty(name = "单科次A3(页)", width = 30, index = 9)
     private String singlePagesA3;
+    private String singlePagesA4;
     private Integer pagesA3;
     private Integer pagesA4;
     @ExcelProperty(name = "科次", width = 30, index = 10)
     private Integer totalSubjects;
+    private Integer totalPrint;
     private String status;
     @ExcelProperty(name = "印刷状态", width = 30, index = 11)
     private String statusStr;
@@ -161,6 +163,14 @@ public class ClientPrintTaskDto {
         this.singlePagesA3 = singlePagesA3;
     }
 
+    public String getSinglePagesA4() {
+        return singlePagesA4;
+    }
+
+    public void setSinglePagesA4(String singlePagesA4) {
+        this.singlePagesA4 = singlePagesA4;
+    }
+
     public Integer getPagesA3() {
         return pagesA3;
     }
@@ -185,6 +195,14 @@ public class ClientPrintTaskDto {
         this.totalSubjects = totalSubjects;
     }
 
+    public Integer getTotalPrint() {
+        return totalPrint;
+    }
+
+    public void setTotalPrint(Integer totalPrint) {
+        this.totalPrint = totalPrint;
+    }
+
     public String getStatus() {
         return status;
     }

+ 62 - 0
distributed-print-business/src/main/java/com/qmth/distributed/print/business/bean/dto/ExamStudentCourseDto.java

@@ -0,0 +1,62 @@
+package com.qmth.distributed.print.business.bean.dto;
+
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
+import com.qmth.distributed.print.business.entity.ExamStudent;
+import io.swagger.annotations.ApiModelProperty;
+
+/**
+ * @Description: 考生科目 dto
+ * @Param:
+ * @return:
+ * @Author: wangliang
+ * @Date: 2021/5/14
+ */
+public class ExamStudentCourseDto extends ExamStudent {
+
+    @ApiModelProperty(value = "科目编码")
+    private String courseCode;
+
+    @ApiModelProperty(value = "科目名称")
+    private String courseName;
+
+    @ApiModelProperty(value = "A3数量")
+    private Integer paperPageA3;
+
+    @ApiModelProperty("试卷编号")
+    private String paperNumber;
+
+    public String getPaperNumber() {
+        return paperNumber;
+    }
+
+    public void setPaperNumber(String paperNumber) {
+        this.paperNumber = paperNumber;
+    }
+
+    public String getCourseCode() {
+        return courseCode;
+    }
+
+    public void setCourseCode(String courseCode) {
+        this.courseCode = courseCode;
+    }
+
+    public String getCourseName() {
+        return courseName;
+    }
+
+    public void setCourseName(String courseName) {
+        this.courseName = courseName;
+    }
+
+    public Integer getPaperPageA3() {
+        return paperPageA3;
+    }
+
+    public void setPaperPageA3(Integer paperPageA3) {
+        this.paperPageA3 = paperPageA3;
+    }
+}

+ 6 - 6
distributed-print-business/src/main/java/com/qmth/distributed/print/business/bean/dto/ExaminationImportDto.java

@@ -25,23 +25,23 @@ public class ExaminationImportDto {
     private String siteNumber;
 
     @ApiModelProperty(value = "姓名")
-    @ExcelDBFieldDesc(name = "姓名",length = 15)
+    @ExcelDBFieldDesc(name = "姓名",length = 50)
     private String studentName;
 
     @ApiModelProperty(value = "课程代码")
-    @ExcelDBFieldDesc(name = "课程代码",length = 10)
+    @ExcelDBFieldDesc(name = "课程代码",length = 30)
     private String courseCode;
 
     @ApiModelProperty(value = "课程名称")
-    @ExcelDBFieldDesc(name = "课程名称",length = 20)
+    @ExcelDBFieldDesc(name = "课程名称",length = 50)
     private String courseName;
 
     @ApiModelProperty(value = "考点")
-    @ExcelDBFieldDesc(name = "考点",length = 10)
+    @ExcelDBFieldDesc(name = "考点",length = 30)
     private String examPlace;
 
     @ApiModelProperty(value = "考场")
-    @ExcelDBFieldDesc(name = "考场",length = 10)
+    @ExcelDBFieldDesc(name = "考场",length = 30)
     private String examRoom;
 
     @ApiModelProperty(value = "考试日期")
@@ -53,7 +53,7 @@ public class ExaminationImportDto {
     private String examTime;
 
     @ApiModelProperty(value = "试卷编号")
-    @ExcelDBFieldDesc(name = "试卷编号",length = 15)
+    @ExcelDBFieldDesc(name = "试卷编号",length = 30)
     private String paperNumber;
 
     @ApiModelProperty(value = "备选字段集合")

+ 11 - 0
distributed-print-business/src/main/java/com/qmth/distributed/print/business/bean/result/TaskListResult.java

@@ -61,6 +61,17 @@ public class TaskListResult implements Serializable {
     @ApiModelProperty(value = "重新生成次数")
     int resetCount;
 
+    @ApiModelProperty(value = "人工错误原因")
+    String errorMessage;
+
+    public String getErrorMessage() {
+        return errorMessage;
+    }
+
+    public void setErrorMessage(String errorMessage) {
+        this.errorMessage = errorMessage;
+    }
+
     public int getResetCount() {
         return resetCount;
     }

+ 21 - 6
distributed-print-business/src/main/java/com/qmth/distributed/print/business/entity/ClientStatus.java

@@ -30,12 +30,19 @@ public class ClientStatus extends BaseEntity implements Serializable {
      */
     @TableField("machine_code")
     private String machineCode;
+    /**
+     * 考场ID
+     */
+    @JsonSerialize(using = ToStringSerializer.class)
+    @TableField("exam_detail_id")
+    private Long examDetailId;
+
     /**
      * 命题任务ID
      */
     @JsonSerialize(using = ToStringSerializer.class)
-    @TableField("exam_task_id")
-    private Long examTaskId;
+    @TableField("print_plan_id")
+    private Long printPlanId;
 
     /**
      * 课程代码
@@ -93,12 +100,20 @@ public class ClientStatus extends BaseEntity implements Serializable {
         this.machineCode = machineCode;
     }
 
-    public Long getExamTaskId() {
-        return examTaskId;
+    public Long getExamDetailId() {
+        return examDetailId;
+    }
+
+    public void setExamDetailId(Long examDetailId) {
+        this.examDetailId = examDetailId;
+    }
+
+    public Long getPrintPlanId() {
+        return printPlanId;
     }
 
-    public void setExamTaskId(Long examTaskId) {
-        this.examTaskId = examTaskId;
+    public void setPrintPlanId(Long printPlanId) {
+        this.printPlanId = printPlanId;
     }
 
     public String getCourseCode() {

+ 15 - 2
distributed-print-business/src/main/java/com/qmth/distributed/print/business/entity/TBTask.java

@@ -1,6 +1,7 @@
 package com.qmth.distributed.print.business.entity;
 
 import com.baomidou.mybatisplus.annotation.FieldFill;
+import com.baomidou.mybatisplus.annotation.FieldStrategy;
 import com.baomidou.mybatisplus.annotation.TableField;
 import com.baomidou.mybatisplus.annotation.TableId;
 import com.fasterxml.jackson.databind.annotation.JsonSerialize;
@@ -79,11 +80,11 @@ public class TBTask implements Serializable {
     private Boolean enable;
 
     @ApiModelProperty(value = "导入文件名")
-    @TableField(value = "import_file_name")
+    @TableField(value = "import_file_name", updateStrategy = FieldStrategy.IGNORED)
     private String importFileName;
 
     @ApiModelProperty(value = "导入文件路径")
-    @TableField(value = "import_file_path")
+    @TableField(value = "import_file_path", updateStrategy = FieldStrategy.IGNORED)
     private String importFilePath;
 
     @ApiModelProperty(value = "导出文件路径")
@@ -119,6 +120,18 @@ public class TBTask implements Serializable {
     @TableField(value = "version")
     private int version;
 
+    @ApiModelProperty(value = "人工错误")
+    @TableField(value = "error_message", updateStrategy = FieldStrategy.IGNORED)
+    private String errorMessage;
+
+    public String getErrorMessage() {
+        return errorMessage;
+    }
+
+    public void setErrorMessage(String errorMessage) {
+        this.errorMessage = errorMessage;
+    }
+
     public int getVersion() {
         return version;
     }

+ 12 - 0
distributed-print-business/src/main/java/com/qmth/distributed/print/business/mapper/ExamStudentMapper.java

@@ -1,8 +1,11 @@
 package com.qmth.distributed.print.business.mapper;
 
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.qmth.distributed.print.business.bean.dto.ExamStudentCourseDto;
 import com.qmth.distributed.print.business.entity.ExamStudent;
+import org.apache.ibatis.annotations.Param;
 
+import java.util.List;
 import java.util.Map;
 
 /**
@@ -16,4 +19,13 @@ import java.util.Map;
 public interface ExamStudentMapper extends BaseMapper<ExamStudent> {
 
     Map<String, Object> getStudentDetail(Long id);
+
+    /**
+     * 根据科目查询考生
+     *
+     * @param schoolId
+     * @param examDetailCourseIds
+     * @return
+     */
+    List<ExamStudentCourseDto> queryBySchoolIdAndExamDetailCourseIds(@Param("schoolId") Long schoolId, @Param("examDetailCourseIds") List<Long> examDetailCourseIds);
 }

+ 1 - 1
distributed-print-business/src/main/java/com/qmth/distributed/print/business/mapper/ExamTaskMapper.java

@@ -73,7 +73,7 @@ public interface ExamTaskMapper extends BaseMapper<ExamTask> {
 
     IPage<ClientExamTaskDto> listClientExamTaskPage(Page<ClientExamTaskDto> page, @Param("schoolId") Long schoolId, @Param("machineCode") String machineCode, @Param("printPlanId") Long printPlanId, @Param("courseCode") String courseCode, @Param("paperNumber") String paperNumber, @Param("isTry") Boolean isTry, @Param("isPass") Boolean isPass, @Param("orgIds") Set<Long> orgIds, @Param("printPlanStatus") String printPlanStatus, @Param("examDetailStatus") String[] examDetailStatus);
 
-    List<ClientExamTaskDto> listClientExamTaskPage(@Param("schoolId") Long schoolId, @Param("machineCode") String machineCode, @Param("printPlanId") Long printPlanId, @Param("courseCode") String courseCode, @Param("paperNumber") String paperNumber, @Param("isTry") Boolean isTry, @Param("isPass") Boolean isPass, @Param("orgIds") Set<Long> orgIds, @Param("printPlanStatus") String printPlanStatus, @Param("examDetailStatus") String examDetailStatus);
+    List<ClientExamTaskDto> listClientExamTaskPage(@Param("schoolId") Long schoolId, @Param("machineCode") String machineCode, @Param("printPlanId") Long printPlanId, @Param("courseCode") String courseCode, @Param("paperNumber") String paperNumber, @Param("isTry") Boolean isTry, @Param("isPass") Boolean isPass, @Param("orgIds") Set<Long> orgIds, @Param("printPlanStatus") String printPlanStatus, @Param("examDetailStatus") String[] examDetailStatus);
 
     List<ExamTask> listExamTaskByCardId(Long cardId);
 

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

@@ -13,9 +13,9 @@ import java.util.Map;
 public interface ClientService {
     IPage<ClientExamTaskDto> listTryTask(String machineCode, Long orgId, Long printPlanId, String courseCode, String paperNumber, Boolean isTry, Boolean isPass, Integer pageNumber, Integer pageSize);
 
-    Map<String, String> getUrl(Long examTaskId);
+    Map<String, String> getUrl(Long printPlanId, Long examTaskId);
 
-    Boolean tagPass(String courseCode, String courseName, String paperNumber, String machineCode, Boolean isPass, Long userId);
+    Boolean tagPass(Long printPlanId, String courseCode, String courseName, String paperNumber, String machineCode, Boolean isPass, Long userId);
 
     Boolean updatePrintProgress(Long examDetailId, String machineCode, Integer printProgress);
 

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

@@ -3,8 +3,6 @@ package com.qmth.distributed.print.business.service;
 import com.baomidou.mybatisplus.extension.service.IService;
 import com.qmth.distributed.print.business.entity.ClientStatus;
 
-import java.util.List;
-
 /**
  * <p>
  * 客户端下载状态 服务类
@@ -14,5 +12,5 @@ import java.util.List;
  * @since 2021-04-19
  */
 public interface ClientStatusService extends IService<ClientStatus> {
-    Boolean tagPass(Long schoolId, String courseCode, String courseName, String paperNumber, String machineCode, Boolean isPass, Long userId);
+    Boolean tagPass(Long schoolId, Long printPlanId, String courseCode, String courseName, String paperNumber, String machineCode, Boolean isPass, Long userId);
 }

+ 10 - 0
distributed-print-business/src/main/java/com/qmth/distributed/print/business/service/ExamStudentService.java

@@ -1,6 +1,7 @@
 package com.qmth.distributed.print.business.service;
 
 import com.baomidou.mybatisplus.extension.service.IService;
+import com.qmth.distributed.print.business.bean.dto.ExamStudentCourseDto;
 import com.qmth.distributed.print.business.entity.ExamDetailCourse;
 import com.qmth.distributed.print.business.entity.ExamStudent;
 
@@ -22,4 +23,13 @@ public interface ExamStudentService extends IService<ExamStudent> {
     List<String> listByExamDetailCourseId(String examDetailCourseId);
 
     Map<String, Object> getStudentDetail(Long id);
+
+    /**
+     * 根据科目查询考生
+     *
+     * @param schoolId
+     * @param examDetailCourseIds
+     * @return
+     */
+    List<ExamStudentCourseDto> queryBySchoolIdAndExamDetailCourseIds(Long schoolId, List<Long> examDetailCourseIds);
 }

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

@@ -34,7 +34,7 @@ public interface ExamTaskDetailService extends IService<ExamTaskDetail> {
 
     List<ExamTaskDetail> listByTemplateId(Long templateId);
 
-    Map<String, String>  getUrl(Long schoolId, Long examTaskId);
+    Map<String, String>  getUrl(Long schoolId, Long printPlanId, Long examTaskId);
 
     boolean paperUpdate(ExamTaskDetail examTaskDetail);
 

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

@@ -11,6 +11,6 @@ import java.io.IOException;
  */
 public interface OrgCenterDataDisposeService {
 
-    @Async("taskThreadPool")
+    @Async
     void updateSchoolInfo() throws IOException;
 }

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

@@ -145,8 +145,8 @@ public interface TBTaskService extends IService<TBTask> {
     /**
      * 更新任务状态
      */
-    @Async("taskThreadPool")
-    public void updateStatus();
+    @Async
+    public void updateStatus() throws IOException;
 
     /**
      * 重新生成pdf失败任务

+ 76 - 32
distributed-print-business/src/main/java/com/qmth/distributed/print/business/service/impl/BasicMessageServiceImpl.java

@@ -5,6 +5,7 @@ import com.aliyuncs.DefaultAcsClient;
 import com.aliyuncs.IAcsClient;
 import com.aliyuncs.dysmsapi.model.v20170525.SendSmsRequest;
 import com.aliyuncs.dysmsapi.model.v20170525.SendSmsResponse;
+import com.aliyuncs.exceptions.ClientException;
 import com.aliyuncs.http.MethodType;
 import com.aliyuncs.profile.DefaultProfile;
 import com.aliyuncs.profile.IClientProfile;
@@ -74,38 +75,7 @@ public class BasicMessageServiceImpl extends ServiceImpl<BasicMessageMapper, Bas
                 throw ExceptionResultEnum.ERROR.exception("短信消息提示已关闭");
             }
 
-            System.setProperty("sun.net.client.defaultConnectTimeout", "180000");
-            System.setProperty("sun.net.client.defaultReadTimeout", "18000");
-            // 初始化ascClient需要的几个参数
-            final String product = "Dysmsapi";// 短信API产品名称(短信产品名固定,无需修改)
-            final String domain = "dysmsapi.aliyuncs.com";// 短信API产品域名(接口地址固定,无需修改)
-            // 替换成你的AK
-            final String accessKeyId = dictionaryConfig.smsDomain().getAliyunSMSKey();// 你的accessKeyId,参考本文档步骤2
-            final String accessKeySecret = dictionaryConfig.smsDomain().getAliyunSMSSecret();// 你的accessKeySecret,参考本文档步骤2
-            // 初始化ascClient,暂时不支持多region(请勿修改)
-            IClientProfile profile = DefaultProfile.getProfile("cn-hangzhou", accessKeyId, accessKeySecret);
-            DefaultProfile.addEndpoint("cn-hangzhou", "cn-hangzhou", product, domain);
-            IAcsClient acsClient = new DefaultAcsClient(profile);
-            // 组装请求对象
-            SendSmsRequest request = new SendSmsRequest();
-            // 使用post提交
-            request.setMethod(MethodType.POST);
-            // 必填:待发送手机号。支持以逗号分隔的形式进行批量调用,批量上限为1000个手机号码,批量调用相对于单条调用及时性稍有延迟,验证码类型的短信推荐使用单条调用的方式;发送国际/港澳台消息时,接收号码格式为00+国际区号+号码,如“0085200000000”
-            request.setPhoneNumbers(mobileNumber);
-            // 必填:短信签名-可在短信控制台中找到
-            request.setSignName(dictionaryConfig.smsDomain().getAliyunSMSSignName());
-            // 必填:短信模板-可在短信控制台中找到
-            request.setTemplateCode(templateCode);
-            // 可选:模板中的变量替换JSON串,如模板内容为"亲爱的${name},您的验证码为${code}"时,此处的值为
-            // 友情提示:如果JSON中需要带换行符,请参照标准的JSON协议对换行符的要求,比如短信内容中包含\r\n的情况在JSON中需要表示成\\r\\n,否则会导致JSON在服务端解析失败
-            request.setTemplateParam(variableParams);
-            // 可选-上行短信扩展码(扩展码字段控制在7位或以下,无特殊需求用户请忽略此字段)
-            // request.setSmsUpExtendCode("90997");
-            // 可选:outId为提供给业务方扩展字段,最终在短信回执消息中将此值带回给调用者
-//             request.setOutId("yourOutId");
-            // 请求失败这里会抛ClientException异常
-
-            SendSmsResponse sendSmsResponse = acsClient.getAcsResponse(request);
+            SendSmsResponse sendSmsResponse = sendSms(mobileNumber, templateCode, variableParams);
 
             if (sendSmsResponse.getCode() != null) {
 
@@ -141,6 +111,50 @@ public class BasicMessageServiceImpl extends ServiceImpl<BasicMessageMapper, Bas
         }
     }
 
+    /**
+     * 发送短信
+     * @param mobileNumber
+     * @param templateCode
+     * @param variableParams
+     * @return
+     * @throws ClientException
+     */
+    private SendSmsResponse sendSms(String mobileNumber, String templateCode, String variableParams) throws ClientException {
+        System.setProperty("sun.net.client.defaultConnectTimeout", "180000");
+        System.setProperty("sun.net.client.defaultReadTimeout", "18000");
+        // 初始化ascClient需要的几个参数
+        final String product = "Dysmsapi";// 短信API产品名称(短信产品名固定,无需修改)
+        final String domain = "dysmsapi.aliyuncs.com";// 短信API产品域名(接口地址固定,无需修改)
+        // 替换成你的AK
+        final String accessKeyId = dictionaryConfig.smsDomain().getAliyunSMSKey();// 你的accessKeyId,参考本文档步骤2
+        final String accessKeySecret = dictionaryConfig.smsDomain().getAliyunSMSSecret();// 你的accessKeySecret,参考本文档步骤2
+        // 初始化ascClient,暂时不支持多region(请勿修改)
+        IClientProfile profile = DefaultProfile.getProfile("cn-hangzhou", accessKeyId, accessKeySecret);
+        DefaultProfile.addEndpoint("cn-hangzhou", "cn-hangzhou", product, domain);
+        IAcsClient acsClient = new DefaultAcsClient(profile);
+        // 组装请求对象
+        SendSmsRequest request = new SendSmsRequest();
+        // 使用post提交
+        request.setMethod(MethodType.POST);
+        // 必填:待发送手机号。支持以逗号分隔的形式进行批量调用,批量上限为1000个手机号码,批量调用相对于单条调用及时性稍有延迟,验证码类型的短信推荐使用单条调用的方式;发送国际/港澳台消息时,接收号码格式为00+国际区号+号码,如“0085200000000”
+        request.setPhoneNumbers(mobileNumber);
+        // 必填:短信签名-可在短信控制台中找到
+        request.setSignName(dictionaryConfig.smsDomain().getAliyunSMSSignName());
+        // 必填:短信模板-可在短信控制台中找到
+        request.setTemplateCode(templateCode);
+        // 可选:模板中的变量替换JSON串,如模板内容为"亲爱的${name},您的验证码为${code}"时,此处的值为
+        // 友情提示:如果JSON中需要带换行符,请参照标准的JSON协议对换行符的要求,比如短信内容中包含\r\n的情况在JSON中需要表示成\\r\\n,否则会导致JSON在服务端解析失败
+        request.setTemplateParam(variableParams);
+        // 可选-上行短信扩展码(扩展码字段控制在7位或以下,无特殊需求用户请忽略此字段)
+        // request.setSmsUpExtendCode("90997");
+        // 可选:outId为提供给业务方扩展字段,最终在短信回执消息中将此值带回给调用者
+//             request.setOutId("yourOutId");
+        // 请求失败这里会抛ClientException异常
+
+        SendSmsResponse sendSmsResponse = acsClient.getAcsResponse(request);
+        return sendSmsResponse;
+    }
+
     @Transactional(rollbackFor = Exception.class)
     @Override
     public void noticeOfExamTaskAudit(List<Long> examTaskIdList, MessageEnum messageType, SysUser sysUser) {
@@ -242,8 +256,38 @@ public class BasicMessageServiceImpl extends ServiceImpl<BasicMessageMapper, Bas
             queryWrapper.lambda().ne(BasicMessage::getSendStatus, "OK").lt(BasicMessage::getResendCount, resendCount);
             List<BasicMessage> basicMessageList = this.list(queryWrapper);
             if (basicMessageList != null && basicMessageList.size() > 0) {
+                for (BasicMessage basicMessage : basicMessageList) {
+                    this.saveMessageResendLog(basicMessage);
+                }
+            }
+        }
+    }
 
+    /**
+     * 自动重发
+     * @param basicMessage
+     */
+    private void saveMessageResendLog(BasicMessage basicMessage) {
+        String errorMessage = null;
+        try {
+            SendSmsResponse sendSmsResponse = sendSms(basicMessage.getMobileNumber(), basicMessage.getTemplateCode(), basicMessage.getVariableParams());
+            if (sendSmsResponse.getCode() != null) {
+                basicMessage.setSendStatus(sendSmsResponse.getCode());
+                basicMessage.setSendResult(sendSmsResponse.getMessage());
+            } else {
+                throw ExceptionResultEnum.ERROR.exception(sendSmsResponse.getMessage());
+            }
+        } catch (Exception e) {
+            errorMessage = e.getMessage();
+        } finally {
+            // 重试次数+1
+            basicMessage.setResendCount(basicMessage.getResendCount() + 1);
+            // 经过处理的新字段
+            if (errorMessage != null && errorMessage.length() > 0) {
+                basicMessage.setSendStatus("SYSTEM_ERROR");
+                basicMessage.setSendResult(errorMessage);
             }
+            this.updateById(basicMessage);
         }
     }
 

+ 15 - 11
distributed-print-business/src/main/java/com/qmth/distributed/print/business/service/impl/ClientServiceImpl.java

@@ -8,8 +8,6 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.qmth.distributed.print.business.bean.dto.*;
 import com.qmth.distributed.print.business.entity.*;
 import com.qmth.distributed.print.business.enums.ExamDetailStatusEnum;
-import com.qmth.distributed.print.business.enums.ExamStatusEnum;
-import com.qmth.distributed.print.business.enums.PrintPlanStatusEnum;
 import com.qmth.distributed.print.business.service.*;
 import com.qmth.distributed.print.business.util.ExcelUtil;
 import com.qmth.distributed.print.business.util.ServletUtil;
@@ -68,15 +66,15 @@ public class ClientServiceImpl implements ClientService {
     }
 
     @Override
-    public Map<String, String> getUrl(Long examTaskId) {
+    public Map<String, String> getUrl(Long printPlanId, Long examTaskId) {
         Long schoolId = Long.valueOf(ServletUtil.getRequestHeaderSchoolId().toString());
-        return examTaskDetailService.getUrl(schoolId, examTaskId);
+        return examTaskDetailService.getUrl(schoolId, printPlanId, examTaskId);
     }
 
     @Override
-    public Boolean tagPass(String courseCode, String courseName, String paperNumber, String machineCode, Boolean isPass, Long userId) {
+    public Boolean tagPass(Long printPlanId, String courseCode, String courseName, String paperNumber, String machineCode, Boolean isPass, Long userId) {
         Long schoolId = Long.valueOf(ServletUtil.getRequestHeaderSchoolId().toString());
-        return clientStatusService.tagPass(schoolId, courseCode, courseName, paperNumber, machineCode, isPass, userId);
+        return clientStatusService.tagPass(schoolId, printPlanId, courseCode, courseName, paperNumber, machineCode, isPass, userId);
     }
 
     @Override
@@ -302,9 +300,11 @@ public class ClientServiceImpl implements ClientService {
                 }
                 String examTaskId = examDetailCours.get("examTaskId").toString();
                 UpdateWrapper<ExamTaskDetail> examTaskDetailUpdateWrapper = new UpdateWrapper<>();
+                String exposedPaper = String.join(",", exposedPaperSet);
+                String unexposedPaper = String.join(",", unexposedPaperSet);
                 examTaskDetailUpdateWrapper.lambda()
-                        .set(ExamTaskDetail::getExposedPaperType, String.join(",", exposedPaperSet))
-                        .set(ExamTaskDetail::getUnexposedPaperType, String.join(",", unexposedPaperSet))
+                        .set(ExamTaskDetail::getExposedPaperType, StringUtils.isBlank(exposedPaper) ? null : exposedPaper)
+                        .set(ExamTaskDetail::getUnexposedPaperType, StringUtils.isBlank(unexposedPaper) ? null : unexposedPaper)
                         .eq(ExamTaskDetail::getExamTaskId, examTaskId);
                 examTaskDetailService.update(examTaskDetailUpdateWrapper);
             }
@@ -348,18 +348,21 @@ public class ClientServiceImpl implements ClientService {
 
     @Override
     public Boolean updateDownload(Long examDetailId, String machineCode, Boolean isDownload) {
+        ExamDetail examDetail = examDetailService.getById(examDetailId);
         Long schoolId = Long.valueOf(ServletUtil.getRequestHeaderSchoolId().toString());
         QueryWrapper<ExamDetailCourse> examDetailCourseQueryWrapper = new QueryWrapper<>();
         examDetailCourseQueryWrapper.lambda().eq(ExamDetailCourse::getSchoolId, schoolId).eq(ExamDetailCourse::getExamDetailId, examDetailId);
         List<ExamDetailCourse> examDetailCourses = examDetailCourseService.list(examDetailCourseQueryWrapper);
         for (ExamDetailCourse examDetailCours : examDetailCourses) {
             QueryWrapper<ClientStatus> clientStatusQueryWrapper = new QueryWrapper<>();
-            clientStatusQueryWrapper.lambda().eq(ClientStatus::getSchoolId, schoolId).eq(ClientStatus::getCourseCode, examDetailCours.getCourseCode()).eq(ClientStatus::getPaperNumber, examDetailCours.getPaperNumber()).eq(ClientStatus::getMachineCode, machineCode);
+            clientStatusQueryWrapper.lambda().eq(ClientStatus::getSchoolId, schoolId).eq(ClientStatus::getExamDetailId, examDetailId).eq(ClientStatus::getPrintPlanId, examDetail.getPrintPlanId()).eq(ClientStatus::getCourseCode, examDetailCours.getCourseCode()).eq(ClientStatus::getPaperNumber, examDetailCours.getPaperNumber()).eq(ClientStatus::getMachineCode, machineCode);
             ClientStatus clientStatus = clientStatusService.getOne(clientStatusQueryWrapper);
             if (clientStatus == null) {
                 clientStatus = new ClientStatus();
                 clientStatus.setId(SystemConstant.getDbUuid());
                 clientStatus.setSchoolId(schoolId);
+                clientStatus.setExamDetailId(examDetailId);
+                clientStatus.setPrintPlanId(examDetail.getPrintPlanId());
                 clientStatus.setMachineCode(machineCode);
                 clientStatus.setCourseCode(examDetailCours.getCourseCode());
                 clientStatus.setCourseName(examDetailCours.getCourseName());
@@ -456,10 +459,11 @@ public class ClientServiceImpl implements ClientService {
         List<Map<String, String>> list = new ArrayList<>();
         for (ClientExamTaskDto clientExamTaskDto : clientExamTaskDtos) {
             Map<String, String> map = new HashMap<>();
+            map.put("printPlanId", clientExamTaskDto.getPrintPlanId());
             map.put("courseCode", clientExamTaskDto.getCourseCode());
             map.put("courseName", clientExamTaskDto.getCourseName());
             map.put("paperNumber", clientExamTaskDto.getPaperNumber());
-            Map<String, String> stringMap = examTaskDetailService.getUrl(schoolId, Long.valueOf(clientExamTaskDto.getExamTaskId()));
+            Map<String, String> stringMap = examTaskDetailService.getUrl(schoolId, Long.valueOf(clientExamTaskDto.getPrintPlanId()), Long.valueOf(clientExamTaskDto.getExamTaskId()));
             map.putAll(stringMap);
             list.add(map);
         }
@@ -489,7 +493,7 @@ public class ClientServiceImpl implements ClientService {
                 String pEndTime = simpleDateFormat.format(new Date(m.getPrintEndTime()));
                 m.setPrintEndTimeStr(pEndTime);
             }
-            m.setStatusStr(ExamStatusEnum.valueOf(m.getStatus()).getDesc());
+            m.setStatusStr(ExamDetailStatusEnum.valueOf(m.getStatus()).getDesc());
             m.setValidateStr(m.getValidate() ? "是" : "否");
             m.setDownloadStr(m.getDownload() ? "是" : "否");
             return m;

+ 37 - 26
distributed-print-business/src/main/java/com/qmth/distributed/print/business/service/impl/ClientStatusServiceImpl.java

@@ -3,13 +3,17 @@ package com.qmth.distributed.print.business.service.impl;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.qmth.distributed.print.business.entity.ClientStatus;
+import com.qmth.distributed.print.business.entity.ExamDetailCourse;
 import com.qmth.distributed.print.business.mapper.ClientStatusMapper;
 import com.qmth.distributed.print.business.service.ClientStatusService;
+import com.qmth.distributed.print.business.service.ExamDetailCourseService;
 import com.qmth.distributed.print.business.service.ExamTaskService;
 import com.qmth.distributed.print.common.contant.SystemConstant;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
+import java.util.List;
+
 /**
  * @Date: 2021/4/19.
  */
@@ -17,36 +21,43 @@ import org.springframework.stereotype.Service;
 public class ClientStatusServiceImpl extends ServiceImpl<ClientStatusMapper, ClientStatus> implements ClientStatusService {
 
     @Autowired
-    private ExamTaskService examTaskService;
+    private ExamDetailCourseService examDetailCourseService;
 
     @Override
-    public Boolean tagPass(Long schoolId, String courseCode, String courseName, String paperNumber, String machineCode, Boolean isPass, Long userId) {
-        QueryWrapper<ClientStatus> queryWrapper = new QueryWrapper<>();
-        queryWrapper.lambda().eq(ClientStatus::getSchoolId, schoolId).eq(ClientStatus::getCourseCode, courseCode).eq(ClientStatus::getPaperNumber, paperNumber).eq(ClientStatus::getMachineCode, machineCode);
-        ClientStatus clientStatus = this.getOne(queryWrapper);
-        if(clientStatus != null){
-            clientStatus.setPass(isPass);
-            clientStatus.setUpdateId(userId);
-            clientStatus.setUpdateTime(System.currentTimeMillis());
-            // 合格,更新打印时间
-            if(isPass){
+    public Boolean tagPass(Long schoolId, Long printPlanId, String courseCode, String courseName, String paperNumber, String machineCode, Boolean isPass, Long userId) {
+        List<ExamDetailCourse> examDetailCourses = examDetailCourseService.listByPrintPlanIdAndCourseCodeAndPaperNumber(schoolId, printPlanId, courseCode, paperNumber);
+        for (ExamDetailCourse examDetailCours : examDetailCourses) {
+            QueryWrapper<ClientStatus> queryWrapper = new QueryWrapper<>();
+            queryWrapper.lambda().eq(ClientStatus::getSchoolId, schoolId).eq(ClientStatus::getExamDetailId, examDetailCours.getExamDetailId()).eq(ClientStatus::getPrintPlanId, printPlanId).eq(ClientStatus::getCourseCode, courseCode).eq(ClientStatus::getPaperNumber, paperNumber).eq(ClientStatus::getMachineCode, machineCode);
+            ClientStatus clientStatus = this.getOne(queryWrapper);
+            if(clientStatus != null){
+                clientStatus.setPass(isPass);
+                clientStatus.setUpdateId(userId);
+                clientStatus.setUpdateTime(System.currentTimeMillis());
+                // 合格,更新打印时间
+                if(isPass){
+                    clientStatus.setTryTime(System.currentTimeMillis());
+                }
+                this.updateById(clientStatus);
+            } else {
+                clientStatus = new ClientStatus();
+                clientStatus.setId(SystemConstant.getDbUuid());
+                clientStatus.setSchoolId(schoolId);
+                clientStatus.setExamDetailId(examDetailCours.getExamDetailId());
+                clientStatus.setPrintPlanId(printPlanId);
+                clientStatus.setMachineCode(machineCode);
+                clientStatus.setCourseCode(courseCode);
+                clientStatus.setCourseName(courseName);
+                clientStatus.setPaperNumber(paperNumber);
+                clientStatus.setTry(true);
                 clientStatus.setTryTime(System.currentTimeMillis());
+                clientStatus.setPass(isPass);
+                clientStatus.setDownload(false);
+                clientStatus.setCreateId(userId);
+                clientStatus.setCreateTime(System.currentTimeMillis());
+                this.save(clientStatus);
             }
-            return this.updateById(clientStatus);
-        } else {
-            clientStatus = new ClientStatus();
-            clientStatus.setId(SystemConstant.getDbUuid());
-            clientStatus.setSchoolId(schoolId);
-            clientStatus.setMachineCode(machineCode);
-            clientStatus.setCourseCode(courseCode);
-            clientStatus.setCourseName(courseName);
-            clientStatus.setPaperNumber(paperNumber);
-            clientStatus.setTry(true);
-            clientStatus.setTryTime(System.currentTimeMillis());
-            clientStatus.setPass(isPass);
-            clientStatus.setCreateId(userId);
-            clientStatus.setCreateTime(System.currentTimeMillis());
-            return this.save(clientStatus);
         }
+        return true;
     }
 }

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

@@ -80,6 +80,9 @@ public class ExamDetailServiceImpl extends ServiceImpl<ExamDetailMapper, ExamDet
     @Resource
     AsyncCreatePdfTempleteService asyncCreatePdfTempleteService;
 
+    @Autowired
+    ClientStatusService clientStatusService;
+
     private final static Logger log = LoggerFactory.getLogger(ExamDetailServiceImpl.class);
 
     @Transactional(rollbackFor = Exception.class)
@@ -366,6 +369,23 @@ public class ExamDetailServiceImpl extends ServiceImpl<ExamDetailMapper, ExamDet
             printPlanUpdateWrapper.lambda().set(ExamPrintPlan::getStatus, PrintPlanStatusEnum.READY).eq(ExamPrintPlan::getId, detail.getPrintPlanId());
             examPrintPlanService.update(printPlanUpdateWrapper);
         }
+
+        // 当关联课程所有考场都撤回,清除提当前计划下打样记录
+        QueryWrapper<ExamDetailCourse> examDetailCourseQueryWrapper = new QueryWrapper<>();
+        examDetailCourseQueryWrapper.lambda().eq(ExamDetailCourse::getExamDetailId, detail.getId());
+        List<ExamDetailCourse> examDetailCourses = examDetailCourseService.list(examDetailCourseQueryWrapper);
+        for (ExamDetailCourse examDetailCours : examDetailCourses) {
+            List<ExamDetail> examDetailList = this.listByPrintPlanIdAndCourseCodeAndPaperNumber(detail.getSchoolId(), detail.getPrintPlanId(), examDetailCours.getCourseCode(), examDetailCours.getPaperNumber());
+            long count = examDetailList.stream().filter(m->!m.getStatus().name().equals(ExamDetailStatusEnum.NEW.name()) && !m.getStatus().name().equals(ExamDetailStatusEnum.READY.name())).count();
+            if(count == 0){
+                UpdateWrapper<ClientStatus> clientStatusUpdateWrapper = new UpdateWrapper<>();
+                clientStatusUpdateWrapper.lambda().eq(ClientStatus::getSchoolId, detail.getSchoolId())
+                        .eq(ClientStatus::getPrintPlanId, detail.getPrintPlanId())
+                        .eq(ClientStatus::getCourseCode, examDetailCours.getCourseCode())
+                        .eq(ClientStatus::getPaperNumber, examDetailCours.getPaperNumber());
+                clientStatusService.remove(clientStatusUpdateWrapper);
+            }
+        }
         return true;
     }
 

+ 20 - 3
distributed-print-business/src/main/java/com/qmth/distributed/print/business/service/impl/ExamStudentServiceImpl.java

@@ -4,6 +4,7 @@ import com.alibaba.fastjson.JSONObject;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.qmth.distributed.print.business.bean.dto.ExamStudentCourseDto;
 import com.qmth.distributed.print.business.entity.ExamDetailCourse;
 import com.qmth.distributed.print.business.entity.ExamStudent;
 import com.qmth.distributed.print.business.mapper.ExamStudentMapper;
@@ -11,6 +12,7 @@ import com.qmth.distributed.print.business.service.ExamStudentService;
 import org.apache.commons.lang3.StringUtils;
 import org.springframework.stereotype.Service;
 
+import javax.annotation.Resource;
 import java.util.List;
 import java.util.Map;
 import java.util.Objects;
@@ -27,6 +29,9 @@ import java.util.stream.Collectors;
 @Service
 public class ExamStudentServiceImpl extends ServiceImpl<ExamStudentMapper, ExamStudent> implements ExamStudentService {
 
+    @Resource
+    ExamStudentMapper examStudentMapper;
+
     @Override
     public void updatePaperType(List<Long> examDetailCourseIds, String relatePaperType) {
         UpdateWrapper<ExamStudent> updateWrapper = new UpdateWrapper<>();
@@ -39,8 +44,8 @@ public class ExamStudentServiceImpl extends ServiceImpl<ExamStudentMapper, ExamS
         QueryWrapper<ExamStudent> queryWrapper = new QueryWrapper<>();
         queryWrapper.lambda().eq(ExamStudent::getExamDetailCourseId, examDetailCourseId);
         List<ExamStudent> examStudents = this.list(queryWrapper);
-        if(!examStudents.isEmpty()){
-            List<String> strings = examStudents.stream().filter(m-> StringUtils.isNotBlank(m.getPaperType())).map(m->m.getPaperType()).distinct().collect(Collectors.toList());
+        if (!examStudents.isEmpty()) {
+            List<String> strings = examStudents.stream().filter(m -> StringUtils.isNotBlank(m.getPaperType())).map(m -> m.getPaperType()).distinct().collect(Collectors.toList());
             return strings;
         }
         return null;
@@ -50,10 +55,22 @@ public class ExamStudentServiceImpl extends ServiceImpl<ExamStudentMapper, ExamS
     public Map<String, Object> getStudentDetail(Long id) {
         Map<String, Object> map = this.baseMapper.getStudentDetail(id);
         Object extendFields = map.get("extendFields");
-        if(Objects.nonNull(extendFields)){
+        if (Objects.nonNull(extendFields)) {
             List<Map> list = JSONObject.parseArray(extendFields.toString(), Map.class);
             map.put("extendFields", list);
         }
         return map;
     }
+
+    /**
+     * 根据科目查询考生
+     *
+     * @param schoolId
+     * @param examDetailCourseIds
+     * @return
+     */
+    @Override
+    public List<ExamStudentCourseDto> queryBySchoolIdAndExamDetailCourseIds(Long schoolId, List<Long> examDetailCourseIds) {
+        return examStudentMapper.queryBySchoolIdAndExamDetailCourseIds(schoolId, examDetailCourseIds);
+    }
 }

+ 24 - 18
distributed-print-business/src/main/java/com/qmth/distributed/print/business/service/impl/ExamTaskDetailServiceImpl.java

@@ -22,6 +22,7 @@ import org.apache.commons.lang3.StringUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
+import org.springframework.util.CollectionUtils;
 
 import javax.annotation.Resource;
 import java.io.IOException;
@@ -142,7 +143,7 @@ public class ExamTaskDetailServiceImpl extends ServiceImpl<ExamTaskDetailMapper,
         ExamTask examTask = examTaskService.getById(paperParam.getExamTaskId());
         // 校验课程关联考场,是否已经提交打印
         Boolean isCreate = commonService.checkExamDetailStatus(examTask.getSchoolId(), examTask.getCourseCode(), examTask.getPaperNumber());
-        if(isCreate) {
+        if (isCreate) {
             // 提交印刷的考场,不允许修改关联试卷
             List<ExamDetail> examDetails = examDetailService.listByPrintPlanIdAndCourseCodeAndPaperNumber(examTask.getSchoolId(), paperParam.getPrintPlanId(), examTask.getCourseCode(), examTask.getPaperNumber());
             List<ExamDetail> examDetails1 = examDetails.stream().filter(m -> !ExamDetailStatusEnum.NEW.equals(m.getStatus()) && !ExamDetailStatusEnum.READY.equals(m.getStatus())).collect(Collectors.toList());
@@ -230,24 +231,29 @@ public class ExamTaskDetailServiceImpl extends ServiceImpl<ExamTaskDetailMapper,
     }
 
     @Override
-    public Map<String, String> getUrl(Long schoolId, Long examTaskId) {
-        QueryWrapper<ExamTaskDetail> examTaskDetailQueryWrapper = new QueryWrapper<>();
-        examTaskDetailQueryWrapper.lambda().eq(ExamTaskDetail::getExamTaskId, examTaskId);
-        ExamTaskDetail examTaskDetail = this.getOne(examTaskDetailQueryWrapper);
-        if (examTaskDetail != null) {
-            String relatePaperType = examTaskDetail.getRelatePaperType();
-            if (StringUtils.isNotBlank(relatePaperType)) {
-                String paperAttachmentIds = examTaskDetail.getPaperAttachmentIds();
-                List<Map> list = JSONObject.parseArray(paperAttachmentIds, Map.class);
-                String attachmentId = null;
-                for (Map map : list) {
-                    String name = map.get("name").toString();
-                    if (relatePaperType.equals(name)) {
-                        attachmentId = map.get("attachmentId").toString();
+    public Map<String, String> getUrl(Long schoolId, Long printPlanId, Long examTaskId) {
+        ExamTask examTask = examTaskService.getById(examTaskId);
+        List<ExamDetailCourse> examDetailCourses = examDetailCourseService.listByPrintPlanIdAndCourseCodeAndPaperNumber(schoolId, printPlanId, examTask.getCourseCode(), examTask.getPaperNumber());
+        if (!CollectionUtils.isEmpty(examDetailCourses)) {
+            ExamDetailCourse examDetailCourse = examDetailCourses.get(0);
+            QueryWrapper<ExamTaskDetail> examTaskDetailQueryWrapper = new QueryWrapper<>();
+            examTaskDetailQueryWrapper.lambda().eq(ExamTaskDetail::getExamTaskId, examTaskId);
+            ExamTaskDetail examTaskDetail = this.getOne(examTaskDetailQueryWrapper);
+            if (examTaskDetail != null) {
+                String relatePaperType = examTaskDetail.getRelatePaperType();
+                if (StringUtils.isNotBlank(relatePaperType)) {
+                    String paperAttachmentIds = examTaskDetail.getPaperAttachmentIds();
+                    List<Map> list = JSONObject.parseArray(paperAttachmentIds, Map.class);
+                    String attachmentId = null;
+                    for (Map map : list) {
+                        String name = map.get("name").toString();
+                        if (name.equals(examDetailCourse.getPaperType())) {
+                            attachmentId = map.get("attachmentId").toString();
+                        }
+                    }
+                    if (StringUtils.isNotBlank(attachmentId)) {
+                        return commonService.filePreviewByAttachmentId(Long.valueOf(attachmentId), false);
                     }
-                }
-                if (StringUtils.isNotBlank(attachmentId)) {
-                    return commonService.filePreviewByAttachmentId(Long.valueOf(attachmentId), false);
                 }
             }
         }

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

@@ -270,6 +270,7 @@ public class ExamTaskServiceImpl extends ServiceImpl<ExamTaskMapper, ExamTask> i
 
     @Override
     public ExamTaskImportDto importFile(MultipartFile file) throws IOException, NoSuchFieldException {
+        Long schoolId = Long.valueOf(ServletUtil.getRequestHeaderSchoolId().toString());
         List<LinkedMultiValueMap<Integer, Object>> finalList = ExcelUtil.excelReader(file.getInputStream(), Lists.newArrayList(ExamTaskTempDto.class), (finalExcelList, finalColumnNameList, finalExcelErrorList) -> {
             Map<String, String> courseCodePaperNumberMap = new HashMap<>();
             List<ExcelError> excelErrorTemp = new ArrayList<>();
@@ -291,7 +292,7 @@ public class ExamTaskServiceImpl extends ServiceImpl<ExamTaskMapper, ExamTask> i
 
                     // 课程是否存在并且与名称对应
                     QueryWrapper<BasicCourse> queryWrapper = new QueryWrapper<>();
-                    queryWrapper.lambda().eq(BasicCourse::getCode, userImportDto.getCourseCode());
+                    queryWrapper.lambda().eq(BasicCourse::getSchoolId, schoolId).eq(BasicCourse::getCode, userImportDto.getCourseCode());
                     BasicCourse course = basicCourseService.getOne(queryWrapper);
                     if (course == null) {
                         excelErrorTemp.add(new ExcelError(y + 1, "excel第" + (i + 1) + "个sheet第" + (y + 1) + "行[课程代码]在系统中不存在"));
@@ -1026,7 +1027,8 @@ public class ExamTaskServiceImpl extends ServiceImpl<ExamTaskMapper, ExamTask> i
     public List<ClientExamTaskDto> listTryTask(Long schoolId, String machineCode, Long orgId, Long printPlanId, String courseCode, String paperNumber, Boolean isTry, Boolean isPass) {
         Set<Long> orgIds = commonService.listSubOrgIds(orgId);
         // 印刷任务状态为印刷中(PRINTING),考场状态为待打印(WAITING)
-        List<ClientExamTaskDto> examTaskDtoIPage = this.baseMapper.listClientExamTaskPage(schoolId, machineCode, printPlanId, courseCode, paperNumber, isTry, isPass, orgIds, PrintPlanStatusEnum.PRINTING.name(), ExamDetailStatusEnum.WAITING.name());
+        String[] examDetailstatus = {ExamDetailStatusEnum.NEW.name(), ExamDetailStatusEnum.READY.name()};
+        List<ClientExamTaskDto> examTaskDtoIPage = this.baseMapper.listClientExamTaskPage(schoolId, machineCode, printPlanId, courseCode, paperNumber, isTry, isPass, orgIds, PrintPlanStatusEnum.PRINTING.name(), examDetailstatus);
         return examTaskDtoIPage;
     }
 

+ 8 - 8
distributed-print-business/src/main/java/com/qmth/distributed/print/business/service/impl/OrgCenterDataDisposeServiceImpl.java

@@ -44,17 +44,17 @@ public class OrgCenterDataDisposeServiceImpl implements OrgCenterDataDisposeServ
         List<Long> needDisable = new ArrayList<>();
         List<Long> needDelete = new ArrayList<>();
         for (Long aLong : oldIdList) {
-            if (!newIdList.contains(aLong)){
+            if (!newIdList.contains(aLong)) {
                 needDisable.add(aLong);
-            }else {
+            } else {
                 needDelete.add(aLong);
             }
         }
-        if (needDisable.size() > 0){
-            basicSchoolService.update(new UpdateWrapper<BasicSchool>().lambda().set(BasicSchool::getEnable,false).in(BasicSchool::getId,needDisable));
+        if (needDisable.size() > 0) {
+            basicSchoolService.update(new UpdateWrapper<BasicSchool>().lambda().set(BasicSchool::getEnable, false).in(BasicSchool::getId, needDisable));
         }
-        if (needDelete.size() > 0){
-            basicSchoolService.remove(new QueryWrapper<BasicSchool>().lambda().in(BasicSchool::getId,needDelete));
+        if (needDelete.size() > 0) {
+            basicSchoolService.remove(new QueryWrapper<BasicSchool>().lambda().in(BasicSchool::getId, needDelete));
         }
 
         for (Map map : result) {
@@ -67,10 +67,10 @@ public class OrgCenterDataDisposeServiceImpl implements OrgCenterDataDisposeServ
             Map typeMap = JSONObject.parseObject(String.valueOf(map.get("type")));
             String typeCode = String.valueOf(typeMap.get("code"));
             String typeName = String.valueOf(typeMap.get("name"));
-            if (!Arrays.stream(OrgCenterTypeEnum.values()).map(OrgCenterTypeEnum::getTypeCode).collect(Collectors.toList()).contains(typeCode)){
+            if (!Arrays.stream(OrgCenterTypeEnum.values()).map(OrgCenterTypeEnum::getTypeCode).collect(Collectors.toList()).contains(typeCode)) {
                 throw ExceptionResultEnum.ERROR.exception("机构类型在枚举中不存在 + typeCode = " + typeCode);
             }
-            if (!OrgCenterTypeEnum.PARTNER.getTypeCode().equals(typeCode)){
+            if (!OrgCenterTypeEnum.PARTNER.getTypeCode().equals(typeCode)) {
                 BasicSchool school = new BasicSchool();
                 school.setId(id);
                 school.setCode(code);

+ 28 - 6
distributed-print-business/src/main/java/com/qmth/distributed/print/business/service/impl/TBTaskServiceImpl.java

@@ -315,13 +315,35 @@ public class TBTaskServiceImpl extends ServiceImpl<TBTaskMapper, TBTask> impleme
      */
     @Override
     @Transactional
-    public void updateStatus() {
-        UpdateWrapper<TBTask> tbTaskQueryWrapper = new UpdateWrapper<>();
-        tbTaskQueryWrapper.lambda().set(TBTask::getStatus, TaskStatusEnum.FINISH)
+    public void updateStatus() throws IOException {
+        //不是自动生成pdf的全部改为失败
+        UpdateWrapper<TBTask> tbTaskUpdateWrapper = new UpdateWrapper<>();
+        tbTaskUpdateWrapper.lambda().set(TBTask::getStatus, TaskStatusEnum.FINISH)
                 .set(TBTask::getSummary, "系统提交:网络异常或程序异常中断!")
                 .set(TBTask::getResult, TaskResultEnum.ERROR)
-                .isNotNull(TBTask::getStatus).ne(TBTask::getStatus, TaskStatusEnum.FINISH);
-        this.update(tbTaskQueryWrapper);
+                .isNotNull(TBTask::getStatus).ne(TBTask::getStatus, TaskStatusEnum.FINISH)
+                .ne(TBTask::getType, TaskTypeEnum.CREATE_PDF);
+        this.update(tbTaskUpdateWrapper);
+
+        QueryWrapper<TBTask> tbTaskQueryWrapper = new QueryWrapper<>();
+        tbTaskQueryWrapper.lambda().eq(TBTask::getType, TaskTypeEnum.CREATE_PDF)
+                .ne(TBTask::getStatus, TaskStatusEnum.FINISH)
+                .ne(TBTask::getResult, TaskResultEnum.SUCCESS).or().isNull(TBTask::getResult)
+                .orderByDesc(TBTask::getStatus);
+        List<TBTask> tbTasks = this.list(tbTaskQueryWrapper);
+        if (Objects.nonNull(tbTasks) && tbTasks.size() > 0) {
+            for (TBTask tbTask : tbTasks) {
+                Map<String, Object> map = new HashMap<>();
+                if (Objects.nonNull(tbTask.getRemark())) {
+                    JSONArray jsonArray = JSONArray.parseArray(tbTask.getRemark());
+                    ArraysParams arraysParams = new ArraysParams(jsonArray.toArray(new Long[jsonArray.size()]));
+                    map.computeIfAbsent("examDetailCourseIds", v -> Arrays.asList(arraysParams.getIds()));
+                }
+                map.computeIfAbsent(SystemConstant.TASK, v -> tbTask);
+                map.computeIfAbsent(SystemConstant.USER, v -> sysUserService.getById(tbTask.getCreateId()));
+                asyncCreatePdfTempleteService.createPdf(map, null);
+            }
+        }
     }
 
     /**
@@ -341,7 +363,7 @@ public class TBTaskServiceImpl extends ServiceImpl<TBTaskMapper, TBTask> impleme
             for (TBTask tbTask : tbTasks) {
                 if (tbTask.getResetCount() < dictionaryConfig.sysDomain().getAutoCreatePdfResetMaxCount()) {
                     Map<String, Object> map = new HashMap<>();
-                    tbTask.setVersion(new AtomicInteger(tbTask.getVersion()).incrementAndGet());
+//                    tbTask.setVersion(new AtomicInteger(tbTask.getVersion()).incrementAndGet());
                     if (Objects.nonNull(tbTask.getRemark())) {
                         JSONArray jsonArray = JSONArray.parseArray(tbTask.getRemark());
                         ArraysParams arraysParams = new ArraysParams(jsonArray.toArray(new Long[jsonArray.size()]));

+ 20 - 8
distributed-print-business/src/main/java/com/qmth/distributed/print/business/templete/execute/AsyncCreatePdfTempleteService.java

@@ -6,22 +6,24 @@ import com.qmth.distributed.print.business.entity.TBTask;
 import com.qmth.distributed.print.business.enums.TaskResultEnum;
 import com.qmth.distributed.print.business.enums.TaskStatusEnum;
 import com.qmth.distributed.print.business.service.TBTaskService;
-import com.qmth.distributed.print.business.templete.create.AsyncCreateTaskTemplete;
 import com.qmth.distributed.print.business.templete.callback.CallbackCreatePdf;
+import com.qmth.distributed.print.business.templete.create.AsyncCreateTaskTemplete;
 import com.qmth.distributed.print.business.templete.service.TaskLogicService;
 import com.qmth.distributed.print.common.contant.SpringContextHolder;
 import com.qmth.distributed.print.common.contant.SystemConstant;
+import com.qmth.distributed.print.common.enums.ExceptionResultEnum;
 import com.qmth.distributed.print.common.util.Result;
 import com.qmth.distributed.print.common.util.ResultUtil;
-import org.apache.poi.ss.formula.functions.T;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.stereotype.Service;
 
 import java.io.IOException;
 import java.text.MessageFormat;
-import java.util.*;
-import java.util.concurrent.atomic.AtomicInteger;
+import java.util.Date;
+import java.util.Map;
+import java.util.Objects;
+import java.util.StringJoiner;
 
 /**
  * @Description: 创建pdf模版
@@ -61,11 +63,21 @@ public class AsyncCreatePdfTempleteService extends AsyncCreateTaskTemplete {
             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()));
             tbTask.setResult(TaskResultEnum.ERROR);
-            TBTask dbTask = tbTaskService.getById(tbTask.getId());
-            if (tbTask.getVersion() == dbTask.getVersion()) {
-                tbTask.setResetCount(new AtomicInteger(tbTask.getResetCount()).incrementAndGet());
-            }
+//            TBTask dbTask = tbTaskService.getById(tbTask.getId());
+//            if (tbTask.getVersion() == dbTask.getVersion()) {
+//                tbTask.setResetCount(new AtomicInteger(tbTask.getResetCount()).incrementAndGet());
+//            }
             if (e instanceof ApiException) {
+                if (((ApiException) e).getCode() == ExceptionResultEnum.PAPER_ERROR.getCode()
+                        || ((ApiException) e).getCode() == ExceptionResultEnum.PAPER_TYPE_ERROR.getCode()
+                        || ((ApiException) e).getCode() == ExceptionResultEnum.ATTACHMENT_IS_NULL.getCode()
+                        || ((ApiException) e).getCode() == ExceptionResultEnum.EXAM_PRINT_IS_NULL.getCode()
+                        || ((ApiException) e).getCode() == ExceptionResultEnum.EXAM_RULE_IS_NULL.getCode()
+                        || ((ApiException) e).getCode() == ExceptionResultEnum.EXAM_DETAIL_IS_NULL.getCode()
+                        || ((ApiException) e).getCode() == ExceptionResultEnum.EXAM_CARD_IS_NULL.getCode()
+                        || ((ApiException) e).getCode() == ExceptionResultEnum.EXAM_TASK_IS_NULL.getCode()) {
+                    tbTask.setErrorMessage(e.getMessage());
+                }
                 ResultUtil.error((ApiException) e, e.getMessage());
             } else {
                 ResultUtil.error(e.getMessage());

+ 1 - 1
distributed-print-business/src/main/java/com/qmth/distributed/print/business/templete/export/AsyncExportTaskTemplete.java

@@ -51,7 +51,7 @@ public abstract class AsyncExportTaskTemplete {
      * @param map
      * @return
      */
-    @Async("taskThreadPool")
+    @Async
     public abstract Result exportTask(Map<String, Object> map) throws Exception;
 
     /**

+ 6 - 5
distributed-print-business/src/main/java/com/qmth/distributed/print/business/templete/importData/AsyncImportTaskTemplete.java

@@ -54,7 +54,7 @@ public abstract class AsyncImportTaskTemplete {
      * @return
      * @throws IOException
      */
-    @Async("taskThreadPool")
+    @Async
     public abstract Result importTask(Map<String, Object> map) throws IOException, Exception;
 
     /**
@@ -140,10 +140,10 @@ public abstract class AsyncImportTaskTemplete {
             stringJoinerSummary.add(MessageFormat.format("{0}{1}{2}{3}", DateUtil.format(new Date(), SystemConstant.DEFAULT_DATE_PATTERN), EXCEPTION_CREATE_TXT_TITLE, EXCEPTION_DATA, e.getMessage()));
             tbTask.setSummary(stringJoinerSummary.toString());
             tbTask.setResult(TaskResultEnum.ERROR);
-            TBTask dbTask = tbTaskService.getById(tbTask.getId());
-            if (tbTask.getVersion() == dbTask.getVersion()) {
-                tbTask.setResetCount(new AtomicInteger(tbTask.getResetCount()).incrementAndGet());
-            }
+//            TBTask dbTask = tbTaskService.getById(tbTask.getId());
+//            if (tbTask.getVersion() == dbTask.getVersion()) {
+//                tbTask.setResetCount(new AtomicInteger(tbTask.getResetCount()).incrementAndGet());
+//            }
             if (e instanceof ApiException) {
                 ResultUtil.error((ApiException) e, e.getMessage());
             } else {
@@ -166,6 +166,7 @@ public abstract class AsyncImportTaskTemplete {
                 tbTask.setResultFilePath(tbTask.getImportFilePath());
                 tbTask.setImportFileName(null);
                 tbTask.setImportFilePath(null);
+                tbTask.setErrorMessage(null);
             }
             tbTaskService.updateById(tbTask);
         }

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

@@ -7,6 +7,7 @@ import com.alibaba.fastjson.JSONObject;
 import com.aliyun.oss.common.utils.BinaryUtil;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
+import com.itextpdf.text.DocumentException;
 import com.qmth.boot.api.exception.ApiException;
 import com.qmth.distributed.print.business.annotation.ExcelDBFieldDesc;
 import com.qmth.distributed.print.business.bean.dto.*;
@@ -47,6 +48,7 @@ import java.io.*;
 import java.lang.reflect.Field;
 import java.time.LocalDateTime;
 import java.util.*;
+import java.util.function.Function;
 import java.util.stream.Collectors;
 
 /**
@@ -117,6 +119,9 @@ public class TaskLogicServiceImpl implements TaskLogicService {
     @Resource
     TBTaskService tbTaskService;
 
+    @Resource
+    BasicCardRuleService basicCardRuleService;
+
     /**
      * 创建pdf前置条件
      *
@@ -133,7 +138,7 @@ public class TaskLogicServiceImpl implements TaskLogicService {
         //查询printPlan
         ExamPrintPlan examPrintPlan = examPrintPlanService.getById(tbTask.getPrintPlanId());
         if (Objects.isNull(examPrintPlan)) {
-            throw ExceptionResultEnum.ERROR.exception("印刷计划为空");
+            throw ExceptionResultEnum.EXAM_PRINT_IS_NULL.exception();
         }
         UpdateWrapper<ExamDetail> examDetailQueryWrapper = new UpdateWrapper<>();
         examDetailQueryWrapper.lambda().eq(ExamDetail::getSchoolId, sysUser.getSchoolId())
@@ -160,6 +165,208 @@ public class TaskLogicServiceImpl implements TaskLogicService {
         return map;
     }
 
+    /**
+     * 创建pdf核心逻辑
+     *
+     * @param examDetailCourseList
+     * @param examPrintPlan
+     * @param examDetail
+     * @param sysUser
+     * @param paperTypeParam
+     * @param basicAttachmentList
+     * @param attachmentIds
+     * @param list
+     * @return
+     * @throws IOException
+     * @throws DocumentException
+     */
+    @Transactional
+    public List<BasicAttachment> createPdfCoreLogic(List<ExamDetailCourse> examDetailCourseList,
+                                                    ExamPrintPlan examPrintPlan,
+                                                    ExamDetail examDetail,
+                                                    SysUser sysUser,
+                                                    String paperTypeParam,
+                                                    List<BasicAttachment> basicAttachmentList,
+                                                    Set<Long> attachmentIds,
+                                                    List<PdfDto>... list
+    ) throws IOException, DocumentException {
+        if (Objects.nonNull(examDetailCourseList) && examDetailCourseList.size() > 0) {
+            Map<Long, BasicCardRule> basicCardRuleMap = new HashMap<>();
+            for (ExamDetailCourse examDetailCourse : examDetailCourseList) {
+                List<PdfDto> paperPdfTempList = new ArrayList<>();//所有试卷
+                List<PdfDto> examStudentTempPdfList = new ArrayList<>();//所有题卡
+                List<PdfDto> backupPaperTempPdfList = new ArrayList<>();//备份试卷
+                List<PdfDto> cardPdfTempList = new ArrayList<>();//备份题卡
+
+                //查询试卷
+                QueryWrapper<ExamTask> examTaskQueryWrapper = new QueryWrapper<>();
+                examTaskQueryWrapper.lambda().eq(ExamTask::getSchoolId, sysUser.getSchoolId())
+                        .eq(ExamTask::getCourseCode, examDetailCourse.getCourseCode())
+                        .eq(ExamTask::getCourseName, examDetailCourse.getCourseName())
+                        .eq(ExamTask::getPaperNumber, examDetailCourse.getPaperNumber())
+                        .eq(ExamTask::getEnable, true)
+                        .eq(ExamTask::getStatus, ExamStatusEnum.FINISH)
+                        .orderByAsc(ExamTask::getPaperNumber);
+                List<ExamTask> examTaskList = examTaskService.list(examTaskQueryWrapper);
+                if (Objects.isNull(examTaskList) || examTaskList.size() == 0) {
+                    throw ExceptionResultEnum.EXAM_TASK_IS_NULL.exception();
+                }
+                Set<Long> examTaskIds = examTaskList.stream().map(s -> s.getId()).collect(Collectors.toSet());
+                Map<Long, ExamTask> examTaskMap = examTaskList.stream().collect(
+                        Collectors.toMap(ExamTask::getId, Function.identity(), (dto1, dto2) -> dto1));
+
+                QueryWrapper<ExamTaskDetail> examTaskDetailQueryWrapper = new QueryWrapper<>();
+                examTaskDetailQueryWrapper.lambda().in(ExamTaskDetail::getExamTaskId, examTaskIds)
+                        .eq(ExamTaskDetail::getEnable, true);
+                List<ExamTaskDetail> examTaskDetailList = examTaskDetailService.list(examTaskDetailQueryWrapper);
+                JSONObject jsonObject = new JSONObject();
+                JSONArray jsonArray = new JSONArray();
+                for (ExamTaskDetail examTaskDetail : examTaskDetailList) {
+                    //查询题卡
+                    ExamCard examCard = examCardService.getById(examTaskDetail.getCardId());
+                    if (Objects.isNull(examCard)) {
+                        throw ExceptionResultEnum.EXAM_CARD_IS_NULL.exception();
+                    }
+
+                    //查询题卡规则
+                    ExamTask examTask = examTaskMap.get(examTaskDetail.getExamTaskId());
+                    BasicCardRule basicCardRule = null;
+                    if (Objects.nonNull(examTask)) {
+                        if (!basicCardRuleMap.containsKey(examTask.getCardRuleId())) {
+                            basicCardRule = basicCardRuleService.getById(examTask.getCardRuleId());
+                            BasicCardRule finalBasicCardRule = basicCardRule;
+                            basicCardRuleMap.computeIfAbsent(examTask.getCardRuleId(), v -> finalBasicCardRule);
+                        } else {
+                            basicCardRule = basicCardRuleMap.get(examTask.getCardRuleId());
+                        }
+                    }
+                    QueryWrapper<ExamCardDetail> examCardDetailQueryWrapper = new QueryWrapper<>();
+                    examCardDetailQueryWrapper.lambda().eq(ExamCardDetail::getCardId, examCard.getId());
+                    List<ExamCardDetail> examCardDetailList = examCardDetailService.list(examCardDetailQueryWrapper);
+
+                    //拼装key
+                    String key = examDetail.getSchoolId()
+                            + "_" + examDetail.getExamStartTime()
+                            + "_" + examDetail.getExamEndTime()
+                            + "_" + examDetailCourse.getCourseCode()
+                            + "_" + examDetailCourse.getPaperNumber();
+                    String paperType = null;
+                    if (Objects.nonNull(paperTypeParam)) {
+                        paperType = paperTypeParam;
+                        CreatePdfCacheUtil.setPaperType(key, paperType);
+                    } else {
+                        paperType = createPdfUtil.getPaperType(examPrintPlan, examTaskDetail, key);//抽取卷型
+                    }
+                    examTaskDetail.setRelatePaperType(paperType);
+                    examDetailCourse.setPaperType(paperType);
+
+                    PaperPdfDto paperPdfDto = createPdfUtil.getPaperPdfFile(paperType, examTaskDetail);
+
+                    //获取试卷pdf
+                    PdfDto pdfDto = createPdfUtil.getPaperPdf(paperPdfDto, examPrintPlan.getBackupCount(), backupPaperTempPdfList);
+                    examDetailCourse.setPaperPagesA3(Objects.nonNull(pdfDto) ? pdfDto.getPageCount() : examDetailCourse.getPaperPagesA3());
+                    list[0].addAll(backupPaperTempPdfList);
+
+                    basicAttachmentList = Objects.isNull(basicAttachmentList) ? basicAttachmentList = new ArrayList<>() : basicAttachmentList;
+                    for (ExamCardDetail examCardDetail : examCardDetailList) {
+                        createPdfUtil.getCardAttachmentId(examCardDetail, attachmentIds);
+
+                        //把模板页面上的 ${} 替换成实际内容
+                        String cardContent = createPdfUtil.replaceHtmlTemplete(examCardDetail);
+                        String studentContent = cardContent;
+
+                        for (int i = 1; i <= examPrintPlan.getBackupCount(); i++) {
+                            BasicAttachment basicAttachment = createPdfUtil.cardHtml(String.format("%02d", i), cardContent, examDetail, examDetailCourse, examCard, jsonArray, sysUser.getId(), cardPdfTempList, basicCardRule);
+                            examDetailCourse.setCardPagesA3(basicAttachment.getPages());
+                            basicAttachmentList.add(basicAttachment);
+                        }
+                        list[1].addAll(cardPdfTempList);
+
+                        //查询考生
+                        QueryWrapper<ExamStudent> examStudentQueryWrapper = new QueryWrapper<>();
+                        examStudentQueryWrapper.lambda().eq(ExamStudent::getSchoolId, sysUser.getSchoolId())
+                                .eq(ExamStudent::getExamDetailCourseId, examDetailCourse.getId());
+                        List<ExamStudent> examStudentList = examStudentService.list(examStudentQueryWrapper);
+
+                        for (ExamStudent t : examStudentList) {
+                            if (Objects.nonNull(pdfDto)) {
+                                createPdfUtil.getExamStudentPaperPdf(paperPdfDto, paperPdfTempList);
+                            }
+                            basicAttachmentList.add(createPdfUtil.examStudentHtml(attachmentIds, studentContent, t, examDetail, examDetailCourse, sysUser.getId(), examStudentTempPdfList));
+                        }
+                        list[2].addAll(paperPdfTempList);
+                        list[3].addAll(examStudentTempPdfList);
+                        examStudentService.saveOrUpdateBatch(examStudentList);
+                        jsonObject.put("card", jsonArray);
+                        examCardDetail.setAttachmentId(jsonObject.toJSONString());
+                    }
+                    examCardDetailService.saveOrUpdateBatch(examCardDetailList);
+                }
+                examTaskDetailService.saveOrUpdateBatch(examTaskDetailList);
+            }
+            detailCourseService.saveOrUpdateBatch(examDetailCourseList);
+        }
+        return basicAttachmentList;
+    }
+
+    /**
+     * 创建A4文件
+     *
+     * @param examPrintPlan
+     * @param examDetail
+     * @param basicSchool
+     * @param ftlList
+     * @param examDetailCourseListIds
+     * @param list
+     * @throws IOException
+     * @throws DocumentException
+     */
+    @Transactional
+    public void createA4File(ExamPrintPlan examPrintPlan, ExamDetail examDetail, BasicSchool basicSchool, Set<File> ftlList, List<Long> examDetailCourseListIds, List<PdfDto>... list) throws IOException, DocumentException {
+        if (Objects.nonNull(examPrintPlan.getOrdinaryContent())) {
+            //获取普通印品
+            JSONArray jsonArrayOrdinary = JSONArray.parseArray(examPrintPlan.getOrdinaryContent());
+            for (int i = 0; i < jsonArrayOrdinary.size(); i++) {
+                JSONObject jsonObjectOrdinary = jsonArrayOrdinary.getJSONObject(i);
+                if (Objects.nonNull(jsonObjectOrdinary.get("attachmentId")) && !Objects.equals("", jsonObjectOrdinary.get("attachmentId"))) {
+                    Long attachmentId = Long.parseLong((String) jsonObjectOrdinary.get("attachmentId"));
+                    BasicAttachment basicAttachment = basicAttachmentService.getById(attachmentId);
+                    createPdfUtil.createCheckIn(examDetail, basicAttachment, list[0], (Integer) jsonObjectOrdinary.get("backupCount"));
+                }
+            }
+        }
+
+        if (Objects.nonNull(examPrintPlan.getVariableContent())) {
+            List<ExamStudentCourseDto> examStudentCourseDtoList = examStudentService.queryBySchoolIdAndExamDetailCourseIds(basicSchool.getId(), examDetailCourseListIds);
+            int count = (int) examStudentCourseDtoList.stream().filter(s -> s.getPaperPageA3() > 2).count();
+            boolean tag = count > 0 ? true : false;
+
+            //获取变量印品
+            JSONArray jsonArrayVariable = JSONArray.parseArray(examPrintPlan.getVariableContent());
+            for (int i = 0; i < jsonArrayVariable.size(); i++) {
+                JSONObject jsonObjectVariable = jsonArrayVariable.getJSONObject(i);
+                String type = (String) jsonObjectVariable.get("type");
+                if (Objects.nonNull(jsonObjectVariable.get("attachmentId")) && !Objects.equals("", jsonObjectVariable.get("attachmentId"))) {
+                    Long attachmentId = Long.parseLong((String) jsonObjectVariable.get("attachmentId"));
+                    BasicAttachment basicAttachment = basicAttachmentService.getById(attachmentId);
+                    ftlList.add(commonService.getFile(basicAttachment.getPath(), false));
+                    if (Objects.nonNull(type) && Objects.equals(type.toUpperCase(), "SIGN")) {//签到表
+                        createPdfUtil.createSignBook(basicAttachment, basicSchool.getName(), examDetail, examStudentCourseDtoList, list[1], (Integer) jsonObjectVariable.get("backupCount"));
+                    } else if (Objects.nonNull(type) && Objects.equals(type.toUpperCase(), "PACKAGE")) {//卷袋贴
+                        createPdfUtil.createPaperPackage(tag, basicAttachment, basicSchool.getName(), examDetail, examStudentCourseDtoList, list[1], (Integer) jsonObjectVariable.get("backupCount"));
+                    }
+                }
+            }
+        }
+
+        Collections.sort(list[1], new Comparator<PdfDto>() {
+            @Override
+            public int compare(PdfDto o1, PdfDto o2) {
+                return o1.getSequence() > o2.getSequence() ? 1 : -1;
+            }
+        });
+    }
+
     /**
      * 创建pdf逻辑
      *
@@ -167,7 +374,7 @@ public class TaskLogicServiceImpl implements TaskLogicService {
      * @return
      */
     @Override
-    @Transactional
+//    @Transactional
     public Map<String, Object> executeCreatePdfLogic(Map<String, Object> map) throws IOException {
         List<BasicAttachment> basicAttachmentList = null;
         try {
@@ -179,21 +386,16 @@ public class TaskLogicServiceImpl implements TaskLogicService {
             List<Long> examDetailCourseIds = Objects.nonNull(map.get("examDetailCourseIds")) ? (List<Long>) map.get("examDetailCourseIds") : null;
             String paperTypeParam = Objects.nonNull(map.get("paperType")) ? (String) map.get("paperType") : null;
 
-            //这里为保存附件html的逻辑
-            //查询题卡详情是否有附件id,有的话则把以前的附件删除
-            Set<Long> attachmentIds = null;
-            Set<File> ftlList = null;
-
             //查询printPlan
             ExamPrintPlan examPrintPlan = examPrintPlanService.getById(tbTask.getPrintPlanId());
             if (Objects.isNull(examPrintPlan)) {
-                throw ExceptionResultEnum.ERROR.exception("印刷计划为空");
+                throw ExceptionResultEnum.EXAM_PRINT_IS_NULL.exception();
             }
 
             BasicSchool basicSchool = cacheService.schoolCache(examPrintPlan.getSchoolId());
             BasicExamRule basicExamRule = basicExamRuleService.getBySchoolId(schoolId);
             if (Objects.isNull(basicExamRule)) {
-                throw ExceptionResultEnum.ERROR.exception("考务规则为空");
+                throw ExceptionResultEnum.EXAM_RULE_IS_NULL.exception();
             }
 
             //查询examDetail
@@ -207,10 +409,10 @@ public class TaskLogicServiceImpl implements TaskLogicService {
             }
             List<ExamDetail> examDetailList = detailService.list(examDetailQueryWrapper);
             if (Objects.isNull(examDetailList) || examDetailList.size() == 0) {
-                throw ExceptionResultEnum.ERROR.exception("考务计划为空");
+                throw ExceptionResultEnum.EXAM_DETAIL_IS_NULL.exception();
             }
-            attachmentIds = Objects.isNull(attachmentIds) ? attachmentIds = new HashSet<>() : attachmentIds;
-            ftlList = Objects.isNull(ftlList) ? ftlList = new HashSet<>() : ftlList;
+            Set<Long> attachmentIds = new HashSet<>();
+            Set<File> ftlList = new HashSet<>();
             for (ExamDetail examDetail : examDetailList) {
                 tbTask.setObjName(examDetail.getExamRoom() + "-" + examDetail.getExamPlace());
                 //查询examDetailCourse
@@ -221,161 +423,40 @@ public class TaskLogicServiceImpl implements TaskLogicService {
                     examDetailCourseQueryWrapper.lambda().eq(ExamDetailCourse::getExamDetailId, examDetail.getId());
                 }
                 List<ExamDetailCourse> examDetailCourseList = detailCourseService.list(examDetailCourseQueryWrapper);
-                if (Objects.nonNull(examDetailCourseList) && examDetailCourseList.size() > 0) {
-                    List<PdfDto> variablePdfList = new ArrayList<>();//变量印品(签到表、卷袋贴)
-                    List<PdfDto> ordinaryPdfList = new ArrayList<>();//普通印品(登记表)
-                    List<PdfDto> paperPdfList = new ArrayList<>();//所有试卷
-                    List<PdfDto> examStudentPdfList = new ArrayList<>();//所有题卡
-                    List<PdfDto> backupPaperPdfList = new ArrayList<>();//备份试卷
-                    List<PdfDto> cardPdfList = new ArrayList<>();//备份题卡
-
-                    for (ExamDetailCourse examDetailCourse : examDetailCourseList) {
-                        if (Objects.nonNull(examPrintPlan.getOrdinaryContent())) {
-                            //获取普通印品
-                            JSONArray jsonArrayOrdinary = JSONArray.parseArray(examPrintPlan.getOrdinaryContent());
-                            for (int i = 0; i < jsonArrayOrdinary.size(); i++) {
-                                JSONObject jsonObjectOrdinary = jsonArrayOrdinary.getJSONObject(i);
-                                if (Objects.nonNull(jsonObjectOrdinary.get("attachmentId")) && !Objects.equals("", jsonObjectOrdinary.get("attachmentId"))) {
-                                    Long attachmentId = Long.parseLong((String) jsonObjectOrdinary.get("attachmentId"));
-                                    BasicAttachment basicAttachment = basicAttachmentService.getById(attachmentId);
-                                    createPdfUtil.createCheckIn(examDetail, basicAttachment, ordinaryPdfList, (Integer) jsonObjectOrdinary.get("backupCount"));
-                                }
-                            }
-                        }
-
-                        List<PdfDto> paperPdfTempList = new ArrayList<>();//所有试卷
-                        List<PdfDto> examStudentTempPdfList = new ArrayList<>();//所有题卡
-                        List<PdfDto> backupPaperTempPdfList = new ArrayList<>();//备份试卷
-                        List<PdfDto> cardPdfTempList = new ArrayList<>();//备份题卡
-
-                        //查询试卷
-                        QueryWrapper<ExamTask> examTaskQueryWrapper = new QueryWrapper<>();
-                        examTaskQueryWrapper.lambda().eq(ExamTask::getSchoolId, sysUser.getSchoolId())
-                                .eq(ExamTask::getCourseCode, examDetailCourse.getCourseCode())
-                                .eq(ExamTask::getCourseName, examDetailCourse.getCourseName())
-                                .eq(ExamTask::getPaperNumber, examDetailCourse.getPaperNumber())
-                                .eq(ExamTask::getEnable, true)
-                                .eq(ExamTask::getStatus, ExamStatusEnum.FINISH)
-                                .orderByAsc(ExamTask::getPaperNumber);
-                        List<ExamTask> examTaskList = examTaskService.list(examTaskQueryWrapper);
-                        if (Objects.isNull(examTaskList) || examTaskList.size() == 0) {
-                            throw ExceptionResultEnum.ERROR.exception("命题任务为空");
-                        }
-                        Set<Long> examTaskIds = examTaskList.stream().map(s -> s.getId()).collect(Collectors.toSet());
-
-                        QueryWrapper<ExamTaskDetail> examTaskDetailQueryWrapper = new QueryWrapper<>();
-                        examTaskDetailQueryWrapper.lambda().in(ExamTaskDetail::getExamTaskId, examTaskIds)
-                                .eq(ExamTaskDetail::getEnable, true);
-                        List<ExamTaskDetail> examTaskDetailList = examTaskDetailService.list(examTaskDetailQueryWrapper);
-                        JSONObject jsonObject = new JSONObject();
-                        JSONArray jsonArray = new JSONArray();
-                        for (ExamTaskDetail examTaskDetail : examTaskDetailList) {
-                            //查询题卡
-                            ExamCard examCard = examCardService.getById(examTaskDetail.getCardId());
-                            if (Objects.isNull(examCard)) {
-                                throw ExceptionResultEnum.ERROR.exception("题卡为空");
-                            }
-                            QueryWrapper<ExamCardDetail> examCardDetailQueryWrapper = new QueryWrapper<>();
-                            examCardDetailQueryWrapper.lambda().eq(ExamCardDetail::getCardId, examCard.getId());
-                            List<ExamCardDetail> examCardDetailList = examCardDetailService.list(examCardDetailQueryWrapper);
-
-                            //拼装key
-                            String key = examDetail.getSchoolId()
-                                    + "_" + examDetail.getExamStartTime()
-                                    + "_" + examDetail.getExamEndTime()
-                                    + "_" + examDetailCourse.getCourseCode()
-                                    + "_" + examDetailCourse.getPaperNumber();
-                            String paperType = null;
-                            if (Objects.nonNull(paperTypeParam)) {
-                                paperType = paperTypeParam;
-                                CreatePdfCacheUtil.setPaperType(key, paperType);
-                            } else {
-                                paperType = createPdfUtil.getPaperType(examPrintPlan, examTaskDetail, key);//抽取卷型
-                            }
-                            examTaskDetail.setRelatePaperType(paperType);
-                            examDetailCourse.setPaperType(paperType);
-
-                            PaperPdfDto paperPdfDto = createPdfUtil.getPaperPdfFile(paperType, examTaskDetail);
-
-                            //获取试卷pdf
-                            PdfDto pdfDto = createPdfUtil.getPaperPdf(paperPdfDto, examPrintPlan.getBackupCount(), backupPaperTempPdfList);
-                            examDetailCourse.setPaperPagesA3(Objects.nonNull(pdfDto) ? pdfDto.getPageCount() : examDetailCourse.getPaperPagesA3());
-                            backupPaperPdfList.addAll(backupPaperTempPdfList);
-
-                            basicAttachmentList = Objects.isNull(basicAttachmentList) ? basicAttachmentList = new ArrayList<>() : basicAttachmentList;
-                            for (ExamCardDetail examCardDetail : examCardDetailList) {
-                                createPdfUtil.getCardAttachmentId(examCardDetail, attachmentIds);
-
-                                //把模板页面上的 ${} 替换成实际内容
-                                String cardContent = createPdfUtil.replaceHtmlTemplete(examCardDetail);
-                                String studentContent = cardContent;
-
-                                for (int i = 1; i <= examPrintPlan.getBackupCount(); i++) {
-                                    BasicAttachment basicAttachment = createPdfUtil.cardHtml(String.format("%02d", i), cardContent, examDetail, examDetailCourse, examCard, jsonArray, sysUser.getId(), cardPdfTempList);
-                                    examDetailCourse.setCardPagesA3(basicAttachment.getPages());
-                                    basicAttachmentList.add(basicAttachment);
-                                }
-                                cardPdfList.addAll(cardPdfTempList);
-
-                                //查询考生
-                                QueryWrapper<ExamStudent> examStudentQueryWrapper = new QueryWrapper<>();
-                                examStudentQueryWrapper.lambda().eq(ExamStudent::getSchoolId, sysUser.getSchoolId())
-                                        .eq(ExamStudent::getExamDetailCourseId, examDetailCourse.getId());
-                                List<ExamStudent> examStudentList = examStudentService.list(examStudentQueryWrapper);
-
-                                if (Objects.nonNull(examPrintPlan.getVariableContent())) {
-                                    //获取变量印品
-                                    JSONArray jsonArrayVariable = JSONArray.parseArray(examPrintPlan.getVariableContent());
-                                    for (int i = 0; i < jsonArrayVariable.size(); i++) {
-                                        JSONObject jsonObjectVariable = jsonArrayVariable.getJSONObject(i);
-                                        String type = (String) jsonObjectVariable.get("type");
-                                        if (Objects.nonNull(jsonObjectVariable.get("attachmentId")) && !Objects.equals("", jsonObjectVariable.get("attachmentId"))) {
-                                            Long attachmentId = Long.parseLong((String) jsonObjectVariable.get("attachmentId"));
-                                            BasicAttachment basicAttachment = basicAttachmentService.getById(attachmentId);
-                                            ftlList.add(commonService.getFile(basicAttachment.getPath(), false));
-                                            if (Objects.nonNull(type) && Objects.equals(type.toUpperCase(), "SIGN")) {//签到表
-                                                createPdfUtil.createSignBook(basicAttachment, basicSchool.getName(), examDetail, examDetailCourse, examStudentList, variablePdfList, (Integer) jsonObjectVariable.get("backupCount"));
-                                            } else if (Objects.nonNull(type) && Objects.equals(type.toUpperCase(), "PACKAGE")) {//卷袋贴
-                                                if (Objects.nonNull(pdfDto)) {
-                                                    createPdfUtil.createPaperPackage(pdfDto.isTag(), basicAttachment, basicSchool.getName(), examDetail, examDetailCourse, examStudentList, variablePdfList, (Integer) jsonObjectVariable.get("backupCount"));
-                                                }
-                                            }
-                                        }
-                                    }
-                                }
-
-                                Collections.sort(variablePdfList, new Comparator<PdfDto>() {
-                                    @Override
-                                    public int compare(PdfDto o1, PdfDto o2) {
-                                        return o1.getSequence() > o2.getSequence() ? 1 : -1;
-                                    }
-                                });
-
-                                for (ExamStudent t : examStudentList) {
-                                    if (Objects.nonNull(pdfDto)) {
-                                        createPdfUtil.getExamStudentPaperPdf(paperPdfDto, paperPdfTempList);
-                                    }
-                                    basicAttachmentList.add(createPdfUtil.examStudentHtml(attachmentIds, studentContent, t, examDetail, examDetailCourse, sysUser.getId(), examStudentTempPdfList));
-                                }
-                                paperPdfList.addAll(paperPdfTempList);
-                                examStudentPdfList.addAll(examStudentTempPdfList);
-                                examStudentService.saveOrUpdateBatch(examStudentList);
-                                jsonObject.put("card", jsonArray);
-                                examCardDetail.setAttachmentId(jsonObject.toJSONString());
-                            }
-                            examCardDetailService.saveOrUpdateBatch(examCardDetailList);
-                        }
-                        examTaskDetailService.saveOrUpdateBatch(examTaskDetailList);
-                    }
-                    detailCourseService.saveOrUpdateBatch(examDetailCourseList);
-                    //合并pdf
-                    basicAttachmentList.add(createPdfUtil.mergePdf(basicExamRule, tbTask, examDetail, sysUser.getId(), schoolId, variablePdfList, ordinaryPdfList, paperPdfList, examStudentPdfList, backupPaperPdfList, cardPdfList));
-                }
-            }
-            if (PrintMethodEnum.AUTO == basicExamRule.getPrintMethod()) {
-                examPrintPlan.setStatus(PrintPlanStatusEnum.PRINTING);
-                examPrintPlanService.updateById(examPrintPlan);
+                List<Long> examDetailCourseListIds = examDetailCourseList.stream().map(s -> s.getId()).collect(Collectors.toList());
+
+                List<PdfDto> variablePdfList = new ArrayList<>();//变量印品(签到表、卷袋贴)
+                List<PdfDto> ordinaryPdfList = new ArrayList<>();//普通印品(登记表)
+                List<PdfDto> paperPdfList = new ArrayList<>();//所有试卷
+                List<PdfDto> examStudentPdfList = new ArrayList<>();//所有题卡
+                List<PdfDto> backupPaperPdfList = new ArrayList<>();//备份试卷
+                List<PdfDto> cardPdfList = new ArrayList<>();//备份题卡
+
+                //创建pdf核心逻辑
+                basicAttachmentList = createPdfCoreLogic(examDetailCourseList,
+                        examPrintPlan,
+                        examDetail,
+                        sysUser,
+                        paperTypeParam,
+                        basicAttachmentList,
+                        attachmentIds,
+                        backupPaperPdfList,
+                        cardPdfList,
+                        paperPdfList,
+                        examStudentPdfList);
+
+                createA4File(examPrintPlan, examDetail, basicSchool, ftlList, examDetailCourseListIds, ordinaryPdfList, variablePdfList);
+
+                //合并pdf
+                String dirNameA3 = createPdfUtil.mergeA3Pdf(paperPdfList, examStudentPdfList, backupPaperPdfList, cardPdfList);
+                String dirNameA4 = createPdfUtil.mergeA4Pdf(variablePdfList, ordinaryPdfList);
+
+                List<PdfDto> mergePdfDeleteList = new ArrayList<>();
+                mergePdfDeleteList.addAll(examStudentPdfList);
+                mergePdfDeleteList.addAll(cardPdfList);
+                basicAttachmentList.add(createPdfUtil.mergePdfSaveDb(dirNameA4, dirNameA3, tbTask, sysUser.getId(), examDetail, basicExamRule, mergePdfDeleteList));
             }
+            updateExamPrintPlan(basicExamRule, examPrintPlan);
             map.computeIfAbsent("size", v -> examDetailList.size());
             //最后一步删除附件
 //            createPdfUtil.deleteAttachment(attachmentIds, ftlList);
@@ -391,6 +472,20 @@ public class TaskLogicServiceImpl implements TaskLogicService {
         return map;
     }
 
+    /**
+     * 更新考试计划
+     *
+     * @param basicExamRule
+     * @param examPrintPlan
+     */
+    @Transactional
+    public void updateExamPrintPlan(BasicExamRule basicExamRule, ExamPrintPlan examPrintPlan) {
+        if (PrintMethodEnum.AUTO == basicExamRule.getPrintMethod()) {
+            examPrintPlan.setStatus(PrintPlanStatusEnum.PRINTING);
+            examPrintPlanService.updateById(examPrintPlan);
+        }
+    }
+
     @Transactional(rollbackFor = Exception.class)
     @Override
     public Map<String, Object> executeExaminationLogic(Map<String, Object> map) throws Exception {

+ 101 - 50
distributed-print-business/src/main/java/com/qmth/distributed/print/business/util/CreatePdfUtil.java

@@ -6,6 +6,7 @@ import com.alibaba.fastjson.JSONObject;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.google.gson.Gson;
 import com.itextpdf.text.DocumentException;
+import com.qmth.distributed.print.business.bean.dto.ExamStudentCourseDto;
 import com.qmth.distributed.print.business.bean.dto.ExamStudentDto;
 import com.qmth.distributed.print.business.bean.dto.PaperPdfDto;
 import com.qmth.distributed.print.business.bean.dto.PdfDto;
@@ -21,6 +22,7 @@ import org.apache.commons.codec.digest.DigestUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.stereotype.Component;
+import org.springframework.transaction.annotation.Transactional;
 
 import javax.annotation.Resource;
 import java.io.File;
@@ -68,7 +70,7 @@ public class CreatePdfUtil {
      */
     public void createCheckIn(ExamDetail examDetail, BasicAttachment basicAttachment, List<PdfDto> ordinaryPdfList, Integer printCount) throws IOException, DocumentException {
         if (Objects.isNull(basicAttachment)) {
-            throw ExceptionResultEnum.ERROR.exception("找不到附件");
+            throw ExceptionResultEnum.ATTACHMENT_IS_NULL.exception();
         }
         String type = basicAttachment.getType();
         JSONObject jsonObject = JSONObject.parseObject(basicAttachment.getPath());
@@ -91,29 +93,32 @@ public class CreatePdfUtil {
      * @param tag
      * @param basicAttachment
      * @param schoolName
-     * @param examDetailCourse
      * @param examStudentList
      * @param variablePdfList
      * @param printCount
      * @throws IOException
      */
-    public void createPaperPackage(boolean tag, BasicAttachment basicAttachment, String schoolName, ExamDetail examDetail, ExamDetailCourse examDetailCourse, List<ExamStudent> examStudentList, List<PdfDto> variablePdfList, Integer printCount) throws IOException {
+    public void createPaperPackage(boolean tag, BasicAttachment basicAttachment, String schoolName, ExamDetail examDetail, List<ExamStudentCourseDto> examStudentList, List<PdfDto> variablePdfList, Integer printCount) throws IOException {
         if (Objects.isNull(basicAttachment)) {
-            throw ExceptionResultEnum.ERROR.exception("找不到附件");
+            throw ExceptionResultEnum.ATTACHMENT_IS_NULL.exception();
         }
         Map<String, Object> htmlMap = new HashMap<>();
-        htmlMap.put("examDetailCourseId", examDetailCourse.getId());
+        if (Objects.nonNull(examStudentList) && examStudentList.size() > 0) {
+            htmlMap.put("examDetailCourseId", examStudentList.get(0).getExamDetailCourseId());
+            htmlMap.put("courseName", examStudentList.get(0).getCourseName());
+            htmlMap.put("courseCode", examStudentList.get(0).getCourseCode());
+        } else {
+            htmlMap.put("examDetailCourseId", "");
+            htmlMap.put("courseName", "");
+            htmlMap.put("courseCode", "");
+        }
         htmlMap.put("schoolName", schoolName);
-        htmlMap.put("courseName", examDetailCourse.getCourseName());
-        htmlMap.put("courseCode", examDetailCourse.getCourseCode());
         htmlMap.put("examSite", examDetail.getExamPlace());
         htmlMap.put("examRoom", examDetail.getExamRoom());
         htmlMap.put("startTime", DateUtil.format(new Date(examDetail.getExamStartTime()), SystemConstant.DEFAULT_DATE_PATTERN));
         htmlMap.put("endTime", DateUtil.format(new Date(examDetail.getExamEndTime()), SystemConstant.DEFAULT_DATE_PATTERN));
         htmlMap.put("paperCode", examDetail.getPackageCode());
-        if (Objects.nonNull(examDetailCourse.getPaperNumber())) {
-            htmlMap.put("paperCodeImg", GoogleBarCodeUtil.createBarCode(examDetail.getPackageCode(), false));
-        }
+        htmlMap.put("paperCodeImg", GoogleBarCodeUtil.createBarCode(examDetail.getPackageCode(), false));
 
         List<String> extendColumnList = examStudentList.stream().map(m -> m.getExtendFields()).distinct().collect(Collectors.toList());
         Set<String> startCollege = new HashSet();
@@ -174,20 +179,25 @@ public class CreatePdfUtil {
      * @param basicAttachment
      * @param schoolName
      * @param examDetail
-     * @param examDetailCourse
      * @param examStudentList
      * @param variablePdfList
      * @param printCount
      */
-    public void createSignBook(BasicAttachment basicAttachment, String schoolName, ExamDetail examDetail, ExamDetailCourse examDetailCourse, List<ExamStudent> examStudentList, List<PdfDto> variablePdfList, Integer printCount) throws IOException {
+    public void createSignBook(BasicAttachment basicAttachment, String schoolName, ExamDetail examDetail, List<ExamStudentCourseDto> examStudentList, List<PdfDto> variablePdfList, Integer printCount) throws IOException {
         if (Objects.isNull(basicAttachment)) {
-            throw ExceptionResultEnum.ERROR.exception("找不到附件");
+            throw ExceptionResultEnum.ATTACHMENT_IS_NULL.exception();
         }
         Map<String, Object> htmlMap = new HashMap<>();
-        htmlMap.put("examDetailCourseId", examDetailCourse.getId());
+        if (Objects.nonNull(examStudentList) && examStudentList.size() > 0) {
+            htmlMap.put("examDetailCourseId", examStudentList.get(0).getExamDetailCourseId());
+            htmlMap.put("courseName", examStudentList.get(0).getCourseName());
+            htmlMap.put("courseCode", examStudentList.get(0).getCourseCode());
+        } else {
+            htmlMap.put("examDetailCourseId", "");
+            htmlMap.put("courseName", "");
+            htmlMap.put("courseCode", "");
+        }
         htmlMap.put("schoolName", schoolName);
-        htmlMap.put("courseName", examDetailCourse.getCourseName());
-        htmlMap.put("courseCode", examDetailCourse.getCourseCode());
         htmlMap.put("examRoom", examDetail.getExamRoom());
 
         List<String> extendColumnList = examStudentList.stream().map(m -> m.getExtendFields()).distinct().collect(Collectors.toList());
@@ -206,9 +216,7 @@ public class CreatePdfUtil {
         htmlMap.put("startTime", DateUtil.format(new Date(examDetail.getExamStartTime()), SystemConstant.DEFAULT_DATE_PATTERN));
         htmlMap.put("endTime", DateUtil.format(new Date(examDetail.getExamEndTime()), SystemConstant.DEFAULT_DATE_PATTERN));
         htmlMap.put("paperCode", examDetail.getPackageCode());
-        if (Objects.nonNull(examDetailCourse.getPaperNumber())) {
-            htmlMap.put("paperCodeImg", GoogleBarCodeUtil.createBarCode(examDetail.getPackageCode(), false));
-        }
+        htmlMap.put("paperCodeImg", GoogleBarCodeUtil.createBarCode(examDetail.getPackageCode(), false));
 
         int totalCount = examStudentList.size();
         if (totalCount > 0) {
@@ -218,7 +226,7 @@ public class CreatePdfUtil {
                 Map subMap = new HashMap();
                 subMap.put("index", i + 1);
                 int studentCount;
-                List<ExamStudent> subStudents;
+                List<ExamStudentCourseDto> subStudents;
                 if (pageCount == 1) {
                     studentCount = totalCount;
                     subStudents = examStudentList;
@@ -360,7 +368,7 @@ public class CreatePdfUtil {
                 Long attachmentId = Long.parseLong((String) (object.get("attachmentId")));
                 BasicAttachment basicAttachment = basicAttachmentService.getById(attachmentId);
                 if (Objects.isNull(basicAttachment)) {
-                    throw ExceptionResultEnum.ERROR.exception("找不到附件");
+                    throw ExceptionResultEnum.ATTACHMENT_IS_NULL.exception();
                 }
                 String name = (String) object.get("name");
                 if (Objects.equals(name.toUpperCase(), paperType.toUpperCase())) {
@@ -390,14 +398,14 @@ public class CreatePdfUtil {
         //已曝光卷型
         String exposedPaperType = examTaskDetail.getExposedPaperType();
         if (drawRule == DrawRuleEnum.ONE) {
-            if (Objects.isNull(unexposedPaperType)) {
+            if (Objects.isNull(unexposedPaperType) || Objects.equals(unexposedPaperType.trim(), "")) {
                 CreatePdfCacheUtil.deletePaperType(key);
-                throw ExceptionResultEnum.ERROR.exception("当前没有未曝光的卷型");
+                throw ExceptionResultEnum.PAPER_ERROR.exception();
             }
         } else {
-            if (Objects.isNull(exposedPaperType) && Objects.isNull(unexposedPaperType)) {
+            if ((Objects.isNull(exposedPaperType) || Objects.equals(exposedPaperType.trim(), "")) && (Objects.isNull(unexposedPaperType) || Objects.equals(unexposedPaperType.trim(), ""))) {
                 CreatePdfCacheUtil.deletePaperType(key);
-                throw ExceptionResultEnum.ERROR.exception("当前没有未曝光的卷型");
+                throw ExceptionResultEnum.PAPER_ERROR.exception();
             }
         }
         String paperType = null;
@@ -439,45 +447,65 @@ public class CreatePdfUtil {
         log.info("getPaperType key:{},paperType:{},lock:{}", key, paperType, lock);
         if (!lock) {
             log.info("getPaperType 未获取到锁,key:{}", key);
-            throw ExceptionResultEnum.ERROR.exception("未获取到试卷类型");
+            throw ExceptionResultEnum.PAPER_TYPE_ERROR.exception();
         }
         return paperType;
     }
 
     /**
-     * 合并pdf
+     * 合并A3 pdf
      *
-     * @param tbTask
-     * @param examDetail
-     * @param userId
-     * @param schoolId
      * @param list
      * @return
      * @throws IOException
      */
-    public BasicAttachment mergePdf(BasicExamRule basicExamRule, TBTask tbTask, ExamDetail examDetail, Long userId, Long schoolId, List<PdfDto>... list) throws IOException {
-        StringJoiner stringJoiner = new StringJoiner("").add(SystemConstant.PDF_TEMP_FILES_DIR).add(File.separator);
+    public String mergeA3Pdf(List<PdfDto>... list) throws IOException {
         List<PdfDto> mergePdfA3List = new ArrayList<>();
+        for (int i = 0; i < list.length; i++) {
+            mergePdfA3List.addAll(list[i]);
+        }
+        List<String> pathA3List = mergePdfA3List.stream().map(PdfDto::getPath).collect(Collectors.toList());
+        return PdfUtil.mergePdf(pathA3List.toArray(new String[mergePdfA3List.size()]), null);
+    }
+
+    /**
+     * 合并A4 pdf
+     *
+     * @param list
+     * @return
+     * @throws IOException
+     */
+    public String mergeA4Pdf(List<PdfDto>... list) throws IOException {
         List<PdfDto> mergePdfA4List = new ArrayList<>();
-        List<PdfDto> mergePdfDeleteList = new ArrayList<>();
-//        AtomicInteger pageA4Count = new AtomicInteger(0);
-//        AtomicInteger pageA3Count = new AtomicInteger(0);
         for (int i = 0; i < list.length; i++) {
-            if (list[i].size() > 0 && list[i].get(0).getPageSize() == PageSizeEnum.A4) {
-//                pageA4Count.addAndGet(list[i].stream().mapToInt(PdfDto::getPageCount).sum());
-                mergePdfA4List.addAll(list[i]);
-            } else if (list[i].size() > 0 && list[i].get(0).getPageSize() == PageSizeEnum.A3) {
-//                pageA3Count.addAndGet(list[i].stream().mapToInt(PdfDto::getPageCount).sum());
-                mergePdfA3List.addAll(list[i]);
-            }
+            mergePdfA4List.addAll(list[i]);
         }
-//        mergePdfDeleteA3List.addAll(list[2]);
-        mergePdfDeleteList.addAll(list[3]);
-        mergePdfDeleteList.addAll(list[5]);
         List<String> pathA4List = mergePdfA4List.stream().map(PdfDto::getPath).collect(Collectors.toList());
-        List<String> pathA3List = mergePdfA3List.stream().map(PdfDto::getPath).collect(Collectors.toList());
-        String dirNameA4 = PdfUtil.mergePdf(pathA4List.toArray(new String[mergePdfA4List.size()]), null);
-        String dirNameA3 = PdfUtil.mergePdf(pathA3List.toArray(new String[mergePdfA3List.size()]), null);
+        return PdfUtil.mergePdf(pathA4List.toArray(new String[mergePdfA4List.size()]), null);
+    }
+
+    /**
+     * 合并pdf后保存数据库
+     *
+     * @param dirNameA4
+     * @param dirNameA3
+     * @param tbTask
+     * @param userId
+     * @param examDetail
+     * @param basicExamRule
+     * @param mergePdfDeleteList
+     * @return
+     * @throws IOException
+     */
+    @Transactional
+    public BasicAttachment mergePdfSaveDb(String dirNameA4,
+                                          String dirNameA3,
+                                          TBTask tbTask,
+                                          Long userId,
+                                          ExamDetail examDetail,
+                                          BasicExamRule basicExamRule,
+                                          List<PdfDto> mergePdfDeleteList) throws IOException {
+        StringJoiner stringJoiner = new StringJoiner("").add(SystemConstant.PDF_TEMP_FILES_DIR).add(File.separator);
         // oss上只认"/",windows生成的路径分隔符全部替换为"/"
         File localA4PdfFile = null, localA3PdfFile = null;
         BasicAttachment basicAttachment = null;
@@ -610,10 +638,11 @@ public class CreatePdfUtil {
      * @param jsonArray
      * @param userId
      * @param cardPdfList
+     * @param basicCardRule
      * @return
      * @throws IOException
      */
-    public BasicAttachment cardHtml(String sequence, String cardContent, ExamDetail examDetail, ExamDetailCourse examDetailCourse, ExamCard examCard, JSONArray jsonArray, Long userId, List<PdfDto> cardPdfList) throws IOException {
+    public BasicAttachment cardHtml(String sequence, String cardContent, ExamDetail examDetail, ExamDetailCourse examDetailCourse, ExamCard examCard, JSONArray jsonArray, Long userId, List<PdfDto> cardPdfList, BasicCardRule basicCardRule) throws IOException {
         //通用题卡
         String cardTemp = cardContent;
         cardTemp = cardTemp.replaceAll("\\$\\{paperTypeName\\}", examDetailCourse.getPaperType());
@@ -621,6 +650,28 @@ public class CreatePdfUtil {
         if (Objects.nonNull(examDetailCourse.getPaperType())) {
             cardTemp = cardTemp.replaceAll("\\$\\{paperType\\}", GoogleBarCodeUtil.createBarCode(SystemConstant.convertPaperType(examDetailCourse.getPaperType()), false));
         }
+        if (Objects.nonNull(basicCardRule) && Objects.nonNull(basicCardRule.getExtendFields())) {
+            JSONArray jsonObjectExtend = (JSONArray) JSONArray.parse(basicCardRule.getExtendFields());//扩展字段
+            if (Objects.nonNull(jsonObjectExtend)) {
+                for (int i = 0; i < jsonObjectExtend.size(); i++) {
+                    JSONObject object = (JSONObject) jsonObjectExtend.get(i);
+                    cardTemp = cardTemp.replaceAll("\\$\\{" + object.get("code") + "\\}", "");
+                }
+            }
+        }
+        cardTemp = cardTemp.replaceAll("\\$\\{examDate\\}", "");
+        cardTemp = cardTemp.replaceAll("\\$\\{examTime\\}", "");
+        cardTemp = cardTemp.replaceAll("\\$\\{ticketNumber\\}", "");
+        cardTemp = cardTemp.replaceAll("\\$\\{siteNumber\\}", "");
+        cardTemp = cardTemp.replaceAll("\\$\\{paperTypeName\\}", "");
+        cardTemp = cardTemp.replaceAll("\\$\\{studentCode\\}", "");
+        cardTemp = cardTemp.replaceAll("\\$\\{studentName\\}", "");
+        cardTemp = cardTemp.replaceAll("\\$\\{courseName\\}", "");
+        cardTemp = cardTemp.replaceAll("\\$\\{courseCode\\}", "");
+        cardTemp = cardTemp.replaceAll("\\$\\{examPlace\\}", "");
+        cardTemp = cardTemp.replaceAll("\\$\\{examRoom\\}", "");
+        cardTemp = cardTemp.replaceAll("\\$\\{paperNumber\\}", "");
+
         //通用题卡生成卷袋贴条码
         String packageCode = examDetail.getPackageCode() + sequence;
         String packageCodeImg = null;

+ 2 - 0
distributed-print-business/src/main/resources/db/init-table.sql

@@ -241,6 +241,7 @@ CREATE TABLE `client_status`  (
   `school_id` bigint(20) NULL DEFAULT NULL,
   `machine_code` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '机器唯一码',
   `exam_task_id` bigint(20) NULL COMMENT '命题任务ID',
+  `print_plan_id` bigint(20) NULL COMMENT '印刷计划ID',
   `course_code` varchar(100) NOT NULL COMMENT '课程代码',
   `course_name` varchar(200) NOT NULL COMMENT '课程名称',
   `paper_number` varchar(50) NOT NULL COMMENT '试卷编号',
@@ -1597,6 +1598,7 @@ CREATE TABLE `t_b_task`  (
   `obj_name` varchar(500) DEFAULT NULL COMMENT '实体名称',
   `reset_count` int DEFAULT '0' COMMENT '重试次数',
   `version` int DEFAULT '0' COMMENT '更新版本号',
+  `error_message` varchar(500) DEFAULT NULL COMMENT '人工错误原因',
   PRIMARY KEY (`id`) USING BTREE
 ) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '导入导出任务表' ROW_FORMAT = Dynamic;
 

+ 0 - 4
distributed-print-business/src/main/resources/mapper/ExamDetailCourseMapper.xml

@@ -50,10 +50,6 @@
             exam_task b ON a.school_id = b.school_id
                 AND a.course_code = b.course_code
                 AND a.paper_number = b.paper_number
-                LEFT JOIN
-            exam_task_detail c ON b.id = c.exam_task_id
-                LEFT JOIN
-            exam_card_detail d ON c.card_id = d.card_id
         WHERE
             a.exam_detail_id = #{examDetailId} AND b.status != #{status}
     </select>

+ 10 - 4
distributed-print-business/src/main/resources/mapper/ExamPrintPlanMapper.xml

@@ -89,6 +89,7 @@
                 and a.school_id = #{schoolId}
             </if>
             <if test="source == 'client'">
+                AND LOCATE('PAPER', print_content) > 0
                 AND a.status IN
                 <foreach collection="status" item="item" index="index" open="(" separator="," close=")">
                     #{item}
@@ -121,6 +122,7 @@
             b.total_subjects totalSubjects,
             IFNULL(b.pages_a3, 0) pagesA3,
             IFNULL(b.pages_a4, 0) pagesA4,
+            case b.status when 'FINISH' then IFNULL(b.pages_a3, 0)+IFNULL(b.pages_a4, 0) else 0 end totalPrint,
             c.singlePagesA3,
             b.status,
             ifnull(b.validate, false) validate,
@@ -137,7 +139,8 @@
             exam_detail b ON a.id = b.print_plan_id
                 JOIN
             (SELECT
-                exam_detail_id,
+                    b.exam_detail_id,
+                    b.print_plan_id,
                     GROUP_CONCAT(CONCAT(a.course_name, '(', a.course_code, ')')) courseNameCode,
                     GROUP_CONCAT(a.paper_number) paperNumber,
                     GROUP_CONCAT(IFNULL(a.paper_pages_a3, 0) + IFNULL(a.card_pages_a3, 0)) singlePagesA3,
@@ -156,10 +159,11 @@
             FROM
                 exam_detail_course a
             LEFT JOIN client_status b ON a.school_id = b.school_id
+                AND a.exam_detail_id = b.exam_detail_id
                 AND a.course_code = b.course_code
                 AND a.paper_number = b.paper_number
                 AND b.machine_code = #{machineCode}
-            GROUP BY exam_detail_id) c ON b.id = c.exam_detail_id
+            GROUP BY b.exam_detail_id, b.print_plan_id) c ON a.id = c.print_plan_id and b.id = c.exam_detail_id
                 LEFT JOIN
             sys_user e ON b.print_user = e.login_name
                 LEFT JOIN
@@ -227,7 +231,8 @@
             exam_detail b ON a.id = b.print_plan_id
         JOIN
             (SELECT
-                exam_detail_id,
+                b.exam_detail_id,
+                b.print_plan_id,
                 GROUP_CONCAT(CONCAT(a.course_name, '(', a.course_code, ')')) courseNameCode,
                 GROUP_CONCAT(a.paper_number) paperNumber,
                 GROUP_CONCAT(IFNULL(a.paper_pages_a3, 0) + IFNULL(a.card_pages_a3, 0)) singlePagesA3,
@@ -246,10 +251,11 @@
         FROM
             exam_detail_course a
                 LEFT JOIN client_status b ON a.school_id = b.school_id
+                AND a.exam_detail_id = b.exam_detail_id
                 AND a.course_code = b.course_code
                 AND a.paper_number = b.paper_number
                 AND b.machine_code = #{machineCode}
-        GROUP BY exam_detail_id) c ON b.id = c.exam_detail_id
+        GROUP BY b.exam_detail_id, b.print_plan_id) c ON a.id = c.print_plan_id and b.id = c.exam_detail_id
             LEFT JOIN
         sys_user e ON b.print_user = e.login_name
             LEFT JOIN

+ 40 - 0
distributed-print-business/src/main/resources/mapper/ExamStudentMapper.xml

@@ -46,4 +46,44 @@
             a.id = #{id}
     </select>
 
+    <select id="queryBySchoolIdAndExamDetailCourseIds" resultType="com.qmth.distributed.print.business.bean.dto.ExamStudentCourseDto">
+        select
+            es.id,
+            es.school_id as schoolId,
+            es.exam_detail_course_id as examDetailCourseId,
+            es.student_name as studentName,
+            es.student_code as studentCode,
+            es.ticket_number as ticketNumber,
+            es.site_number as siteNumber,
+            es.print_paper as printPaper,
+            es.print_card as printCard,
+            es.extend_fields as extendFields,
+            es.paper_type as paperType,
+            es.create_id as createId,
+            es.create_time as createTime,
+            es.update_id as updateId,
+            es.update_time as updateTime,
+            es.attachment_id as attachmentId,
+            edc.course_code as courseCode,
+            edc.course_name as courseName,
+            edc.paper_pages_a3 as paperPageA3,
+            edc.paper_number as paperNumber
+        from
+            exam_student es
+        left join exam_detail_course edc on
+            edc.id = es.exam_detail_course_id
+            <where>
+                <if test="schoolId != null and schoolId != ''">
+                    and es.school_id = #{schoolId}
+                </if>
+                <if test="examDetailCourseIds != null">
+                    AND edc.id IN
+                    <foreach collection="examDetailCourseIds" item="examDetailCourseId" index="index" open="(" separator="," close=")">
+                        #{examDetailCourseId}
+                    </foreach>
+                </if>
+            </where>
+            order by edc.course_code
+    </select>
+
 </mapper>

+ 3 - 0
distributed-print-business/src/main/resources/mapper/ExamTaskMapper.xml

@@ -469,6 +469,8 @@
                 AND d.paper_number = c.paper_number
                 LEFT JOIN
             client_status e ON e.school_id = d.school_id
+                AND b.id = e.exam_detail_id
+                AND a.id = e.print_plan_id
                 AND e.course_code = d.course_code
                 AND e.paper_number = d.paper_number
                 and e.machine_code = #{machineCode}
@@ -479,6 +481,7 @@
         <where>
             and a.status = #{printPlanStatus}
             and d.status = 'FINISH'
+            and LOCATE('PAPER', a.print_content) > 0
             and b.status not in
             <foreach item="item" collection="examDetailStatus" separator="," open="(" close=")" index="">
                 #{item}

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

@@ -21,7 +21,8 @@
             t.id = tbt.create_id) as createName,
             if(ISNULL(tbt.result_file_path),false,true) as hasResultFile,
             if(ISNULL(tbt.report_file_path),false,true) as hasReportFile,
-            tbt.reset_count as resetCount
+            tbt.reset_count as resetCount,
+            tbt.error_message as errorMessage
             from
             t_b_task tbt
             left join exam_print_plan epp on

+ 16 - 0
distributed-print-common/src/main/java/com/qmth/distributed/print/common/enums/ExceptionResultEnum.java

@@ -61,6 +61,22 @@ public enum ExceptionResultEnum {
 
     SCHOOL_ENABLE(HttpStatus.INTERNAL_SERVER_ERROR, 5000021, "学校已停用"),
 
+    PAPER_ERROR(HttpStatus.INTERNAL_SERVER_ERROR, 50000022, "当前没有未曝光的卷型"),
+
+    PAPER_TYPE_ERROR(HttpStatus.INTERNAL_SERVER_ERROR, 50000023, "未获取到试卷类型"),
+
+    ATTACHMENT_IS_NULL(HttpStatus.INTERNAL_SERVER_ERROR, 50000024, "找不到附件"),
+
+    EXAM_PRINT_IS_NULL(HttpStatus.INTERNAL_SERVER_ERROR, 50000025, "印刷计划为空"),
+
+    EXAM_RULE_IS_NULL(HttpStatus.INTERNAL_SERVER_ERROR, 50000026, "考务规则为空"),
+
+    EXAM_DETAIL_IS_NULL(HttpStatus.INTERNAL_SERVER_ERROR, 50000027, "考场数据为空"),
+
+    EXAM_CARD_IS_NULL(HttpStatus.INTERNAL_SERVER_ERROR, 50000028, "题卡为空"),
+
+    EXAM_TASK_IS_NULL(HttpStatus.INTERNAL_SERVER_ERROR, 50000029, "命题任务为空"),
+
     /**
      * 401
      */

+ 5 - 1
distributed-print-task/src/main/java/com/qmth/distributed/print/task/enums/JobEnum.java

@@ -25,7 +25,11 @@ public enum JobEnum {
 
     SMS_NOTICE_TASK_OVERDUE_JOB("任务逾期提醒定时任务"),
 
-    SMS_NOTICE_TASK_OVERDUE_JOB_GROUP("任务逾期提醒定时任务job组");
+    SMS_NOTICE_TASK_OVERDUE_JOB_GROUP("任务逾期提醒定时任务job组"),
+
+    SMS_NOTICE_TASK_RESEND_JOB("短信发送失败重发定时任务"),
+
+    SMS_NOTICE_TASK_RESEND_JOB_GROUP("短信发送失败重发定时任务job组");
 
     private String title;
 

+ 6 - 4
distributed-print/src/main/java/com/qmth/distributed/print/api/ClientController.java

@@ -128,8 +128,9 @@ public class ClientController {
      */
     @ApiOperation(value = "试卷打样-查看/试印/重印")
     @RequestMapping(value = "/paper_try/print", method = RequestMethod.POST)
-    public Result paperTryPrint(@RequestParam("examTaskId") Long examTaskId) {
-        Map<String, String> map = clientService.getUrl(examTaskId);
+    public Result paperTryPrint(@RequestParam("printPlanId") Long printPlanId,
+                                @RequestParam("examTaskId") Long examTaskId) {
+        Map<String, String> map = clientService.getUrl(printPlanId, examTaskId);
         return ResultUtil.ok(map);
     }
 
@@ -168,13 +169,14 @@ public class ClientController {
      */
     @ApiOperation(value = "试卷打样-标记合格状态")
     @RequestMapping(value = "/paper_try/tag_pass", method = RequestMethod.POST)
-    public Result paperTryTagPass(@RequestParam("courseCode") String courseCode,
+    public Result paperTryTagPass(@RequestParam("printPlanId") Long printPlanId,
+                                  @RequestParam("courseCode") String courseCode,
                                   @RequestParam("courseName") String courseName,
                                   @RequestParam("paperNumber") String paperNumber,
                                   @RequestParam("machineCode") String machineCode,
                                   @RequestParam("isPass") Boolean isPass,
                                   @RequestParam("userId") Long userId) {
-        Boolean isSuccess = clientService.tagPass(courseCode, courseName, paperNumber, machineCode, isPass, userId);
+        Boolean isSuccess = clientService.tagPass(printPlanId, courseCode, courseName, paperNumber, machineCode, isPass, userId);
         return ResultUtil.ok(isSuccess);
     }
 

+ 5 - 5
distributed-print/src/main/java/com/qmth/distributed/print/api/EnumsController.java

@@ -85,19 +85,19 @@ public class EnumsController {
         } else if (type.equals(EnumType.CARD_REQUIRED_FIELDS.name())) {
             //题卡必选字段
             list = CardRequiredFieldsEnum.listTypes();
-        } else if (type.equals(EnumType.ORG_CENTER_TYPE_ENUM.name())){
+        } else if (type.equals(EnumType.ORG_CENTER_TYPE_ENUM.name())) {
             //机构用户中心类型
             list = OrgCenterTypeEnum.listTypes();
-        } else if (type.equals(EnumType.PRINT_PLAN_STATUS_ENUM.name())){
+        } else if (type.equals(EnumType.PRINT_PLAN_STATUS_ENUM.name())) {
             //印刷计划状态
             list = PrintPlanStatusEnum.listTypes();
-        } else if (type.equals(EnumType.MAKE_METHOD.name())){
+        } else if (type.equals(EnumType.MAKE_METHOD.name())) {
             // 题卡制作方式
             list = MakeMethodEnum.listTypes();
-        } else if (type.equals(EnumType.CARD_TYPE.name())){
+        } else if (type.equals(EnumType.CARD_TYPE.name())) {
             // 题卡类型
             list = CardTypeEnum.listTypes();
-        } else if (type.equals(EnumType.EXAM_DETAIL_STATUS_ENUM.name())){
+        } else if (type.equals(EnumType.EXAM_DETAIL_STATUS_ENUM.name())) {
             // 考场状态
             list = ExamDetailStatusEnum.listTypes();
         }

+ 7 - 8
distributed-print/src/main/java/com/qmth/distributed/print/api/TBTaskController.java

@@ -1,14 +1,12 @@
 package com.qmth.distributed.print.api;
 
 import com.alibaba.fastjson.JSONArray;
-import com.alibaba.fastjson.JSONObject;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.qmth.boot.api.constant.ApiConstant;
 import com.qmth.distributed.print.business.bean.params.ArraysParams;
 import com.qmth.distributed.print.business.bean.result.EditResult;
 import com.qmth.distributed.print.business.bean.result.TaskListResult;
-import com.qmth.distributed.print.business.config.DictionaryConfig;
 import com.qmth.distributed.print.business.entity.SysUser;
 import com.qmth.distributed.print.business.entity.TBTask;
 import com.qmth.distributed.print.business.enums.TaskResultEnum;
@@ -18,7 +16,6 @@ import com.qmth.distributed.print.business.service.TBTaskService;
 import com.qmth.distributed.print.business.templete.execute.AsyncCreatePdfTempleteService;
 import com.qmth.distributed.print.business.util.ServletUtil;
 import com.qmth.distributed.print.common.contant.SystemConstant;
-import com.qmth.distributed.print.common.enums.ExceptionResultEnum;
 import com.qmth.distributed.print.common.util.Result;
 import com.qmth.distributed.print.common.util.ResultUtil;
 import io.swagger.annotations.*;
@@ -30,7 +27,6 @@ import org.springframework.web.bind.annotation.RestController;
 import javax.annotation.Resource;
 import java.io.IOException;
 import java.util.*;
-import java.util.concurrent.atomic.AtomicInteger;
 
 /**
  * <p>
@@ -48,8 +44,8 @@ public class TBTaskController {
     @Resource
     TBTaskService tbTaskService;
 
-    @Resource
-    DictionaryConfig dictionaryConfig;
+//    @Resource
+//    DictionaryConfig dictionaryConfig;
 
     @Resource
     AsyncCreatePdfTempleteService asyncCreatePdfTempleteService;
@@ -67,7 +63,10 @@ public class TBTaskController {
         if (Objects.nonNull(taskListResultIPage) && Objects.nonNull(taskListResultIPage.getRecords()) && taskListResultIPage.getRecords().size() > 0) {
             List<TaskListResult> taskListResultList = taskListResultIPage.getRecords();
             for (TaskListResult taskListResult : taskListResultList) {
-                if (Objects.equals(taskListResult.getStatus(), TaskStatusEnum.FINISH.getTitle()) && Objects.equals(taskListResult.getResult(), TaskResultEnum.ERROR.getTitle()) && taskListResult.getResetCount() >= dictionaryConfig.sysDomain().getAutoCreatePdfResetMaxCount()) {
+                if (Objects.equals(taskListResult.getStatus(), TaskStatusEnum.FINISH.getTitle()) && Objects.equals(taskListResult.getResult(), TaskResultEnum.ERROR.getTitle())
+//                        && taskListResult.getResetCount() >= dictionaryConfig.sysDomain().getAutoCreatePdfResetMaxCount()
+                        && Objects.equals(taskListResult.getType(), TaskTypeEnum.CREATE_PDF.getTitle())
+                        && Objects.isNull(taskListResult.getErrorMessage())) {
                     taskListResult.setResetCreatePdf(true);
                 }
             }
@@ -81,7 +80,7 @@ public class TBTaskController {
     public Result resetCreatePdf(@ApiParam(value = "任务id", required = true) @RequestParam String id) throws IOException {
         Long taskId = Long.parseLong(id);
         TBTask tbTask = tbTaskService.getById(taskId);
-        tbTask.setVersion(new AtomicInteger(tbTask.getVersion()).incrementAndGet());
+//        tbTask.setVersion(new AtomicInteger(tbTask.getVersion()).incrementAndGet());
         SysUser sysUser = (SysUser) ServletUtil.getRequestUser();
         Map<String, Object> map = new HashMap<>();
         if (Objects.nonNull(tbTask.getRemark())) {

+ 18 - 9
distributed-print/src/main/java/com/qmth/distributed/print/start/StartRunning.java

@@ -4,6 +4,7 @@ import com.qmth.distributed.print.business.service.OrgCenterDataDisposeService;
 import com.qmth.distributed.print.business.service.TBTaskService;
 import com.qmth.distributed.print.common.contant.SystemConstant;
 import com.qmth.distributed.print.task.enums.JobEnum;
+import com.qmth.distributed.print.task.job.ResendSmsJob;
 import com.qmth.distributed.print.task.job.ResetCreatePdfJob;
 import com.qmth.distributed.print.task.job.TimedSyncSchoolJob;
 import com.qmth.distributed.print.task.service.QuartzService;
@@ -42,7 +43,7 @@ public class StartRunning implements CommandLineRunner {
         SystemConstant.initTempFiles();
         orgCenterDataDisposeService.updateSchoolInfo();
 
-        taskService.updateStatus();
+//        taskService.updateStatus();
 
         log.info("增加学校信息同步定时任务 start");
         Map schoolJobMap = new HashMap();
@@ -52,13 +53,13 @@ public class StartRunning implements CommandLineRunner {
         quartzService.addJob(TimedSyncSchoolJob.class, JobEnum.TIMED_SYNC_SCHOOL_JOB.name(), JobEnum.TIMED_TASK_JOB_GROUP.name(), "0 0 0 * * ?", schoolJobMap);
         log.info("增加学校信息同步定时任务 end");
 
-        log.info("增加重新生成pdf定时任务 start");
-        Map taskJobMap = new HashMap();
-        schoolJobMap.computeIfAbsent("name", v -> ResetCreatePdfJob.class.getName());
-        quartzService.deleteJob(JobEnum.RESET_CREATE_PDF_JOB.name(), JobEnum.RESET_CREATE_PDF_JOB_GROUP.name());
-        // 每天0点定时任务
-        quartzService.addJob(ResetCreatePdfJob.class, JobEnum.RESET_CREATE_PDF_JOB.name(), JobEnum.RESET_CREATE_PDF_JOB_GROUP.name(), "0 0/1 * * * ?", taskJobMap);
-        log.info("增加重新生成pdf定时任务 end");
+//        log.info("增加重新生成pdf定时任务 start");
+//        Map taskJobMap = new HashMap();
+//        schoolJobMap.computeIfAbsent("name", v -> ResetCreatePdfJob.class.getName());
+//        quartzService.deleteJob(JobEnum.RESET_CREATE_PDF_JOB.name(), JobEnum.RESET_CREATE_PDF_JOB_GROUP.name());
+//         //每天0点定时任务
+//        quartzService.addJob(ResetCreatePdfJob.class, JobEnum.RESET_CREATE_PDF_JOB.name(), JobEnum.RESET_CREATE_PDF_JOB_GROUP.name(), "0 0/1 * * * ?", taskJobMap);
+//        log.info("增加重新生成pdf定时任务 end");
 
 //        log.info("增加任务到期提醒定时任务 start");
 //        Map expireJobMap = new HashMap();
@@ -73,9 +74,17 @@ public class StartRunning implements CommandLineRunner {
 //        orverdueJobMap.computeIfAbsent("name", v -> SendSmsOverdueJob.class.getName());
 //        quartzService.deleteJob(JobEnum.SMS_NOTICE_TASK_OVERDUE_JOB.name(), JobEnum.SMS_NOTICE_TASK_OVERDUE_JOB_GROUP.name());
 //        // 每天9点定时任务
-//        quartzService.addJob(SendSmsOverdueJob.class, JobEnum.SMS_NOTICE_TASK_OVERDUE_JOB.name(), JobEnum.SMS_NOTICE_TASK_OVERDUE_JOB_GROUP.name(), "0 */5 * * * ?", orverdueJobMap);
+//        quartzService.addJob(SendSmsOverdueJob.class, JobEnum.SMS_NOTICE_TASK_OVERDUE_JOB.name(), JobEnum.SMS_NOTICE_TASK_OVERDUE_JOB_GROUP.name(), "0 0 9 * * ?", orverdueJobMap);
 //        log.info("增加任务逾期提醒定时任务 end");
 
+//        log.info("增加短信发送失败重发定时任务 start");
+//        Map rensendJobMap = new HashMap();
+//        rensendJobMap.computeIfAbsent("name", v -> ResendSmsJob.class.getName());
+//        quartzService.deleteJob(JobEnum.SMS_NOTICE_TASK_RESEND_JOB.name(), JobEnum.SMS_NOTICE_TASK_RESEND_JOB_GROUP.name());
+//        // 每隔1小时定时任务
+//        quartzService.addJob(ResendSmsJob.class, JobEnum.SMS_NOTICE_TASK_RESEND_JOB.name(), JobEnum.SMS_NOTICE_TASK_RESEND_JOB_GROUP.name(), "0 */30 * * * ?", rensendJobMap);
+//        log.info("增加短信发送失败重发定时任务 end");
+
         log.info("服务器启动时执行 end");
     }
 }

+ 3 - 3
distributed-print/src/main/resources/application.properties

@@ -12,7 +12,7 @@ spring.application.name=distributed-print
 #\u6570\u636E\u6E90\u914D\u7F6E
 db.host=localhost
 db.port=3306
-db.name=distributed-136
+db.name=distributed-test
 db.username=root
 db.password=123456789
 
@@ -58,8 +58,8 @@ sys.config.adminLogoUrl=http://qmth-test.oss-cn-shenzhen.aliyuncs.com/frontend/w
 #sys.config.htmlToPdfUrl=/usr/local/bin/wkhtmltopdf
 sys.config.htmlToPdfUrl=/usr/local/bin/wkhtmltopdf
 sys.config.autoCreatePdfResetMaxCount=5
-sys.config.threadPoolCoreSize=5
-sys.config.customThreadPoolCoreSize=false
+sys.config.threadPoolCoreSize=1
+sys.config.customThreadPoolCoreSize=true
 spring.resources.static-locations=file:${sys.config.serverUpload},classpath:/META-INF/resources/,classpath:/resources/
 
 org.center.url=https://solar.qmth.com.cn

+ 277 - 0
distributed-print/src/test/java/com/qmth/distributed/print/BasicUserImportTest.java

@@ -0,0 +1,277 @@
+package com.qmth.distributed.print;
+
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
+import com.qmth.distributed.print.business.entity.*;
+import com.qmth.distributed.print.business.enums.RoleTypeEnum;
+import com.qmth.distributed.print.business.service.*;
+import com.qmth.distributed.print.common.contant.SystemConstant;
+import org.apache.poi.ss.usermodel.Cell;
+import org.apache.poi.ss.usermodel.Row;
+import org.apache.poi.xssf.usermodel.XSSFSheet;
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
+import org.junit.Test;
+import org.junit.platform.commons.util.StringUtils;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.junit4.SpringRunner;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @Description: 用户数据导入、课程导入、组织机构导入
+ */
+@SpringBootTest
+@RunWith(SpringRunner.class)
+public class BasicUserImportTest {
+    @Autowired
+    private BasicCourseService basicCourseService;
+    @Autowired
+    private SysUserService sysUserService;
+    @Autowired
+    private SysOrgService sysOrgService;
+    @Autowired
+    private BasicUserCourseService basicUserCourseService;
+    @Autowired
+    private SysRoleService sysRoleService;
+    @Autowired
+    private SysUserRoleService sysUserRoleService;
+    @Autowired
+    private SysRolePrivilegeService sysRolePrivilegeService;
+
+    // 学校Id
+    private Long schoolId = 5l;
+
+    // 用户数据文件
+    String userFile = "D:\\20210514_追加命题及课程数据-2.xlsx";
+    // 课程数据文件
+    String courseFile = "D:\\20210514_追加命题及课程数据-1.xlsx";
+
+
+    @Test
+    public void importBasicCourse() throws Exception {
+        List<BasicCourse> courses = readCourseFile();
+        for (BasicCourse cours : courses) {
+            QueryWrapper<BasicCourse> queryWrapper = new QueryWrapper<>();
+            queryWrapper.lambda().eq(BasicCourse::getCode, cours.getCode());
+            BasicCourse basicCourse = basicCourseService.getOne(queryWrapper);
+            if (basicCourse != null) {
+                if (basicCourse.getName().equals(cours.getName())) {
+                    continue;
+                } else {
+                    throw new Exception(String.format("s%代码已存在,名称不一致,数据库:s%,文件中:s%", cours.getCode(), basicCourse.getName(), cours.getName()));
+                }
+            }
+
+            cours.setId(SystemConstant.getDbUuid());
+            cours.setCreateId(124882698949885952l);
+            cours.setSchoolId(schoolId);
+            basicCourseService.save(cours);
+        }
+    }
+
+    @Test
+//    @Transactional
+    public void importBasicUser() throws Exception {
+        List<Map<String, String>> users = readUserFile();
+        for (Map<String, String> userMap : users) {
+            // sys_org
+            String orgCode = userMap.get("orgCode");
+            String orgName = userMap.get("orgName");
+            QueryWrapper<SysOrg> orgQueryWrapper = new QueryWrapper<>();
+            orgQueryWrapper.lambda().eq(SysOrg::getSchoolId, schoolId).eq(SysOrg::getCode, orgCode);
+            SysOrg sysOrg = sysOrgService.getOne(orgQueryWrapper);
+            if (sysOrg != null) {
+                if (!sysOrg.getName().equals(orgName)) {
+                    throw new Exception(String.format("s%代码已存在,名称不一致,数据库:s%,文件中:s%", orgCode, sysOrg.getName(), orgName));
+                }
+            } else {
+                sysOrg = new SysOrg();
+                sysOrg.setId(SystemConstant.getDbUuid());
+                sysOrg.setSchoolId(schoolId);
+                sysOrg.setCode(orgCode);
+                sysOrg.setName(orgName);
+                sysOrg.setParentId(100l);
+                sysOrgService.save(sysOrg);
+            }
+
+            // sys_user
+            String loginName = userMap.get("loginName");
+            String realName = userMap.get("realName");
+            String mobileNumber = userMap.get("mobileNumber");
+            String password = userMap.get("password");
+            QueryWrapper<SysUser> userQueryWrapper = new QueryWrapper<>();
+            userQueryWrapper.lambda().eq(SysUser::getSchoolId, schoolId).eq(SysUser::getLoginName, loginName);
+            SysUser sysUser = sysUserService.getOne(userQueryWrapper);
+            if(sysUser == null){
+                sysUser = new SysUser();
+                sysUser.setId(SystemConstant.getDbUuid());
+                sysUser.setSchoolId(schoolId);
+                sysUser.setLoginName(loginName);
+                sysUser.setRealName(realName);
+                sysUser.setPassword(password);
+                sysUser.setMobileNumber(mobileNumber);
+                sysUser.setOrgId(sysOrg.getId());
+                sysUserService.save(sysUser);
+            } else {
+                sysUser.setEnable(true);
+                sysUser.setMobileNumber(mobileNumber);
+                sysUserService.updateById(sysUser);
+
+                String a = "update `sys_user` set mobile_number = %s, enable = true where id = %s;";
+                System.out.println(String.format(a, mobileNumber, sysUser.getId()));
+            }
+
+            // sys_user_role
+            String roleType = userMap.get("roleType");
+            QueryWrapper<SysRole> roleQueryWrapper = new QueryWrapper<>();
+            roleQueryWrapper.lambda().eq(SysRole::getType, roleType);
+            SysRole sysRole = sysRoleService.getOne(roleQueryWrapper);
+            if (sysRole == null) {
+                throw new Exception("角色不存在");
+            }
+
+            UpdateWrapper<SysUserRole> sysUserRoleUpdateWrapper = new UpdateWrapper<>();
+            sysUserRoleUpdateWrapper.lambda().eq(SysUserRole::getUserId, sysUser.getId());
+            sysUserRoleService.remove(sysUserRoleUpdateWrapper);
+
+            QueryWrapper<SysRolePrivilege> rolePrivilegeQueryWrapper = new QueryWrapper<>();
+            rolePrivilegeQueryWrapper.lambda().eq(SysRolePrivilege::getRoleId, sysRole.getId()).eq(SysRolePrivilege::getEnable, true);
+            List<SysRolePrivilege> rolePrivileges = sysRolePrivilegeService.list(rolePrivilegeQueryWrapper);
+            List<SysUserRole> userRoles = new ArrayList<>();
+            for (SysRolePrivilege rolePrivilege : rolePrivileges) {
+                SysUserRole sysUserRole = new SysUserRole();
+                sysUserRole.setId(SystemConstant.getDbUuid());
+                sysUserRole.setUserId(sysUser.getId());
+                sysUserRole.setRoleId(rolePrivilege.getRoleId());
+                sysUserRole.setPrivilegeId(rolePrivilege.getPrivilegeId());
+                sysUserRole.setEnable(true);
+                userRoles.add(sysUserRole);
+            }
+            sysUserRoleService.saveBatch(userRoles);
+
+            // sys_user_course
+            String courseCodeses = userMap.get("courseCode");
+            if(roleType.equals(RoleTypeEnum.QUESTION_TEACHER.name())){
+                if(StringUtils.isBlank(courseCodeses)){
+                    throw new Exception("命题老师课程不能为空");
+                }
+
+                List<BasicUserCourse> userCourses = new ArrayList<>();
+                String[] courseCodes = courseCodeses.split(",");
+                for (String courseCode : courseCodes) {
+                    String[] coursees = courseCode.split("/");
+                    QueryWrapper<BasicCourse> basicCourseQueryWrapper = new QueryWrapper<>();
+                    basicCourseQueryWrapper.lambda().eq(BasicCourse::getSchoolId, schoolId).eq(BasicCourse::getCode, coursees[0]);
+                    BasicCourse basicCourse = basicCourseService.getOne(basicCourseQueryWrapper);
+                    if(basicCourse == null){
+                        throw new Exception("命题老师对应课程不存在,"+ coursees[0]);
+                    }
+                    BasicUserCourse basicUserCourse = new BasicUserCourse();
+                    basicUserCourse.setId(SystemConstant.getDbUuid());
+                    basicUserCourse.setUserId(sysUser.getId());
+                    basicUserCourse.setCourseId(basicCourse.getId());
+                    userCourses.add(basicUserCourse);
+                }
+                basicUserCourseService.saveBatch(userCourses);
+            }
+        }
+    }
+
+    /**
+     * 读取课程数据文件
+     *
+     * @return
+     * @throws Exception
+     */
+    private List<BasicCourse> readCourseFile() throws Exception {
+        File file = new File(courseFile);
+        if (!file.exists()) {
+            throw new Exception("课程数据文件不存在");
+        }
+        FileInputStream fileInputStream = new FileInputStream(file);
+        XSSFWorkbook workbook = new XSSFWorkbook(fileInputStream);
+        XSSFSheet sheet = workbook.getSheetAt(0);
+
+        List<BasicCourse> courseList = new ArrayList<>();
+        for (int i = 1; i < sheet.getPhysicalNumberOfRows(); i++) {
+            BasicCourse basicCourse = new BasicCourse();
+            Row row = sheet.getRow(i);
+            // 用户名
+            Cell cell0 = row.getCell(0);
+            basicCourse.setCode(cell0 == null ? null : cell0.getStringCellValue());
+            // 姓名
+            Cell cell1 = row.getCell(1);
+            basicCourse.setName(cell1 == null ? null : cell1.getStringCellValue());
+            courseList.add(basicCourse);
+        }
+        return courseList;
+    }
+
+    /**
+     * 读取用户数据文件
+     *
+     * @return
+     * @throws Exception
+     */
+    private List<Map<String, String>> readUserFile() throws Exception {
+        File file = new File(userFile);
+        if (!file.exists()) {
+            throw new Exception("用户数据文件不存在");
+        }
+        FileInputStream fileInputStream = new FileInputStream(file);
+        XSSFWorkbook workbook = new XSSFWorkbook(fileInputStream);
+        XSSFSheet sheet = workbook.getSheetAt(0);
+
+        List<Map<String, String>> userList = new ArrayList<>();
+        for (int i = 1; i < sheet.getPhysicalNumberOfRows(); i++) {
+            Map<String, String> map = new HashMap<>();
+            Row row = sheet.getRow(i);
+            // 用户名
+            Cell cell0 = row.getCell(0);
+            map.put("loginName", cell0 == null ? null : cell0.getStringCellValue());
+            // 姓名
+            Cell cell1 = row.getCell(1);
+            map.put("realName", cell1 == null ? null : cell1.getStringCellValue());
+            // 手机号
+            Cell cell2 = row.getCell(2);
+            map.put("mobileNumber", cell2 == null ? null : cell2.getStringCellValue());
+            // 密码
+            Cell cell4 = row.getCell(4);
+            map.put("password", cell4 == null ? null : cell4.getStringCellValue());
+            // 角色Code
+            Cell cell5 = row.getCell(5);
+            map.put("roleType", cell5 == null ? null : cell5.getStringCellValue());
+            // 机构code
+            Cell cell8 = row.getCell(8);
+            map.put("orgCode", cell8 == null ? null : cell8.getStringCellValue());
+            // 机构名称
+            Cell cell9 = row.getCell(9);
+            map.put("orgName", cell9 == null ? null : cell9.getStringCellValue());
+            // 命题老师可操作课程代码
+            Cell cell10 = row.getCell(10);
+            map.put("courseCode", cell10 == null ? null : cell10.getStringCellValue());
+            userList.add(map);
+        }
+
+        return userList;
+    }
+
+    @Test
+    public void createCourse() {
+        QueryWrapper<BasicCourse> courseQueryWrapper = new QueryWrapper<>();
+        courseQueryWrapper.lambda().eq(BasicCourse::getSchoolId, schoolId);
+        List<BasicCourse> courses = basicCourseService.list(courseQueryWrapper);
+        for (BasicCourse cours : courses) {
+            String a = "INSERT INTO `basic_course` VALUES (%s,1,'%s','%s',124882698949885952,1620464769921,NULL,1620464769921);";
+            System.out.println(String.format(a, SystemConstant.getDbUuid(), cours.getCode(), cours.getName()));
+        }
+    }
+
+}