Kaynağa Gözat

3.3.0 评卷设置

xiaofei 1 yıl önce
ebeveyn
işleme
a02fc380a2
21 değiştirilmiş dosya ile 431 ekleme ve 36 silme
  1. 4 4
      distributed-print/install/mysql/upgrade/3.3.0.sql
  2. 14 4
      distributed-print/src/main/java/com/qmth/distributed/print/api/mark/MarkClassController.java
  3. 51 0
      distributed-print/src/main/java/com/qmth/distributed/print/api/mark/MarkQuestionController.java
  4. 9 0
      teachcloud-common/src/main/java/com/qmth/teachcloud/common/bean/dto/mark/setting/MarkUserClassDto.java
  5. 59 0
      teachcloud-common/src/main/java/com/qmth/teachcloud/common/bean/params/mark/setting/MarkClassUserParams.java
  6. 22 0
      teachcloud-common/src/main/java/com/qmth/teachcloud/common/bean/params/mark/setting/MarkObjectiveQuestionParams.java
  7. 15 12
      teachcloud-common/src/main/java/com/qmth/teachcloud/common/entity/MarkPaper.java
  8. 1 1
      teachcloud-common/src/main/java/com/qmth/teachcloud/common/mapper/MarkQuestionMapper.java
  9. 10 1
      teachcloud-common/src/main/java/com/qmth/teachcloud/common/service/MarkQuestionService.java
  10. 3 0
      teachcloud-common/src/main/java/com/qmth/teachcloud/common/service/MarkStudentService.java
  11. 62 4
      teachcloud-common/src/main/java/com/qmth/teachcloud/common/service/impl/MarkQuestionServiceImpl.java
  12. 20 0
      teachcloud-common/src/main/java/com/qmth/teachcloud/common/service/impl/MarkStudentServiceImpl.java
  13. 44 1
      teachcloud-common/src/main/java/com/qmth/teachcloud/common/util/FileStoreUtil.java
  14. 2 2
      teachcloud-common/src/main/resources/mapper/MarkPaperMapper.xml
  15. 2 1
      teachcloud-common/src/main/resources/mapper/MarkQuestionMapper.xml
  16. 4 0
      teachcloud-mark/src/main/java/com/qmth/teachcloud/mark/mapper/MarkUserClassMapper.java
  17. 8 0
      teachcloud-mark/src/main/java/com/qmth/teachcloud/mark/service/MarkUserClassService.java
  18. 1 1
      teachcloud-mark/src/main/java/com/qmth/teachcloud/mark/service/impl/MarkGroupServiceImpl.java
  19. 80 4
      teachcloud-mark/src/main/java/com/qmth/teachcloud/mark/service/impl/MarkUserClassServiceImpl.java
  20. 1 1
      teachcloud-mark/src/main/java/com/qmth/teachcloud/mark/service/impl/MarkUserGroupServiceImpl.java
  21. 19 0
      teachcloud-mark/src/main/resources/mapper/MarkUserClassMapper.xml

+ 4 - 4
distributed-print/install/mysql/upgrade/3.3.0.sql

@@ -35,10 +35,10 @@ INSERT INTO `sys_privilege` (`id`, `name`, `url`, `type`, `parent_id`, `sequence
 INSERT INTO `sys_privilege` (`id`, `name`, `url`, `type`, `parent_id`, `sequence`, `property`, `enable`, `default_auth`, `front_display`) VALUES ('907', '评卷任务删除', '/api/admin/mark/group/delete', 'URL', '897', '6', 'AUTH', '1', '1', '1');
 INSERT INTO `sys_privilege` (`id`, `name`, `url`, `type`, `parent_id`, `sequence`, `property`, `enable`, `default_auth`, `front_display`) VALUES ('908', '分班阅查询', '/api/admin/mark/class/list', 'URL', '897', '7', 'AUTH', '1', '1', '1');
 INSERT INTO `sys_privilege` (`id`, `name`, `url`, `type`, `parent_id`, `sequence`, `property`, `enable`, `default_auth`, `front_display`) VALUES ('909', '分班阅提交', '/api/admin/mark/class/save', 'URL', '897', '8', 'AUTH', '1', '1', '1');
-INSERT INTO `sys_privilege` (`id`, `name`, `url`, `type`, `parent_id`, `sequence`, `property`, `enable`, `default_auth`, `front_display`) VALUES ('910', '客观题标答查询', '/api/admin/mark/objective/list', 'URL', '897', '9', 'AUTH', '1', '1', '1');
-INSERT INTO `sys_privilege` (`id`, `name`, `url`, `type`, `parent_id`, `sequence`, `property`, `enable`, `default_auth`, `front_display`) VALUES ('911', '客观题标答提交', '/api/admin/mark/objective/save', 'URL', '897', '10', 'AUTH', '1', '1', '1');
-INSERT INTO `sys_privilege` (`id`, `name`, `url`, `type`, `parent_id`, `sequence`, `property`, `enable`, `default_auth`, `front_display`) VALUES ('912', '主观题标答查询', '/api/admin/mark/subjective/list', 'URL', '897', '11', 'AUTH', '1', '1', '1');
-INSERT INTO `sys_privilege` (`id`, `name`, `url`, `type`, `parent_id`, `sequence`, `property`, `enable`, `default_auth`, `front_display`) VALUES ('913', '主观题标答提交', '/api/admin/mark/subjective/save', 'URL', '897', '12', 'AUTH', '1', '1', '1');
+INSERT INTO `sys_privilege` (`id`, `name`, `url`, `type`, `parent_id`, `sequence`, `property`, `enable`, `default_auth`, `front_display`) VALUES ('910', '客观题标答查询', '/api/admin/mark/question/objective/list', 'URL', '897', '9', 'AUTH', '1', '1', '1');
+INSERT INTO `sys_privilege` (`id`, `name`, `url`, `type`, `parent_id`, `sequence`, `property`, `enable`, `default_auth`, `front_display`) VALUES ('911', '客观题标答提交', '/api/admin/mark/question/objective/save', 'URL', '897', '10', 'AUTH', '1', '1', '1');
+INSERT INTO `sys_privilege` (`id`, `name`, `url`, `type`, `parent_id`, `sequence`, `property`, `enable`, `default_auth`, `front_display`) VALUES ('912', '主观题标答查询', '/api/admin/mark/question/subjective/get', 'URL', '897', '11', 'AUTH', '1', '1', '1');
+INSERT INTO `sys_privilege` (`id`, `name`, `url`, `type`, `parent_id`, `sequence`, `property`, `enable`, `default_auth`, `front_display`) VALUES ('913', '主观题标答提交', '/api/admin/mark/question/subjective/upload', 'URL', '897', '12', 'AUTH', '1', '1', '1');
 INSERT INTO `sys_privilege` (`id`, `name`, `url`, `type`, `parent_id`, `sequence`, `property`, `related`, `enable`, `default_auth`, `front_display`) VALUES ('914', '评卷设置', 'MarkConfig', 'LINK', '897', '4', 'AUTH', '915,916', '1', '1', '1');
 INSERT INTO `sys_privilege` (`id`, `name`, `url`, `type`, `parent_id`, `sequence`, `property`, `enable`, `default_auth`, `front_display`) VALUES ('915', '数据获取', '/api/admin/mark/setting/paper/get', 'URL', '897', '13', 'AUTH', '1', '1', '1');
 INSERT INTO `sys_privilege` (`id`, `name`, `url`, `type`, `parent_id`, `sequence`, `property`, `enable`, `default_auth`, `front_display`) VALUES ('916', '数据保存', '/api/admin/mark/setting/paper/save', 'URL', '897', '14', 'AUTH', '1', '1', '1');

+ 14 - 4
distributed-print/src/main/java/com/qmth/distributed/print/api/mark/MarkClassController.java

@@ -2,19 +2,19 @@ package com.qmth.distributed.print.api.mark;
 
 
 import com.qmth.boot.api.constant.ApiConstant;
+import com.qmth.teachcloud.common.annotation.OperationLogDetail;
 import com.qmth.teachcloud.common.bean.dto.mark.setting.MarkGroupTaskDto;
 import com.qmth.teachcloud.common.bean.dto.mark.setting.MarkUserClassDto;
+import com.qmth.teachcloud.common.bean.params.mark.setting.MarkClassUserParams;
 import com.qmth.teachcloud.common.contant.SystemConstant;
+import com.qmth.teachcloud.common.enums.log.CustomizedOperationTypeEnum;
 import com.qmth.teachcloud.common.util.Result;
 import com.qmth.teachcloud.common.util.ResultUtil;
 import com.qmth.teachcloud.mark.service.MarkUserClassService;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
 import io.swagger.annotations.ApiParam;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RequestMethod;
-import org.springframework.web.bind.annotation.RequestParam;
-import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.bind.annotation.*;
 
 import javax.annotation.Resource;
 import java.util.List;
@@ -45,4 +45,14 @@ public class MarkClassController {
         List<MarkUserClassDto> markUserClassDtoList = markUserClassService.listMarkUserClassByExamIdAndPaperNumber(examId, paperNumber);
         return ResultUtil.ok(markUserClassDtoList);
     }
+
+    /**
+     * 查询
+     */
+    @ApiOperation(value = "提交")
+    @RequestMapping(value = "/save", method = RequestMethod.POST)
+    @OperationLogDetail(customizedOperationType = CustomizedOperationTypeEnum.ADD)
+    public Result save(@RequestBody MarkClassUserParams markClassUserParams) {
+        return ResultUtil.ok(markUserClassService.saveMarkClassUser(markClassUserParams));
+    }
 }

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

@@ -2,9 +2,12 @@ package com.qmth.distributed.print.api.mark;
 
 
 import com.qmth.boot.api.constant.ApiConstant;
+import com.qmth.teachcloud.common.annotation.OperationLogDetail;
+import com.qmth.teachcloud.common.bean.params.mark.setting.MarkObjectiveQuestionParams;
 import com.qmth.teachcloud.common.bean.params.mark.setting.MarkQuestionParams;
 import com.qmth.teachcloud.common.contant.SystemConstant;
 import com.qmth.teachcloud.common.entity.MarkQuestion;
+import com.qmth.teachcloud.common.enums.log.CustomizedOperationTypeEnum;
 import com.qmth.teachcloud.common.service.MarkQuestionService;
 import com.qmth.teachcloud.common.util.Result;
 import com.qmth.teachcloud.common.util.ResultUtil;
@@ -12,6 +15,7 @@ import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
 import io.swagger.annotations.ApiParam;
 import org.springframework.web.bind.annotation.*;
+import org.springframework.web.multipart.MultipartFile;
 
 import javax.annotation.Resource;
 import java.util.List;
@@ -48,8 +52,55 @@ public class MarkQuestionController {
      */
     @ApiOperation(value = "提交")
     @RequestMapping(value = "/save", method = RequestMethod.POST)
+    @OperationLogDetail(customizedOperationType = CustomizedOperationTypeEnum.ADD)
     public Result save(@RequestBody MarkQuestionParams markQuestionParams) {
         markQuestionService.saveQuestions(markQuestionParams);
         return ResultUtil.ok(true);
     }
+
+    /**
+     * 客观题标答查询
+     */
+    @ApiOperation(value = "客观题标答查询")
+    @RequestMapping(value = "/objective/list", method = RequestMethod.POST)
+    public Result listObjective(@ApiParam(value = "考试ID", required = true) @RequestParam Long examId,
+                                @ApiParam(value = "试卷编号", required = true) @RequestParam String paperNumber) {
+        List<MarkQuestion> markQuestionList = markQuestionService.listQuestionByExamIdAndPaperNumberAndGroupNumber(examId, paperNumber, null, true);
+        return ResultUtil.ok(markQuestionList);
+    }
+
+    /**
+     * 客观题标答保存
+     */
+    @ApiOperation(value = "客观题标答提交")
+    @RequestMapping(value = "/objective/save", method = RequestMethod.POST)
+    @OperationLogDetail(customizedOperationType = CustomizedOperationTypeEnum.ADD)
+    public Result saveObjective(@RequestBody MarkObjectiveQuestionParams markObjectiveQuestionParams) {
+        markQuestionService.saveObjectiveQuestions(markObjectiveQuestionParams);
+        return ResultUtil.ok(true);
+    }
+
+    /**
+     * 主观题标答文件查询
+     */
+    @ApiOperation(value = "主观题标答文件查询")
+    @RequestMapping(value = "/subjective/get", method = RequestMethod.POST)
+    public Result getSubjective(@ApiParam(value = "考试ID", required = true) @RequestParam Long examId,
+                                @ApiParam(value = "试卷编号", required = true) @RequestParam String paperNumber) {
+        return ResultUtil.ok(markQuestionService.previewAnswerFileByExamIdAndPaperNumber(examId, paperNumber));
+    }
+
+    /**
+     * 主观题标答文件上传
+     */
+    @ApiOperation(value = "主观题标答文件上传")
+    @RequestMapping(value = "/subjective/upload", method = RequestMethod.POST)
+    @OperationLogDetail(customizedOperationType = CustomizedOperationTypeEnum.ADD)
+    public Result uploadSubjective(@ApiParam(value = "考试ID", required = true) @RequestParam Long examId,
+                                   @ApiParam(value = "试卷编号", required = true) @RequestParam String paperNumber,
+                                   @ApiParam(value = "文件", required = true) @RequestParam MultipartFile file,
+                                   @ApiParam(value = "文件md5", required = true) @RequestParam String md5) {
+
+        return ResultUtil.ok(markQuestionService.uploadSubjectiveFile(examId, paperNumber, file, md5));
+    }
 }

+ 9 - 0
teachcloud-common/src/main/java/com/qmth/teachcloud/common/bean/dto/mark/setting/MarkUserClassDto.java

@@ -4,11 +4,20 @@ import java.util.List;
 
 public class MarkUserClassDto {
 
+    private String className;
     private Integer groupNumber;
     private String groupQuestions;
     private List<MarkUser> markerList;
     private List<MarkUser> classMarkerList;
 
+    public String getClassName() {
+        return className;
+    }
+
+    public void setClassName(String className) {
+        this.className = className;
+    }
+
     public Integer getGroupNumber() {
         return groupNumber;
     }

+ 59 - 0
teachcloud-common/src/main/java/com/qmth/teachcloud/common/bean/params/mark/setting/MarkClassUserParams.java

@@ -0,0 +1,59 @@
+package com.qmth.teachcloud.common.bean.params.mark.setting;
+
+import com.qmth.teachcloud.common.bean.dto.mark.setting.MarkUser;
+import com.qmth.teachcloud.common.entity.MarkQuestion;
+
+import java.io.Serializable;
+import java.util.List;
+
+/**
+ * 分班阅保存请求参数
+ */
+public class MarkClassUserParams implements Serializable {
+
+    private Long examId;
+    private String paperNumber;
+    private String className;
+    private Integer groupNumber;
+    private List<MarkUser> classMarkerList;
+
+    public Long getExamId() {
+        return examId;
+    }
+
+    public void setExamId(Long examId) {
+        this.examId = examId;
+    }
+
+    public String getPaperNumber() {
+        return paperNumber;
+    }
+
+    public void setPaperNumber(String paperNumber) {
+        this.paperNumber = paperNumber;
+    }
+
+    public String getClassName() {
+        return className;
+    }
+
+    public void setClassName(String className) {
+        this.className = className;
+    }
+
+    public Integer getGroupNumber() {
+        return groupNumber;
+    }
+
+    public void setGroupNumber(Integer groupNumber) {
+        this.groupNumber = groupNumber;
+    }
+
+    public List<MarkUser> getClassMarkerList() {
+        return classMarkerList;
+    }
+
+    public void setClassMarkerList(List<MarkUser> classMarkerList) {
+        this.classMarkerList = classMarkerList;
+    }
+}

+ 22 - 0
teachcloud-common/src/main/java/com/qmth/teachcloud/common/bean/params/mark/setting/MarkObjectiveQuestionParams.java

@@ -0,0 +1,22 @@
+package com.qmth.teachcloud.common.bean.params.mark.setting;
+
+import com.qmth.teachcloud.common.entity.MarkQuestion;
+
+import java.io.Serializable;
+import java.util.List;
+
+/**
+ * 客观题标答保存请求参数
+ */
+public class MarkObjectiveQuestionParams implements Serializable {
+
+    private List<MarkQuestion> questions;
+
+    public List<MarkQuestion> getQuestions() {
+        return questions;
+    }
+
+    public void setQuestions(List<MarkQuestion> questions) {
+        this.questions = questions;
+    }
+}

+ 15 - 12
teachcloud-common/src/main/java/com/qmth/teachcloud/common/entity/MarkPaper.java

@@ -65,10 +65,10 @@ public class MarkPaper implements Serializable {
     private String cardType;
 
     @ApiModelProperty(value = "试卷文件类型")
-    private String paperFileType;
+    private String paperFilePath;
 
     @ApiModelProperty(value = "标答文件类型")
-    private String answerFileType;
+    private String answerFilePath;
 
     @ApiModelProperty(value = "评卷是否跳转")
     private Boolean autoScroll;
@@ -184,20 +184,23 @@ public class MarkPaper implements Serializable {
     public void setCardType(String cardType) {
         this.cardType = cardType;
     }
-    public String getPaperFileType() {
-        return paperFileType;
+
+    public String getPaperFilePath() {
+        return paperFilePath;
     }
 
-    public void setPaperFileType(String paperFileType) {
-        this.paperFileType = paperFileType;
+    public void setPaperFilePath(String paperFilePath) {
+        this.paperFilePath = paperFilePath;
     }
-    public String getAnswerFileType() {
-        return answerFileType;
+
+    public String getAnswerFilePath() {
+        return answerFilePath;
     }
 
-    public void setAnswerFileType(String answerFileType) {
-        this.answerFileType = answerFileType;
+    public void setAnswerFilePath(String answerFilePath) {
+        this.answerFilePath = answerFilePath;
     }
+
     public Boolean getAutoScroll() {
         return autoScroll;
     }
@@ -278,8 +281,8 @@ public class MarkPaper implements Serializable {
             ", passScore=" + passScore +
             ", excellentScore=" + excellentScore +
             ", cardType=" + cardType +
-            ", paperFileType=" + paperFileType +
-            ", answerFileType=" + answerFileType +
+            ", paperFilePath=" + paperFilePath +
+            ", answerFilePath=" + answerFilePath +
             ", autoScroll=" + autoScroll +
             ", markMode=" + markMode +
             ", markStartTime=" + markStartTime +

+ 1 - 1
teachcloud-common/src/main/java/com/qmth/teachcloud/common/mapper/MarkQuestionMapper.java

@@ -14,5 +14,5 @@ import org.apache.ibatis.annotations.Param;
  */
 public interface MarkQuestionMapper extends BaseMapper<MarkQuestion> {
 
-    String groupQuestionsByExamIdAndPaperNumberAndNumber(@Param("examId") Long examId, @Param("paperNumber") String paperNumber, @Param("groupNumber") Integer groupNumber);
+    String assembleQuestionsByExamIdAndPaperNumberAndNumber(@Param("examId") Long examId, @Param("paperNumber") String paperNumber, @Param("groupNumber") Integer groupNumber);
 }

+ 10 - 1
teachcloud-common/src/main/java/com/qmth/teachcloud/common/service/MarkQuestionService.java

@@ -1,8 +1,11 @@
 package com.qmth.teachcloud.common.service;
 
 import com.baomidou.mybatisplus.extension.service.IService;
+import com.qmth.teachcloud.common.bean.params.mark.setting.MarkObjectiveQuestionParams;
 import com.qmth.teachcloud.common.bean.params.mark.setting.MarkQuestionParams;
 import com.qmth.teachcloud.common.entity.MarkQuestion;
+import com.qmth.teachcloud.common.enums.UploadFileEnum;
+import org.springframework.web.multipart.MultipartFile;
 
 import java.util.List;
 
@@ -23,11 +26,17 @@ public interface MarkQuestionService extends IService<MarkQuestion> {
      * @param paperNumber 试卷编号
      * @param groupNumber 分组号
      */
-    String getGroupQuestionsByExamIdAndPaperNumberAndNumber(Long examId, String paperNumber, Integer groupNumber);
+    String assembleGroupQuestionsByExamIdAndPaperNumberAndNumber(Long examId, String paperNumber, Integer groupNumber);
 
     List<MarkQuestion> listQuestionByExamIdAndPaperNumber(Long examId, String paperNumber);
 
     void saveQuestions(MarkQuestionParams markQuestionParams);
 
     List<MarkQuestion> listQuestionByExamIdAndPaperNumberAndGroupNumber(Long examId, String paperNumber, Integer number, Boolean isObjective);
+
+    void saveObjectiveQuestions(MarkObjectiveQuestionParams markObjectiveQuestionParams);
+
+    String uploadSubjectiveFile(Long examId, String paperNumber, MultipartFile file, String md5);
+
+    String previewAnswerFileByExamIdAndPaperNumber(Long examId, String paperNumber);
 }

+ 3 - 0
teachcloud-common/src/main/java/com/qmth/teachcloud/common/service/MarkStudentService.java

@@ -3,6 +3,8 @@ package com.qmth.teachcloud.common.service;
 import com.qmth.teachcloud.common.entity.MarkStudent;
 import com.baomidou.mybatisplus.extension.service.IService;
 
+import java.util.List;
+
 /**
  * <p>
  * 考试考生库 服务类
@@ -13,4 +15,5 @@ import com.baomidou.mybatisplus.extension.service.IService;
  */
 public interface MarkStudentService extends IService<MarkStudent> {
 
+    List<String> listClassByExamIdAndCourseCode(Long examId, String paperNumber);
 }

+ 62 - 4
teachcloud-common/src/main/java/com/qmth/teachcloud/common/service/impl/MarkQuestionServiceImpl.java

@@ -1,16 +1,26 @@
 package com.qmth.teachcloud.common.service.impl;
 
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.qmth.teachcloud.common.bean.params.mark.setting.MarkObjectiveQuestionParams;
 import com.qmth.teachcloud.common.bean.params.mark.setting.MarkQuestionParams;
+import com.qmth.teachcloud.common.entity.MarkPaper;
 import com.qmth.teachcloud.common.entity.MarkQuestion;
 import com.qmth.teachcloud.common.enums.ExceptionResultEnum;
+import com.qmth.teachcloud.common.enums.UploadFileEnum;
 import com.qmth.teachcloud.common.mapper.MarkQuestionMapper;
+import com.qmth.teachcloud.common.service.MarkPaperService;
 import com.qmth.teachcloud.common.service.MarkQuestionService;
+import com.qmth.teachcloud.common.service.TeachcloudCommonService;
+import com.qmth.teachcloud.common.util.FileStoreUtil;
 import org.apache.commons.collections4.CollectionUtils;
+import org.apache.commons.lang3.StringUtils;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
+import org.springframework.web.multipart.MultipartFile;
 
+import javax.annotation.Resource;
 import java.util.*;
 import java.util.stream.Collectors;
 
@@ -25,9 +35,18 @@ import java.util.stream.Collectors;
 @Service
 public class MarkQuestionServiceImpl extends ServiceImpl<MarkQuestionMapper, MarkQuestion> implements MarkQuestionService {
 
+    @Resource
+    private TeachcloudCommonService teachcloudCommonService;
+
+    @Resource
+    private MarkPaperService markPaperService;
+
+    @Resource
+    private FileStoreUtil fileStoreUtil;
+
     @Override
-    public String getGroupQuestionsByExamIdAndPaperNumberAndNumber(Long examId, String paperNumber, Integer groupNumber) {
-        return this.baseMapper.groupQuestionsByExamIdAndPaperNumberAndNumber(examId, paperNumber, groupNumber);
+    public String assembleGroupQuestionsByExamIdAndPaperNumberAndNumber(Long examId, String paperNumber, Integer groupNumber) {
+        return this.baseMapper.assembleQuestionsByExamIdAndPaperNumberAndNumber(examId, paperNumber, groupNumber);
     }
 
     @Override
@@ -111,8 +130,10 @@ public class MarkQuestionServiceImpl extends ServiceImpl<MarkQuestionMapper, Mar
     public List<MarkQuestion> listQuestionByExamIdAndPaperNumberAndGroupNumber(Long examId, String paperNumber, Integer number, Boolean isObjective) {
         QueryWrapper<MarkQuestion> queryWrapper = new QueryWrapper<>();
         queryWrapper.lambda().eq(MarkQuestion::getExamId, examId)
-                .eq(MarkQuestion::getPaperNumber, paperNumber)
-                .eq(MarkQuestion::getGroupNumber, number);
+                .eq(MarkQuestion::getPaperNumber, paperNumber);
+        if (number != null) {
+            queryWrapper.lambda().eq(MarkQuestion::getGroupNumber, number);
+        }
         if (isObjective != null) {
             queryWrapper.lambda().eq(MarkQuestion::getObjective, isObjective);
         }
@@ -120,4 +141,41 @@ public class MarkQuestionServiceImpl extends ServiceImpl<MarkQuestionMapper, Mar
                 .orderByAsc(MarkQuestion::getSubNumber);
         return this.list(queryWrapper);
     }
+
+    @Transactional
+    @Override
+    public void saveObjectiveQuestions(MarkObjectiveQuestionParams markObjectiveQuestionParams) {
+        for (MarkQuestion question : markObjectiveQuestionParams.getQuestions()) {
+            if (StringUtils.isBlank(question.getAnswer())) {
+                throw ExceptionResultEnum.ERROR.exception("答案不能为空");
+            }
+            UpdateWrapper<MarkQuestion> updateWrapper = new UpdateWrapper<>();
+            updateWrapper.lambda().set(MarkQuestion::getAnswer, question.getAnswer());
+            if (StringUtils.isNotBlank(question.getObjectivePolicy())) {
+                updateWrapper.lambda().set(MarkQuestion::getObjectivePolicy, question.getObjectivePolicy());
+            }
+            updateWrapper.lambda().eq(MarkQuestion::getId, question.getId());
+            this.update(updateWrapper);
+        }
+    }
+
+    @Override
+    public String uploadSubjectiveFile(Long examId, String paperNumber, MultipartFile file, String md5) {
+        String answerFilePath = fileStoreUtil.uploadFile(file, md5, UploadFileEnum.PDF);
+        UpdateWrapper<MarkPaper> updateWrapper = new UpdateWrapper<>();
+        updateWrapper.lambda().set(MarkPaper::getAnswerFilePath, answerFilePath)
+                .eq(MarkPaper::getExamId, examId)
+                .eq(MarkPaper::getPaperNumber, paperNumber);
+        markPaperService.update(updateWrapper);
+        return teachcloudCommonService.filePreview(answerFilePath);
+    }
+
+    @Override
+    public String previewAnswerFileByExamIdAndPaperNumber(Long examId, String paperNumber) {
+        MarkPaper markPaper = markPaperService.getByExamIdAndPaperNumber(examId, paperNumber);
+        if(markPaper != null){
+            return teachcloudCommonService.filePreview(markPaper.getAnswerFilePath());
+        }
+        return null;
+    }
 }

+ 20 - 0
teachcloud-common/src/main/java/com/qmth/teachcloud/common/service/impl/MarkStudentServiceImpl.java

@@ -1,11 +1,18 @@
 package com.qmth.teachcloud.common.service.impl;
 
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.qmth.teachcloud.common.entity.MarkStudent;
 import com.qmth.teachcloud.common.mapper.MarkStudentMapper;
 import com.qmth.teachcloud.common.service.MarkStudentService;
+import org.apache.commons.collections4.CollectionUtils;
+import org.apache.commons.lang3.StringUtils;
 import org.springframework.stereotype.Service;
 
+import java.util.ArrayList;
+import java.util.List;
+import java.util.stream.Collectors;
+
 /**
  * <p>
  * 考试考生库 服务实现类
@@ -17,4 +24,17 @@ import org.springframework.stereotype.Service;
 @Service
 public class MarkStudentServiceImpl extends ServiceImpl<MarkStudentMapper, MarkStudent> implements MarkStudentService {
 
+    @Override
+    public List<String> listClassByExamIdAndCourseCode(Long examId, String paperNumber) {
+        QueryWrapper<MarkStudent> queryWrapper = new QueryWrapper<>();
+        queryWrapper.lambda().eq(MarkStudent::getExamId, examId)
+                .eq(MarkStudent::getPaperNumber, paperNumber);
+        List<MarkStudent> markStudentList = this.list(queryWrapper);
+
+        List<String> classNameList = new ArrayList<>();
+        if (CollectionUtils.isNotEmpty(markStudentList)) {
+            classNameList = markStudentList.stream().filter(m -> StringUtils.isNotBlank(m.getClassName())).map(MarkStudent::getClassName).distinct().collect(Collectors.toList());
+        }
+        return classNameList;
+    }
 }

+ 44 - 1
teachcloud-common/src/main/java/com/qmth/teachcloud/common/util/FileStoreUtil.java

@@ -1,5 +1,6 @@
 package com.qmth.teachcloud.common.util;
 
+import com.alibaba.fastjson.JSONObject;
 import com.qmth.boot.core.fss.service.FileService;
 import com.qmth.boot.core.fss.store.FileStore;
 import com.qmth.teachcloud.common.config.DictionaryConfig;
@@ -9,15 +10,19 @@ import com.qmth.teachcloud.common.enums.LocalCatalogEnum;
 import com.qmth.teachcloud.common.enums.UploadFileEnum;
 import org.apache.commons.codec.digest.DigestUtils;
 import org.apache.commons.io.FileUtils;
+import org.apache.commons.io.FilenameUtils;
 import org.apache.commons.io.IOUtils;
+import org.apache.commons.lang3.StringUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.stereotype.Component;
+import org.springframework.web.multipart.MultipartFile;
 
 import javax.annotation.Resource;
 import java.io.*;
 import java.time.Duration;
 import java.util.Objects;
+import java.util.StringJoiner;
 
 /**
  * @Description: 文件存储工具类
@@ -242,7 +247,7 @@ public class FileStoreUtil {
             Boolean oss = dictionaryConfig.sysDomain().isOss();
             if (Objects.nonNull(oss) && oss) {
                 FileStore fileStore = fileService.getFileStore(type);
-                if(isExpire) {
+                if (isExpire) {
                     return fileStore.getPresignedUrl(objectPath, Duration.ofMinutes(5L));
                 } else {
                     return fileStore.getPresignedUrl(objectPath, Duration.ofMinutes(300L));
@@ -323,4 +328,42 @@ public class FileStoreUtil {
         }
         return file;
     }
+
+    public String uploadFile(MultipartFile file, String md5, UploadFileEnum type) {
+        JSONObject jsonObject;
+        try {
+            String fileMd5 = DigestUtils.md5Hex(file.getBytes());
+            log.info("fileMd5:{}", fileMd5);
+            log.info("md5:{}", md5);
+            if (!Objects.equals(fileMd5, md5)) {
+                throw ExceptionResultEnum.MD5_EQUALS_FALSE.exception();
+            }
+
+            boolean oss = dictionaryConfig.sysDomain().isOss();
+            StringJoiner stringJoiner = new StringJoiner("");
+            if (!oss && (Objects.nonNull(dictionaryConfig.fssPublicDomain()) && !StringUtils.isBlank(dictionaryConfig.fssPublicDomain().getConfig())) && !dictionaryConfig.fssPublicDomain().getConfig().startsWith(SystemConstant.START_PARENT)) {
+                stringJoiner.add(dictionaryConfig.fssPublicDomain().getConfig()).add(File.separator);
+            }
+            String format = "." + FilenameUtils.getExtension(file.getOriginalFilename());
+            stringJoiner = SystemConstant.getDirName(stringJoiner, type, true);
+            stringJoiner.add(SystemConstant.getNanoId()).add(format);
+
+            jsonObject = new JSONObject();
+            String dirName = stringJoiner.toString().replaceAll("\\\\", SystemConstant.ORG_SPLIT);
+            if (oss || (!oss && dictionaryConfig.fssPrivateDomain().getConfig().startsWith(SystemConstant.START_PARENT))) {//上传至oss
+                this.ossUpload(dirName, file.getInputStream(), md5, type.getFssType());
+                jsonObject.put(SystemConstant.TYPE, oss ? SystemConstant.OSS : SystemConstant.LOCAL);
+                jsonObject.put(SystemConstant.PATH, dirName);
+            } else {//上传至服务器
+                this.localUpload(dirName, file.getInputStream(), md5, LocalCatalogEnum.LOCAL_FILE);
+                jsonObject.put(SystemConstant.TYPE, SystemConstant.LOCAL);
+                jsonObject.put(SystemConstant.PATH, dirName);
+            }
+            jsonObject.put(SystemConstant.UPLOAD_TYPE, type);
+        } catch (Exception e) {
+            throw ExceptionResultEnum.ERROR.exception("文件上传失败");
+        }
+
+        return jsonObject.toJSONString();
+    }
 }

+ 2 - 2
teachcloud-common/src/main/resources/mapper/MarkPaperMapper.xml

@@ -17,8 +17,8 @@
         <result column="pass_score" property="passScore" />
         <result column="excellent_score" property="excellentScore" />
         <result column="card_type" property="cardType" />
-        <result column="paper_file_type" property="paperFileType" />
-        <result column="answer_file_type" property="answerFileType" />
+        <result column="paper_file_path" property="paperFilePath" />
+        <result column="answer_file_path" property="answerFilePath" />
         <result column="auto_scroll" property="autoScroll" />
         <result column="mark_mode" property="markMode" />
         <result column="mark_start_time" property="markStartTime" />

+ 2 - 1
teachcloud-common/src/main/resources/mapper/MarkQuestionMapper.xml

@@ -19,7 +19,7 @@
         <result column="question_type" property="questionType" />
         <result column="name" property="name" />
     </resultMap>
-    <select id="groupQuestionsByExamIdAndPaperNumberAndNumber" resultType="java.lang.String">
+    <select id="assembleQuestionsByExamIdAndPaperNumberAndNumber" resultType="java.lang.String">
         SELECT
             GROUP_CONCAT(CONCAT(mq.main_number, '-', mq.sub_number))
         FROM
@@ -28,6 +28,7 @@
             mq.exam_id = #{examId}
           AND mq.paper_number = #{paperNumber}
           AND mq.group_number = #{groupNumber}
+          AND mq.is_objective = false
         ORDER BY mq.main_number , mq.sub_number
     </select>
 

+ 4 - 0
teachcloud-mark/src/main/java/com/qmth/teachcloud/mark/mapper/MarkUserClassMapper.java

@@ -1,8 +1,11 @@
 package com.qmth.teachcloud.mark.mapper;
 
+import com.qmth.teachcloud.common.bean.dto.mark.setting.MarkUser;
 import com.qmth.teachcloud.mark.entity.MarkUserClass;
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 
+import java.util.List;
+
 /**
  * <p>
  * 评卷员班级 Mapper 接口
@@ -13,4 +16,5 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper;
  */
 public interface MarkUserClassMapper extends BaseMapper<MarkUserClass> {
 
+    List<MarkUser> listClassMarkerByExamIdAndPaperNumberAndGroupNumberAndClassName(Long examId, String paperNumber, Integer groupNumber, String className);
 }

+ 8 - 0
teachcloud-mark/src/main/java/com/qmth/teachcloud/mark/service/MarkUserClassService.java

@@ -1,6 +1,8 @@
 package com.qmth.teachcloud.mark.service;
 
+import com.qmth.teachcloud.common.bean.dto.mark.setting.MarkUser;
 import com.qmth.teachcloud.common.bean.dto.mark.setting.MarkUserClassDto;
+import com.qmth.teachcloud.common.bean.params.mark.setting.MarkClassUserParams;
 import com.qmth.teachcloud.mark.entity.MarkUserClass;
 import com.baomidou.mybatisplus.extension.service.IService;
 
@@ -19,4 +21,10 @@ public interface MarkUserClassService extends IService<MarkUserClass> {
     void deleteByExamIdAndPaperNumber(Long examId, String paperNumber);
 
     List<MarkUserClassDto> listMarkUserClassByExamIdAndPaperNumber(Long examId, String paperNumber);
+
+    List<MarkUser> listClassMarkerByExamIdAndPaperNumberAndGroupNumberAndClassName(Long examId, String paperNumber, Integer groupNumber, String className);
+
+    boolean saveMarkClassUser(MarkClassUserParams markClassUserParams);
+
+    boolean deleteByExamIdAndPaperNumberAndGroupNumber(Long examId, String paperNumber, Integer groupNumber);
 }

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

@@ -72,7 +72,7 @@ public class MarkGroupServiceImpl extends ServiceImpl<MarkGroupMapper, MarkGroup
                 markGroupDto.setMarkers(markUserGroupService.listGroupUserByExamIdAndPaperNumberAndGroupNumber(examId, paperNumber, markGroup.getNumber()));
                 // 题目
                 markGroupDto.setQuestions(markQuestionService.listQuestionByExamIdAndPaperNumberAndGroupNumber(examId, paperNumber, markGroup.getNumber(), false));
-                markGroupDto.setGroupQuestions(markQuestionService.getGroupQuestionsByExamIdAndPaperNumberAndNumber(examId, paperNumber, markGroup.getNumber()));
+                markGroupDto.setGroupQuestions(markQuestionService.assembleGroupQuestionsByExamIdAndPaperNumberAndNumber(examId, paperNumber, markGroup.getNumber()));
                 markGroupDtoList.add(markGroupDto);
             }
             markGroupTaskDto.setGroups(markGroupDtoList);

+ 80 - 4
teachcloud-mark/src/main/java/com/qmth/teachcloud/mark/service/impl/MarkUserClassServiceImpl.java

@@ -1,17 +1,26 @@
 package com.qmth.teachcloud.mark.service.impl;
 
 import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.qmth.teachcloud.common.bean.dto.mark.setting.MarkGroupDto;
+import com.qmth.teachcloud.common.bean.dto.mark.setting.MarkUser;
 import com.qmth.teachcloud.common.bean.dto.mark.setting.MarkUserClassDto;
-import com.qmth.teachcloud.common.entity.MarkStudent;
+import com.qmth.teachcloud.common.bean.params.mark.setting.MarkClassUserParams;
+import com.qmth.teachcloud.common.service.MarkQuestionService;
 import com.qmth.teachcloud.common.service.MarkStudentService;
+import com.qmth.teachcloud.mark.entity.MarkGroup;
 import com.qmth.teachcloud.mark.entity.MarkUserClass;
 import com.qmth.teachcloud.mark.mapper.MarkUserClassMapper;
+import com.qmth.teachcloud.mark.service.MarkGroupService;
 import com.qmth.teachcloud.mark.service.MarkUserClassService;
-import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.qmth.teachcloud.mark.service.MarkUserGroupService;
 import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
 
 import javax.annotation.Resource;
+import java.util.ArrayList;
 import java.util.List;
+import java.util.stream.Collectors;
 
 /**
  * <p>
@@ -23,10 +32,18 @@ import java.util.List;
  */
 @Service
 public class MarkUserClassServiceImpl extends ServiceImpl<MarkUserClassMapper, MarkUserClass> implements MarkUserClassService {
+    @Resource
+    MarkUserGroupService markUserGroupService;
 
     @Resource
     MarkStudentService markStudentService;
 
+    @Resource
+    MarkGroupService markGroupService;
+
+    @Resource
+    MarkQuestionService markQuestionService;
+
     @Override
     public void deleteByExamIdAndPaperNumber(Long examId, String paperNumber) {
         UpdateWrapper<MarkUserClass> updateWrapper = new UpdateWrapper<>();
@@ -38,8 +55,67 @@ public class MarkUserClassServiceImpl extends ServiceImpl<MarkUserClassMapper, M
     @Override
     public List<MarkUserClassDto> listMarkUserClassByExamIdAndPaperNumber(Long examId, String paperNumber) {
         // 课程下所有班级数据
-//        List<String> paperNumberClassList =
+        List<String> paperNumberClassList = markStudentService.listClassByExamIdAndCourseCode(examId, paperNumber);
+        // 课程下所有分组
+        List<MarkGroup> markGroupList = markGroupService.listGroupByExamIdAndPaperNumber(examId, paperNumber);
+        List<MarkGroupDto> markGroupDtoList = markGroupList.stream().map(m -> {
+            MarkGroupDto markGroupDto = new MarkGroupDto();
+            markGroupDto.setGroupNumber(m.getNumber());
+            markGroupDto.setMarkers(markUserGroupService.listGroupUserByExamIdAndPaperNumberAndGroupNumber(examId, paperNumber, m.getNumber()));
+            markGroupDto.setGroupQuestions(markQuestionService.assembleGroupQuestionsByExamIdAndPaperNumberAndNumber(examId, paperNumber, m.getNumber()));
+            return markGroupDto;
+        }).collect(Collectors.toList());
+
+
+        List<MarkUserClassDto> markUserClassDtoList = new ArrayList<>();
+        for (String className : paperNumberClassList) {
+            for (MarkGroupDto markGroupDto : markGroupDtoList) {
+                MarkUserClassDto markUserClassDto = new MarkUserClassDto();
+                markUserClassDto.setClassName(className);
+                markUserClassDto.setGroupNumber(markGroupDto.getGroupNumber());
+                markUserClassDto.setGroupQuestions(markGroupDto.getGroupQuestions());
+                markUserClassDto.setMarkerList(markGroupDto.getMarkers());
+                // 班级+分组绑定的评卷员集合
+                markUserClassDto.setClassMarkerList(this.listClassMarkerByExamIdAndPaperNumberAndGroupNumberAndClassName(examId, paperNumber, markGroupDto.getGroupNumber(), className));
+                markUserClassDtoList.add(markUserClassDto);
+            }
+        }
+        return markUserClassDtoList;
+    }
 
-        return null;
+    @Override
+    public List<MarkUser> listClassMarkerByExamIdAndPaperNumberAndGroupNumberAndClassName(Long examId, String paperNumber, Integer groupNumber, String className) {
+        return this.baseMapper.listClassMarkerByExamIdAndPaperNumberAndGroupNumberAndClassName(examId, paperNumber, groupNumber, className);
+    }
+
+    @Transactional
+    @Override
+    public boolean saveMarkClassUser(MarkClassUserParams markClassUserParams) {
+        Long examId = markClassUserParams.getExamId();
+        String paperNumber = markClassUserParams.getPaperNumber();
+        String className = markClassUserParams.getClassName();
+        Integer groupNumber = markClassUserParams.getGroupNumber();
+        List<MarkUserClass> markUserClasses = new ArrayList<>();
+        for (MarkUser markUser : markClassUserParams.getClassMarkerList()) {
+            MarkUserClass markUserClass = new MarkUserClass();
+            markUserClass.setExamId(examId);
+            markUserClass.setPaperNumber(paperNumber);
+            markUserClass.setGroupNumber(groupNumber);
+            markUserClass.setClassName(className);
+            markUserClass.setUserId(markUser.getUserId());
+            markUserClasses.add(markUserClass);
+        }
+        this.deleteByExamIdAndPaperNumberAndGroupNumber(examId, paperNumber, groupNumber);
+        this.saveBatch(markUserClasses);
+        return true;
+    }
+
+    @Override
+    public boolean deleteByExamIdAndPaperNumberAndGroupNumber(Long examId, String paperNumber, Integer groupNumber) {
+        UpdateWrapper<MarkUserClass> updateWrapper = new UpdateWrapper<>();
+        updateWrapper.lambda().eq(MarkUserClass::getExamId, examId)
+                .eq(MarkUserClass::getPaperNumber, paperNumber)
+                .eq(MarkUserClass::getGroupNumber, groupNumber);
+        return this.remove(updateWrapper);
     }
 }

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

@@ -52,7 +52,7 @@ public class MarkUserGroupServiceImpl extends ServiceImpl<MarkUserGroupMapper, M
             }
 
             // 分组题目
-            record.setGroupQuestions(markQuestionService.getGroupQuestionsByExamIdAndPaperNumberAndNumber(record.getExamId(), record.getPaperNumber(), record.getGroupNumber()));
+            record.setGroupQuestions(markQuestionService.assembleGroupQuestionsByExamIdAndPaperNumberAndNumber(record.getExamId(), record.getPaperNumber(), record.getGroupNumber()));
         }
         return markEntranceDtoIPage;
     }

+ 19 - 0
teachcloud-mark/src/main/resources/mapper/MarkUserClassMapper.xml

@@ -11,5 +11,24 @@
         <result column="user_id" property="userId" />
         <result column="class_name" property="className" />
     </resultMap>
+    <select id="listClassMarkerByExamIdAndPaperNumberAndGroupNumberAndClassName"
+            resultType="com.qmth.teachcloud.common.bean.dto.mark.setting.MarkUser">
+        SELECT
+            su.id userId,
+            su.login_name loginName,
+            su.real_name name,
+            so.name orgName
+        FROM
+            mark_user_class muc
+                LEFT JOIN
+            sys_user su ON muc.user_id = su.id
+                LEFT JOIN
+            sys_org so ON su.org_id = so.id
+        WHERE
+            muc.exam_id = #{examId}
+          AND muc.paper_number = #{paperNumber}
+          AND muc.group_number = #{groupNumber}
+          AND muc.class_name = #{className}
+    </select>
 
 </mapper>