Przeglądaj źródła

3.4.4 update-20250318,bug修复

xiaofei 3 miesięcy temu
rodzic
commit
91e9f45dcb
24 zmienionych plików z 302 dodań i 130 usunięć
  1. 5 3
      distributed-print-business/src/main/java/com/qmth/distributed/print/business/bean/dto/initMarkData/ExamDetailCourseInitMarkDto.java
  2. 2 2
      distributed-print-business/src/main/java/com/qmth/distributed/print/business/mapper/ExamCardModelFourMapper.java
  3. 6 2
      distributed-print-business/src/main/java/com/qmth/distributed/print/business/service/ExamCardModelFourService.java
  4. 51 12
      distributed-print-business/src/main/java/com/qmth/distributed/print/business/service/impl/ExamCardModelFourServiceImpl.java
  5. 37 14
      distributed-print-business/src/main/java/com/qmth/distributed/print/business/service/impl/ExamCardServiceImpl.java
  6. 49 53
      distributed-print-business/src/main/java/com/qmth/distributed/print/business/service/impl/PrintFinishServiceImpl.java
  7. 4 13
      distributed-print-business/src/main/resources/mapper/ConditionMapper.xml
  8. 2 2
      distributed-print-business/src/main/resources/mapper/ExamCardModelFourMapper.xml
  9. 6 1
      distributed-print/install/mysql/upgrade/3.4.4.sql
  10. 11 2
      distributed-print/src/main/java/com/qmth/distributed/print/api/ExamCardModelFourController.java
  11. 18 18
      distributed-print/src/main/java/com/qmth/distributed/print/api/mark/MarkQuestionController.java
  12. 6 1
      pom.xml
  13. 62 0
      teachcloud-common/src/main/java/com/qmth/teachcloud/common/util/PDFConverter.java
  14. 2 1
      teachcloud-mark/src/main/java/com/qmth/teachcloud/mark/bean/vo/parseCard/pic/SubPictureConfig.java
  15. 0 2
      teachcloud-mark/src/main/java/com/qmth/teachcloud/mark/dto/mark/setting/MarkUserClassDto.java
  16. 2 0
      teachcloud-mark/src/main/java/com/qmth/teachcloud/mark/mapper/MarkUserQuestionMapper.java
  17. 2 1
      teachcloud-mark/src/main/java/com/qmth/teachcloud/mark/service/MarkQuestionAnswerService.java
  18. 3 0
      teachcloud-mark/src/main/java/com/qmth/teachcloud/mark/service/MarkUserQuestionService.java
  19. 1 0
      teachcloud-mark/src/main/java/com/qmth/teachcloud/mark/service/ScanAnswerCardService.java
  20. 2 0
      teachcloud-mark/src/main/java/com/qmth/teachcloud/mark/service/impl/MarkQuestionAnswerServiceImpl.java
  21. 2 2
      teachcloud-mark/src/main/java/com/qmth/teachcloud/mark/service/impl/MarkQuestionServiceImpl.java
  22. 2 1
      teachcloud-mark/src/main/java/com/qmth/teachcloud/mark/service/impl/MarkUserClassServiceImpl.java
  23. 7 0
      teachcloud-mark/src/main/java/com/qmth/teachcloud/mark/service/impl/MarkUserQuestionServiceImpl.java
  24. 20 0
      teachcloud-mark/src/main/resources/mapper/MarkUserQuestionMapper.xml

+ 5 - 3
distributed-print-business/src/main/java/com/qmth/distributed/print/business/bean/dto/initMarkData/ExamDetailCourseInitMarkDto.java

@@ -2,6 +2,8 @@ package com.qmth.distributed.print.business.bean.dto.initMarkData;
 
 import com.qmth.distributed.print.business.entity.ExamCardModelFour;
 import com.qmth.teachcloud.common.contant.SystemConstant;
+import com.qmth.teachcloud.mark.entity.MarkPaper;
+import org.yaml.snakeyaml.error.Mark;
 
 /**
  * 课程同步阅卷数据dto
@@ -24,12 +26,12 @@ public class ExamDetailCourseInitMarkDto {
 
     }
 
-    public ExamDetailCourseInitMarkDto(ExamCardModelFour examCardModelFour, String paperNumber, Long userId) {
+    public ExamDetailCourseInitMarkDto(ExamCardModelFour examCardModelFour, MarkPaper markPaper, Long userId) {
         this.schoolId = examCardModelFour.getSchoolId();
         this.examId = examCardModelFour.getExamId();
         this.courseId = examCardModelFour.getCourseId();
-        this.paperNumber = paperNumber;
-        this.coursePaperId = examCardModelFour.getId().toString();
+        this.paperNumber = markPaper.getPaperNumber();
+        this.coursePaperId = markPaper.getCoursePaperId();
         this.serialNumber = 1;
         this.paperType = SystemConstant.DEFAULT_PAPER_TYPE_A;
         this.openAb = false;

+ 2 - 2
distributed-print-business/src/main/java/com/qmth/distributed/print/business/mapper/ExamCardModelFourMapper.java

@@ -26,13 +26,13 @@ public interface ExamCardModelFourMapper extends BaseMapper<ExamCardModelFour> {
      * @param semesterId
      * @param examId
      * @param courseId
-     * @param collegeId
+     * @param openCollegeId
      * @param title
      * @param paperNumber
      * @param dpr
      * @return
      */
-    IPage<ExamCardModelFour> listPage(IPage<Map> iPage, @Param("schoolId") Long schoolId, @Param("semesterId") Long semesterId, @Param("examId") Long examId, @Param("courseId") Long courseId, @Param("collegeId") Long collegeId, @Param("title") String title, @Param("paperNumber") String paperNumber, @Param("dpr") DataPermissionRule dpr);
+    IPage<ExamCardModelFour> listPage(IPage<Map> iPage, @Param("schoolId") Long schoolId, @Param("semesterId") Long semesterId, @Param("examId") Long examId, @Param("courseId") Long courseId, @Param("openCollegeId") Long openCollegeId, @Param("title") String title, @Param("paperNumber") String paperNumber, @Param("dpr") DataPermissionRule dpr);
 
     /**
      * 根据id countCardNumber

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

@@ -43,11 +43,11 @@ public interface ExamCardModelFourService extends IService<ExamCardModelFour> {
      * @param examId
      * @param courseId
      * @param paperNumber
-     * @param collegeId
+     * @param openCollegeId
      * @param title
      * @return
      */
-    IPage<ExamCardModelFour> listPage(IPage<Map> iPage, Long semesterId, Long examId, Long courseId, String paperNumber, Long collegeId, String title);
+    IPage<ExamCardModelFour> listPage(IPage<Map> iPage, Long semesterId, Long examId, Long courseId, String paperNumber, Long openCollegeId, String title);
 
     /**
      * 根据id获取模式4题卡
@@ -85,4 +85,8 @@ public interface ExamCardModelFourService extends IService<ExamCardModelFour> {
      * @param ids
      */
     void batchDownloadCard(List<Long> ids);
+
+    ExamCardModelFour getByExamIdAndCourseId(Long examId, Long courseId);
+
+    void validCourse(GenericExamCardModelFourParams params);
 }

+ 51 - 12
distributed-print-business/src/main/java/com/qmth/distributed/print/business/service/impl/ExamCardModelFourServiceImpl.java

@@ -37,8 +37,7 @@ import com.qmth.teachcloud.mark.entity.MarkPaper;
 import com.qmth.teachcloud.mark.entity.ScanAnswerCard;
 import com.qmth.teachcloud.mark.enums.CardSource;
 import com.qmth.teachcloud.mark.enums.LockType;
-import com.qmth.teachcloud.mark.service.MarkPaperService;
-import com.qmth.teachcloud.mark.service.ScanAnswerCardService;
+import com.qmth.teachcloud.mark.service.*;
 import org.apache.commons.codec.digest.DigestUtils;
 import org.apache.commons.collections4.CollectionUtils;
 import org.apache.commons.lang3.StringUtils;
@@ -100,17 +99,23 @@ public class ExamCardModelFourServiceImpl extends ServiceImpl<ExamCardModelFourM
 
     @Resource
     ScanAnswerCardService scanAnswerCardService;
+    @Resource
+    ScanAnswerCardQuestionService scanAnswerCardQuestionService;
+
+    @Resource
+    MarkQuestionService markQuestionService;
+    @Resource
+    MarkQuestionAnswerService markQuestionAnswerService;
 
     /**
      * 新增/修改模式4题卡
      *
      * @param params
      * @return
-     * @throws Exception
      */
     @Override
     @Transactional
-    public Map<String, String> saveGeneric(GenericExamCardModelFourParams params) throws Exception {
+    public Map<String, String> saveGeneric(GenericExamCardModelFourParams params) {
         Objects.requireNonNull(params, "题卡信息不能为空");
         Objects.requireNonNull(params.getExamId(), "考试id不能为空");
         Objects.requireNonNull(params.getCourseId(), "课程id不能为空");
@@ -147,12 +152,12 @@ public class ExamCardModelFourServiceImpl extends ServiceImpl<ExamCardModelFourM
                 if (Objects.nonNull(checkTitleExamCardModelFourDb) && params.getId().longValue() != examCardModelFour.getId().longValue()) {
                     throw ExceptionResultEnum.ERROR.exception("题卡名称重复");
                 }
+                int count = this.baseMapper.countByCardNumber(examCardModelFour.getId());
+                if (count > 0) {
+                    throw ExceptionResultEnum.ERROR.exception("题卡已扫描不能修改");
+                }
                 examCardModelFour.updateInfo(sysUser.getId());
             }
-            ScanAnswerCard scanAnswerCardDb = scanAnswerCardService.findByExamAndCardIdAndCardSource(examCardModelFour.getExamId(), examCardModelFour.getId(), CardSource.WEB);
-            if (Objects.nonNull(scanAnswerCardDb)) {
-                throw ExceptionResultEnum.ERROR.exception("题卡已扫描不能重复修改");
-            }
 
             examCardModelFour.updateInformation(params);
             try {
@@ -192,7 +197,7 @@ public class ExamCardModelFourServiceImpl extends ServiceImpl<ExamCardModelFourM
                 if (markPaperList.size() > 1) {
                     throw ExceptionResultEnum.ERROR.exception("找到多条试卷信息");
                 }
-                ExamDetailCourseInitMarkDto dto = new ExamDetailCourseInitMarkDto(examCardModelFour, markPaperList.get(0).getPaperNumber(), sysUser.getId());
+                ExamDetailCourseInitMarkDto dto = new ExamDetailCourseInitMarkDto(examCardModelFour, markPaperList.get(0), sysUser.getId());
                 // 解析卡格式中试卷结构并保存
                 printFinishService.insertMarkQuestion(dto.getExamId(), dto.getCourseId(), dto.getPaperNumber(), examCardModelFour.getContent(), null);
                 // 生成并保存卡格式文件(后缀为.json)
@@ -258,16 +263,16 @@ public class ExamCardModelFourServiceImpl extends ServiceImpl<ExamCardModelFourM
      * @param examId
      * @param courseId
      * @param paperNumber
-     * @param collegeId
+     * @param openCollegeId
      * @param title
      * @return
      */
     @Override
-    public IPage<ExamCardModelFour> listPage(IPage<Map> iPage, Long semesterId, Long examId, Long courseId, String paperNumber, Long collegeId, String title) {
+    public IPage<ExamCardModelFour> listPage(IPage<Map> iPage, Long semesterId, Long examId, Long courseId, String paperNumber, Long openCollegeId, String title) {
         Long schoolId = Long.valueOf(ServletUtil.getRequestHeaderSchoolId().toString());
         SysUser requestUser = (SysUser) ServletUtil.getRequestUser();
         DataPermissionRule dpr = basicRoleDataPermissionService.findDataPermission(schoolId, requestUser.getId(), ServletUtil.getRequest().getServletPath());
-        IPage<ExamCardModelFour> cardPageDtoIPage = this.baseMapper.listPage(iPage, schoolId, semesterId, examId, courseId, collegeId, title, paperNumber, dpr);
+        IPage<ExamCardModelFour> cardPageDtoIPage = this.baseMapper.listPage(iPage, schoolId, semesterId, examId, courseId, openCollegeId, title, paperNumber, dpr);
         for (ExamCardModelFour record : cardPageDtoIPage.getRecords()) {
             if (StringUtils.isNotBlank(record.getJpgAttachment())) {
                 List<JSONObject> mapList = JSON.parseArray(record.getJpgAttachment(), JSONObject.class);
@@ -312,6 +317,18 @@ public class ExamCardModelFourServiceImpl extends ServiceImpl<ExamCardModelFourM
         if (count > 0) {
             throw ExceptionResultEnum.ERROR.exception("已扫描的题卡不允许删除");
         }
+        ExamCardModelFour examCardModelFour = this.getById(id);
+        List<MarkPaper> markPaperList = markPaperService.listByExamIdAndCourseIdForModel4(examCardModelFour.getExamId(), examCardModelFour.getCourseId());
+        if (CollectionUtils.isNotEmpty(markPaperList)) {
+            MarkPaper markPaper = markPaperList.get(0);
+            markQuestionService.deleteByExamIdAndPaperNumber(markPaper.getExamId(), markPaper.getPaperNumber());
+            markQuestionAnswerService.deleteByExamIdAndPaperNumber(markPaper.getExamId(), markPaper.getPaperNumber());
+            ScanAnswerCard scanAnswerCard = scanAnswerCardService.findByExamAndCardIdAndCardSource(markPaper.getExamId(), id, CardSource.WEB);
+            if (scanAnswerCard != null) {
+                scanAnswerCardService.removeById(scanAnswerCard.getId());
+                scanAnswerCardQuestionService.deleteByExamIdAndPaperNumberAndCardNumber(markPaper.getExamId(), markPaper.getPaperNumber(), scanAnswerCard.getNumber());
+            }
+        }
         return this.removeById(id);
     }
 
@@ -397,6 +414,28 @@ public class ExamCardModelFourServiceImpl extends ServiceImpl<ExamCardModelFourM
         }
     }
 
+    @Override
+    public ExamCardModelFour getByExamIdAndCourseId(Long examId, Long courseId) {
+        QueryWrapper<ExamCardModelFour> queryWrapper = new QueryWrapper<>();
+        queryWrapper.lambda().eq(ExamCardModelFour::getExamId, examId)
+                .eq(ExamCardModelFour::getCourseId, courseId);
+        return this.getOne(queryWrapper);
+    }
+
+    @Override
+    public void validCourse(GenericExamCardModelFourParams params) {
+        ExamCardModelFour examCardModelFour = this.getByExamIdAndCourseId(params.getExamId(), params.getCourseId());
+        if (params.getId() == null) {
+            if (examCardModelFour != null) {
+                throw ExceptionResultEnum.ERROR.exception("每个课程只能创建一个题卡");
+            }
+        } else {
+            if (examCardModelFour != null && !examCardModelFour.getId().equals(params.getId())) {
+                throw ExceptionResultEnum.ERROR.exception("每个课程只能创建一个题卡");
+            }
+        }
+    }
+
     /**
      * 创建zip
      *

+ 37 - 14
distributed-print-business/src/main/java/com/qmth/distributed/print/business/service/impl/ExamCardServiceImpl.java

@@ -10,10 +10,7 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.qmth.boot.api.exception.ApiException;
 import com.qmth.boot.core.concurrent.service.ConcurrentService;
 import com.qmth.distributed.print.business.bean.params.GenericExamCardParams;
-import com.qmth.distributed.print.business.entity.BasicCardRule;
-import com.qmth.distributed.print.business.entity.BasicExamRule;
-import com.qmth.distributed.print.business.entity.ExamCard;
-import com.qmth.distributed.print.business.entity.ExamTaskDetail;
+import com.qmth.distributed.print.business.entity.*;
 import com.qmth.distributed.print.business.enums.CardTypeEnum;
 import com.qmth.distributed.print.business.enums.ExamCardStatusEnum;
 import com.qmth.distributed.print.business.enums.MakeMethodEnum;
@@ -29,20 +26,16 @@ import com.qmth.teachcloud.common.bean.marking.ConvertJpgStorage;
 import com.qmth.teachcloud.common.bean.vo.FilePathVo;
 import com.qmth.teachcloud.common.bean.vo.PaperInfoVo;
 import com.qmth.teachcloud.common.contant.SystemConstant;
-import com.qmth.teachcloud.common.entity.BasicAttachment;
-import com.qmth.teachcloud.common.entity.BasicCourse;
-import com.qmth.teachcloud.common.entity.BasicPrintConfig;
-import com.qmth.teachcloud.common.entity.SysUser;
-import com.qmth.teachcloud.common.enums.CardCreateMethodEnum;
-import com.qmth.teachcloud.common.enums.ExceptionResultEnum;
-import com.qmth.teachcloud.common.enums.PageSizeEnum;
-import com.qmth.teachcloud.common.enums.UploadFileEnum;
+import com.qmth.teachcloud.common.entity.*;
+import com.qmth.teachcloud.common.enums.*;
 import com.qmth.teachcloud.common.service.*;
 import com.qmth.teachcloud.common.util.Base64Util;
 import com.qmth.teachcloud.common.util.FileUtil;
 import com.qmth.teachcloud.common.util.HtmlToPdfUtil;
 import com.qmth.teachcloud.common.util.ServletUtil;
+import com.qmth.teachcloud.mark.entity.MarkPaper;
 import com.qmth.teachcloud.mark.enums.LockType;
+import com.qmth.teachcloud.mark.service.MarkPaperService;
 import com.qmth.teachcloud.mark.service.ScanAnswerCardService;
 import org.apache.commons.codec.digest.DigestUtils;
 import org.apache.commons.collections4.CollectionUtils;
@@ -98,6 +91,12 @@ public class ExamCardServiceImpl extends ServiceImpl<ExamCardMapper, ExamCard> i
     private BasicPrintConfigService basicPrintConfigService;
     @Resource
     private ConcurrentService concurrentService;
+    @Resource
+    private BasicExamService basicExamService;
+    @Resource
+    private MarkPaperService markPaperService;
+    @Resource
+    ExamCardModelFourService examCardModelFourService;
 
     @Transactional
     @Override
@@ -507,11 +506,35 @@ public class ExamCardServiceImpl extends ServiceImpl<ExamCardMapper, ExamCard> i
     @Override
     public List<CardJpgResult> listCardImage(Long examId, String paperNumber, Integer serialNumber) {
         ExamTaskDetail examTaskDetail = examTaskDetailService.getByExamIdAndPaperNumberAndSerialNumber(examId, paperNumber, serialNumber);
+        List<CardJpgResult> cardJpgResultList = new ArrayList<>();
+
         if (examTaskDetail == null) {
-            return scanAnswerCardService.listPageImage(examId, paperNumber);
+            BasicExam basicExam = basicExamService.getById(examId);
+            if (ExamModelEnum.MODEL4.equals(basicExam.getExamModel())) {
+                MarkPaper markPaper = markPaperService.getByExamIdAndPaperNumber(examId, paperNumber);
+                if (markPaper != null) {
+                    ExamCardModelFour examCardModelFour = examCardModelFourService.getByExamIdAndCourseId(examId, markPaper.getCourseId());
+                    if (examCardModelFour != null) {
+                        List<ConvertJpgStorage> convertJpgStorageList = JSONObject.parseArray(examCardModelFour.getJpgAttachment(), ConvertJpgStorage.class);
+                        cardJpgResultList.addAll(convertJpgStorageList.stream().flatMap(e -> {
+                            BasicAttachment basicAttachment = basicAttachmentService.getById(e.getAttachmentId());
+
+                            CardJpgResult cardJpgResult = new CardJpgResult();
+                            cardJpgResult.setName(basicAttachment.getName());
+                            cardJpgResult.setIndex(e.getIndex());
+                            cardJpgResult.setPath(teachcloudCommonService.filePreview(basicAttachment.getPath()));
+                            return Stream.of(cardJpgResult);
+                        }).collect(Collectors.toList()));
+                    }
+                }
+            }
+            if (CollectionUtils.isNotEmpty(cardJpgResultList)) {
+                return cardJpgResultList;
+            } else {
+                return scanAnswerCardService.listPageImage(examId, paperNumber);
+            }
         }
 
-        List<CardJpgResult> cardJpgResultList = new ArrayList<>();
         if (Objects.nonNull(examTaskDetail) && Objects.nonNull(examTaskDetail.getPaperAttachmentIds())) {
             List<PaperInfoVo> paperInfoVoList = ExamTaskUtil.parsePaperAttachmentPath(examTaskDetail.getPaperAttachmentIds());
             // AB卷共用同一份题卡

+ 49 - 53
distributed-print-business/src/main/java/com/qmth/distributed/print/business/service/impl/PrintFinishServiceImpl.java

@@ -184,68 +184,64 @@ public class PrintFinishServiceImpl implements PrintFinishService {
 
     @Override
     public ScanAnswerCard insertScanAnswerCard(ExamDetailCourseInitMarkDto dto, String cardId, String content) {
-        ExamCard examCard = examCardService.getById(cardId);
-        if (examCard != null) {
-            ScanAnswerCard scanAnswerCard = scanAnswerCardService.getByExamIdAndCoursePaperIdAndSerialNumberAndCardId(dto.getExamId(), dto.getCoursePaperId(), dto.getSerialNumber(), Long.valueOf(cardId));
-            if (scanAnswerCard != null) {
-                return scanAnswerCard;
-            }
+        ScanAnswerCard scanAnswerCard = scanAnswerCardService.getByExamIdAndCoursePaperIdAndSerialNumberAndCardId(dto.getExamId(), dto.getCoursePaperId(), dto.getSerialNumber(), Long.valueOf(cardId));
+        if (scanAnswerCard != null) {
+            return scanAnswerCard;
+        }
 
-            File tempFile = SystemConstant.getFileTempDirVar(System.currentTimeMillis() + File.separator + SystemConstant.getNanoId(), SystemConstant.TEMP_PREFIX);
-            String rootPath = tempFile.getParent();
-            String jsonPath = rootPath + File.separator + cardId + SystemConstant.JSON_PREFIX;
+        File tempFile = SystemConstant.getFileTempDirVar(System.currentTimeMillis() + File.separator + SystemConstant.getNanoId(), SystemConstant.TEMP_PREFIX);
+        String rootPath = tempFile.getParent();
+        String jsonPath = rootPath + File.separator + cardId + SystemConstant.JSON_PREFIX;
 
-            InputStream inputStream = null;
-            File jsonFile = null;
-            try {
-                // 将知学知考卡格式内容,转换为扫描端格式
-                CardFile cardFile = CardFile.parse(examCard.getContent());
-                jsonFile = SystemConstant.createJsonFile(jsonPath, cardFile.output());
-                if (jsonFile.exists()) {
-                    inputStream = new FileInputStream(jsonFile);
-                    String md5 = DigestUtils.md5Hex(new FileInputStream(jsonFile));
-                    Integer number = scanAnswerCardService.findMaxCardNumberByExamId(dto.getExamId()) + 1;
-                    String path = markFileService.getAnswerCardUri(dto.getExamId(), dto.getCoursePaperId(), number);
-                    String uploadPath = fileStoreUtils.uploadFile(inputStream, md5, UploadFileEnum.CARD, path);
+        InputStream inputStream = null;
+        File jsonFile = null;
+        try {
+            // 将知学知考卡格式内容,转换为扫描端格式
+            CardFile cardFile = CardFile.parse(content);
+            jsonFile = SystemConstant.createJsonFile(jsonPath, cardFile.output());
+            if (jsonFile.exists()) {
+                inputStream = new FileInputStream(jsonFile);
+                String md5 = DigestUtils.md5Hex(new FileInputStream(jsonFile));
+                Integer number = scanAnswerCardService.findMaxCardNumberByExamId(dto.getExamId()) + 1;
+                String path = markFileService.getAnswerCardUri(dto.getExamId(), dto.getCoursePaperId(), number);
+                String uploadPath = fileStoreUtils.uploadFile(inputStream, md5, UploadFileEnum.CARD, path);
 
-                    scanAnswerCard = new ScanAnswerCard();
-                    scanAnswerCard.setId(SystemConstant.getDbUuid());
-                    scanAnswerCard.setExamId(dto.getExamId());
-                    scanAnswerCard.setPaperNumber(dto.getPaperNumber());
-                    scanAnswerCard.setCoursePaperId(dto.getCoursePaperId());
-                    scanAnswerCard.setSerialNumber(dto.getSerialNumber());
-                    scanAnswerCard.setPaperType(dto.getPaperType());
-                    scanAnswerCard.setCardId(Long.valueOf(cardId));
-                    scanAnswerCard.setNumber(number);
-                    scanAnswerCard.setSource(CardSource.WEB);
-                    scanAnswerCard.setUri(uploadPath);
-                    scanAnswerCard.setMd5(md5);
-                    scanAnswerCard.setNeedAdapte(true);
-                    scanAnswerCard.setSinglePage(false);// 默认false
-                    // 题卡张数
-                    int paperCount = CardParseUtils.calcPaperCount(content, true);
-                    scanAnswerCard.setPaperCount(paperCount);
-                    scanAnswerCardService.save(scanAnswerCard);
-                }
+                scanAnswerCard = new ScanAnswerCard();
+                scanAnswerCard.setId(SystemConstant.getDbUuid());
+                scanAnswerCard.setExamId(dto.getExamId());
+                scanAnswerCard.setPaperNumber(dto.getPaperNumber());
+                scanAnswerCard.setCoursePaperId(dto.getCoursePaperId());
+                scanAnswerCard.setSerialNumber(dto.getSerialNumber());
+                scanAnswerCard.setPaperType(dto.getPaperType());
+                scanAnswerCard.setCardId(Long.valueOf(cardId));
+                scanAnswerCard.setNumber(number);
+                scanAnswerCard.setSource(CardSource.WEB);
+                scanAnswerCard.setUri(uploadPath);
+                scanAnswerCard.setMd5(md5);
+                scanAnswerCard.setNeedAdapte(true);
+                scanAnswerCard.setSinglePage(false);// 默认false
+                // 题卡张数
+                int paperCount = CardParseUtils.calcPaperCount(content, true);
+                scanAnswerCard.setPaperCount(paperCount);
+                scanAnswerCardService.save(scanAnswerCard);
+            }
+        } catch (IOException e) {
+            log.info("考试[{}],试卷编号[{}],题卡ID[{}]同步阅卷失败", dto.getExamId(), dto.getPaperNumber(), cardId);
+        } finally {
+            try {
+                FileUtils.forceDeleteOnExit(jsonFile);
             } catch (IOException e) {
-                log.info("考试[{}],试卷编号[{}],题卡ID[{}]同步阅卷失败", dto.getExamId(), dto.getPaperNumber(), cardId);
-            } finally {
+                log.info("删除jsonFile失败");
+            }
+            if (inputStream != null) {
                 try {
-                    FileUtils.forceDeleteOnExit(jsonFile);
+                    inputStream.close();
                 } catch (IOException e) {
-                    log.info("删除jsonFile失败");
-                }
-                if (inputStream != null) {
-                    try {
-                        inputStream.close();
-                    } catch (IOException e) {
-                        log.info("关闭inputStream流失败");
-                    }
+                    log.info("关闭inputStream流失败");
                 }
             }
-            return scanAnswerCard;
         }
-        return null;
+        return scanAnswerCard;
     }
 
     @Transactional

+ 4 - 13
distributed-print-business/src/main/resources/mapper/ConditionMapper.xml

@@ -1188,23 +1188,14 @@
     <select id="listCourseForMarkPaper" resultType="com.qmth.teachcloud.common.entity.BasicCourse">
         select distinct bc.id,bc.code,bc.name
         from
-            mark_paper mp
-            left join basic_exam be on be.id = mp.exam_id
-            left join basic_course bc on bc.id = mp.course_id
+            basic_course bc
         <where>
-            <if test="semesterId != null and semesterId != ''">
-                and be.semester_id = #{semesterId}
-            </if>
-            <if test="examId != null and examId != ''">
-                and mp.exam_id = #{examId}
-            </if>
-            and exists(select 1 from basic_exam_student bes where bes.exam_id = #{examId} and mp.course_id = bes.course_id
             <if test="dpr != null">
                 <if test="dpr.requestUserId != null">
-                    AND bes.create_id = #{dpr.requestUserId}
+                    AND bc.create_id = #{dpr.requestUserId}
                 </if>
                 <if test="dpr.courseUserId != null">
-                    AND EXISTS( SELECT 1 FROM (select course_id from teach_course where exam_id = #{examId} and user_id = #{dpr.courseUserId}) tc WHERE tc.course_id = bes.course_id)
+                    AND EXISTS( SELECT 1 FROM (select course_id from teach_course where exam_id = #{examId} and user_id = #{dpr.courseUserId}) tc WHERE tc.course_id = bc.id)
                 </if>
                 <if test="dpr.orgIdSet != null and dpr.orgIdSet != '' and dpr.orgIdSet.size > 0">
                     AND bc.teaching_room_id IN
@@ -1212,7 +1203,7 @@
                         #{item}
                     </foreach>
                 </if>
-            </if> )
+            </if>
         </where>
     </select>
 </mapper>

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

@@ -22,8 +22,8 @@
             <if test="paperNumber != null and paperNumber != ''">
                 AND bes.paper_number = #{paperNumber}
             </if>
-            <if test="collegeId != null and collegeId != ''">
-                AND bc.teaching_room_id = #{collegeId}
+            <if test="openCollegeId != null and openCollegeId != ''">
+                AND bc.teaching_room_id = #{openCollegeId}
             </if>
             <if test="title != null and title != ''">
                 and ecmf.title like concat('%', #{title}, '%')

+ 6 - 1
distributed-print/install/mysql/upgrade/3.4.4.sql

@@ -320,4 +320,9 @@ update mark_paper set merge_marker = 1 where merge_marker is null;
 update mark_paper set double_mark = 0 where double_mark is null;
 update mark_student set version = 1 where version is null;
 update mark_student ms left join basic_exam_student bes on ms.basic_student_id = bes.id set ms.teach_class_name = bes.teach_class_name where ms.teach_class_name is null;
-update mark_question mq left join mark_paper mp on mq.exam_id = mp.exam_id and mq.paper_number = mp.paper_number set mq.course_id = mp.course_id where mq.course_id is null;
+update mark_question mq left join mark_paper mp on mq.exam_id = mp.exam_id and mq.paper_number = mp.paper_number set mq.course_id = mp.course_id where mq.course_id is null;
+
+-- 2025-03-18
+INSERT INTO `sys_privilege` (`id`, `name`, `url`, `type`, `parent_id`, `sequence`, `property`, `enable`, `default_auth`, `front_display`) VALUES ('1217', '课程唯一性校验', '/api/admin/exam/model_4/card/valid_course', 'URL', '1199', '8', 'AUTH', '1', '1', '1');
+UPDATE `sys_privilege` SET `related` = '1210,1217' WHERE (`id` = '1201');
+UPDATE `sys_privilege` SET `related` = '1210,1217' WHERE (`id` = '1206');

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

@@ -45,11 +45,20 @@ public class ExamCardModelFourController {
                        @ApiParam(value = "考试ID", required = true) @RequestParam Long examId,
                        @ApiParam(value = "课程代码") @RequestParam(required = false) Long courseId,
                        @ApiParam(value = "试卷编号") @RequestParam(required = false) String paperNumber,
-                       @ApiParam(value = "开课学院ID") @RequestParam(required = false) Long collegeId,
+                       @ApiParam(value = "开课学院ID") @RequestParam(required = false) Long openCollegeId,
                        @ApiParam(value = "题卡名称模糊查询") @RequestParam(required = false) String title,
                        @ApiParam(value = "分页页码", required = true) @RequestParam @Min(SystemConstant.PAGE_NUMBER_MIN) Integer pageNumber,
                        @ApiParam(value = "分页数", required = true) @RequestParam @Min(SystemConstant.PAGE_SIZE_MIN) @Max(SystemConstant.PAGE_SIZE_MAX) Integer pageSize) {
-        return ResultUtil.ok(examCardModelFourService.listPage(new Page<>(pageNumber, pageSize), semesterId, examId, courseId, paperNumber, collegeId, title));
+        return ResultUtil.ok(examCardModelFourService.listPage(new Page<>(pageNumber, pageSize), semesterId, examId, courseId, paperNumber, openCollegeId, title));
+    }
+
+    @ApiOperation(value = "校验课程是否唯一")
+    @RequestMapping(value = "/valid_course", method = RequestMethod.POST)
+    @OperationLogDetail(operationType = OperationTypeEnum.SAVE, detail = "新增/修改操作,题卡ID:{{params.id}}、题卡标题:{{params.title}}")
+    @ApiResponses({@ApiResponse(code = 200, message = "新增/修改", response = EditResult.class)})
+    public Result validCourse(GenericExamCardModelFourParams params) {
+        examCardModelFourService.validCourse(params);
+        return ResultUtil.success(true);
     }
 
     @ApiOperation(value = "根据ID获取题卡详情")

+ 18 - 18
distributed-print/src/main/java/com/qmth/distributed/print/api/mark/MarkQuestionController.java

@@ -71,25 +71,25 @@ public class MarkQuestionController extends BaseController {
     @RequestMapping(value = "/list", method = RequestMethod.POST)
     public Result list(@ApiParam(value = "考试ID", required = true) @RequestParam Long examId,
                        @ApiParam(value = "试卷编号", required = true) @RequestParam String paperNumber) {
-        boolean canCreate = false;
-        MarkPaper markPaper = markPaperService.getByExamIdAndPaperNumber(examId, paperNumber);
-        ExamTaskDetail examTaskDetail = examTaskDetailService.findByExamIdAndPaperNumberAndSerialNumber(examId, paperNumber, markPaper.getSerialNumber());
-        if (examTaskDetail == null) {
-            canCreate = true;
-        } else {
-            List<PaperInfoVo> paperInfoVoList = ExamTaskUtil.parsePaperAttachmentPath(examTaskDetail.getPaperAttachmentIds());
-            PaperInfoVo paperInfoVo = paperInfoVoList.get(0);
-            if (paperInfoVo.getCardId() != null) {
-                ExamCard examCard = examCardService.getById(paperInfoVo.getCardId());
-                if (examCard != null) {
-                    if (CardCreateMethodEnum.UPLOAD.equals(examCard.getCreateMethod())) {
-                        canCreate = true;
-                    }
-                }
-            }
-        }
+//        boolean canCreate = false;
+//        MarkPaper markPaper = markPaperService.getByExamIdAndPaperNumber(examId, paperNumber);
+//        ExamTaskDetail examTaskDetail = examTaskDetailService.findByExamIdAndPaperNumberAndSerialNumber(examId, paperNumber, markPaper.getSerialNumber());
+//        if (examTaskDetail == null) {
+//            canCreate = true;
+//        } else {
+//            List<PaperInfoVo> paperInfoVoList = ExamTaskUtil.parsePaperAttachmentPath(examTaskDetail.getPaperAttachmentIds());
+//            PaperInfoVo paperInfoVo = paperInfoVoList.get(0);
+//            if (paperInfoVo.getCardId() != null) {
+//                ExamCard examCard = examCardService.getById(paperInfoVo.getCardId());
+//                if (examCard != null) {
+//                    if (CardCreateMethodEnum.UPLOAD.equals(examCard.getCreateMethod())) {
+//                        canCreate = true;
+//                    }
+//                }
+//            }
+//        }
         MarkQuestionDto markQuestionDto = markQuestionService.pageQuestionsByExamIdAndPaperNumber(examId, paperNumber);
-        markQuestionDto.setCanCreate(canCreate);
+//        markQuestionDto.setCanCreate(canCreate);
         return ResultUtil.ok(markQuestionDto);
     }
 

+ 6 - 1
pom.xml

@@ -25,7 +25,7 @@
         <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
         <maven.compiler.source>1.8</maven.compiler.source>
         <maven.compiler.target>1.8</maven.compiler.target>
-        <qmth.boot.version>1.0.5</qmth.boot.version>
+        <qmth.boot.version>1.0.6</qmth.boot.version>
 <!--        <swagger2.version>2.9.2</swagger2.version>-->
         <knife4j.version>2.0.7</knife4j.version>
         <fastjson.version>1.2.68</fastjson.version>
@@ -184,6 +184,11 @@
                 <artifactId>tools-poi</artifactId>
                 <version>${qmth.boot.version}</version>
             </dependency>
+            <dependency>
+                <groupId>com.qmth.boot</groupId>
+                <artifactId>data-upgrade</artifactId>
+                <version>${qmth.boot.version}</version>
+            </dependency>
 <!--            <dependency>-->
 <!--                <groupId>io.springfox</groupId>-->
 <!--                <artifactId>springfox-swagger-ui</artifactId>-->

+ 62 - 0
teachcloud-common/src/main/java/com/qmth/teachcloud/common/util/PDFConverter.java

@@ -0,0 +1,62 @@
+package com.qmth.teachcloud.common.util;
+
+
+import com.itextpdf.text.Document;
+import com.itextpdf.text.PageSize;
+import com.itextpdf.text.Paragraph;
+import com.itextpdf.text.Rectangle;
+import com.itextpdf.text.pdf.*;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+
+public class PDFConverter {
+    public static void main(String[] args) throws IOException {
+
+
+    }
+
+    private File pdfA3ToA4(String source) {
+        String inputPdf = "/Users/xiaofei/111.pdf";
+        String outputPdf = "/Users/xiaofei/222.pdf";
+
+        try {
+            // 创建A3横向页面尺寸
+            Rectangle a3Landscape = PageSize.A3.rotate();
+
+            // 初始化文档和写入器
+            Document document = new Document(a3Landscape);
+            PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(outputPdf));
+            document.open();
+
+            // 读取源PDF
+            PdfReader reader = new PdfReader(inputPdf);
+
+            // 遍历所有页面
+            for (int i = 1; i <= reader.getNumberOfPages(); i++) {
+                // 创建新A3页面
+                document.newPage();
+
+                // 获取当前页内容
+                PdfImportedPage importedPage = writer.getImportedPage(reader, i);
+
+                // 获取画布对象
+                PdfContentByte content = writer.getDirectContent();
+
+                // 将A4页面添加到A3左半边(原点在左下角)
+                content.addTemplate(importedPage, 0, 0); // 直接放置,不缩放
+            }
+
+            // 关闭资源
+            document.close();
+            reader.close();
+
+            System.out.println("转换完成!");
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+
+        return null;
+    }
+}

+ 2 - 1
teachcloud-mark/src/main/java/com/qmth/teachcloud/mark/bean/vo/parseCard/pic/SubPictureConfig.java

@@ -2,6 +2,7 @@ package com.qmth.teachcloud.mark.bean.vo.parseCard.pic;
 
 import com.alibaba.fastjson.JSON;
 import com.qmth.teachcloud.common.bean.dto.mark.PictureConfig;
+import com.qmth.teachcloud.mark.bean.answercard.CardFile;
 import org.apache.commons.collections4.CollectionUtils;
 
 import java.util.List;
@@ -43,7 +44,7 @@ public class SubPictureConfig {
             pictureConfig.setH(m.getH());
             return pictureConfig;
         }).collect(Collectors.toList());
-        return JSON.toJSONString(configList);
+        return CardFile.getMarkConfigAdd(configList, 0.015);
     }
 
     public int getI() {

+ 0 - 2
teachcloud-mark/src/main/java/com/qmth/teachcloud/mark/dto/mark/setting/MarkUserClassDto.java

@@ -1,7 +1,5 @@
 package com.qmth.teachcloud.mark.dto.mark.setting;
 
-import com.qmth.teachcloud.common.bean.dto.mark.MarkUser;
-
 import java.util.List;
 
 public class MarkUserClassDto {

+ 2 - 0
teachcloud-mark/src/main/java/com/qmth/teachcloud/mark/mapper/MarkUserQuestionMapper.java

@@ -71,4 +71,6 @@ public interface MarkUserQuestionMapper extends BaseMapper<MarkUserQuestion> {
      * @return
      */
     int insertSms(@Param("basicMessageDto") BasicMessageDto basicMessageDto);
+
+    List<MarkUser> listUserByExamIdAndPaperNumber(@Param("examId") Long examId, @Param("paperNumber") String paperNumber);
 }

+ 2 - 1
teachcloud-mark/src/main/java/com/qmth/teachcloud/mark/service/MarkQuestionAnswerService.java

@@ -3,6 +3,8 @@ package com.qmth.teachcloud.mark.service;
 import com.qmth.teachcloud.common.entity.MarkQuestion;
 import com.qmth.teachcloud.mark.entity.MarkQuestionAnswer;
 import com.baomidou.mybatisplus.extension.service.IService;
+import com.qmth.teachcloud.mark.entity.ScanAnswerCard;
+import com.qmth.teachcloud.mark.enums.CardSource;
 
 import java.util.List;
 
@@ -26,5 +28,4 @@ public interface MarkQuestionAnswerService extends IService<MarkQuestionAnswer>
     void deleteByExamIdAndPaperNumber(Long examId, String paperNumber);
 
     void saveByMarkQuestion(Long examId, String paperNumber, List<MarkQuestion> markQuestions, boolean containAnswer);
-
 }

+ 3 - 0
teachcloud-mark/src/main/java/com/qmth/teachcloud/mark/service/MarkUserQuestionService.java

@@ -5,6 +5,7 @@ import com.baomidou.mybatisplus.extension.service.IService;
 import com.qmth.teachcloud.common.bean.dto.MarkTaskSmsDto;
 import com.qmth.teachcloud.common.bean.dto.mark.MarkUser;
 import com.qmth.teachcloud.common.entity.MarkQuestion;
+import com.qmth.teachcloud.common.entity.SysUser;
 import com.qmth.teachcloud.common.enums.MessageEnum;
 import com.qmth.teachcloud.common.enums.mark.MarkPaperStatus;
 import com.qmth.teachcloud.mark.bean.marker.MarkerAddParam;
@@ -128,4 +129,6 @@ public interface MarkUserQuestionService extends IService<MarkUserQuestion> {
      * @param paperNumber
      */
     void smsMarkTask(Long examId, Long courseId, String paperNumber);
+
+    List<MarkUser> listUserByExamIdAndPaperNumber(Long examId, String paperNumber);
 }

+ 1 - 0
teachcloud-mark/src/main/java/com/qmth/teachcloud/mark/service/ScanAnswerCardService.java

@@ -57,4 +57,5 @@ public interface ScanAnswerCardService extends IService<ScanAnswerCard> {
      * @return
      */
     ScanAnswerCard findByExamAndCardIdAndCardSource(Long examId, Long cardId, CardSource source);
+
 }

+ 2 - 0
teachcloud-mark/src/main/java/com/qmth/teachcloud/mark/service/impl/MarkQuestionAnswerServiceImpl.java

@@ -6,6 +6,8 @@ import com.qmth.teachcloud.common.entity.MarkQuestion;
 import com.qmth.teachcloud.common.enums.ObjectivePolicy;
 import com.qmth.teachcloud.mark.entity.MarkPaper;
 import com.qmth.teachcloud.mark.entity.MarkQuestionAnswer;
+import com.qmth.teachcloud.mark.entity.ScanAnswerCard;
+import com.qmth.teachcloud.mark.enums.CardSource;
 import com.qmth.teachcloud.mark.mapper.MarkQuestionAnswerMapper;
 import com.qmth.teachcloud.mark.service.MarkPaperService;
 import com.qmth.teachcloud.mark.service.MarkQuestionAnswerService;

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

@@ -801,8 +801,8 @@ public class MarkQuestionServiceImpl extends ServiceImpl<MarkQuestionMapper, Mar
                 if (subjectiveMarker) {
                     // 分班阅
                     MarkPaper markPaper = markPaperService.getByExamIdAndPaperNumber(examId, paperNumber);
-                    subjectiveMarkerClass = markPaper != null && markPaper.getClassMark();
-                    if (subjectiveMarkerClass) {
+                    subjectiveMarkerClass = markPaper != null && !markPaper.getClassMark();
+                    if (!subjectiveMarkerClass) {
                         MarkStudentQuery markStudentQuery = new MarkStudentQuery();
                         markStudentQuery.setExamId(examId);
                         markStudentQuery.setPaperNumber(paperNumber);

+ 2 - 1
teachcloud-mark/src/main/java/com/qmth/teachcloud/mark/service/impl/MarkUserClassServiceImpl.java

@@ -11,6 +11,7 @@ import com.qmth.teachcloud.common.bean.params.mark.group.MarkClassUserParams;
 import com.qmth.teachcloud.common.bean.params.mark.group.MarkGroupClassUserParams;
 import com.qmth.teachcloud.common.contant.SystemConstant;
 import com.qmth.teachcloud.common.entity.MarkQuestion;
+import com.qmth.teachcloud.common.entity.SysUser;
 import com.qmth.teachcloud.common.enums.ExceptionResultEnum;
 import com.qmth.teachcloud.mark.bean.student.MarkStudentQuery;
 import com.qmth.teachcloud.mark.dto.mark.MarkStudentVo;
@@ -86,7 +87,7 @@ public class MarkUserClassServiceImpl extends ServiceImpl<MarkUserClassMapper, M
     public MarkUserClassDto listMarkUserClassByExamIdAndPaperNumber(Long examId, String paperNumber) {
         // 课程下所有班级数据
         List<String> paperNumberClassList = markStudentService.listClassByExamIdAndCourseCode(examId, paperNumber);
-        List<MarkUser> markUserList = markUserQuestionService.listGroupUserByExamIdAndPaperNumberAndQuestionIdAndClassName(examId, paperNumber, null, null);
+        List<MarkUser> markUserList = markUserQuestionService.listUserByExamIdAndPaperNumber(examId, paperNumber);
 
         MarkUserClassDto markUserClassDto = new MarkUserClassDto();
         markUserClassDto.setClassNames(paperNumberClassList);

+ 7 - 0
teachcloud-mark/src/main/java/com/qmth/teachcloud/mark/service/impl/MarkUserQuestionServiceImpl.java

@@ -11,6 +11,7 @@ import com.google.common.collect.ImmutableMap;
 import com.qmth.teachcloud.common.bean.dto.MarkTaskSmsDto;
 import com.qmth.teachcloud.common.bean.dto.mark.MarkUser;
 import com.qmth.teachcloud.common.bean.result.SmsResponseResult;
+import com.qmth.teachcloud.common.contant.SystemConstant;
 import com.qmth.teachcloud.common.entity.MarkQuestion;
 import com.qmth.teachcloud.common.entity.SysConfig;
 import com.qmth.teachcloud.common.entity.SysUser;
@@ -506,6 +507,7 @@ public class MarkUserQuestionServiceImpl extends ServiceImpl<MarkUserQuestionMap
         } catch (Exception e) {
             basicMessageDto.setErrorInfo(e.getMessage());
         } finally {
+            basicMessageDto.setId(SystemConstant.getDbUuid());
             this.baseMapper.insertSms(basicMessageDto);
         }
     }
@@ -532,4 +534,9 @@ public class MarkUserQuestionServiceImpl extends ServiceImpl<MarkUserQuestionMap
             }
         }
     }
+
+    @Override
+    public List<MarkUser> listUserByExamIdAndPaperNumber(Long examId, String paperNumber) {
+        return this.baseMapper.listUserByExamIdAndPaperNumber(examId, paperNumber);
+    }
 }

+ 20 - 0
teachcloud-mark/src/main/resources/mapper/MarkUserQuestionMapper.xml

@@ -303,6 +303,26 @@
           and bm.send_status = 'OK'
           and (bm.remark is not null and bm.remark = #{condition})
     </select>
+    <select id="listUserByExamIdAndPaperNumber" resultType="com.qmth.teachcloud.common.bean.dto.mark.MarkUser">
+        SELECT
+            su.id userId,
+            su.login_name loginName,
+            su.real_name name,
+            so.name orgName
+        FROM
+            sys_user su
+                LEFT JOIN
+            sys_org so ON su.org_id = so.id
+        WHERE
+            EXISTS( SELECT
+                        1
+                    FROM
+                        mark_user_question muq
+                    WHERE
+                        muq.exam_id = #{examId} AND muq.paper_number = #{paperNumber}
+                      AND muq.enable = TRUE
+                      AND su.id = muq.user_id)
+    </select>
 
     <insert id="insertSms" parameterType="com.qmth.teachcloud.mark.dto.BasicMessageDto">
         INSERT INTO basic_message