ting.yin 2 vuotta sitten
vanhempi
commit
e909d341c4

+ 5 - 4
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/service/ExamStudentService.java

@@ -107,8 +107,7 @@ public interface ExamStudentService {
     public Long countByExamIdAndSubjectCodeAndCampus(Integer examId, String code, String campusName, boolean upload,
     public Long countByExamIdAndSubjectCodeAndCampus(Integer examId, String code, String campusName, boolean upload,
             boolean absent);
             boolean absent);
 
 
-    public long countByNoAbsentAndBreach(int examId, String subjectCode, boolean upload, boolean absent,
-            boolean breach);
+    public long countByNoAbsentAndBreach(int examId, String subjectCode, boolean upload, boolean absent, boolean breach);
 
 
     public long countByAbsentAndBreach(int examId, String subjectCode, Boolean absent, Boolean breach);
     public long countByAbsentAndBreach(int examId, String subjectCode, Boolean absent, Boolean breach);
 
 
@@ -151,8 +150,7 @@ public interface ExamStudentService {
     public void updateSubjectiveStatusAndTimeAndInspectorId(Integer studentId, SubjectiveStatus status,
     public void updateSubjectiveStatusAndTimeAndInspectorId(Integer studentId, SubjectiveStatus status,
             Date inspectTime, Integer inspectorId);
             Date inspectTime, Integer inspectorId);
 
 
-    public List<ExamStudent> findByExamIdAndStudentCodeAndSubjectCode(int examId, String studentCode,
-            String subjectCode);
+    public List<ExamStudent> findByExamIdAndStudentCodeAndSubjectCode(int examId, String studentCode, String subjectCode);
 
 
     long countByExamIdAndSubjectCodeAndStatus(int examId, String subjectCode, SubjectiveStatus... status);
     long countByExamIdAndSubjectCodeAndStatus(int examId, String subjectCode, SubjectiveStatus... status);
 
 
@@ -171,4 +169,7 @@ public interface ExamStudentService {
     public int findMinInspectCountByExamIdAndSubjectCode(int examId, String subjectCode);
     public int findMinInspectCountByExamIdAndSubjectCode(int examId, String subjectCode);
 
 
     public void updateInspectCount(Integer studentId, Integer inspectCount);
     public void updateInspectCount(Integer studentId, Integer inspectCount);
+
+    Map<Integer, List<PictureTag>> buildSliceTags(ExamStudent student, boolean withGroupScore);
+
 }
 }

+ 99 - 21
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/service/impl/ExamStudentServiceImpl.java

@@ -14,6 +14,7 @@ import cn.com.qmth.stmms.biz.utils.PictureConfigTransform;
 import cn.com.qmth.stmms.biz.utils.PictureTag;
 import cn.com.qmth.stmms.biz.utils.PictureTag;
 import cn.com.qmth.stmms.biz.utils.ScoreItem;
 import cn.com.qmth.stmms.biz.utils.ScoreItem;
 import cn.com.qmth.stmms.common.enums.SubjectiveStatus;
 import cn.com.qmth.stmms.common.enums.SubjectiveStatus;
+
 import org.apache.commons.lang.StringUtils;
 import org.apache.commons.lang.StringUtils;
 import org.apache.commons.lang.math.RandomUtils;
 import org.apache.commons.lang.math.RandomUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -25,9 +26,11 @@ import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.transaction.annotation.Transactional;
 
 
 import javax.persistence.criteria.*;
 import javax.persistence.criteria.*;
+
 import java.math.BigDecimal;
 import java.math.BigDecimal;
 import java.text.DecimalFormat;
 import java.text.DecimalFormat;
 import java.util.*;
 import java.util.*;
+import java.util.Map.Entry;
 
 
 @Service
 @Service
 public class ExamStudentServiceImpl extends BaseQueryService<ExamStudent> implements ExamStudentService {
 public class ExamStudentServiceImpl extends BaseQueryService<ExamStudent> implements ExamStudentService {
@@ -995,16 +998,17 @@ public class ExamStudentServiceImpl extends BaseQueryService<ExamStudent> implem
             List<MarkConfigItem> configList = group.getPictureConfigList();
             List<MarkConfigItem> configList = group.getPictureConfigList();
             if (configList.isEmpty()) {
             if (configList.isEmpty()) {
                 // 未设置评卷区域,则自动取第一张裁切图的固定位置
                 // 未设置评卷区域,则自动取第一张裁切图的固定位置
-                originTags.add(new OriginTag(format.format(score), 1, 10, 10));
+                originTags.add(new OriginTag(0, group.getNumber(), format.format(score), 1, 10, 10));
             } else {
             } else {
                 // 取第一个显示区域相对裁切图的位置
                 // 取第一个显示区域相对裁切图的位置
                 MarkConfigItem config = configList.get(0);
                 MarkConfigItem config = configList.get(0);
-                OriginTag tag = new OriginTag(format.format(score), config.getI(), config.getX(), config.getY());
+                OriginTag tag = new OriginTag(0, group.getNumber(), format.format(score), config.getI(), config.getX(),
+                        config.getY());
                 // 兼容比例模式,且元素在裁切坐标内
                 // 兼容比例模式,且元素在裁切坐标内
                 if (config.getX() <= 1 && config.getY() <= 1 && config.getI() <= sliceConfig.size()
                 if (config.getX() <= 1 && config.getY() <= 1 && config.getI() <= sliceConfig.size()
                         && sliceConfig.get(config.getI() - 1).getW() > 0
                         && sliceConfig.get(config.getI() - 1).getW() > 0
                         && sliceConfig.get(config.getI() - 1).getH() > 0) {
                         && sliceConfig.get(config.getI() - 1).getH() > 0) {
-                    tag = new OriginTag(format.format(score), config.getI(), config.getX()
+                    tag = new OriginTag(0, group.getNumber(), format.format(score), config.getI(), config.getX()
                             * sliceConfig.get(config.getI() - 1).getW(), config.getY()
                             * sliceConfig.get(config.getI() - 1).getW(), config.getY()
                             * sliceConfig.get(config.getI() - 1).getH());
                             * sliceConfig.get(config.getI() - 1).getH());
                 }
                 }
@@ -1012,28 +1016,55 @@ public class ExamStudentServiceImpl extends BaseQueryService<ExamStudent> implem
             }
             }
         }
         }
         // 检测应该使用哪个评卷任务的轨迹记录
         // 检测应该使用哪个评卷任务的轨迹记录
-        MarkLibrary selected = null;
+        // MarkLibrary selected = null;
+        // List<MarkLibrary> libraries =
+        // libraryService.findByStudentAndGroup(student.getId(),
+        // group.getNumber());
+        // for (MarkLibrary library : libraries) {
+        // if (checkScore(library, score.doubleValue(), details)) {
+        // selected = library;
+        // break;
+        // }
+        // }
+        // if (selected != null) {
+        // // 添加轨迹分
+        // List<MarkTrack> tracks =
+        // trackService.findByLibraryId(selected.getId());
+        // for (MarkTrack markTrack : tracks) {
+        // // 轨迹分为未作答时,只显示一个汉字"空"
+        // originTags.add(new OriginTag(markTrack.isUnanswered() ? "空" :
+        // format.format(markTrack.getScore()),
+        // markTrack.getOffsetIndex(), markTrack.getOffsetX(),
+        // markTrack.getOffsetY()));
+        // }
+        // // 添加特殊标记
+        // List<MarkSpecialTag> specialTags =
+        // specialTagService.findByLibraryId(selected.getId());
+        // for (MarkSpecialTag markSpecialTag : specialTags) {
+        // originTags.add(new OriginTag(markSpecialTag.getTagName(),
+        // markSpecialTag.getOffsetIndex(),
+        // markSpecialTag.getOffsetX(), markSpecialTag.getOffsetY()));
+        // }
         List<MarkLibrary> libraries = libraryService.findByStudentAndGroup(student.getId(), group.getNumber());
         List<MarkLibrary> libraries = libraryService.findByStudentAndGroup(student.getId(), group.getNumber());
         for (MarkLibrary library : libraries) {
         for (MarkLibrary library : libraries) {
             if (checkScore(library, score.doubleValue(), details)) {
             if (checkScore(library, score.doubleValue(), details)) {
-                selected = library;
-                break;
-            }
-        }
-        if (selected != null) {
-            // 添加轨迹分
-            List<MarkTrack> tracks = trackService.findByLibraryId(selected.getId());
-            for (MarkTrack markTrack : tracks) {
-                // 轨迹分为未作答时,只显示一个汉字"空"
-                originTags.add(new OriginTag(markTrack.isUnanswered() ? "空" : format.format(markTrack.getScore()),
-                        markTrack.getOffsetIndex(), markTrack.getOffsetX(), markTrack.getOffsetY()));
-            }
-            // 添加特殊标记
-            List<MarkSpecialTag> specialTags = specialTagService.findByLibraryId(selected.getId());
-            for (MarkSpecialTag markSpecialTag : specialTags) {
-                originTags.add(new OriginTag(markSpecialTag.getTagName(), markSpecialTag.getOffsetIndex(),
-                        markSpecialTag.getOffsetX(), markSpecialTag.getOffsetY()));
+                // 添加轨迹分
+                List<MarkTrack> tracks = trackService.findByLibraryId(library.getId());
+                for (MarkTrack markTrack : tracks) {
+                    // 未作答时只显示汉字"空"
+                    originTags.add(new OriginTag(library.getMarkerId(), library.getGroupNumber(), markTrack
+                            .isUnanswered() ? "空" : format.format(markTrack.getScore()), markTrack.getOffsetIndex(),
+                            markTrack.getOffsetX(), markTrack.getOffsetY()));
+                }
+                // 添加特殊标记
+                List<MarkSpecialTag> specialTags = specialTagService.findByLibraryId(library.getId());
+                for (MarkSpecialTag markSpecialTag : specialTags) {
+                    originTags.add(new OriginTag(library.getMarkerId(), library.getGroupNumber(), markSpecialTag
+                            .getTagName(), markSpecialTag.getOffsetIndex(), markSpecialTag.getOffsetX(), markSpecialTag
+                            .getOffsetY()));
+                }
             }
             }
+
         }
         }
         return originTags;
         return originTags;
     }
     }
@@ -1152,4 +1183,51 @@ public class ExamStudentServiceImpl extends BaseQueryService<ExamStudent> implem
     public void updateInspectCount(Integer studentId, Integer inspectCount) {
     public void updateInspectCount(Integer studentId, Integer inspectCount) {
         studentDao.updateInspectCount(studentId, inspectCount);
         studentDao.updateInspectCount(studentId, inspectCount);
     }
     }
+
+    /**
+     * 根据考生获得所有原图上的评卷标记和分数明细
+     */
+    @Override
+    public Map<Integer, List<PictureTag>> buildSliceTags(ExamStudent student, boolean withGroupScore) {
+        Map<MarkGroup, List<OriginTag>> tagMap = new HashMap<MarkGroup, List<OriginTag>>();
+        Exam exam = examService.findById(student.getExamId());
+        ExamSubject subject = subjectService.find(student.getExamId(), student.getSubjectCode());
+        List<PictureConfigItem> sliceConfig = new ArrayList<PictureConfigItem>();
+        if (student.getCardNumber() != null) {
+            AnswerCard card = cardService.findByExamIdAndNumber(student.getExamId(), student.getCardNumber());
+            if (card != null) {
+                sliceConfig = card.getSliceConfigList();
+            }
+        }
+        if (sliceConfig.isEmpty()) {
+            sliceConfig = subject.getSliceConfigList();
+        }
+        if (sliceConfig.isEmpty()) {
+            sliceConfig = exam.getSliceConfigList();
+        }
+        if (!sliceConfig.isEmpty()) {
+            // 有裁切图配置时才需要获取原始评卷标记信息
+            tagMap = getSliceTags(student, withGroupScore, sliceConfig);
+        }
+        Map<Integer, List<PictureTag>> map = new HashMap<Integer, List<PictureTag>>();
+        for (Entry<MarkGroup, List<OriginTag>> entry : tagMap.entrySet()) {
+            // 遍历所有显示元素
+            for (OriginTag tag : entry.getValue()) {
+                PictureTag pt = new PictureTag();
+                pt.setContent(tag.getContent());
+                pt.setLeft(tag.getOffsetX());
+                pt.setTop(tag.getOffsetY());
+                pt.setUserId(tag.getUserId());
+                pt.setGroupNumber(tag.getGroupNumber());
+                List<PictureTag> list = map.get(tag.getOffsetIndex());
+                if (list == null) {
+                    list = new LinkedList<>();
+                    map.put(tag.getOffsetIndex(), list);
+                }
+                list.add(pt);
+            }
+        }
+        return map;
+    }
+
 }
 }

+ 2 - 0
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/mark/dao/MarkTrackDao.java

@@ -15,6 +15,8 @@ public interface MarkTrackDao extends JpaRepository<MarkTrack, MarkTrackPK>, Jpa
 
 
     List<MarkTrack> findByPkLibraryId(Integer libraryId);
     List<MarkTrack> findByPkLibraryId(Integer libraryId);
 
 
+    List<MarkTrack> findByPkLibraryIdAndPkQuestionNumberOrderByPkNumberAsc(Integer libraryId, String questionNumber);
+
     List<MarkTrack> findByStudentId(Integer studentId);
     List<MarkTrack> findByStudentId(Integer studentId);
 
 
     @Modifying(clearAutomatically = true)
     @Modifying(clearAutomatically = true)

+ 21 - 0
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/mark/model/MarkerSpecialTagDTO.java

@@ -0,0 +1,21 @@
+package cn.com.qmth.stmms.biz.mark.model;
+
+public class MarkerSpecialTagDTO extends SpecialTagDTO {
+
+    private static final long serialVersionUID = 4928109012686348307L;
+
+    private int markerId;
+
+    public MarkerSpecialTagDTO(int markerId, MarkSpecialTag specialTag) {
+        super(specialTag);
+        this.markerId = markerId;
+    }
+
+    public int getMarkerId() {
+        return markerId;
+    }
+
+    public void setMarkerId(int markerId) {
+        this.markerId = markerId;
+    }
+}

+ 21 - 0
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/mark/model/MarkerTrackDTO.java

@@ -0,0 +1,21 @@
+package cn.com.qmth.stmms.biz.mark.model;
+
+public class MarkerTrackDTO extends TrackDTO {
+
+    private static final long serialVersionUID = -7010285593473357594L;
+
+    private int markerId;
+
+    public MarkerTrackDTO(MarkTrack track) {
+        super(track);
+        this.markerId = track.getMarkerId();
+    }
+
+    public int getMarkerId() {
+        return markerId;
+    }
+
+    public void setMarkerId(int markerId) {
+        this.markerId = markerId;
+    }
+}

+ 5 - 0
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/mark/service/Impl/MarkTrackServiceImpl.java

@@ -27,6 +27,11 @@ public class MarkTrackServiceImpl extends BaseQueryService<MarkTrack> implements
         return markTrackDao.findByPkLibraryId(libraryId);
         return markTrackDao.findByPkLibraryId(libraryId);
     }
     }
 
 
+    @Override
+    public List<MarkTrack> findByLibraryIdAndQuestionNumber(Integer libraryId, String questionNumber) {
+        return markTrackDao.findByPkLibraryIdAndPkQuestionNumberOrderByPkNumberAsc(libraryId, questionNumber);
+    }
+
     @Transactional
     @Transactional
     @Override
     @Override
     public MarkTrack save(MarkTrack track) {
     public MarkTrack save(MarkTrack track) {

+ 17 - 7
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/mark/service/Impl/TaskServiceImpl.java

@@ -34,6 +34,7 @@ import cn.com.qmth.stmms.biz.mark.model.MarkLibrary;
 import cn.com.qmth.stmms.biz.mark.model.MarkSpecialTag;
 import cn.com.qmth.stmms.biz.mark.model.MarkSpecialTag;
 import cn.com.qmth.stmms.biz.mark.model.MarkStepDTO;
 import cn.com.qmth.stmms.biz.mark.model.MarkStepDTO;
 import cn.com.qmth.stmms.biz.mark.model.MarkTrack;
 import cn.com.qmth.stmms.biz.mark.model.MarkTrack;
+import cn.com.qmth.stmms.biz.mark.model.MarkerTrackDTO;
 import cn.com.qmth.stmms.biz.mark.model.RejectHistory;
 import cn.com.qmth.stmms.biz.mark.model.RejectHistory;
 import cn.com.qmth.stmms.biz.mark.model.SpecialTagDTO;
 import cn.com.qmth.stmms.biz.mark.model.SpecialTagDTO;
 import cn.com.qmth.stmms.biz.mark.model.Task;
 import cn.com.qmth.stmms.biz.mark.model.Task;
@@ -453,6 +454,7 @@ public class TaskServiceImpl implements TaskService {
         // List<ScoreItem> sItems = student.getScoreList(false);
         // List<ScoreItem> sItems = student.getScoreList(false);
         for (int i = 0; i < scoreList.size(); i++) {
         for (int i = 0; i < scoreList.size(); i++) {
             ExamQuestion question = sList.get(i);
             ExamQuestion question = sList.get(i);
+            String questionNumber = question.getQuestionNumber();
             if (map.containsKey(question.getMainNumber())) {
             if (map.containsKey(question.getMainNumber())) {
                 question.setSelectiveIndex(map.get(question.getMainNumber()).getSelectiveIndex());
                 question.setSelectiveIndex(map.get(question.getMainNumber()).getSelectiveIndex());
             }
             }
@@ -467,22 +469,30 @@ public class TaskServiceImpl implements TaskService {
             // 增加阅卷轨迹列表获取
             // 增加阅卷轨迹列表获取
             if (trialGroupCount > 0) {
             if (trialGroupCount > 0) {
                 List<TrialTrack> tracks = trialService.findTrackByStudentId(student.getId());
                 List<TrialTrack> tracks = trialService.findTrackByStudentId(student.getId());
-                String questionNumber = question.getQuestionNumber();
                 for (TrialTrack track : tracks) {
                 for (TrialTrack track : tracks) {
                     if (track.getQuestionNumber().equals(questionNumber)) {
                     if (track.getQuestionNumber().equals(questionNumber)) {
                         step.addTrack(new TrackDTO(track));
                         step.addTrack(new TrackDTO(track));
                     }
                     }
                 }
                 }
             } else {
             } else {
+                // List<MarkLibrary> libraryList =
+                // libraryService.findByStudentAndGroup(student.getId(),
+                // question.getGroupNumber());
+                // if (libraryList.size() == 1) {
+                // List<MarkTrack> tracks =
+                // trackService.findByStudentId(student.getId());
                 List<MarkLibrary> libraryList = libraryService.findByStudentAndGroup(student.getId(),
                 List<MarkLibrary> libraryList = libraryService.findByStudentAndGroup(student.getId(),
                         question.getGroupNumber());
                         question.getGroupNumber());
-                if (libraryList.size() == 1) {
-                    List<MarkTrack> tracks = trackService.findByStudentId(student.getId());
-                    String questionNumber = question.getQuestionNumber();
+                // 不管单评还是多评显示所有评卷员给分轨迹
+                for (MarkLibrary library : libraryList) {
+                    List<MarkTrack> tracks = trackService.findByLibraryIdAndQuestionNumber(library.getId(),
+                            questionNumber);
                     for (MarkTrack track : tracks) {
                     for (MarkTrack track : tracks) {
-                        if (track.getQuestionNumber().equals(questionNumber)) {
-                            step.addTrack(new TrackDTO(track));
-                        }
+                        // if (track.getQuestionNumber().equals(questionNumber))
+                        // {
+                        // step.addTrack(new TrackDTO(track));
+                        // }
+                        step.addTrack(new MarkerTrackDTO(track));
                     }
                     }
                 }
                 }
             }
             }

+ 2 - 0
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/mark/service/MarkTrackService.java

@@ -12,4 +12,6 @@ public interface MarkTrackService {
 
 
     List<MarkTrack> findByLibraryId(Integer libraryId);
     List<MarkTrack> findByLibraryId(Integer libraryId);
 
 
+    List<MarkTrack> findByLibraryIdAndQuestionNumber(Integer libraryId, String questionNumber);
+
 }
 }

+ 25 - 1
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/utils/OriginTag.java

@@ -2,6 +2,10 @@ package cn.com.qmth.stmms.biz.utils;
 
 
 public class OriginTag {
 public class OriginTag {
 
 
+    private Integer userId;
+
+    private Integer groupNumber;
+
     private String content;
     private String content;
 
 
     private int offsetIndex;
     private int offsetIndex;
@@ -14,7 +18,10 @@ public class OriginTag {
 
 
     }
     }
 
 
-    public OriginTag(String content, int offsetIndex, double offsetX, double offsetY) {
+    public OriginTag(Integer userId, Integer groupNumber, String content, int offsetIndex, double offsetX,
+            double offsetY) {
+        this.userId = userId;
+        this.groupNumber = groupNumber;
         this.content = content;
         this.content = content;
         this.offsetIndex = offsetIndex;
         this.offsetIndex = offsetIndex;
         this.offsetX = offsetX;
         this.offsetX = offsetX;
@@ -52,4 +59,21 @@ public class OriginTag {
     public void setOffsetY(double offsetY) {
     public void setOffsetY(double offsetY) {
         this.offsetY = offsetY;
         this.offsetY = offsetY;
     }
     }
+
+    public Integer getUserId() {
+        return userId;
+    }
+
+    public void setUserId(Integer userId) {
+        this.userId = userId;
+    }
+
+    public Integer getGroupNumber() {
+        return groupNumber;
+    }
+
+    public void setGroupNumber(Integer groupNumber) {
+        this.groupNumber = groupNumber;
+    }
+
 }
 }

+ 7 - 3
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/utils/PictureConfigTransform.java

@@ -35,12 +35,13 @@ public class PictureConfigTransform {
             for (OriginTag tag : entry.getValue()) {
             for (OriginTag tag : entry.getValue()) {
                 if (tag.getOffsetIndex() > sliceCount) {
                 if (tag.getOffsetIndex() > sliceCount) {
                     // 元素所属裁切图不在裁切坐标范围内,表示裁切图直接使用的原图
                     // 元素所属裁切图不在裁切坐标范围内,表示裁切图直接使用的原图
-                    buildTag(map, tag.getContent(), tag.getOffsetIndex(), tag.getOffsetX(), tag.getOffsetY());
+                    buildTag(map, tag.getContent(), tag.getOffsetIndex(), tag.getOffsetX(), tag.getOffsetY(),
+                            tag.getUserId(), tag.getGroupNumber());
                 } else {
                 } else {
                     // 有裁切坐标时,原图坐标=元素相对坐标+裁切坐标
                     // 有裁切坐标时,原图坐标=元素相对坐标+裁切坐标
                     PictureConfigItem config = sliceConfigs.get(tag.getOffsetIndex() - 1);
                     PictureConfigItem config = sliceConfigs.get(tag.getOffsetIndex() - 1);
                     buildTag(map, tag.getContent(), config.getI(), config.getX() + tag.getOffsetX(), config.getY()
                     buildTag(map, tag.getContent(), config.getI(), config.getX() + tag.getOffsetX(), config.getY()
-                            + tag.getOffsetY());
+                            + tag.getOffsetY(), tag.getUserId(), tag.getGroupNumber());
                 }
                 }
             }
             }
         }
         }
@@ -61,11 +62,14 @@ public class PictureConfigTransform {
      * @param top
      * @param top
      *            - 在原图内的上偏移
      *            - 在原图内的上偏移
      */
      */
-    private static void buildTag(Map<Integer, List<PictureTag>> tags, String content, int index, double left, double top) {
+    private static void buildTag(Map<Integer, List<PictureTag>> tags, String content, int index, double left,
+            double top, int userId, int groupNumber) {
         PictureTag tag = new PictureTag();
         PictureTag tag = new PictureTag();
         tag.setContent(content);
         tag.setContent(content);
         tag.setLeft(left);
         tag.setLeft(left);
         tag.setTop(top);
         tag.setTop(top);
+        tag.setUserId(userId);
+        tag.setGroupNumber(groupNumber);
         List<PictureTag> list = tags.get(index);
         List<PictureTag> list = tags.get(index);
         if (list == null) {
         if (list == null) {
             list = new LinkedList<>();
             list = new LinkedList<>();

+ 20 - 0
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/utils/PictureTag.java

@@ -4,6 +4,10 @@ import java.util.List;
 
 
 public class PictureTag {
 public class PictureTag {
 
 
+    private int userId;
+
+    private int groupNumber;
+
     private String[] content;
     private String[] content;
 
 
     private double left;
     private double left;
@@ -50,4 +54,20 @@ public class PictureTag {
         this.size = size;
         this.size = size;
     }
     }
 
 
+    public int getUserId() {
+        return userId;
+    }
+
+    public void setUserId(int userId) {
+        this.userId = userId;
+    }
+
+    public int getGroupNumber() {
+        return groupNumber;
+    }
+
+    public void setGroupNumber(int groupNumber) {
+        this.groupNumber = groupNumber;
+    }
+
 }
 }

+ 134 - 0
stmms-web/src/main/java/cn/com/qmth/stmms/api/controller/ExamStudentController.java

@@ -314,4 +314,138 @@ public class ExamStudentController extends BaseApiController {
         return encrypt ? AESUtil.encrypt(result) : result;
         return encrypt ? AESUtil.encrypt(result) : result;
     }
     }
 
 
+    @RoleRequire({ Role.SCHOOL_ADMIN, Role.SCANNER })
+    @RequestMapping("/exam/students/slice")
+    @ResponseBody
+    public JSONArray getStudentsSlice(HttpServletRequest request, ExamStudentSearchQuery query,
+            @RequestParam(required = false) Boolean withScoreDetail,
+            @RequestParam(required = false) Boolean withMarkTrack,
+            @RequestParam(required = false) Boolean withGroupScoreTrack,
+            @RequestParam(required = false) Boolean withSliceUrl) {
+        ApiUser user = RequestUtils.getApiUser(request);
+        JSONArray array = new JSONArray();
+        if (query.getExamId() == null) {
+            return array;
+        }
+        Exam exam = examService.findById(query.getExamId());
+        if (exam != null && exam.getSchoolId().equals(user.getSchoolId())) {
+            DecimalFormat format = new DecimalFormat("####.###");
+            studentService.findByQuery(query);
+            for (ExamStudent student : query.getResult()) {
+                JSONObject obj = new JSONObject();
+                obj.accumulate("id", student.getId());
+                obj.accumulate("schoolId", student.getSchoolId());
+                obj.accumulate("examNumber", student.getExamNumber());
+                obj.accumulate("campusCode", "0");
+                obj.accumulate("campusName", StringUtils.trimToEmpty(student.getCampusName()));
+                obj.accumulate("subjectCode", student.getSubjectCode());
+                obj.accumulate("subjectName", student.getSubjectName());
+                obj.accumulate("name", student.getName());
+                obj.accumulate("studentCode", student.getStudentCode());
+                obj.accumulate("packageCode", StringUtils.trimToEmpty(student.getPackageCode()));
+                obj.accumulate("paperType", StringUtils.trimToEmpty(student.getPaperType()));
+                obj.accumulate("batchCode", StringUtils.trimToEmpty(student.getBatchCode()));
+                obj.accumulate("sheetCount", student.getSheetCount() != null ? student.getSheetCount() : 0);
+                obj.accumulate("sliceCount", student.getSliceCount() != null ? student.getSliceCount() : 0);
+                obj.accumulate("answers", StringUtils.trimToEmpty(student.getAnswers()));
+                obj.accumulate("upload", student.isUpload());
+                obj.accumulate("absent", student.isAbsent());
+                obj.accumulate("manualAbsent", student.isManualAbsent());
+                obj.accumulate("breach", student.isBreach());
+                obj.accumulate("objectiveScore",
+                        student.getObjectiveScore() == null ? "" : format.format(student.getObjectiveScore()));
+                obj.accumulate("subjectiveScore",
+                        student.getSubjectiveScore() == null ? "" : format.format(student.getSubjectiveScore()));
+                obj.accumulate("subjectiveStatus", student.getSubjectiveStatus().toString());
+                obj.accumulate("examSite", StringUtils.trimToEmpty(student.getExamSite()));
+                obj.accumulate("examRoom", StringUtils.trimToEmpty(student.getExamRoom()));
+                obj.accumulate("remark", StringUtils.trimToEmpty(student.getRemark()));
+                obj.accumulate("college", StringUtils.trimToEmpty(student.getCollege()));
+                obj.accumulate("className", StringUtils.trimToEmpty(student.getClassName()));
+                obj.accumulate("teacher", StringUtils.trimToEmpty(student.getTeacher()));
+                if (student.getInspectorId() != null) {
+                    obj.accumulate("inspector", getInspector(student.getInspectorId()));
+                }
+
+                try {
+                    if (withScoreDetail != null && withScoreDetail.booleanValue()) {
+                        // 构造客观题得分明细
+                        JSONArray objective = new JSONArray();
+                        List<ScoreItem> scoreList = student.getScoreList(true);
+                        List<ExamQuestion> questionList = questionService.findByExamAndSubjectAndObjectiveAndPaperType(
+                                student.getExamId(), student.getSubjectCode(), true, student.getPaperType());
+                        int i = 0;
+                        for (ScoreItem item : scoreList) {
+                            i++;
+                            if (questionList.size() < i) {
+                                break;
+                            }
+                            ExamQuestion question = questionList.get(i - 1);
+                            if (question.getTotalScore() == null || question.getTotalScore() == 0) {
+                                continue;
+                            }
+                            JSONObject detail = new JSONObject();
+                            detail.accumulate("mainNumber", question.getMainNumber());
+                            detail.accumulate("subNumber", question.getSubNumber());
+                            detail.accumulate("score", item.getScore());
+                            detail.accumulate("answer", item.getAnswer());
+                            objective.add(detail);
+                        }
+                        obj.accumulate("objectiveScoreDetail", objective);
+
+                        // 构造主观题得分明细
+                        JSONArray subjective = new JSONArray();
+                        scoreList = student.getScoreList(false);
+                        questionList = questionService.findByExamAndSubjectAndObjective(student.getExamId(),
+                                student.getSubjectCode(), false);
+                        i = 0;
+                        for (ScoreItem item : scoreList) {
+                            i++;
+                            if (questionList.size() < i) {
+                                break;
+                            }
+                            ExamQuestion question = questionList.get(i - 1);
+                            if (question.getTotalScore() == null || question.getTotalScore() == 0) {
+                                continue;
+                            }
+                            JSONObject detail = new JSONObject();
+                            detail.accumulate("mainNumber", question.getMainNumber());
+                            detail.accumulate("subNumber", question.getSubNumber());
+                            detail.accumulate("score", item.getScore());
+                            detail.accumulate("marker", getMarkerNames(student, question.getGroupNumber()));
+                            String header = getHeaderName(student, question.getGroupNumber());
+                            if (header != null) {
+                                detail.accumulate("header", header);
+                            }
+                            detail.accumulate("groupNumber", question.getGroupNumber());
+                            detail.accumulate("mainTitle", question.getMainTitle());
+                            subjective.add(detail);
+                        }
+                        obj.accumulate("subjectiveScoreDetail", subjective);
+                    }
+                    // 返回评卷标记
+                    if (withMarkTrack != null && withMarkTrack.booleanValue()) {
+                        obj.accumulate(
+                                "tags",
+                                studentService.buildSliceTags(student, withGroupScoreTrack != null
+                                        && withGroupScoreTrack.booleanValue()));
+                    }
+                    // 返回原图下载地址
+                    if (withSliceUrl != null && withSliceUrl.booleanValue()) {
+                        obj.accumulate(
+                                "sliceUrls",
+                                fileService
+                                        .getSliceUris(student.getExamId(), student.getSecretNumber(), 1,
+                                                student.getSliceCount()).stream()
+                                        .map(uri -> fileService.getFileServer().concat(uri))
+                                        .collect(Collectors.toList()));
+                    }
+                    array.add(obj);
+                } catch (Exception e) {
+                    logger.error("student api error", e);
+                }
+            }
+        }
+        return array;
+    }
 }
 }