Browse Source

3.4.5 update-20250424,bug修改

xiaofei 1 month ago
parent
commit
05df69cf51
15 changed files with 231 additions and 18 deletions
  1. 6 0
      distributed-print-business/src/main/java/com/qmth/distributed/print/business/bean/dto/ExamTaskDetailDto.java
  2. 7 0
      distributed-print-business/src/main/java/com/qmth/distributed/print/business/mapper/ExamTaskMapper.java
  3. 9 0
      distributed-print-business/src/main/java/com/qmth/distributed/print/business/service/ExamSyncService.java
  4. 6 0
      distributed-print-business/src/main/java/com/qmth/distributed/print/business/service/ExamTaskService.java
  5. 4 0
      distributed-print-business/src/main/java/com/qmth/distributed/print/business/service/PrintCommonService.java
  6. 74 0
      distributed-print-business/src/main/java/com/qmth/distributed/print/business/service/impl/ExamSyncServiceImpl.java
  7. 50 3
      distributed-print-business/src/main/java/com/qmth/distributed/print/business/service/impl/ExamTaskServiceImpl.java
  8. 17 12
      distributed-print-business/src/main/java/com/qmth/distributed/print/business/service/impl/PrintCommonServiceImpl.java
  9. 18 0
      distributed-print-business/src/main/resources/mapper/ExamTaskMapper.xml
  10. 4 0
      distributed-print/install/mysql/init/teachcloud_db.sql
  11. 5 0
      distributed-print/install/mysql/upgrade/3.4.5.sql
  12. 21 1
      distributed-print/src/main/java/com/qmth/distributed/print/api/ExamTaskQueryController.java
  13. 5 0
      distributed-print/src/main/resources/upgrade/3.4.5-upgrade.sql
  14. 2 1
      teachcloud-mark/src/main/java/com/qmth/teachcloud/mark/enums/LockType.java
  15. 3 1
      teachcloud-mark/src/main/java/com/qmth/teachcloud/mark/service/impl/MarkQuestionServiceImpl.java

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

@@ -2,6 +2,7 @@ package com.qmth.distributed.print.business.bean.dto;
 
 import com.fasterxml.jackson.databind.annotation.JsonSerialize;
 import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
+import com.qmth.boot.tools.excel.annotation.ExcelColumn;
 import com.qmth.distributed.print.business.enums.MakeMethodEnum;
 import io.swagger.annotations.ApiModelProperty;
 
@@ -15,10 +16,13 @@ public class ExamTaskDetailDto {
     private String examDetailId;
     private String printPlanId;
     private String printPlanName;
+    @ExcelColumn(name = "试卷编号", index = 2)
     private String paperNumber;
     @JsonSerialize(using = ToStringSerializer.class)
     private Long courseId;
+    @ExcelColumn(name = "课程代码", index = 0)
     private String courseCode;
+    @ExcelColumn(name = "课程名称", index = 1)
     private String courseName;
     private String openCollege;
     private String specialty;
@@ -27,7 +31,9 @@ public class ExamTaskDetailDto {
     @ApiModelProperty(value = "题卡规则名称")
     private String cardRuleName;
     private String userId;
+    @ExcelColumn(name = "命题老师工号", index = 3)
     private String loginName;
+    @ExcelColumn(name = "命题老师姓名", index = 4)
     private String userName;
     private String status;
     private Boolean enable;

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

@@ -53,6 +53,11 @@ public interface ExamTaskMapper extends BaseMapper<ExamTask> {
             @Param("paperNumber") String paperNumber, @Param("startTime") Long startTime, @Param("endTime") Long endTime, @Param("dpr") DataPermissionRule dpr,
             @Param("containsQuestionTeacher") boolean containsQuestionTeacher, @Param("userId") Long userId);
 
+    List<ExamTaskDetailDto> listTaskPaper(@Param("schoolId") Long schoolId, @Param("semesterId") Long semesterId, @Param("examId") Long examId,
+                                           @Param("openCollegeId") Long openCollegeId, @Param("courseId") Long courseId,
+                                           @Param("paperNumber") String paperNumber, @Param("startTime") Long startTime, @Param("endTime") Long endTime, @Param("dpr") DataPermissionRule dpr,
+                                           @Param("containsQuestionTeacher") boolean containsQuestionTeacher, @Param("userId") Long userId);
+
     ExamTaskDetailCardDto applyGetOne(@Param("examTaskId") Long examTaskId, @Param("source") String source);
 
     List<ExamTask> listExamTaskExpire(@Param("startTime") Long startTime, @Param("endTime") Long endTime, @Param("status") String[] status);
@@ -200,4 +205,6 @@ public interface ExamTaskMapper extends BaseMapper<ExamTask> {
      * @return
      */
     public ScanCalculateResult scanCalculate(@Param("examId") Long examId, @Param("courseId") Long courseId, @Param("paperNumber") String paperNumber, @Param("studentCount") int studentCount);
+
+    List<ExamTask> listUnRelateStudentExamTask(Long examId);
 }

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

@@ -0,0 +1,9 @@
+package com.qmth.distributed.print.business.service;
+
+import com.qmth.teachcloud.common.entity.BasicExam;
+import com.qmth.teachcloud.common.entity.SysUser;
+
+public interface ExamSyncService {
+
+    void relateStudentByExamTask(BasicExam basicExam, SysUser sysUser);
+}

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

@@ -260,4 +260,10 @@ public interface ExamTaskService extends IService<ExamTask> {
     public List<ScanCountResult> scanCountListExport(Long semesterId, Long examId, Long collegeId, Long courseId, String paperNumber, CardTypeEnum cardType);
 
     void saveExamTaskFormSync(Long schoolId, Long examId, ExamTaskDataVo examTaskDataVo);
+
+    boolean relateStudentByExamId(Long examId);
+
+    List<ExamTask> listUnRelateStudentExamTask(Long examId);
+
+    void export(Long semesterId, Long examId, Long openCollegeId, Long courseId, String paperNumber, Long startTime, Long endTime, HttpServletResponse response);
 }

+ 4 - 0
distributed-print-business/src/main/java/com/qmth/distributed/print/business/service/PrintCommonService.java

@@ -6,9 +6,11 @@ import com.qmth.distributed.print.business.bean.dto.PdfSignDto;
 import com.qmth.distributed.print.business.bean.excel.ExcelField;
 import com.qmth.distributed.print.business.entity.BasicTemplate;
 import com.qmth.distributed.print.business.entity.ExamDetail;
+import com.qmth.distributed.print.business.entity.ExamTask;
 import com.qmth.teachcloud.common.bean.vo.PrintPathVo;
 import com.qmth.teachcloud.common.entity.BasicAttachment;
 import com.qmth.teachcloud.common.entity.BasicCourse;
+import com.qmth.teachcloud.common.entity.BasicExam;
 import com.qmth.teachcloud.common.entity.SysUser;
 import com.qmth.teachcloud.common.enums.PageSizeEnum;
 import com.qmth.teachcloud.common.enums.TaskTypeEnum;
@@ -143,6 +145,8 @@ public interface PrintCommonService {
      */
     void checkExamDataAndCreatePdfTask(Long schoolId, Long examId, Long courseId, String paperNumber, SysUser user) throws IOException;
 
+    void autoRelateStudent(BasicExam basicExam, ExamTask examTask, SysUser sysUser);
+
     void checkDataMakeup(Long schoolId, ExamDetail examDetail, Long courseId, String paperNumber, SysUser user);
 
     /**

+ 74 - 0
distributed-print-business/src/main/java/com/qmth/distributed/print/business/service/impl/ExamSyncServiceImpl.java

@@ -0,0 +1,74 @@
+package com.qmth.distributed.print.business.service.impl;
+
+import com.qmth.distributed.print.business.entity.ExamDetail;
+import com.qmth.distributed.print.business.entity.ExamTask;
+import com.qmth.distributed.print.business.entity.TFFlowApprove;
+import com.qmth.distributed.print.business.enums.ExamStatusEnum;
+import com.qmth.distributed.print.business.service.*;
+import com.qmth.teachcloud.common.entity.BasicExam;
+import com.qmth.teachcloud.common.entity.SysUser;
+import com.qmth.teachcloud.common.enums.FlowStatusEnum;
+import com.qmth.teachcloud.mark.enums.LockType;
+import com.qmth.teachcloud.mark.lock.LockService;
+import org.apache.commons.collections4.CollectionUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.scheduling.annotation.Async;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.Resource;
+import java.util.List;
+
+@Service
+public class ExamSyncServiceImpl implements ExamSyncService {
+
+    private static final Logger logger = LoggerFactory.getLogger(ExamSyncServiceImpl.class);
+
+    @Resource
+    private ExamTaskService examTaskService;
+    @Resource
+    private TFFlowApproveService tfFlowApproveService;
+    @Resource
+    private ExamDetailService examDetailService;
+    @Resource
+    private PrintCommonService printCommonService;
+    @Resource
+    private LockService lockService;
+
+    @Async
+    @Override
+    public void relateStudentByExamTask(BasicExam basicExam, SysUser sysUser) {
+        try {
+            if (basicExam != null) {
+                List<ExamTask> examTaskList = examTaskService.listUnRelateStudentExamTask(basicExam.getId());
+                for (ExamTask examTask : examTaskList) {
+                    if (examTask.getReview()) {
+                        TFFlowApprove tfFlowApprove = tfFlowApproveService.findByFlowId(examTask.getFlowId());
+                        // 命题任务未入库
+                        if (tfFlowApprove == null || tfFlowApprove.getStatus() != FlowStatusEnum.FINISH) {
+                            logger.info("【关联考生】考试:{},试卷编号:{}未审核通过", basicExam.getName(), examTask.getPaperNumber());
+                            continue;
+                        }
+                    }
+                    // 不需要审核时,未提交
+                    else if (!ExamStatusEnum.SUBMIT.equals(examTask.getStatus())) {
+                        logger.info("【关联考生】考试:{},试卷编号:{}未提交", basicExam.getName(), examTask.getPaperNumber());
+                        continue;
+                    }
+
+                    // 有考场数据
+                    List<ExamDetail> examDetailList = examDetailService.listExamDetailByExamIdAndCourseIdAndPaperNumber(examTask.getExamId(), examTask.getCourseId(), examTask.getPaperNumber());
+                    if (CollectionUtils.isNotEmpty(examDetailList)) {
+                        logger.info("【关联考生】考试:{},试卷编号:{}已有考场", basicExam.getName(), examTask.getPaperNumber());
+                        continue;
+                    }
+                    printCommonService.autoRelateStudent(basicExam, examTask, sysUser);
+                }
+            }
+        } catch (Exception e) {
+            logger.error("reset marker error", e);
+        } finally {
+            lockService.unlock(LockType.RELATE_STUDENTS, basicExam.getId());
+        }
+    }
+}

+ 50 - 3
distributed-print-business/src/main/java/com/qmth/distributed/print/business/service/impl/ExamTaskServiceImpl.java

@@ -11,6 +11,7 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.google.common.collect.Lists;
 import com.google.gson.Gson;
 import com.qmth.boot.tools.excel.ExcelReader;
+import com.qmth.boot.tools.excel.ExcelWriter;
 import com.qmth.boot.tools.excel.enums.ExcelType;
 import com.qmth.distributed.print.business.bean.dto.*;
 import com.qmth.distributed.print.business.bean.dto.approvalForm.*;
@@ -30,7 +31,6 @@ import com.qmth.distributed.print.business.service.*;
 import com.qmth.distributed.print.business.templete.execute.AsyncPaperReviewPdfExportService;
 import com.qmth.distributed.print.business.util.CreatePdfUtil;
 import com.qmth.distributed.print.business.util.ExamTaskUtil;
-import com.qmth.distributed.print.business.util.HtmlToJpgUtil;
 import com.qmth.distributed.print.business.util.PdfUtil;
 import com.qmth.teachcloud.common.bean.dto.AssignTeacherDto;
 import com.qmth.teachcloud.common.bean.dto.BlurryUserDto;
@@ -49,7 +49,8 @@ import com.qmth.teachcloud.common.kit.TikuUtils;
 import com.qmth.teachcloud.common.service.*;
 import com.qmth.teachcloud.common.util.*;
 import com.qmth.teachcloud.common.util.excel.ExcelError;
-import jdk.nashorn.internal.runtime.regexp.joni.ast.StringNode;
+import com.qmth.teachcloud.mark.enums.LockType;
+import com.qmth.teachcloud.mark.lock.LockService;
 import org.activiti.engine.ActivitiObjectNotFoundException;
 import org.activiti.engine.TaskService;
 import org.activiti.engine.task.Task;
@@ -66,12 +67,14 @@ import org.springframework.util.LinkedMultiValueMap;
 import org.springframework.web.multipart.MultipartFile;
 
 import javax.annotation.Resource;
+import javax.servlet.ServletOutputStream;
 import javax.servlet.http.HttpServletResponse;
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.math.BigDecimal;
+import java.net.URLEncoder;
 import java.nio.charset.StandardCharsets;
 import java.util.*;
 import java.util.concurrent.atomic.AtomicInteger;
@@ -117,7 +120,7 @@ public class ExamTaskServiceImpl extends ServiceImpl<ExamTaskMapper, ExamTask> i
     @Resource
     private ExamDetailService examDetailService;
     @Resource
-    private HtmlToJpgUtil htmlToJpgUtil;
+    private ExamSyncService examSyncService;
     @Resource
     TBTaskService tbTaskService;
     @Resource
@@ -172,6 +175,8 @@ public class ExamTaskServiceImpl extends ServiceImpl<ExamTaskMapper, ExamTask> i
     private FileUploadService fileUploadService;
     @Resource
     private TikuUtils tikuUtils;
+    @Resource
+    private LockService lockService;
 
     @Override
     public IPage<ExamTaskDto> list(Long semesterId, Long examId, Boolean enable, String status, Long openCollegeId, Long courseId, String paperNumber, Long startTime, Long endTime, String userName, Integer pageNumber, Integer pageSize) {
@@ -2030,6 +2035,7 @@ public class ExamTaskServiceImpl extends ServiceImpl<ExamTaskMapper, ExamTask> i
     public List<ExamDetail> matchBasicExamStudent(BasicExam basicExam, ExamTask examTask, SysUser sysUser) {
         List<BasicExamStudent> basicExamStudentList = basicExamStudentService.listByExamIdAndCourseIdAndPaperNumber(examTask.getExamId(), examTask.getCourseId(), examTask.getPaperNumber());
         if (CollectionUtils.isEmpty(basicExamStudentList)) {
+            logger.info("考试:{},试卷编号:{}未查询到考生", basicExam.getName(), examTask.getPaperNumber());
             return null;
         }
         // 创建印刷计划
@@ -2394,6 +2400,47 @@ public class ExamTaskServiceImpl extends ServiceImpl<ExamTaskMapper, ExamTask> i
         }
     }
 
+    @Override
+    public boolean relateStudentByExamId(Long examId) {
+        BasicExam basicExam = basicExamService.getById(examId);
+        SysUser sysUser = (SysUser) ServletUtil.getRequestUser();
+
+        if (basicExam != null) {
+            if (lockService.trylock(LockType.RELATE_STUDENTS, basicExam.getId())) {
+                examSyncService.relateStudentByExamTask(basicExam, sysUser);
+                return true;
+            } else {
+                throw ExceptionResultEnum.ERROR.exception("关联考生任务正在进行中,请稍后再试");
+            }
+        }
+        return true;
+    }
+
+    @Override
+    public List<ExamTask> listUnRelateStudentExamTask(Long examId) {
+        return this.baseMapper.listUnRelateStudentExamTask(examId);
+    }
+
+    @Override
+    public void export(Long semesterId, Long examId, Long openCollegeId, Long courseId, String paperNumber, Long startTime, Long endTime, HttpServletResponse response) {
+        List<ExamTaskDetailDto> dtoList = this.listTaskPaper(semesterId, examId, openCollegeId, courseId, paperNumber, startTime, endTime);
+        try {
+            log.debug("导出Excel开始...");
+            response.setHeader("Content-Disposition",
+                    "inline;filename=" + URLEncoder.encode("成绩导出", SystemConstant.CHARSET_NAME) + ".xlsx");
+            response.setContentType("application/vnd.ms-excel");
+            ServletOutputStream outputStream = response.getOutputStream();
+            ExcelWriter writer = ExcelWriter.create(ExcelType.XLSX);
+            writer.writeObjects("试卷清单", null, ExamTaskDetailDto.class, dtoList.listIterator());
+            writer.output(response.getOutputStream());
+            outputStream.flush();
+            outputStream.close();
+            log.debug("导出Excel结束");
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+    }
+
     private ExamTaskPaperData saveTikuPaperData(Long examId, Long paperId, String uuid, File zipFile) {
         SysUser sysUser = (SysUser) ServletUtil.getRequestUser();
         String zipDestPath = null;

+ 17 - 12
distributed-print-business/src/main/java/com/qmth/distributed/print/business/service/impl/PrintCommonServiceImpl.java

@@ -895,23 +895,28 @@ public class PrintCommonServiceImpl implements PrintCommonService {
                 // 指派命题老师方式,自动关联考生管理数据
                 if (ExamTaskSourceEnum.ASSIGN.equals(examTask.getSource())) {
                     // 自动关联考生表中数据,并生成考场信息
-                    List<ExamDetail> examDetailList1 = examTaskService.matchBasicExamStudent(basicExam, examTask, user);
-                    if (CollectionUtils.isNotEmpty(examDetailList1)) {
-                        for (ExamDetail examDetail : examDetailList1) {
-                            // 更新考场状态为初始新建状态
-                            examDetailService.updateStatusById(examDetail.getId(), ExamDetailStatusEnum.NEW);
-
-                            // 所有考场都撤回,印刷任务状态改为就绪
-                            examPrintPlanService.updateStatusById(examDetail.getPrintPlanId(), PrintPlanStatusEnum.READY);
-                            TbTaskDetailResult tbTaskDetailResult = examDetailCourseService.getByExamDetailId(examDetail.getId());
-                            tbTaskPdfService.saveTask(tbTaskDetailResult, examDetail.getPrintPlanId(), user, examDetail.getId());
-                        }
-                    }
+                    this.autoRelateStudent(basicExam, examTask, user);
                 }
             }
         }
     }
 
+    @Override
+    public void autoRelateStudent(BasicExam basicExam, ExamTask examTask, SysUser sysUser) {
+        List<ExamDetail> examDetailList1 = examTaskService.matchBasicExamStudent(basicExam, examTask, sysUser);
+        if (CollectionUtils.isNotEmpty(examDetailList1)) {
+            for (ExamDetail examDetail : examDetailList1) {
+                // 更新考场状态为初始新建状态
+                examDetailService.updateStatusById(examDetail.getId(), ExamDetailStatusEnum.NEW);
+
+                // 所有考场都撤回,印刷任务状态改为就绪
+                examPrintPlanService.updateStatusById(examDetail.getPrintPlanId(), PrintPlanStatusEnum.READY);
+                TbTaskDetailResult tbTaskDetailResult = examDetailCourseService.getByExamDetailId(examDetail.getId());
+                tbTaskPdfService.saveTask(tbTaskDetailResult, examDetail.getPrintPlanId(), sysUser, examDetail.getId());
+            }
+        }
+    }
+
     /**
      * 校验是否可以提交
      *

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

@@ -1539,4 +1539,22 @@
                     and ms.scan_status <![CDATA[ <> ]]> 'UNEXIST'
                 </where>) t
     </select>
+    <select id="listUnRelateStudentExamTask" resultType="com.qmth.distributed.print.business.entity.ExamTask">
+        SELECT
+            *
+        FROM
+            exam_task et
+        WHERE
+            et.exam_id = #{examId}
+          AND NOT EXISTS( SELECT
+                              1
+                          FROM
+                              exam_detail ed
+                                  LEFT JOIN
+                              exam_detail_course edc ON ed.id = edc.exam_detail_id
+                          WHERE
+                              ed.exam_id = #{examId}
+                            AND et.course_id = edc.course_id
+                            AND et.paper_number = edc.paper_number)
+    </select>
 </mapper>

+ 4 - 0
distributed-print/install/mysql/init/teachcloud_db.sql

@@ -3268,6 +3268,10 @@ INSERT INTO `sys_privilege` (`id`, `name`, `url`, `type`, `parent_id`, `sequence
 INSERT INTO `sys_privilege` (`id`, `name`, `url`, `type`, `parent_id`, `sequence`, `property`, `related`, `enable`, `default_auth`, `front_display`) VALUES (241, '印刷-单文件打印', '/api/admin/client/print/single', 'URL', 199, 17, 'AUTH', NULL, 1, 1, 1);
 INSERT INTO `sys_privilege` (`id`, `name`, `url`, `type`, `parent_id`, `sequence`, `property`, `related`, `enable`, `default_auth`, `front_display`) VALUES (242, '查询条件-课程', '/api/admin/client/course/list', 'URL', 199, 18, 'AUTH', NULL, 1, 1, 1);
 INSERT INTO `sys_privilege` (`id`, `name`, `url`, `type`, `parent_id`, `sequence`, `property`, `related`, `enable`, `default_auth`, `front_display`) VALUES (243, '导入', 'Import', 'BUTTON', 5, 3, 'AUTH', '81', 1, 0, 1);
+INSERT INTO `sys_privilege` (`id`, `name`, `url`, `type`, `parent_id`, `sequence`, `property`, `related`, `enable`, `default_auth`, `front_display`) VALUES (244, '关联考生', 'AutoRelateStudent', 'BUTTON', 42, 7, 'AUTH', '245', 1, 0, 1);
+INSERT INTO `sys_privilege` (`id`, `name`, `url`, `type`, `parent_id`, `sequence`, `property`, `related`, `enable`, `default_auth`, `front_display`) VALUES (245, '关联考生', '/api/admin/exam/task/relate_students', 'URL', 42, 10, 'AUTH', NULL, 1, 1, 1);
+INSERT INTO `sys_privilege` (`id`, `name`, `url`, `type`, `parent_id`, `sequence`, `property`, `related`, `enable`, `default_auth`, `front_display`) VALUES (246, '下载试卷清单', 'ExportPaperList', 'BUTTON', 42, 8, 'AUTH', '247', 1, 0, 1);
+INSERT INTO `sys_privilege` (`id`, `name`, `url`, `type`, `parent_id`, `sequence`, `property`, `related`, `enable`, `default_auth`, `front_display`) VALUES (247, '下载试卷清单', '/api/admin/exam/task/export_paper_list', 'URL', 42, 11, 'AUTH', NULL, 1, 1, 1);
 INSERT INTO `sys_privilege` (`id`, `name`, `url`, `type`, `parent_id`, `sequence`, `property`, `related`, `enable`, `default_auth`, `front_display`) VALUES (249, '查询', 'Select', 'BUTTON', 11, 1, 'AUTH', '123', 1, 0, 1);
 INSERT INTO `sys_privilege` (`id`, `name`, `url`, `type`, `parent_id`, `sequence`, `property`, `related`, `enable`, `default_auth`, `front_display`) VALUES (250, '新增', 'Add', 'BUTTON', 11, 2, 'AUTH', '124', 1, 0, 1);
 INSERT INTO `sys_privilege` (`id`, `name`, `url`, `type`, `parent_id`, `sequence`, `property`, `related`, `enable`, `default_auth`, `front_display`) VALUES (251, '预览', 'Preview', 'LINK', 11, 1, 'AUTH', '192', 1, 0, 1);

+ 5 - 0
distributed-print/install/mysql/upgrade/3.4.5.sql

@@ -129,3 +129,8 @@ INSERT INTO `sys_privilege` (`id`, `name`, `url`, `type`, `parent_id`, `sequence
 UPDATE `sys_privilege` SET `name` = '成绩下载(广药)' WHERE (`id` = '545');
 UPDATE `sys_privilege` SET `name` = '成绩下载(广药)' WHERE (`id` = '546');
 ALTER TABLE `mark_ocr_student_question` ADD INDEX `idx_1` (`exam_id` ASC, `paper_number` ASC, `student_id` ASC, `question_id` ASC);
+
+INSERT INTO `sys_privilege` (`id`, `name`, `url`, `type`, `parent_id`, `sequence`, `property`, `related`, `enable`, `default_auth`, `front_display`) VALUES ('244', '关联考生', 'AutoRelateStudent', 'BUTTON', '42', '7', 'AUTH', '245', '1', '0', '1');
+INSERT INTO `sys_privilege` (`id`, `name`, `url`, `type`, `parent_id`, `sequence`, `property`, `enable`, `default_auth`, `front_display`) VALUES ('245', '关联考生', '/api/admin/exam/task/relate_students', 'URL', '42', '10', 'AUTH', '1', '1', '1');
+INSERT INTO `sys_privilege` (`id`, `name`, `url`, `type`, `parent_id`, `sequence`, `property`, `related`, `enable`, `default_auth`, `front_display`) VALUES ('246', '下载试卷清单', 'ExportPaperList', 'BUTTON', '42', '8', 'AUTH', '247', '1', '0', '1');
+INSERT INTO `sys_privilege` (`id`, `name`, `url`, `type`, `parent_id`, `sequence`, `property`, `enable`, `default_auth`, `front_display`) VALUES ('247', '下载试卷清单', '/api/admin/exam/task/export_paper_list', 'URL', '42', '11', 'AUTH', '1', '1', '1');

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

@@ -4,7 +4,6 @@ import com.qmth.boot.api.constant.ApiConstant;
 import com.qmth.distributed.print.business.bean.result.EditResult;
 import com.qmth.distributed.print.business.entity.ExamTask;
 import com.qmth.distributed.print.business.entity.ExamTaskDetail;
-import com.qmth.distributed.print.business.enums.MakeMethodEnum;
 import com.qmth.distributed.print.business.service.*;
 import com.qmth.teachcloud.common.annotation.OperationLogDetail;
 import com.qmth.teachcloud.common.contant.SystemConstant;
@@ -179,5 +178,26 @@ public class ExamTaskQueryController {
         }
         return ResultUtil.ok(isSuccess);
     }
+
+    @ApiOperation(value = "卷库查询-关联考生")
+    @RequestMapping(value = "/relate_students", method = RequestMethod.POST)
+    @OperationLogDetail(operationType = OperationTypeEnum.UPDATE, detail = "关联考生操作,命题任务ID:{{examTaskDetail.examTaskId}}")
+    public Result relateStudents(@ApiParam(value = "考试ID") @RequestParam(value = "examId", required = false) Long examId) {
+        return ResultUtil.ok(examTaskService.relateStudentByExamId(examId));
+    }
+
+    @ApiOperation(value = "下载试卷清单")
+    @RequestMapping(value = "/export_paper_list", method = RequestMethod.POST)
+    public Result export(@ApiParam(value = "学期ID") @RequestParam(value = "semesterId", required = false) Long semesterId,
+                         @ApiParam(value = "考试ID") @RequestParam(value = "examId", required = false) Long examId,
+                         @ApiParam(value = "开课学院id") @RequestParam(value = "openCollegeId", required = false) Long openCollegeId,
+                         @ApiParam(value = "课程ID") @RequestParam(value = "courseId", required = false) Long courseId,
+                         @ApiParam(value = "试卷编号") @RequestParam(value = "paperNumber", required = false) String paperNumber,
+                         @ApiParam(value = "入库时间(开始)") @RequestParam(value = "startTime", required = false) Long startTime,
+                         @ApiParam(value = "入库时间(结束)") @RequestParam(value = "endTime", required = false) Long endTime,
+                         HttpServletResponse response) throws IOException {
+        examTaskService.export(semesterId, examId, openCollegeId, courseId, paperNumber, startTime, endTime, response);
+        return ResultUtil.ok();
+    }
 }
 

+ 5 - 0
distributed-print/src/main/resources/upgrade/3.4.5-upgrade.sql

@@ -129,3 +129,8 @@ INSERT INTO `sys_privilege` (`id`, `name`, `url`, `type`, `parent_id`, `sequence
 UPDATE `sys_privilege` SET `name` = '成绩下载(广药)' WHERE (`id` = '545');
 UPDATE `sys_privilege` SET `name` = '成绩下载(广药)' WHERE (`id` = '546');
 ALTER TABLE `mark_ocr_student_question` ADD INDEX `idx_1` (`exam_id` ASC, `paper_number` ASC, `student_id` ASC, `question_id` ASC);
+
+INSERT INTO `sys_privilege` (`id`, `name`, `url`, `type`, `parent_id`, `sequence`, `property`, `related`, `enable`, `default_auth`, `front_display`) VALUES ('244', '关联考生', 'AutoRelateStudent', 'BUTTON', '42', '7', 'AUTH', '245', '1', '0', '1');
+INSERT INTO `sys_privilege` (`id`, `name`, `url`, `type`, `parent_id`, `sequence`, `property`, `enable`, `default_auth`, `front_display`) VALUES ('245', '关联考生', '/api/admin/exam/task/relate_students', 'URL', '42', '10', 'AUTH', '1', '1', '1');
+INSERT INTO `sys_privilege` (`id`, `name`, `url`, `type`, `parent_id`, `sequence`, `property`, `related`, `enable`, `default_auth`, `front_display`) VALUES ('246', '下载试卷清单', 'ExportPaperList', 'BUTTON', '42', '8', 'AUTH', '247', '1', '0', '1');
+INSERT INTO `sys_privilege` (`id`, `name`, `url`, `type`, `parent_id`, `sequence`, `property`, `enable`, `default_auth`, `front_display`) VALUES ('247', '下载试卷清单', '/api/admin/exam/task/export_paper_list', 'URL', '42', '11', 'AUTH', '1', '1', '1');

+ 2 - 1
teachcloud-mark/src/main/java/com/qmth/teachcloud/mark/enums/LockType.java

@@ -25,7 +25,8 @@ public enum LockType {
     CUSTOM_MODEL_FOUR_CARD_SAVE("custom_model_four_card_save"),
 	AI_TASK_RESET("ai_task_reset"),
 	OCR_MARK("ocr_mark"),
-	AI_MARK("ai_mark"), ;
+	AI_MARK("ai_mark"),
+	RELATE_STUDENTS("relate_students");
 
 	private String name;
 

+ 3 - 1
teachcloud-mark/src/main/java/com/qmth/teachcloud/mark/service/impl/MarkQuestionServiceImpl.java

@@ -56,6 +56,8 @@ import org.springframework.web.multipart.MultipartFile;
 
 import javax.annotation.Resource;
 import javax.servlet.http.HttpServletResponse;
+import java.math.BigDecimal;
+import java.math.RoundingMode;
 import java.util.*;
 import java.util.stream.Collectors;
 import java.util.stream.Stream;
@@ -953,7 +955,7 @@ public class MarkQuestionServiceImpl extends ServiceImpl<MarkQuestionMapper, Mar
             lambda.set(MarkQuestion::getDoubleRate, 100);
             lambda.set(markQuestion.getScorePolicy() == null, MarkQuestion::getScorePolicy, ScorePolicy.AVG);
             double mul = BigDecimalUtils.mul(markQuestion.getTotalScore(), 0.2d);
-            lambda.set(MarkQuestion::getArbitrateThreshold, mul < 1 ? markQuestion.getTotalScore() : mul);
+            lambda.set(markQuestion.getArbitrateThreshold() == null, MarkQuestion::getArbitrateThreshold, mul < 1 ? markQuestion.getTotalScore() : new BigDecimal(mul).setScale(0, RoundingMode.FLOOR));
         } else {
             // 删除AI评卷参数,直接默认切换为单评
             lambda.set(MarkQuestion::getDoubleRate, 0);