ting.yin 4 vuotta sitten
vanhempi
commit
62578d3add
33 muutettua tiedostoa jossa 1063 lisäystä ja 1330 poistoa
  1. 0 10
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/dao/MarkerDao.java
  2. 15 0
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/query/ExamStudentSearchQuery.java
  3. 14 0
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/service/InspectedService.java
  4. 0 4
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/service/MarkerService.java
  5. 40 0
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/service/impl/InspectedServiceImpl.java
  6. 0 11
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/service/impl/MarkerServiceImpl.java
  7. 6 6
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/mark/dao/MarkLibraryDao.java
  8. 4 0
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/mark/dao/MarkTrackDao.java
  9. 7 4
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/mark/model/MarkLibrary.java
  10. 19 20
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/mark/model/MarkResult.java
  11. 19 19
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/mark/model/MarkStepDTO.java
  12. 26 0
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/mark/model/Task.java
  13. 5 7
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/mark/model/TrackDTO.java
  14. 44 8
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/mark/service/Impl/MarkLibraryServiceImpl.java
  15. 92 8
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/mark/service/Impl/MarkServiceImpl.java
  16. 50 43
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/mark/service/Impl/TaskServiceImpl.java
  17. 10 1
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/mark/service/MarkLibraryService.java
  18. 10 0
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/mark/service/MarkService.java
  19. 7 6
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/mark/service/MarkSpecialTagService.java
  20. 2 1
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/mark/service/TaskService.java
  21. 3 3
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/utils/ScoreItem.java
  22. 14 0
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/utils/TaskLock.java
  23. 28 0
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/utils/TaskLockUtil.java
  24. 2 0
      stmms-biz/src/main/resources/META-INF/persistence.xml
  25. 30 0
      stmms-web/src/main/java/cn/com/qmth/stmms/admin/dto/RejectResult.java
  26. 97 87
      stmms-web/src/main/java/cn/com/qmth/stmms/admin/exam/ArbitrateController.java
  27. 155 172
      stmms-web/src/main/java/cn/com/qmth/stmms/admin/exam/InspectedController.java
  28. 89 134
      stmms-web/src/main/java/cn/com/qmth/stmms/admin/exam/LibraryController.java
  29. 31 65
      stmms-web/src/main/java/cn/com/qmth/stmms/admin/exam/MarkQualityController.java
  30. 31 36
      stmms-web/src/main/java/cn/com/qmth/stmms/admin/exam/MarkTrackController.java
  31. 0 560
      stmms-web/src/main/java/cn/com/qmth/stmms/mark/MarkApi.java
  32. 212 124
      stmms-web/src/main/java/cn/com/qmth/stmms/mark/MarkController.java
  33. 1 1
      stmms-web/src/main/webapp/WEB-INF/views/modules/exam/inspectedList.jsp

+ 0 - 10
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/dao/MarkerDao.java

@@ -19,10 +19,6 @@ public interface MarkerDao extends PagingAndSortingRepository<Marker, Integer>,
     @Query("select count(m) from Marker m where m.examId=?1 and m.subjectCode=?2 and m.groupNumber=?3")
     public long countByExamIdAndSubjectCodeAndGroupNumber(int examId, String subjectCode, int number);
 
-    public List<Marker> findByExamId(int examId);
-
-    public List<Marker> findByExamIdAndSubjectCode(int examId, String subjectCode, Pageable page);
-
     public List<Marker> findByExamIdAndSubjectCodeAndGroupNumber(int examId, String subjectCode, int number,
             Pageable page);
 
@@ -49,10 +45,6 @@ public interface MarkerDao extends PagingAndSortingRepository<Marker, Integer>,
     public void updateQualityById(Integer id, int finishCount, int validCount, double avgSpeed, double avgScore,
             double stdevScore);
 
-    @Modifying
-    @Query("update Marker m set m.markSetting=?2 where m.id=?1")
-    public void updateMarkSettingById(Integer id, String setting);
-
     @Modifying
     @Query("update Marker m set m.finishCount=null, m.validCount=null, m.avgSpeed=null, m.avgScore=null, m.stdevScore=null "
             + "where m.examId=?1 and m.subjectCode=?2 and m.groupNumber=?3")
@@ -61,8 +53,6 @@ public interface MarkerDao extends PagingAndSortingRepository<Marker, Integer>,
     @Query(value = "select e.* from eb_marker e,m_library m where 1=1 and e.id = m.marker_id and m.student_id =?1", nativeQuery = true)
     public List<Marker> findByStudentId(int studentId);
 
-    public List<Marker> findByMode(String common);
-
     public Marker findByExamIdAndSubjectCodeAndGroupNumberAndUserId(int examId, String subjectCode, Integer number,
             Integer userId);
 

+ 15 - 0
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/query/ExamStudentSearchQuery.java

@@ -94,6 +94,8 @@ public class ExamStudentSearchQuery extends BaseQuery<ExamStudent> {
 
     private List<Integer> studentIds;
 
+    private Integer inspectorId;
+
     public ExamStudentSearchQuery() {
         super();
         this.statusSet = new HashSet<>();
@@ -107,6 +109,10 @@ public class ExamStudentSearchQuery extends BaseQuery<ExamStudent> {
         setSort(new Sort(Direction.DESC, "examId"));
     }
 
+    public void orderByInspectTimeDesc() {
+        setSort(new Sort(Direction.DESC, "inspectTime"));
+    }
+
     public Integer getExamId() {
         return examId;
     }
@@ -430,4 +436,13 @@ public class ExamStudentSearchQuery extends BaseQuery<ExamStudent> {
     public void setStudentIds(List<Integer> studentIds) {
         this.studentIds = studentIds;
     }
+
+    public Integer getInspectorId() {
+        return inspectorId;
+    }
+
+    public void setInspectorId(Integer inspectorId) {
+        this.inspectorId = inspectorId;
+    }
+
 }

+ 14 - 0
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/service/InspectedService.java

@@ -14,4 +14,18 @@ public interface InspectedService {
     Integer countByQuery(ExamStudentSearchQuery query, SubjectiveStatus status, Integer mainNumber,
             Double mainStartScore, Double mainEndScore, Double questionScore);
 
+    void releaseByUserId(Integer examId, String subjectCode, Integer userId);
+
+    void releaseByStudent(ExamStudent student);
+
+    /**
+     * 申请领取某个任务
+     */
+    boolean applyStudent(ExamStudent student, Integer userId);
+
+    /**
+     * 是否已领取了某个任务
+     */
+    boolean hasApplied(ExamStudent student, Integer userId);
+
 }

+ 0 - 4
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/service/MarkerService.java

@@ -25,12 +25,8 @@ public interface MarkerService {
 
     List<Marker> getMarkCount(int examId, Set<String> subjectCodes);
 
-    List<Marker> findMode(String commo);
-
     public int batchSave(List<Marker> list);
 
-    void updateMarkSetting(Integer id, String setting);
-
     List<Marker> findByExamAndUserId(Integer examId, Integer userId);
 
     Marker findByExamAndSubjectAndNumberAndUserId(int examId, String subjectCode, Integer number, Integer userId);

+ 40 - 0
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/service/impl/InspectedServiceImpl.java

@@ -16,6 +16,8 @@ import cn.com.qmth.stmms.biz.exam.model.ExamStudent;
 import cn.com.qmth.stmms.biz.exam.query.ExamStudentSearchQuery;
 import cn.com.qmth.stmms.biz.exam.service.ExamStudentService;
 import cn.com.qmth.stmms.biz.exam.service.InspectedService;
+import cn.com.qmth.stmms.biz.utils.TaskLock;
+import cn.com.qmth.stmms.biz.utils.TaskLockUtil;
 import cn.com.qmth.stmms.common.enums.SubjectiveStatus;
 
 @Service
@@ -133,4 +135,42 @@ public class InspectedServiceImpl extends BaseQueryService<ExamStudent> implemen
         return count;
     }
 
+    @Override
+    public void releaseByUserId(Integer examId, String subjectCode, Integer userId) {
+        TaskLock taskLock = TaskLockUtil.getInspectedStudentTask(examId + '_' + subjectCode);
+        taskLock.clear(userId);
+    }
+
+    @Override
+    public void releaseByStudent(ExamStudent student) {
+        TaskLock taskLock = TaskLockUtil.getInspectedStudentTask(getKey(student));
+        taskLock.remove(student.getId(), 1);
+    }
+
+    @Override
+    public boolean applyStudent(ExamStudent student, Integer userId) {
+        TaskLock taskLock = TaskLockUtil.getInspectedStudentTask(getKey(student));
+        boolean lock = taskLock.add(student.getId(), 1, userId);
+        // 上锁失败直接返回
+        if (!lock) {
+            return false;
+        }
+        // 重复校验任务状态
+        if (student.getSubjectiveStatus().equals(SubjectiveStatus.MARKED)) {
+            return true;
+        } else {
+            taskLock.remove(student.getId(), 1, userId);
+            return false;
+        }
+    }
+
+    @Override
+    public boolean hasApplied(ExamStudent student, Integer userId) {
+        TaskLock taskLock = TaskLockUtil.getInspectedStudentTask(getKey(student));
+        return taskLock.exist(student.getId(), 1, userId);
+    }
+
+    private String getKey(ExamStudent student) {
+        return student.getExamId() + "_" + student.getSubjectCode();
+    }
 }

+ 0 - 11
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/service/impl/MarkerServiceImpl.java

@@ -46,12 +46,6 @@ public class MarkerServiceImpl extends BaseQueryService<Marker> implements Marke
         return markerDao.save(marker);
     }
 
-    @Transactional
-    @Override
-    public void updateMarkSetting(Integer id, String setting) {
-        markerDao.updateMarkSettingById(id, setting);
-    }
-
     @Override
     public Marker findById(Integer id) {
         return markerDao.findOne(id);
@@ -148,11 +142,6 @@ public class MarkerServiceImpl extends BaseQueryService<Marker> implements Marke
         return list.size();
     }
 
-    @Override
-    public List<Marker> findMode(String commo) {
-        return markerDao.findByMode(commo);
-    }
-
     @Override
     public Marker findByExamAndSubjectAndNumberAndUserId(int examId, String subjectCode, Integer number, Integer userId) {
         return markerDao.findByExamIdAndSubjectCodeAndGroupNumberAndUserId(examId, subjectCode, number, userId);

+ 6 - 6
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/mark/dao/MarkLibraryDao.java

@@ -30,8 +30,8 @@ public interface MarkLibraryDao extends JpaRepository<MarkLibrary, Integer>, Jpa
     @Query("select l1 from MarkLibrary l1 where l1.examId=?1 and l1.subjectCode=?2 and l1.groupNumber=?3 and l1.status in (?6) "
             + "and not exists (select l2 from MarkLibrary l2 where l2.studentId=l1.studentId and l2.id!=l1.id and l2.markerId=?4) "
             + "and exists (select mc.id from MarkerClass mc, ExamStudent s where l1.studentId=s.id and mc.userId=?5 and s.className=mc.className)")
-    List<MarkLibrary> findUnMarkedFilterClass(Integer examId, String subjectCode, Integer groupNumber, Integer markerId,
-            Integer userId, Set<LibraryStatus> statusSet, Pageable page);
+    List<MarkLibrary> findUnMarkedFilterClass(Integer examId, String subjectCode, Integer groupNumber,
+            Integer markerId, Integer userId, Set<LibraryStatus> statusSet, Pageable page);
 
     List<MarkLibrary> findByMarkerId(Integer markerId);
 
@@ -53,8 +53,8 @@ public interface MarkLibraryDao extends JpaRepository<MarkLibrary, Integer>, Jpa
     long countByExamIdAndSubjectCodeAndGroupNumber(Integer examId, String subjectCode, Integer groupNumber);
 
     @Query("select count(f) from MarkLibrary f where f.examId=?1 and f.subjectCode=?2 and f.groupNumber=?3 and f.taskNumber=?4")
-    long countByExamIdAndSubjectCodeAndGroupNumberAndTaskNumber(Integer examId, String subjectCode, Integer groupNumber,
-            Integer taskNumber);
+    long countByExamIdAndSubjectCodeAndGroupNumberAndTaskNumber(Integer examId, String subjectCode,
+            Integer groupNumber, Integer taskNumber);
 
     @Query("select count(f) from MarkLibrary f where f.examId=?1 and f.subjectCode=?2 and f.groupNumber=?3 and f.status in (?4)")
     long countByExamIdAndSubjectCodeAndGroupNumberAndStatus(Integer examId, String subjectCode, Integer groupNumber,
@@ -114,8 +114,8 @@ public interface MarkLibraryDao extends JpaRepository<MarkLibrary, Integer>, Jpa
     @Modifying(clearAutomatically = true)
     @Query("update MarkLibrary m set m.headerId=?3, m.headerScore=?4, m.headerScoreList=?5, m.headerTime=?6, m.status=?7 "
             + " where m.studentId=?1 and m.groupNumber=?2")
-    void updateHeaderResult(Integer studentId, Integer groupNumber, Integer userId, Double totalScore, String scoreList,
-            Date updateTime, LibraryStatus arbitrated);
+    void updateHeaderResult(Integer studentId, Integer groupNumber, Integer userId, Double totalScore,
+            String scoreList, Date updateTime, LibraryStatus arbitrated);
 
     @Modifying(clearAutomatically = true)
     @Query("update MarkLibrary m set m.status=?3 where m.studentId=?1 and m.groupNumber=?2")

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

@@ -33,4 +33,8 @@ public interface MarkTrackDao extends JpaRepository<MarkTrack, MarkTrackPK>, Jpa
     @Query("delete from MarkTrack t where t.examId=?1 and t.subjectCode=?2 and t.groupNumber=?3")
     void deleteByExamIdAndSubjectCodeAndGroupNumber(Integer examId, String subjectCode, Integer groupNumber);
 
+    @Modifying(clearAutomatically = true)
+    @Query("delete from MarkTrack t where t.pk.libraryId=?1 and t.pk.questionNumber=?2")
+    void deleteByLibraryIdAndQuestionNumber(Integer id, String questionNumber);
+
 }

+ 7 - 4
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/mark/model/MarkLibrary.java

@@ -226,9 +226,13 @@ public class MarkLibrary implements Serializable {
             try {
                 String[] values = scoreList.split(",");
                 for (String value : values) {
-                    ScoreItem item = ScoreItem.parse(value, false);
-                    if (item != null) {
-                        list.add(item);
+                    if (value.equals("")) {
+                        list.add(new ScoreItem(false));
+                    } else {
+                        ScoreItem item = ScoreItem.parse(value, false);
+                        if (item != null) {
+                            list.add(item);
+                        }
                     }
                 }
             } catch (Exception e) {
@@ -300,5 +304,4 @@ public class MarkLibrary implements Serializable {
     public void setMarkerLoginName(String markerLoginName) {
         this.markerLoginName = markerLoginName;
     }
-
 }

+ 19 - 20
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/mark/model/MarkResult.java

@@ -8,7 +8,6 @@ import java.util.Map;
 import org.apache.commons.lang.StringUtils;
 
 import cn.com.qmth.stmms.biz.exam.model.Marker;
-import cn.com.qmth.stmms.common.enums.MarkStatus;
 
 /**
  * 标准评卷结果对象
@@ -23,7 +22,7 @@ public class MarkResult {
     /**
      * 评卷状态
      */
-    private MarkStatus statusValue;
+    private String statusValue;
 
     /**
      * 考生编号
@@ -38,7 +37,7 @@ public class MarkResult {
     /**
      * 总分
      */
-    private double totalScore;
+    private double markerScore;
 
     /**
      * 分值列表
@@ -53,7 +52,7 @@ public class MarkResult {
     /**
      * 特殊标记列表
      */
-    private SpecialTagDTO[] tagList;
+    private SpecialTagDTO[] specialTagList;
 
     /**
      * 所花时间
@@ -70,11 +69,11 @@ public class MarkResult {
      */
     private Integer problemTypeId;
 
-    public MarkStatus getStatusValue() {
+    public String getStatusValue() {
         return statusValue;
     }
 
-    public void setStatusValue(MarkStatus statusValue) {
+    public void setStatusValue(String statusValue) {
         this.statusValue = statusValue;
     }
 
@@ -86,12 +85,12 @@ public class MarkResult {
         this.libraryId = libraryId;
     }
 
-    public double getTotalScore() {
-        return totalScore;
+    public double getMarkerScore() {
+        return markerScore;
     }
 
-    public void setTotalScore(double totalScore) {
-        this.totalScore = totalScore;
+    public void setMarkerScore(double markerScore) {
+        this.markerScore = markerScore;
     }
 
     public String getScoreList() {
@@ -110,12 +109,12 @@ public class MarkResult {
         this.trackList = trackList;
     }
 
-    public SpecialTagDTO[] getTagList() {
-        return tagList;
+    public SpecialTagDTO[] getSpecialTagList() {
+        return specialTagList;
     }
 
-    public void setTagList(SpecialTagDTO[] tagList) {
-        this.tagList = tagList;
+    public void setSpecialTagList(SpecialTagDTO[] specialTagList) {
+        this.specialTagList = specialTagList;
     }
 
     public int getSpent() {
@@ -138,7 +137,7 @@ public class MarkResult {
         Map<String, List<TrackDTO>> map = new HashMap<String, List<TrackDTO>>();
         if (trackList != null) {
             for (TrackDTO dto : trackList) {
-                String questionNumber = dto.getQuestionNumber();
+                String questionNumber = dto.getMainNumber() + "." + dto.getSubNumber();
                 List<TrackDTO> list = map.get(questionNumber);
                 if (list == null) {
                     list = new LinkedList<TrackDTO>();
@@ -154,7 +153,7 @@ public class MarkResult {
         Map<String, List<MarkTrack>> map = new HashMap<>();
         if (trackList != null) {
             for (TrackDTO dto : trackList) {
-                String questionNumber = dto.getQuestionNumber();
+                String questionNumber = dto.getMainNumber() + "." + dto.getSubNumber();
                 List<MarkTrack> list = map.get(questionNumber);
                 if (list == null) {
                     list = new LinkedList<MarkTrack>();
@@ -188,8 +187,8 @@ public class MarkResult {
 
     public List<MarkSpecialTag> getSpecialTagList(MarkLibrary library, Marker marker) {
         List<MarkSpecialTag> list = new LinkedList<>();
-        if (tagList != null) {
-            for (SpecialTagDTO dto : tagList) {
+        if (specialTagList != null) {
+            for (SpecialTagDTO dto : specialTagList) {
                 list.add(dto.transform(library));
             }
         }
@@ -198,8 +197,8 @@ public class MarkResult {
 
     public List<TrialTag> getTagList(TrialHistory history) {
         List<TrialTag> list = new LinkedList<>();
-        if (tagList != null) {
-            for (SpecialTagDTO dto : tagList) {
+        if (specialTagList != null) {
+            for (SpecialTagDTO dto : specialTagList) {
                 list.add(dto.transform(history));
             }
         }

+ 19 - 19
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/mark/model/MarkStepDTO.java

@@ -14,7 +14,7 @@ public class MarkStepDTO implements Serializable {
 
     private String subNumber;
 
-    private double interval;
+    private double intervalScore;
 
     private double defaultScore;
 
@@ -22,9 +22,9 @@ public class MarkStepDTO implements Serializable {
 
     private Double score;
 
-    private double max;
+    private double maxScore;
 
-    private double min;
+    private double minScore;
 
     private List<TrackDTO> trackList = new ArrayList<TrackDTO>();
 
@@ -44,20 +44,28 @@ public class MarkStepDTO implements Serializable {
         this.subNumber = subNumber;
     }
 
-    public double getMax() {
-        return max;
+    public double getIntervalScore() {
+        return intervalScore;
     }
 
-    public void setMax(double max) {
-        this.max = max;
+    public void setIntervalScore(double intervalScore) {
+        this.intervalScore = intervalScore;
     }
 
-    public double getMin() {
-        return min;
+    public double getMaxScore() {
+        return maxScore;
     }
 
-    public void setMin(double min) {
-        this.min = min;
+    public void setMaxScore(double maxScore) {
+        this.maxScore = maxScore;
+    }
+
+    public double getMinScore() {
+        return minScore;
+    }
+
+    public void setMinScore(double minScore) {
+        this.minScore = minScore;
     }
 
     public double getDefaultScore() {
@@ -76,14 +84,6 @@ public class MarkStepDTO implements Serializable {
         this.title = title;
     }
 
-    public double getInterval() {
-        return interval;
-    }
-
-    public void setInterval(double interval) {
-        this.interval = interval;
-    }
-
     public List<TrackDTO> getTrackList() {
         return trackList;
     }

+ 26 - 0
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/mark/model/Task.java

@@ -105,6 +105,16 @@ public class Task implements Serializable {
      */
     private boolean isRejected;
 
+    /**
+     * 评卷员登录名
+     */
+    private String markerName;
+
+    /**
+     * 复核时间
+     */
+    private Date inspectTime;
+
     public Integer getLibraryId() {
         return libraryId;
     }
@@ -257,4 +267,20 @@ public class Task implements Serializable {
         this.isRejected = isRejected;
     }
 
+    public String getMarkerName() {
+        return markerName;
+    }
+
+    public void setMarkerName(String markerName) {
+        this.markerName = markerName;
+    }
+
+    public Date getInspectTime() {
+        return inspectTime;
+    }
+
+    public void setInspectTime(Date inspectTime) {
+        this.inspectTime = inspectTime;
+    }
+
 }

+ 5 - 7
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/mark/model/TrackDTO.java

@@ -36,7 +36,8 @@ public class TrackDTO implements Serializable {
     }
 
     public TrackDTO(MarkTrack track) {
-        String str[] = track.getQuestionNumber().split(".");
+        String questionNumber = track.getQuestionNumber();
+        String str[] = questionNumber.split("\\.");
         setMainNumber(Integer.parseInt(str[0]));
         setSubNumber(str[1]);
         setNumber(track.getNumber());
@@ -49,7 +50,7 @@ public class TrackDTO implements Serializable {
     }
 
     public TrackDTO(TrialTrack track) {
-        String str[] = track.getQuestionNumber().split(".");
+        String str[] = track.getQuestionNumber().split("\\.");
         setMainNumber(Integer.parseInt(str[0]));
         setSubNumber(str[1]);
         setNumber(track.getNumber());
@@ -64,7 +65,7 @@ public class TrackDTO implements Serializable {
     public MarkTrack transform(MarkLibrary library, Marker marker) {
         MarkTrack track = new MarkTrack();
         track.setLibraryId(library.getId());
-        track.setQuestionNumber(getQuestionNumber());
+        track.setQuestionNumber(getMainNumber() + "." + getSubNumber());
         track.setNumber(getNumber());
         track.setStudentId(library.getStudentId());
         track.setExamId(library.getExamId());
@@ -84,7 +85,7 @@ public class TrackDTO implements Serializable {
         TrialTrack track = new TrialTrack();
         track.setLibraryId(history.getLibraryId());
         track.setMarkerId(history.getMarkerId());
-        track.setQuestionNumber(getQuestionNumber());
+        track.setQuestionNumber(getMainNumber() + "." + getSubNumber());
         track.setNumber(getNumber());
         track.setStudentId(history.getStudentId());
         track.setExamId(history.getExamId());
@@ -172,7 +173,4 @@ public class TrackDTO implements Serializable {
         this.offsetY = offsetY;
     }
 
-    public String getQuestionNumber() {
-        return getMainNumber() + "." + getSubNumber();
-    }
 }

+ 44 - 8
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/mark/service/Impl/MarkLibraryServiceImpl.java

@@ -1,6 +1,5 @@
 package cn.com.qmth.stmms.biz.mark.service.Impl;
 
-import java.util.HashSet;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Set;
@@ -21,6 +20,8 @@ import cn.com.qmth.stmms.biz.mark.dao.MarkLibraryDao;
 import cn.com.qmth.stmms.biz.mark.model.MarkLibrary;
 import cn.com.qmth.stmms.biz.mark.query.MarkLibrarySearchQuery;
 import cn.com.qmth.stmms.biz.mark.service.MarkLibraryService;
+import cn.com.qmth.stmms.biz.utils.TaskLock;
+import cn.com.qmth.stmms.biz.utils.TaskLockUtil;
 import cn.com.qmth.stmms.common.enums.LibraryStatus;
 
 @Service
@@ -46,10 +47,7 @@ public class MarkLibraryServiceImpl extends BaseQueryService<MarkLibrary> implem
 
     @Override
     public List<MarkLibrary> findUnMarked(Integer examId, String subjectCode, Integer groupNumber, Integer markerId,
-            Integer userId, boolean filterClass, int pageNumber, int pageSize) {
-        Set<LibraryStatus> statusSet = new HashSet<>();
-        statusSet.add(LibraryStatus.WAITING);
-
+            Integer userId, boolean filterClass, int pageNumber, int pageSize, Set<LibraryStatus> statusSet) {
         MarkLibrarySearchQuery query = new MarkLibrarySearchQuery();
         query.setPageNumber(pageNumber);
         query.setPageSize(pageSize);
@@ -136,9 +134,8 @@ public class MarkLibraryServiceImpl extends BaseQueryService<MarkLibrary> implem
                     Predicate predicate2 = cb.le(root.get("markerScore"), query.getEndScroe());
                     predicates.add(cb.and(predicate1, predicate2));
                 }
-                return predicates.isEmpty() ?
-                        cb.conjunction() :
-                        cb.and(predicates.toArray(new Predicate[predicates.size()]));
+                return predicates.isEmpty() ? cb.conjunction() : cb.and(predicates.toArray(new Predicate[predicates
+                        .size()]));
             }
         };
     }
@@ -164,4 +161,43 @@ public class MarkLibraryServiceImpl extends BaseQueryService<MarkLibrary> implem
         return libraryDao.save(library);
     }
 
+    @Override
+    public void releaseByLibrary(MarkLibrary library) {
+        TaskLock taskLock = TaskLockUtil.getInspectedStudentTask(getGroupKey(library));
+        taskLock.remove(library.getId(), 1);
+    }
+
+    @Override
+    public void releaseByUserId(Integer examId, String subjectCode, Integer groupNumber, Integer userId) {
+        TaskLock taskLock = TaskLockUtil.getInspectedLibraryTask(examId + "_" + subjectCode + "_" + groupNumber);
+        taskLock.clear(userId);
+    }
+
+    @Override
+    public boolean hasApplied(MarkLibrary library, Integer userId) {
+        TaskLock taskLock = TaskLockUtil.getInspectedLibraryTask(getGroupKey(library));
+        return taskLock.exist(library.getId(), 1, userId);
+    }
+
+    @Override
+    public boolean applyLibrary(MarkLibrary library, Integer userId) {
+        TaskLock taskLock = TaskLockUtil.getInspectedLibraryTask(getGroupKey(library));
+        boolean lock = taskLock.add(library.getId(), 1, userId);
+        // 上锁失败直接返回
+        if (!lock) {
+            return false;
+        }
+        // 重复校验任务状态
+        if (library.getStatus().equals(LibraryStatus.MARKED)) {
+            return true;
+        } else {
+            taskLock.remove(library.getId(), 1, userId);
+            return false;
+        }
+    }
+
+    private String getGroupKey(MarkLibrary library) {
+        return library.getExamId() + "_" + library.getSubjectCode() + "_" + library.getGroupNumber();
+    }
+
 }

+ 92 - 8
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/mark/service/Impl/MarkServiceImpl.java

@@ -13,6 +13,7 @@ import cn.com.qmth.stmms.biz.utils.TaskLock;
 import cn.com.qmth.stmms.biz.utils.TaskLockUtil;
 import cn.com.qmth.stmms.common.enums.*;
 import cn.com.qmth.stmms.common.utils.BigDecimalUtils;
+
 import org.apache.commons.lang.StringUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -474,7 +475,7 @@ public class MarkServiceImpl implements MarkService {
         // 判断评卷分组是否存在/评卷是否结束
         MarkGroup group = groupDao.findOne(marker.getExamId(), marker.getSubjectCode(), marker.getGroupNumber());
         if (group == null || group.getStatus() == MarkStatus.FINISH
-                || !group.getStatus().equals(result.getStatusValue())) {
+                || !group.getStatus().toString().equals(result.getStatusValue())) {
             return SubmitResult.faile();
         }
 
@@ -494,7 +495,8 @@ public class MarkServiceImpl implements MarkService {
             if (library != null && library.getExamId().equals(group.getExamId())
                     && library.getSubjectCode().equals(group.getSubjectCode())
                     && library.getGroupNumber().equals(group.getNumber())
-                    && result.getTotalScore() <= group.getTotalScore() && StringUtils.isNotBlank(result.getScoreList())) {
+                    && result.getMarkerScore() <= group.getTotalScore()
+                    && StringUtils.isNotBlank(result.getScoreList())) {
                 if (submitLibrary(library, marker, group, result)) {
                     updateMarkedCount(group);
                     return SubmitResult.success(library);
@@ -505,7 +507,8 @@ public class MarkServiceImpl implements MarkService {
             if (library != null && library.getExamId().equals(group.getExamId())
                     && library.getSubjectCode().equals(group.getSubjectCode())
                     && library.getGroupNumber().equals(group.getNumber())
-                    && result.getTotalScore() <= group.getTotalScore() && StringUtils.isNotBlank(result.getScoreList())) {
+                    && result.getMarkerScore() <= group.getTotalScore()
+                    && StringUtils.isNotBlank(result.getScoreList())) {
                 TrialHistory history = new TrialHistory();
                 history.setExamId(library.getExamId());
                 history.setSubjectCode(library.getSubjectCode());
@@ -514,7 +517,7 @@ public class MarkServiceImpl implements MarkService {
                 history.setStudentId(library.getStudentId());
                 history.setMarkerId(marker.getId());
                 history.setMarkerTime(new Date());
-                history.setMarkerScore(result.getTotalScore());
+                history.setMarkerScore(result.getMarkerScore());
                 history.setMarkerScoreList(result.getScoreList());
                 history.setSecretNumber(library.getSecretNumber());
                 history = trialHistoryDao.save(history);
@@ -523,7 +526,7 @@ public class MarkServiceImpl implements MarkService {
                         trialTrackDao.deleteByLibraryIdAndMarkerId(history.getLibraryId(), history.getMarkerId());
                         trialTrackDao.save(result.getTrackList(history));
                     }
-                    if (result.getTagList() != null) {
+                    if (result.getSpecialTagList() != null) {
                         trialTagDao.deleteByLibraryIdAndMarkerId(history.getLibraryId(), history.getMarkerId());
                         trialTagDao.save(result.getTagList(history));
                     }
@@ -584,7 +587,7 @@ public class MarkServiceImpl implements MarkService {
         // 尝试提交评卷结果
         Date now = new Date();
         if (libraryDao.updateMarkerResult(library.getId(), LibraryStatus.MARKED, marker.getId(),
-                result.getTotalScore(), result.getScoreList(), now, result.getSpent(), LibraryStatus.WAITING,
+                result.getMarkerScore(), result.getScoreList(), now, result.getSpent(), LibraryStatus.WAITING,
                 LibraryStatus.MARKED, LibraryStatus.INSPECTED) == 0) {
             // 条件不符更新失败,直接返回
             return false;
@@ -598,7 +601,7 @@ public class MarkServiceImpl implements MarkService {
             }
         }
         // 保存特殊标记
-        if (result.getTagList() != null) {
+        if (result.getSpecialTagList() != null) {
             specialTagDao.deleteByLibraryId(library.getId());
             specialTagDao.save(result.getSpecialTagList(library, marker));
         }
@@ -614,7 +617,7 @@ public class MarkServiceImpl implements MarkService {
                     continue;
                 }
                 // 分差超过阀值,
-                if (Math.abs(other.getMarkerScore() - result.getTotalScore()) > group.getArbitrateThreshold()) {
+                if (Math.abs(other.getMarkerScore() - result.getMarkerScore()) > group.getArbitrateThreshold()) {
                     // 开启三评
                     if (group.getThirdPolicy().equals(ThirdPolicy.LOW_DIFF_HIGH_AVG)) {
                         if (libraryDao.countByStudentIdAndGroupNumber(library.getStudentId(), library.getGroupNumber()) == 2) {
@@ -1344,4 +1347,85 @@ public class MarkServiceImpl implements MarkService {
         return false;
     }
 
+    @Override
+    @Transactional
+    public boolean rejectedStudent(ExamStudent student, MarkStepDTO[] markStepDTOs, Integer userId) {
+        Map<MarkGroup, List<MarkStepDTO>> map = new HashMap<MarkGroup, List<MarkStepDTO>>();
+
+        for (MarkStepDTO markStepDTO : markStepDTOs) {
+            MarkGroup group = groupDao.findOne(student.getExamId(), student.getSubjectCode(),
+                    markStepDTO.getGroupNumber());
+            if (group.getStatus() == MarkStatus.FINISH) {
+                return false;
+            }
+            List<MarkStepDTO> list = map.get(group);
+            if (list == null) {
+                list = new ArrayList<MarkStepDTO>();
+            }
+            list.add(markStepDTO);
+            map.put(group, list);
+        }
+        for (MarkGroup group : map.keySet()) {
+            List<MarkLibrary> list = libraryDao.findByStudentIdAndGroupNumber(student.getId(), group.getNumber());
+            List<ExamQuestion> questions = questionDao.findByExamIdAndSubjectCodeAndObjectiveAndGroupNumber(
+                    group.getExamId(), group.getSubjectCode(), false, group.getNumber());
+            int count = 0;
+            for (MarkLibrary library : list) {
+                if (library.getTaskNumber() == 3) {
+                    // 出现三评时删除第三条任务
+                    problemHistoryDao.deleteByLibraryId(library.getId());
+                    libraryDao.delete(library);
+                    updateLibraryCount(group);
+                    count++;
+                    continue;
+                }
+                if (library.getStatus().equals(LibraryStatus.ARBITRATED)) {
+                    // 仲裁任务直接重置
+                    libraryDao.resetById(library.getId(), LibraryStatus.WAITING, LibraryStatus.MARKED,
+                            LibraryStatus.PROBLEM, LibraryStatus.INSPECTED);
+                    trackDao.deleteByLibraryId(library.getId());
+                    specialTagDao.deleteByLibraryId(library.getId());
+                    count++;
+                    continue;
+                }
+                if (library.getStatus().equals(LibraryStatus.MARKED)) {
+                    List<MarkStepDTO> qList = map.get(group);
+                    List<ScoreItem> sList = library.getScoreList();
+                    for (MarkStepDTO markStepDTO : qList) {
+                        trackDao.deleteByLibraryIdAndQuestionNumber(library.getId(), markStepDTO.getMainNumber() + "."
+                                + markStepDTO.getSubNumber());
+                        for (int i = 0; i < questions.size(); i++) {
+                            ExamQuestion question = questions.get(i);
+                            if (markStepDTO.getMainNumber() == question.getMainNumber()
+                                    && markStepDTO.getSubNumber().equals(markStepDTO.getSubNumber())) {
+                                sList.remove(i);
+                                sList.add(i, new ScoreItem(false));
+                            }
+                        }
+                    }
+                    StringBuilder markerScoreList = new StringBuilder();
+                    for (int i = 0; i < sList.size(); i++) {
+                        ScoreItem scoreItem = sList.get(i);
+                        if (scoreItem.getScore() != null) {
+                            markerScoreList.append(scoreItem.getScore());
+                        }
+                        if (i < sList.size() - 1) {
+                            markerScoreList.append(",");
+                        }
+                    }
+                    libraryDao.updateMarkerResult(library.getId(), LibraryStatus.REJECTED, null, null,
+                            markerScoreList.toString(), null, null, LibraryStatus.MARKED);
+                    count++;
+                }
+            }
+            if (count > 0) {
+                updateMarkedCount(group);
+                resetStudentGroup(student.getId(), group.getExamId(), group.getSubjectCode(), group.getNumber());
+                studentService.updateSubjectiveStatusAndTimeAndInspectorId(student.getId(), SubjectiveStatus.UNMARK,
+                        null, null);
+                return true;
+            }
+        }
+        return false;
+    }
 }

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

@@ -4,6 +4,7 @@ import java.util.ArrayList;
 import java.util.LinkedList;
 import java.util.List;
 
+import org.apache.commons.lang.StringUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -14,7 +15,6 @@ import cn.com.qmth.stmms.biz.exam.model.ExamQuestion;
 import cn.com.qmth.stmms.biz.exam.model.ExamStudent;
 import cn.com.qmth.stmms.biz.exam.model.ExamSubject;
 import cn.com.qmth.stmms.biz.exam.model.MarkGroup;
-import cn.com.qmth.stmms.biz.exam.model.Marker;
 import cn.com.qmth.stmms.biz.exam.service.ExamQuestionService;
 import cn.com.qmth.stmms.biz.exam.service.ExamService;
 import cn.com.qmth.stmms.biz.exam.service.ExamStudentService;
@@ -23,12 +23,10 @@ import cn.com.qmth.stmms.biz.exam.service.MarkGroupService;
 import cn.com.qmth.stmms.biz.exam.service.MarkerService;
 import cn.com.qmth.stmms.biz.file.service.FileService;
 import cn.com.qmth.stmms.biz.mark.model.ArbitrateHistory;
-import cn.com.qmth.stmms.biz.mark.model.ArbitrationDTO;
 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.MarkStepDTO;
 import cn.com.qmth.stmms.biz.mark.model.MarkTrack;
-import cn.com.qmth.stmms.biz.mark.model.PictureConfigItem;
 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.TrackDTO;
@@ -108,7 +106,6 @@ public class TaskServiceImpl implements TaskService {
     @Override
     public Task build(ArbitrateHistory history, MarkGroup group) {
         ExamStudent student = studentService.findByExamIdAndExamNumber(history.getExamId(), history.getExamNumber());
-        List<MarkLibrary> libraryList = libraryService.findByStudentAndGroup(student.getId(), group.getNumber());
         Task task = new Task();
         task.setStudentId(history.getStudentId());
         task.setLibraryId(history.getId());
@@ -118,25 +115,13 @@ public class TaskServiceImpl implements TaskService {
                 student.getSliceCount()));
         task.setSliceConfig(group.getPictureConfigList());
         task.setJsonUrl(fileService.getJsonUri(student.getExamId(), student.getSecretNumber()));
-        task.setObjectiveScore(student.getObjectiveScore() != null ? student.getObjectiveScore() : 0);
+        if (StringUtils.isNotBlank(student.getObjectiveScoreList())) {
+            task.setObjectiveScore(student.getObjectiveScore());
+        }
         task.setMarkTime(history.getUpdateTime());
-        // 构造仲裁信息
-        List<ArbitrationDTO> list = new ArrayList<ArbitrationDTO>();
-        for (MarkLibrary library : libraryList) {
-            if (library.getStatus() != LibraryStatus.WAITING) {
-                Marker marker = markerService.findById(library.getMarkerId());
-                marker.setUser(userService.findById(marker.getUserId()));
-                list.add(new ArbitrationDTO(library, marker));
-            }
+        if (history.getTotalScore() != null) {
+            task.setMarkerScore(history.getTotalScore());
         }
-        // task.setArbitrationList(list);
-        // 回评状态下的打分信息
-        // if (history.getTotalScore() != null) {
-        // task.setTotalScore(history.getTotalScore());
-        // }
-        // if (history.getScoreList() != null) {
-        // task.setScoreList(history.getScoreList());
-        // }
         return task;
     }
 
@@ -166,7 +151,9 @@ public class TaskServiceImpl implements TaskService {
         }
         task.setQuestionList(buildMarkStep(group, library));
         task.setSpecialTagList(getMarkSpecialTagList(library.getId()));
-        task.setObjectiveScore(student.getObjectiveScore() != null ? student.getObjectiveScore() : 0);
+        if (StringUtils.isNotBlank(student.getObjectiveScoreList())) {
+            task.setObjectiveScore(student.getObjectiveScore());
+        }
         task.setMarkTime(library.getMarkerTime());
         if (library.getStatus() == LibraryStatus.REJECTED && library.getMarkerId() != null) {
             task.setRejected(true);
@@ -194,7 +181,9 @@ public class TaskServiceImpl implements TaskService {
         task.setExamNumber(library.getExamNumber());
         task.setSubject(subject);
         task.setQuestionList(buildTrialStep(group, history));
-        task.setObjectiveScore(student.getObjectiveScore());
+        if (StringUtils.isNotBlank(student.getObjectiveScoreList())) {
+            task.setObjectiveScore(student.getObjectiveScore());
+        }
         if (ExamType.MULTI_MEDIA.equals(exam.getType())) {
             task.setJsonUrl(fileService.getJsonUri(library.getExamId(), library.getSecretNumber()));
         } else {
@@ -208,7 +197,7 @@ public class TaskServiceImpl implements TaskService {
             task.setSpecialTagList(getTrialTagList(history));
             task.setMarkTime(history.getMarkerTime());
             task.setMarkerScore(history.getMarkerScore());
-            task.setRejected(true);
+            task.setPrevious(true);
         }
         return task;
     }
@@ -274,9 +263,9 @@ public class TaskServiceImpl implements TaskService {
         step.setGroupNumber(question.getGroupNumber());
         step.setTitle(question.getMainTitle());
         step.setDefaultScore(0d);
-        step.setMax(question.getTotalScore());
-        step.setMin(0d);
-        step.setInterval(question.getIntervalScore());
+        step.setMaxScore(question.getTotalScore());
+        step.setMinScore(0d);
+        step.setIntervalScore(question.getIntervalScore());
         return step;
     }
 
@@ -319,13 +308,12 @@ public class TaskServiceImpl implements TaskService {
     }
 
     @Override
-    public Task build(Integer studentId) {
-        ExamStudent student = studentService.findById(studentId);
+    public Task build(ExamStudent student) {
         ExamSubject subject = subjectService.find(student.getExamId(), student.getSubjectCode());
         Exam exam = examService.findById(student.getExamId());
 
         Task task = new Task();
-        task.setStudentId(studentId);
+        task.setStudentId(student.getId());
         task.setSecretNumber(student.getSecretNumber());
         task.setStudentCode(student.getStudentCode());
         task.setStudentName(student.getName());
@@ -340,18 +328,34 @@ public class TaskServiceImpl implements TaskService {
                     student.getSheetCount()));
         }
         task.setQuestionList(buildMarkStep(student));
-        // task.setSpecialTagList(getMarkSpecialTagList(library.getId()));
-        task.setObjectiveScore(student.getObjectiveScore() != null ? student.getObjectiveScore() : 0);
+        task.setSpecialTagList(getMarkSpecialTagList(student));
+        if (StringUtils.isNotBlank(student.getObjectiveScoreList())) {
+            task.setObjectiveScore(student.getObjectiveScore());
+        }
         task.setMarkerScore(student.getTotalScore());
+        task.setInspectTime(student.getInspectTime());
         return task;
     }
 
-    private List<PictureConfigItem> buildPictureConfig(int picCount) {
-        List<PictureConfigItem> list = new LinkedList<PictureConfigItem>();
-        for (int i = 1; i <= picCount; i++) {
-            list.add(new PictureConfigItem(String.valueOf(i)));
+    private SpecialTagDTO[] getMarkSpecialTagList(ExamStudent student) {
+        List<SpecialTagDTO> list = new ArrayList<SpecialTagDTO>();
+        List<MarkGroup> groups = groupService.findByExamAndSubject(student.getExamId(), student.getSubjectCode());
+        for (MarkGroup group : groups) {
+            List<MarkLibrary> libraryList = libraryService.findByStudentAndGroup(student.getId(), group.getNumber());
+            if (libraryList.size() == 1) {
+                SpecialTagDTO[] tags = getMarkSpecialTagList(libraryList.get(0).getId());
+                if (tags != null) {
+                    for (SpecialTagDTO specialTagDTO : tags) {
+                        list.add(specialTagDTO);
+                    }
+                }
+            }
         }
-        return list;
+        SpecialTagDTO[] specialTags = new SpecialTagDTO[list.size()];
+        for (int i = 0; i < list.size(); i++) {
+            specialTags[i] = list.get(i);
+        }
+        return specialTags;
     }
 
     private List<MarkStepDTO> buildMarkStep(ExamStudent student) {
@@ -366,16 +370,19 @@ public class TaskServiceImpl implements TaskService {
                 step.setScore(sItems.get(i).getScore());
             }
             // 增加阅卷轨迹列表获取
-            List<MarkTrack> tracks = trackService.findByStudentId(student.getId());
-            String questionNumber = question.getQuestionNumber();
-            for (MarkTrack track : tracks) {
-                if (track.getQuestionNumber().equals(questionNumber)) {
-                    step.addTrack(new TrackDTO(track));
+            MarkGroup group = groupService.findOne(student.getExamId(), student.getSubjectCode(),
+                    question.getGroupNumber());
+            if (group.getDoubleRate() == null || group.getDoubleRate() == 0) {
+                List<MarkTrack> tracks = trackService.findByStudentId(student.getId());
+                String questionNumber = question.getQuestionNumber();
+                for (MarkTrack track : tracks) {
+                    if (track.getQuestionNumber().equals(questionNumber)) {
+                        step.addTrack(new TrackDTO(track));
+                    }
                 }
             }
             list.add(step);
         }
         return list;
     }
-
 }

+ 10 - 1
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/mark/service/MarkLibraryService.java

@@ -1,6 +1,7 @@
 package cn.com.qmth.stmms.biz.mark.service;
 
 import java.util.List;
+import java.util.Set;
 
 import cn.com.qmth.stmms.biz.mark.model.MarkLibrary;
 import cn.com.qmth.stmms.biz.mark.query.MarkLibrarySearchQuery;
@@ -17,7 +18,7 @@ public interface MarkLibraryService {
     MarkLibrarySearchQuery findByQuery(MarkLibrarySearchQuery query);
 
     List<MarkLibrary> findUnMarked(Integer examId, String subjectCode, Integer groupNumber, Integer markerId,
-            Integer userId, boolean filterClass, int pageNumber, int pageSize);
+            Integer userId, boolean filterClass, int pageNumber, int pageSize, Set<LibraryStatus> statusSet);
 
     long countByExamAndSubjectAndGroupAndStatus(int examId, String subjectCode, int groupNumber, LibraryStatus status);
 
@@ -34,4 +35,12 @@ public interface MarkLibraryService {
 
     MarkLibrary save(MarkLibrary library);
 
+    void releaseByLibrary(MarkLibrary library);
+
+    void releaseByUserId(Integer examId, String subjectCode, Integer groupNumber, Integer userId);
+
+    boolean hasApplied(MarkLibrary library, Integer userId);
+
+    boolean applyLibrary(MarkLibrary library, Integer userId);
+
 }

+ 10 - 0
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/mark/service/MarkService.java

@@ -228,4 +228,14 @@ public interface MarkService {
      * @return
      */
     boolean backStudentByGroup(ExamStudent student, Integer groupNumber, Integer userId);
+
+    /**
+     * 管理员/组长打回某个学生的指定题目
+     * 
+     * @param student
+     * @param questionList
+     * @param userId
+     * @return
+     */
+    boolean rejectedStudent(ExamStudent student, MarkStepDTO[] questionList, Integer userId);
 }

+ 7 - 6
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/mark/service/MarkSpecialTagService.java

@@ -5,14 +5,15 @@ import java.util.List;
 import cn.com.qmth.stmms.biz.mark.model.MarkSpecialTag;
 
 public interface MarkSpecialTagService {
-	public MarkSpecialTag save(MarkSpecialTag tag);
 
-	public void deleteByLibraryId(Integer libraryId);
+    public MarkSpecialTag save(MarkSpecialTag tag);
 
-	public List<MarkSpecialTag> findByLibraryId(Integer libraryId);
+    public void deleteByLibraryId(Integer libraryId);
 
-	public void deleteByMarkerId(Integer markerId);
+    public List<MarkSpecialTag> findByLibraryId(Integer libraryId);
+
+    public void deleteByMarkerId(Integer markerId);
+
+    public void deleteByExamAndSubjectAndGroup(Integer examId, String subjectCode, Integer number);
 
-	public void deleteByExamAndSubjectAndGroup(Integer examId,
-			String subjectCode, Integer number);
 }

+ 2 - 1
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/mark/service/TaskService.java

@@ -2,6 +2,7 @@ package cn.com.qmth.stmms.biz.mark.service;
 
 import java.util.List;
 
+import cn.com.qmth.stmms.biz.exam.model.ExamStudent;
 import cn.com.qmth.stmms.biz.exam.model.MarkGroup;
 import cn.com.qmth.stmms.biz.mark.model.ArbitrateHistory;
 import cn.com.qmth.stmms.biz.mark.model.MarkLibrary;
@@ -20,6 +21,6 @@ public interface TaskService {
 
     Task build(MarkLibrary library);
 
-    Task build(Integer studentId);
+    Task build(ExamStudent student);
 
 }

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

@@ -16,7 +16,7 @@ public class ScoreItem {
 
     private String title;
 
-    private double score;
+    private Double score;
 
     private String answer;
 
@@ -57,11 +57,11 @@ public class ScoreItem {
         this.title = title;
     }
 
-    public double getScore() {
+    public Double getScore() {
         return score;
     }
 
-    public void setScore(double score) {
+    public void setScore(Double score) {
         this.score = score;
     }
 

+ 14 - 0
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/utils/TaskLock.java

@@ -80,6 +80,20 @@ public class TaskLock {
         return false;
     }
 
+    public synchronized boolean remove(Object id, int number) {
+        LockNode node = head.next;
+        while (node != null) {
+            if (node.isId(id) && node.isNumber(number)) {
+                node.remove();
+                count--;
+                return true;
+            } else {
+                node = node.next;
+            }
+        }
+        return false;
+    }
+
     public synchronized void clear() {
         head.next = null;
         count = 0;

+ 28 - 0
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/utils/TaskLockUtil.java

@@ -11,6 +11,12 @@ public class TaskLockUtil {
     // 试评任务并发处理互斥锁
     private static final Map<String, TaskLock> trialTaskMap = new HashMap<>();
 
+    // 复核整卷并发处理互斥锁
+    private static final Map<String, TaskLock> inspectedStudentMap = new HashMap<>();
+
+    // 复核评卷任务并发处理互斥锁
+    private static final Map<String, TaskLock> inspectedLibraryMap = new HashMap<>();
+
     public static void clearTimeoutTask(long timeoutMinute) {
         for (TaskLock taskLock : trialTaskMap.values()) {
             taskLock.expire(timeoutMinute);
@@ -18,6 +24,9 @@ public class TaskLockUtil {
         for (TaskLock taskLock : formalTaskMap.values()) {
             taskLock.expire(timeoutMinute);
         }
+        for (TaskLock taskLock : inspectedStudentMap.values()) {
+            taskLock.expire(timeoutMinute);
+        }
     }
 
     public static TaskLock getTrialTask(String key) {
@@ -40,4 +49,23 @@ public class TaskLockUtil {
         return taskLock;
     }
 
+    public static TaskLock getInspectedStudentTask(String key) {
+        TaskLock taskLock = inspectedStudentMap.get(key);
+        if (taskLock == null) {
+            synchronized (inspectedStudentMap) {
+                taskLock = inspectedStudentMap.computeIfAbsent(key, k -> new TaskLock());
+            }
+        }
+        return taskLock;
+    }
+
+    public static TaskLock getInspectedLibraryTask(String key) {
+        TaskLock taskLock = inspectedLibraryMap.get(key);
+        if (taskLock == null) {
+            synchronized (inspectedLibraryMap) {
+                taskLock = inspectedLibraryMap.computeIfAbsent(key, k -> new TaskLock());
+            }
+        }
+        return taskLock;
+    }
 }

+ 2 - 0
stmms-biz/src/main/resources/META-INF/persistence.xml

@@ -14,6 +14,8 @@
 				value="true" />
 			<property name="hibernate.cache.provider_class" value="org.hibernate.cache.SingletonEhCacheProvider"/>
 			<property name="hibernate.cache.use_query_cache" value="true" />
+			<property name="hibernate.query.plan_cache_max_size" value="512"/>
+			<property name="hibernate.query.plan_parameter_metadata_max_size" value="64"/>
 		</properties>
 	</persistence-unit>
 </persistence>  

+ 30 - 0
stmms-web/src/main/java/cn/com/qmth/stmms/admin/dto/RejectResult.java

@@ -0,0 +1,30 @@
+package cn.com.qmth.stmms.admin.dto;
+
+import cn.com.qmth.stmms.biz.mark.model.MarkStepDTO;
+
+public class RejectResult {
+
+    /**
+     * 考生编号
+     */
+    private Integer studentId;
+
+    private MarkStepDTO[] questionList;
+
+    public Integer getStudentId() {
+        return studentId;
+    }
+
+    public void setStudentId(Integer studentId) {
+        this.studentId = studentId;
+    }
+
+    public MarkStepDTO[] getQuestionList() {
+        return questionList;
+    }
+
+    public void setQuestionList(MarkStepDTO[] questionList) {
+        this.questionList = questionList;
+    }
+
+}

+ 97 - 87
stmms-web/src/main/java/cn/com/qmth/stmms/admin/exam/ArbitrateController.java

@@ -1,40 +1,64 @@
 package cn.com.qmth.stmms.admin.exam;
 
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import javax.servlet.http.HttpServletRequest;
+
+import net.sf.json.JSONObject;
+
+import org.apache.commons.lang.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.domain.Sort;
+import org.springframework.data.domain.Sort.Direction;
+import org.springframework.stereotype.Controller;
+import org.springframework.ui.Model;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestBody;
+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.ResponseBody;
+
 import cn.com.qmth.stmms.biz.exam.model.Exam;
 import cn.com.qmth.stmms.biz.exam.model.ExamSubject;
 import cn.com.qmth.stmms.biz.exam.model.MarkGroup;
+import cn.com.qmth.stmms.biz.exam.model.Marker;
 import cn.com.qmth.stmms.biz.exam.service.ExamQuestionService;
 import cn.com.qmth.stmms.biz.exam.service.ExamService;
 import cn.com.qmth.stmms.biz.exam.service.ExamSubjectService;
 import cn.com.qmth.stmms.biz.exam.service.MarkGroupService;
+import cn.com.qmth.stmms.biz.exam.service.MarkerService;
 import cn.com.qmth.stmms.biz.file.service.FileService;
 import cn.com.qmth.stmms.biz.lock.LockService;
 import cn.com.qmth.stmms.biz.mark.model.ArbitrateHistory;
+import cn.com.qmth.stmms.biz.mark.model.ArbitrationDTO;
+import cn.com.qmth.stmms.biz.mark.model.MarkLibrary;
+import cn.com.qmth.stmms.biz.mark.model.MarkResult;
 import cn.com.qmth.stmms.biz.mark.model.Task;
 import cn.com.qmth.stmms.biz.mark.query.ArbitrateHistorySearchQuery;
 import cn.com.qmth.stmms.biz.mark.service.ArbitrateHistoryService;
+import cn.com.qmth.stmms.biz.mark.service.MarkLibraryService;
 import cn.com.qmth.stmms.biz.mark.service.MarkService;
 import cn.com.qmth.stmms.biz.mark.service.TaskService;
 import cn.com.qmth.stmms.biz.user.service.UserService;
 import cn.com.qmth.stmms.common.annotation.Logging;
 import cn.com.qmth.stmms.common.annotation.RoleRequire;
 import cn.com.qmth.stmms.common.domain.WebUser;
-import cn.com.qmth.stmms.common.enums.*;
+import cn.com.qmth.stmms.common.enums.HistoryStatus;
+import cn.com.qmth.stmms.common.enums.LibraryStatus;
+import cn.com.qmth.stmms.common.enums.LockType;
+import cn.com.qmth.stmms.common.enums.LogType;
+import cn.com.qmth.stmms.common.enums.Role;
 import cn.com.qmth.stmms.common.utils.RequestUtils;
-import net.sf.json.JSONObject;
-
-import org.apache.commons.lang.StringUtils;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.data.domain.Sort;
-import org.springframework.data.domain.Sort.Direction;
-import org.springframework.stereotype.Controller;
-import org.springframework.ui.Model;
-import org.springframework.web.bind.annotation.*;
-
-import javax.servlet.http.HttpServletRequest;
-import java.util.*;
 
 @Controller("arbitrateController")
 @RequestMapping("/admin/exam/arbitrate")
@@ -72,6 +96,12 @@ public class ArbitrateController extends BaseExamController {
     @Autowired
     private FileService fileService;
 
+    @Autowired
+    private MarkerService markerService;
+
+    @Autowired
+    private MarkLibraryService libraryService;
+
     // 并发处理互斥锁
     private Map<Integer, Integer> currentTaskMap = new HashMap<Integer, Integer>();
 
@@ -110,63 +140,34 @@ public class ArbitrateController extends BaseExamController {
         return "modules/exam/arbitrateList";
     }
 
-    @RequestMapping("/process")
+    @RequestMapping("/getSetting")
     @RoleRequire({ Role.SCHOOL_ADMIN, Role.SUBJECT_HEADER })
-    public String singleProcess(Model model, HttpServletRequest request, @RequestParam Integer historyId) {
+    @ResponseBody
+    public JSONObject getSetting(Model model, HttpServletRequest request,
+            @RequestParam(required = false) String subjectCode, @RequestParam(required = false) Integer groupNumber,
+            @RequestParam(required = false) Integer historyId) {
         int examId = getSessionExamId(request);
         WebUser wu = RequestUtils.getWebUser(request);
-        ArbitrateHistory history = arbitrateService.findById(historyId);
-        if (history == null || !history.getExamId().equals(examId) || !subjectCheck(history.getSubjectCode(), wu)) {
-            return "redirect:/admin/exam/arbitrate";
-        }
-        MarkGroup group = groupService.findOne(examId, history.getSubjectCode(), history.getGroupNumber());
-        if (group == null) {
-            return "redirect:/admin/exam/arbitrate";
-        }
-        ExamSubject subject = subjectService.find(group.getExamId(), group.getSubjectCode());
-        if (subject == null) {
-            return "redirect:/admin/exam/arbitrate";
-        }
         releaseByUser(wu.getUser().getId());
-        subject.setPaperAnswerUrl(fileService);
-        model.addAttribute("fileServer", fileService.getFileServer());
-        model.addAttribute("subject", subject);
-        model.addAttribute("group", group);
-        model.addAttribute("history", history);
-        Exam exam = examService.findById(examId);
-        if (ExamType.MULTI_MEDIA.equals(exam.getType())) {
-            return "modules/exam/arbitrateSingleProcessJson";
-        }
-        return "modules/exam/arbitrateSingleProcess";
-    }
+        JSONObject setting = new JSONObject();
 
-    @RequestMapping("/batchProcess")
-    @RoleRequire({ Role.SCHOOL_ADMIN, Role.SUBJECT_HEADER })
-    public String batchProcess(Model model, HttpServletRequest request, @RequestParam String subjectCode,
-            @RequestParam Integer groupNumber) {
-        int examId = getSessionExamId(request);
-        WebUser wu = RequestUtils.getWebUser(request);
-        if (!subjectCheck(subjectCode, wu)) {
-            return "redirect:/admin/exam/arbitrate";
+        if (historyId != null) {
+            ArbitrateHistory history = arbitrateService.findById(historyId);
+            subjectCode = history.getSubjectCode();
+            groupNumber = history.getGroupNumber();
         }
-        MarkGroup group = groupService.findOne(examId, subjectCode, groupNumber);
-        if (group == null) {
-            return "redirect:/admin/exam/arbitrate";
-        }
-        ExamSubject subject = subjectService.find(group.getExamId(), group.getSubjectCode());
-        if (subject == null) {
-            return "redirect:/admin/exam/arbitrate";
-        }
-        releaseByUser(wu.getUser().getId());
-        subject.setPaperAnswerUrl(fileService);
-        model.addAttribute("fileServer", fileService.getFileServer());
-        model.addAttribute("subject", subject);
-        model.addAttribute("group", group);
+        ExamSubject examSubject = subjectService.find(examId, subjectCode);
+        setting.accumulate("fileServer", fileService.getFileServer());
         Exam exam = examService.findById(examId);
-        if (ExamType.MULTI_MEDIA.equals(exam.getType())) {
-            return "modules/exam/arbitrateBatchProcessJson";
-        }
-        return "modules/exam/arbitrateBatchProcess";
+        setting.accumulate("mode", exam.getType());
+        setting.accumulate("userName", wu.getName());
+        JSONObject subject = new JSONObject();
+        subject.accumulate("name", examSubject.getName());
+        subject.accumulate("code", examSubject.getCode());
+        subject.accumulate("paperUrl", examSubject.getPaperUrl() == null ? "" : examSubject.getPaperUrl());
+        subject.accumulate("answerUrl", examSubject.getAnswerUrl() == null ? "" : examSubject.getAnswerUrl());
+        setting.accumulate("subject", subject);
+        return setting;
     }
 
     @Logging(menu = "打回仲裁任务", type = LogType.UPDATE)
@@ -239,35 +240,26 @@ public class ArbitrateController extends BaseExamController {
             }
             query = arbitrateService.findByQuery(query);
             for (ArbitrateHistory history : query.getResult()) {
-                list.add(taskService.build(history, group));
+                Task task = taskService.build(history, group);
+                task.setPrevious(true);
+                list.add(task);
             }
         }
         return list;
     }
 
-    @RequestMapping("/singleTask")
+    @RequestMapping("/getTask")
     @ResponseBody
     @RoleRequire({ Role.SCHOOL_ADMIN, Role.SUBJECT_HEADER })
-    public Task getSingleTask(HttpServletRequest request, @RequestParam Integer historyId) {
+    public Task getTask(HttpServletRequest request, @RequestParam(required = false) String subjectCode,
+            @RequestParam(required = false) Integer groupNumber, @RequestParam(required = false) Integer historyId) {
         int examId = getSessionExamId(request);
         WebUser wu = RequestUtils.getWebUser(request);
-        ArbitrateHistory history = arbitrateService.findById(historyId);
-        if (history != null && history.getExamId().equals(examId) && subjectCheck(history.getSubjectCode(), wu)) {
-            MarkGroup group = groupService.findOne(history.getExamId(), history.getSubjectCode(),
-                    history.getGroupNumber());
+        if (historyId != null) {
+            ArbitrateHistory history = arbitrateService.findById(historyId);
+            MarkGroup group = groupService.findOne(examId, history.getSubjectCode(), history.getGroupNumber());
             return taskService.build(history, group);
         }
-        Task task = new Task();
-        // task.setExist(false);
-        return task;
-    }
-
-    @RequestMapping("/getTask")
-    @ResponseBody
-    @RoleRequire({ Role.SCHOOL_ADMIN, Role.SUBJECT_HEADER })
-    public Task getTask(HttpServletRequest request, @RequestParam String subjectCode, @RequestParam Integer groupNumber) {
-        int examId = getSessionExamId(request);
-        WebUser wu = RequestUtils.getWebUser(request);
         MarkGroup group = groupService.findOne(examId, subjectCode, groupNumber);
         if (subjectCheck(subjectCode, wu) && group != null) {
             ArbitrateHistorySearchQuery query = new ArbitrateHistorySearchQuery();
@@ -304,18 +296,18 @@ public class ArbitrateController extends BaseExamController {
     @RequestMapping(value = "/saveTask", method = RequestMethod.POST)
     @ResponseBody
     @RoleRequire({ Role.SCHOOL_ADMIN, Role.SUBJECT_HEADER })
-    public JSONObject saveTask(HttpServletRequest request, @RequestBody Task task) {
+    public JSONObject saveTask(HttpServletRequest request, @RequestBody MarkResult markResult) {
         WebUser wu = RequestUtils.getWebUser(request);
         JSONObject result = new JSONObject();
-        ArbitrateHistory history = arbitrateService.findById(task.getLibraryId());
-        if (history != null && subjectCheck(history.getSubjectCode(), wu) && task.getMarkerScore() >= 0) {
+        ArbitrateHistory history = arbitrateService.findById(markResult.getLibraryId());
+        if (history != null && subjectCheck(history.getSubjectCode(), wu) && markResult.getMarkerScore() >= 0) {
             try {
                 lockService.watch(LockType.EXAM_SUBJECT, history.getExamId(), history.getSubjectCode());
                 lockService.watch(LockType.GROUP, history.getExamId(), history.getSubjectCode(),
                         history.getGroupNumber());
 
                 history.setUserId(wu.getUser().getId());
-                history.setTotalScore(task.getMarkerScore());
+                history.setTotalScore(markResult.getMarkerScore());
                 // history.setScoreList(task.getScoreList());
                 history.setStatus(HistoryStatus.MARKED);
                 history.setUpdateTime(new Date());
@@ -367,6 +359,24 @@ public class ArbitrateController extends BaseExamController {
         return status;
     }
 
+    @RequestMapping("/getArbitrationList")
+    @ResponseBody
+    @RoleRequire({ Role.SCHOOL_ADMIN, Role.SUBJECT_HEADER })
+    public Object getList(HttpServletRequest request, @RequestParam Integer historyId) {
+        ArbitrateHistory history = arbitrateService.findById(historyId);
+        List<ArbitrationDTO> list = new ArrayList<ArbitrationDTO>();
+        List<MarkLibrary> libraryList = libraryService.findByStudentAndGroup(history.getStudentId(),
+                history.getGroupNumber());
+        for (MarkLibrary library : libraryList) {
+            if (library.getStatus() != LibraryStatus.WAITING) {
+                Marker marker = markerService.findById(library.getMarkerId());
+                marker.setUser(userService.findById(marker.getUserId()));
+                list.add(new ArbitrationDTO(library, marker));
+            }
+        }
+        return list;
+    }
+
     @RequestMapping("/clear")
     @ResponseBody
     @RoleRequire({ Role.SCHOOL_ADMIN, Role.SUBJECT_HEADER })

+ 155 - 172
stmms-web/src/main/java/cn/com/qmth/stmms/admin/exam/InspectedController.java

@@ -2,48 +2,40 @@ package cn.com.qmth.stmms.admin.exam;
 
 import java.util.ArrayList;
 import java.util.Date;
-import java.util.HashMap;
-import java.util.HashSet;
 import java.util.List;
-import java.util.Map;
-import java.util.Set;
 
 import javax.servlet.http.HttpServletRequest;
 
-import net.sf.json.JSONArray;
 import net.sf.json.JSONObject;
 
 import org.apache.commons.lang.StringUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
 import org.springframework.stereotype.Controller;
 import org.springframework.ui.Model;
+import org.springframework.web.bind.annotation.RequestBody;
 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.ResponseBody;
-import org.springframework.web.servlet.ModelAndView;
 import org.springframework.web.servlet.mvc.support.RedirectAttributes;
 
+import cn.com.qmth.stmms.admin.dto.RejectResult;
 import cn.com.qmth.stmms.biz.exam.model.Exam;
-import cn.com.qmth.stmms.biz.exam.model.ExamQuestion;
 import cn.com.qmth.stmms.biz.exam.model.ExamStudent;
 import cn.com.qmth.stmms.biz.exam.model.ExamSubject;
-import cn.com.qmth.stmms.biz.exam.model.MarkGroup;
-import cn.com.qmth.stmms.biz.exam.model.SubjectiveScore;
 import cn.com.qmth.stmms.biz.exam.query.ExamStudentSearchQuery;
 import cn.com.qmth.stmms.biz.exam.service.ExamQuestionService;
 import cn.com.qmth.stmms.biz.exam.service.ExamService;
 import cn.com.qmth.stmms.biz.exam.service.ExamStudentService;
 import cn.com.qmth.stmms.biz.exam.service.InspectedService;
-import cn.com.qmth.stmms.biz.exam.service.MarkGroupService;
-import cn.com.qmth.stmms.biz.exam.service.SubjectiveScoreService;
 import cn.com.qmth.stmms.biz.file.service.FileService;
 import cn.com.qmth.stmms.biz.lock.LockService;
+import cn.com.qmth.stmms.biz.mark.model.Task;
 import cn.com.qmth.stmms.biz.mark.service.MarkService;
-import cn.com.qmth.stmms.biz.mark.service.MarkSpecialTagService;
-import cn.com.qmth.stmms.biz.mark.service.MarkTrackService;
+import cn.com.qmth.stmms.biz.mark.service.TaskService;
 import cn.com.qmth.stmms.common.annotation.Logging;
 import cn.com.qmth.stmms.common.annotation.RoleRequire;
 import cn.com.qmth.stmms.common.domain.WebUser;
@@ -69,32 +61,23 @@ public class InspectedController extends BaseExamController {
     @Autowired
     private ExamQuestionService questionService;
 
-    @Autowired
-    private MarkTrackService markTrackService;
-
-    @Autowired
-    private MarkSpecialTagService markSpecialTagService;
-
-    @Autowired
-    private MarkGroupService groupService;
-
     @Autowired
     private FileService fileService;
 
     @Autowired
     private LockService lockService;
 
-    @Autowired
-    private SubjectiveScoreService scoreService;
-
     @Autowired
     private MarkService markService;
 
     @Autowired
     private ExamService examService;
 
-    // 并发处理互斥锁
-    private Map<Integer, Integer> currentTaskMap = new HashMap<Integer, Integer>();
+    @Autowired
+    private TaskService taskService;
+
+    @Value("${slice.split.config}")
+    private String splitConfig;
 
     @RequestMapping
     public String list(Model model, HttpServletRequest request, ExamStudentSearchQuery query,
@@ -134,147 +117,103 @@ public class InspectedController extends BaseExamController {
     }
 
     @Logging(menu = "开始考生复核", type = LogType.QUERY)
-    @RequestMapping("/start")
+    @RequestMapping(value = "/getTask", method = RequestMethod.POST)
     @ResponseBody
-    public ModelAndView start(HttpServletRequest request, RedirectAttributes redirectAttributes,
+    public Task getTask(HttpServletRequest request, RedirectAttributes redirectAttributes,
             ExamStudentSearchQuery query, @RequestParam(required = false) Integer mainNumber,
             @RequestParam(required = false) Double mainStartScore, @RequestParam(required = false) Double mainEndScore,
-            @RequestParam(required = false) Double questionScore) {
+            @RequestParam(required = false) Double questionScore, @RequestParam(required = false) Integer studentId) {
         int examId = getSessionExamId(request);
         WebUser wu = RequestUtils.getWebUser(request);
-        releaseByUser(wu.getUser().getId());
-        ModelAndView view = new ModelAndView("modules/exam/inspected");
-        query.setExamId(examId);
-        query.setPageNumber(1);
-        query.setPageSize(Integer.MAX_VALUE);
-        List<ExamSubject> subjectList = getExamSubject(examId, wu);
-        if (StringUtils.isBlank(query.getSubjectCode()) && !subjectList.isEmpty()) {
-            query.setSubjectCode(subjectList.get(0).getCode());
-        }
-        List<ExamStudent> list = inspectedService.findByQuery(query, SubjectiveStatus.MARKED, mainNumber,
-                mainStartScore, mainEndScore, questionScore);
-        List<Integer> ids = new ArrayList<Integer>();
-        if (!list.isEmpty()) {
-            for (ExamStudent student : list) {
-                ids.add(student.getId());
+        Task task = null;
+        if (studentId != null) {
+            releaseStudent(studentId);
+            ExamStudent student = studentService.findById(studentId);
+            if (inspectedService.applyStudent(student, wu.getId())) {
+                task = taskService.build(student);
             }
         }
-        view.addObject("inspectCount", ids.size());
-        view.addObject("fileServer", fileService.getFileServer());
-        view.addObject("ids", StringUtils.join(ids, ","));
-        view.addObject("message", ids.size() > 0 ? "" : "没有待复核的任务");
-        return view;
-    }
-
-    @Logging(menu = "开始考生复核", type = LogType.QUERY)
-    @RequestMapping("/startById")
-    public ModelAndView startById(HttpServletRequest request, RedirectAttributes redirectAttributes,
-            @RequestParam Integer studentId) {
-        WebUser wu = RequestUtils.getWebUser(request);
-        releaseByUser(wu.getUser().getId());
-        ModelAndView view = new ModelAndView("modules/exam/inspected");
-        List<Integer> ids = new ArrayList<Integer>();
-        ExamStudent student = studentService.findById(studentId);
-        if (student != null && student.getSubjectiveStatus().equals(SubjectiveStatus.MARKED)) {
-            releaseTask(studentId);
-            ids.add(studentId);
-        }
-        view.addObject("inspectCount", ids.size());
-        view.addObject("fileServer", fileService.getFileServer());
-        view.addObject("ids", StringUtils.join(ids, ","));
-        view.addObject("studentId", studentId);
-        return view;
-    }
-
-    @RequestMapping("/info")
-    @ResponseBody
-    public Object info(HttpServletRequest request, @RequestParam Integer studentId) {
-        WebUser wu = RequestUtils.getWebUser(request);
-        ExamStudent student = studentService.findById(studentId);
-        JSONObject result = new JSONObject();
-        if (setCurrent(student.getId(), wu.getUser().getId())
-                && student.getSubjectiveStatus().equals(SubjectiveStatus.MARKED)) {
-            result.accumulate("id", student.getId());
-            result.accumulate("secretNumber", student.getSecretNumber());
-            result.accumulate("studentCode", student.getStudentCode());
-            result.accumulate("name", student.getName());
-            result.accumulate("subjectCode", student.getSubjectCode());
-            result.accumulate("subjectName", student.getSubjectName());
-            result.accumulate("totalScore", student.getTotalScore());
-
-            List<MarkGroup> groups = groupService.findByExamAndSubject(student.getExamId(), student.getSubjectCode());
-            JSONArray groupArray = new JSONArray();
-            Map<Integer, String> mainTitleMap = new HashMap<Integer, String>();
-            for (MarkGroup markGroup : groups) {
-                JSONObject group = new JSONObject();
-                group.accumulate("groupNumber", markGroup.getNumber());
-                List<SubjectiveScore> scores = scoreService.findByStudentIdAndGroupNumber(student.getId(),
-                        markGroup.getNumber());
-                JSONArray array = new JSONArray();
-                for (SubjectiveScore scoreItem : scores) {
-                    JSONObject obj = new JSONObject();
-                    String mainTitle = mainTitleMap.get(scoreItem.getMainNumber());
-                    if (mainTitle == null) {
-                        ExamQuestion q = questionService.findByExamAndSubjectAndObjectiveAndMainNumberAndSubNumber(
-                                student.getExamId(), student.getSubjectCode(), false, scoreItem.getMainNumber(),
-                                scoreItem.getSubNumber());
-                        mainTitleMap.put(scoreItem.getMainNumber(), mainTitle);
-                        mainTitle = q.getMainTitle();
-                    }
-                    obj.accumulate("mainTitle", mainTitle);
-                    obj.accumulate("questionNumber", scoreItem.getMainNumber() + "-" + scoreItem.getSubNumber());
-                    obj.accumulate("score", scoreItem.getScore());
-                    array.add(obj);
+        int retry = 1;
+        while (task == null) {
+            List<ExamStudent> list = new ArrayList<ExamStudent>();
+            // 需要判断评卷员是否绑定了班级
+            query.setExamId(examId);
+            query.setPageNumber(retry);
+            query.setPageSize(20);
+            List<ExamSubject> subjectList = getExamSubject(examId, wu);
+            if (StringUtils.isBlank(query.getSubjectCode()) && !subjectList.isEmpty()) {
+                query.setSubjectCode(subjectList.get(0).getCode());
+            }
+            list = inspectedService.findByQuery(query, SubjectiveStatus.MARKED, mainNumber, mainStartScore,
+                    mainEndScore, questionScore);
+            if (list.isEmpty()) {
+                break;
+            }
+            for (ExamStudent student : list) {
+                if (inspectedService.applyStudent(student, wu.getId())) {
+                    task = taskService.build(student);
+                    break;
                 }
-                group.accumulate("questions", array);
-                groupArray.add(group);
             }
-            result.accumulate("groups", groupArray);
-            List<String> picUrls = fileService.getSliceUris(student.getExamId(), student.getSecretNumber(), 1,
-                    student.getSliceCount());
-            result.accumulate("picUrls", picUrls);
-            result.accumulate("success", true);
-        } else {
-            result.accumulate("success", false);
+            if (task == null) {
+                retry++;
+            }
         }
-        return result;
+        return task;
     }
 
     @Logging(menu = "考生评卷复核", type = LogType.UPDATE)
-    @RequestMapping("/save")
+    @RequestMapping(value = "/save", method = RequestMethod.POST)
     @ResponseBody
     public Object save(HttpServletRequest request, @RequestParam Integer studentId) {
         WebUser wu = RequestUtils.getWebUser(request);
         ExamStudent student = studentService.findById(studentId);
-        if (student != null && student.getSubjectiveStatus().equals(SubjectiveStatus.MARKED)) {
-            studentService.updateSubjectiveStatusAndTimeAndInspectorId(studentId, SubjectiveStatus.INSPECTED,
-                    new Date(), wu.getUser().getId());
-            return true;
-        } else {
-            return false;
+        JSONObject obj = new JSONObject();
+        try {
+            if (lockService.trylock(LockType.STUDENT, student.getId())
+                    && inspectedService.hasApplied(student, wu.getId())) {
+                studentService.updateSubjectiveStatusAndTimeAndInspectorId(studentId, SubjectiveStatus.INSPECTED,
+                        new Date(), wu.getUser().getId());
+                inspectedService.releaseByStudent(student);
+                obj.accumulate("success", true);
+            } else {
+                obj.accumulate("success", false);
+            }
+        } catch (Exception e) {
+            obj.accumulate("success", false);
+            log.error("inspected save error", e);
+        } finally {
+            lockService.unlock(LockType.STUDENT, student.getId());
         }
+        return obj;
     }
 
-    @RequestMapping("/clear")
+    @RequestMapping(value = "/clear", method = RequestMethod.POST)
     @ResponseBody
     @RoleRequire({ Role.SCHOOL_ADMIN, Role.SUBJECT_HEADER, Role.INSPECTOR })
-    public Object clear(HttpServletRequest request, @RequestParam(required = false) Integer studentId) {
-        WebUser wu = RequestUtils.getWebUser(request);
+    public JSONObject clear(HttpServletRequest request, @RequestParam(required = false) String subjectCode,
+            @RequestParam(required = false) Integer studentId) {
+        JSONObject obj = new JSONObject();
+        obj.accumulate("success", false);
         if (studentId != null) {
-            releaseTask(studentId);
-        } else {
-            releaseByUser(wu.getUser().getId());
+            releaseStudent(studentId);
+            obj.accumulate("success", true);
         }
-        return true;
+        if (subjectCode != null) {
+            int examId = getSessionExamId(request);
+            releaseUser(examId, subjectCode, RequestUtils.getWebUser(request).getId());
+            obj.accumulate("success", true);
+        }
+        return obj;
     }
 
     @Logging(menu = "取消复核", type = LogType.UPDATE)
     @RequestMapping(value = "/cancel", method = RequestMethod.POST)
     @ResponseBody
     @RoleRequire({ Role.SCHOOL_ADMIN, Role.SUBJECT_HEADER, Role.INSPECTOR })
-    public JSONObject cancel(HttpServletRequest request, @RequestParam Integer id) {
+    public JSONObject cancel(HttpServletRequest request, @RequestParam Integer studentId) {
         JSONObject obj = new JSONObject();
-        ExamStudent student = studentService.findById(id);
+        ExamStudent student = studentService.findById(studentId);
         WebUser wu = RequestUtils.getWebUser(request);
         if (student != null && student.getSubjectiveStatus().equals(SubjectiveStatus.INSPECTED)) {
             if (subjectCheck(student.getSubjectCode(), wu)) {
@@ -305,21 +244,19 @@ public class InspectedController extends BaseExamController {
         return obj;
     }
 
-    @Logging(menu = "复核打回", type = LogType.UPDATE)
-    @RequestMapping(value = "/back", method = RequestMethod.POST)
+    @Logging(menu = "打回", type = LogType.UPDATE)
+    @RequestMapping(value = "/rejected", method = RequestMethod.POST)
     @ResponseBody
     @RoleRequire({ Role.SCHOOL_ADMIN, Role.SUBJECT_HEADER, Role.INSPECTOR })
-    public JSONObject back(HttpServletRequest request, @RequestParam Integer studentId,
-            @RequestParam Integer groupNumber) {
+    public JSONObject rejected(HttpServletRequest request, @RequestBody RejectResult rejectResult) {
         JSONObject obj = new JSONObject();
-        ExamStudent student = studentService.findById(studentId);
+        ExamStudent student = studentService.findById(rejectResult.getStudentId());
         WebUser wu = RequestUtils.getWebUser(request);
         if (student != null && student.getSubjectiveStatus().equals(SubjectiveStatus.MARKED)) {
             if (subjectCheck(student.getSubjectCode(), wu) && lockService.trylock(LockType.STUDENT, student.getId())) {
                 try {
                     lockService.watch(LockType.EXAM_SUBJECT, student.getExamId(), student.getSubjectCode());
-                    lockService.watch(LockType.GROUP, student.getExamId(), student.getSubjectCode(), groupNumber);
-                    if (markService.backStudentByGroup(student, groupNumber, wu.getId())) {
+                    if (markService.rejectedStudent(student, rejectResult.getQuestionList(), wu.getId())) {
                         obj.accumulate("success", true);
                     } else {
                         obj.accumulate("success", false);
@@ -330,7 +267,6 @@ public class InspectedController extends BaseExamController {
                     obj.accumulate("message", "打回失败");
                     log.error("back inspected error", e);
                 } finally {
-                    lockService.unwatch(LockType.GROUP, student.getExamId(), student.getSubjectCode(), groupNumber);
                     lockService.unwatch(LockType.EXAM_SUBJECT, student.getExamId(), student.getSubjectCode());
                     lockService.unlock(LockType.STUDENT, student.getId());
                 }
@@ -345,39 +281,86 @@ public class InspectedController extends BaseExamController {
         return obj;
     }
 
-    private boolean setCurrent(Integer taskId, Integer userId) {
-        Integer value = currentTaskMap.get(taskId);
-        if (value == null) {
-            synchronized (currentTaskMap) {
-                value = currentTaskMap.get(taskId);
-                if (value == null) {
-                    currentTaskMap.put(taskId, userId);
-                    return true;
-                } else {
-                    return false;
-                }
-            }
-        } else {
-            return false;
+    @Logging(menu = "回看复核任务", type = LogType.QUERY)
+    @RequestMapping(value = "/getHistory", method = RequestMethod.POST)
+    @ResponseBody
+    public Object getHistory(HttpServletRequest request, @RequestParam String subjectCode,
+            @RequestParam int pageNumber, @RequestParam int pageSize) throws Exception {
+        int examId = getSessionExamId(request);
+        WebUser wu = RequestUtils.getWebUser(request);
+        List<Task> list = new ArrayList<>();
+        ExamStudentSearchQuery query = new ExamStudentSearchQuery();
+        query.setExamId(examId);
+        query.setSubjectCode(subjectCode);
+        query.setInspectorId(wu.getId());
+        query.addStatus(SubjectiveStatus.INSPECTED);
+        query.setPageNumber(pageNumber);
+        query.setPageSize(pageSize);
+        query.orderByInspectTimeDesc();
+        query = studentService.findByQuery(query);
+        for (ExamStudent student : query.getResult()) {
+            Task task = taskService.build(student);
+            task.setPrevious(true);
+            list.add(task);
+        }
+        return list;
+    }
+
+    @RequestMapping(value = "/getStatus", method = RequestMethod.POST)
+    @ResponseBody
+    public JSONObject status(HttpServletRequest request, ExamStudentSearchQuery query,
+            @RequestParam(required = false) Integer mainNumber, @RequestParam(required = false) Double mainStartScore,
+            @RequestParam(required = false) Double mainEndScore, @RequestParam(required = false) Double questionScore) {
+        JSONObject status = new JSONObject();
+        int examId = getSessionExamId(request);
+        query.setExamId(examId);
+        Integer totalCount = inspectedService.countByQuery(query, SubjectiveStatus.MARKED, mainNumber, mainStartScore,
+                mainEndScore, questionScore);
+        status.accumulate("totalCount", totalCount);
+        status.accumulate("valid", totalCount > 0);
+        return status;
+    }
+
+    @RequestMapping(value = "/getSetting", method = RequestMethod.POST)
+    @ResponseBody
+    public JSONObject getSetting(HttpServletRequest request) {
+        JSONObject setting = new JSONObject();
+        WebUser wu = RequestUtils.getWebUser(request);
+        setting.accumulate("fileServer", fileService.getFileServer());
+        setting.accumulate("userName", wu.getName());
+        setting.accumulate("splitConfig", getSplitConfig());
+        return setting;
+    }
+
+    private double[] getSplitConfig() {
+        String strs[] = splitConfig.split(",");
+        double[] config = new double[strs.length];
+        for (int i = 0; i < strs.length; i++) {
+            config[i] = Double.parseDouble(strs[i]);
         }
+        return config;
     }
 
-    private void releaseTask(Integer taskId) {
-        synchronized (currentTaskMap) {
-            currentTaskMap.remove(taskId);
+    private void releaseUser(Integer examId, String subjectCode, Integer userId) {
+        try {
+            lockService.waitlock(LockType.USER, userId);
+            inspectedService.releaseByUserId(examId, subjectCode, userId);
+        } catch (Exception e) {
+            log.error("release user error", e);
+        } finally {
+            lockService.unlock(LockType.USER, userId);
         }
     }
 
-    private void releaseByUser(Integer userId) {
-        Set<Integer> taskIds = new HashSet<>();
-        taskIds.addAll(currentTaskMap.keySet());
-        synchronized (currentTaskMap) {
-            for (Integer taskId : taskIds) {
-                Integer value = currentTaskMap.get(taskId);
-                if (value != null && value.equals(userId)) {
-                    currentTaskMap.remove(taskId);
-                }
-            }
+    private void releaseStudent(Integer studentId) {
+        try {
+            lockService.waitlock(LockType.STUDENT, studentId);
+            ExamStudent student = studentService.findById(studentId);
+            inspectedService.releaseByStudent(student);
+        } catch (Exception e) {
+            log.error("release user error", e);
+        } finally {
+            lockService.unlock(LockType.STUDENT, studentId);
         }
     }
 }

+ 89 - 134
stmms-web/src/main/java/cn/com/qmth/stmms/admin/exam/LibraryController.java

@@ -2,15 +2,10 @@ package cn.com.qmth.stmms.admin.exam;
 
 import java.util.ArrayList;
 import java.util.Date;
-import java.util.HashMap;
-import java.util.HashSet;
 import java.util.List;
-import java.util.Map;
-import java.util.Set;
 
 import javax.servlet.http.HttpServletRequest;
 
-import net.sf.json.JSONArray;
 import net.sf.json.JSONObject;
 
 import org.apache.commons.lang.StringUtils;
@@ -23,7 +18,6 @@ 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.ResponseBody;
-import org.springframework.web.servlet.ModelAndView;
 import org.springframework.web.servlet.mvc.support.RedirectAttributes;
 
 import cn.com.qmth.stmms.biz.exam.model.Exam;
@@ -41,16 +35,12 @@ import cn.com.qmth.stmms.biz.file.enums.FormatType;
 import cn.com.qmth.stmms.biz.file.service.FileService;
 import cn.com.qmth.stmms.biz.lock.LockService;
 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.MarkTrack;
+import cn.com.qmth.stmms.biz.mark.model.Task;
 import cn.com.qmth.stmms.biz.mark.query.MarkLibrarySearchQuery;
 import cn.com.qmth.stmms.biz.mark.service.MarkLibraryService;
 import cn.com.qmth.stmms.biz.mark.service.MarkService;
-import cn.com.qmth.stmms.biz.mark.service.MarkSpecialTagService;
-import cn.com.qmth.stmms.biz.mark.service.MarkTrackService;
-import cn.com.qmth.stmms.biz.user.model.User;
+import cn.com.qmth.stmms.biz.mark.service.TaskService;
 import cn.com.qmth.stmms.biz.user.service.UserService;
-import cn.com.qmth.stmms.biz.utils.ScoreItem;
 import cn.com.qmth.stmms.common.annotation.Logging;
 import cn.com.qmth.stmms.common.annotation.RoleRequire;
 import cn.com.qmth.stmms.common.domain.WebUser;
@@ -98,13 +88,7 @@ public class LibraryController extends BaseExamController {
     private UserService userService;
 
     @Autowired
-    private MarkTrackService markTrackService;
-
-    @Autowired
-    private MarkSpecialTagService markSpecialTagService;
-
-    // 并发处理互斥锁
-    private Map<Integer, Integer> currentTaskMap = new HashMap<Integer, Integer>();
+    private TaskService taskService;
 
     @Logging(menu = "评卷任务查询", type = LogType.QUERY)
     @RequestMapping
@@ -125,9 +109,6 @@ public class LibraryController extends BaseExamController {
         }
         List<MarkGroup> groupList = groupService.findByExamAndSubjectAndStatus(examId, query.getSubjectCode(),
                 MarkStatus.FORMAL);
-        // if (groupList.isEmpty()) {
-        // return "redirect:/admin/exam/mark";
-        // }
         if (!groupList.isEmpty()) {
             if (query.getGroupNumber() == 0 && !groupList.isEmpty()) {
                 query.setGroupNumber(groupList.get(0).getNumber());
@@ -237,158 +218,132 @@ public class LibraryController extends BaseExamController {
     }
 
     @Logging(menu = "开始任务复核", type = LogType.QUERY)
-    @RequestMapping("/inspected/start")
+    @RequestMapping(value = "/getTask", method = RequestMethod.POST)
     @ResponseBody
-    public ModelAndView start(HttpServletRequest request, RedirectAttributes redirectAttributes,
+    public Task getTask(HttpServletRequest request, RedirectAttributes redirectAttributes,
             @RequestParam String subjectCode, @RequestParam Integer groupNumber) {
         int examId = getSessionExamId(request);
         MarkGroup group = groupService.findOne(examId, subjectCode, groupNumber);
-        WebUser wu = RequestUtils.getWebUser(request);
-        releaseByUser(wu.getUser().getId());
-        ModelAndView view = new ModelAndView("modules/exam/inspectedLibrary");
         if (group == null) {
-            view.addObject("message", "大题不存在或评卷已结束");
-            return view;
+            return null;
         } else if (group.getStatus() == MarkStatus.FINISH) {
-            view.addObject("message", "评卷已结束");
-            return view;
+            return null;
         } else if (group.getStatus() == MarkStatus.TRIAL) {
-            view.addObject("message", "试评任务无需复核");
-            return view;
-        } else {
-            List<Integer> ids = new ArrayList<Integer>();
+            return null;
+        }
+        Task task = null;
+        WebUser wu = RequestUtils.getWebUser(request);
+        int retry = 1;
+        while (task == null) {
             MarkLibrarySearchQuery query = new MarkLibrarySearchQuery();
             query.setExamId(examId);
             query.setSubjectCode(subjectCode);
             query.setGroupNumber(groupNumber);
-            query.setPageNumber(1);
-            query.setPageSize(1000);
+            query.setPageNumber(retry);
+            query.setPageSize(20);
             query.addStatus(LibraryStatus.MARKED);
             query = libraryService.findByQuery(query);
-            if (query.getResult() != null && query.getResult().size() > 0) {
-                for (MarkLibrary library : query.getResult()) {
-                    ids.add(library.getId());
+            if (query.getResult().isEmpty()) {
+                break;
+            }
+            for (MarkLibrary library : query.getResult()) {
+                if (libraryService.applyLibrary(library, wu.getId())) {
+                    task = taskService.build(library);
+                    break;
                 }
             }
-            view.addObject("inspectCount", ids.size());
-            view.addObject("fileServer", fileService.getFileServer());
-            view.addObject("ids", StringUtils.join(ids, ","));
-            view.addObject("message", ids.size() > 0 ? "" : "没有待复核的任务");
-            return view;
-        }
-    }
-
-    @RequestMapping("/inspected/info")
-    @ResponseBody
-    public Object info(HttpServletRequest request, @RequestParam Integer libraryId) {
-        WebUser wu = RequestUtils.getWebUser(request);
-        MarkLibrary library = libraryService.findById(libraryId);
-        JSONObject result = new JSONObject();
-        if (setCurrent(library.getId(), wu.getUser().getId())) {
-            ExamStudent student = studentService.findById(library.getStudentId());
-            result.accumulate("id", libraryId);
-            result.accumulate("studentId", library.getSecretNumber());
-            result.accumulate("subjectCode", library.getSubjectCode());
-            result.accumulate("subjectName", student.getSubjectName());
-            Marker marker = markerService.findById(library.getMarkerId());
-            User user = userService.findById(marker.getUserId());
-            result.accumulate("markerName", user.getLoginName());
-            result.accumulate("markerScore", library.getMarkerScore());
-
-            JSONArray array = new JSONArray();
-            List<ExamQuestion> questions = questionService.findByExamAndSubjectAndObjectiveAndGroupNumber(
-                    library.getExamId(), library.getSubjectCode(), false, library.getGroupNumber());
-            List<ScoreItem> scores = library.getScoreList();
-            for (int i = 0; i < questions.size(); i++) {
-                ExamQuestion question = questions.get(i);
-                JSONObject obj = new JSONObject();
-                obj.accumulate("questionNumber", question.getMainTitle() + " " + question.getQuestionNumber());
-                obj.accumulate("score", scores.get(i).getScore());
-                array.add(obj);
+            if (task == null) {
+                retry++;
             }
-            result.accumulate("questions", array);
-
-            MarkGroup group = groupService.findOne(student.getExamId(), student.getSubjectCode(),
-                    library.getGroupNumber());
-            List<String> picUrls = fileService.getSliceUris(student.getExamId(), student.getSecretNumber(), 1,
-                    student.getSliceCount());
-            List<MarkTrack> markTracks = markTrackService.findByLibraryId(library.getId());
-            List<MarkSpecialTag> markSpecialTagList = markSpecialTagService.findByLibraryId(library.getId());
-            result.accumulate("picUrls", picUrls);
-            result.accumulate("pictureConfig", group.getPictureConfigList());
-            result.accumulate("markTracks", markTracks);
-            result.accumulate("markSpecialTagList", markSpecialTagList);
-            result.accumulate("success", true);
-        } else {
-            result.accumulate("success", false);
         }
-        return result;
+        return task;
     }
 
     @Logging(menu = "考生评卷复核", type = LogType.UPDATE)
-    @RequestMapping("/inspected/save")
+    @RequestMapping(value = "/inspected/save", method = RequestMethod.POST)
     @ResponseBody
     public Object save(HttpServletRequest request, @RequestParam Integer libraryId) {
         WebUser wu = RequestUtils.getWebUser(request);
         MarkLibrary library = libraryService.findById(libraryId);
-        if (libraryId != null && library.getStatus().equals(LibraryStatus.MARKED)) {
-            library.setHeaderId(wu.getUser().getId());
-            library.setHeaderTime(new Date());
-            library.setStatus(LibraryStatus.INSPECTED);
-            libraryService.save(library);
-            releaseTask(libraryId);
-            return true;
-        } else {
-            return false;
+        JSONObject obj = new JSONObject();
+        try {
+            if (libraryId != null && library.getStatus().equals(LibraryStatus.MARKED)
+                    && lockService.trylock(LockType.GROUP_LIBRARY, library.getId())
+                    && libraryService.hasApplied(library, wu.getId())) {
+                library.setHeaderId(wu.getUser().getId());
+                library.setHeaderTime(new Date());
+                library.setStatus(LibraryStatus.INSPECTED);
+                libraryService.save(library);
+                libraryService.releaseByLibrary(library);
+                obj.accumulate("success", true);
+            } else {
+                obj.accumulate("success", false);
+            }
+        } catch (Exception e) {
+            obj.accumulate("success", false);
+            log.error("inspected library save error", e);
+        } finally {
+            lockService.unlock(LockType.GROUP_LIBRARY, library.getId());
         }
+        return obj;
     }
 
-    @RequestMapping("/inspected/clear")
+    @RequestMapping(value = "/clear", method = RequestMethod.POST)
     @ResponseBody
     @RoleRequire({ Role.SCHOOL_ADMIN, Role.SUBJECT_HEADER })
-    public Object clear(HttpServletRequest request, @RequestParam(required = false) Integer libraryId) {
+    public Object clear(HttpServletRequest request, @RequestParam String subjectCode,
+            @RequestParam Integer groupNumber, @RequestParam(required = false) Integer libraryId) {
         WebUser wu = RequestUtils.getWebUser(request);
+        JSONObject obj = new JSONObject();
+        obj.accumulate("success", false);
         if (libraryId != null) {
-            releaseTask(libraryId);
+            releaseLibrary(libraryId);
+            obj.accumulate("success", true);
         } else {
-            releaseByUser(wu.getUser().getId());
+            int examId = getSessionExamId(request);
+            releaseUser(examId, subjectCode, groupNumber, wu.getUser().getId());
+            obj.accumulate("success", true);
         }
-        return true;
+        return obj;
     }
 
-    private boolean setCurrent(Integer taskId, Integer userId) {
-        Integer value = currentTaskMap.get(taskId);
-        if (value == null) {
-            synchronized (currentTaskMap) {
-                value = currentTaskMap.get(taskId);
-                if (value == null) {
-                    currentTaskMap.put(taskId, userId);
-                    return true;
-                } else {
-                    return false;
-                }
-            }
-        } else {
-            return false;
-        }
+    @RequestMapping(value = "/getStatus", method = RequestMethod.POST)
+    @ResponseBody
+    public JSONObject status(HttpServletRequest request, @RequestParam String subjectCode,
+            @RequestParam Integer groupNumber) {
+        JSONObject status = new JSONObject();
+        int examId = getSessionExamId(request);
+        MarkLibrarySearchQuery query = new MarkLibrarySearchQuery();
+        query.setExamId(examId);
+        query.setSubjectCode(query.getSubjectCode());
+        query.setGroupNumber(query.getGroupNumber());
+        query.addStatus(LibraryStatus.MARKED);
+        long inspectedCount = libraryService.countByQuery(query);
+        status.accumulate("totalCount", inspectedCount);
+        status.accumulate("valid", inspectedCount > 0);
+        return status;
     }
 
-    private void releaseTask(Integer taskId) {
-        synchronized (currentTaskMap) {
-            currentTaskMap.remove(taskId);
+    private void releaseUser(Integer examId, String subjectCode, Integer groupNumber, Integer userId) {
+        try {
+            lockService.waitlock(LockType.USER, userId);
+            libraryService.releaseByUserId(examId, subjectCode, groupNumber, userId);
+        } catch (Exception e) {
+            log.error("release user error", e);
+        } finally {
+            lockService.unlock(LockType.USER, userId);
         }
     }
 
-    private void releaseByUser(Integer userId) {
-        Set<Integer> taskIds = new HashSet<>();
-        taskIds.addAll(currentTaskMap.keySet());
-        synchronized (currentTaskMap) {
-            for (Integer taskId : taskIds) {
-                Integer value = currentTaskMap.get(taskId);
-                if (value != null && value.equals(userId)) {
-                    currentTaskMap.remove(taskId);
-                }
-            }
+    private void releaseLibrary(Integer libraryId) {
+        try {
+            lockService.waitlock(LockType.GROUP_LIBRARY, libraryId);
+            MarkLibrary library = libraryService.findById(libraryId);
+            libraryService.releaseByLibrary(library);
+        } catch (Exception e) {
+            log.error("release user error", e);
+        } finally {
+            lockService.unlock(LockType.GROUP_LIBRARY, libraryId);
         }
     }
 }

+ 31 - 65
stmms-web/src/main/java/cn/com/qmth/stmms/admin/exam/MarkQualityController.java

@@ -1,12 +1,36 @@
 package cn.com.qmth.stmms.admin.exam;
 
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.apache.commons.lang.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.core.task.AsyncTaskExecutor;
+import org.springframework.stereotype.Controller;
+import org.springframework.ui.Model;
+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.ResponseBody;
+import org.springframework.web.servlet.mvc.support.RedirectAttributes;
+
 import cn.com.qmth.stmms.admin.vo.MarkerVO;
-import cn.com.qmth.stmms.biz.exam.model.Exam;
 import cn.com.qmth.stmms.biz.exam.model.ExamSubject;
 import cn.com.qmth.stmms.biz.exam.model.MarkGroup;
 import cn.com.qmth.stmms.biz.exam.model.Marker;
 import cn.com.qmth.stmms.biz.exam.query.MarkerSearchQuery;
-import cn.com.qmth.stmms.biz.exam.service.*;
+import cn.com.qmth.stmms.biz.exam.service.ExamQuestionService;
+import cn.com.qmth.stmms.biz.exam.service.ExamService;
+import cn.com.qmth.stmms.biz.exam.service.ExamSubjectService;
+import cn.com.qmth.stmms.biz.exam.service.MarkGroupService;
+import cn.com.qmth.stmms.biz.exam.service.MarkerService;
 import cn.com.qmth.stmms.biz.file.service.FileService;
 import cn.com.qmth.stmms.biz.lock.LockService;
 import cn.com.qmth.stmms.biz.mark.model.Task;
@@ -22,29 +46,13 @@ import cn.com.qmth.stmms.biz.user.service.UserService;
 import cn.com.qmth.stmms.common.annotation.Logging;
 import cn.com.qmth.stmms.common.annotation.RoleRequire;
 import cn.com.qmth.stmms.common.domain.WebUser;
-import cn.com.qmth.stmms.common.enums.*;
+import cn.com.qmth.stmms.common.enums.LibraryStatus;
+import cn.com.qmth.stmms.common.enums.LockType;
+import cn.com.qmth.stmms.common.enums.LogType;
+import cn.com.qmth.stmms.common.enums.MarkStatus;
+import cn.com.qmth.stmms.common.enums.Role;
 import cn.com.qmth.stmms.common.utils.RequestUtils;
 
-import org.apache.commons.lang.StringUtils;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.beans.factory.annotation.Qualifier;
-import org.springframework.core.task.AsyncTaskExecutor;
-import org.springframework.stereotype.Controller;
-import org.springframework.ui.Model;
-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.ResponseBody;
-import org.springframework.web.servlet.mvc.support.RedirectAttributes;
-
-import javax.servlet.http.HttpServletRequest;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
 @Controller("markQualityController")
 @RequestMapping("/admin/exam/quality")
 public class MarkQualityController extends BaseExamController {
@@ -79,9 +87,6 @@ public class MarkQualityController extends BaseExamController {
     @Autowired
     private TrialService trialService;
 
-    @Autowired
-    private ExamStudentService studentService;
-
     @Autowired
     private ExamService examService;
 
@@ -224,37 +229,6 @@ public class MarkQualityController extends BaseExamController {
     }
 
     @Logging(menu = "质量监控查询给分记录详情", type = LogType.QUERY)
-    @RequestMapping("/batchProcess")
-    @RoleRequire({ Role.SCHOOL_ADMIN, Role.SUBJECT_HEADER })
-    public String batchProcess(Model model, HttpServletRequest request, @RequestParam Integer markerId,
-            @RequestParam Double markerScore) {
-        int examId = getSessionExamId(request);
-        Marker marker = markerService.findById(markerId);
-        WebUser wu = RequestUtils.getWebUser(request);
-        if (!subjectCheck(marker.getSubjectCode(), wu)) {
-            return "redirect:/admin/exam/mark";
-        }
-        MarkGroup group = groupService.findOne(examId, marker.getSubjectCode(), marker.getGroupNumber());
-        if (group == null) {
-            return "redirect:/admin/exam/mark";
-        }
-        ExamSubject subject = subjectService.find(group.getExamId(), group.getSubjectCode());
-        if (subject == null) {
-            return "redirect:/admin/exam/mark";
-        }
-        subject.setPaperAnswerUrl(fileService);
-        model.addAttribute("fileServer", fileService.getFileServer());
-        model.addAttribute("subject", subject);
-        model.addAttribute("group", group);
-        model.addAttribute("markerId", markerId);
-        model.addAttribute("markerScore", markerScore);
-        Exam exam = examService.findById(examId);
-        if (ExamType.MULTI_MEDIA.equals(exam.getType())) {
-            return "modules/exam/qualityProcessJson";
-        }
-        return "modules/exam/qualityProcess";
-    }
-
     @RequestMapping(value = "/history", method = RequestMethod.POST)
     @ResponseBody
     @RoleRequire({ Role.SCHOOL_ADMIN, Role.SUBJECT_HEADER })
@@ -283,11 +257,6 @@ public class MarkQualityController extends BaseExamController {
             query.orderByMarkerTimeDesc();
 
             list = taskService.findByQuery(query);
-            for (Task task : list) {
-                task.setPrevious(true);
-                task.setStudentName(studentService.findById(task.getStudentId()).getName());
-                // task.setMarkerId(markerId);
-            }
         } else if (group != null && group.getStatus() == MarkStatus.TRIAL) {
             // 试评查找给分历史记录
             List<TrialHistory> historyList = new ArrayList<TrialHistory>();
@@ -297,9 +266,6 @@ public class MarkQualityController extends BaseExamController {
                 TrialLibrary library = trialService.findLibrary(history.getLibraryId());
                 if (library != null) {
                     Task task = taskService.build(library, history);
-                    task.setPrevious(true);
-                    task.setStudentName(studentService.findById(task.getStudentId()).getName());
-                    // task.setMarkerId(markerId);
                     list.add(task);
                 }
             }

+ 31 - 36
stmms-web/src/main/java/cn/com/qmth/stmms/admin/exam/MarkTrackController.java

@@ -1,5 +1,20 @@
 package cn.com.qmth.stmms.admin.exam;
 
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import org.apache.commons.lang.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.ResponseBody;
+
 import cn.com.qmth.stmms.biz.exam.model.ExamStudent;
 import cn.com.qmth.stmms.biz.exam.model.MarkGroup;
 import cn.com.qmth.stmms.biz.exam.service.ExamQuestionService;
@@ -9,30 +24,16 @@ import cn.com.qmth.stmms.biz.file.service.FileService;
 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.MarkTrack;
+import cn.com.qmth.stmms.biz.mark.model.Task;
 import cn.com.qmth.stmms.biz.mark.service.MarkLibraryService;
 import cn.com.qmth.stmms.biz.mark.service.MarkSpecialTagService;
 import cn.com.qmth.stmms.biz.mark.service.MarkTrackService;
+import cn.com.qmth.stmms.biz.mark.service.TaskService;
 import cn.com.qmth.stmms.biz.utils.OriginTag;
 
-import org.apache.commons.lang.StringUtils;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Controller;
-import org.springframework.web.bind.annotation.PathVariable;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.ResponseBody;
-import org.springframework.web.servlet.ModelAndView;
-
 import com.fasterxml.jackson.core.JsonProcessingException;
 import com.fasterxml.jackson.databind.ObjectMapper;
 
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-
 @Controller("trackController")
 @RequestMapping("/admin/exam/track")
 public class MarkTrackController extends BaseExamController {
@@ -60,36 +61,33 @@ public class MarkTrackController extends BaseExamController {
     @Autowired
     private FileService fileService;
 
+    @Autowired
+    private TaskService taskService;
+
+    @ResponseBody
     @RequestMapping("/student/{studentId}")
-    public ModelAndView view(@PathVariable Integer studentId) {
-        ModelAndView view = new ModelAndView("modules/exam/studentTrack");
-        view.addObject("fileServer", fileService.getFileServer());
+    public HashMap<String, Object> studentTrack(@PathVariable Integer studentId) {
+        HashMap<String, Object> map = new HashMap<String, Object>();
+        map.put("fileServer", fileService.getFileServer());
         ExamStudent student = studentService.findById(studentId);
         if (student != null && student.isUpload()) {
             List<String> sliceUrls = fileService.getSliceUris(student.getExamId(), student.getSecretNumber(), 1,
                     student.getSliceCount());
-            view.addObject("urls", StringUtils.join(sliceUrls, ","));
-
-            // JSONArray result = new JSONArray();
+            map.put("sliceUrls", StringUtils.join(sliceUrls, ","));
             Map<MarkGroup, List<OriginTag>> maps = studentService.getSliceTags(student, false);
             List<OriginTag> tags = new ArrayList<OriginTag>();
             for (Entry<MarkGroup, List<OriginTag>> entry : maps.entrySet()) {
-                // MarkGroup group = entry.getKey();
-                // JSONObject item = new JSONObject();
-                // item.accumulate("config", group.getPictureConfigList());
-                // item.accumulate("tags", entry.getValue());
-                // result.add(item);
                 tags.addAll(entry.getValue());
             }
             ObjectMapper mapper = new ObjectMapper();
             try {
-                view.addObject("tags", mapper.writeValueAsString(tags));
+                map.put("tagList", mapper.writeValueAsString(tags));
             } catch (JsonProcessingException e) {
                 e.printStackTrace();
                 log.error("MarkTrackController-轨迹坐标获取出错", e);
             }
         }
-        return view;
+        return map;
     }
 
     /**
@@ -115,15 +113,12 @@ public class MarkTrackController extends BaseExamController {
     }
 
     @ResponseBody
-    @RequestMapping("/byLibrary")
-    public HashMap<String, Object> byLibrary(Integer libraryId) {
+    @RequestMapping("/library/{libraryId}")
+    public HashMap<String, Object> byLibrary(@PathVariable Integer libraryId) {
         MarkLibrary library = libraryService.findById(libraryId);
-        ExamStudent examStudent = studentService.findById(library.getStudentId());
-        List<Object> list = new ArrayList<Object>();
         HashMap<String, Object> map = new HashMap<String, Object>();
-        HashMap<String, Object> groups = set(library, examStudent);
-        list.add(groups);
-        map.put("list", list);
+        Task task = taskService.build(library);
+        map.put("task", task);
         map.put("fileServer", fileService.getFileServer());
         return map;
     }

+ 0 - 560
stmms-web/src/main/java/cn/com/qmth/stmms/mark/MarkApi.java

@@ -1,560 +0,0 @@
-package cn.com.qmth.stmms.mark;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import javax.servlet.http.HttpServletRequest;
-
-import net.sf.json.JSONArray;
-import net.sf.json.JSONObject;
-
-import org.apache.commons.lang.StringEscapeUtils;
-import org.apache.commons.lang.StringUtils;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.data.domain.Sort;
-import org.springframework.data.domain.Sort.Direction;
-import org.springframework.stereotype.Controller;
-import org.springframework.web.bind.annotation.RequestBody;
-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.ResponseBody;
-
-import cn.com.qmth.stmms.biz.exam.model.Exam;
-import cn.com.qmth.stmms.biz.exam.model.ExamSubject;
-import cn.com.qmth.stmms.biz.exam.model.MarkGroup;
-import cn.com.qmth.stmms.biz.exam.model.Marker;
-import cn.com.qmth.stmms.biz.exam.service.ExamQuestionService;
-import cn.com.qmth.stmms.biz.exam.service.ExamService;
-import cn.com.qmth.stmms.biz.exam.service.ExamSubjectService;
-import cn.com.qmth.stmms.biz.exam.service.MarkGroupService;
-import cn.com.qmth.stmms.biz.exam.service.MarkerClassService;
-import cn.com.qmth.stmms.biz.exam.service.MarkerService;
-import cn.com.qmth.stmms.biz.file.service.FileService;
-import cn.com.qmth.stmms.biz.lock.LockService;
-import cn.com.qmth.stmms.biz.mark.model.MarkLibrary;
-import cn.com.qmth.stmms.biz.mark.model.MarkResult;
-import cn.com.qmth.stmms.biz.mark.model.PictureConfigItem;
-import cn.com.qmth.stmms.biz.mark.model.ProblemType;
-import cn.com.qmth.stmms.biz.mark.model.SubmitResult;
-import cn.com.qmth.stmms.biz.mark.model.Task;
-import cn.com.qmth.stmms.biz.mark.model.TrialHistory;
-import cn.com.qmth.stmms.biz.mark.model.TrialLibrary;
-import cn.com.qmth.stmms.biz.mark.query.MarkLibrarySearchQuery;
-import cn.com.qmth.stmms.biz.mark.service.MarkLibraryService;
-import cn.com.qmth.stmms.biz.mark.service.MarkService;
-import cn.com.qmth.stmms.biz.mark.service.ProblemTypeService;
-import cn.com.qmth.stmms.biz.mark.service.TaskService;
-import cn.com.qmth.stmms.biz.mark.service.TrialService;
-import cn.com.qmth.stmms.biz.user.model.User;
-import cn.com.qmth.stmms.biz.user.service.UserService;
-import cn.com.qmth.stmms.common.annotation.Logging;
-import cn.com.qmth.stmms.common.controller.BaseController;
-import cn.com.qmth.stmms.common.domain.WebUser;
-import cn.com.qmth.stmms.common.enums.ExamType;
-import cn.com.qmth.stmms.common.enums.LibraryStatus;
-import cn.com.qmth.stmms.common.enums.LockType;
-import cn.com.qmth.stmms.common.enums.LogType;
-import cn.com.qmth.stmms.common.enums.MarkMode;
-import cn.com.qmth.stmms.common.enums.MarkStatus;
-import cn.com.qmth.stmms.common.utils.EncryptUtils;
-import cn.com.qmth.stmms.common.utils.RequestUtils;
-
-import com.fasterxml.jackson.core.JsonProcessingException;
-import com.fasterxml.jackson.databind.ObjectMapper;
-
-@Controller
-public class MarkApi extends BaseController {
-
-    private static Logger log = LoggerFactory.getLogger(MarkApi.class);
-
-    @Autowired
-    private ExamSubjectService subjectService;
-
-    @Autowired
-    private TrialService trialService;
-
-    @Autowired
-    private MarkerService markerService;
-
-    @Autowired
-    private MarkLibraryService libraryService;
-
-    @Autowired
-    private TaskService taskService;
-
-    @Autowired
-    private MarkService markService;
-
-    @Autowired
-    private ExamService examService;
-
-    @Autowired
-    private MarkGroupService groupService;
-
-    @Autowired
-    private LockService lockService;
-
-    @Autowired
-    private ProblemTypeService problemTypeService;
-
-    @Autowired
-    private UserService userService;
-
-    @Autowired
-    private MarkerClassService markerClassService;
-
-    @Autowired
-    private ExamQuestionService questionService;
-
-    @Autowired
-    private FileService fileService;
-
-    @Value("${marker.forceMode}")
-    private String forceMarkMode;
-
-    @Value("${slice.split.config}")
-    private String splitConfig;
-
-    @Value("${marker.prefetch.count}")
-    private long prefetchCount;
-
-    @RequestMapping(value = "/mark/getSetting", method = RequestMethod.POST)
-    @ResponseBody
-    public JSONObject getSetting(HttpServletRequest request) {
-        JSONObject setting = new JSONObject();
-        WebUser wu = RequestUtils.getWebUser(request);
-        Marker marker = wu.getMarker();
-        Exam exam = examService.findById(marker.getExamId());
-        MarkGroup group = groupService.findOne(marker.getExamId(), marker.getSubjectCode(), marker.getGroupNumber());
-        setting.accumulate("examType", exam.getType());
-        setting.accumulate("startTime", exam.getStartTime().getTime());
-        setting.accumulate("endTime", exam.getEndTime().getTime());
-        setting.accumulate("topCount", marker.getTopCount() != null ? marker.getTopCount() : 0);
-        setting.accumulate("sheetView", group.isSheetView());
-        setting.accumulate("enableAllZero", group.isEnableAllZero());
-        setting.accumulate("statusValue", group.getStatus());
-        setting.accumulate("groupNumber", group.getNumber());
-        setting.accumulate("fileServer", fileService.getFileServer());
-        setting.accumulate("forceSpecialTag", exam.isForceSpecialTag());
-        setting.accumulate("uiSetting",
-                StringUtils.isBlank(marker.getMarkSetting()) ? new JSONObject() : marker.getMarkSetting());
-        setting.accumulate("splitConfig", getSplitConfig());
-        setting.accumulate("prefetchCount", prefetchCount);
-        setting.accumulate("returnUrl", wu.getLogoutUrl() == null ? "mark-login" : wu.getLogoutUrl());
-        setModeAndForceMode(setting, exam, marker, group);
-        setSubjectAndSheetConfig(setting, marker, exam);
-        setMarker(setting, marker, RequestUtils.getWebUser(request).getName());
-        setProblemType(setting, marker);
-        return setting;
-    }
-
-    private double[] getSplitConfig() {
-        String strs[] = splitConfig.split(",");
-        double[] config = new double[strs.length];
-        for (int i = 0; i < strs.length; i++) {
-            config[i] = Double.parseDouble(strs[i]);
-        }
-        return config;
-    }
-
-    @RequestMapping(value = "/mark/getStatus", method = RequestMethod.POST)
-    @ResponseBody
-    public JSONObject status(HttpServletRequest request) {
-        JSONObject status = new JSONObject();
-        Marker marker = RequestUtils.getWebUser(request).getMarker();
-        ExamSubject subject = subjectService.find(marker.getExamId(), marker.getSubjectCode());
-        MarkGroup group = groupService.findOne(marker.getExamId(), marker.getSubjectCode(), marker.getGroupNumber());
-        if (subject == null || group == null || group.getStatus() == MarkStatus.FINISH) {
-            status.accumulate("valid", false);
-            return status;
-        }
-        long totalCount = 0;
-        long personCount = 0;
-        long markedCount = 0;
-        long problemCount = 0;
-        long arbitrateCount = 0;
-        if (group.getStatus() == MarkStatus.FORMAL) {
-            MarkLibrarySearchQuery query = new MarkLibrarySearchQuery();
-            query.setExamId(marker.getExamId());
-            query.setSubjectCode(marker.getSubjectCode());
-            query.setGroupNumber(marker.getGroupNumber());
-            totalCount = libraryService.countByQuery(query);
-
-            query.setMarkerId(marker.getId());
-            personCount = libraryService.countByQuery(query);
-
-            query.setMarkerId(0);
-            query.addStatus(LibraryStatus.MARKED);
-            query.addStatus(LibraryStatus.ARBITRATED);
-            query.addStatus(LibraryStatus.INSPECTED);
-            markedCount = libraryService.countByQuery(query);
-
-            query.clearStatus();
-            query.addStatus(LibraryStatus.PROBLEM);
-            problemCount = libraryService.countByQuery(query);
-
-            query.clearStatus();
-            query.addStatus(LibraryStatus.WAIT_ARBITRATE);
-            arbitrateCount = libraryService.countByQuery(query);
-        } else if (group.getStatus() == MarkStatus.TRIAL) {
-            totalCount = trialService.countLibrary(group.getExamId(), group.getSubjectCode(), group.getNumber());
-            personCount = trialService.countMarkerHistory(marker.getId());
-            markedCount = personCount;
-        }
-        status.accumulate("personCount", personCount);
-        status.accumulate("totalCount", totalCount);
-        status.accumulate("markedCount", markedCount);
-        status.accumulate("problemCount", problemCount);
-        status.accumulate("arbitrateCount", arbitrateCount);
-        status.accumulate("valid", totalCount > 0);
-        return status;
-    }
-
-    @RequestMapping(value = "/mark/getGroup", method = RequestMethod.POST)
-    @ResponseBody
-    public JSONArray getGroup(HttpServletRequest request) {
-        Marker marker = RequestUtils.getWebUser(request).getMarker();
-        JSONArray array = new JSONArray();
-        List<Marker> markers = markerService.findByExamAndSubjectAndUserIdAndEnable(marker.getExamId(),
-                marker.getSubjectCode(), marker.getUserId(), true);
-        for (Marker m : markers) {
-            JSONObject json = new JSONObject();
-            json.accumulate("markerId", m.getId());
-            json.accumulate("number", m.getGroupNumber());
-            MarkGroup group = groupService
-                    .findOne(marker.getExamId(), marker.getSubjectCode(), marker.getGroupNumber());
-            group.setQuestionList(questionService.findByExamAndSubjectAndObjectiveAndGroupNumber(marker.getExamId(),
-                    marker.getSubjectCode(), false, group.getNumber()));
-            json.accumulate("title", group.getTitle());
-            json.accumulate("markedCount", group.getMarkerCount());
-            json.accumulate("totalCount", group.getLibraryCount());
-            array.add(json);
-        }
-        return array;
-    }
-
-    @RequestMapping(value = "/mark/getTask", method = RequestMethod.POST)
-    @ResponseBody
-    public Task getTask(HttpServletRequest request) {
-        Marker marker = RequestUtils.getWebUser(request).getMarker();
-        Task task = null;
-        try {
-            lockService.watch(LockType.GROUP, marker.getExamId(), marker.getSubjectCode(), marker.getGroupNumber());
-            lockService.watch(LockType.MARKER, marker.getId());
-
-            MarkGroup group = groupService
-                    .findOne(marker.getExamId(), marker.getSubjectCode(), marker.getGroupNumber());
-            if (group == null) {
-                task = new Task();
-                // task.setExist(false);
-                // task.setMessage("mark.control.task.not.exist");
-            } else if (group.getStatus() == MarkStatus.FINISH) {
-                task = new Task();
-                // task.setExist(false);
-                // task.setMessage("mark.control.task.finish");
-            } else if (group.getStatus() == MarkStatus.TRIAL) {
-                task = getTrialTask(marker);
-            } else if (group.getStatus() == MarkStatus.FORMAL) {
-                task = getFormalTask(marker);
-            }
-            if (task == null) {
-                task = new Task();
-                // task.setExist(false);
-                // task.setMessage("mark.control.task.null");
-            }
-        } catch (Exception e) {
-            log.error("get task error", e);
-        } finally {
-            lockService.unwatch(LockType.MARKER, marker.getId());
-            lockService.unwatch(LockType.GROUP, marker.getExamId(), marker.getSubjectCode(), marker.getGroupNumber());
-        }
-        return task;
-    }
-
-    private Task getFormalTask(Marker marker) {
-        int retry = 1;
-        Task task = null;
-        while (task == null) {
-            List<MarkLibrary> list = new ArrayList<MarkLibrary>();
-            // 需要判断评卷员是否绑定了班级
-            long classCount = markerClassService.countByUserIdAndExamId(marker.getUserId(), marker.getExamId());
-            list = libraryService.findUnMarked(marker.getExamId(), marker.getSubjectCode(), marker.getGroupNumber(),
-                    marker.getId(), marker.getUserId(), classCount > 0, retry, 20);
-            if (list.isEmpty()) {
-                break;
-            }
-            for (MarkLibrary library : list) {
-                if (markService.applyLibrary(library, marker)) {
-                    task = taskService.build(library);
-                    break;
-                }
-            }
-            if (task == null) {
-                retry++;
-            }
-        }
-        return task;
-    }
-
-    private Task getTrialTask(Marker marker) {
-        int retry = 1;
-        Task task = null;
-        while (task == null) {
-            List<TrialLibrary> list = trialService.findUnMarkedLibrary(marker.getExamId(), marker.getSubjectCode(),
-                    marker.getGroupNumber(), marker.getId(), retry, 10);
-            if (list.isEmpty()) {
-                break;
-            }
-            for (TrialLibrary library : list) {
-                if (markService.applyLibrary(library, marker)) {
-                    task = taskService.build(library, null);
-                    break;
-                }
-            }
-            retry++;
-        }
-        return task;
-    }
-
-    @Logging(menu = "评卷", type = LogType.UPDATE)
-    @RequestMapping(value = "/mark/saveTask", method = RequestMethod.POST)
-    @ResponseBody
-    public JSONObject saveTask(HttpServletRequest request, @RequestBody MarkResult markResult) {
-        JSONObject result = new JSONObject();
-        Marker marker = RequestUtils.getWebUser(request).getMarker();
-        boolean success = false;
-        try {
-            lockService.watch(LockType.EXAM_SUBJECT, marker.getExamId(), marker.getSubjectCode());
-            lockService.watch(LockType.GROUP, marker.getExamId(), marker.getSubjectCode(), marker.getGroupNumber());
-            lockService.watch(LockType.MARKER, marker.getId());
-            lockService.waitlock(LockType.STUDENT, markResult.getStudentId());
-            SubmitResult sr = markService.submitTask(markResult, marker);
-            if (sr.isSuccess()) {
-                markService.releaseTask(sr, marker);
-                success = true;
-            }
-        } catch (Exception e) {
-            log.error("save task error", e);
-        } finally {
-            lockService.unlock(LockType.STUDENT, markResult.getStudentId());
-            lockService.unwatch(LockType.MARKER, marker.getId());
-            lockService.unwatch(LockType.GROUP, marker.getExamId(), marker.getSubjectCode(), marker.getGroupNumber());
-            lockService.unwatch(LockType.EXAM_SUBJECT, marker.getExamId(), marker.getSubjectCode());
-        }
-        result.accumulate("success", success);
-        result.accumulate("status", status(request));
-        if (!success) {
-            result.accumulate("message", "mark.control.task.error");
-        }
-        return result;
-    }
-
-    @Logging(menu = "查询回评任务", type = LogType.QUERY)
-    @RequestMapping(value = "/mark/getHistory", method = RequestMethod.POST)
-    @ResponseBody
-    public Object history(HttpServletRequest request, @RequestParam int pageNumber, @RequestParam int pageSize,
-            @RequestParam String order, @RequestParam String sort, @RequestParam(required = false) String secretNumber)
-            throws Exception {
-        Marker marker = RequestUtils.getWebUser(request).getMarker();
-        List<Task> list = new ArrayList<>();
-        Direction d = Direction.DESC;
-        Sort querySort = null;
-        if (sort.equals("ASC")) {
-            d = Direction.ASC;
-        }
-        if (order.equals("markerTime")) {
-            querySort = new Sort(d, "markerTime");
-        } else if (order.equals("markerScore")) {
-            querySort = new Sort(d, "markerScore");
-        }
-        MarkGroup group = groupService.findOne(marker.getExamId(), marker.getSubjectCode(), marker.getGroupNumber());
-        if (group != null && group.getStatus() == MarkStatus.FORMAL) {
-            // 正评查找已给分的评卷任务
-            MarkLibrarySearchQuery query = new MarkLibrarySearchQuery();
-            query.setExamId(marker.getExamId());
-            query.setSubjectCode(marker.getSubjectCode());
-            query.setMarkerId(marker.getId());
-            query.addStatus(LibraryStatus.MARKED);
-            query.addStatus(LibraryStatus.INSPECTED);
-            query.setGroupNumber(marker.getGroupNumber());
-            query.setSecretNumber(secretNumber);
-            query.setPageNumber(pageNumber);
-            query.setPageSize(pageSize);
-            if (querySort != null) {
-                query.setSort(querySort);
-            } else {
-                query.orderByMarkerTimeDesc();
-            }
-            list = taskService.findByQuery(query);
-            for (Task task : list) {
-                task.setPrevious(true);
-            }
-        } else if (group != null && group.getStatus() == MarkStatus.TRIAL) {
-            // 试评查找给分历史记录
-            List<TrialHistory> historyList = new ArrayList<TrialHistory>();
-            if (StringUtils.isNotBlank(secretNumber)) {
-                historyList = trialService.findHistory(marker.getExamId(), marker.getSubjectCode(),
-                        marker.getGroupNumber(), marker.getId(), secretNumber, pageNumber, pageSize, querySort);
-            } else {
-                historyList = trialService.findHistory(marker.getExamId(), marker.getSubjectCode(),
-                        marker.getGroupNumber(), marker.getId(), pageNumber, pageSize, querySort, null);
-            }
-            for (TrialHistory history : historyList) {
-                TrialLibrary library = trialService.findLibrary(history.getLibraryId());
-                if (library != null) {
-                    Task task = taskService.build(library, history);
-                    task.setPrevious(true);
-                    list.add(task);
-                }
-            }
-        }
-        return list;
-    }
-
-    @Logging(menu = "修改密码", type = LogType.UPDATE)
-    @RequestMapping(value = "/mark/changeName", method = RequestMethod.POST)
-    @ResponseBody
-    public JSONObject changeName(HttpServletRequest request, @RequestParam String name,
-            @RequestParam(required = false) String password) {
-        User user = userService.findById(RequestUtils.getWebUser(request).getId());
-        JSONObject result = new JSONObject();
-        user.setName(name);
-        if (StringUtils.isNotEmpty(password)) {
-            user.setPassword(EncryptUtils.md5(password));
-        }
-        try {
-            user = userService.save(user);
-            result.accumulate("success", true);
-        } catch (Exception e) {
-            result.accumulate("success", false);
-            log.error("MarkController-修改名字出错", e);
-        }
-        return result;
-    }
-
-    @RequestMapping(value = "/mark/updateSetting", method = RequestMethod.POST)
-    @ResponseBody
-    public JSONObject updateSetting(HttpServletRequest request, @RequestParam(required = false) String uiSetting,
-            @RequestParam(required = false) String mode) {
-        Marker marker = RequestUtils.getWebUser(request).getMarker();
-        if (uiSetting != null) {
-            markerService.updateMarkSetting(marker.getId(),
-                    StringEscapeUtils.unescapeHtml(StringUtils.trimToNull(uiSetting)));
-        }
-        if (mode != null) {
-            marker.setMode(MarkMode.findByName(mode));
-            markerService.save(marker);
-        }
-        JSONObject result = new JSONObject();
-        result.accumulate("success", true);
-        return result;
-    }
-
-    @RequestMapping("/mark/clear")
-    @ResponseBody
-    public void clear(HttpServletRequest request) {
-        releaseMarker(RequestUtils.getWebUser(request).getMarker());
-    }
-
-    private void releaseMarker(Marker marker) {
-        if (marker == null) {
-            return;
-        }
-        try {
-            lockService.waitlock(LockType.MARKER, marker.getId());
-            markService.releaseByMarker(marker);
-        } catch (Exception e) {
-            log.error("release marker error", e);
-        } finally {
-            lockService.unlock(LockType.MARKER, marker.getId());
-        }
-    }
-
-    protected String buildPictureConfig(String sheetConfig) {
-        String json = "";
-        if (StringUtils.isNotBlank(sheetConfig)) {
-            try {
-                ObjectMapper mapper = new ObjectMapper();
-                json = mapper.writeValueAsString(PictureConfigItem.parse(sheetConfig));
-            } catch (JsonProcessingException e) {
-                e.printStackTrace();
-            }
-        }
-        return json;
-    }
-
-    private void setProblemType(JSONObject setting, Marker marker) {
-        List<ProblemType> problemTypes = problemTypeService.findByExamId(marker.getExamId());
-        ObjectMapper mapper = new ObjectMapper();
-        try {
-            setting.accumulate("problemTypes", mapper.writeValueAsString(problemTypes));
-        } catch (JsonProcessingException e) {
-            log.error("MarkController-问题类型获取出错", e);
-        }
-    }
-
-    private void setMarker(JSONObject setting, Marker marker, String name) {
-        JSONObject m = new JSONObject();
-        m.accumulate("id", marker.getId());
-        m.accumulate("name", name);
-        setting.accumulate("marker", m);
-    }
-
-    private void setSubjectAndSheetConfig(JSONObject setting, Marker marker, Exam exam) {
-        ExamSubject examSubject = subjectService.find(marker.getExamId(), marker.getSubjectCode());
-        String sheetConfig = "";
-        if (StringUtils.isNotBlank(examSubject.getSheetConfig())) {
-            sheetConfig = buildPictureConfig(examSubject.getSheetConfig());
-        } else if (StringUtils.isNotBlank(exam.getSheetConfig())) {
-            sheetConfig = buildPictureConfig(exam.getSheetConfig());
-        }
-        setting.accumulate("sheetConfig", sheetConfig);
-
-        JSONObject subject = new JSONObject();
-        subject.accumulate("name", examSubject.getName());
-        subject.accumulate("code", examSubject.getCode());
-        subject.accumulate("paperUrl", examSubject.getPaperUrl() == null ? "" : examSubject.getPaperUrl());
-        subject.accumulate("answerUrl", examSubject.getAnswerUrl() == null ? "" : examSubject.getAnswerUrl());
-        setting.accumulate("subject", subject);
-    }
-
-    private void setModeAndForceMode(JSONObject setting, Exam exam, Marker marker, MarkGroup group) {
-        MarkMode mode = null;
-        boolean forceMode = false;
-        if (MarkMode.findByName(forceMarkMode) != null) {
-            // 全局配置的强制评卷模式
-            mode = MarkMode.findByName(forceMarkMode);
-            forceMode = true;
-        } else {
-            // 没有全局配置,优先从大题配置取强制评卷模式
-            if (group != null && group.getMarkMode() != null) {
-                mode = group.getMarkMode();
-                forceMode = true;
-            }
-            // 否则取评卷员当前记录的评卷模式
-            if (mode == null) {
-                mode = marker.getMode();
-            }
-            if (mode == null) {
-                mode = MarkMode.COMMON;
-            }
-            if (marker.getMode() != mode) {
-                marker.setMode(mode);
-                markerService.save(marker);
-            }
-        }
-        setting.accumulate("mode", mode);
-        setting.accumulate("forceMode", forceMode);
-
-        if (ExamType.MULTI_MEDIA.equals(exam.getType())) {
-            setting.accumulate("forceMode", true);
-            setting.accumulate("sheetView", false);
-            setting.accumulate("forceSpecialTag", false);
-        }
-    }
-
-}

+ 212 - 124
stmms-web/src/main/java/cn/com/qmth/stmms/mark/MarkController.java

@@ -21,10 +21,13 @@ import cn.com.qmth.stmms.common.session.model.StmmsSession;
 import cn.com.qmth.stmms.common.session.service.SessionService;
 import cn.com.qmth.stmms.common.utils.EncryptUtils;
 import cn.com.qmth.stmms.common.utils.RequestUtils;
+
 import com.fasterxml.jackson.core.JsonProcessingException;
 import com.fasterxml.jackson.databind.ObjectMapper;
+
 import net.sf.json.JSONArray;
 import net.sf.json.JSONObject;
+
 import org.apache.commons.lang.StringEscapeUtils;
 import org.apache.commons.lang.StringUtils;
 import org.slf4j.Logger;
@@ -39,6 +42,7 @@ import org.springframework.web.servlet.ModelAndView;
 
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
+
 import java.util.*;
 
 @Controller
@@ -89,6 +93,15 @@ public class MarkController extends BaseController {
     @Autowired
     private FileService fileService;
 
+    @Autowired
+    private ExamQuestionService questionService;
+
+    @Value("${slice.split.config}")
+    private String splitConfig;
+
+    @Value("${marker.prefetch.count}")
+    private long prefetchCount;
+
     @Value("${marker.forceMode}")
     private String forceMarkMode;
 
@@ -187,111 +200,62 @@ public class MarkController extends BaseController {
         session.saveWebUser(user);
         sessionService.put(request, response, session);
         SessionExamUtils.setExamId(request, exam);
-        return new ModelAndView("redirect:/mark/index");
-    }
-
-    @RequestMapping("/index")
-    public ModelAndView index(HttpServletRequest request, @RequestParam(value = "mode", required = false) String mode) {
-        Marker marker = RequestUtils.getWebUser(request).getMarker();
-        if (marker == null) {
-            return new ModelAndView("redirect:/mark/subject-select");
-        }
-        ModelAndView modelAndView = getMarkModeView(marker, MarkMode.findByName(mode));
-        preProcess(marker, modelAndView);
-        return modelAndView;
-    }
-
-    private ModelAndView getMarkModeView(Marker marker, MarkMode mode) {
-        // 多媒体阅卷
-        Exam exam = examService.findById(marker.getExamId());
-        boolean forceMode = false;
-        MarkMode sysMode = MarkMode.findByName(forceMarkMode);
-        MarkGroup group = groupService.findOne(marker.getExamId(), marker.getSubjectCode(), marker.getGroupNumber());
-        if (ExamType.MULTI_MEDIA.equals(exam.getType())) {
-            ModelAndView view = new ModelAndView("modules/mark/markJson");
-            view.addObject("forceMode", false);
-            view.addObject("sheetView", false);
-            view.addObject("isFormal", group.getStatus() == MarkStatus.FORMAL);
-            return view;
-        }
-        if (sysMode != null) {
-            // 全局配置的强制评卷模式
-            mode = sysMode;
-            forceMode = true;
-        } else {
-            // 没有全局配置,优先从大题配置取强制评卷模式
-            if (group != null && group.getMarkMode() != null) {
-                mode = group.getMarkMode();
-                forceMode = true;
-            }
-            // 否则取评卷员当前记录的评卷模式
-            if (mode == null) {
-                mode = marker.getMode();
-            }
-            if (mode == null) {
-                mode = MarkMode.COMMON;
-            }
-            if (marker.getMode() != mode) {
-                marker.setMode(mode);
-                markerService.save(marker);
-            }
-        }
-        ModelAndView view = new ModelAndView(mode == MarkMode.TRACK ? "modules/mark/markTrack" : "modules/mark/markNew");
-        view.addObject("forceMode", forceMode);
-        view.addObject("sheetView", group.isSheetView());
-        view.addObject("enableAllZero", group.isEnableAllZero());
-        view.addObject("isFormal", group.getStatus() == MarkStatus.FORMAL);
-        return view;
+        return new ModelAndView("redirect:/web/mark");
     }
 
     @RequestMapping("/logout")
     public ModelAndView logout(HttpServletRequest request) {
         WebUser wu = RequestUtils.getWebUser(request);
         releaseMarker(wu.getMarker());
-        return new ModelAndView("redirect:/logout");
+        StmmsSession session = RequestUtils.getSession(request);
+        String logoutUrl = session.getWebUserLogoutUrl();
+        session.setInvalid(true);
+        if (StringUtils.isNotBlank(logoutUrl)) {
+            return new ModelAndView("redirect:" + logoutUrl);
+        } else {
+            return new ModelAndView("redirect:/mark-login");
+        }
     }
 
-    /**
-     * 进入评卷界面后的通用预处理
-     *
-     * @param marker
-     * @param modelAndView
-     */
-    private void preProcess(Marker marker, ModelAndView modelAndView) {
-        modelAndView.addObject("fileServer", fileService.getFileServer());
-        modelAndView.addObject("marker", marker);
-        ExamSubject subject = subjectService.find(marker.getExamId(), marker.getSubjectCode());
-        subject.setPaperAnswerUrl(fileService);
-        modelAndView.addObject("subject", subject);
+    @RequestMapping(value = "/getSetting", method = RequestMethod.POST)
+    @ResponseBody
+    public JSONObject getSetting(HttpServletRequest request) {
+        JSONObject setting = new JSONObject();
+        WebUser wu = RequestUtils.getWebUser(request);
+        Marker marker = wu.getMarker();
         Exam exam = examService.findById(marker.getExamId());
-        modelAndView.addObject("forceSpecialTag", exam.isForceSpecialTag());
-        modelAndView.addObject("defaultSetting", StringUtils.trimToNull(marker.getMarkSetting()));
-        String sheetConfig = "";
-        if (StringUtils.isNotBlank(subject.getSheetConfig())) {
-            sheetConfig = buildPictureConfig(subject.getSheetConfig());
-        } else if (StringUtils.isNotBlank(exam.getSheetConfig())) {
-            sheetConfig = buildPictureConfig(exam.getSheetConfig());
-        }
-        modelAndView.addObject("sheetConfig", sheetConfig);
-        releaseMarker(marker);
+        MarkGroup group = groupService.findOne(marker.getExamId(), marker.getSubjectCode(), marker.getGroupNumber());
+        setting.accumulate("examType", exam.getType());
+        setting.accumulate("startTime", exam.getStartTime() == null ? 0 : exam.getStartTime().getTime());
+        setting.accumulate("endTime", exam.getEndTime() == null ? 0 : exam.getEndTime().getTime());
+        setting.accumulate("topCount", marker.getTopCount() != null ? marker.getTopCount() : 0);
+        setting.accumulate("sheetView", group.isSheetView());
+        setting.accumulate("enableAllZero", group.isEnableAllZero());
+        setting.accumulate("statusValue", group.getStatus());
+        setting.accumulate("groupNumber", group.getNumber());
+        setting.accumulate("fileServer", fileService.getFileServer());
+        setting.accumulate("forceSpecialTag", exam.isForceSpecialTag());
+        setting.accumulate("uiSetting",
+                StringUtils.isBlank(marker.getMarkSetting()) ? new JSONObject() : marker.getMarkSetting());
+        setting.accumulate("splitConfig", getSplitConfig());
+        setting.accumulate("prefetchCount", prefetchCount);
+        setModeAndForceMode(setting, exam, marker, group);
+        setSubjectAndSheetConfig(setting, marker, exam);
+        setting.accumulate("userName", RequestUtils.getWebUser(request).getName());
+        setProblemType(setting, marker);
+        return setting;
+    }
 
-        List<ProblemType> problemTypes = problemTypeService.findByExamId(marker.getExamId());
-        List<Marker> markers = markerService.findByExamAndSubjectAndUserIdAndEnable(marker.getExamId(),
-                marker.getSubjectCode(), marker.getUserId(), true);
-        markers.remove(marker);
-        for (Marker m : markers) {
-            m.setMarkSetting(null);
-        }
-        ObjectMapper mapper = new ObjectMapper();
-        try {
-            modelAndView.addObject("problemTypes", mapper.writeValueAsString(problemTypes));
-            modelAndView.addObject("groups", mapper.writeValueAsString(markers));
-        } catch (JsonProcessingException e) {
-            log.error("MarkController-问题类型获取出错", e);
+    private double[] getSplitConfig() {
+        String strs[] = splitConfig.split(",");
+        double[] config = new double[strs.length];
+        for (int i = 0; i < strs.length; i++) {
+            config[i] = Double.parseDouble(strs[i]);
         }
+        return config;
     }
 
-    @RequestMapping("/status")
+    @RequestMapping(value = "/getStatus", method = RequestMethod.POST)
     @ResponseBody
     public JSONObject status(HttpServletRequest request) {
         JSONObject status = new JSONObject();
@@ -305,11 +269,9 @@ public class MarkController extends BaseController {
         long totalCount = 0;
         long personCount = 0;
         long markedCount = 0;
-        long exceptionCount = 0;
-        long topCount = 0;
+        long problemCount = 0;
+        long arbitrateCount = 0;
         if (group.getStatus() == MarkStatus.FORMAL) {
-            topCount = marker.getTopCount() != null ? marker.getTopCount() : 0;
-
             MarkLibrarySearchQuery query = new MarkLibrarySearchQuery();
             query.setExamId(marker.getExamId());
             query.setSubjectCode(marker.getSubjectCode());
@@ -326,9 +288,12 @@ public class MarkController extends BaseController {
             markedCount = libraryService.countByQuery(query);
 
             query.clearStatus();
-            query.addStatus(LibraryStatus.WAIT_ARBITRATE);
             query.addStatus(LibraryStatus.PROBLEM);
-            exceptionCount = libraryService.countByQuery(query);
+            problemCount = libraryService.countByQuery(query);
+
+            query.clearStatus();
+            query.addStatus(LibraryStatus.WAIT_ARBITRATE);
+            arbitrateCount = libraryService.countByQuery(query);
         } else if (group.getStatus() == MarkStatus.TRIAL) {
             totalCount = trialService.countLibrary(group.getExamId(), group.getSubjectCode(), group.getNumber());
             personCount = trialService.countMarkerHistory(marker.getId());
@@ -337,13 +302,35 @@ public class MarkController extends BaseController {
         status.accumulate("personCount", personCount);
         status.accumulate("totalCount", totalCount);
         status.accumulate("markedCount", markedCount);
-        status.accumulate("exceptionCount", exceptionCount);
+        status.accumulate("problemCount", problemCount);
+        status.accumulate("arbitrateCount", arbitrateCount);
         status.accumulate("valid", totalCount > 0);
-        status.accumulate("topCount", topCount);
         return status;
     }
 
-    @RequestMapping("/gettask")
+    @RequestMapping(value = "/getGroup", method = RequestMethod.POST)
+    @ResponseBody
+    public JSONArray getGroup(HttpServletRequest request) {
+        Marker marker = RequestUtils.getWebUser(request).getMarker();
+        JSONArray array = new JSONArray();
+        List<Marker> markers = markerService.findByExamAndSubjectAndUserIdAndEnable(marker.getExamId(),
+                marker.getSubjectCode(), marker.getUserId(), true);
+        for (Marker m : markers) {
+            JSONObject json = new JSONObject();
+            json.accumulate("markerId", m.getId());
+            json.accumulate("number", m.getGroupNumber());
+            MarkGroup group = groupService.findOne(m.getExamId(), m.getSubjectCode(), m.getGroupNumber());
+            group.setQuestionList(questionService.findByExamAndSubjectAndObjectiveAndGroupNumber(group.getExamId(),
+                    group.getSubjectCode(), false, group.getNumber()));
+            json.accumulate("title", group.getTitle());
+            json.accumulate("markedCount", group.getMarkedCount());
+            json.accumulate("totalCount", group.getLibraryCount());
+            array.add(json);
+        }
+        return array;
+    }
+
+    @RequestMapping(value = "/getTask", method = RequestMethod.POST)
     @ResponseBody
     public Task getTask(HttpServletRequest request) {
         Marker marker = RequestUtils.getWebUser(request).getMarker();
@@ -384,12 +371,21 @@ public class MarkController extends BaseController {
     private Task getFormalTask(Marker marker) {
         int retry = 1;
         Task task = null;
+        List<MarkLibrary> list = new ArrayList<MarkLibrary>();
         while (task == null) {
-            List<MarkLibrary> list = new ArrayList<MarkLibrary>();
             // 需要判断评卷员是否绑定了班级
+            Set<LibraryStatus> statusSet = new HashSet<>();
+            statusSet.add(LibraryStatus.WAITING);
             long classCount = markerClassService.countByUserIdAndExamId(marker.getUserId(), marker.getExamId());
             list = libraryService.findUnMarked(marker.getExamId(), marker.getSubjectCode(), marker.getGroupNumber(),
-                    marker.getId(), marker.getUserId(), classCount > 0, retry, 20);
+                    marker.getId(), marker.getUserId(), classCount > 0, retry, 20, statusSet);
+            if (list.isEmpty()) {
+                // 正评任务无法获取后,获取打回的任务
+                statusSet.add(LibraryStatus.REJECTED);
+                list = libraryService.findUnMarked(marker.getExamId(), marker.getSubjectCode(),
+                        marker.getGroupNumber(), marker.getId(), marker.getUserId(), classCount > 0, retry, 20,
+                        statusSet);
+            }
             if (list.isEmpty()) {
                 break;
             }
@@ -427,7 +423,7 @@ public class MarkController extends BaseController {
     }
 
     @Logging(menu = "评卷", type = LogType.UPDATE)
-    @RequestMapping(value = "/savetask", method = RequestMethod.POST)
+    @RequestMapping(value = "/saveTask", method = RequestMethod.POST)
     @ResponseBody
     public JSONObject saveTask(HttpServletRequest request, @RequestBody MarkResult markResult) {
         JSONObject result = new JSONObject();
@@ -452,7 +448,7 @@ public class MarkController extends BaseController {
             lockService.unwatch(LockType.EXAM_SUBJECT, marker.getExamId(), marker.getSubjectCode());
         }
         result.accumulate("success", success);
-        result.accumulate("status", status(request));
+        // result.accumulate("status", status(request));
         if (!success) {
             result.accumulate("message", "mark.control.task.error");
         }
@@ -460,24 +456,21 @@ public class MarkController extends BaseController {
     }
 
     @Logging(menu = "查询回评任务", type = LogType.QUERY)
-    @RequestMapping("/gethistory")
+    @RequestMapping(value = "/getHistory", method = RequestMethod.POST)
     @ResponseBody
-    public Object history(HttpServletRequest request, @RequestParam int pageNumber, @RequestParam int pageSize,
-            @RequestParam String order, @RequestParam String sort,
-            @RequestParam(required = false, defaultValue = "false") Boolean isTag,
-            @RequestParam(required = false) String secretNumber) throws Exception {
+    public Object getHistory(HttpServletRequest request, @RequestParam int pageNumber, @RequestParam int pageSize,
+            @RequestParam String order, @RequestParam String sort, @RequestParam(required = false) String secretNumber)
+            throws Exception {
         Marker marker = RequestUtils.getWebUser(request).getMarker();
         List<Task> list = new ArrayList<>();
         Direction d = Direction.DESC;
         Sort querySort = null;
-        if (sort.equals("asc")) {
+        if (sort.equals("ASC")) {
             d = Direction.ASC;
         }
-        if (order.equals("time")) {
+        if (order.equals("markerTime")) {
             querySort = new Sort(d, "markerTime");
-        } else if (order.equals("studentId")) {
-            querySort = new Sort(d, "studentId");
-        } else if (order.equals("score")) {
+        } else if (order.equals("markerScore")) {
             querySort = new Sort(d, "markerScore");
         }
         MarkGroup group = groupService.findOne(marker.getExamId(), marker.getSubjectCode(), marker.getGroupNumber());
@@ -499,9 +492,6 @@ public class MarkController extends BaseController {
                 query.orderByMarkerTimeDesc();
             }
             list = taskService.findByQuery(query);
-            for (Task task : list) {
-                task.setPrevious(true);
-            }
         } else if (group != null && group.getStatus() == MarkStatus.TRIAL) {
             // 试评查找给分历史记录
             List<TrialHistory> historyList = new ArrayList<TrialHistory>();
@@ -525,7 +515,7 @@ public class MarkController extends BaseController {
     }
 
     @Logging(menu = "修改密码", type = LogType.UPDATE)
-    @RequestMapping("/change-name")
+    @RequestMapping(value = "/changeName", method = RequestMethod.POST)
     @ResponseBody
     public JSONObject changeName(HttpServletRequest request, @RequestParam String name,
             @RequestParam(required = false) String password) {
@@ -538,7 +528,6 @@ public class MarkController extends BaseController {
         try {
             user = userService.save(user);
             result.accumulate("success", true);
-            result.accumulate("name", user.getName());
         } catch (Exception e) {
             result.accumulate("success", false);
             log.error("MarkController-修改名字出错", e);
@@ -546,17 +535,54 @@ public class MarkController extends BaseController {
         return result;
     }
 
-    @RequestMapping("/update-setting")
+    @RequestMapping(value = "/updateSetting", method = RequestMethod.POST)
     @ResponseBody
-    public JSONObject updateSetting(HttpServletRequest request, @RequestParam String setting) {
+    public JSONObject updateSetting(HttpServletRequest request, @RequestParam(required = false) String uiSetting,
+            @RequestParam(required = false) String mode) {
         Marker marker = RequestUtils.getWebUser(request).getMarker();
+        if (uiSetting != null) {
+            marker.setMarkSetting(StringEscapeUtils.unescapeHtml(StringUtils.trimToNull(uiSetting)));
+        }
+        if (mode != null) {
+            marker.setMode(MarkMode.findByName(mode));
+        }
+        markerService.save(marker);
         JSONObject result = new JSONObject();
-        markerService
-                .updateMarkSetting(marker.getId(), StringEscapeUtils.unescapeHtml(StringUtils.trimToNull(setting)));
         result.accumulate("success", true);
         return result;
     }
 
+    @RequestMapping("/clear")
+    @ResponseBody
+    public void clear(HttpServletRequest request) {
+        releaseMarker(RequestUtils.getWebUser(request).getMarker());
+    }
+
+    @ResponseBody
+    @RequestMapping(value = "/subjectSelect", method = RequestMethod.POST)
+    public Object subjectSelect(HttpServletRequest request, HttpServletResponse response, @RequestParam Integer markerId) {
+        WebUser user = RequestUtils.getWebUser(request);
+        Marker old = user.getMarker();
+        Marker marker = markerService.findById(markerId);
+        JSONObject result = new JSONObject();
+        MarkGroup group = groupService.findOne(marker.getExamId(), marker.getSubjectCode(), marker.getGroupNumber());
+        if (group == null) {
+            result.accumulate("success", false);
+            result.accumulate("message", "user.login.error.group");
+        } else if (group.getStatus() == MarkStatus.FINISH) {
+            result.accumulate("success", false);
+            result.accumulate("message", "user.login.error.finish");
+        } else {
+            releaseMarker(old);
+            user.setMarkerId(marker.getId());
+            StmmsSession session = RequestUtils.getSession(request);
+            session.saveWebUser(user);
+            sessionService.put(request, response, session);
+            result.accumulate("success", true);
+        }
+        return result;
+    }
+
     private void releaseMarker(Marker marker) {
         if (marker == null) {
             return;
@@ -584,4 +610,66 @@ public class MarkController extends BaseController {
         return json;
     }
 
+    private void setProblemType(JSONObject setting, Marker marker) {
+        List<ProblemType> problemTypes = problemTypeService.findByExamId(marker.getExamId());
+        ObjectMapper mapper = new ObjectMapper();
+        try {
+            setting.accumulate("problemTypes", mapper.writeValueAsString(problemTypes));
+        } catch (JsonProcessingException e) {
+            log.error("MarkController-问题类型获取出错", e);
+        }
+    }
+
+    private void setSubjectAndSheetConfig(JSONObject setting, Marker marker, Exam exam) {
+        ExamSubject examSubject = subjectService.find(marker.getExamId(), marker.getSubjectCode());
+        String sheetConfig = "";
+        if (StringUtils.isNotBlank(examSubject.getSheetConfig())) {
+            sheetConfig = buildPictureConfig(examSubject.getSheetConfig());
+        } else if (StringUtils.isNotBlank(exam.getSheetConfig())) {
+            sheetConfig = buildPictureConfig(exam.getSheetConfig());
+        }
+        setting.accumulate("sheetConfig", sheetConfig);
+
+        JSONObject subject = new JSONObject();
+        subject.accumulate("name", examSubject.getName());
+        subject.accumulate("code", examSubject.getCode());
+        subject.accumulate("paperUrl", examSubject.getPaperUrl() == null ? "" : examSubject.getPaperUrl());
+        subject.accumulate("answerUrl", examSubject.getAnswerUrl() == null ? "" : examSubject.getAnswerUrl());
+        setting.accumulate("subject", subject);
+    }
+
+    private void setModeAndForceMode(JSONObject setting, Exam exam, Marker marker, MarkGroup group) {
+        MarkMode mode = null;
+        boolean forceMode = false;
+        if (MarkMode.findByName(forceMarkMode) != null) {
+            // 全局配置的强制评卷模式
+            mode = MarkMode.findByName(forceMarkMode);
+            forceMode = true;
+        } else {
+            // 没有全局配置,优先从大题配置取强制评卷模式
+            if (group != null && group.getMarkMode() != null) {
+                mode = group.getMarkMode();
+                forceMode = true;
+            }
+            // 否则取评卷员当前记录的评卷模式
+            if (mode == null) {
+                mode = marker.getMode();
+            }
+            if (mode == null) {
+                mode = MarkMode.COMMON;
+            }
+            if (marker.getMode() != mode) {
+                marker.setMode(mode);
+                markerService.save(marker);
+            }
+        }
+        setting.accumulate("mode", mode);
+        setting.accumulate("forceMode", forceMode);
+
+        if (ExamType.MULTI_MEDIA.equals(exam.getType())) {
+            setting.accumulate("forceMode", true);
+            setting.accumulate("sheetView", false);
+            setting.accumulate("forceSpecialTag", false);
+        }
+    }
 }

+ 1 - 1
stmms-web/src/main/webapp/WEB-INF/views/modules/exam/inspectedList.jsp

@@ -120,7 +120,7 @@
             if (!confirm('确定要取消复核吗?')) {
                 return;
             }
-            $.post('${ctx}/admin/exam/inspected/cancel', {id: $(this).attr('data-id')}, function (result) {
+            $.post('${ctx}/admin/exam/inspected/cancel', {studentId: $(this).attr('data-id')}, function (result) {
                 if (result.success == true) {
                     alert('取消成功');
                     $("#searchForm").submit();