1
0
Pārlūkot izejas kodu

Squashed commit of the following:

commit c139ffd067327e389b8f6cd9a382e6f40cccd945
Author: ting.yin <yinting@qmth.com.cn>
Date:   Fri Mar 12 13:50:46 2021 +0800

    修复刷新取任务时间刷新问题

commit da7892f3f37ffaef8d7a4267e3a1652501eafdf6
Author: ting.yin <yinting@qmth.com.cn>
Date:   Fri Mar 12 09:46:59 2021 +0800

    fix

commit bae50518a8811069f6d672ae7f4a20b630b43ef1
Author: luoshi <luoshi@qmth.com.cn>
Date:   Fri Mar 12 09:05:46 2021 +0800

    修改评卷任务提交后的释放策略,需要等到数据库事务提交后才进行

commit e2200b14f1906f09b8da587c7a54ea9872aa0fcf
Author: luoshi <luoshi@qmth.com.cn>
Date:   Thu Mar 11 16:43:28 2021 +0800

    修改领取任务策略,加入上锁成功后的任务状态强制校验,避免重复领取已评任务

commit 9726a0a50bc1c07ed8bf3dc106a48a0b8aa6ac60
Author: luoshi <luoshi@qmth.com.cn>
Date:   Thu Mar 11 15:52:36 2021 +0800

    优化TaskLockUtil性能;修改TaskLock.list方法放回数据类型;修改领取任务分页,尝试解决重复领取已评任务问题;

commit fef3f0dc8c8115441d56b83aba13a0c39fd600ec
Author: ting.yin <yinting@qmth.com.cn>
Date:   Wed Mar 10 09:44:17 2021 +0800

    修复chrome版本88后期无window.opener导致框图失败问题

commit f644821c7c28691df95750fd57956229a6cb3282
Author: ting.yin <yinting@qmth.com.cn>
Date:   Mon Mar 8 17:49:50 2021 +0800

    fixbugs

commit 99aa5ab14839f737092b5633b324880446437ae1
Author: ting.yin <yinting@qmth.com.cn>
Date:   Fri Mar 5 09:36:53 2021 +0800

    修复同时提交统分问题

commit d6845058eb5f681a17512b04a83bc147051228bb
Author: ting.yin <yinting@qmth.com.cn>
Date:   Thu Mar 4 15:43:58 2021 +0800

    修改统分计算时java对浮点数的加减计算

commit 43fffbaf51f070d228008c69b0f4fd1b20b8b94f
Author: ting.yin <yinting@qmth.com.cn>
Date:   Thu Mar 4 10:47:46 2021 +0800

    给分板小数相减问题

commit cbb9efd0290b242d24f0af352ae240adabc0fceb
Author: ting.yin <yinting@qmth.com.cn>
Date:   Wed Mar 3 15:15:51 2021 +0800

    修复间隔分为0.1时给分板steplist数量不对问题

commit 5e7f1ec0cc2a6293e5d89295d432f8eccf9be3ec
Author: ting.yin <yinting@qmth.com.cn>
Date:   Wed Mar 3 14:25:37 2021 +0800

    修复导入复核排序

commit 087b6fc1a6f0dd457f14b5a0e51e8f0100d16dde
Author: ting.yin <yinting@qmth.com.cn>
Date:   Wed Mar 3 11:14:19 2021 +0800

    修复间隔必须大于0.1和给分板相加问题

commit 334779730aa482708e61a590f8e7d7a7a9515224
Author: ting.yin <yinting@qmth.com.cn>
Date:   Fri Feb 26 15:15:46 2021 +0800

    fixbugs

commit fdd6cfb9e60d960aa5662c40c32f2ad3a343c0cb
Author: ting.yin <yinting@qmth.com.cn>
Date:   Fri Feb 26 15:10:33 2021 +0800

    fixbugs

commit f1dc8747101a76e80a1ef0862832600f27a7c461
Author: ting.yin <yinting@qmth.com.cn>
Date:   Fri Feb 26 15:04:04 2021 +0800

    update

commit ba30c910ec65f19c424b581543de7a6b56570c8c
Author: ting.yin <yinting@qmth.com.cn>
Date:   Fri Feb 26 11:22:27 2021 +0800

    update

commit 61f9c5f8f74fb07d2b9978dc7a78dd8f9b360f0f
Author: ting.yin <yinting@qmth.com.cn>
Date:   Thu Feb 25 16:56:21 2021 +0800

    update

commit 120525d669f40d637e934df5328cabad5c797eb4
Author: ting.yin <yinting@qmth.com.cn>
Date:   Thu Feb 25 10:46:44 2021 +0800

    update

commit 9de6a555a7252c254fe8ef823bda7f6126fa1fcb
Author: ting.yin <ting.yin@192.168.11.32>
Date:   Thu Feb 25 10:09:57 2021 +0800

    update

commit 1975082071d24086366fc4c8624d5f25e489a1ae
Author: ting.yin <ting.yin@192.168.11.32>
Date:   Thu Feb 25 10:09:27 2021 +0800

    更新锁卷逻辑,修复评卷页面拖拽问题,间隔分不能为0
luoshi 4 gadi atpakaļ
vecāks
revīzija
b8f9345329
29 mainītis faili ar 645 papildinājumiem un 715 dzēšanām
  1. 2 2
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/common/BaseQuery.java
  2. 4 1
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/model/ExamQuestion.java
  3. 17 0
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/service/InspectedService.java
  4. 136 0
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/service/impl/InspectedServiceImpl.java
  5. 9 6
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/mark/dao/MarkLibraryDao.java
  6. 44 0
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/mark/model/SubmitResult.java
  7. 36 37
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/mark/service/Impl/MarkCronService.java
  8. 70 66
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/mark/service/Impl/MarkServiceImpl.java
  9. 5 16
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/mark/service/MarkService.java
  10. 0 52
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/utils/AbstractTask.java
  11. 0 34
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/utils/BlockTaskCountUtil.java
  12. 0 197
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/utils/CurrentTaskUtil2.java
  13. 232 0
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/utils/TaskLock.java
  14. 43 0
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/utils/TaskLockUtil.java
  15. 0 206
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/utils/TrialTaskUtil.java
  16. 2 2
      stmms-web/src/main/java/cn/com/qmth/stmms/admin/dto/SubjectiveQuestionDTO.java
  17. 2 1
      stmms-web/src/main/java/cn/com/qmth/stmms/admin/exam/ImportQueryController.java
  18. 16 57
      stmms-web/src/main/java/cn/com/qmth/stmms/admin/exam/InspectedController.java
  19. 7 8
      stmms-web/src/main/java/cn/com/qmth/stmms/mark/MarkController.java
  20. 4 18
      stmms-web/src/main/java/cn/com/qmth/stmms/monitor/TaskMonitorController.java
  21. 1 1
      stmms-web/src/main/webapp/WEB-INF/views/modules/exam/examEdit.jsp
  22. 1 1
      stmms-web/src/main/webapp/WEB-INF/views/modules/exam/groupAdd.jsp
  23. 1 1
      stmms-web/src/main/webapp/WEB-INF/views/modules/exam/groupEditFull.jsp
  24. 3 3
      stmms-web/src/main/webapp/WEB-INF/views/modules/exam/groupEditSimple.jsp
  25. 1 1
      stmms-web/src/main/webapp/WEB-INF/views/modules/exam/subjectEdit.jsp
  26. 1 1
      stmms-web/src/main/webapp/WEB-INF/views/modules/mark/markNew.jsp
  27. 1 1
      stmms-web/src/main/webapp/WEB-INF/views/modules/mark/markTrack.jsp
  28. 4 0
      stmms-web/src/main/webapp/static/mark-track/js/mark-control.js
  29. 3 3
      stmms-web/src/main/webapp/static/mark-track/js/modules/mark-board.js

+ 2 - 2
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/common/BaseQuery.java

@@ -261,10 +261,10 @@ public class BaseQuery<T> implements Pageable {
         sb.append("<li class=\"disabled controls\"><a href=\"javascript:\">当前 ");
         sb.append("<input type=\"text\" value=\"" + pageNumber
                 + "\" onkeypress=\"var e=window.event||this;var c=e.keyCode||e.which;if(c==13)");
-        sb.append(funcName + "(this.value," + pageSize + ");\" onclick=\"this.select();\"/> / ");
+        sb.append(funcName + "(this.value," + pageSize + ");\" onclick=\"this.select();\"/> / ");
         sb.append("<input type=\"text\" value=\"" + pageSize
                 + "\" onkeypress=\"var e=window.event||this;var c=e.keyCode||e.which;if(c==13)");
-        sb.append(funcName + "(" + pageNumber + ",this.value);\" onclick=\"this.select();\"/> ,");
+        sb.append(funcName + "(" + pageNumber + ",this.value);\" onclick=\"this.select();\"/> ,");
         sb.append("共 " + totalCount + " 条" + (message != null ? message : "") + "</a><li>\n");
 
         sb.insert(0, "<ul>\n").append("</ul>\n");

+ 4 - 1
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/model/ExamQuestion.java

@@ -161,9 +161,12 @@ public class ExamQuestion implements Serializable {
     public List<Double> getScoreList() {
         List<Double> list = new LinkedList<Double>();
         if (totalScore != null && intervalScore != null) {
+            totalScore = totalScore * 100;
+            intervalScore = intervalScore * 100;
             for (double score = 0; score <= totalScore; score += intervalScore) {
-                list.add(score);
+                list.add(score / 100);
             }
+            totalScore = totalScore / 100;
             if (list.get(list.size() - 1) < totalScore) {
                 list.add(totalScore);
             }

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

@@ -0,0 +1,17 @@
+package cn.com.qmth.stmms.biz.exam.service;
+
+import java.util.List;
+
+import cn.com.qmth.stmms.biz.exam.model.ExamStudent;
+import cn.com.qmth.stmms.biz.exam.query.ExamStudentSearchQuery;
+import cn.com.qmth.stmms.common.enums.SubjectiveStatus;
+
+public interface InspectedService {
+
+    List<ExamStudent> findByQuery(ExamStudentSearchQuery query, SubjectiveStatus status, Integer mainNumber,
+            Double mainStartScore, Double mainEndScore, Double questionScore);
+
+    Integer countByQuery(ExamStudentSearchQuery query, SubjectiveStatus status, Integer mainNumber,
+            Double mainStartScore, Double mainEndScore, Double questionScore);
+
+}

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

@@ -0,0 +1,136 @@
+package cn.com.qmth.stmms.biz.exam.service.impl;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.persistence.EntityManager;
+import javax.persistence.PersistenceContext;
+import javax.persistence.Query;
+
+import org.apache.commons.lang.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import cn.com.qmth.stmms.biz.common.BaseQueryService;
+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.common.enums.SubjectiveStatus;
+
+@Service
+public class InspectedServiceImpl extends BaseQueryService<ExamStudent> implements InspectedService {
+
+    @PersistenceContext
+    private EntityManager entityManager;
+
+    @Autowired
+    private ExamStudentService studentService;
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public List<ExamStudent> findByQuery(ExamStudentSearchQuery query, SubjectiveStatus status, Integer mainNumber,
+            Double mainStartScore, Double mainEndScore, Double questionScore) {
+        StringBuilder dataSql = new StringBuilder("select distinct s.id "
+                + " from eb_exam_student s left join eb_subjective_score e on e.student_id = s.id ");
+        StringBuilder limitSql = new StringBuilder(" limit :offset,:pageSize");
+        Query dataQuery = getQuery(query, status, mainNumber, mainStartScore, mainEndScore, questionScore, dataSql,
+                limitSql);
+        dataQuery.setParameter("offset", (query.getPageNumber() - 1) * query.getPageSize());
+        dataQuery.setParameter("pageSize", query.getPageSize());
+        List<Integer> list = dataQuery.getResultList();
+        List<ExamStudent> resultList = new ArrayList<ExamStudent>();
+        if (list != null && !list.isEmpty()) {
+            for (Integer id : list) {
+                ExamStudent e = studentService.findById(id);
+                resultList.add(e);
+            }
+        }
+        return resultList;
+
+    }
+
+    private Query getQuery(ExamStudentSearchQuery query, SubjectiveStatus status, Integer mainNumber,
+            Double mainStartScore, Double mainEndScore, Double questionScore, StringBuilder dataSql,
+            StringBuilder limitSql) {
+        StringBuilder whereSql = new StringBuilder(" WHERE s.is_upload = 1 and s.is_absent = 0 and s.is_breach = 0 ");
+        if (query.getExamId() != null) {
+            whereSql.append(" and s.exam_id = :examId");
+        }
+        if (StringUtils.isNotBlank(query.getSubjectCode())) {
+            whereSql.append(" and s.subject_code = :subjectCode");
+        }
+        if (status != null) {
+            whereSql.append(" and s.subjective_status = :status");
+        } else {
+            whereSql.append(" and s.subjective_status IN ('MARKED','INSPECTED')");
+        }
+        if (query.getStartScore() != null) {
+            whereSql.append(" and (s.objective_score+s.subjective_score) >= :startScore");
+        }
+        if (query.getEndScore() != null) {
+            whereSql.append(" and (s.objective_score+s.subjective_score) <= :endScore");
+        }
+        if (mainNumber != null) {
+            whereSql.append(" and e.main_number = :mainNumber");
+        }
+        if (mainStartScore != null) {
+            whereSql.append(" and e.main_score >= :mainStartScore");
+        }
+        if (mainEndScore != null) {
+            whereSql.append(" and e.main_score <= :mainEndScore");
+        }
+        if (questionScore != null) {
+            whereSql.append(" and e.score = :questionScore");
+        }
+        dataSql.append(whereSql);
+        // StringBuilder orderSql = new StringBuilder("order by s.id desc ");
+        // dataSql.append(orderSql);
+        if (limitSql != null) {
+            dataSql.append(limitSql);
+        }
+        Query dataQuery = entityManager.createNativeQuery(dataSql.toString());
+
+        if (query.getExamId() != null) {
+            dataQuery.setParameter("examId", query.getExamId());
+        }
+        if (StringUtils.isNotBlank(query.getSubjectCode())) {
+            dataQuery.setParameter("subjectCode", query.getSubjectCode());
+        }
+        if (status != null) {
+            dataQuery.setParameter("status", status.toString());
+        }
+        if (query.getStartScore() != null) {
+            dataQuery.setParameter("startScore", query.getStartScore());
+        }
+        if (query.getEndScore() != null) {
+            dataQuery.setParameter("endScore", query.getEndScore());
+        }
+        if (mainNumber != null) {
+            dataQuery.setParameter("mainNumber", mainNumber);
+        }
+        if (mainStartScore != null) {
+            dataQuery.setParameter("mainStartScore", mainStartScore);
+        }
+        if (mainEndScore != null) {
+            dataQuery.setParameter("mainEndScore", mainEndScore);
+        }
+        if (questionScore != null) {
+            dataQuery.setParameter("questionScore", questionScore);
+        }
+        return dataQuery;
+    }
+
+    @Override
+    public Integer countByQuery(ExamStudentSearchQuery query, SubjectiveStatus status, Integer mainNumber,
+            Double mainStartScore, Double mainEndScore, Double questionScore) {
+        StringBuilder countSql = new StringBuilder("select count(distinct s.id) "
+                + "from eb_exam_student s left join eb_subjective_score e on e.student_id = s.id ");
+        Query countQuery = getQuery(query, status, mainNumber, mainStartScore, mainEndScore, questionScore, countSql,
+                null);
+        Object singleResult = countQuery.getResultList().get(0);
+        Integer count = singleResult == null ? 0 : Integer.valueOf(singleResult.toString());
+        return count;
+    }
+
+}

+ 9 - 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,
@@ -69,6 +69,9 @@ public interface MarkLibraryDao extends JpaRepository<MarkLibrary, Integer>, Jpa
     @Query("select count(f) from MarkLibrary f where f.studentId=?1 and f.markerId=?2 and f.id!=?3")
     long countByStudentIdAndMarkerIdAndIdNotEqual(Integer studentId, Integer markerId, Integer id);
 
+    @Query("select count(f) from MarkLibrary f where f.id=?1 and f.status=?2")
+    long countByIdAndStatus(Integer id, LibraryStatus status);
+
     @Modifying(clearAutomatically = true)
     @Query("update MarkLibrary m set m.status=?4, m.markerId=null, m.markerTime=null, m.markerScore=null, m.markerScoreList=null, m.markerSpent=null, "
             + "m.headerId=null , m.headerTime=null , m.headerScore=null , m.headerScoreList=null where m.examId=?1 and m.subjectCode=?2 and m.groupNumber=?3")
@@ -111,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")

+ 44 - 0
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/mark/model/SubmitResult.java

@@ -0,0 +1,44 @@
+package cn.com.qmth.stmms.biz.mark.model;
+
+/**
+ * 评卷提交结果状态
+ */
+public class SubmitResult {
+
+    private boolean success;
+
+    private MarkLibrary markLibrary;
+
+    private TrialLibrary trialLibrary;
+
+    public static SubmitResult faile() {
+        return new SubmitResult(false, null, null);
+    }
+
+    public static SubmitResult success(MarkLibrary library) {
+        return new SubmitResult(true, library, null);
+    }
+
+    public static SubmitResult success(TrialLibrary library) {
+        return new SubmitResult(true, null, library);
+    }
+
+    private SubmitResult(boolean success, MarkLibrary markLibrary, TrialLibrary trialLibrary) {
+        this.success = success;
+        this.markLibrary = markLibrary;
+        this.trialLibrary = trialLibrary;
+    }
+
+    public boolean isSuccess() {
+        return success;
+    }
+
+    public MarkLibrary getMarkLibrary() {
+        return markLibrary;
+    }
+
+    public TrialLibrary getTrialLibrary() {
+        return trialLibrary;
+    }
+
+}

+ 36 - 37
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/mark/service/Impl/MarkCronService.java

@@ -1,5 +1,15 @@
 package cn.com.qmth.stmms.biz.mark.service.Impl;
 
+import java.util.Date;
+import java.util.List;
+
+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.scheduling.annotation.Scheduled;
+import org.springframework.stereotype.Component;
+
 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;
@@ -10,19 +20,9 @@ import cn.com.qmth.stmms.biz.exam.service.MarkGroupService;
 import cn.com.qmth.stmms.biz.exam.service.MarkerService;
 import cn.com.qmth.stmms.biz.lock.LockService;
 import cn.com.qmth.stmms.biz.mark.service.MarkService;
-import cn.com.qmth.stmms.biz.utils.FormalTaskUtil;
-import cn.com.qmth.stmms.biz.utils.TrialTaskUtil;
+import cn.com.qmth.stmms.biz.utils.TaskLockUtil;
 import cn.com.qmth.stmms.common.enums.LockType;
 import cn.com.qmth.stmms.common.enums.MarkStatus;
-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.scheduling.annotation.Scheduled;
-import org.springframework.stereotype.Component;
-
-import java.util.Date;
-import java.util.List;
 
 /**
  * 与评卷相关的所有定时任务
@@ -76,8 +76,7 @@ public class MarkCronService {
     @Scheduled(cron = "${mark.cleanTaskSchedule}")
     public void cronCleanTask() {
         try {
-            FormalTaskUtil.clearTimeoutTask(timeoutMinute);
-            TrialTaskUtil.clearTimeoutTask(timeoutMinute);
+            TaskLockUtil.clearTimeoutTask(timeoutMinute * 60 * 1000);
         } catch (Exception e) {
             log.error("CronCleanTask error", e);
         }
@@ -123,11 +122,11 @@ public class MarkCronService {
         // 获取主观题总分大于0的科目
         List<ExamSubject> subjects = subjectService.list(examId, 0);
         for (ExamSubject subject : subjects) {
-            List<MarkGroup> groups = groupService
-                    .findByExamAndSubjectAndStatus(examId, subject.getCode(), MarkStatus.FORMAL);
+            List<MarkGroup> groups = groupService.findByExamAndSubjectAndStatus(examId, subject.getCode(),
+                    MarkStatus.FORMAL);
             for (MarkGroup markGroup : groups) {
-                List<Marker> markers = markerService
-                        .findByExamAndSubjectAndGroup(examId, subject.getCode(), markGroup.getNumber());
+                List<Marker> markers = markerService.findByExamAndSubjectAndGroup(examId, subject.getCode(),
+                        markGroup.getNumber());
                 for (Marker marker : markers) {
                     try {
                         if (markService.needUpdateQuality(marker, markerActiveExpireMinute)) {
@@ -147,8 +146,8 @@ public class MarkCronService {
         List<ExamSubject> subjects = subjectService.listSubjectiveScore(examId, 0d);
         for (ExamSubject subject : subjects) {
             // 清除缺考考生和违纪考生
-            List<ExamStudent> list = studentService
-                    .findAbsentOrBreachLibraryStudent(subject.getExamId(), subject.getCode());
+            List<ExamStudent> list = studentService.findAbsentOrBreachLibraryStudent(subject.getExamId(),
+                    subject.getCode());
             if (list != null) {
                 for (ExamStudent student : list) {
                     try {
@@ -163,16 +162,15 @@ public class MarkCronService {
             }
             // 处理正常考生
             // 生成试评任务
-            List<MarkGroup> groups = groupService
-                    .findByExamAndSubjectAndStatus(subject.getExamId(), subject.getCode(), MarkStatus.TRIAL);
+            List<MarkGroup> groups = groupService.findByExamAndSubjectAndStatus(subject.getExamId(), subject.getCode(),
+                    MarkStatus.TRIAL);
             for (MarkGroup group : groups) {
                 buildTrialLibrary(group);
             }
             // 生成正评任务
             // 试评状态的分组也提前生成
-            groups = groupService
-                    .findByExamAndSubjectAndStatus(subject.getExamId(), subject.getCode(), MarkStatus.FORMAL,
-                            MarkStatus.TRIAL);
+            groups = groupService.findByExamAndSubjectAndStatus(subject.getExamId(), subject.getCode(),
+                    MarkStatus.FORMAL, MarkStatus.TRIAL);
             for (MarkGroup group : groups) {
                 buildFormalLibrary(subject, group);
             }
@@ -182,17 +180,16 @@ public class MarkCronService {
     private void buildFormalLibrary(ExamSubject subject, MarkGroup group) {
         Date lastBuildTime = group.getBuildTime();
         int count = 0;
-        ExamStudent student = studentService
-                .findUnLibraryStudent(group.getExamId(), group.getSubjectCode(), group.getNumber(), lastBuildTime);
+        ExamStudent student = studentService.findUnLibraryStudent(group.getExamId(), group.getSubjectCode(),
+                group.getNumber(), lastBuildTime);
         while (student != null) {
             // 尝试构造评卷任务
             try {
                 lockService.watch(LockType.GROUP, group.getExamId(), group.getSubjectCode(), group.getNumber());
                 lockService.watch(LockType.STUDENT, student.getId());
                 // 上锁后重复验证分组状态
-                if (!groupService
-                        .validateStatus(group.getExamId(), group.getSubjectCode(), group.getNumber(), MarkStatus.FORMAL,
-                                MarkStatus.TRIAL)) {
+                if (!groupService.validateStatus(group.getExamId(), group.getSubjectCode(), group.getNumber(),
+                        MarkStatus.FORMAL, MarkStatus.TRIAL)) {
                     break;
                 }
                 // 上锁后重复验证考生状态
@@ -202,15 +199,16 @@ public class MarkCronService {
                     count++;
                 }
             } catch (Exception e) {
-                log.error("build formal library error for studentId=" + student.getId() + ", groupNumber=" + group
-                        .getNumber(), e);
+                log.error(
+                        "build formal library error for studentId=" + student.getId() + ", groupNumber="
+                                + group.getNumber(), e);
             } finally {
                 lockService.unwatch(LockType.STUDENT, student.getId());
                 lockService.unwatch(LockType.GROUP, group.getExamId(), group.getSubjectCode(), group.getNumber());
             }
             // 取下一个考生
-            student = studentService
-                    .findUnLibraryStudent(group.getExamId(), group.getSubjectCode(), group.getNumber(), lastBuildTime);
+            student = studentService.findUnLibraryStudent(group.getExamId(), group.getSubjectCode(), group.getNumber(),
+                    lastBuildTime);
         }
         // 有新任务创建,同时正评状态,此时才需要更新任务数量
         if (count > 0) {
@@ -225,8 +223,8 @@ public class MarkCronService {
     private void buildTrialLibrary(MarkGroup group) {
         while (group.getTrialCount() > group.getLibraryCount()) {
             // 随机取一个未生成试评任务的考生
-            ExamStudent student = studentService
-                    .randomUnTrialStudent(group.getExamId(), group.getSubjectCode(), group.getNumber());
+            ExamStudent student = studentService.randomUnTrialStudent(group.getExamId(), group.getSubjectCode(),
+                    group.getNumber());
             if (student == null) {
                 return;
             }
@@ -246,8 +244,9 @@ public class MarkCronService {
                     markService.updateMarkedCount(group);
                 }
             } catch (Exception e) {
-                log.error("build trial library error for studentId=" + student.getId() + ", groupNumber=" + group
-                        .getNumber(), e);
+                log.error(
+                        "build trial library error for studentId=" + student.getId() + ", groupNumber="
+                                + group.getNumber(), e);
             } finally {
                 lockService.unwatch(LockType.STUDENT, student.getId());
                 lockService.unwatch(LockType.GROUP, group.getExamId(), group.getSubjectCode(), group.getNumber());

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

@@ -8,11 +8,11 @@ import cn.com.qmth.stmms.biz.mark.dao.*;
 import cn.com.qmth.stmms.biz.mark.model.*;
 import cn.com.qmth.stmms.biz.mark.query.MarkLibrarySearchQuery;
 import cn.com.qmth.stmms.biz.mark.service.MarkService;
-import cn.com.qmth.stmms.biz.utils.FormalTaskUtil;
 import cn.com.qmth.stmms.biz.utils.ScoreItem;
-import cn.com.qmth.stmms.biz.utils.TrialTaskUtil;
+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;
@@ -21,11 +21,7 @@ import org.springframework.data.domain.Sort;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
 import java.util.concurrent.ConcurrentHashMap;
 
 /**
@@ -99,9 +95,11 @@ public class MarkServiceImpl implements MarkService {
     public int applyCount(MarkGroup group) {
         int count = 0;
         if (group.getStatus() == MarkStatus.TRIAL) {
-            count = TrialTaskUtil.count(group.getExamId(), group.getSubjectCode(), group.getNumber());
+            TaskLock taskLock = TaskLockUtil.getTrialTask(getGroupKey(group));
+            count = taskLock.count();
         } else if (group.getStatus() == MarkStatus.FORMAL) {
-            count = FormalTaskUtil.count(group.getExamId(), group.getSubjectCode(), group.getNumber());
+            TaskLock taskLock = TaskLockUtil.getFormalTask(getGroupKey(group));
+            count = taskLock.count();
         }
         return count;
     }
@@ -121,9 +119,11 @@ public class MarkServiceImpl implements MarkService {
         }
         if (group != null) {
             if (group.getStatus() == MarkStatus.FORMAL) {
-                return FormalTaskUtil.count(marker);
+                TaskLock taskLock = TaskLockUtil.getFormalTask(getGroupKey(marker));
+                return taskLock.count(marker.getId());
             } else if (group.getStatus() == MarkStatus.TRIAL) {
-                return TrialTaskUtil.count(marker);
+                TaskLock taskLock = TaskLockUtil.getTrialTask(getGroupKey(marker));
+                return taskLock.count(marker.getId());
             }
         }
         return 0;
@@ -162,9 +162,11 @@ public class MarkServiceImpl implements MarkService {
     @Override
     public void releaseByGroup(MarkGroup group) {
         if (group.getStatus() == MarkStatus.TRIAL) {
-            TrialTaskUtil.clear(group.getExamId(), group.getSubjectCode(), group.getNumber());
+            TaskLock taskLock = TaskLockUtil.getTrialTask(getGroupKey(group));
+            taskLock.clear();
         } else if (group.getStatus() == MarkStatus.FORMAL) {
-            FormalTaskUtil.clear(group.getExamId(), group.getSubjectCode(), group.getNumber());
+            TaskLock taskLock = TaskLockUtil.getFormalTask(getGroupKey(group));
+            taskLock.clear();
         }
     }
 
@@ -275,12 +277,19 @@ public class MarkServiceImpl implements MarkService {
     @Override
     public boolean applyLibrary(MarkLibrary library, Marker marker) {
         // 查询待领取任务时,已经做了多评同一studentId互斥处理
-        // 首先判断多评情况下,同一个studentId是否已被该评卷员处理过
-        // if (libraryDao.countByStudentIdAndMarkerId(library.getStudentId(),
-        // marker.getId()) > 0) {
-        // return false;
-        // }
-        return FormalTaskUtil.add(marker, getApplyTaskId(library));
+        TaskLock taskLock = TaskLockUtil.getFormalTask(getGroupKey(marker));
+        boolean lock = taskLock.add(library.getStudentId(), library.getTaskNumber(), marker.getId());
+        // 上锁失败直接返回
+        if (!lock) {
+            return false;
+        }
+        // 重复校验任务状态
+        if (libraryDao.countByIdAndStatus(library.getId(), library.getStatus()) == 1) {
+            return true;
+        } else {
+            taskLock.remove(library.getStudentId(), library.getTaskNumber(), marker.getId());
+            return false;
+        }
     }
 
     /**
@@ -294,7 +303,8 @@ public class MarkServiceImpl implements MarkService {
      */
     @Override
     public boolean applyLibrary(TrialLibrary library, Marker marker) {
-        return TrialTaskUtil.add(marker, getApplyTaskId(library, marker));
+        TaskLock taskLock = TaskLockUtil.getTrialTask(getGroupKey(marker));
+        return taskLock.add(getApplyTaskId(library, marker), 1, marker.getId());
     }
 
     /**
@@ -308,7 +318,8 @@ public class MarkServiceImpl implements MarkService {
      */
     @Override
     public boolean hasApplied(MarkLibrary library, Marker marker) {
-        return FormalTaskUtil.exists(marker, getApplyTaskId(library));
+        TaskLock taskLock = TaskLockUtil.getFormalTask(getGroupKey(marker));
+        return taskLock.exist(library.getStudentId(), library.getTaskNumber(), marker.getId());
     }
 
     /**
@@ -322,33 +333,29 @@ public class MarkServiceImpl implements MarkService {
      */
     @Override
     public boolean hasApplied(TrialLibrary library, Marker marker) {
-        return TrialTaskUtil.exists(marker, getApplyTaskId(library, marker));
-    }
-
-    /**
-     * 释放某个评卷员已领取的正评任务
-     *
-     * @param library
-     *            - 正评任务
-     * @param marker
-     *            - 评卷员
-     */
-    @Override
-    public void releaseLibrary(MarkLibrary library, Marker marker) {
-        FormalTaskUtil.remove(marker, getApplyTaskId(library));
+        TaskLock taskLock = TaskLockUtil.getTrialTask(getGroupKey(marker));
+        return taskLock.exist(getApplyTaskId(library, marker), 1, marker.getId());
     }
 
     /**
-     * 释放某个评卷员已领取的试评任务
+     * 释放某个评卷员已完成的评卷任务
      *
-     * @param library
-     *            - 试评任务
+     * @param result
+     *            - 评卷结果
      * @param marker
      *            - 评卷员
      */
     @Override
-    public void releaseLibrary(TrialLibrary library, Marker marker) {
-        TrialTaskUtil.remove(marker, getApplyTaskId(library, marker));
+    public void releaseTask(SubmitResult result, Marker marker) {
+        if (result.getMarkLibrary() != null) {
+            TaskLock taskLock = TaskLockUtil.getFormalTask(getGroupKey(marker));
+            taskLock.remove(result.getMarkLibrary().getStudentId(), result.getMarkLibrary().getTaskNumber(),
+                    marker.getId());
+            taskLock.refresh(marker.getId());
+        } else if (result.getTrialLibrary() != null) {
+            TaskLock taskLock = TaskLockUtil.getTrialTask(getGroupKey(marker));
+            taskLock.remove(getApplyTaskId(result.getTrialLibrary(), marker), 1, marker.getId());
+        }
     }
 
     /**
@@ -359,8 +366,8 @@ public class MarkServiceImpl implements MarkService {
      */
     @Override
     public void releaseByMarker(Marker marker) {
-        FormalTaskUtil.clear(marker);
-        TrialTaskUtil.clear(marker);
+        TaskLock taskLock = TaskLockUtil.getFormalTask(getGroupKey(marker));
+        taskLock.clear(marker.getId());
     }
 
     /**
@@ -463,12 +470,12 @@ public class MarkServiceImpl implements MarkService {
      */
     @Override
     @Transactional
-    public boolean submitTask(MarkResult result, Marker marker) {
+    public SubmitResult submitTask(MarkResult result, Marker marker) {
         // 判断评卷分组是否存在/评卷是否结束
         MarkGroup group = groupDao.findOne(marker.getExamId(), marker.getSubjectCode(), marker.getGroupNumber());
         if (group == null || group.getStatus() == MarkStatus.FINISH
                 || group.getStatus().getValue() != result.getStatusValue()) {
-            return false;
+            return SubmitResult.faile();
         }
 
         // 根据评卷状态选择读取不同的评卷任务
@@ -481,8 +488,8 @@ public class MarkServiceImpl implements MarkService {
                         result.getSpent(), LibraryStatus.WAITING, LibraryStatus.MARKED, LibraryStatus.INSPECTED) != 0) {
                     saveProblemHistory(result, library);
                     updateMarkedCount(group);
-                    releaseLibrary(library, marker);
-                    return true;
+                    // releaseLibrary(library, marker);
+                    return SubmitResult.success(library);
                 }
             }
             if (library != null && library.getExamId().equals(group.getExamId())
@@ -491,8 +498,8 @@ public class MarkServiceImpl implements MarkService {
                     && result.getTotalScore() <= group.getTotalScore() && StringUtils.isNotBlank(result.getScoreList())) {
                 if (submitLibrary(library, marker, group, result)) {
                     updateMarkedCount(group);
-                    releaseLibrary(library, marker);
-                    return true;
+                    // releaseLibrary(library, marker);
+                    return SubmitResult.success(library);
                 }
             }
         } else if (group.getStatus() == MarkStatus.TRIAL) {
@@ -523,12 +530,12 @@ public class MarkServiceImpl implements MarkService {
                         trialTagDao.save(result.getTagList(history));
                     }
                     updateMarkedCount(group);
-                    releaseLibrary(library, marker);
-                    return true;
+                    // releaseLibrary(library, marker);
+                    return SubmitResult.success(library);
                 }
             }
         }
-        return false;
+        return SubmitResult.faile();
     }
 
     private void saveProblemHistory(MarkResult result, MarkLibrary library) {
@@ -814,7 +821,7 @@ public class MarkServiceImpl implements MarkService {
         // 循环所有主观得分明细
         List<SubjectiveScore> list = scoreDao.findByStudentId(studentId);
         for (SubjectiveScore ss : list) {
-            totalScore += ss.getScore();
+            totalScore = BigDecimalUtils.add(totalScore, ss.getScore());
             scoreList.add(new ScoreItem(ss));
             List<SubjectiveScore> mainScoreList = map.get(ss.getMainNumber());
             if (mainScoreList == null) {
@@ -828,7 +835,7 @@ public class MarkServiceImpl implements MarkService {
             List<SubjectiveScore> mainScoreList = map.get(mainNumber);
             double mainScore = 0.0;
             for (SubjectiveScore subjectiveScore : mainScoreList) {
-                mainScore += subjectiveScore.getScore();
+                mainScore = BigDecimalUtils.add(mainScore, subjectiveScore.getScore());
             }
             for (SubjectiveScore subjectiveScore : mainScoreList) {
                 subjectiveScore.setMainScore(mainScore);
@@ -898,7 +905,7 @@ public class MarkServiceImpl implements MarkService {
                         try {
                             ScoreItem item = detail.get(i);
                             ScoreItem other = scores.get(i);
-                            item.setScore(item.getScore() + other.getScore());
+                            item.setScore(BigDecimalUtils.add(item.getScore(), other.getScore()));
                         } catch (Exception e) {
                             continue;
                         }
@@ -1088,17 +1095,6 @@ public class MarkServiceImpl implements MarkService {
         }
     }
 
-    /**
-     * 领取正式评卷任务时,用来区分的唯一标识<br/>
-     * 多评时同一个考生的多份任务不能被同一位评卷员领取
-     *
-     * @param library
-     *            - 正评任务
-     */
-    private String getApplyTaskId(MarkLibrary library) {
-        return library.getStudentId() + "_" + library.getGroupNumber();
-    }
-
     /**
      * 领取试评评卷任务时,用来区分的唯一标识
      *
@@ -1109,6 +1105,14 @@ public class MarkServiceImpl implements MarkService {
         return library.getId() + "_" + marker.getId();
     }
 
+    private String getGroupKey(MarkGroup group) {
+        return group.getExamId() + "_" + group.getSubjectCode() + "_" + group.getNumber();
+    }
+
+    private String getGroupKey(Marker marker) {
+        return marker.getExamId() + "_" + marker.getSubjectCode() + "_" + marker.getGroupNumber();
+    }
+
     /**
      * 重置评卷分组的连带操作
      *

+ 5 - 16
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/mark/service/MarkService.java

@@ -1,10 +1,7 @@
 package cn.com.qmth.stmms.biz.mark.service;
 
 import cn.com.qmth.stmms.biz.exam.model.*;
-import cn.com.qmth.stmms.biz.mark.model.ArbitrateHistory;
-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.TrialLibrary;
+import cn.com.qmth.stmms.biz.mark.model.*;
 import cn.com.qmth.stmms.common.enums.ScorePolicy;
 import cn.com.qmth.stmms.common.enums.ThirdPolicy;
 
@@ -13,20 +10,12 @@ import java.util.List;
 public interface MarkService {
 
     /**
-     * 释放某个评卷员已领取的正评任务
+     * 释放某个评卷员已完成的评卷任务
      *
-     * @param library
-     * @param marker
-     */
-    void releaseLibrary(MarkLibrary library, Marker marker);
-
-    /**
-     * 释放某个评卷员已领取的试评任务
-     *
-     * @param library
+     * @param result
      * @param marker
      */
-    void releaseLibrary(TrialLibrary library, Marker marker);
+    void releaseTask(SubmitResult result, Marker marker);
 
     /**
      * /** 释放某个大题的锁定任务
@@ -198,7 +187,7 @@ public interface MarkService {
      * @param marker
      * @return
      */
-    boolean submitTask(MarkResult result, Marker marker);
+    SubmitResult submitTask(MarkResult result, Marker marker);
 
     /**
      * 管理员/组长重置某个试评任务

+ 0 - 52
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/utils/AbstractTask.java

@@ -1,52 +0,0 @@
-package cn.com.qmth.stmms.biz.utils;
-
-import java.util.Date;
-
-import org.apache.log4j.Logger;
-
-public abstract class AbstractTask implements Runnable {
-
-    protected static final Logger logger = Logger.getLogger(AbstractTask.class);
-
-    private Date start;
-
-    private Date finish;
-
-    private String status;
-
-    public AbstractTask() {
-        status("等待开始");
-    }
-
-    @Override
-    public void run() {
-        logger.info("运行中");
-        start = new Date();
-        status("运行中");
-
-        process();
-
-        status("任务结束");
-        finish = new Date();
-        logger.info("任务结束");
-    }
-
-    protected abstract void process();
-
-    protected void status(String status) {
-        this.status = status;
-    }
-
-    public Date getStart() {
-        return start;
-    }
-
-    public Date getFinish() {
-        return finish;
-    }
-
-    public String getStatus() {
-        return status;
-    }
-
-}

+ 0 - 34
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/utils/BlockTaskCountUtil.java

@@ -1,34 +0,0 @@
-package cn.com.qmth.stmms.biz.utils;
-
-import org.springframework.dao.DataAccessException;
-import org.springframework.data.redis.connection.RedisConnection;
-import org.springframework.data.redis.core.RedisCallback;
-import org.springframework.data.redis.core.StringRedisTemplate;
-
-import cn.com.qmth.stmms.common.redis.RedisKeyBuilder;
-
-public class BlockTaskCountUtil {
-
-    public static void incrBlockTotalCount(StringRedisTemplate redisTemplate, final int blockId) {
-        redisTemplate.execute(new RedisCallback<Long>() {
-
-            @Override
-            public Long doInRedis(RedisConnection conn) throws DataAccessException {
-                try {
-                    conn.incr(RedisKeyBuilder.getBlockTotalCountKey(blockId).getBytes("UTF-8"));
-                } catch (Exception e) {
-                }
-                return 0l;
-            }
-        });
-    }
-
-    public static void addBlockMarkedTask(StringRedisTemplate redisTemplate, final int blockId, final int libraryId) {
-        redisTemplate.opsForSet().add(RedisKeyBuilder.getBlockMarkedTaskKey(blockId), String.valueOf(libraryId));
-    }
-
-    public static int getBlockMarkedTaskCount(StringRedisTemplate redisTemplate, final int blockId) {
-        Long count = redisTemplate.opsForSet().size(RedisKeyBuilder.getBlockMarkedTaskKey(blockId));
-        return count != null ? count.intValue() : 0;
-    }
-}

+ 0 - 197
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/utils/CurrentTaskUtil2.java

@@ -1,197 +0,0 @@
-package cn.com.qmth.stmms.biz.utils;
-
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
-import java.util.concurrent.locks.Lock;
-import java.util.concurrent.locks.ReentrantLock;
-
-import cn.com.qmth.stmms.biz.exam.model.Marker;
-
-/**
- * Redis zset替代方案,单JVM内部针对已领取未给分任务的管理工具
- * 
- * @author luoshi
- * 
- */
-public class CurrentTaskUtil2 {
-
-    private static Map<String, TaskGroup> store = new HashMap<String, TaskGroup>();
-
-    /**
-     * 尝试领取某个任务
-     * 
-     * @param marker
-     * @param libraryId
-     * @return
-     */
-    public static boolean add(Marker marker, int libraryId) {
-        return getTaskMap(marker.getExamId(), marker.getSubjectCode()).add(libraryId, marker.getId());
-    }
-
-    /**
-     * 删除某个已完成的任务
-     * 
-     * @param marker
-     * @param libraryId
-     */
-    public static void remove(Marker marker, int libraryId) {
-        getTaskMap(marker.getExamId(), marker.getSubjectCode()).remove(libraryId);
-    }
-
-    /**
-     * 某个科目已领取未给分的任务总数
-     * 
-     * @param examId
-     * @param subjectCode
-     * @return
-     */
-    public static int count(int examId, String subjectCode) {
-        return getTaskMap(examId, subjectCode).count();
-    }
-
-    /**
-     * 某个评卷员已领取未给分的任务总数
-     * 
-     * @param marker
-     * @return
-     */
-    public static int count(Marker marker) {
-        return getTaskMap(marker.getExamId(), marker.getSubjectCode()).count(marker.getId());
-    }
-
-    /**
-     * 清除某个科目已领取未给分的任务
-     * 
-     * @param examId
-     * @param subjectCode
-     */
-    public static void clear(int examId, String subjectCode) {
-        getTaskMap(examId, subjectCode).clear();
-    }
-
-    /**
-     * 清除某个评卷员已领取未给分的任务
-     * 
-     * @param examId
-     * @param subjectCode
-     */
-    public static void clear(Marker marker) {
-        getTaskMap(marker.getExamId(), marker.getSubjectCode()).clear(marker.getId());
-    }
-
-    /**
-     * 获取某个科目的任务控制器
-     * 
-     * @param examId
-     * @param subjectCode
-     * @return
-     */
-    private static TaskGroup getTaskMap(int examId, String subjectCode) {
-        String key = examId + "_" + subjectCode;
-        TaskGroup group = store.get(key);
-        if (group == null) {
-            synchronized (CurrentTaskUtil2.class) {
-                group = store.get(key);
-                if (group == null) {
-                    group = new TaskGroup();
-                    store.put(key, group);
-                }
-            }
-        }
-        return group;
-    }
-}
-
-class TaskGroup {
-
-    // 任务-评卷员对应关系
-    private Map<Integer, Integer> taskStore;
-
-    // 评卷员-任务对应关系
-    private Map<Integer, Set<Integer>> markerStore;
-
-    private Lock lock;
-
-    public TaskGroup() {
-        this.taskStore = new HashMap<Integer, Integer>();
-        this.markerStore = new HashMap<Integer, Set<Integer>>();
-        this.lock = new ReentrantLock();
-    }
-
-    public boolean add(int libraryId, int markerId) {
-        if (taskStore.containsKey(libraryId)) {
-            return false;
-        }
-        lock.lock();
-        try {
-            if (taskStore.containsKey(libraryId)) {
-                return false;
-            }
-            taskStore.put(libraryId, markerId);
-            Set<Integer> set = markerStore.get(markerId);
-            if (set == null) {
-                set = new HashSet<Integer>();
-                markerStore.put(markerId, set);
-            }
-            set.add(libraryId);
-            return true;
-        } catch (Exception e) {
-            return false;
-        } finally {
-            lock.unlock();
-        }
-    }
-
-    public void remove(int libraryId) {
-        lock.lock();
-        try {
-            Integer markerId = taskStore.get(libraryId);
-            if (markerId != null) {
-                markerStore.get(markerId).remove(libraryId);
-            }
-            taskStore.remove(libraryId);
-        } catch (Exception e) {
-        } finally {
-            lock.unlock();
-        }
-    }
-
-    public int count() {
-        return taskStore.size();
-    }
-
-    public int count(int markerId) {
-        try {
-            return markerStore.get(markerId).size();
-        } catch (Exception e) {
-            return 0;
-        }
-    }
-
-    public void clear() {
-        lock.lock();
-        try {
-            taskStore.clear();
-            markerStore.clear();
-        } catch (Exception e) {
-        } finally {
-            lock.unlock();
-        }
-    }
-
-    public void clear(int markerId) {
-        lock.lock();
-        try {
-            Set<Integer> set = markerStore.get(markerId);
-            for (Integer id : set) {
-                taskStore.remove(id);
-            }
-            set.clear();
-        } catch (Exception e) {
-        } finally {
-            lock.unlock();
-        }
-    }
-}

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

@@ -0,0 +1,232 @@
+package cn.com.qmth.stmms.biz.utils;
+
+import cn.com.qmth.stmms.common.utils.DateUtils;
+
+import java.util.*;
+
+/**
+ * 链表模式实现的任务互斥锁工具
+ */
+public class TaskLock {
+
+    // 固定头节点
+    private LockNode head;
+
+    // 总量计数
+    private int count;
+
+    public TaskLock() {
+        head = new LockNode(0, 0, 0);
+        count = 0;
+    }
+
+    public synchronized boolean add(Object id, int number, Object owner) {
+        if (head.next == null) {
+            head.append(id, number, owner);
+            count++;
+            return true;
+        } else {
+            LockNode node = head.next;
+            while (true) {
+                // id+number,只能被一个owner获取
+                if (node.isId(id) && node.isNumber(number)) {
+                    return false;
+                }
+                // id只能被一个owner领取一个number
+                else if (node.isId(id) && node.isOwner(owner)) {
+                    return false;
+                }
+                // 跳到下一个node
+                else if (node.hasNext()) {
+                    node = node.next;
+                }
+                // 可以领取
+                else {
+                    node.append(id, number, owner);
+                    count++;
+                    return true;
+                }
+            }
+        }
+    }
+
+    public synchronized boolean exist(Object id, int number, Object owner) {
+        LockNode node = head.next;
+        while (node != null) {
+            if (node.isId(id) && node.isNumber(number)) {
+                return node.isOwner(owner);
+            } else {
+                node = node.next;
+            }
+        }
+        return false;
+    }
+
+    public synchronized boolean remove(Object id, int number, Object owner) {
+        LockNode node = head.next;
+        while (node != null) {
+            if (node.isId(id) && node.isNumber(number)) {
+                if (node.isOwner(owner)) {
+                    node.remove();
+                    count--;
+                    return true;
+                } else {
+                    return false;
+                }
+            } else {
+                node = node.next;
+            }
+        }
+        return false;
+    }
+
+    public synchronized void clear() {
+        head.next = null;
+        count = 0;
+    }
+
+    public synchronized void clear(Object owner) {
+        LockNode node = head.next;
+        while (node != null) {
+            if (node.isOwner(owner)) {
+                node.remove();
+                count--;
+            }
+            node = node.next;
+        }
+    }
+
+    public synchronized void expire(long expireTime) {
+        long current = System.currentTimeMillis();
+        LockNode node = head.next;
+        while (node != null) {
+            if ((current - node.time) > expireTime) {
+                node.remove();
+                count--;
+            }
+            node = node.next;
+        }
+    }
+
+    public synchronized boolean refresh(Object id, int number, Object owner) {
+        LockNode node = head.next;
+        while (node != null) {
+            if (node.isId(id) && node.isNumber(number) && node.isOwner(owner)) {
+                node.time = System.currentTimeMillis();
+                return true;
+            }
+            node = node.next;
+        }
+        return false;
+    }
+
+    public synchronized void refresh(Object owner) {
+        LockNode node = head.next;
+        while (node != null) {
+            if (node.isOwner(owner)) {
+                node.time = System.currentTimeMillis();
+            }
+            node = node.next;
+        }
+    }
+
+    public int count() {
+        return count;
+    }
+
+    public int count(Object owner) {
+        int count = 0;
+        LockNode node = head.next;
+        while (node != null) {
+            if (node.isOwner(owner)) {
+                count++;
+            }
+            node = node.next;
+        }
+        return count;
+    }
+
+    public List<Map<String, Object>> list() {
+        List<Map<String, Object>> list = new LinkedList<>();
+        LockNode node = head.next;
+        while (node != null) {
+            Map<String, Object> map = new HashMap<>();
+            map.put("taskId", node.getId());
+            map.put("number", node.getNumber());
+            map.put("markerId", node.getOwner());
+            map.put("time", DateUtils.formatDateTime(new Date(node.getTime())));
+            list.add(map);
+            node = node.next;
+        }
+        return list;
+    }
+
+    private static class LockNode {
+
+        private LockNode previous;
+
+        private LockNode next;
+
+        private Object id;
+
+        private int number;
+
+        private Object owner;
+
+        private long time;
+
+        LockNode(Object id, int number, Object owner) {
+            this.id = id;
+            this.number = number;
+            this.owner = owner;
+            this.time = System.currentTimeMillis();
+        }
+
+        private boolean hasNext() {
+            return this.next != null;
+        }
+
+        private boolean isId(Object id) {
+            return this.id.equals(id);
+        }
+
+        private boolean isNumber(int number) {
+            return this.number == number;
+        }
+
+        private boolean isOwner(Object owner) {
+            return this.owner.equals(owner);
+        }
+
+        private void remove() {
+            this.previous.next = this.next;
+            if (this.next != null) {
+                this.next.previous = this.previous;
+            }
+        }
+
+        private void append(Object id, int number, Object owner) {
+            LockNode node = new LockNode(id, number, owner);
+            this.next = node;
+            node.previous = this;
+        }
+
+        public Object getId() {
+            return id;
+        }
+
+        public int getNumber() {
+            return number;
+        }
+
+        public Object getOwner() {
+            return owner;
+        }
+
+        public long getTime() {
+            return time;
+        }
+
+    }
+
+}

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

@@ -0,0 +1,43 @@
+package cn.com.qmth.stmms.biz.utils;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class TaskLockUtil {
+
+    // 评卷任务并发处理互斥锁
+    private static final Map<String, TaskLock> formalTaskMap = new HashMap<>();
+
+    // 试评任务并发处理互斥锁
+    private static final Map<String, TaskLock> trialTaskMap = new HashMap<>();
+
+    public static void clearTimeoutTask(long timeoutMinute) {
+        for (TaskLock taskLock : trialTaskMap.values()) {
+            taskLock.expire(timeoutMinute);
+        }
+        for (TaskLock taskLock : formalTaskMap.values()) {
+            taskLock.expire(timeoutMinute);
+        }
+    }
+
+    public static TaskLock getTrialTask(String key) {
+        TaskLock taskLock = trialTaskMap.get(key);
+        if (taskLock == null) {
+            synchronized (trialTaskMap) {
+                taskLock = trialTaskMap.computeIfAbsent(key, k -> new TaskLock());
+            }
+        }
+        return taskLock;
+    }
+
+    public static TaskLock getFormalTask(String key) {
+        TaskLock taskLock = formalTaskMap.get(key);
+        if (taskLock == null) {
+            synchronized (formalTaskMap) {
+                taskLock = formalTaskMap.computeIfAbsent(key, k -> new TaskLock());
+            }
+        }
+        return taskLock;
+    }
+
+}

+ 0 - 206
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/utils/TrialTaskUtil.java

@@ -1,206 +0,0 @@
-package cn.com.qmth.stmms.biz.utils;
-
-import java.text.ParseException;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
-
-import com.google.common.collect.HashMultimap;
-import com.google.common.collect.Multiset;
-import com.google.common.collect.SetMultimap;
-
-import cn.com.qmth.stmms.biz.exam.model.Marker;
-
-/**
- * Redis zset替代方案,单JVM内部针对已领取未给分<strong>试评</strong>任务的内存锁
- * 
- * @author luoshi
- * 
- */
-public class TrialTaskUtil {
-
-    private static SetMultimap<String, TaskEntry> taskMap = HashMultimap.create();
-
-    /**
-     * 尝试领取某个任务
-     * 
-     * @param marker
-     * @param taskId
-     * @return
-     */
-    public static boolean add(Marker marker, String taskId) {
-        String key = getKey(marker);
-        TaskEntry obj = new TaskEntry(marker.getId(), taskId);
-
-        synchronized (TrialTaskUtil.class) {
-            if (taskMap.containsEntry(key, obj)) {
-                return false;
-            } else {
-                taskMap.put(key, obj);
-                return true;
-            }
-        }
-    }
-
-    /**
-     * 是否已领取某个任务
-     * 
-     * @param marker
-     * @param taskId
-     * @return
-     */
-    public static boolean exists(Marker marker, String taskId) {
-        String key = getKey(marker);
-        Set<TaskEntry> set = taskMap.get(key);
-        if (set != null) {
-            for (TaskEntry entry : set) {
-                if (entry.getTaskId().equals(taskId) && entry.getMarkerId() == marker.getId()) {
-                    return true;
-                }
-            }
-        }
-        return false;
-    }
-
-    /**
-     * 删除某个已完成的任务
-     * 
-     * @param marker
-     * @param taskId
-     */
-    public static void remove(Marker marker, String taskId) {
-        TaskEntry obj = new TaskEntry(marker.getId(), taskId);
-        synchronized (TrialTaskUtil.class) {
-            taskMap.remove(getKey(marker), obj);
-        }
-    }
-
-    /**
-     * 某个科目已领取未给分的任务总数
-     * 
-     * @param examId
-     * @param subjectCode
-     * @return
-     */
-    public static int count(int examId, String subjectCode, int number) {
-        Set<TaskEntry> set = taskMap.get(getKey(examId, subjectCode, number));
-        return set != null ? set.size() : 0;
-    }
-
-    /**
-     * 某个评卷员已领取未给分的任务总数
-     * 
-     * @param marker
-     * @return
-     */
-    public static int count(Marker marker) {
-        Set<TaskEntry> set = taskMap.get(getKey(marker));
-        int count = 0;
-        if (set != null) {
-            for (TaskEntry obj : set) {
-                if (obj.getMarkerId() == marker.getId()) {
-                    count++;
-                }
-            }
-        }
-        return count;
-    }
-
-    /**
-     * 清除某个科目已领取未给分的任务
-     * 
-     * @param examId
-     * @param subjectCode
-     */
-    public static void clear(int examId, String subjectCode, int number) {
-        synchronized (TrialTaskUtil.class) {
-            taskMap.removeAll(getKey(examId, subjectCode, number));
-        }
-    }
-
-    /**
-     * 清除某个评卷员已领取未给分的任务
-     * 
-     * @param marker
-     */
-    public static void clear(Marker marker) {
-        String key = getKey(marker);
-        Set<TaskEntry> set = new HashSet<TaskEntry>();
-        synchronized (TrialTaskUtil.class) {
-            set.addAll(taskMap.get(key));
-            for (TaskEntry obj : set) {
-                if (obj.getMarkerId() == marker.getId()) {
-                    taskMap.remove(key, obj);
-                }
-            }
-        }
-    }
-
-    /**
-     * 获取当前已领取的任务快照
-     * 
-     * @param examId
-     * @param subjectCode
-     * @param groupNumber
-     */
-    public static Set<TaskEntry> list(Integer examId, String subjectCode, Integer groupNumber) {
-        return taskMap.get(getKey(examId, subjectCode, groupNumber));
-    }
-
-    private static String getKey(int examId, String subjectCode, int number) {
-        return examId + "_" + subjectCode + "_" + number;
-    }
-
-    private static String getKey(Marker marker) {
-        return getKey(marker.getExamId(), marker.getSubjectCode(), marker.getGroupNumber());
-    }
-
-    public static void clearTimeoutTask(long timeoutMinute) {
-        synchronized (TrialTaskUtil.class) {
-            SetMultimap<String, TaskEntry> taskMap1 = HashMultimap.create();
-            // System.out.println("任务池大小:"+taskMap.size());
-            // System.out.println("间隔时间:"+cleanMapinterval);
-            if (taskMap.size() > 0) {
-                Multiset<String> keysTemp = taskMap.keys();
-                Set<String> setKey = new HashSet<String>();
-                for (String key : keysTemp) {
-                    setKey.add(key);
-                }
-                for (String key : setKey) {
-                    Set<TaskEntry> set = taskMap.get(key);
-                    if (set != null) {
-                        for (TaskEntry obj : set) {
-                            if (getDateDifference(obj.getTimestamp()) >= timeoutMinute) {// 如果相隔时间超过阀值,则该试卷的放入清空池中
-                                taskMap1.put(key, obj);
-                            }
-                        }
-                    }
-                }
-            }
-            for (Map.Entry<String, TaskEntry> taskEntry : taskMap1.entries()) {
-                taskMap.remove(taskEntry.getKey(), taskEntry.getValue());
-            }
-            taskMap1.clear();
-        }
-    }
-
-    /**
-     * 获取当前时间戳
-     * 
-     * @return
-     * @throws ParseException
-     */
-    public static Long getDateString() {
-        return System.currentTimeMillis();
-    }
-
-    /**
-     * 时间戳相隔分钟
-     * 
-     * @return
-     * @throws ParseException
-     */
-    public static Long getDateDifference(Long oldTime) {
-        return (getDateString() - oldTime) / (1000 * 60);
-    }
-}

+ 2 - 2
stmms-web/src/main/java/cn/com/qmth/stmms/admin/dto/SubjectiveQuestionDTO.java

@@ -73,7 +73,7 @@ public class SubjectiveQuestionDTO implements QuestionDTO {
                 : 0d);
         setScorePolicy(group != null && group.getScorePolicy() != null ? group.getScorePolicy().getValue()
                 : ScorePolicy.AVG.getValue());
-        setMarkMode(group != null && group.getMarkMode() != null ? group.getMarkMode().getName() : "");
+        setMarkMode(group != null && group.getMarkMode() != null ? group.getMarkMode().toString() : "");
         setTrialCount(group != null && group.getTrialCount() != null ? group.getTrialCount() : 0);
     }
 
@@ -87,7 +87,7 @@ public class SubjectiveQuestionDTO implements QuestionDTO {
         question.setGroupNumber(groupNumber);
         question.setObjective(false);
         question.setTotalScore(totalScore);
-        question.setIntervalScore(intervalScore != null && intervalScore > 0 ? intervalScore : 1d);
+        question.setIntervalScore(intervalScore != null && intervalScore >= 0.1 ? intervalScore : 1d);
         question.setPicList(picList);
         question.setDoubleRate(doubleRate);
         question.setArbitrateThreshold(arbitrateThreshold);

+ 2 - 1
stmms-web/src/main/java/cn/com/qmth/stmms/admin/exam/ImportQueryController.java

@@ -3,6 +3,7 @@ package cn.com.qmth.stmms.admin.exam;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.HashSet;
+import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
@@ -139,7 +140,7 @@ public class ImportQueryController extends BaseExamController {
         try {
             int successNum = 0;
             int failureNum = 0;
-            Set<Integer> successStudent = new HashSet<Integer>();
+            Set<Integer> successStudent = new LinkedHashSet<Integer>();
             Set<String> failureStudent = new HashSet<String>();
             ImportExcel ei = new ImportExcel(file, 1, 0);
             List<InspectedStudentVO> list = ei.getDataList(InspectedStudentVO.class);

+ 16 - 57
stmms-web/src/main/java/cn/com/qmth/stmms/admin/exam/InspectedController.java

@@ -33,10 +33,10 @@ 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.query.SubjectiveScoreSearchQuery;
 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;
@@ -63,6 +63,9 @@ public class InspectedController extends BaseExamController {
     @Autowired
     private ExamStudentService studentService;
 
+    @Autowired
+    private InspectedService inspectedService;
+
     @Autowired
     private ExamQuestionService questionService;
 
@@ -105,36 +108,18 @@ public class InspectedController extends BaseExamController {
         }
         WebUser wu = RequestUtils.getWebUser(request);
         query.setExamId(examId);
-        query.setUpload(true);
-        query.setAbsent(false);
-        query.setBreach(false);
         List<ExamSubject> subjectList = getExamSubject(examId, wu);
         if (StringUtils.isBlank(query.getSubjectCode()) && !subjectList.isEmpty()) {
             query.setSubjectCode(subjectList.get(0).getCode());
         }
-        if (status != null) {
-            query.addStatus(status);
-        } else {
-            query.addStatus(SubjectiveStatus.INSPECTED);
-            query.addStatus(SubjectiveStatus.MARKED);
-        }
-        if (mainStartScore != null || mainEndScore != null || questionScore != null) {
-            SubjectiveScoreSearchQuery query2 = new SubjectiveScoreSearchQuery();
-            query2.setExamId(examId);
-            query2.setSubjectCode(query.getSubjectCode());
-            query2.setMainNumber(mainNumber);
-            query2.setMainStartScore(mainStartScore);
-            query2.setMainEndScore(mainEndScore);
-            query2.setScore(questionScore);
-            query2.setPageSize(Integer.MAX_VALUE);
-            List<Integer> studentIds = scoreService.findStudentIdByQuery(query2);
-            query.setStudentIds(studentIds);
-        }
-        if (query.getStudentIds() == null || query.getStudentIds().size() != 0) {
-            query = studentService.findByQuery(query);
-        }
+        List<ExamStudent> list = inspectedService.findByQuery(query, status, mainNumber, mainStartScore, mainEndScore,
+                questionScore);
+        Integer count = inspectedService.countByQuery(query, status, mainNumber, mainStartScore, mainEndScore,
+                questionScore);
+        query.setResult(list);
+        query.setTotalCount(count);
         model.addAttribute("query", query);
-        model.addAttribute("inspectCount", query.getTotalCount());
+        model.addAttribute("inspectCount", count);
         model.addAttribute("questionList",
                 questionService.findMainByExamAndSubjectAndObjective(examId, query.getSubjectCode(), false));
         model.addAttribute("mainNumber", mainNumber);
@@ -160,34 +145,17 @@ public class InspectedController extends BaseExamController {
         releaseByUser(wu.getUser().getId());
         ModelAndView view = new ModelAndView("modules/exam/inspected");
         query.setExamId(examId);
-        query.setUpload(true);
-        query.setAbsent(false);
-        query.setBreach(false);
-        query.addStatus(SubjectiveStatus.MARKED);
         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());
         }
-        if (mainNumber != null || mainStartScore != null || mainEndScore != null || questionScore != null) {
-            SubjectiveScoreSearchQuery query2 = new SubjectiveScoreSearchQuery();
-            query2.setExamId(examId);
-            query2.setSubjectCode(query.getSubjectCode());
-            query2.setMainNumber(mainNumber);
-            query2.setMainStartScore(mainStartScore);
-            query2.setMainEndScore(mainEndScore);
-            query2.setScore(questionScore);
-            query2.setPageSize(Integer.MAX_VALUE);
-            List<Integer> studentIds = scoreService.findStudentIdByQuery(query2);
-            query.setStudentIds(studentIds);
-        }
-        if (query.getStudentIds() == null || query.getStudentIds().size() != 0) {
-            query = studentService.findByQuery(query);
-        }
+        List<ExamStudent> list = inspectedService.findByQuery(query, SubjectiveStatus.MARKED, mainNumber,
+                mainStartScore, mainEndScore, questionScore);
         List<Integer> ids = new ArrayList<Integer>();
-        if (query.getResult() != null && query.getResult().size() > 0) {
-            for (ExamStudent student : query.getResult()) {
+        if (!list.isEmpty()) {
+            for (ExamStudent student : list) {
                 ids.add(student.getId());
             }
         }
@@ -208,6 +176,7 @@ public class InspectedController extends BaseExamController {
         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());
@@ -261,19 +230,9 @@ public class InspectedController extends BaseExamController {
                 groupArray.add(group);
             }
             result.accumulate("groups", groupArray);
-            // 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);

+ 7 - 8
stmms-web/src/main/java/cn/com/qmth/stmms/mark/MarkController.java

@@ -447,19 +447,18 @@ public class MarkController extends BaseController {
         try {
             lockService.watch(LockType.EXAM_SUBJECT, marker.getExamId(), marker.getSubjectCode());
             lockService.watch(LockType.GROUP, marker.getExamId(), marker.getSubjectCode(), marker.getGroupNumber());
-            lockService.watch(LockType.STUDENT, markResult.getStudentId());
             lockService.watch(LockType.MARKER, marker.getId());
-            lockService.waitlock(LockType.GROUP_LIBRARY, markResult.getStudentId(), marker.getExamId(),
-                    marker.getSubjectCode(), marker.getGroupNumber());
-            success = markService.submitTask(markResult, marker);
+            lockService.waitlock(LockType.STUDENT, markResult.getStudentId());
+            SubmitResult sr = markService.submitTask(markResult, marker);
+            if (sr.isSuccess()) {
+                markService.releaseTask(sr, marker);
+                success = true;
+            }
         } catch (Exception e) {
-            success = false;
             log.error("save task error", e);
         } finally {
-            lockService.unlock(LockType.GROUP_LIBRARY, markResult.getStudentId(), marker.getExamId(),
-                    marker.getSubjectCode(), marker.getGroupNumber());
+            lockService.unlock(LockType.STUDENT, markResult.getStudentId());
             lockService.unwatch(LockType.MARKER, marker.getId());
-            lockService.unwatch(LockType.STUDENT, markResult.getStudentId());
             lockService.unwatch(LockType.GROUP, marker.getExamId(), marker.getSubjectCode(), marker.getGroupNumber());
             lockService.unwatch(LockType.EXAM_SUBJECT, marker.getExamId(), marker.getSubjectCode());
         }

+ 4 - 18
stmms-web/src/main/java/cn/com/qmth/stmms/monitor/TaskMonitorController.java

@@ -1,8 +1,5 @@
 package cn.com.qmth.stmms.monitor;
 
-import java.util.Date;
-import java.util.Set;
-
 import javax.servlet.http.HttpServletRequest;
 
 import org.springframework.stereotype.Controller;
@@ -10,11 +7,8 @@ import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RequestParam;
 import org.springframework.web.bind.annotation.ResponseBody;
 
-import cn.com.qmth.stmms.biz.utils.FormalTaskUtil;
-import cn.com.qmth.stmms.biz.utils.TaskEntry;
-import cn.com.qmth.stmms.common.utils.DateUtils;
-import net.sf.json.JSONArray;
-import net.sf.json.JSONObject;
+import cn.com.qmth.stmms.biz.utils.TaskLock;
+import cn.com.qmth.stmms.biz.utils.TaskLockUtil;
 
 @Controller("taskMonitor")
 @RequestMapping("/monitor/task")
@@ -24,16 +18,8 @@ public class TaskMonitorController {
     @ResponseBody
     public Object list(HttpServletRequest request, @RequestParam Integer examId, @RequestParam String subjectCode,
             @RequestParam Integer groupNumber) {
-        Set<TaskEntry> set = FormalTaskUtil.list(examId, subjectCode, groupNumber);
-        JSONArray array = new JSONArray();
-        for (TaskEntry entry : set) {
-            JSONObject obj = new JSONObject();
-            obj.accumulate("taskId", entry.getTaskId());
-            obj.accumulate("markerId", entry.getMarkerId());
-            obj.accumulate("time", DateUtils.formatDateTime(new Date(entry.getTimestamp())));
-            array.add(obj);
-        }
-        return array;
+        TaskLock taskLock = TaskLockUtil.getFormalTask(examId + "_" + subjectCode + "_" + groupNumber);
+        return taskLock.list();
     }
 
 }

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

@@ -130,7 +130,7 @@
                 <div class="controls">
                     <input name="picList" id="picList" type="hidden"/>
                     <a href="${ctx}/admin/exam/getSheetConfig?examId=${exam.id}" target="_blank" class="required"
-                       id="configuration">设置</a>
+                       id="configuration" rel="opener">设置</a>
                 </div>
             </div>
         </c:if>

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

@@ -98,7 +98,7 @@
             <label class="control-label">图片显示</label>
             <div class="controls">
                 <a href="${ctx}/admin/exam/group/getPictureConfig?subjectCode=${group.subjectCode}&number=${group.number}"
-                   target="_blank" id="configuration">设置</a>
+                   target="_blank" id="configuration" rel="opener">设置</a>
             </div>
         </div>
     </c:if>

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

@@ -120,7 +120,7 @@
             <label class="control-label">图片显示</label>
             <div class="controls">
                 <a href="${ctx}/admin/exam/group/getPictureConfig?subjectCode=${group.subjectCode}&number=${group.number}"
-                   target="_blank" class="required" id="configuration">设置</a>
+                   target="_blank" class="required" id="configuration" rel="opener">设置</a>
             </div>
         </div>
     </c:if>

+ 3 - 3
stmms-web/src/main/webapp/WEB-INF/views/modules/exam/groupEditSimple.jsp

@@ -98,7 +98,7 @@
             <label class="control-label">图片显示</label>
             <div class="controls">
                 <a href="${ctx}/admin/exam/group/getPictureConfig?subjectCode=${group.subjectCode}&number=${group.number}"
-                   target="_blank" class="required" id="configuration">设置</a>
+                   target="_blank" class="required" id="configuration" rel="opener">设置</a>
             </div>
         </div>
     </c:if>
@@ -158,7 +158,7 @@
         var fill = true;
         $('.interval-score-input').each(function () {
             var score = $(this).val();
-            if (score == '') {
+            if (score == '' || score<0.1) {
                 fill = false;
             } else {
                 array.push(score);
@@ -168,7 +168,7 @@
             $('#intervalScoreList').val(array.join(','));
             $('#inputForm').submit();
         } else {
-            alert('间隔分不能为空');
+            alert('间隔分不能为空且大于等于0.1分');
         }
     });
 </script>

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

@@ -43,7 +43,7 @@
             <label class="control-label">原图遮盖</label>
             <div class="controls">
                 <input name="picList" id="picList"  type="hidden"/>
-                <a href="${ctx}/admin/exam/getSheetConfig?examId=${subject.examId}&subjectCode=${subject.code}" target="_blank" class="required" id= "configuration">设置</a>
+                <a href="${ctx}/admin/exam/getSheetConfig?examId=${subject.examId}&subjectCode=${subject.code}" target="_blank" class="required" id= "configuration" rel="opener">设置</a>
             </div>
         </div>
 		<div class="form-actions">

+ 1 - 1
stmms-web/src/main/webapp/WEB-INF/views/modules/mark/markNew.jsp

@@ -41,7 +41,7 @@
     <script type="text/javascript" src="${ctxStatic}/mark-new/js/modules/problem-process.js"></script>
     <script type="text/javascript" src="${ctxStatic}/mark-new/js/modules/switch-group.js"></script>
 </head>
-<body>
+<body ondragstart="return false;" ondrop="return false;">
 <div class="container-fluid" id="container"></div>
 <script type="text/javascript">
     $(document).ajaxError(function (evt, req, settings) {

+ 1 - 1
stmms-web/src/main/webapp/WEB-INF/views/modules/mark/markTrack.jsp

@@ -34,7 +34,7 @@
     <script type="text/javascript" src="${ctxStatic}/mark-new/js/modules/problem-process.js"></script>
     <script type="text/javascript" src="${ctxStatic}/mark-new/js/modules/switch-group.js"></script>
 </head>
-<body>
+<body ondragstart="return false;" ondrop="return false;">
 <div class="container-fluid" id="container"></div>
 <script type="text/javascript">
     $(document).ajaxError(function (evt, req, settings) {

+ 4 - 0
stmms-web/src/main/webapp/static/mark-track/js/mark-control.js

@@ -708,6 +708,10 @@ function numberAdd(n1, n2) {
     return (n1 * 10 + n2 * 10) / 10;
 }
 
+function numberMinus(n1, n2) {
+    return (n1 * 10 - n2 * 10) / 10;
+}
+
 function getDom(content, markControl) {
     if (markControl != undefined && markControl.option.staticServer != undefined) {
         content = content.replace(/{staticServer}/g, markControl.option.staticServer);

+ 3 - 3
stmms-web/src/main/webapp/static/mark-track/js/modules/mark-board.js

@@ -402,9 +402,9 @@ MarkBoard.prototype.updateStepScore = function (step) {
         if (totalScore == undefined) {
             totalScore = 0;
         }
-        totalScore += parseFloat(step.trackList[i].score);
+        totalScore = numberAdd(totalScore,step.trackList[i].score);
     }
-    var leftScore = totalScore != undefined ? (step.max - totalScore) : step.max;
+    var leftScore = totalScore != undefined ? numberMinus(step.max , totalScore) : step.max;
     for (var i = 0; i < step.scoreArray.length; i++) {
         var dom = step.scoreArray[i];
         dom.removeClass('selected');
@@ -438,7 +438,7 @@ MarkBoard.prototype.updateTotalScore = function () {
                 if (totalScore == '') {
                     totalScore = 0;
                 }
-                totalScore += this.stepList[i].markScore;
+                totalScore = numberAdd(totalScore,this.stepList[i].markScore);
             } else {
                 finish = false;
             }