Browse Source

3.3.0 成绩检查-轨迹图

xiaofei 1 năm trước cách đây
mục cha
commit
ed01cdb90c
24 tập tin đã thay đổi với 605 bổ sung250 xóa
  1. 26 1
      distributed-print/src/main/java/com/qmth/distributed/print/api/mark/MarkTrackController.java
  2. 23 0
      teachcloud-mark/src/main/java/com/qmth/teachcloud/mark/dto/mark/manage/MarkerTrackDTO.java
  3. 4 16
      teachcloud-mark/src/main/java/com/qmth/teachcloud/mark/dto/mark/manage/Task.java
  4. 32 0
      teachcloud-mark/src/main/java/com/qmth/teachcloud/mark/dto/mark/score/SheetUrlDto.java
  5. 63 0
      teachcloud-mark/src/main/java/com/qmth/teachcloud/mark/dto/mark/score/StudentPaperDetailDto.java
  6. 13 3
      teachcloud-mark/src/main/java/com/qmth/teachcloud/mark/dto/mark/score/StudentScoreDetailDto.java
  7. 16 3
      teachcloud-mark/src/main/java/com/qmth/teachcloud/mark/entity/MarkStudent.java
  8. 5 0
      teachcloud-mark/src/main/java/com/qmth/teachcloud/mark/mapper/ScanPaperMapper.java
  9. 2 0
      teachcloud-mark/src/main/java/com/qmth/teachcloud/mark/service/MarkHeaderTrackService.java
  10. 12 9
      teachcloud-mark/src/main/java/com/qmth/teachcloud/mark/service/MarkStudentService.java
  11. 6 0
      teachcloud-mark/src/main/java/com/qmth/teachcloud/mark/service/MarkSubjectiveScoreService.java
  12. 1 0
      teachcloud-mark/src/main/java/com/qmth/teachcloud/mark/service/MarkTaskService.java
  13. 4 0
      teachcloud-mark/src/main/java/com/qmth/teachcloud/mark/service/MarkTrackService.java
  14. 2 0
      teachcloud-mark/src/main/java/com/qmth/teachcloud/mark/service/ScanPaperService.java
  15. 2 0
      teachcloud-mark/src/main/java/com/qmth/teachcloud/mark/service/TaskService.java
  16. 8 0
      teachcloud-mark/src/main/java/com/qmth/teachcloud/mark/service/impl/MarkHeaderTrackServiceImpl.java
  17. 212 208
      teachcloud-mark/src/main/java/com/qmth/teachcloud/mark/service/impl/MarkStudentServiceImpl.java
  18. 46 0
      teachcloud-mark/src/main/java/com/qmth/teachcloud/mark/service/impl/MarkSubjectiveScoreServiceImpl.java
  19. 8 0
      teachcloud-mark/src/main/java/com/qmth/teachcloud/mark/service/impl/MarkTaskServiceImpl.java
  20. 11 0
      teachcloud-mark/src/main/java/com/qmth/teachcloud/mark/service/impl/MarkTrackServiceImpl.java
  21. 6 0
      teachcloud-mark/src/main/java/com/qmth/teachcloud/mark/service/impl/ScanPaperServiceImpl.java
  22. 80 10
      teachcloud-mark/src/main/java/com/qmth/teachcloud/mark/service/impl/TaskServiceImpl.java
  23. 1 0
      teachcloud-mark/src/main/resources/mapper/MarkStudentMapper.xml
  24. 22 0
      teachcloud-mark/src/main/resources/mapper/ScanPaperMapper.xml

+ 26 - 1
distributed-print/src/main/java/com/qmth/distributed/print/api/mark/MarkTrackController.java

@@ -3,11 +3,21 @@ package com.qmth.distributed.print.api.mark;
 
 import com.qmth.boot.api.constant.ApiConstant;
 import com.qmth.teachcloud.common.contant.SystemConstant;
+import com.qmth.teachcloud.common.util.Result;
+import com.qmth.teachcloud.common.util.ResultUtil;
+import com.qmth.teachcloud.mark.dto.mark.manage.Task;
+import com.qmth.teachcloud.mark.service.MarkTrackService;
+import com.qmth.teachcloud.mark.service.TaskService;
 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 javax.annotation.Resource;
+
 /**
  * <p>
  * 轨迹给分表 前端控制器
@@ -21,4 +31,19 @@ import org.springframework.web.bind.annotation.RestController;
 @RequestMapping(ApiConstant.DEFAULT_URI_PREFIX + SystemConstant.PREFIX_URL_MARK + "/track")
 public class MarkTrackController {
 
+    @Resource
+    private MarkTrackService markTrackService;
+    @Resource
+    private TaskService taskService;
+
+    /**
+     * 轨迹图
+     */
+    @ApiOperation(value = "轨迹图")
+    @RequestMapping(value = "/getTask", method = RequestMethod.POST)
+    public Result listStudentScore(@ApiParam(value = "考生ID", required = true) @RequestParam Long studentId) {
+        Task task = taskService.build(studentId);
+        return ResultUtil.ok(task);
+    }
+
 }

+ 23 - 0
teachcloud-mark/src/main/java/com/qmth/teachcloud/mark/dto/mark/manage/MarkerTrackDTO.java

@@ -0,0 +1,23 @@
+package com.qmth.teachcloud.mark.dto.mark.manage;
+
+import com.qmth.teachcloud.mark.entity.MarkTrack;
+
+public class MarkerTrackDTO extends TrackDTO {
+
+    private static final long serialVersionUID = -7010285593473357594L;
+
+    private Long userId;
+
+    public MarkerTrackDTO(MarkTrack track) {
+        super(track);
+        this.userId = track.getUserId();
+    }
+
+    public Long getUserId() {
+        return userId;
+    }
+
+    public void setUserId(Long userId) {
+        this.userId = userId;
+    }
+}

+ 4 - 16
teachcloud-mark/src/main/java/com/qmth/teachcloud/mark/dto/mark/manage/Task.java

@@ -1,5 +1,6 @@
 package com.qmth.teachcloud.mark.dto.mark.manage;
 
+import com.qmth.teachcloud.mark.dto.mark.score.SheetUrlDto;
 import com.qmth.teachcloud.mark.entity.MarkPaper;
 
 import java.io.Serializable;
@@ -35,11 +36,6 @@ public class Task implements Serializable {
      */
     private String studentCode;
 
-    /**
-     * 准考证号
-     */
-    private String examNumber;
-
     /**
      * 科目
      */
@@ -68,7 +64,7 @@ public class Task implements Serializable {
     /**
      * 题卡原图地址
      */
-    private List<String> sheetUrls;
+    private List<SheetUrlDto> sheetUrls;
 
     /**
      * 客观题总分
@@ -155,14 +151,6 @@ public class Task implements Serializable {
         this.studentCode = studentCode;
     }
 
-    public String getExamNumber() {
-        return examNumber;
-    }
-
-    public void setExamNumber(String examNumber) {
-        this.examNumber = examNumber;
-    }
-
     public MarkPaper getMarkPaper() {
         return markPaper;
     }
@@ -187,11 +175,11 @@ public class Task implements Serializable {
         this.questionList = questionList;
     }
 
-    public List<String> getSheetUrls() {
+    public List<SheetUrlDto> getSheetUrls() {
         return sheetUrls;
     }
 
-    public void setSheetUrls(List<String> sheetUrls) {
+    public void setSheetUrls(List<SheetUrlDto> sheetUrls) {
         this.sheetUrls = sheetUrls;
     }
 

+ 32 - 0
teachcloud-mark/src/main/java/com/qmth/teachcloud/mark/dto/mark/score/SheetUrlDto.java

@@ -0,0 +1,32 @@
+package com.qmth.teachcloud.mark.dto.mark.score;
+
+public class SheetUrlDto {
+
+    private int index;
+
+    private String url;
+
+    public SheetUrlDto() {
+    }
+
+    public SheetUrlDto(int index, String url) {
+        this.index = index;
+        this.url = url;
+    }
+
+    public int getIndex() {
+        return index;
+    }
+
+    public void setIndex(int index) {
+        this.index = index;
+    }
+
+    public String getUrl() {
+        return url;
+    }
+
+    public void setUrl(String url) {
+        this.url = url;
+    }
+}

+ 63 - 0
teachcloud-mark/src/main/java/com/qmth/teachcloud/mark/dto/mark/score/StudentPaperDetailDto.java

@@ -0,0 +1,63 @@
+package com.qmth.teachcloud.mark.dto.mark.score;
+
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
+
+public class StudentPaperDetailDto {
+
+    @JsonSerialize(using = ToStringSerializer.class)
+    private Long studentId;
+    private Integer paperIndex;
+    private Long paperId;
+    private Integer cardNumber;
+    private Integer pageIndex;
+    private String sheetPath;
+
+    public Long getStudentId() {
+        return studentId;
+    }
+
+    public void setStudentId(Long studentId) {
+        this.studentId = studentId;
+    }
+
+    public Integer getPaperIndex() {
+        return paperIndex;
+    }
+
+    public void setPaperIndex(Integer paperIndex) {
+        this.paperIndex = paperIndex;
+    }
+
+    public Long getPaperId() {
+        return paperId;
+    }
+
+    public void setPaperId(Long paperId) {
+        this.paperId = paperId;
+    }
+
+    public Integer getCardNumber() {
+        return cardNumber;
+    }
+
+    public void setCardNumber(Integer cardNumber) {
+        this.cardNumber = cardNumber;
+    }
+
+    public Integer getPageIndex() {
+        return pageIndex;
+    }
+
+    public void setPageIndex(Integer pageIndex) {
+        this.pageIndex = pageIndex;
+    }
+
+    public String getSheetPath() {
+        return sheetPath;
+    }
+
+    public void setSheetPath(String sheetPath) {
+        this.sheetPath = sheetPath;
+    }
+}

+ 13 - 3
teachcloud-mark/src/main/java/com/qmth/teachcloud/mark/dto/mark/score/StudentScoreDetailDto.java

@@ -7,6 +7,8 @@ import java.util.List;
 
 public class StudentScoreDetailDto {
 
+    @JsonSerialize(using = ToStringSerializer.class)
+    private Long studentId;
     @JsonSerialize(using = ToStringSerializer.class)
     private Long examId;
     private String courseCode;
@@ -25,7 +27,15 @@ public class StudentScoreDetailDto {
     private String checkUserLoginName;
     private String checkUserName;
     private Long checkTime;
-    private List<String> sheetUrls;
+    private List<SheetUrlDto> sheetUrls;
+
+    public Long getStudentId() {
+        return studentId;
+    }
+
+    public void setStudentId(Long studentId) {
+        this.studentId = studentId;
+    }
 
     public Long getExamId() {
         return examId;
@@ -163,11 +173,11 @@ public class StudentScoreDetailDto {
         this.checkTime = checkTime;
     }
 
-    public List<String> getSheetUrls() {
+    public List<SheetUrlDto> getSheetUrls() {
         return sheetUrls;
     }
 
-    public void setSheetUrls(List<String> sheetUrls) {
+    public void setSheetUrls(List<SheetUrlDto> sheetUrls) {
         this.sheetUrls = sheetUrls;
     }
 }

+ 16 - 3
teachcloud-mark/src/main/java/com/qmth/teachcloud/mark/entity/MarkStudent.java

@@ -5,7 +5,9 @@ import com.baomidou.mybatisplus.annotation.TableName;
 import com.fasterxml.jackson.databind.annotation.JsonSerialize;
 import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
 import com.qmth.teachcloud.common.enums.ScanStatus;
+import com.qmth.teachcloud.common.enums.mark.SubjectiveStatus;
 import com.qmth.teachcloud.mark.dto.mark.ScoreItem;
+import com.qmth.teachcloud.mark.utils.BigDecimalUtils;
 import io.swagger.annotations.ApiModel;
 import io.swagger.annotations.ApiModelProperty;
 import org.apache.commons.lang3.StringUtils;
@@ -107,7 +109,7 @@ public class MarkStudent implements Serializable {
     private String objectiveScoreList;
 
     @ApiModelProperty(value = "主观题状态")
-    private String subjectiveStatus;
+    private SubjectiveStatus subjectiveStatus;
 
     @ApiModelProperty(value = "主观总分")
     private Double subjectiveScore;
@@ -356,11 +358,11 @@ public class MarkStudent implements Serializable {
         this.objectiveScoreList = objectiveScoreList;
     }
 
-    public String getSubjectiveStatus() {
+    public SubjectiveStatus getSubjectiveStatus() {
         return subjectiveStatus;
     }
 
-    public void setSubjectiveStatus(String subjectiveStatus) {
+    public void setSubjectiveStatus(SubjectiveStatus subjectiveStatus) {
         this.subjectiveStatus = subjectiveStatus;
     }
 
@@ -494,6 +496,17 @@ public class MarkStudent implements Serializable {
 		this.coursePaperId = coursePaperId;
 	}
 
+    public double getTotalScore() {
+        double score = 0;
+        if (objectiveScore != null) {
+            score = BigDecimalUtils.add(score, objectiveScore);
+        }
+        if (subjectiveScore != null) {
+            score = BigDecimalUtils.add(score, subjectiveScore);
+        }
+        return score;
+    }
+
 	@Override
     public String toString() {
         return "MarkStudent{" +

+ 5 - 0
teachcloud-mark/src/main/java/com/qmth/teachcloud/mark/mapper/ScanPaperMapper.java

@@ -1,7 +1,11 @@
 package com.qmth.teachcloud.mark.mapper;
 
+import com.qmth.teachcloud.mark.dto.mark.score.StudentPaperDetailDto;
 import com.qmth.teachcloud.mark.entity.ScanPaper;
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
 
 /**
  * <p>
@@ -13,4 +17,5 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper;
  */
 public interface ScanPaperMapper extends BaseMapper<ScanPaper> {
 
+    List<StudentPaperDetailDto> listStudentPaperDetail(@Param("studentId") Long studentId);
 }

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

@@ -17,6 +17,8 @@ public interface MarkHeaderTrackService extends IService<MarkHeaderTrack> {
 
     List<MarkHeaderTrack> listByExamAndPaperNumberAndGroupNumberAndStudentId(Long examId, String paperNumber, Integer groupNumber, Long studentId);
 
+    List<MarkHeaderTrack> listByStudentIdAndQuestionNumber(Long studentId, String questionNumber);
+
     void deleteByExamIdAndPaperNumberAndGroupNumberAndStudentId(Long examId, String paperNumber, Integer groupNumber, Long studentId);
 
 }

+ 12 - 9
teachcloud-mark/src/main/java/com/qmth/teachcloud/mark/service/MarkStudentService.java

@@ -10,6 +10,7 @@ import com.qmth.teachcloud.common.entity.BasicExam;
 import com.qmth.teachcloud.common.enums.mark.SubjectiveStatus;
 import com.qmth.teachcloud.mark.bean.scanexaminfo.ScanExamCheckInfoVo;
 import com.qmth.teachcloud.mark.bean.scanexaminfo.ScanExamInfoVo;
+import com.qmth.teachcloud.mark.dto.mark.score.SheetUrlDto;
 import com.qmth.teachcloud.mark.dto.mark.score.StudentScoreDetailDto;
 import com.qmth.teachcloud.mark.entity.MarkStudent;
 
@@ -27,18 +28,20 @@ public interface MarkStudentService extends IService<MarkStudent> {
 
     void updateSubjectiveStatusAndScore(Long studentId, SubjectiveStatus status, Double score, String scoreList);
 
-	ScanExamInfoVo getScanExamInfo(BasicExam exam);
+    ScanExamInfoVo getScanExamInfo(BasicExam exam);
 
     IPage<StudentScoreDetailDto> pageStudentScore(Long examId, String paperNumber, String college, String className, String teacher, Integer filter, Boolean absent, Boolean breach, Double startScore, Double endScore, Double subScore, Integer objectiveScoreRateLt, String studentName, String studentCode, Integer pageNumber, Integer pageSize);
 
-	ScanExamCheckInfoVo checkInfo(BasicExam exam);
+    List<SheetUrlDto> buildSheetUrls(Long studentId);
+
+    ScanExamCheckInfoVo checkInfo(BasicExam exam);
+
+    /**
+     * 根据考生当前绑定的paper刷新考生状态,需要在外部调用处对考生上锁
+     */
+    void updateStudentByPaper(@NotNull Long userId, @NotNull Long studentId, @NotNull boolean updateOmrTask);
+
+    MarkStudent findByExamIdAndCoursePaperIdAndStudentCode(Long examId, String coursePaperId, String studentCode);
 
-	/**
-	 * 根据考生当前绑定的paper刷新考生状态,需要在外部调用处对考生上锁
-	 *
-	 * @param id
-	 */
-	void updateStudentByPaper(@NotNull Long userId, @NotNull Long studentId, @NotNull boolean updateOmrTask);
 
-	MarkStudent findByExamIdAndCoursePaperIdAndStudentCode(Long examId, String coursePaperId, String studentCode);
 }

+ 6 - 0
teachcloud-mark/src/main/java/com/qmth/teachcloud/mark/service/MarkSubjectiveScoreService.java

@@ -4,6 +4,7 @@ import com.qmth.teachcloud.mark.entity.MarkSubjectiveScore;
 import com.baomidou.mybatisplus.extension.service.IService;
 
 import java.util.List;
+import java.util.Set;
 
 /**
  * <p>
@@ -16,4 +17,9 @@ import java.util.List;
 public interface MarkSubjectiveScoreService extends IService<MarkSubjectiveScore> {
 
     List<MarkSubjectiveScore> listByStudentIdAndGroupNumber(Long studentId, Integer groupNumber);
+
+    Set<Integer> listMainNumberByStudentIdAndUncalculate(Long studentId, boolean uncalculate);
+
+    List<MarkSubjectiveScore> listByStudentIdAndUncalculate(Long studentId, boolean uncalculate);
+
 }

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

@@ -42,6 +42,7 @@ public interface MarkTaskService extends IService<MarkTask> {
     MarkTask getLastOneByUserIdAndStatus(Long examId, String paperNumber, Integer groupNumber, Long userId, MarkTaskStatus status);
 
     List<MarkTask> listByExamIdAndPaperNumberAndGroupNumberAndStudentId(Long examId, String paperNumber, Integer groupNumber, Long studentId);
+    List<MarkTask> listByStudentIdAndGroupNumber(Long studentId, Integer groupNumber);
 
     void updateHeaderResult(Long examId, String paperNumber, Integer groupNumber, Long studentId, Long updateUserId, Double totalScore, String scoreList, Long updateTime, MarkTaskStatus arbitrated);
 }

+ 4 - 0
teachcloud-mark/src/main/java/com/qmth/teachcloud/mark/service/MarkTrackService.java

@@ -3,6 +3,8 @@ package com.qmth.teachcloud.mark.service;
 import com.qmth.teachcloud.mark.entity.MarkTrack;
 import com.baomidou.mybatisplus.extension.service.IService;
 
+import java.util.List;
+
 /**
  * <p>
  * 轨迹给分表 服务类
@@ -14,4 +16,6 @@ import com.baomidou.mybatisplus.extension.service.IService;
 public interface MarkTrackService extends IService<MarkTrack> {
 
     void deleteByTaskId(Long taskId);
+
+    List<MarkTrack> listByTaskIdAndQuestionNumber(Long taskId, String questionNumber);
 }

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

@@ -1,5 +1,6 @@
 package com.qmth.teachcloud.mark.service;
 
+import com.qmth.teachcloud.mark.dto.mark.score.StudentPaperDetailDto;
 import com.qmth.teachcloud.mark.entity.ScanPaper;
 import com.qmth.teachcloud.mark.entity.ScanPaperPage;
 
@@ -21,4 +22,5 @@ public interface ScanPaperService extends IService<ScanPaper> {
 
 	int getAssignedCount(Long examId, Boolean checked);
 
+    List<StudentPaperDetailDto> listStudentPaperDetail(Long studentId);
 }

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

@@ -6,4 +6,6 @@ import com.qmth.teachcloud.mark.entity.MarkGroup;
 
 public interface TaskService {
     Task build(MarkArbitrateHistory markArbitrateHistory, MarkGroup markGroup);
+
+    Task build(Long studentId);
 }

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

@@ -31,6 +31,14 @@ public class MarkHeaderTrackServiceImpl extends ServiceImpl<MarkHeaderTrackMappe
         return this.list(queryWrapper);
     }
 
+    @Override
+    public List<MarkHeaderTrack> listByStudentIdAndQuestionNumber(Long studentId, String questionNumber) {
+        QueryWrapper<MarkHeaderTrack> queryWrapper = new QueryWrapper<>();
+        queryWrapper.lambda().eq(MarkHeaderTrack::getStudentId, studentId)
+                .eq(MarkHeaderTrack::getQuestionNumber, questionNumber);
+        return this.list(queryWrapper);
+    }
+
     @Override
     public void deleteByExamIdAndPaperNumberAndGroupNumberAndStudentId(Long examId, String paperNumber, Integer groupNumber, Long studentId) {
         UpdateWrapper<MarkHeaderTrack> updateWrapper = new UpdateWrapper<>();

+ 212 - 208
teachcloud-mark/src/main/java/com/qmth/teachcloud/mark/service/impl/MarkStudentServiceImpl.java

@@ -1,18 +1,5 @@
 package com.qmth.teachcloud.mark.service.impl;
 
-import java.text.DecimalFormat;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.stream.Collectors;
-
-import javax.validation.constraints.NotNull;
-
-import org.apache.commons.collections4.CollectionUtils;
-import org.apache.commons.lang3.StringUtils;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Service;
-import org.springframework.transaction.annotation.Transactional;
-
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
@@ -25,26 +12,29 @@ import com.qmth.teachcloud.common.enums.ExceptionResultEnum;
 import com.qmth.teachcloud.common.enums.ScanStatus;
 import com.qmth.teachcloud.common.enums.mark.SubjectiveStatus;
 import com.qmth.teachcloud.common.enums.scan.ConditionType;
+import com.qmth.teachcloud.common.service.TeachcloudCommonService;
 import com.qmth.teachcloud.mark.bean.scanexaminfo.CheckTask;
 import com.qmth.teachcloud.mark.bean.scanexaminfo.ScanExamCheckInfoVo;
 import com.qmth.teachcloud.mark.bean.scanexaminfo.ScanExamInfoVo;
+import com.qmth.teachcloud.mark.dto.mark.score.SheetUrlDto;
+import com.qmth.teachcloud.mark.dto.mark.score.StudentPaperDetailDto;
 import com.qmth.teachcloud.mark.dto.mark.score.StudentScoreDetailDto;
-import com.qmth.teachcloud.mark.entity.MarkPaper;
-import com.qmth.teachcloud.mark.entity.MarkStudent;
-import com.qmth.teachcloud.mark.entity.ScanAnswerCard;
-import com.qmth.teachcloud.mark.entity.ScanPaper;
-import com.qmth.teachcloud.mark.entity.ScanPaperPage;
-import com.qmth.teachcloud.mark.entity.ScanStudentPaper;
+import com.qmth.teachcloud.mark.entity.*;
 import com.qmth.teachcloud.mark.enums.OmrTaskStatus;
 import com.qmth.teachcloud.mark.mapper.MarkStudentMapper;
-import com.qmth.teachcloud.mark.service.MarkPaperService;
-import com.qmth.teachcloud.mark.service.MarkStudentService;
-import com.qmth.teachcloud.mark.service.ScanAnswerCardService;
-import com.qmth.teachcloud.mark.service.ScanOmrTaskService;
-import com.qmth.teachcloud.mark.service.ScanPackageService;
-import com.qmth.teachcloud.mark.service.ScanPaperPageService;
-import com.qmth.teachcloud.mark.service.ScanPaperService;
-import com.qmth.teachcloud.mark.service.ScanStudentPaperService;
+import com.qmth.teachcloud.mark.service.*;
+import org.apache.commons.collections4.CollectionUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import javax.annotation.Resource;
+import javax.validation.constraints.NotNull;
+import java.text.DecimalFormat;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.stream.Collectors;
 
 /**
  * <p>
@@ -56,188 +46,202 @@ import com.qmth.teachcloud.mark.service.ScanStudentPaperService;
  */
 @Service
 public class MarkStudentServiceImpl extends ServiceImpl<MarkStudentMapper, MarkStudent> implements MarkStudentService {
-	@Autowired
-	private MarkPaperService markPaperService;
-	@Autowired
-	private ScanPackageService scanPackageService;
-	@Autowired
-	private ScanPaperService scanPaperService;
-	@Autowired
-	private ScanPaperPageService scanPaperPageService;
-	@Autowired
-	private ScanOmrTaskService scanOmrTaskService;
-	@Autowired
-	private ScanAnswerCardService answerCardService;
-	@Autowired
-	private ScanStudentPaperService studentPaperService;
-
-	@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;
-	}
-
-	@Override
-	public void updateSubjectiveStatusAndScore(Long studentId, SubjectiveStatus status, Double score,
-			String scoreList) {
-		UpdateWrapper<MarkStudent> updateWrapper = new UpdateWrapper<>();
-		updateWrapper.lambda().set(MarkStudent::getSubjectiveStatus, status).set(MarkStudent::getSubjectiveScore, score)
-				.set(MarkStudent::getSubjectiveScoreList, scoreList).eq(MarkStudent::getId, studentId);
-		this.update(updateWrapper);
-	}
-
-	@Override
-	public ScanExamInfoVo getScanExamInfo(BasicExam exam) {
-		ScanExamInfoVo vo = new ScanExamInfoVo();
-		vo.setId(exam.getId());
-		vo.setName(exam.getName());
-		vo.getAnswerScan().setCourseCount(markPaperService.getCountByExam(exam.getId()));
-		vo.getAnswerScan().setTotalCount(getCount(exam.getId(), null));
-		vo.getAnswerScan().setScannedCount(getCount(exam.getId(), ScanStatus.SCANNED));
-		vo.getPackageScan().setScannedCount(scanPackageService.getCount(exam.getId()));
-		return vo;
-	}
-
-	@Override
-	public IPage<StudentScoreDetailDto> pageStudentScore(Long examId, String paperNumber, String college,
-			String className, String teacher, Integer filter, Boolean absent, Boolean breach, Double startScore,
-			Double endScore, Double subScore, Integer objectiveScoreRateLt, String studentName, String studentCode,
-			Integer pageNumber, Integer pageSize) {
-		if (startScore != null && endScore == null) {
-			throw ExceptionResultEnum.ERROR.exception("请输入结束分数值");
-		}
-		Page<StudentScoreDetailDto> page = new Page<>(pageNumber, pageSize);
-		MarkPaper markPaper = markPaperService.getByExamIdAndPaperNumber(examId, paperNumber);
-		Double objectiveScoreLt = objectiveScoreRateLt == null ? null
-				: Double.parseDouble(new DecimalFormat("####.###")
-						.format(markPaper.getObjectiveScore() * objectiveScoreRateLt / 100));
-		IPage<StudentScoreDetailDto> studentScoreDetailDtoIPage = this.baseMapper.pageStudentScore(page, examId,
-				paperNumber, college, className, teacher, filter, absent, breach, startScore, endScore, subScore,
-				objectiveScoreLt, studentName, studentCode);
-		for (StudentScoreDetailDto scoreDetailDto : studentScoreDetailDtoIPage.getRecords()) {
-			// 原图
-		}
-		return studentScoreDetailDtoIPage;
-	}
-
-	private int getCount(Long examId, ScanStatus status) {
-		QueryWrapper<MarkStudent> wrapper = new QueryWrapper<>();
-		LambdaQueryWrapper<MarkStudent> lw = wrapper.lambda();
-		lw.eq(MarkStudent::getExamId, examId);
-		if (status != null) {
-			lw.eq(MarkStudent::getScanStatus, status);
-		}
-		return baseMapper.selectCount(wrapper);
-	}
-
-	private int getOmrAbsentCount(Long examId, Boolean checked) {
-		QueryWrapper<MarkStudent> wrapper = new QueryWrapper<>();
-		LambdaQueryWrapper<MarkStudent> lw = wrapper.lambda();
-		lw.eq(MarkStudent::getExamId, examId);
-		lw.eq(MarkStudent::getOmrAbsent, true);
-		if (checked != null) {
-			lw.eq(MarkStudent::getOmrAbsentChecked, checked);
-		}
-		return baseMapper.selectCount(wrapper);
-	}
-
-	private int getIncompleteCount(Long examId) {
-		QueryWrapper<MarkStudent> wrapper = new QueryWrapper<>();
-		LambdaQueryWrapper<MarkStudent> lw = wrapper.lambda();
-		lw.eq(MarkStudent::getExamId, examId);
-		lw.eq(MarkStudent::getIncomplete, true);
-		return baseMapper.selectCount(wrapper);
-	}
-
-	@Override
-	public ScanExamCheckInfoVo checkInfo(BasicExam exam) {
-		Long examId = exam.getId();
-		ScanExamCheckInfoVo vo = new ScanExamCheckInfoVo();
-		vo.setId(exam.getId());
-		vo.setName(exam.getName());
-		CheckTask ct = vo.getCheckTask();
-		ct.setUnexistCount(getCount(examId, ScanStatus.UNEXIST));
-		ct.setUnexistCheckedCount(getCount(examId, ScanStatus.MANUAL_ABSENT));
-		ct.setAssignedCount(scanPaperService.getAssignedCount(examId, false));
-		ct.setAssignedCheckedCount(scanPaperService.getAssignedCount(examId, true));
-		ct.setAbsentCheckCount(getOmrAbsentCount(examId, false));
-		ct.setAbsentCheckedCount(getOmrAbsentCount(examId, true));
-		ct.setObjectiveCheckCount(scanOmrTaskService.getCount(examId, OmrTaskStatus.WAITING));
-		ct.setObjectiveCheckedCount(scanOmrTaskService.getCount(examId, OmrTaskStatus.PROCESSED));
-		ct.setIncompleteCount(getIncompleteCount(examId));
-		return vo;
-	}
-
-	/**
-	 * 根据考生当前绑定的paper刷新考生状态,需要在外部调用处对考生上锁
-	 *
-	 * @param id
-	 */
-	@Override
-	@Transactional
-	public void updateStudentByPaper(@NotNull Long userId, @NotNull Long studentId, @NotNull boolean updateOmrTask) {
-		MarkStudent student = this.getById(studentId);
-		if (student == null) {
-			throw new ParameterException("找不到对应的考生");
-		}
-		// 重置状态
-		student.setIncomplete(false);
-		student.setAssigned(false);
-		student.setQuestionFilled(false);
-		student.setOmrAbsent(false);
-		int paperCount = 0;
-		List<ScanStudentPaper> studentPaperList = studentPaperService.findByStudentId(studentId);
-		for (ScanStudentPaper studentPaper : studentPaperList) {
-			paperCount++;
-			// 获取paper详情更新考生状态
-			ScanPaper paper = scanPaperService.getById(studentPaper.getPaperId());
-			student.setAssigned(student.getAssigned() || paper.getAssigned());
-			student.setQuestionFilled(student.getQuestionFilled() || paper.getQuestionFilled());
-			student.setCardNumber(paper.getCardNumber());
-			// 单独判断首张纸正面的识别结果
-			if (studentPaper.getPaperIndex() == 1) {
-				// 根据识别结果更新考生属性
-				ScanPaperPage page = scanPaperPageService.findPaperIdAndIndex(paper.getId(), 1);
-				student.setOmrAbsent(page.getAbsent() == null ? false : page.getAbsent().getResult());
+    @Autowired
+    private MarkPaperService markPaperService;
+    @Autowired
+    private ScanPackageService scanPackageService;
+    @Autowired
+    private ScanPaperService scanPaperService;
+    @Autowired
+    private ScanPaperPageService scanPaperPageService;
+    @Autowired
+    private ScanOmrTaskService scanOmrTaskService;
+    @Autowired
+    private ScanAnswerCardService answerCardService;
+    @Autowired
+    private ScanStudentPaperService studentPaperService;
+    @Resource
+    private TeachcloudCommonService teachcloudCommonService;
+
+    @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;
+    }
+
+    @Override
+    public void updateSubjectiveStatusAndScore(Long studentId, SubjectiveStatus status, Double score,
+                                               String scoreList) {
+        UpdateWrapper<MarkStudent> updateWrapper = new UpdateWrapper<>();
+        updateWrapper.lambda().set(MarkStudent::getSubjectiveStatus, status).set(MarkStudent::getSubjectiveScore, score)
+                .set(MarkStudent::getSubjectiveScoreList, scoreList).eq(MarkStudent::getId, studentId);
+        this.update(updateWrapper);
+    }
+
+    @Override
+    public ScanExamInfoVo getScanExamInfo(BasicExam exam) {
+        ScanExamInfoVo vo = new ScanExamInfoVo();
+        vo.setId(exam.getId());
+        vo.setName(exam.getName());
+        vo.getAnswerScan().setCourseCount(markPaperService.getCountByExam(exam.getId()));
+        vo.getAnswerScan().setTotalCount(getCount(exam.getId(), null));
+        vo.getAnswerScan().setScannedCount(getCount(exam.getId(), ScanStatus.SCANNED));
+        vo.getPackageScan().setScannedCount(scanPackageService.getCount(exam.getId()));
+        return vo;
+    }
+
+    @Override
+    public IPage<StudentScoreDetailDto> pageStudentScore(Long examId, String paperNumber, String college,
+                                                         String className, String teacher, Integer filter, Boolean absent, Boolean breach, Double startScore,
+                                                         Double endScore, Double subScore, Integer objectiveScoreRateLt, String studentName, String studentCode,
+                                                         Integer pageNumber, Integer pageSize) {
+        if (startScore != null && endScore == null) {
+            throw ExceptionResultEnum.ERROR.exception("请输入结束分数值");
+        }
+        Page<StudentScoreDetailDto> page = new Page<>(pageNumber, pageSize);
+        MarkPaper markPaper = markPaperService.getByExamIdAndPaperNumber(examId, paperNumber);
+        Double objectiveScoreLt = objectiveScoreRateLt == null ? null
+                : Double.parseDouble(new DecimalFormat("####.###")
+                .format(markPaper.getObjectiveScore() * objectiveScoreRateLt / 100));
+        IPage<StudentScoreDetailDto> studentScoreDetailDtoIPage = this.baseMapper.pageStudentScore(page, examId,
+                paperNumber, college, className, teacher, filter, absent, breach, startScore, endScore, subScore,
+                objectiveScoreLt, studentName, studentCode);
+        for (StudentScoreDetailDto scoreDetailDto : studentScoreDetailDtoIPage.getRecords()) {
+            // 原图
+            scoreDetailDto.setSheetUrls(buildSheetUrls(scoreDetailDto.getStudentId()));
+
+        }
+        return studentScoreDetailDtoIPage;
+    }
+
+    @Override
+    public List<SheetUrlDto> buildSheetUrls(Long studentId) {
+        // 原图
+        List<SheetUrlDto> sheetUrls = new ArrayList<>();
+        List<StudentPaperDetailDto> studentPaperDetailDtoList = scanPaperService.listStudentPaperDetail(studentId);
+        for (int i = 0; i < studentPaperDetailDtoList.size(); i++) {
+            StudentPaperDetailDto studentPaperDetailDto = studentPaperDetailDtoList.get(i);
+            sheetUrls.add(new SheetUrlDto(2 * (studentPaperDetailDto.getPaperIndex() - 1) + studentPaperDetailDto.getPageIndex(), teachcloudCommonService.filePreview(studentPaperDetailDto.getSheetPath())));
+        }
+        return sheetUrls;
+    }
+
+    private int getCount(Long examId, ScanStatus status) {
+        QueryWrapper<MarkStudent> wrapper = new QueryWrapper<>();
+        LambdaQueryWrapper<MarkStudent> lw = wrapper.lambda();
+        lw.eq(MarkStudent::getExamId, examId);
+        if (status != null) {
+            lw.eq(MarkStudent::getScanStatus, status);
+        }
+        return baseMapper.selectCount(wrapper);
+    }
+
+    private int getOmrAbsentCount(Long examId, Boolean checked) {
+        QueryWrapper<MarkStudent> wrapper = new QueryWrapper<>();
+        LambdaQueryWrapper<MarkStudent> lw = wrapper.lambda();
+        lw.eq(MarkStudent::getExamId, examId);
+        lw.eq(MarkStudent::getOmrAbsent, true);
+        if (checked != null) {
+            lw.eq(MarkStudent::getOmrAbsentChecked, checked);
+        }
+        return baseMapper.selectCount(wrapper);
+    }
+
+    private int getIncompleteCount(Long examId) {
+        QueryWrapper<MarkStudent> wrapper = new QueryWrapper<>();
+        LambdaQueryWrapper<MarkStudent> lw = wrapper.lambda();
+        lw.eq(MarkStudent::getExamId, examId);
+        lw.eq(MarkStudent::getIncomplete, true);
+        return baseMapper.selectCount(wrapper);
+    }
+
+    @Override
+    public ScanExamCheckInfoVo checkInfo(BasicExam exam) {
+        Long examId = exam.getId();
+        ScanExamCheckInfoVo vo = new ScanExamCheckInfoVo();
+        vo.setId(exam.getId());
+        vo.setName(exam.getName());
+        CheckTask ct = vo.getCheckTask();
+        ct.setUnexistCount(getCount(examId, ScanStatus.UNEXIST));
+        ct.setUnexistCheckedCount(getCount(examId, ScanStatus.MANUAL_ABSENT));
+        ct.setAssignedCount(scanPaperService.getAssignedCount(examId, false));
+        ct.setAssignedCheckedCount(scanPaperService.getAssignedCount(examId, true));
+        ct.setAbsentCheckCount(getOmrAbsentCount(examId, false));
+        ct.setAbsentCheckedCount(getOmrAbsentCount(examId, true));
+        ct.setObjectiveCheckCount(scanOmrTaskService.getCount(examId, OmrTaskStatus.WAITING));
+        ct.setObjectiveCheckedCount(scanOmrTaskService.getCount(examId, OmrTaskStatus.PROCESSED));
+        ct.setIncompleteCount(getIncompleteCount(examId));
+        return vo;
+    }
+
+    /**
+     * 根据考生当前绑定的paper刷新考生状态,需要在外部调用处对考生上锁
+     */
+    @Override
+    @Transactional
+    public void updateStudentByPaper(@NotNull Long userId, @NotNull Long studentId, @NotNull boolean updateOmrTask) {
+        MarkStudent student = this.getById(studentId);
+        if (student == null) {
+            throw new ParameterException("找不到对应的考生");
+        }
+        // 重置状态
+        student.setIncomplete(false);
+        student.setAssigned(false);
+        student.setQuestionFilled(false);
+        student.setOmrAbsent(false);
+        int paperCount = 0;
+        List<ScanStudentPaper> studentPaperList = studentPaperService.findByStudentId(studentId);
+        for (ScanStudentPaper studentPaper : studentPaperList) {
+            paperCount++;
+            // 获取paper详情更新考生状态
+            ScanPaper paper = scanPaperService.getById(studentPaper.getPaperId());
+            student.setAssigned(student.getAssigned() || paper.getAssigned());
+            student.setQuestionFilled(student.getQuestionFilled() || paper.getQuestionFilled());
+            student.setCardNumber(paper.getCardNumber());
+            // 单独判断首张纸正面的识别结果
+            if (studentPaper.getPaperIndex() == 1) {
+                // 根据识别结果更新考生属性
+                ScanPaperPage page = scanPaperPageService.findPaperIdAndIndex(paper.getId(), 1);
+                student.setOmrAbsent(page.getAbsent() == null ? false : page.getAbsent().getResult());
 //                student.setDevice(batchService.findByPaperId(paper.getId()).getDevice());
-			}
-		}
-		// 更新考生状态
-		if (paperCount > 0) {
-			ScanAnswerCard answerCard = answerCardService.findByExamAndNumber(student.getExamId(),
-					student.getCardNumber());
-			student.setIncomplete(paperCount != answerCard.getPaperCount());
-			student.setScanStatus(ScanStatus.SCANNED);
-		} else {
-			student.setScanStatus(ScanStatus.UNEXIST);
-		}
+            }
+        }
+        // 更新考生状态
+        if (paperCount > 0) {
+            ScanAnswerCard answerCard = answerCardService.findByExamAndNumber(student.getExamId(),
+                    student.getCardNumber());
+            student.setIncomplete(paperCount != answerCard.getPaperCount());
+            student.setScanStatus(ScanStatus.SCANNED);
+        } else {
+            student.setScanStatus(ScanStatus.UNEXIST);
+        }
 //        student.setUpdaterId(userId);
 //        student.setUpdateTime(System.currentTimeMillis());
-		this.saveOrUpdate(student);
-		if (updateOmrTask) {
-			// 清除识别对照任务
-			scanOmrTaskService.deleteByStudentId(student.getExamId(), student.getId());
-			// 重新生成识别对照任务
-			scanOmrTaskService.buildTask(ConditionType.FILL_SUSPECT, student.getId());
-		}
-	}
-
-	@Override
-	public MarkStudent findByExamIdAndCoursePaperIdAndStudentCode(Long examId, String coursePaperId,
-			String studentCode) {
-		QueryWrapper<MarkStudent> wrapper = new QueryWrapper<>();
-		LambdaQueryWrapper<MarkStudent> lw = wrapper.lambda();
-		lw.eq(MarkStudent::getExamId, examId);
-		lw.eq(MarkStudent::getCoursePaperId, coursePaperId);
-		lw.eq(MarkStudent::getStudentCode, studentCode);
-		return baseMapper.selectOne(wrapper);
-	}
+        this.saveOrUpdate(student);
+        if (updateOmrTask) {
+            // 清除识别对照任务
+            scanOmrTaskService.deleteByStudentId(student.getExamId(), student.getId());
+            // 重新生成识别对照任务
+            scanOmrTaskService.buildTask(ConditionType.FILL_SUSPECT, student.getId());
+        }
+    }
+
+    @Override
+    public MarkStudent findByExamIdAndCoursePaperIdAndStudentCode(Long examId, String coursePaperId,
+                                                                  String studentCode) {
+        QueryWrapper<MarkStudent> wrapper = new QueryWrapper<>();
+        LambdaQueryWrapper<MarkStudent> lw = wrapper.lambda();
+        lw.eq(MarkStudent::getExamId, examId);
+        lw.eq(MarkStudent::getCoursePaperId, coursePaperId);
+        lw.eq(MarkStudent::getStudentCode, studentCode);
+        return baseMapper.selectOne(wrapper);
+    }
 }

+ 46 - 0
teachcloud-mark/src/main/java/com/qmth/teachcloud/mark/service/impl/MarkSubjectiveScoreServiceImpl.java

@@ -7,7 +7,9 @@ import com.qmth.teachcloud.mark.mapper.MarkSubjectiveScoreMapper;
 import com.qmth.teachcloud.mark.service.MarkSubjectiveScoreService;
 import org.springframework.stereotype.Service;
 
+import java.util.HashSet;
 import java.util.List;
+import java.util.Set;
 
 /**
  * <p>
@@ -28,6 +30,50 @@ public class MarkSubjectiveScoreServiceImpl extends ServiceImpl<MarkSubjectiveSc
             queryWrapper.lambda().eq(MarkSubjectiveScore::getGroupNumber, groupNumber);
         }
 
+        List<MarkSubjectiveScore> list = this.list(queryWrapper);
+        sort(list);
+        return list;
+    }
+
+    @Override
+    public Set<Integer> listMainNumberByStudentIdAndUncalculate(Long studentId, boolean uncalculate) {
+        Set<Integer> mainNumbers = new HashSet<Integer>();
+        List<MarkSubjectiveScore> list = this.listByStudentIdAndUncalculate(studentId, uncalculate);
+        for (MarkSubjectiveScore subjectiveScore : list) {
+            mainNumbers.add(subjectiveScore.getMainNumber());
+        }
+        return mainNumbers;
+    }
+
+    @Override
+    public List<MarkSubjectiveScore> listByStudentIdAndUncalculate(Long studentId, boolean uncalculate) {
+        QueryWrapper<MarkSubjectiveScore> queryWrapper = new QueryWrapper<>();
+        queryWrapper.lambda().eq(MarkSubjectiveScore::getStudentId, studentId)
+                .eq(MarkSubjectiveScore::getUncalculate, uncalculate)
+                .orderByAsc(MarkSubjectiveScore::getMainNumber)
+                .orderByAsc(MarkSubjectiveScore::getSubNumber);
         return this.list(queryWrapper);
     }
+
+    private void sort(List<MarkSubjectiveScore> list) {
+        list.sort((o1, o2) -> {
+            int i = o1.getMainNumber() - o2.getMainNumber();
+            if (i == 0) {
+                if (o1.getSubNumber().contains("-")) {
+                    String[] o1s = o1.getSubNumber().split("-");
+                    String[] o2s = o2.getSubNumber().split("-");
+                    int j = Integer.parseUnsignedInt(o1s[0]) - Integer.parseUnsignedInt(o2s[0]);
+                    if (j == 0) {
+                        return Integer.parseUnsignedInt(o1s[1]) - Integer.parseUnsignedInt(o2s[1]);
+                    } else {
+                        return j;
+                    }
+                } else {
+                    return Integer.parseUnsignedInt(o1.getSubNumber()) - Integer.parseUnsignedInt(o2.getSubNumber());
+                }
+            }
+            return i;
+        });
+    }
+
 }

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

@@ -164,6 +164,14 @@ public class MarkTaskServiceImpl extends ServiceImpl<MarkTaskMapper, MarkTask> i
         return this.list(queryWrapper);
     }
 
+    @Override
+    public List<MarkTask> listByStudentIdAndGroupNumber(Long studentId, Integer groupNumber) {
+        QueryWrapper<MarkTask> queryWrapper = new QueryWrapper<>();
+        queryWrapper.lambda().eq(MarkTask::getStudentId, studentId)
+                .eq(MarkTask::getGroupNumber, groupNumber);
+        return this.list(queryWrapper);
+    }
+
     @Override
     public void updateHeaderResult(Long examId, String paperNumber, Integer groupNumber, Long studentId, Long updateUserId, Double totalScore, String scoreList, Long updateTime, MarkTaskStatus arbitrated) {
         UpdateWrapper<MarkTask> updateWrapper = new UpdateWrapper<>();

+ 11 - 0
teachcloud-mark/src/main/java/com/qmth/teachcloud/mark/service/impl/MarkTrackServiceImpl.java

@@ -1,5 +1,6 @@
 package com.qmth.teachcloud.mark.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.mark.entity.MarkTrack;
@@ -7,6 +8,8 @@ import com.qmth.teachcloud.mark.mapper.MarkTrackMapper;
 import com.qmth.teachcloud.mark.service.MarkTrackService;
 import org.springframework.stereotype.Service;
 
+import java.util.List;
+
 /**
  * <p>
  * 轨迹给分表 服务实现类
@@ -24,4 +27,12 @@ public class MarkTrackServiceImpl extends ServiceImpl<MarkTrackMapper, MarkTrack
         updateWrapper.lambda().eq(MarkTrack::getTaskId, taskId);
         this.remove(updateWrapper);
     }
+
+    @Override
+    public List<MarkTrack> listByTaskIdAndQuestionNumber(Long taskId, String questionNumber) {
+        QueryWrapper<MarkTrack> queryWrapper = new QueryWrapper<>();
+        queryWrapper.lambda().eq(MarkTrack::getTaskId, taskId)
+                .eq(MarkTrack::getQuestionNumber, questionNumber);
+        return this.list(queryWrapper);
+    }
 }

+ 6 - 0
teachcloud-mark/src/main/java/com/qmth/teachcloud/mark/service/impl/ScanPaperServiceImpl.java

@@ -4,6 +4,7 @@ import java.util.List;
 
 import javax.validation.constraints.NotNull;
 
+import com.qmth.teachcloud.mark.dto.mark.score.StudentPaperDetailDto;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
@@ -86,4 +87,9 @@ public class ScanPaperServiceImpl extends ServiceImpl<ScanPaperMapper, ScanPaper
         return baseMapper.selectCount(wrapper);
 	}
 
+    @Override
+    public List<StudentPaperDetailDto> listStudentPaperDetail(Long studentId) {
+        return this.baseMapper.listStudentPaperDetail(studentId);
+    }
+
 }

+ 80 - 10
teachcloud-mark/src/main/java/com/qmth/teachcloud/mark/service/impl/TaskServiceImpl.java

@@ -1,19 +1,14 @@
 package com.qmth.teachcloud.mark.service.impl;
 
-import com.qmth.teachcloud.mark.entity.MarkQuestion;
-import com.qmth.teachcloud.mark.entity.MarkStudent;
-import com.qmth.teachcloud.mark.service.MarkPaperService;
-import com.qmth.teachcloud.mark.service.MarkQuestionService;
-import com.qmth.teachcloud.mark.service.MarkStudentService;
+import com.qmth.teachcloud.common.enums.mark.SubjectiveStatus;
+import com.qmth.teachcloud.common.service.TeachcloudCommonService;
 import com.qmth.teachcloud.mark.dto.mark.ScoreItem;
 import com.qmth.teachcloud.mark.dto.mark.manage.MarkStepDTO;
+import com.qmth.teachcloud.mark.dto.mark.manage.MarkerTrackDTO;
 import com.qmth.teachcloud.mark.dto.mark.manage.Task;
 import com.qmth.teachcloud.mark.dto.mark.manage.TrackDTO;
-import com.qmth.teachcloud.mark.entity.MarkArbitrateHistory;
-import com.qmth.teachcloud.mark.entity.MarkGroup;
-import com.qmth.teachcloud.mark.entity.MarkHeaderTrack;
-import com.qmth.teachcloud.mark.service.MarkHeaderTrackService;
-import com.qmth.teachcloud.mark.service.TaskService;
+import com.qmth.teachcloud.mark.entity.*;
+import com.qmth.teachcloud.mark.service.*;
 import org.apache.commons.lang3.StringUtils;
 import org.springframework.stereotype.Service;
 
@@ -21,6 +16,7 @@ import javax.annotation.Resource;
 import java.util.ArrayList;
 import java.util.LinkedList;
 import java.util.List;
+import java.util.Set;
 
 @Service
 public class TaskServiceImpl implements TaskService {
@@ -28,11 +24,19 @@ public class TaskServiceImpl implements TaskService {
     @Resource
     private MarkPaperService markPaperService;
     @Resource
+    private MarkTaskService markTaskService;
+    @Resource
     private MarkStudentService markStudentService;
     @Resource
     private MarkQuestionService markQuestionService;
     @Resource
     private MarkHeaderTrackService markHeaderTrackService;
+    @Resource
+    private MarkTrackService markTrackService;
+    @Resource
+    private MarkSubjectiveScoreService markSubjectiveScoreService;
+    @Resource
+    private TeachcloudCommonService teachcloudCommonService;
 
     @Override
     public Task build(MarkArbitrateHistory markArbitrateHistory, MarkGroup markGroup) {
@@ -55,6 +59,72 @@ public class TaskServiceImpl implements TaskService {
         return task;
     }
 
+    @Override
+    public Task build(Long studentId) {
+        MarkStudent markStudent = markStudentService.getById(studentId);
+        Task task = new Task();
+        if (markStudent != null) {
+            MarkPaper markPaper = markPaperService.getByExamIdAndPaperNumber(markStudent.getExamId(), markStudent.getPaperNumber());
+
+            task.setStudentId(markStudent.getId());
+            task.setSecretNumber(markStudent.getSecretNumber());
+            task.setStudentCode(markStudent.getStudentCode());
+            task.setStudentName(markStudent.getStudentName());
+            task.setMarkPaper(markPaper);
+
+            // 原图
+            task.setSheetUrls(markStudentService.buildSheetUrls(studentId));
+
+            if (!markStudent.getSubjectiveStatus().equals(SubjectiveStatus.UNMARK)) {
+                task.setQuestionList(buildMarkStep(markStudent));
+//                task.setSpecialTagList(getMarkSpecialTagList(student, trialGroupCount));
+//                task.setHeaderTagList(getHeaderTagList(student));
+            }
+            if (StringUtils.isNotBlank(markStudent.getObjectiveScoreList())) {
+                task.setObjectiveScore(markStudent.getObjectiveScore());
+            }
+            task.setMarkerScore(markStudent.getTotalScore());
+            return task;
+        }
+        return task;
+    }
+
+    private List<MarkStepDTO> buildMarkStep(MarkStudent markStudent) {
+        Long examId = markStudent.getExamId();
+        String paperNumber = markStudent.getPaperNumber();
+        List<MarkStepDTO> list = new LinkedList<MarkStepDTO>();
+        List<MarkQuestion> sList = markQuestionService.listQuestionByExamIdAndPaperNumberAndGroupNumber(examId, paperNumber, null, false);
+        Set<Integer> mainList = markSubjectiveScoreService.listMainNumberByStudentIdAndUncalculate(markStudent.getId(), true);
+        List<MarkSubjectiveScore> scoreList = markSubjectiveScoreService.listByStudentIdAndGroupNumber(markStudent.getId(), null);
+        for (int i = 0; i < scoreList.size(); i++) {
+            MarkQuestion question = sList.get(i);
+            String questionNumber = question.getQuestionNumber();
+            MarkStepDTO step = buildStep(question);
+            if (!scoreList.isEmpty() && scoreList.size() == sList.size()) {
+                step.setScore(scoreList.get(i).getScore());
+                if (mainList.contains(step.getMainNumber())) {
+                    step.setUncalculate(true);
+                }
+            }
+            // 增加阅卷轨迹列表获取
+            List<MarkTask> markTaskList = markTaskService.listByStudentIdAndGroupNumber(markStudent.getId(), question.getGroupNumber());
+            // 不管单评还是多评显示所有评卷员给分轨迹
+            for (MarkTask markTask : markTaskList) {
+                List<MarkTrack> tracks = markTrackService.listByTaskIdAndQuestionNumber(markTask.getId(), questionNumber);
+                for (MarkTrack track : tracks) {
+                    step.addTrack(new MarkerTrackDTO(track));
+                }
+            }
+            // 仲裁轨迹
+            List<MarkHeaderTrack> headerTracks = markHeaderTrackService.listByStudentIdAndQuestionNumber(markStudent.getId(), questionNumber);
+            for (MarkHeaderTrack headerTrack : headerTracks) {
+                step.addHeaderTrack(new TrackDTO(headerTrack));
+            }
+            list.add(step);
+        }
+        return list;
+    }
+
     private List<MarkStepDTO> buildArbitrateStep(MarkGroup group, MarkArbitrateHistory markArbitrateHistory) {
         List<MarkStepDTO> list = new LinkedList<>();
         List<MarkQuestion> markQuestionList = markQuestionService.listQuestionByExamIdAndPaperNumberAndGroupNumber(group.getExamId(), group.getPaperNumber(), group.getNumber(), false);

+ 1 - 0
teachcloud-mark/src/main/resources/mapper/MarkStudentMapper.xml

@@ -43,6 +43,7 @@
     </resultMap>
     <select id="pageStudentScore" resultType="com.qmth.teachcloud.mark.dto.mark.score.StudentScoreDetailDto">
         SELECT
+            ms.id studentId,
             ms.exam_id examId,
             ms.course_code courseCode,
             ms.course_name courseName,

+ 22 - 0
teachcloud-mark/src/main/resources/mapper/ScanPaperMapper.xml

@@ -17,5 +17,27 @@
         <result column="create_time" property="createTime" />
         <result column="update_time" property="updateTime" />
     </resultMap>
+    <select id="listStudentPaperDetail" resultType="com.qmth.teachcloud.mark.dto.mark.score.StudentPaperDetailDto">
+        SELECT
+            ssp.student_id studentId,
+            ssp.paper_index paperIndex,
+            ssp.paper_id paperId,
+            sp.card_number cardNumber,
+            spp.page_index pageIndex,
+            spp.sheet_path sheetPath
+        FROM
+            (SELECT
+                 student_id, paper_index, paper_id
+             FROM
+                 scan_student_paper
+             WHERE
+                 student_id = #{studentId}) ssp
+                JOIN
+            scan_paper sp ON ssp.paper_id = sp.id
+                AND ssp.paper_index = sp.number
+                JOIN
+            scan_paper_page spp ON sp.id = spp.paper_id
+        ORDER BY ssp.paper_index , spp.page_index
+    </select>
 
 </mapper>