Răsfoiți Sursa

3.4.2 update

xiaofei 8 luni în urmă
părinte
comite
6bf9e24578
16 a modificat fișierele cu 272 adăugiri și 191 ștergeri
  1. 5 10
      distributed-print-business/src/main/java/com/qmth/distributed/print/business/bean/params/ExamTaskSubmitContent.java
  2. 26 0
      distributed-print-business/src/main/java/com/qmth/distributed/print/business/entity/BasicCardRule.java
  3. 35 0
      distributed-print-business/src/main/java/com/qmth/distributed/print/business/entity/ExamTask.java
  4. 32 47
      distributed-print-business/src/main/java/com/qmth/distributed/print/business/entity/ExamTaskDetail.java
  5. 5 0
      distributed-print-business/src/main/java/com/qmth/distributed/print/business/service/ExamTaskDetailService.java
  6. 2 2
      distributed-print-business/src/main/java/com/qmth/distributed/print/business/service/impl/ExamTaskAssignPaperTypeServiceImpl.java
  7. 27 3
      distributed-print-business/src/main/java/com/qmth/distributed/print/business/service/impl/ExamTaskDetailServiceImpl.java
  8. 65 68
      distributed-print-business/src/main/java/com/qmth/distributed/print/business/service/impl/ExamTaskServiceImpl.java
  9. 3 8
      distributed-print-business/src/main/java/com/qmth/distributed/print/business/templete/service/impl/PdfTaskLogicServiceImpl.java
  10. 32 36
      distributed-print-business/src/main/java/com/qmth/distributed/print/business/util/CreatePdfUtil.java
  11. 20 0
      distributed-print-business/src/main/resources/db/log/xf.sql
  12. 1 1
      distributed-print/src/main/java/com/qmth/distributed/print/api/ExamTaskApplyController.java
  13. 2 1
      teachcloud-common/src/main/java/com/qmth/teachcloud/common/entity/BasicOperationLog.java
  14. 1 1
      teachcloud-common/src/main/java/com/qmth/teachcloud/common/enums/ExceptionResultEnum.java
  15. 1 1
      teachcloud-common/src/main/java/com/qmth/teachcloud/common/enums/log/OperationTypeEnum.java
  16. 15 13
      teachcloud-mark/src/main/java/com/qmth/teachcloud/mark/service/impl/MarkServiceImpl.java

+ 5 - 10
distributed-print-business/src/main/java/com/qmth/distributed/print/business/bean/params/ExamTaskSubmitContent.java

@@ -1,12 +1,7 @@
 package com.qmth.distributed.print.business.bean.params;
 
-import com.baomidou.mybatisplus.annotation.FieldStrategy;
-import com.baomidou.mybatisplus.annotation.TableField;
-import com.fasterxml.jackson.databind.annotation.JsonSerialize;
-import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
 import com.qmth.distributed.print.business.entity.ExamTask;
 import com.qmth.distributed.print.business.entity.ExamTaskDetail;
-import com.qmth.teachcloud.common.base.BaseEntity;
 import io.swagger.annotations.ApiModelProperty;
 
 import java.io.Serializable;
@@ -25,7 +20,7 @@ public class ExamTaskSubmitContent implements Serializable {
     private ExamTask examTask;
 
     @ApiModelProperty(value = "命题任务详情")
-    private ExamTaskDetail examTaskDetail;
+    private List<ExamTaskDetail> examTaskDetailList;
 
     @ApiModelProperty(value = "考场数据")
     private ExamDetailParams examDetail;
@@ -38,12 +33,12 @@ public class ExamTaskSubmitContent implements Serializable {
         this.examTask = examTask;
     }
 
-    public ExamTaskDetail getExamTaskDetail() {
-        return examTaskDetail;
+    public List<ExamTaskDetail> getExamTaskDetailList() {
+        return examTaskDetailList;
     }
 
-    public void setExamTaskDetail(ExamTaskDetail examTaskDetail) {
-        this.examTaskDetail = examTaskDetail;
+    public void setExamTaskDetailList(List<ExamTaskDetail> examTaskDetailList) {
+        this.examTaskDetailList = examTaskDetailList;
     }
 
     public ExamDetailParams getExamDetail() {

+ 26 - 0
distributed-print-business/src/main/java/com/qmth/distributed/print/business/entity/BasicCardRule.java

@@ -92,6 +92,16 @@ public class BasicCardRule extends BaseEntity implements Serializable {
      */
     @TableField("required_fields")
     private String requiredFields;
+    /**
+     * 学号是否包含字母
+     */
+    @TableField("contains_letter")
+    private String containsLetter;
+    /**
+     * 学号字母位置坐标
+     */
+    @TableField("relation_list")
+    private String relationList;
     /**
      * 扩展字段
      */
@@ -355,4 +365,20 @@ public class BasicCardRule extends BaseEntity implements Serializable {
     public void setDefaultOptionNumber(Integer defaultOptionNumber) {
         this.defaultOptionNumber = defaultOptionNumber;
     }
+
+    public String getContainsLetter() {
+        return containsLetter;
+    }
+
+    public void setContainsLetter(String containsLetter) {
+        this.containsLetter = containsLetter;
+    }
+
+    public String getRelationList() {
+        return relationList;
+    }
+
+    public void setRelationList(String relationList) {
+        this.relationList = relationList;
+    }
 }

+ 35 - 0
distributed-print-business/src/main/java/com/qmth/distributed/print/business/entity/ExamTask.java

@@ -54,6 +54,11 @@ public class ExamTask extends BaseEntity implements Serializable {
      */
     @TableField("paper_number")
     private String paperNumber;
+    /**
+     * 是否开启AB卷
+     */
+    @TableField("open_ab")
+    private Boolean openAb;
 
     /**
      * 课程创建的任务序号
@@ -103,6 +108,12 @@ public class ExamTask extends BaseEntity implements Serializable {
      */
     @TableField("review_status")
     private ReviewStatusEnum reviewStatus;
+    @TableField("paper_confirm_attachment_ids")
+    private String paperConfirmAttachmentIds;
+    /**
+     * 备注
+     */
+    private String remark;
     /**
      * 0-禁用,1-启用
      */
@@ -233,6 +244,14 @@ public class ExamTask extends BaseEntity implements Serializable {
         this.paperNumber = paperNumber;
     }
 
+    public Boolean getOpenAb() {
+        return openAb;
+    }
+
+    public void setOpenAb(Boolean openAb) {
+        this.openAb = openAb;
+    }
+
     public String getSequence() {
         return sequence;
     }
@@ -416,4 +435,20 @@ public class ExamTask extends BaseEntity implements Serializable {
     public void setExamTaskContent(String examTaskContent) {
         this.examTaskContent = examTaskContent;
     }
+
+    public String getPaperConfirmAttachmentIds() {
+        return paperConfirmAttachmentIds;
+    }
+
+    public void setPaperConfirmAttachmentIds(String paperConfirmAttachmentIds) {
+        this.paperConfirmAttachmentIds = paperConfirmAttachmentIds;
+    }
+
+    public String getRemark() {
+        return remark;
+    }
+
+    public void setRemark(String remark) {
+        this.remark = remark;
+    }
 }

+ 32 - 47
distributed-print-business/src/main/java/com/qmth/distributed/print/business/entity/ExamTaskDetail.java

@@ -36,14 +36,27 @@ public class ExamTaskDetail extends BaseEntity implements Serializable {
     @JsonSerialize(using = ToStringSerializer.class)
     @TableField("exam_task_id")
     private Long examTaskId;
+    /**
+     * 备用卷序号
+     */
+    @TableField("serial_number")
+    private Integer serialNumber;
     /**
      * 试卷类型,多个以”/“分隔,如A/B/C/D
      */
     @TableField("paper_type")
     private String paperType;
-
-    @TableField("open_ab")
-    private Boolean openAb;
+    /**
+     * 是否曝光
+     */
+    @TableField("exposed")
+    private Boolean exposed;
+    /**
+     * 曝光的考试ID
+     */
+    @JsonSerialize(using = ToStringSerializer.class)
+    @TableField("exposed_exam_id")
+    private Long exposedExamId;
     /**
      * [
      * {
@@ -61,23 +74,6 @@ public class ExamTaskDetail extends BaseEntity implements Serializable {
     @ApiModelProperty(value = "转换后A3试卷附件")
     @TableField("paper_attachment_ids")
     private String paperAttachmentIds;
-
-    /**
-     * [
-     * {
-     * "attachmentId": 12
-     * },
-     * {
-     * "attachmentId": 13
-     * }
-     * ]
-     */
-    @TableField("paper_confirm_attachment_ids")
-    private String paperConfirmAttachmentIds;
-    /**
-     * 备注
-     */
-    private String remark;
     /**
      * 曝光卷型:已打印卷型,多个以”/“分隔,如A/B/C/D
      */
@@ -92,9 +88,6 @@ public class ExamTaskDetail extends BaseEntity implements Serializable {
 
     private Boolean enable;
 
-    @TableField(exist = false)
-    private String operateType;
-
     @ApiModelProperty(value = "流程审批人列表")
     @JsonSerialize(using = ToStringSerializer.class)
     @TableField(exist = false)
@@ -138,36 +131,36 @@ public class ExamTaskDetail extends BaseEntity implements Serializable {
         this.paperType = paperType;
     }
 
-    public Boolean getOpenAb() {
-        return openAb;
+    public Integer getSerialNumber() {
+        return serialNumber;
     }
 
-    public void setOpenAb(Boolean openAb) {
-        this.openAb = openAb;
+    public void setSerialNumber(Integer serialNumber) {
+        this.serialNumber = serialNumber;
     }
 
-    public String getPaperAttachmentIds() {
-        return paperAttachmentIds;
+    public Boolean getExposed() {
+        return exposed;
     }
 
-    public void setPaperAttachmentIds(String paperAttachmentIds) {
-        this.paperAttachmentIds = paperAttachmentIds;
+    public void setExposed(Boolean exposed) {
+        this.exposed = exposed;
     }
 
-    public String getPaperConfirmAttachmentIds() {
-        return paperConfirmAttachmentIds;
+    public Long getExposedExamId() {
+        return exposedExamId;
     }
 
-    public void setPaperConfirmAttachmentIds(String paperConfirmAttachmentIds) {
-        this.paperConfirmAttachmentIds = paperConfirmAttachmentIds;
+    public void setExposedExamId(Long exposedExamId) {
+        this.exposedExamId = exposedExamId;
     }
 
-    public String getRemark() {
-        return remark;
+    public String getPaperAttachmentIds() {
+        return paperAttachmentIds;
     }
 
-    public void setRemark(String remark) {
-        this.remark = remark;
+    public void setPaperAttachmentIds(String paperAttachmentIds) {
+        this.paperAttachmentIds = paperAttachmentIds;
     }
 
     public String getExposedPaperType() {
@@ -202,14 +195,6 @@ public class ExamTaskDetail extends BaseEntity implements Serializable {
         this.enable = enable;
     }
 
-    public String getOperateType() {
-        return operateType;
-    }
-
-    public void setOperateType(String operateType) {
-        this.operateType = operateType;
-    }
-
     public String getExamTaskContent() {
         return examTaskContent;
     }

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

@@ -64,4 +64,9 @@ public interface ExamTaskDetailService extends IService<ExamTaskDetail> {
     void updateUnexposePaperType(Long examId, String paperNumber, String exposePaperType);
 
     int countByCardId(Long cardId);
+
+    List<ExamTaskDetail> listByExamIdAndPaperNumber(Long examId, String paperNumber);
+    List<ExamTaskDetail> listByExamTaskId(Long examTaskId);
+
+    void updateExposedExamIdById(Long examId, Long id);
 }

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

@@ -42,8 +42,8 @@ public class ExamTaskAssignPaperTypeServiceImpl extends MppServiceImpl<ExamTaskA
         ExamTaskAssignPaperType examTaskAssignPaperType = this.selectByMultiId(new ExamTaskAssignPaperType(tbTaskPdf.getExamId(), examDetailCourse.getPaperNumber(), examDetail.getExamStartTime(), examDetail.getExamEndTime()));
         if (examTaskAssignPaperType == null) {
             try {
-                String paperType = createPdfUtil.getPaperType(examDetail.getPrintPlanId(), examDetail.getExamId(), examDetailCourse.getPaperNumber());
-                examTaskAssignPaperType = new ExamTaskAssignPaperType(tbTaskPdf.getExamId(), examDetailCourse.getPaperNumber(), examDetail.getExamStartTime(), examDetail.getExamEndTime(), paperType, AssignModeEnum.AUTO);
+                ExamTaskDetail paperType = createPdfUtil.getPaperType(examDetail.getPrintPlanId(), examDetail.getExamId(), examDetailCourse.getPaperNumber());
+                examTaskAssignPaperType = new ExamTaskAssignPaperType(tbTaskPdf.getExamId(), examDetailCourse.getPaperNumber(), examDetail.getExamStartTime(), examDetail.getExamEndTime(), paperType.getSerialNumber().toString(), AssignModeEnum.AUTO);
                 this.saveOrUpdateByMultiId(examTaskAssignPaperType);
             } catch (Exception e) {
                 throw ExceptionResultEnum.ERROR.exception(e.getMessage());

+ 27 - 3
distributed-print-business/src/main/java/com/qmth/distributed/print/business/service/impl/ExamTaskDetailServiceImpl.java

@@ -193,9 +193,8 @@ public class ExamTaskDetailServiceImpl extends ServiceImpl<ExamTaskDetailMapper,
         }
 
         // 更新考生关联类型
-        ExamTaskDetail examTaskDetail = this.getByExamTaskId(newExamTask.getId());
         List<String> types = Arrays.asList(paperParam.getRelatePaperType().split(","));
-        int drawCount = examTaskDetail.getOpenAb() ? 2 : 1;
+        int drawCount = examTask.getOpenAb() ? 2 : 1;
         if (drawCount - types.size() != 0) {
             throw ExceptionResultEnum.ERROR.exception("关联卷型与设置数量不一致");
         }
@@ -293,7 +292,6 @@ public class ExamTaskDetailServiceImpl extends ServiceImpl<ExamTaskDetailMapper,
                 .set(ExamTaskDetail::getPaperAttachmentIds, examTaskDetail.getPaperAttachmentIds())
                 .set(ExamTaskDetail::getUnexposedPaperType, unexposedPaperType)
                 .set(ExamTaskDetail::getRelatePaperType, null)
-                .set(ExamTaskDetail::getOpenAb, examTaskDetail.getOpenAb())
                 .eq(ExamTaskDetail::getExamTaskId, examTaskDetail.getExamTaskId());
         this.update(examTaskDetailUpdateWrapper);
 
@@ -727,6 +725,32 @@ public class ExamTaskDetailServiceImpl extends ServiceImpl<ExamTaskDetailMapper,
         return examTaskDetailMapper.countByCardId(cardId);
     }
 
+    @Override
+    public List<ExamTaskDetail> listByExamIdAndPaperNumber(Long examId, String paperNumber) {
+        ExamTask examTask = examTaskService.getByExamIdAndPaperNumber(examId, paperNumber);
+        if (examTask == null) {
+            return Collections.emptyList();
+        }
+        this.listByExamTaskId(examTask.getId());
+        return null;
+    }
+
+    @Override
+    public List<ExamTaskDetail> listByExamTaskId(Long examTaskId) {
+        QueryWrapper<ExamTaskDetail> queryWrapper = new QueryWrapper<>();
+        queryWrapper.lambda().eq(ExamTaskDetail::getExamTaskId, examTaskId)
+                .orderByAsc(ExamTaskDetail::getSerialNumber);
+        return this.list(queryWrapper);
+    }
+
+    @Override
+    public void updateExposedExamIdById(Long examId, Long id) {
+        UpdateWrapper<ExamTaskDetail> updateWrapper = new UpdateWrapper<>();
+        updateWrapper.lambda().set(ExamTaskDetail::getExposedExamId, examId)
+                .eq(ExamTaskDetail::getId, id);
+        this.update(updateWrapper);
+    }
+
     /**
      * 卷库校验
      *

+ 65 - 68
distributed-print-business/src/main/java/com/qmth/distributed/print/business/service/impl/ExamTaskServiceImpl.java

@@ -709,23 +709,17 @@ public class ExamTaskServiceImpl extends ServiceImpl<ExamTaskMapper, ExamTask> i
     public Map<String, Object> saveExamTaskDetail(ExamTaskDetail examTaskDetail) {
         SysUser sysUser = (SysUser) ServletUtil.getRequestUser();
         Optional.ofNullable(examTaskDetail.getExamTaskId()).orElseThrow(() -> ExceptionResultEnum.ERROR.exception("命题任务ID不能为空"));
-        if (StringUtils.isBlank(examTaskDetail.getOperateType())) {
-            throw ExceptionResultEnum.ERROR.exception("命题任务提交类型不能为空");
-        }
-
         // 更新examTask状态status
         ExamTask examTask = this.getById(examTaskDetail.getExamTaskId());
         // 提交时,校验
-        if (ExamStatusEnum.SUBMIT.name().equals(examTaskDetail.getOperateType())) {
-            BasicPrintConfig basicPrintConfig = basicPrintConfigService.getByExamId(examTask.getExamId());
-            if (basicPrintConfig == null) {
-                throw ExceptionResultEnum.ERROR.exception("印品配置未设置");
-            }
-            validSubmitParam(examTaskDetail, basicPrintConfig.getPrintContent());
+        BasicPrintConfig basicPrintConfig = basicPrintConfigService.getByExamId(examTask.getExamId());
+        if (basicPrintConfig == null) {
+            throw ExceptionResultEnum.ERROR.exception("印品配置未设置");
         }
+        validSubmitParam(examTaskDetail, basicPrintConfig.getPrintContent(), examTask.getOpenAb());
 
         Map<String, Object> map = new HashMap<>();
-        if (ExamStatusEnum.SUBMIT.name().equals(examTaskDetail.getOperateType()) && examTask.getReview()) {
+//        if (ExamStatusEnum.SUBMIT.name().equals(examTaskDetail.getOperateType()) && examTask.getReview()) {
             // 审核一级
             Task task = taskService.createTaskQuery().processInstanceId(String.valueOf(examTask.getFlowId())).singleResult();
             if (Objects.nonNull(task)) {
@@ -736,11 +730,11 @@ public class ExamTaskServiceImpl extends ServiceImpl<ExamTaskMapper, ExamTask> i
                 map = activitiService.taskApprove(map);
                 map.put(SystemConstant.SEND_FLOW_MQ, true);
             }
-        }
+//        }
 
         UpdateWrapper<ExamTask> updateWrapper = new UpdateWrapper<>();
         updateWrapper.lambda()
-                .set(ExamTask::getStatus, examTaskDetail.getOperateType())
+//                .set(ExamTask::getStatus, examTaskDetail.getOperateType())
                 .set(ExamTask::getUpdateId, sysUser.getId())
                 .set(ExamTask::getUpdateTime, System.currentTimeMillis())
                 .set(ExamTask::getReviewStatus, null)
@@ -1132,49 +1126,51 @@ public class ExamTaskServiceImpl extends ServiceImpl<ExamTaskMapper, ExamTask> i
             this.save(examTask);
 
             // 新建试卷
-            ExamTaskDetail examTaskDetail = examTaskSubmitContent.getExamTaskDetail();
-            validSubmitParam(examTaskDetail, basicPrintConfig.getPrintContent());
-            // 已曝光试卷和未曝光试卷赋值(新增时,已曝光试卷为null,未曝光试卷为paper_type)
-            examTaskDetail.setId(SystemConstant.getDbUuid());
-            examTaskDetail.setUnexposedPaperType(examTaskDetail.getPaperType());
-            examTaskDetail.setExamTaskId(examTask.getId());
-            examTaskDetail.insertInfo(sysUser.getId());
-            List<PaperInfoVo> filePathVoList = examTaskDetail.getPaperInfoVoList(null);
-            for (PaperInfoVo paperInfoVo : filePathVoList) {
-                BasicAttachment basicAttachment = basicAttachmentService.getById(paperInfoVo.getAttachmentId());
-                FilePathVo filePathVo = JSON.parseObject(basicAttachment.getPath(), FilePathVo.class);
-                InputStream inputStream = fileUploadService.downloadFile(filePathVo.getPath(), filePathVo.getUploadType(), filePathVo.getType());
-                List<ConvertJpgStorage> convertJpgStorageList = htmlToJpgUtil.convertPdfToJpg(Long.valueOf(paperInfoVo.getAttachmentId()), inputStream, sysUser.getId());
-                if (convertJpgStorageList.size() > 0) {
-                    paperInfoVo.setJpgAttachmentId(JSON.toJSONString(convertJpgStorageList));
-                } else {
-                    paperInfoVo.setJpgAttachmentId(null);
+            List<ExamTaskDetail> examTaskDetailList = examTaskSubmitContent.getExamTaskDetailList();
+            for (ExamTaskDetail examTaskDetail : examTaskDetailList) {
+                validSubmitParam(examTaskDetail, basicPrintConfig.getPrintContent(), examTask.getOpenAb());
+                // 已曝光试卷和未曝光试卷赋值(新增时,已曝光试卷为null,未曝光试卷为paper_type)
+                examTaskDetail.setId(SystemConstant.getDbUuid());
+                examTaskDetail.setUnexposedPaperType(examTaskDetail.getPaperType());
+                examTaskDetail.setExamTaskId(examTask.getId());
+                examTaskDetail.insertInfo(sysUser.getId());
+                List<PaperInfoVo> filePathVoList = examTaskDetail.getPaperInfoVoList(null);
+                for (PaperInfoVo paperInfoVo : filePathVoList) {
+                    BasicAttachment basicAttachment = basicAttachmentService.getById(paperInfoVo.getAttachmentId());
+                    FilePathVo filePathVo = JSON.parseObject(basicAttachment.getPath(), FilePathVo.class);
+                    InputStream inputStream = fileUploadService.downloadFile(filePathVo.getPath(), filePathVo.getUploadType(), filePathVo.getType());
+                    List<ConvertJpgStorage> convertJpgStorageList = htmlToJpgUtil.convertPdfToJpg(Long.valueOf(paperInfoVo.getAttachmentId()), inputStream, sysUser.getId());
+                    if (convertJpgStorageList.size() > 0) {
+                        paperInfoVo.setJpgAttachmentId(JSON.toJSONString(convertJpgStorageList));
+                    } else {
+                        paperInfoVo.setJpgAttachmentId(null);
+                    }
                 }
-            }
-            examTaskDetail.setPaperAttachmentIds(JSON.toJSONString(filePathVoList));
-            examTaskDetailService.save(examTaskDetail);
+                examTaskDetail.setPaperAttachmentIds(JSON.toJSONString(filePathVoList));
+                examTaskDetailService.save(examTaskDetail);
 
-            String paperAttachmentIds = examTaskDetail.getPaperAttachmentIds();
-            List<PaperInfoVo> paperInfoVoList = ExamTaskUtil.parsePaperAttachmentPath(paperAttachmentIds);
-            // 将题卡更新为已绑定
-            examCardService.updateUsedById(paperInfoVoList.stream().filter(m -> StringUtils.isNotBlank(m.getCardId())).map(m -> Long.parseLong(m.getCardId())).collect(Collectors.toList()));
-            // 更新题库试卷表
-            for (PaperInfoVo paperInfoVo : paperInfoVoList) {
-                if (StringUtils.isNotBlank(paperInfoVo.getUuid())) {
-                    UpdateWrapper<ExamTaskPaperData> updateWrapper = new UpdateWrapper<>();
-                    updateWrapper.lambda().set(ExamTaskPaperData::getPaperNumber, examTask.getPaperNumber())
-                            .eq(ExamTaskPaperData::getExamId, examTask.getExamId())
-                            .eq(ExamTaskPaperData::getPaperNumber, paperInfoVo.getUuid())
-                            .eq(ExamTaskPaperData::getPaperId, paperInfoVo.getPaperId())
-                            .eq(ExamTaskPaperData::getUuid, paperInfoVo.getUuid());
-                    examTaskPaperDataService.update(updateWrapper);
-
-                    // 删除临时数据
-                    QueryWrapper<ExamTaskPaperData> deleteWrapper = new QueryWrapper<>();
-                    deleteWrapper.lambda().eq(ExamTaskPaperData::getExamId, examTask.getExamId())
-                            .eq(ExamTaskPaperData::getPaperNumber, paperInfoVo.getUuid())
-                            .ne(ExamTaskPaperData::getPaperId, paperInfoVo.getPaperId());
-                    examTaskPaperDataService.remove(deleteWrapper);
+                String paperAttachmentIds = examTaskDetail.getPaperAttachmentIds();
+                List<PaperInfoVo> paperInfoVoList = ExamTaskUtil.parsePaperAttachmentPath(paperAttachmentIds);
+                // 将题卡更新为已绑定
+                examCardService.updateUsedById(paperInfoVoList.stream().filter(m -> StringUtils.isNotBlank(m.getCardId())).map(m -> Long.parseLong(m.getCardId())).collect(Collectors.toList()));
+                // 更新题库试卷表
+                for (PaperInfoVo paperInfoVo : paperInfoVoList) {
+                    if (StringUtils.isNotBlank(paperInfoVo.getUuid())) {
+                        UpdateWrapper<ExamTaskPaperData> updateWrapper = new UpdateWrapper<>();
+                        updateWrapper.lambda().set(ExamTaskPaperData::getPaperNumber, examTask.getPaperNumber())
+                                .eq(ExamTaskPaperData::getExamId, examTask.getExamId())
+                                .eq(ExamTaskPaperData::getPaperNumber, paperInfoVo.getUuid())
+                                .eq(ExamTaskPaperData::getPaperId, paperInfoVo.getPaperId())
+                                .eq(ExamTaskPaperData::getUuid, paperInfoVo.getUuid());
+                        examTaskPaperDataService.update(updateWrapper);
+
+                        // 删除临时数据
+                        QueryWrapper<ExamTaskPaperData> deleteWrapper = new QueryWrapper<>();
+                        deleteWrapper.lambda().eq(ExamTaskPaperData::getExamId, examTask.getExamId())
+                                .eq(ExamTaskPaperData::getPaperNumber, paperInfoVo.getUuid())
+                                .ne(ExamTaskPaperData::getPaperId, paperInfoVo.getPaperId());
+                        examTaskPaperDataService.remove(deleteWrapper);
+                    }
                 }
             }
 
@@ -1194,14 +1190,14 @@ public class ExamTaskServiceImpl extends ServiceImpl<ExamTaskMapper, ExamTask> i
 //                    examPrintPlan.setExamStartTime(examDetailParams.getExamStartTime());
 //                    examPrintPlan.setExamEndTime(examDetailParams.getExamEndTime());
                 }
-                List<String> stringList = JSONObject.parseArray(basicPrintConfig.getPrintContent(), String.class);
-                if (!stringList.contains("PAPER")) {
-                    long count = paperInfoVoList.stream().filter(m -> Objects.isNull(m.getAttachmentId())).count();
-                    if (count == 0) {
-                        stringList.add("PAPER");
-                    }
-                }
-                examPrintPlan.setPrintContent(String.join(",", stringList));
+//                List<String> stringList = JSONObject.parseArray(basicPrintConfig.getPrintContent(), String.class);
+//                if (!stringList.contains("PAPER")) {
+//                    long count = paperInfoVoList.stream().filter(m -> Objects.isNull(m.getAttachmentId())).count();
+//                    if (count == 0) {
+//                        stringList.add("PAPER");
+//                    }
+//                }
+                examPrintPlan.setPrintContent(basicPrintConfig.getPrintContent());
                 examPrintPlan.setBackupMethod(BackupMethodEnum.valueOf(basicPrintConfig.getBackupMethod()));
                 examPrintPlan.setBackupCount(basicPrintConfig.getBackupCount());
                 examPrintPlan.setDrawRule(basicPrintConfig.getDrawRule());
@@ -1221,7 +1217,7 @@ public class ExamTaskServiceImpl extends ServiceImpl<ExamTaskMapper, ExamTask> i
                     Map<String, Object> map = new HashMap<>();
                     map.computeIfAbsent(SystemConstant.FLOW_TASK_ID, v -> task.getId());
                     map.computeIfAbsent(SystemConstant.APPROVE_OPERATION, v -> FlowApprovePassEnum.PASS);
-                    map.computeIfAbsent(SystemConstant.PAPAER_ATTACHMENT_IDS, v -> examTaskDetail.getPaperAttachmentIds());
+                    map.computeIfAbsent(SystemConstant.PAPAER_ATTACHMENT_IDS, v -> examTaskDetailList.stream().map(ExamTaskDetail::getPaperAttachmentIds).collect(Collectors.toList()));
                     map.computeIfAbsent(SystemConstant.APPROVE_USER_IDS, v -> examTaskSubmitPram.getApproveUserIds());
                     activitiService.taskApprove(map);
                     mapVar.putAll(map);
@@ -2224,8 +2220,9 @@ public class ExamTaskServiceImpl extends ServiceImpl<ExamTaskMapper, ExamTask> i
      * 简单校验提交参数
      *
      * @param examTaskDetail
+     * @param openAb
      */
-    void validSubmitParam(ExamTaskDetail examTaskDetail, String printContent) {
+    void validSubmitParam(ExamTaskDetail examTaskDetail, String printContent, Boolean openAb) {
         List<PaperInfoVo> paperInfoVoList = ExamTaskUtil.parsePaperAttachmentPath(examTaskDetail.getPaperAttachmentIds());
         if (StringUtils.isBlank(examTaskDetail.getPaperType()) || CollectionUtils.isEmpty(paperInfoVoList)) {
             throw ExceptionResultEnum.ERROR.exception("请添加卷型并上传试卷或题卡");
@@ -2245,10 +2242,10 @@ public class ExamTaskServiceImpl extends ServiceImpl<ExamTaskMapper, ExamTask> i
         }
 
         String[] paperTypes = examTaskDetail.getPaperType().split(",");
-//        int drawCount = examTaskDetail.getOpenAb() ? 2 : 1;
-//        if (paperTypes.length - drawCount < 0) {
-//            throw ExceptionResultEnum.ERROR.exception("单次抽卷数量不能大于卷型数量");
-//        }
+        int paperCount = openAb != null && openAb ? 2 : 1;
+        if (paperCount - paperTypes.length != 0) {
+            throw ExceptionResultEnum.ERROR.exception(openAb ? "备用卷内必须有AB两个卷型" : "备用卷内只能有A卷");
+        }
 
         // 是否强制包含试卷
         // 未上传试卷的类型个数

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

@@ -186,10 +186,11 @@ public class PdfTaskLogicServiceImpl implements PdfTaskLogicService {
         try {
             for (ExamDetailCourse examDetailCourse : createPdfDto.getExamDetailCourseList()) {
                 ExamTaskAssignPaperType examTaskAssignPaperType = examTaskAssignPaperTypeService.extractPaperType(tbTaskPdf, examDetailCourse);
+                ExamTaskDetail examTaskDetail = createPdfUtil.extractPaperType(tbTaskPdf, examDetailCourse);
                 List<ExamStudent> examStudentList = examStudentService.listByExamDetailCourseId(examDetailCourse.getId());
                 // 考生实际关联试卷类型
                 List<String> relatePaperTypes = new ArrayList<>();
-                List<String> paperTypes = Arrays.stream(examTaskAssignPaperType.getPaperType().split(",")).sorted(Comparator.comparing(String::valueOf)).collect(Collectors.toList());
+                List<String> paperTypes = Arrays.stream(examTaskDetail.getPaperType().split(",")).sorted(Comparator.comparing(String::valueOf)).collect(Collectors.toList());
                 if (CollectionUtils.isNotEmpty(examStudentList)) {
                     AtomicInteger atomicInteger = new AtomicInteger(0);
                     for (ExamStudent examStudent : examStudentList) {
@@ -212,12 +213,6 @@ public class PdfTaskLogicServiceImpl implements PdfTaskLogicService {
                     relatePaperTypes.addAll(paperTypes);
                 }
 
-                // 更新卷型数据
-                if (!CollectionUtils.isEqualCollection(paperTypes, relatePaperTypes)) {
-                    examTaskAssignPaperType.setPaperType(String.join(",", relatePaperTypes));
-                    examTaskAssignPaperTypeService.updateByMultiId(examTaskAssignPaperType);
-                }
-
                 examDetailCourse.setPaperType(String.join(",", relatePaperTypes));
                 examDetailCourseService.updateById(examDetailCourse);
 
@@ -309,7 +304,7 @@ public class PdfTaskLogicServiceImpl implements PdfTaskLogicService {
                     Map<String, BasicAttachment> stringBasicAttachmentMap = new HashMap<>();
                     ExamStudentInfo examStudentInfo = new ExamStudentInfo();
                     examStudentInfo.setCourseCode(basicCourse.getCode());
-                    int drawCount = examTaskDetail.getOpenAb() ? 2 : 1;
+                    int drawCount = examTask.getOpenAb() ? 2 : 1;
                     int i = 0;
                     while (i < examDetailCourse.getTotalSubjects()) {
                         int seq = atomicInteger.getAndIncrement();

+ 32 - 36
distributed-print-business/src/main/java/com/qmth/distributed/print/business/util/CreatePdfUtil.java

@@ -5,6 +5,7 @@ import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONObject;
 import com.itextpdf.text.pdf.PdfReader;
+import com.qmth.boot.core.concurrent.annotation.Lockable;
 import com.qmth.distributed.print.business.bean.dto.*;
 import com.qmth.distributed.print.business.bean.dto.pdf.ExamStudentInfo;
 import com.qmth.distributed.print.business.entity.*;
@@ -451,17 +452,9 @@ public class CreatePdfUtil {
         return paperPdfDtoList;
     }
 
-    private String randomPaperType(String[] unexposedPaperTypes, int drawCount) {
-        List<String> finalTypes = new ArrayList<>();
-        List<String> unexposedPaperTypesList = new ArrayList<>(Arrays.asList(unexposedPaperTypes));
-        for (int i = 0; i < drawCount; i++) {
-            int index = new Random().nextInt(unexposedPaperTypesList.size());
-            finalTypes.add(unexposedPaperTypesList.get(index));
-            unexposedPaperTypesList.remove(index);
-        }
-
-        finalTypes = finalTypes.stream().sorted(Comparator.comparing(String::valueOf)).collect(Collectors.toList());
-        return String.join(",", finalTypes);
+    private ExamTaskDetail randomPaperType(List<ExamTaskDetail> examTaskDetailList) {
+        int index = new Random().nextInt(examTaskDetailList.size());
+        return examTaskDetailList.get(index);
     }
 
     /**
@@ -713,48 +706,51 @@ public class CreatePdfUtil {
         return htmlContent;
     }
 
-    public String getPaperType(Long printPlanId, Long examId, String paperNumber) {
+    public ExamTaskDetail getPaperType(Long printPlanId, Long examId, String paperNumber) {
         ExamPrintPlan examPrintPlan = examPrintPlanService.getById(printPlanId);
         //抽取卷型
         DrawRuleEnum drawRule = Objects.nonNull(examPrintPlan.getDrawRule()) ? examPrintPlan.getDrawRule() : DrawRuleEnum.ONE;
-        ExamTaskDetail examTaskDetail = examTaskDetailService.getByExamIdAndCourseIdAndPaperNumber(examId, null, paperNumber);
-        // 单次抽取套数
-        int drawCount = examTaskDetail.getOpenAb() ? 2 : 1;
+        List<ExamTaskDetail> examTaskDetailList = examTaskDetailService.listByExamIdAndPaperNumber(examId, paperNumber);
 
-        String paperType = null;
         try {
-            //未曝光卷型
-            String unexposedPaperType = examTaskDetail.getUnexposedPaperType();
-            //已曝光卷型
-            String totalPaperType = examTaskDetail.getPaperType();
-            String[] paperTypes;
+            // 未曝光备用卷
+            List<ExamTaskDetail> unexposedExamTaskDetailList = examTaskDetailList.stream().filter(m -> !m.getExposed()).collect(Collectors.toList());
             if (drawRule == DrawRuleEnum.ONE) {
-                if (StringUtils.isBlank(unexposedPaperType)) {
+                if (CollectionUtils.isEmpty(unexposedExamTaskDetailList)) {
                     throw ExceptionResultEnum.PAPER_ERROR.exception();
                 }
-                paperTypes = unexposedPaperType.split(",");
-                if (paperTypes.length - drawCount < 0) {
-                    throw ExceptionResultEnum.ERROR.exception("可用卷型数量小于抽取数量");
-                }
+                return randomPaperType(unexposedExamTaskDetailList);
             } else {
-                if (StringUtils.isAllBlank(totalPaperType, unexposedPaperType)) {
+                if (CollectionUtils.isEmpty(examTaskDetailList)) {
                     throw ExceptionResultEnum.PAPER_ERROR.exception();
                 }
-                if (StringUtils.isNotBlank(unexposedPaperType)) {
-                    paperTypes = unexposedPaperType.split(",");
-                    // 未曝光卷型小于抽取数量,则使用所有卷型
-                    if (paperTypes.length - drawCount < 0) {
-                        paperTypes = totalPaperType.split(",");
-                    }
+                if (CollectionUtils.isNotEmpty(unexposedExamTaskDetailList)) {
+                    return randomPaperType(unexposedExamTaskDetailList);
                 } else {
-                    paperTypes = totalPaperType.split(",");
+                    return randomPaperType(examTaskDetailList);
                 }
             }
-            paperType = randomPaperType(paperTypes, drawCount);
         } catch (Exception e) {
             throw ExceptionResultEnum.ERROR.exception(e.getMessage());
         }
-        return paperType;
     }
 
+    @Lockable(name = "#p0.examId + '-' + #p1.paperNumber")
+    public ExamTaskDetail extractPaperType(TBTaskPdf tbTaskPdf, ExamDetailCourse examDetailCourse) {
+        List<ExamTaskDetail> examTaskDetailList = examTaskDetailService.listByExamIdAndPaperNumber(tbTaskPdf.getExamId(), examDetailCourse.getPaperNumber());
+        Optional<ExamTaskDetail> optional = examTaskDetailList.stream().filter(m -> m.getExposedExamId() != null && m.getExposedExamId().equals(tbTaskPdf.getExamId())).findFirst();
+        if (optional.isPresent()) {
+            ExamTaskDetail examTaskDetail = optional.get();
+            if (examTaskDetail.getExposed()) {
+                throw ExceptionResultEnum.ERROR.exception("备用卷已曝光");
+            }
+            return examTaskDetail;
+        } else {
+            ExamDetail examDetail = examDetailService.getById(tbTaskPdf.getId());
+            ExamTaskDetail examTaskDetail = this.getPaperType(examDetail.getPrintPlanId(), examDetail.getExamId(), examDetailCourse.getPaperNumber());
+            // 更新绑定的考试ID
+            examTaskDetailService.updateExposedExamIdById(tbTaskPdf.getExamId(), examTaskDetail.getId());
+            return examTaskDetail;
+        }
+    }
 }

+ 20 - 0
distributed-print-business/src/main/resources/db/log/xf.sql

@@ -6,3 +6,23 @@ ALTER TABLE `basic_print_config` ADD COLUMN `open_ab` TINYINT(1) NULL DEFAULT 0
 
 -- 20224-10-11
 ALTER TABLE `mark_student` ADD COLUMN `omr_breach` TINYINT(1) NULL DEFAULT 0 COMMENT '识别违纪' AFTER `omr_absent_checked`;
+
+-- 2024-10-14
+ALTER TABLE `exam_task_detail`
+DROP COLUMN `open_ab`,
+ADD COLUMN `serial_number` int(2) NULL COMMENT '备用卷序号(‌1,2,3,4…)' AFTER `exam_task_id`,
+ADD COLUMN `exposed` TINYINT(1) NULL DEFAULT 0 COMMENT '是否曝光' AFTER `remark`;
+ALTER TABLE `exam_task_detail` ADD COLUMN `exposed_exam_id` BIGINT(20) NULL COMMENT '曝光的考试ID' AFTER `exposed`;
+
+ALTER TABLE `exam_task` ADD COLUMN `open_ab` TINYINT(1) NULL DEFAULT 0 COMMENT '是否开启AB卷' AFTER `paper_number`;
+
+ALTER TABLE `basic_card_rule`
+    ADD COLUMN `contains_letter` TINYINT(1) NULL DEFAULT 0 COMMENT '学号是否包含字母' AFTER `default_option_number`,
+ADD COLUMN `relation_list` VARCHAR(500) NULL COMMENT '学号字母所在位置坐标' AFTER `contains_letter`;
+
+ALTER TABLE `exam_task`
+    ADD COLUMN `paper_confirm_attachment_ids` TEXT NULL AFTER `exam_task_content`,
+ADD COLUMN `remark` VARCHAR(200) NULL AFTER `paper_confirm_attachment_ids`;
+
+update exam_task et set et.paper_confirm_attachment_ids = (select paper_confirm_attachment_ids from exam_task_detail etd where et.id = etd.exam_task_id);
+update exam_task et set et.remark = (select remark from exam_task_detail etd where et.id = etd.exam_task_id);

+ 1 - 1
distributed-print/src/main/java/com/qmth/distributed/print/api/ExamTaskApplyController.java

@@ -149,7 +149,7 @@ public class ExamTaskApplyController {
     public Result taskApplySave(@RequestBody ExamTaskDetail examTaskDetail) throws IOException {
         Map<String, Object> map = examTaskService.saveExamTaskDetail(examTaskDetail);
         ExamTask examTask = examTaskService.getById(examTaskDetail.getExamTaskId());
-        if (examTaskDetail.getOperateType().equals(ExamStatusEnum.SUBMIT.name()) && (Objects.nonNull(examTask.getReview()) && !examTask.getReview())) {
+        if ((Objects.nonNull(examTask.getReview()) && !examTask.getReview())) {
             // 校验是否可以提交打印状态
             printCommonService.checkExamDataAndCreatePdfTask(examTask.getSchoolId(), examTask.getExamId(), examTask.getCourseId(), examTask.getPaperNumber(), (SysUser) ServletUtil.getRequestUser());
         }

+ 2 - 1
teachcloud-common/src/main/java/com/qmth/teachcloud/common/entity/BasicOperationLog.java

@@ -52,9 +52,10 @@ public class BasicOperationLog implements Serializable {
     public BasicOperationLog() {
     }
 
-    public BasicOperationLog(Long schoolId, OperationTypeEnum operationType, String functionName, String url, String detail, String args, String runStatus, Long userId) {
+    public BasicOperationLog(Long schoolId, Long privilegeId, OperationTypeEnum operationType, String functionName, String url, String detail, String args, String runStatus, Long userId) {
         this.id = SystemConstant.getDbUuid();
         this.schoolId = schoolId;
+        this.privilegeId = privilegeId;
         this.operationType = operationType;
         this.functionName = functionName;
         this.url = url;

+ 1 - 1
teachcloud-common/src/main/java/com/qmth/teachcloud/common/enums/ExceptionResultEnum.java

@@ -59,7 +59,7 @@ public enum ExceptionResultEnum {
 
     SCHOOL_ENABLE(HttpStatus.INTERNAL_SERVER_ERROR, 5000021, "学校已停用"),
 
-    PAPER_ERROR(HttpStatus.INTERNAL_SERVER_ERROR, 50000022, "当前没有未曝光的卷型"),
+    PAPER_ERROR(HttpStatus.INTERNAL_SERVER_ERROR, 50000022, "没有可用备用卷"),
 
     PAPER_TYPE_ERROR(HttpStatus.INTERNAL_SERVER_ERROR, 50000023, "未获取到试卷类型"),
 

+ 1 - 1
teachcloud-common/src/main/java/com/qmth/teachcloud/common/enums/log/OperationTypeEnum.java

@@ -25,7 +25,7 @@ public enum OperationTypeEnum {
     SYNC("同步"),
     PREVIEW("预览"),
     SSO("单点登录"),
-    SCORE("评卷-回评"),
+    SUBJECTIVE("主观题检查"),
     OTHER("其它");
     private final String name;
 

+ 15 - 13
teachcloud-mark/src/main/java/com/qmth/teachcloud/mark/service/impl/MarkServiceImpl.java

@@ -689,8 +689,6 @@ public class MarkServiceImpl implements MarkService {
                 paperNumber, group.getNumber(), false);
         List<MarkSubjectiveScore> subjectiveScores = markSubjectiveScoreService.listByStudentIdAndGroupNumber(studentId,
                 group.getNumber());
-        // 记录修改日志(按小题)
-        List<BasicOperationLog> basicOperationLogs = new ArrayList<>();
         for (int i = 0; i < questions.size(); i++) {
             MarkQuestion question = questions.get(i);
             MarkSubjectiveScore ss;
@@ -708,12 +706,6 @@ public class MarkServiceImpl implements MarkService {
             ss.setSubNumber(question.getSubNumber());
             if (score != UN_SELECTIVE_SCORE) {
                 ScoreItem item = scoreList.get(i);
-                // 分数有变动,记录日志
-                if (ss.getScore() != null && ss.getScore().doubleValue() != item.getScore().doubleValue()) {
-                    MarkStudentVo markStudent = markStudentService.getDetailById(studentId);
-                    String detail = String.format("%s(%s)课程%s试卷编号下,将%s(%s)的%s题从%s分修改为%s分", markStudent.getCourseName(), markStudent.getCourseCode(), markStudent.getPaperNumber(), markStudent.getStudentName(), markStudent.getStudentCode(), question.getMainNumber() + "-" + question.getSubNumber(), ss.getScore(), item.getScore());
-                    basicOperationLogs.add(new BasicOperationLog(Long.valueOf(ServletUtil.getRequestHeaderSchoolId().toString()), OperationTypeEnum.SCORE, OperationTypeEnum.SCORE.getName(), ServletUtil.getRequest().getServletPath(), detail, JSON.toJSONString(scoreList), "成功", ServletUtil.getRequestUserId()));
-                }
                 ss.setScore(item.getScore());
                 ss.setMainScore(0.0);
                 ss.setUncalculate(false);
@@ -732,10 +724,6 @@ public class MarkServiceImpl implements MarkService {
             // }
             markSubjectiveScoreService.saveOrUpdateByMultiId(ss);
         }
-        // 记录日志
-        if (CollectionUtils.isNotEmpty(basicOperationLogs)) {
-            basicOperationLogService.saveBatch(basicOperationLogs);
-        }
     }
 
     private void scoreCalculate(Long studentId) {
@@ -1026,6 +1014,8 @@ public class MarkServiceImpl implements MarkService {
         markSubjectiveScoreList.sort(Comparator.comparing(MarkSubjectiveScore::getMainNumber)
                 .thenComparingInt(MarkSubjectiveScore::getSubNumber));
         List<Double> scoreList = new ArrayList<>();
+        // 记录修改日志(按小题)
+        List<BasicOperationLog> basicOperationLogs = new ArrayList<>();
         for (MarkSubjectiveScore markSubjectiveScore : markSubjectiveScoreList) {
             List<MarkScoreList> markScoreLists = groupResult.getMarkerScore();
             Optional<MarkScoreList> optional = markScoreLists.stream()
@@ -1033,13 +1023,25 @@ public class MarkServiceImpl implements MarkService {
                             && m.getSubNumber().equals(markSubjectiveScore.getSubNumber()))
                     .findFirst();
             if (optional.isPresent()) {
-                markSubjectiveScore.setScore(optional.get().getScore());
+                double score = optional.get().getScore();
+                // 分数有变动,记录日志
+                if (markSubjectiveScore.getScore().doubleValue() != score) {
+                    MarkStudentVo markStudentVo = markStudentService.getDetailById(markStudent.getId());
+                    String detail = String.format("%s(%s)课程%s试卷编号下,将%s(%s)的%s题从%s分修改为%s分", markStudentVo.getCourseName(), markStudentVo.getCourseCode(), markStudentVo.getPaperNumber(), markStudentVo.getStudentName(), markStudentVo.getStudentCode(), markSubjectiveScore.getMainNumber() + "-" + markSubjectiveScore.getSubNumber(), markSubjectiveScore.getScore(), score);
+                    basicOperationLogs.add(new BasicOperationLog(Long.valueOf(ServletUtil.getRequestHeaderSchoolId().toString()), ServletUtil.getCurrentPrivilegeId(),OperationTypeEnum.SUBJECTIVE, OperationTypeEnum.SUBJECTIVE.getName(), ServletUtil.getRequest().getServletPath(), detail, JSON.toJSONString(scoreList), "成功", ServletUtil.getRequestUserId()));
+                }
+                markSubjectiveScore.setScore(score);
             }
             scoreList.add(markSubjectiveScore.getScore());
         }
         groupResult.setGroupScore(scoreList.stream().collect(Collectors.summingDouble(x -> x)));
         groupResult.setScoreList(scoreList.toArray(new Double[]{}));
         markSubjectiveScoreService.saveOrUpdateBatchByMultiId(markSubjectiveScoreList);
+
+        // 记录日志
+        if (CollectionUtils.isNotEmpty(basicOperationLogs)) {
+            basicOperationLogService.saveBatch(basicOperationLogs);
+        }
     }
 
     private String getKey(MarkStudent student) {