瀏覽代碼

删除旧复核相关;改造客观题统分及分析计算

ting.yin 4 年之前
父節點
當前提交
ad6b6c787b
共有 27 個文件被更改,包括 679 次插入393 次删除
  1. 12 5
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/dao/ExamDao.java
  2. 32 8
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/model/Exam.java
  3. 12 0
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/model/ExamSubject.java
  4. 3 0
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/service/ExamService.java
  5. 6 0
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/service/impl/ExamServiceImpl.java
  6. 2 2
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/service/impl/MarkerServiceImpl.java
  7. 177 142
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/mark/service/Impl/MarkServiceImpl.java
  8. 1 2
      stmms-common/src/main/java/cn/com/qmth/stmms/common/enums/LibraryStatus.java
  9. 31 0
      stmms-common/src/main/java/cn/com/qmth/stmms/common/enums/ObjectiveStatus.java
  10. 2 0
      stmms-web/src/main/java/cn/com/qmth/stmms/admin/exam/ExamController.java
  11. 7 8
      stmms-web/src/main/java/cn/com/qmth/stmms/admin/exam/InspectedController.java
  12. 0 66
      stmms-web/src/main/java/cn/com/qmth/stmms/admin/exam/MarkController.java
  13. 3 6
      stmms-web/src/main/java/cn/com/qmth/stmms/admin/exam/MarkQualityController.java
  14. 131 28
      stmms-web/src/main/java/cn/com/qmth/stmms/admin/exam/PaperController.java
  15. 18 10
      stmms-web/src/main/java/cn/com/qmth/stmms/admin/exam/SubjectController.java
  16. 52 82
      stmms-web/src/main/java/cn/com/qmth/stmms/admin/thread/ScoreCalculateThread.java
  17. 160 0
      stmms-web/src/main/java/cn/com/qmth/stmms/admin/thread/ScoreReportThread.java
  18. 0 10
      stmms-web/src/main/java/cn/com/qmth/stmms/admin/vo/SubjectLibraryVO.java
  19. 0 2
      stmms-web/src/main/java/cn/com/qmth/stmms/mark/MarkController.java
  20. 3 1
      stmms-web/src/main/webapp/WEB-INF/views/modules/exam/examIndex.jsp
  21. 0 14
      stmms-web/src/main/webapp/WEB-INF/views/modules/exam/markInfo.jsp
  22. 19 3
      stmms-web/src/main/webapp/WEB-INF/views/modules/exam/paperList.jsp
  23. 1 1
      stmms-web/src/main/webapp/WEB-INF/views/modules/report/reportSubject.jsp
  24. 2 1
      stmms-web/src/main/webapp/static/i18n/messages.properties
  25. 1 0
      stmms-web/src/main/webapp/static/i18n/messages_en.properties
  26. 2 1
      stmms-web/src/main/webapp/static/i18n/messages_ja.properties
  27. 2 1
      stmms-web/src/main/webapp/static/i18n/messages_zh.properties

+ 12 - 5
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/dao/ExamDao.java

@@ -1,8 +1,8 @@
 package cn.com.qmth.stmms.biz.exam.dao;
 
-import cn.com.qmth.stmms.biz.exam.model.Exam;
-import cn.com.qmth.stmms.common.enums.ExamStatus;
-import cn.com.qmth.stmms.common.enums.ExamType;
+import java.util.Date;
+import java.util.List;
+
 import org.springframework.data.domain.Page;
 import org.springframework.data.domain.Pageable;
 import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
@@ -10,8 +10,10 @@ import org.springframework.data.jpa.repository.Modifying;
 import org.springframework.data.jpa.repository.Query;
 import org.springframework.data.repository.PagingAndSortingRepository;
 
-import java.util.Date;
-import java.util.List;
+import cn.com.qmth.stmms.biz.exam.model.Exam;
+import cn.com.qmth.stmms.common.enums.ExamStatus;
+import cn.com.qmth.stmms.common.enums.ExamType;
+import cn.com.qmth.stmms.common.enums.ObjectiveStatus;
 
 public interface ExamDao extends PagingAndSortingRepository<Exam, Integer>, JpaSpecificationExecutor<Exam> {
 
@@ -43,4 +45,9 @@ public interface ExamDao extends PagingAndSortingRepository<Exam, Integer>, JpaS
     @Query(value = "select * from eb_exam e where e.id in (select s.exam_id from eb_exam_subject s where s.code in (select su.subject_code from eb_subject_user su where su.user_id=?1) )"
             + "order by e.id", nativeQuery = true)
     public List<Exam> findBySubjectHeaderUserId(Integer userId);
+
+    @Modifying
+    @Query("update Exam e set e.objectiveStatus=?2 where e.id=?1")
+    public int updateObjectiveStatus(int examId, ObjectiveStatus status);
+
 }

+ 32 - 8
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/model/Exam.java

@@ -1,19 +1,28 @@
 package cn.com.qmth.stmms.biz.exam.model;
 
-import cn.com.qmth.stmms.biz.file.enums.FormatType;
-import cn.com.qmth.stmms.biz.mark.model.PictureConfigItem;
-import cn.com.qmth.stmms.common.enums.ExamStatus;
-import cn.com.qmth.stmms.common.enums.ExamType;
+import java.io.Serializable;
+import java.util.Date;
+import java.util.List;
 
-import javax.persistence.*;
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.EnumType;
+import javax.persistence.Enumerated;
+import javax.persistence.GeneratedValue;
+import javax.persistence.Id;
+import javax.persistence.Table;
+import javax.persistence.Temporal;
+import javax.persistence.TemporalType;
 
 import net.sf.json.JSONObject;
 
 import org.apache.commons.lang3.StringUtils;
 
-import java.io.Serializable;
-import java.util.Date;
-import java.util.List;
+import cn.com.qmth.stmms.biz.file.enums.FormatType;
+import cn.com.qmth.stmms.biz.mark.model.PictureConfigItem;
+import cn.com.qmth.stmms.common.enums.ExamStatus;
+import cn.com.qmth.stmms.common.enums.ExamType;
+import cn.com.qmth.stmms.common.enums.ObjectiveStatus;
 
 @Entity
 @Table(name = "eb_exam")
@@ -100,6 +109,13 @@ public class Exam implements Serializable {
     @Column(name = "forbidden_info", nullable = false)
     private boolean forbiddenInfo;
 
+    /**
+     * 客观题统分状态
+     */
+    @Enumerated(EnumType.STRING)
+    @Column(name = "objective_status", length = 16, nullable = false)
+    private ObjectiveStatus objectiveStatus;
+
     public Integer getId() {
         return id;
     }
@@ -264,4 +280,12 @@ public class Exam implements Serializable {
         this.forbiddenInfo = forbiddenInfo;
     }
 
+    public ObjectiveStatus getObjectiveStatus() {
+        return objectiveStatus;
+    }
+
+    public void setObjectiveStatus(ObjectiveStatus objectiveStatus) {
+        this.objectiveStatus = objectiveStatus;
+    }
+
 }

+ 12 - 0
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/model/ExamSubject.java

@@ -97,6 +97,9 @@ public class ExamSubject implements Serializable {
     @Transient
     private String answerUrl;
 
+    @Transient
+    private boolean locked;
+
     public ExamSubject() {
         this.pk = new ExamSubjectPK();
     }
@@ -306,4 +309,13 @@ public class ExamSubject implements Serializable {
         }
         return null;
     }
+
+    public boolean isLocked() {
+        return locked;
+    }
+
+    public void setLocked(boolean locked) {
+        this.locked = locked;
+    }
+
 }

+ 3 - 0
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/service/ExamService.java

@@ -7,6 +7,7 @@ import cn.com.qmth.stmms.biz.exam.model.Exam;
 import cn.com.qmth.stmms.biz.exam.query.ExamSearchQuery;
 import cn.com.qmth.stmms.biz.mark.model.PictureConfigItem;
 import cn.com.qmth.stmms.common.enums.ExamType;
+import cn.com.qmth.stmms.common.enums.ObjectiveStatus;
 
 public interface ExamService {
 
@@ -28,4 +29,6 @@ public interface ExamService {
 
     List<Exam> findBySubjectHeaderUserId(Integer userId);
 
+    int updateObjectiveStatus(int examId, ObjectiveStatus calculate);
+
 }

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

@@ -10,6 +10,7 @@ import cn.com.qmth.stmms.biz.mark.model.ProblemType;
 import cn.com.qmth.stmms.biz.mark.service.ProblemTypeService;
 import cn.com.qmth.stmms.common.enums.ExamStatus;
 import cn.com.qmth.stmms.common.enums.ExamType;
+import cn.com.qmth.stmms.common.enums.ObjectiveStatus;
 
 import org.apache.commons.lang.StringUtils;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -133,4 +134,9 @@ public class ExamServiceImpl extends BaseQueryService<Exam> implements ExamServi
         return examDao.findBySubjectHeaderUserId(userId);
     }
 
+    @Override
+    public int updateObjectiveStatus(int examId, ObjectiveStatus status) {
+        return examDao.updateObjectiveStatus(examId, status);
+    }
+
 }

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

@@ -164,7 +164,7 @@ public class MarkerServiceImpl extends BaseQueryService<Marker> implements Marke
     @Override
     public List<Marker> getMarkCount(int examId) {
         List<Marker> list = new LinkedList<Marker>();
-        List<Object[]> result = libraryDao.countMarkerAndStatus(examId, LibraryStatus.MARKED, LibraryStatus.INSPECTED);
+        List<Object[]> result = libraryDao.countMarkerAndStatus(examId, LibraryStatus.MARKED);
         if (result != null) {
             for (Object[] array : result) {
                 try {
@@ -182,7 +182,7 @@ public class MarkerServiceImpl extends BaseQueryService<Marker> implements Marke
     public List<Marker> getMarkCount(int examId, Set<String> subjectCodes) {
         List<Marker> list = new LinkedList<Marker>();
         List<Object[]> result = libraryDao.countMarkerAndStatusAndSubjectCodeIn(examId, subjectCodes,
-                LibraryStatus.MARKED, LibraryStatus.INSPECTED);
+                LibraryStatus.MARKED);
         if (result != null) {
             for (Object[] array : result) {
                 try {

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

@@ -93,7 +93,8 @@ public class MarkServiceImpl implements MarkService {
     /**
      * 某个评卷分组已申请的评卷任务数量
      *
-     * @param group - 评卷分组
+     * @param group
+     *            - 评卷分组
      * @return int
      */
     @Override
@@ -110,7 +111,8 @@ public class MarkServiceImpl implements MarkService {
     /**
      * 某个评卷员已申请的评卷任务数量
      *
-     * @param marker - 评卷员
+     * @param marker
+     *            - 评卷员
      * @return int
      */
     @Override
@@ -132,7 +134,8 @@ public class MarkServiceImpl implements MarkService {
     /**
      * 某个评卷员已完成的评卷任务数量
      *
-     * @param marker - 评卷员
+     * @param marker
+     *            - 评卷员
      * @return long
      */
     @Override
@@ -145,8 +148,8 @@ public class MarkServiceImpl implements MarkService {
             if (group.getStatus() == MarkStatus.TRIAL) {
                 return trialHistoryDao.countByMarkerId(marker.getId());
             } else {
-                return libraryDao.countByMarkerAndStatus(marker.getId(), LibraryStatus.MARKED, LibraryStatus.ARBITRATED,
-                        LibraryStatus.INSPECTED);
+                return libraryDao
+                        .countByMarkerAndStatus(marker.getId(), LibraryStatus.MARKED, LibraryStatus.ARBITRATED);
             }
         }
         return 0;
@@ -155,7 +158,8 @@ public class MarkServiceImpl implements MarkService {
     /**
      * 释放某个评卷分组的锁定任务
      *
-     * @param group - 评卷分组
+     * @param group
+     *            - 评卷分组
      */
     @Override
     public void releaseByGroup(MarkGroup group) {
@@ -169,7 +173,8 @@ public class MarkServiceImpl implements MarkService {
     /**
      * 重置某个评卷分组的所有评卷任务
      *
-     * @param group - 评卷分组
+     * @param group
+     *            - 评卷分组
      */
     @Override
     @Transactional
@@ -180,7 +185,8 @@ public class MarkServiceImpl implements MarkService {
     /**
      * 删除某个评卷分组
      *
-     * @param group - 评卷分组
+     * @param group
+     *            - 评卷分组
      */
     @Override
     @Transactional
@@ -222,9 +228,8 @@ public class MarkServiceImpl implements MarkService {
                 sumTotalScore(group.getExamId(), group.getSubjectCode()));
         // 考生整体状态与总分更新
         long groupCount = groupDao.countByExamIdAndSubjectCode(group.getExamId(), group.getSubjectCode());
-        List<Integer> studentList = studentService
-                .findIdByExamIdAndSubjectCodeAndSubjectiveStatus(group.getExamId(), group.getSubjectCode(),
-                        SubjectiveStatus.MARKED, SubjectiveStatus.INSPECTED);
+        List<Integer> studentList = studentService.findIdByExamIdAndSubjectCodeAndSubjectiveStatus(group.getExamId(),
+                group.getSubjectCode(), SubjectiveStatus.MARKED, SubjectiveStatus.INSPECTED);
         for (Integer studentId : studentList) {
             checkStudentSubjective(studentId, groupCount);
         }
@@ -233,7 +238,8 @@ public class MarkServiceImpl implements MarkService {
     /**
      * 修改某个评卷分组给分步骤,并重置评卷任务
      *
-     * @param group - 评卷分组
+     * @param group
+     *            - 评卷分组
      */
     @Override
     @Transactional
@@ -257,8 +263,10 @@ public class MarkServiceImpl implements MarkService {
     /**
      * 评卷员申请领取某个正式评卷任务
      *
-     * @param library - 正评任务
-     * @param marker  - 评卷员
+     * @param library
+     *            - 正评任务
+     * @param marker
+     *            - 评卷员
      */
     @Override
     public boolean applyLibrary(MarkLibrary library, Marker marker) {
@@ -274,8 +282,10 @@ public class MarkServiceImpl implements MarkService {
     /**
      * 评卷员申请领取某个试评评卷任务
      *
-     * @param library - 试评任务
-     * @param marker  - 评卷员
+     * @param library
+     *            - 试评任务
+     * @param marker
+     *            - 评卷员
      * @return boolean
      */
     @Override
@@ -286,8 +296,10 @@ public class MarkServiceImpl implements MarkService {
     /**
      * 评卷员是否已领取了某个正式评卷任务
      *
-     * @param library - 正评任务
-     * @param marker  - 评卷员
+     * @param library
+     *            - 正评任务
+     * @param marker
+     *            - 评卷员
      * @return boolean
      */
     @Override
@@ -298,8 +310,10 @@ public class MarkServiceImpl implements MarkService {
     /**
      * 评卷员是否已领取了某个试评评卷任务
      *
-     * @param library - 试评任务
-     * @param marker  - 评卷员
+     * @param library
+     *            - 试评任务
+     * @param marker
+     *            - 评卷员
      * @return boolean
      */
     @Override
@@ -310,8 +324,10 @@ public class MarkServiceImpl implements MarkService {
     /**
      * 释放某个评卷员已领取的正评任务
      *
-     * @param library - 正评任务
-     * @param marker  - 评卷员
+     * @param library
+     *            - 正评任务
+     * @param marker
+     *            - 评卷员
      */
     @Override
     public void releaseLibrary(MarkLibrary library, Marker marker) {
@@ -321,8 +337,10 @@ public class MarkServiceImpl implements MarkService {
     /**
      * 释放某个评卷员已领取的试评任务
      *
-     * @param library - 试评任务
-     * @param marker  - 评卷员
+     * @param library
+     *            - 试评任务
+     * @param marker
+     *            - 评卷员
      */
     @Override
     public void releaseLibrary(TrialLibrary library, Marker marker) {
@@ -332,7 +350,8 @@ public class MarkServiceImpl implements MarkService {
     /**
      * 释放某个评卷员的所有锁定任务
      *
-     * @param marker - 评卷员
+     * @param marker
+     *            - 评卷员
      */
     @Override
     public void releaseByMarker(Marker marker) {
@@ -343,7 +362,8 @@ public class MarkServiceImpl implements MarkService {
     /**
      * 重置某个评卷员
      *
-     * @param marker - 评卷员
+     * @param marker
+     *            - 评卷员
      */
     @Override
     @Transactional
@@ -361,9 +381,8 @@ public class MarkServiceImpl implements MarkService {
             libraryDao.resetByMarkerId(marker.getId(), LibraryStatus.WAITING, LibraryStatus.ARBITRATED,
                     LibraryStatus.WAIT_ARBITRATE, LibraryStatus.PROBLEM);
             // 只选取评卷完成状态的记录重新检查
-            List<Integer> studentIdList = groupStudentDao
-                    .findStudentIdByGroupNumberAndStatus(marker.getExamId(), marker.getSubjectCode(),
-                            marker.getGroupNumber(), SubjectiveStatus.MARKED);
+            List<Integer> studentIdList = groupStudentDao.findStudentIdByGroupNumberAndStatus(marker.getExamId(),
+                    marker.getSubjectCode(), marker.getGroupNumber(), SubjectiveStatus.MARKED);
             for (Integer studentId : studentIdList) {
                 checkStudentGroup(studentId, group);
             }
@@ -380,7 +399,8 @@ public class MarkServiceImpl implements MarkService {
     /**
      * 根据考生删除评卷任务
      *
-     * @param student - 考生
+     * @param student
+     *            - 考生
      */
     @Override
     @Transactional
@@ -396,7 +416,7 @@ public class MarkServiceImpl implements MarkService {
         trialTagDao.deleteByStudentId(student.getId());
         trialHistoryDao.deleteByStudentId(student.getId());
         trialLibraryDao.deleteByStudentId(student.getId());
-        //主观状态与得分明细
+        // 主观状态与得分明细
         groupStudentDao.deleteByStudentId(student.getId());
         scoreDao.deleteByStudentId(student.getId());
         updateAllCount(student.getExamId(), student.getSubjectCode());
@@ -405,8 +425,10 @@ public class MarkServiceImpl implements MarkService {
     /**
      * 评卷员提交评卷任务
      *
-     * @param result - 评卷结果
-     * @param marker - 评卷员
+     * @param result
+     *            - 评卷结果
+     * @param marker
+     *            - 评卷员
      * @return boolean
      */
     @Override
@@ -414,8 +436,8 @@ public class MarkServiceImpl implements MarkService {
     public boolean 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()) {
+        if (group == null || group.getStatus() == MarkStatus.FINISH
+                || group.getStatus().getValue() != result.getStatusValue()) {
             return false;
         }
 
@@ -426,17 +448,17 @@ public class MarkServiceImpl implements MarkService {
                 // 状态更新
                 Date now = new Date();
                 if (libraryDao.updateProblemResult(library.getId(), LibraryStatus.PROBLEM, marker.getId(), now,
-                        result.getSpent(), LibraryStatus.WAITING, LibraryStatus.MARKED, LibraryStatus.INSPECTED) != 0) {
+                        result.getSpent(), LibraryStatus.WAITING, LibraryStatus.MARKED) != 0) {
                     saveProblemHistory(result, library);
                     updateMarkedCount(group);
                     releaseLibrary(library, marker);
                     return true;
                 }
             }
-            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())) {
+            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())) {
                 if (submitLibrary(library, marker, group, result)) {
                     updateMarkedCount(group);
                     releaseLibrary(library, marker);
@@ -445,10 +467,10 @@ public class MarkServiceImpl implements MarkService {
             }
         } else if (group.getStatus() == MarkStatus.TRIAL) {
             TrialLibrary library = trialLibraryDao.findOne(result.getLibraryId());
-            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())) {
+            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())) {
                 TrialHistory history = new TrialHistory();
                 history.setExamId(library.getExamId());
                 history.setSubjectCode(library.getSubjectCode());
@@ -499,10 +521,14 @@ public class MarkServiceImpl implements MarkService {
     /**
      * 评卷员提交某个正评任务
      *
-     * @param library - 正评任务
-     * @param marker  - 评卷员
-     * @param group   - 评卷分组
-     * @param result  - 评卷结果
+     * @param library
+     *            - 正评任务
+     * @param marker
+     *            - 评卷员
+     * @param group
+     *            - 评卷分组
+     * @param result
+     *            - 评卷结果
      */
     private boolean submitLibrary(MarkLibrary library, Marker marker, MarkGroup group, MarkResult result) {
         // 非本人领取的待评任务
@@ -510,8 +536,7 @@ public class MarkServiceImpl implements MarkService {
             return false;
         }
         // 非本人的回评任务
-        if ((library.getStatus() == LibraryStatus.MARKED || library.getStatus() == LibraryStatus.INSPECTED) && !library
-                .getMarkerId().equals(marker.getId())) {
+        if ((library.getStatus() == LibraryStatus.MARKED) && !library.getMarkerId().equals(marker.getId())) {
             return false;
         }
         // 是否多评情况下已处理过该考生评卷任务
@@ -521,9 +546,9 @@ 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, LibraryStatus.MARKED,
-                LibraryStatus.INSPECTED) == 0) {
+        if (libraryDao.updateMarkerResult(library.getId(), LibraryStatus.MARKED, marker.getId(),
+                result.getTotalScore(), result.getScoreList(), now, result.getSpent(), LibraryStatus.WAITING,
+                LibraryStatus.MARKED) == 0) {
             // 条件不符更新失败,直接返回
             return false;
         }
@@ -541,9 +566,8 @@ public class MarkServiceImpl implements MarkService {
         ArbitrateHistory history = null;
         if (group.getArbitrateThreshold() != null && group.getArbitrateThreshold() > 0) {
             // 多评模式
-            List<MarkLibrary> list = libraryDao
-                    .findByStudentIdAndGroupNumberAndStatus(library.getStudentId(), library.getGroupNumber(),
-                            LibraryStatus.MARKED, LibraryStatus.INSPECTED);
+            List<MarkLibrary> list = libraryDao.findByStudentIdAndGroupNumberAndStatus(library.getStudentId(),
+                    library.getGroupNumber(), LibraryStatus.MARKED);
             for (MarkLibrary other : list) {
                 if (other.getId().equals(library.getId()) || other.getHeaderScore() != null) {
                     // 本评卷任务或组长已打分,则跳过该任务
@@ -553,13 +577,12 @@ public class MarkServiceImpl implements MarkService {
                 if (Math.abs(other.getMarkerScore() - result.getTotalScore()) > group.getArbitrateThreshold()) {
                     // 开启三评
                     if (group.getThirdPolicy().equals(ThirdPolicy.LOW_DIFF_HIGH_AVG)) {
-                        if (libraryDao.countByStudentIdAndGroupNumber(library.getStudentId(), library.getGroupNumber())
-                                == 2) {
+                        if (libraryDao.countByStudentIdAndGroupNumber(library.getStudentId(), library.getGroupNumber()) == 2) {
                             buildThirdLibrary(library, group);
                         } else {
                             // 两两比较,触发仲裁
-                            List<MarkLibrary> libraries = libraryDao
-                                    .findByStudentIdAndGroupNumber(library.getStudentId(), library.getGroupNumber());
+                            List<MarkLibrary> libraries = libraryDao.findByStudentIdAndGroupNumber(
+                                    library.getStudentId(), library.getGroupNumber());
                             history = buildArbitrateHistory(libraries, group.getArbitrateThreshold(), now);
                         }
                     } else {
@@ -585,8 +608,7 @@ public class MarkServiceImpl implements MarkService {
 
     private ArbitrateHistory buildArbitrateHistory(List<MarkLibrary> list, Double arbitrateThreshold, Date now) {
         for (MarkLibrary library : list) {
-            if (library.getStatus() != LibraryStatus.MARKED && library.getStatus() != LibraryStatus.INSPECTED
-                    && library.getStatus() != LibraryStatus.ARBITRATED) {
+            if (library.getStatus() != LibraryStatus.MARKED && library.getStatus() != LibraryStatus.ARBITRATED) {
                 return null;
             }
         }
@@ -637,7 +659,8 @@ public class MarkServiceImpl implements MarkService {
      * 管理员/组长打回某个评卷任务<br>
      * 暂时不用到BACKED状态,直接等同于重置该评卷任务
      *
-     * @param library - 正评任务
+     * @param library
+     *            - 正评任务
      */
     @Override
     @Transactional
@@ -646,8 +669,7 @@ public class MarkServiceImpl implements MarkService {
         if (group.getStatus() == MarkStatus.FINISH) {
             return false;
         }
-        if (libraryDao.resetById(library.getId(), LibraryStatus.WAITING, LibraryStatus.MARKED, LibraryStatus.INSPECTED,
-                LibraryStatus.PROBLEM) > 0) {
+        if (libraryDao.resetById(library.getId(), LibraryStatus.WAITING, LibraryStatus.MARKED, LibraryStatus.PROBLEM) > 0) {
             trackDao.deleteByLibraryId(library.getId());
             specialTagDao.deleteByLibraryId(library.getId());
             resetStudentGroup(library.getStudentId(), library.getExamId(), library.getSubjectCode(),
@@ -663,7 +685,8 @@ public class MarkServiceImpl implements MarkService {
     /**
      * 管理员/组长重置某个试评任务
      *
-     * @param library - 试评任务
+     * @param library
+     *            - 试评任务
      */
     @Override
     @Transactional
@@ -681,7 +704,8 @@ public class MarkServiceImpl implements MarkService {
     /**
      * 管理员/组长处理仲裁卷
      *
-     * @param history - 仲裁卷
+     * @param history
+     *            - 仲裁卷
      */
     @Override
     @Transactional
@@ -696,39 +720,40 @@ public class MarkServiceImpl implements MarkService {
         }
     }
 
-    //    /**
-    //     * 对某个考生某个科目进行主观题统分
-    //     *
-    //     * @param student - 考生
-    //     * @param groups  - 所有评卷分组
-    //     */
-    //    @Override
-    //    @Transactional
-    //    public void scoreCalculate(ExamStudent student, List<MarkGroup> groups) {
-    //        if (student == null || groups == null || groups.isEmpty()) {
-    //            return;
-    //        }
-    //        List<ScoreItem> scoreList = new ArrayList<>();
-    //        double totalScore = 0.0;
-    //        // 循环所有评卷分组
-    //        for (MarkGroup group : groups) {
-    //            if (group.getStatus().equals(MarkStatus.TRIAL)) {
-    //                return;
-    //            }
-    //            if (calculateGroup(group, student.getId())) {
-    //                totalScore += group.getMarkScore();
-    //                scoreList.addAll(group.getMarkScoreDetail());
-    //            } else {
-    //                // 未评完直接返回
-    //                return;
-    //            }
-    //        }
-    //        // 全部评完,更新考生主观题得分
-    //        student.setSubjectiveScore(totalScore);
-    //        student.setScoreList(scoreList, false);
-    //        studentService
-    //                .updateSubjectiveScore(student.getId(), student.getSubjectiveScore(), student.getSubjectiveScoreList());
-    //    }
+    // /**
+    // * 对某个考生某个科目进行主观题统分
+    // *
+    // * @param student - 考生
+    // * @param groups - 所有评卷分组
+    // */
+    // @Override
+    // @Transactional
+    // public void scoreCalculate(ExamStudent student, List<MarkGroup> groups) {
+    // if (student == null || groups == null || groups.isEmpty()) {
+    // return;
+    // }
+    // List<ScoreItem> scoreList = new ArrayList<>();
+    // double totalScore = 0.0;
+    // // 循环所有评卷分组
+    // for (MarkGroup group : groups) {
+    // if (group.getStatus().equals(MarkStatus.TRIAL)) {
+    // return;
+    // }
+    // if (calculateGroup(group, student.getId())) {
+    // totalScore += group.getMarkScore();
+    // scoreList.addAll(group.getMarkScoreDetail());
+    // } else {
+    // // 未评完直接返回
+    // return;
+    // }
+    // }
+    // // 全部评完,更新考生主观题得分
+    // student.setSubjectiveScore(totalScore);
+    // student.setScoreList(scoreList, false);
+    // studentService
+    // .updateSubjectiveScore(student.getId(), student.getSubjectiveScore(),
+    // student.getSubjectiveScoreList());
+    // }
 
     private void scoreCalculate(Integer studentId) {
         List<ScoreItem> scoreList = new ArrayList<>();
@@ -755,8 +780,7 @@ public class MarkServiceImpl implements MarkService {
             return false;
         }
         for (MarkLibrary library : list) {
-            if (library.getStatus() != LibraryStatus.MARKED && library.getStatus() != LibraryStatus.INSPECTED
-                    && library.getStatus() != LibraryStatus.ARBITRATED) {
+            if (library.getStatus() != LibraryStatus.MARKED && library.getStatus() != LibraryStatus.ARBITRATED) {
                 // 有非完成状态的评卷任务,直接返回
                 return false;
             }
@@ -772,12 +796,12 @@ public class MarkServiceImpl implements MarkService {
                 }
                 return -1;
             });
-            Double score1 =
-                    list.get(0).getHeaderScore() != null ? list.get(0).getHeaderScore() : list.get(0).getMarkerScore();
-            Double score2 =
-                    list.get(1).getHeaderScore() != null ? list.get(1).getHeaderScore() : list.get(1).getMarkerScore();
-            Double score3 =
-                    list.get(2).getHeaderScore() != null ? list.get(2).getHeaderScore() : list.get(2).getMarkerScore();
+            Double score1 = list.get(0).getHeaderScore() != null ? list.get(0).getHeaderScore() : list.get(0)
+                    .getMarkerScore();
+            Double score2 = list.get(1).getHeaderScore() != null ? list.get(1).getHeaderScore() : list.get(1)
+                    .getMarkerScore();
+            Double score3 = list.get(2).getHeaderScore() != null ? list.get(2).getHeaderScore() : list.get(2)
+                    .getMarkerScore();
             if ((score3 - score2) <= (score2 - score1)) {
                 list.remove(0);
             } else {
@@ -849,16 +873,19 @@ public class MarkServiceImpl implements MarkService {
     /**
      * 更新某个评卷分组已评任务数量
      *
-     * @param group - 评卷分组
+     * @param group
+     *            - 评卷分组
      */
     @Override
     @Transactional
     public void updateMarkedCount(MarkGroup group) {
         if (group.getStatus() == MarkStatus.FORMAL || group.getStatus() == MarkStatus.FINISH) {
-            groupDao.updateMarkedCount(group.getExamId(), group.getSubjectCode(), group.getNumber(), (int) libraryDao
-                    .countByExamIdAndSubjectCodeAndGroupNumberAndStatus(group.getExamId(), group.getSubjectCode(),
-                            group.getNumber(), LibraryStatus.MARKED, LibraryStatus.ARBITRATED,
-                            LibraryStatus.INSPECTED));
+            groupDao.updateMarkedCount(
+                    group.getExamId(),
+                    group.getSubjectCode(),
+                    group.getNumber(),
+                    (int) libraryDao.countByExamIdAndSubjectCodeAndGroupNumberAndStatus(group.getExamId(),
+                            group.getSubjectCode(), group.getNumber(), LibraryStatus.MARKED, LibraryStatus.ARBITRATED));
         } else if (group.getStatus() == MarkStatus.TRIAL) {
             groupDao.updateMarkedCount(group.getExamId(), group.getSubjectCode(), group.getNumber(),
                     (int) trialLibraryDao.countMarked(group.getExamId(), group.getSubjectCode(), group.getNumber()));
@@ -868,21 +895,20 @@ public class MarkServiceImpl implements MarkService {
     /**
      * 更新某个评卷分组评卷任务总量
      *
-     * @param group - 评卷分组
+     * @param group
+     *            - 评卷分组
      */
     @Override
     @Transactional
     public void updateLibraryCount(MarkGroup group) {
         if (group.getStatus() == MarkStatus.FORMAL || group.getStatus() == MarkStatus.FINISH) {
-            group.setLibraryCount((int) libraryDao
-                    .countByExamIdAndSubjectCodeAndGroupNumber(group.getExamId(), group.getSubjectCode(),
-                            group.getNumber()));
+            group.setLibraryCount((int) libraryDao.countByExamIdAndSubjectCodeAndGroupNumber(group.getExamId(),
+                    group.getSubjectCode(), group.getNumber()));
             groupDao.updateLibraryCount(group.getExamId(), group.getSubjectCode(), group.getNumber(),
                     group.getLibraryCount());
         } else if (group.getStatus() == MarkStatus.TRIAL) {
-            group.setLibraryCount((int) trialLibraryDao
-                    .countByExamIdAndSubjectCodeAndGroupNumber(group.getExamId(), group.getSubjectCode(),
-                            group.getNumber()));
+            group.setLibraryCount((int) trialLibraryDao.countByExamIdAndSubjectCodeAndGroupNumber(group.getExamId(),
+                    group.getSubjectCode(), group.getNumber()));
             groupDao.updateLibraryCount(group.getExamId(), group.getSubjectCode(), group.getNumber(),
                     group.getLibraryCount());
         }
@@ -891,8 +917,10 @@ public class MarkServiceImpl implements MarkService {
     /**
      * 更新某个科目所有评卷分组评卷任务数量
      *
-     * @param examId      - 考试ID
-     * @param subjectCode - 科目代码
+     * @param examId
+     *            - 考试ID
+     * @param subjectCode
+     *            - 科目代码
      */
     @Transactional
     @Override
@@ -907,9 +935,12 @@ public class MarkServiceImpl implements MarkService {
     /**
      * 根据考生、学习中心、评卷分组构造正式评卷任务
      *
-     * @param student - 考生
-     * @param group   - 评卷分组
-     * @param subject - 科目
+     * @param student
+     *            - 考生
+     * @param group
+     *            - 评卷分组
+     * @param subject
+     *            - 科目
      */
     @Override
     @Transactional
@@ -935,15 +966,14 @@ public class MarkServiceImpl implements MarkService {
                 } else {
                     double studentCount = subject.getUploadCount();
                     double libraryCount = group.getLibraryCount();
-                    double doubleCount = libraryDao
-                            .countByExamIdAndSubjectCodeAndGroupNumberAndTaskNumber(group.getExamId(),
-                                    group.getSubjectCode(), group.getNumber(), 2);
+                    double doubleCount = libraryDao.countByExamIdAndSubjectCodeAndGroupNumberAndTaskNumber(
+                            group.getExamId(), group.getSubjectCode(), group.getNumber(), 2);
                     int expectCount = (int) (studentCount * group.getDoubleRate());
                     // 随机数判断加入当前已经生成双评任务的比例加权
                     // 实际双评任务数小于理论生成数 &&(剩余未生成双评的考生数量小于剩余应生成的数量||随机比例)
-                    needDouble = doubleCount < expectCount && (
-                            (studentCount - libraryCount + doubleCount) <= (expectCount - doubleCount)
-                                    || Math.random() < group.getDoubleRate() + 0.1);
+                    needDouble = doubleCount < expectCount
+                            && ((studentCount - libraryCount + doubleCount) <= (expectCount - doubleCount) || Math
+                                    .random() < group.getDoubleRate() + 0.1);
                 }
                 if (needDouble) {
                     library = new MarkLibrary();
@@ -968,8 +998,10 @@ public class MarkServiceImpl implements MarkService {
     /**
      * 根据考生、学习中心、评卷分组构造试评评卷任务
      *
-     * @param student - 考生
-     * @param group   - 评卷分组
+     * @param student
+     *            - 考生
+     * @param group
+     *            - 评卷分组
      */
     @Override
     @Transactional
@@ -991,7 +1023,8 @@ public class MarkServiceImpl implements MarkService {
      * 领取正式评卷任务时,用来区分的唯一标识<br/>
      * 多评时同一个考生的多份任务不能被同一位评卷员领取
      *
-     * @param library - 正评任务
+     * @param library
+     *            - 正评任务
      */
     private String getApplyTaskId(MarkLibrary library) {
         return library.getStudentId() + "_" + library.getGroupNumber();
@@ -1000,7 +1033,8 @@ public class MarkServiceImpl implements MarkService {
     /**
      * 领取试评评卷任务时,用来区分的唯一标识
      *
-     * @param library - 试评任务
+     * @param library
+     *            - 试评任务
      */
     private String getApplyTaskId(TrialLibrary library, Marker marker) {
         return library.getId() + "_" + marker.getId();
@@ -1009,7 +1043,8 @@ public class MarkServiceImpl implements MarkService {
     /**
      * 重置评卷分组的连带操作
      *
-     * @param group - 评卷分组
+     * @param group
+     *            - 评卷分组
      */
     private void resetGroup(MarkGroup group) {
         if (group.getStatus() == MarkStatus.FORMAL) {
@@ -1022,9 +1057,8 @@ public class MarkServiceImpl implements MarkService {
                     group.getNumber());
             libraryDao.resetByExamIdAndSubjectCodeAndGroupNumber(group.getExamId(), group.getSubjectCode(),
                     group.getNumber(), LibraryStatus.WAITING);
-            libraryDao
-                    .deleteByExamIdAndSubjectCodeAndGroupNumberAndTaskNumber(group.getExamId(), group.getSubjectCode(),
-                            group.getNumber(), 3);
+            libraryDao.deleteByExamIdAndSubjectCodeAndGroupNumberAndTaskNumber(group.getExamId(),
+                    group.getSubjectCode(), group.getNumber(), 3);
             markerDao.resetByExamIdAndSubjectCodeAndGroupNumber(group.getExamId(), group.getSubjectCode(),
                     group.getNumber());
             resetStudentGroup(group.getExamId(), group.getSubjectCode(), group.getNumber());
@@ -1043,7 +1077,8 @@ public class MarkServiceImpl implements MarkService {
     /**
      * 计算并更新指定评卷员的评卷质量指标
      *
-     * @param marker - 评卷员
+     * @param marker
+     *            - 评卷员
      */
     @Override
     @Transactional
@@ -1059,7 +1094,7 @@ public class MarkServiceImpl implements MarkService {
         double avgSpent = 0;
         for (MarkLibrary library : list) {
             finishCount++;
-            if (library.getStatus() == LibraryStatus.MARKED || library.getStatus() == LibraryStatus.INSPECTED) {
+            if (library.getStatus() == LibraryStatus.MARKED) {
                 validCount++;
             }
             double score = library.getMarkerScore() != null ? library.getMarkerScore() : 0;
@@ -1182,7 +1217,7 @@ public class MarkServiceImpl implements MarkService {
 
     private void updateStudentGroupScore(Integer studentId, Integer examId, String subjectCode, Integer groupNumber,
             double score, List<ScoreItem> scoreList) {
-        //scoreDao.deleteByStudentIdAndGroupNumber(studentId, groupNumber);
+        // scoreDao.deleteByStudentIdAndGroupNumber(studentId, groupNumber);
         List<SubjectiveScore> list = new ArrayList<>();
         for (ScoreItem item : scoreList) {
             SubjectiveScore ss = new SubjectiveScore();

+ 1 - 2
stmms-common/src/main/java/cn/com/qmth/stmms/common/enums/LibraryStatus.java

@@ -9,8 +9,7 @@ public enum LibraryStatus {
     BACKED("已打回", 2), 
     WAIT_ARBITRATE("等待仲裁", 3), 
     ARBITRATED("已仲裁", 4),
-    INSPECTED("已复核",5),
-    PROBLEM("问题卷",6);
+    PROBLEM("问题卷",5);
 
     private String name;
 

+ 31 - 0
stmms-common/src/main/java/cn/com/qmth/stmms/common/enums/ObjectiveStatus.java

@@ -0,0 +1,31 @@
+package cn.com.qmth.stmms.common.enums;
+
+public enum ObjectiveStatus {
+    WAITING("待处理", 0), FINISH("已统分", 1);
+
+    private String name;
+
+    private int value;
+
+    private ObjectiveStatus(String name, int value) {
+        this.name = name;
+        this.value = value;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public int getValue() {
+        return value;
+    }
+
+    public void setValue(int value) {
+        this.value = value;
+    }
+
+}

+ 2 - 0
stmms-web/src/main/java/cn/com/qmth/stmms/admin/exam/ExamController.java

@@ -42,6 +42,7 @@ import cn.com.qmth.stmms.common.domain.WebUser;
 import cn.com.qmth.stmms.common.enums.ExamStatus;
 import cn.com.qmth.stmms.common.enums.ExamType;
 import cn.com.qmth.stmms.common.enums.LogType;
+import cn.com.qmth.stmms.common.enums.ObjectiveStatus;
 import cn.com.qmth.stmms.common.enums.Role;
 import cn.com.qmth.stmms.common.utils.RequestUtils;
 
@@ -113,6 +114,7 @@ public class ExamController extends BaseExamController {
         exam.setSchoolId(user.getSchoolId());
         exam.setCreatorId(user.getId());
         exam.setStatus(ExamStatus.START);
+        exam.setObjectiveStatus(ObjectiveStatus.WAITING);
         if (exam.getType().equals(ExamType.MULTI_MEDIA)) {
             exam.setForceSpecialTag(false);
         }

+ 7 - 8
stmms-web/src/main/java/cn/com/qmth/stmms/admin/exam/InspectedController.java

@@ -140,9 +140,8 @@ public class InspectedController extends BaseExamController {
             result.accumulate("markerScore", library.getMarkerScore());
 
             JSONArray array = new JSONArray();
-            List<ExamQuestion> questions = questionService
-                    .findByExamAndSubjectAndObjectiveAndGroupNumber(library.getExamId(), library.getSubjectCode(),
-                            false, library.getGroupNumber());
+            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);
@@ -153,10 +152,10 @@ public class InspectedController extends BaseExamController {
             }
             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());
+            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);
@@ -177,7 +176,7 @@ public class InspectedController extends BaseExamController {
         MarkLibrary library = libraryService.findById(libraryId);
         WebUser wu = RequestUtils.getWebUser(request);
         if (library != null && library.getStatus().equals(LibraryStatus.MARKED)) {
-            library.setStatus(LibraryStatus.INSPECTED);
+            // library.setStatus(LibraryStatus.INSPECTED);
             library.setHeaderId(wu.getUser().getId());
             library.setHeaderTime(new Date());
             libraryService.save(library);

+ 0 - 66
stmms-web/src/main/java/cn/com/qmth/stmms/admin/exam/MarkController.java

@@ -13,44 +13,31 @@ import javax.servlet.http.HttpServletResponse;
 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.servlet.ModelAndView;
 import org.springframework.web.servlet.mvc.support.RedirectAttributes;
 
 import cn.com.qmth.stmms.admin.dto.MarkGroupDTO;
 import cn.com.qmth.stmms.admin.dto.MarkerInfoDTO;
-import cn.com.qmth.stmms.admin.thread.ScoreCalculateThread;
 import cn.com.qmth.stmms.admin.vo.SubjectLibraryVO;
-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.ExamStudentService;
 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.exam.service.query.ExamSubjectSearchQuery;
-import cn.com.qmth.stmms.biz.lock.LockService;
 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.report.service.ReportService;
 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.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.ExportExcel;
 import cn.com.qmth.stmms.common.utils.RequestUtils;
 
@@ -78,22 +65,6 @@ public class MarkController extends BaseExamController {
     @Autowired
     private ExamService examService;
 
-    @Autowired
-    private ReportService reportService;
-
-    @Qualifier("task-executor")
-    @Autowired
-    private AsyncTaskExecutor taskExecutor;
-
-    @Autowired
-    private LockService lockService;
-
-    @Autowired
-    private MarkService markService;
-
-    @Autowired
-    private ExamStudentService studentService;
-
     @Autowired
     private MarkLibraryService libraryService;
 
@@ -120,7 +91,6 @@ public class MarkController extends BaseExamController {
             vo.setSubject(subject);
             vo.setStudentCount(subject.getUploadCount());
             vo.setGroupCount(groupService.countByExamAndSubject(examId, subject.getCode()));
-            vo.setLocked(lockService.isLocked(LockType.SCORE_CALCULATE, examId, subject.getCode()));
             MarkLibrarySearchQuery mQuery = new MarkLibrarySearchQuery();
             mQuery.setExamId(examId);
             mQuery.setSubjectCode(subject.getCode());
@@ -215,40 +185,4 @@ public class MarkController extends BaseExamController {
         }
     }
 
-    @Logging(menu = "科目统分", type = LogType.UPDATE)
-    @RequestMapping("/calculate")
-    @RoleRequire(Role.SCHOOL_ADMIN)
-    public ModelAndView calculate(HttpServletRequest request, RedirectAttributes redirectAttributes,
-            @RequestParam(required = false) String subjectCode) {
-        WebUser wu = RequestUtils.getWebUser(request);
-        Exam exam = examService.findById(getSessionExamId(request));
-        if (exam == null || !exam.getSchoolId().equals(wu.getUser().getSchoolId())) {
-            addMessage(redirectAttributes, "请选择正确的考试");
-        } else {
-            Set<String> subjectSet = new HashSet<String>();
-            if (subjectCode == null) {
-                subjectSet = getCalculateSubjectCodes(exam.getId());
-            } else if (!lockService.isLocked(LockType.SCORE_CALCULATE, exam.getId(), subjectCode)) {
-                subjectSet.add(subjectCode);
-            }
-            if (!subjectSet.isEmpty()) {
-                ScoreCalculateThread thread = new ScoreCalculateThread(exam.getId(), subjectSet, lockService,
-                        studentService, questionService, markService, reportService, examService, subjectService,
-                        groupService);
-                taskExecutor.submit(thread);
-            }
-        }
-        return new ModelAndView("redirect:/admin/exam/mark");
-    }
-
-    private Set<String> getCalculateSubjectCodes(Integer examId) {
-        List<ExamSubject> list = subjectService.list(examId);
-        Set<String> set = new HashSet<>();
-        for (ExamSubject subject : list) {
-            if (!lockService.isLocked(LockType.SCORE_CALCULATE, subject.getExamId(), subject.getCode())) {
-                set.add(subject.getCode());
-            }
-        }
-        return set;
-    }
 }

+ 3 - 6
stmms-web/src/main/java/cn/com/qmth/stmms/admin/exam/MarkQualityController.java

@@ -154,11 +154,10 @@ public class MarkQualityController extends BaseExamController {
         if (group != null) {
             List<MarkerVO> list = new ArrayList<MarkerVO>();
             List<Marker> markers = markerService.findByExamAndSubjectAndGroup(examId, subjectCode, groupNumber);
-            List<Double> scores = libraryService.findScore(examId, subjectCode, groupNumber, LibraryStatus.MARKED,
-                    LibraryStatus.INSPECTED);
+            List<Double> scores = libraryService.findScore(examId, subjectCode, groupNumber, LibraryStatus.MARKED);
             for (Marker marker : markers) {
                 List<Object[]> libraries = libraryService.findScoreCount(examId, subjectCode, groupNumber,
-                        marker.getId(), LibraryStatus.MARKED, LibraryStatus.INSPECTED);
+                        marker.getId(), LibraryStatus.MARKED);
                 Map<Double, Long> scoreCount = new HashMap<Double, Long>();
                 for (Object[] array : libraries) {
                     Double score = (Double) array[0];
@@ -194,11 +193,10 @@ public class MarkQualityController extends BaseExamController {
         List<Marker> markers = markerService.findByExamAndSubjectAndGroup(examId, subjectCode, groupNumber);
         for (Marker marker : markers) {
             List<Object[]> libraries = libraryService.findScoreCount(examId, subjectCode, groupNumber, marker.getId(),
-                    LibraryStatus.MARKED, LibraryStatus.INSPECTED);
+                    LibraryStatus.MARKED);
             MarkLibrarySearchQuery query = new MarkLibrarySearchQuery();
             query.setMarkerId(marker.getId());
             query.addStatus(LibraryStatus.MARKED);
-            query.addStatus(LibraryStatus.INSPECTED);
             long totalCount = libraryService.countByQuery(query);
             Map<Double, Double> scorePercent = new HashMap<Double, Double>();
             for (Object[] array : libraries) {
@@ -269,7 +267,6 @@ public class MarkQualityController extends BaseExamController {
             query.setSubjectCode(marker.getSubjectCode());
             query.setMarkerId(marker.getId());
             query.addStatus(LibraryStatus.MARKED);
-            query.addStatus(LibraryStatus.INSPECTED);
             query.setGroupNumber(marker.getGroupNumber());
             query.setMarkerScore(markerScore);
             if (pageNumber != null) {

+ 131 - 28
stmms-web/src/main/java/cn/com/qmth/stmms/admin/exam/PaperController.java

@@ -1,48 +1,67 @@
 package cn.com.qmth.stmms.admin.exam;
 
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import net.sf.json.JSONArray;
+import net.sf.json.JSONObject;
+
+import org.apache.commons.lang.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.core.task.AsyncTaskExecutor;
+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.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.multipart.MultipartFile;
+import org.springframework.web.servlet.ModelAndView;
+import org.springframework.web.servlet.mvc.support.RedirectAttributes;
+
 import cn.com.qmth.stmms.admin.dto.ObjectiveQuestionDTO;
 import cn.com.qmth.stmms.admin.dto.QuestionDTO;
 import cn.com.qmth.stmms.admin.dto.SubjectQuestionDTO;
 import cn.com.qmth.stmms.admin.dto.SubjectiveQuestionDTO;
+import cn.com.qmth.stmms.admin.thread.ScoreCalculateThread;
+import cn.com.qmth.stmms.admin.thread.ScoreReportThread;
 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.ExamSubject;
 import cn.com.qmth.stmms.biz.exam.model.MarkGroup;
 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.ExamSubjectService;
 import cn.com.qmth.stmms.biz.exam.service.MarkGroupService;
 import cn.com.qmth.stmms.biz.exam.service.query.ExamQuestionSearchQuery;
 import cn.com.qmth.stmms.biz.exam.service.query.ExamSubjectSearchQuery;
 import cn.com.qmth.stmms.biz.file.service.FileService;
+import cn.com.qmth.stmms.biz.lock.LockService;
+import cn.com.qmth.stmms.biz.report.service.ReportService;
 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.LockType;
 import cn.com.qmth.stmms.common.enums.LogType;
 import cn.com.qmth.stmms.common.enums.ObjectivePolicy;
+import cn.com.qmth.stmms.common.enums.ObjectiveStatus;
 import cn.com.qmth.stmms.common.enums.Role;
 import cn.com.qmth.stmms.common.utils.ExportExcel;
 import cn.com.qmth.stmms.common.utils.ImportExcel;
 import cn.com.qmth.stmms.common.utils.RequestUtils;
-import net.sf.json.JSONArray;
-import net.sf.json.JSONObject;
-import org.apache.commons.lang.StringUtils;
-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 org.springframework.web.multipart.MultipartFile;
-import org.springframework.web.servlet.mvc.support.RedirectAttributes;
-
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import java.util.HashMap;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
 
 @Controller("examPaperController")
 @RequestMapping("/admin/exam/paper")
@@ -63,6 +82,19 @@ public class PaperController extends BaseExamController {
     @Autowired
     private FileService fileService;
 
+    @Qualifier("task-executor")
+    @Autowired
+    private AsyncTaskExecutor taskExecutor;
+
+    @Autowired
+    private LockService lockService;
+
+    @Autowired
+    private ExamStudentService studentService;
+
+    @Autowired
+    private ReportService reportService;
+
     @Logging(menu = "试卷管理查询", type = LogType.QUERY)
     @RequestMapping
     public String list(Model model, HttpServletRequest request, ExamSubjectSearchQuery query,
@@ -80,6 +112,7 @@ public class PaperController extends BaseExamController {
         query = subjectService.findByQuery(query);
         for (ExamSubject subject : query.getResult()) {
             subject.setPaperAnswerUrl(fileService);
+            subject.setLocked(lockService.isLocked(LockType.SCORE_CALCULATE, examId, subject.getCode()));
         }
         model.addAttribute("query", query);
         model.addAttribute("upload", upload);
@@ -87,8 +120,7 @@ public class PaperController extends BaseExamController {
         model.addAttribute("levelList", subjectService.listLevel(examId));
         model.addAttribute("categoryList", subjectService.listCategory(examId));
         model.addAttribute("fileServer", fileService.getFileServer());
-        Exam exam = examService.findById(examId);
-        model.addAttribute("examType", exam.getType());
+        model.addAttribute("examLock", lockService.isLocked(LockType.SCORE_CALCULATE, examId));
         return "modules/exam/paperList";
     }
 
@@ -99,8 +131,8 @@ public class PaperController extends BaseExamController {
         WebUser wu = RequestUtils.getWebUser(request);
         int examId = getSessionExamId(request);
         if (wu.isSubjectHeader()
-            // TODO - subjectheader check
-            //&&!subjectCode.equals(wu.getUser().getSubjectCode())
+        // TODO - subjectheader check
+        // &&!subjectCode.equals(wu.getUser().getSubjectCode())
         ) {
             return "redirect:/admin/exam/paper";
         }
@@ -166,10 +198,9 @@ public class PaperController extends BaseExamController {
         query.setPageSize(Integer.MAX_VALUE);
         query = questionService.findByQuery(query);
         for (ExamQuestion q : query.getResult()) {
-            list.add(objective ?
-                    new ObjectiveQuestionDTO(q, subjectMap.get(q.getSubjectCode())) :
-                    new SubjectiveQuestionDTO(q, subjectMap.get(q.getSubjectCode()),
-                            groupMap.get(q.getSubjectCode() + "_" + q.getGroupNumber())));
+            list.add(objective ? new ObjectiveQuestionDTO(q, subjectMap.get(q.getSubjectCode()))
+                    : new SubjectiveQuestionDTO(q, subjectMap.get(q.getSubjectCode()), groupMap.get(q.getSubjectCode()
+                            + "_" + q.getGroupNumber())));
         }
         try {
             String fileName = objective ? "客观题数据.xlsx" : "主观题数据.xlsx";
@@ -195,9 +226,10 @@ public class PaperController extends BaseExamController {
         if (error.isEmpty()) {
             int success = 0;
             for (SubjectQuestionDTO dto : map.values()) {
+                // 每次导入都需要重新统分
+                examService.updateObjectiveStatus(examId, ObjectiveStatus.WAITING);
                 ExamSubject subject = subjectService.find(examId, dto.getSubjectCode());
                 if (subject != null) {
-                    // TODO - 每次导入都需要重新统分
                     if (dto.validate(error)) {
                         if (objective) {
                             questionService.deleteByExamAndSubjectAndObjective(examId, dto.getSubjectCode(), objective);
@@ -304,4 +336,75 @@ public class PaperController extends BaseExamController {
         return "redirect:/admin/exam/paper/detail?subjectCode=" + question.getSubjectCode();
     }
 
+    @Logging(menu = "客观题统分", type = LogType.UPDATE)
+    @RequestMapping("/calculate")
+    @RoleRequire(Role.SCHOOL_ADMIN)
+    public ModelAndView calculate(HttpServletRequest request, RedirectAttributes redirectAttributes,
+            @RequestParam(required = false) String subjectCode) {
+        WebUser wu = RequestUtils.getWebUser(request);
+        Exam exam = examService.findById(getSessionExamId(request));
+        if (exam == null || !exam.getSchoolId().equals(wu.getUser().getSchoolId())) {
+            addMessage(redirectAttributes, "请选择正确的考试");
+        } else {
+            Set<String> subjectSet = new HashSet<String>();
+            // 整个考试加锁
+            boolean examLock = false;
+            if (subjectCode == null) {
+                subjectSet = getCalculateSubjectCodes(exam.getId());
+                examLock = true;
+            } else if (!lockService.isLocked(LockType.SCORE_CALCULATE, exam.getId(), subjectCode)) {
+                subjectSet.add(subjectCode);
+            }
+            if (!subjectSet.isEmpty()) {
+                ScoreCalculateThread thread = new ScoreCalculateThread(exam.getId(), subjectSet, lockService,
+                        studentService, questionService, examService, subjectService, examLock);
+                taskExecutor.submit(thread);
+            }
+        }
+        return new ModelAndView("redirect:/admin/exam/paper");
+    }
+
+    private Set<String> getCalculateSubjectCodes(Integer examId) {
+        List<ExamSubject> list = subjectService.list(examId);
+        Set<String> set = new HashSet<>();
+        for (ExamSubject subject : list) {
+            if (!lockService.isLocked(LockType.SCORE_CALCULATE, subject.getExamId(), subject.getCode())) {
+                set.add(subject.getCode());
+            }
+        }
+        return set;
+    }
+
+    @Logging(menu = "科目成绩分析计算", type = LogType.UPDATE)
+    @RequestMapping("/report")
+    @RoleRequire(Role.SCHOOL_ADMIN)
+    public ModelAndView report(HttpServletRequest request, RedirectAttributes redirectAttributes,
+            @RequestParam(required = false) String subjectCode) {
+        WebUser wu = RequestUtils.getWebUser(request);
+        Exam exam = examService.findById(getSessionExamId(request));
+        if (exam == null || !exam.getSchoolId().equals(wu.getUser().getSchoolId())) {
+            addMessage(redirectAttributes, "请选择正确的考试");
+        } else {
+            Set<String> subjectSet = new HashSet<String>();
+            // 整个考试加锁
+            boolean examLock = false;
+            if (subjectCode == null) {
+                examLock = true;
+                List<ExamSubject> list = subjectService.list(exam.getId());
+                for (ExamSubject subject : list) {
+                    if (!lockService.isLocked(LockType.SCORE_CALCULATE, subject.getExamId(), subject.getCode())) {
+                        subjectSet.add(subject.getCode());
+                    }
+                }
+            } else if (!lockService.isLocked(LockType.SCORE_CALCULATE, exam.getId(), subjectCode)) {
+                subjectSet.add(subjectCode);
+            }
+            if (!subjectSet.isEmpty()) {
+                ScoreReportThread thread = new ScoreReportThread(exam.getId(), subjectSet, lockService, studentService,
+                        questionService, reportService, examService, subjectService, examLock);
+                taskExecutor.submit(thread);
+            }
+        }
+        return new ModelAndView("redirect:/admin/exam/paper");
+    }
 }

+ 18 - 10
stmms-web/src/main/java/cn/com/qmth/stmms/admin/exam/SubjectController.java

@@ -1,12 +1,9 @@
 package cn.com.qmth.stmms.admin.exam;
 
-import cn.com.qmth.stmms.biz.exam.model.ExamSubject;
-import cn.com.qmth.stmms.biz.exam.service.ExamSubjectService;
-import cn.com.qmth.stmms.biz.mark.model.PictureConfigItem;
-import cn.com.qmth.stmms.common.annotation.Logging;
-import cn.com.qmth.stmms.common.annotation.RoleRequire;
-import cn.com.qmth.stmms.common.enums.LogType;
-import cn.com.qmth.stmms.common.enums.Role;
+import java.util.List;
+
+import javax.servlet.http.HttpServletRequest;
+
 import net.sf.json.JSONArray;
 import net.sf.json.JSONObject;
 import net.sf.json.JsonConfig;
@@ -21,9 +18,15 @@ import org.springframework.web.bind.annotation.RequestMethod;
 import org.springframework.web.bind.annotation.RequestParam;
 import org.springframework.web.bind.annotation.ResponseBody;
 
-import javax.servlet.http.HttpServletRequest;
-
-import java.util.List;
+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.service.ExamService;
+import cn.com.qmth.stmms.biz.exam.service.ExamSubjectService;
+import cn.com.qmth.stmms.biz.mark.model.PictureConfigItem;
+import cn.com.qmth.stmms.common.annotation.Logging;
+import cn.com.qmth.stmms.common.annotation.RoleRequire;
+import cn.com.qmth.stmms.common.enums.LogType;
+import cn.com.qmth.stmms.common.enums.Role;
 
 @Controller
 @RequestMapping("/admin/exam/subject")
@@ -32,6 +35,9 @@ public class SubjectController extends BaseExamController {
     @Autowired
     private ExamSubjectService subjectService;
 
+    @Autowired
+    private ExamService examService;
+
     @RequestMapping("/list")
     @ResponseBody
     public JSONArray list(HttpServletRequest request, @RequestParam Integer examId) {
@@ -56,6 +62,8 @@ public class SubjectController extends BaseExamController {
         model.addAttribute("pictureConfig", buildPictureConfig(subject.getSheetConfig()));
         model.addAttribute("passScore", subject.getPassScore());
         model.addAttribute("excellentScore", subject.getExcellentScore());
+        Exam exam = examService.findById(subject.getExamId());
+        model.addAttribute("examType", exam.getType());
         return "modules/exam/subjectEdit";
     }
 

+ 52 - 82
stmms-web/src/main/java/cn/com/qmth/stmms/admin/thread/ScoreCalculateThread.java

@@ -1,20 +1,28 @@
 package cn.com.qmth.stmms.admin.thread;
 
-import cn.com.qmth.stmms.biz.exam.model.*;
-import cn.com.qmth.stmms.biz.exam.service.*;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.commons.lang.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+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.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.ExamSubjectService;
 import cn.com.qmth.stmms.biz.lock.LockService;
-import cn.com.qmth.stmms.biz.mark.service.MarkService;
-import cn.com.qmth.stmms.biz.report.service.ReportService;
-import cn.com.qmth.stmms.biz.report.utils.ReportContext;
 import cn.com.qmth.stmms.biz.utils.ScoreCalculateUtil;
 import cn.com.qmth.stmms.biz.utils.ScoreInfo;
 import cn.com.qmth.stmms.common.enums.ExamStatus;
 import cn.com.qmth.stmms.common.enums.LockType;
-import org.apache.commons.lang.StringUtils;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.util.*;
+import cn.com.qmth.stmms.common.enums.ObjectiveStatus;
 
 public class ScoreCalculateThread implements Runnable {
 
@@ -24,50 +32,40 @@ public class ScoreCalculateThread implements Runnable {
 
     private ExamQuestionService questionService;
 
-    private MarkService markService;
-
     private int examId;
 
     private Set<String> subjectCodeSet;
 
     private LockService lockService;
 
-    private ReportService reportService;
-
     private Map<String, List<ExamQuestion>> objectiveMap;
 
     private Map<String, List<ExamQuestion>> subjectiveMap;
 
-    private Map<String, ExamSubject> subjectMap;
+    // private Map<String, ExamSubject> subjectMap;
 
-    private Map<String, List<MarkGroup>> groupMap;
+    // private Map<String, List<MarkGroup>> groupMap;
+    //
+    // private MarkGroupService groupService;
 
-    private MarkGroupService groupService;
-
-    private ExamSubjectService subjectService;
+    // private ExamSubjectService subjectService;
 
     private ExamService examService;
 
-    private ReportContext context;
+    private boolean examLock;
 
     public ScoreCalculateThread(int examId, Set<String> subjectCodeSet, LockService lockService,
-            ExamStudentService studentService, ExamQuestionService questionService, MarkService markService,
-            ReportService reportService, ExamService examService, ExamSubjectService subjectService,
-            MarkGroupService groupService) {
+            ExamStudentService studentService, ExamQuestionService questionService, ExamService examService,
+            ExamSubjectService subjectService, boolean examLock) {
         this.examId = examId;
         this.subjectCodeSet = subjectCodeSet != null ? subjectCodeSet : new HashSet<>();
         this.lockService = lockService;
         this.studentService = studentService;
         this.questionService = questionService;
-        this.markService = markService;
-        this.reportService = reportService;
         this.examService = examService;
-        this.subjectService = subjectService;
-        this.groupService = groupService;
+        this.examLock = examLock;
         this.objectiveMap = new HashMap<>();
         this.subjectiveMap = new HashMap<>();
-        this.subjectMap = new HashMap<>();
-        this.groupMap = new HashMap<>();
     }
 
     @Override
@@ -79,6 +77,10 @@ public class ScoreCalculateThread implements Runnable {
             return;
         }
         log.info("start calculate for examId=" + examId + ", subjectCode count=" + subjectCodeSet.size());
+        // 判断是否整个考试上锁
+        if (examLock) {
+            lockService.trylock(LockType.SCORE_CALCULATE, examId);
+        }
         for (String subjectCode : subjectCodeSet) {
             // 尝试上锁,失败直接跳过
             if (!lockService.trylock(LockType.SCORE_CALCULATE, examId, subjectCode)) {
@@ -87,38 +89,18 @@ public class ScoreCalculateThread implements Runnable {
             }
             try {
                 log.info("start calculate for examId=" + examId + ", subjectCode=" + subjectCode);
-                // 删除原有统计数据
-                reportService.deleteData(examId, subjectCode);
-                context = new ReportContext(exam);
-                long count = 0;
-                long totalCount = studentService.countByExamIdAndSubjectCode(examId, subjectCode);
                 int pageNumber = 1;
                 int pageSize = 1000;
-                List<ExamStudent> list = studentService
-                        .findByExamIdAndSubjectCode(examId, subjectCode, pageNumber, pageSize);
+                List<ExamStudent> list = studentService.findByExamIdAndSubjectCode(examId, subjectCode, pageNumber,
+                        pageSize);
                 while (list != null && list.size() > 0) {
                     for (ExamStudent student : list) {
-                        // 先统分
                         calculate(student);
-                        // 后统计
-                        statistic(student);
-                        // 累加计数
-                        count++;
-                    }
-                    // 修正进度百分比
-                    double progress = count * 100.0 / totalCount;
-                    if (progress == 100 && count < totalCount) {
-                        progress = 99;
-                    } else if (progress == 0 && count > 0) {
-                        progress = 1;
                     }
-                    // TODO - 更新进度百分比
                     pageNumber++;
-                    list = studentService.findByExamId(examId, pageNumber, pageSize);
+                    list = studentService.findByExamIdAndSubjectCode(examId, subjectCode, pageNumber, pageSize);
                 }
-                // 结束统计
-                context.save();
-                // TODO - 统分结束修改标记
+                examService.updateObjectiveStatus(examId, ObjectiveStatus.FINISH);
             } catch (Exception e) {
                 log.error("calculate exception for examId=" + examId + ", subjectCode=" + subjectCode, e);
             } finally {
@@ -126,6 +108,9 @@ public class ScoreCalculateThread implements Runnable {
                 log.info("finish calculate for examId=" + examId + ", subjectCode=" + subjectCode);
             }
         }
+        if (examLock) {
+            lockService.unlock(LockType.SCORE_CALCULATE, examId);
+        }
     }
 
     private void calculate(ExamStudent student) {
@@ -135,8 +120,8 @@ public class ScoreCalculateThread implements Runnable {
         }
         try {
             ScoreCalculateUtil util = ScoreCalculateUtil.instance(student);
-            ScoreInfo info = util
-                    .calculate(findQuestionList(student.getSubjectCode(), student.getPaperType(), true), null);
+            ScoreInfo info = util.calculate(findQuestionList(student.getSubjectCode(), student.getPaperType(), true),
+                    null);
 
             student.setObjectiveScore(info.getObjectiveScore());
             student.setScoreList(info.getScoreList(), true);
@@ -144,26 +129,20 @@ public class ScoreCalculateThread implements Runnable {
             studentService.updateObjectiveScore(student.getId(), student.getObjectiveScore(),
                     student.getObjectiveScoreList());
             // 增加主观题总分统计
-            // markService.scoreCalculate(student, findMarkGroup(student.getSubjectCode()));
+            // markService.scoreCalculate(student,
+            // findMarkGroup(student.getSubjectCode()));
         } catch (Exception e) {
             log.error("calculate error for studentId=" + student.getId(), e);
         }
     }
 
-    private void statistic(ExamStudent student) {
-        student.setSubject(findExamSubject(student.getSubjectCode()));
-        student.setObjectiveQuestionList(findQuestionList(student.getSubjectCode(), student.getPaperType(), true));
-        student.setSubjectiveQuestionList(findQuestionList(student.getSubjectCode(), student.getPaperType(), false));
-        context.process(student);
-    }
-
     private List<ExamQuestion> findQuestionList(String subjectCode, String paperType, boolean objective) {
         if (objective) {
             String key = subjectCode + "_" + StringUtils.trimToEmpty(paperType);
             List<ExamQuestion> list = objectiveMap.get(key);
             if (list == null) {
-                list = questionService
-                        .findByExamAndSubjectAndObjectiveAndPaperType(examId, subjectCode, true, paperType);
+                list = questionService.findByExamAndSubjectAndObjectiveAndPaperType(examId, subjectCode, true,
+                        paperType);
                 objectiveMap.put(key, list);
             }
             return list;
@@ -177,21 +156,12 @@ public class ScoreCalculateThread implements Runnable {
         }
     }
 
-    private ExamSubject findExamSubject(String subjectCode) {
-        ExamSubject subject = subjectMap.get(subjectCode);
-        if (subject == null) {
-            subject = subjectService.find(examId, subjectCode);
-            subjectMap.put(subjectCode, subject);
-        }
-        return subject;
-    }
-
-    private List<MarkGroup> findMarkGroup(String subjectCode) {
-        List<MarkGroup> list = groupMap.get(subjectCode);
-        if (list == null) {
-            list = groupService.findByExamAndSubject(examId, subjectCode);
-            groupMap.put(subjectCode, list);
-        }
-        return list;
-    }
+    // private List<MarkGroup> findMarkGroup(String subjectCode) {
+    // List<MarkGroup> list = groupMap.get(subjectCode);
+    // if (list == null) {
+    // list = groupService.findByExamAndSubject(examId, subjectCode);
+    // groupMap.put(subjectCode, list);
+    // }
+    // return list;
+    // }
 }

+ 160 - 0
stmms-web/src/main/java/cn/com/qmth/stmms/admin/thread/ScoreReportThread.java

@@ -0,0 +1,160 @@
+package cn.com.qmth.stmms.admin.thread;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.commons.lang.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+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.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.ExamSubjectService;
+import cn.com.qmth.stmms.biz.lock.LockService;
+import cn.com.qmth.stmms.biz.report.service.ReportService;
+import cn.com.qmth.stmms.biz.report.utils.ReportContext;
+import cn.com.qmth.stmms.common.enums.ExamStatus;
+import cn.com.qmth.stmms.common.enums.LockType;
+
+public class ScoreReportThread implements Runnable {
+
+    protected static Logger log = LoggerFactory.getLogger(ScoreReportThread.class);
+
+    private ExamStudentService studentService;
+
+    private ExamQuestionService questionService;
+
+    private int examId;
+
+    private Set<String> subjectCodeSet;
+
+    private LockService lockService;
+
+    private ReportService reportService;
+
+    private Map<String, List<ExamQuestion>> objectiveMap;
+
+    private Map<String, List<ExamQuestion>> subjectiveMap;
+
+    private Map<String, ExamSubject> subjectMap;
+
+    private ExamSubjectService subjectService;
+
+    private ExamService examService;
+
+    private ReportContext context;
+
+    private boolean examLock;
+
+    public ScoreReportThread(int examId, Set<String> subjectCodeSet, LockService lockService,
+            ExamStudentService studentService, ExamQuestionService questionService, ReportService reportService,
+            ExamService examService, ExamSubjectService subjectService, boolean examLock) {
+        this.examId = examId;
+        this.subjectCodeSet = subjectCodeSet != null ? subjectCodeSet : new HashSet<>();
+        this.lockService = lockService;
+        this.studentService = studentService;
+        this.questionService = questionService;
+        this.reportService = reportService;
+        this.examService = examService;
+        this.subjectService = subjectService;
+        this.examLock = examLock;
+        this.objectiveMap = new HashMap<>();
+        this.subjectiveMap = new HashMap<>();
+        this.subjectMap = new HashMap<>();
+    }
+
+    @Override
+    public void run() {
+        // 获取考试信息并判断状态
+        Exam exam = examService.findById(examId);
+        if (exam == null || exam.getStatus() != ExamStatus.START) {
+            log.info("report exception for examId=" + examId + ", exam is null or status error");
+            return;
+        }
+        log.info("start report for examId=" + examId + ", subjectCode count=" + subjectCodeSet.size());
+
+        if (examLock) {
+            lockService.trylock(LockType.SCORE_CALCULATE, examId);
+        }
+        for (String subjectCode : subjectCodeSet) {
+            // 尝试上锁,失败直接跳过
+            if (!lockService.trylock(LockType.SCORE_CALCULATE, examId, subjectCode)) {
+                log.warn("report locked for examId=" + examId + ", subjectCode=" + subjectCode);
+                continue;
+            }
+            try {
+                log.info("start report for examId=" + examId + ", subjectCode=" + subjectCode);
+                // 删除原有统计数据
+                reportService.deleteData(examId, subjectCode);
+                context = new ReportContext(exam);
+                int pageNumber = 1;
+                int pageSize = 1000;
+                List<ExamStudent> list = studentService.findByExamIdAndSubjectCode(examId, subjectCode, pageNumber,
+                        pageSize);
+                while (list != null && list.size() > 0) {
+                    for (ExamStudent student : list) {
+                        // 统计
+                        statistic(student);
+                    }
+                    pageNumber++;
+                    list = studentService.findByExamIdAndSubjectCode(examId, subjectCode, pageNumber, pageSize);
+                }
+                // 结束统计
+                context.save();
+            } catch (Exception e) {
+                log.error("report exception for examId=" + examId + ", subjectCode=" + subjectCode, e);
+            } finally {
+                lockService.unlock(LockType.SCORE_CALCULATE, examId, subjectCode);
+                log.info("finish report for examId=" + examId + ", subjectCode=" + subjectCode);
+            }
+        }
+        if (examLock) {
+            lockService.unlock(LockType.SCORE_CALCULATE, examId);
+        }
+    }
+
+    private void statistic(ExamStudent student) {
+        student.setSubject(findExamSubject(student.getSubjectCode()));
+        student.setObjectiveQuestionList(findQuestionList(student.getSubjectCode(), student.getPaperType(), true));
+        student.setSubjectiveQuestionList(findQuestionList(student.getSubjectCode(), student.getPaperType(), false));
+        context.process(student);
+    }
+
+    private List<ExamQuestion> findQuestionList(String subjectCode, String paperType, boolean objective) {
+        if (objective) {
+            String key = subjectCode + "_" + StringUtils.trimToEmpty(paperType);
+            List<ExamQuestion> list = objectiveMap.get(key);
+            if (list == null) {
+                list = questionService.findByExamAndSubjectAndObjectiveAndPaperType(examId, subjectCode, true,
+                        paperType);
+                objectiveMap.put(key, list);
+            }
+            return list;
+        } else {
+            List<ExamQuestion> list = subjectiveMap.get(subjectCode);
+            if (list == null) {
+                list = questionService.findByExamAndSubjectAndObjective(examId, subjectCode, false);
+                subjectiveMap.put(subjectCode, list);
+            }
+            return list;
+        }
+    }
+
+    private ExamSubject findExamSubject(String subjectCode) {
+        ExamSubject subject = subjectMap.get(subjectCode);
+        if (subject == null) {
+            subject = subjectService.find(examId, subjectCode);
+            subjectMap.put(subjectCode, subject);
+        }
+        return subject;
+    }
+
+}

+ 0 - 10
stmms-web/src/main/java/cn/com/qmth/stmms/admin/vo/SubjectLibraryVO.java

@@ -10,8 +10,6 @@ public class SubjectLibraryVO {
 
     private long groupCount;
 
-    private boolean locked;
-
     private String percent;
 
     public ExamSubject getSubject() {
@@ -38,14 +36,6 @@ public class SubjectLibraryVO {
         this.groupCount = groupCount;
     }
 
-    public boolean isLocked() {
-        return locked;
-    }
-
-    public void setLocked(boolean locked) {
-        this.locked = locked;
-    }
-
     public String getPercent() {
         return percent;
     }

+ 0 - 2
stmms-web/src/main/java/cn/com/qmth/stmms/mark/MarkController.java

@@ -287,7 +287,6 @@ public class MarkController extends BaseController {
 
             query.setMarkerId(0);
             query.addStatus(LibraryStatus.MARKED);
-            query.addStatus(LibraryStatus.INSPECTED);
             query.addStatus(LibraryStatus.ARBITRATED);
             markedCount = libraryService.countByQuery(query);
 
@@ -455,7 +454,6 @@ public class MarkController extends BaseController {
             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);

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

@@ -130,10 +130,11 @@
                                         <li><a href="${ctx}/admin/user/list" target="mainFrame"><i class="icon-user"></i><span data-i18n-text="index.user">用户管理</span></a></li>
                                         <li><a href="${ctx}/admin/exam/list" target="mainFrame"><i class="icon-th-list"></i><span data-i18n-text="index.exam">考试管理</span></a></li>
                                         <li><a href="${ctx}/admin/exam/student" target="mainFrame"><i class="icon-user"></i><span data-i18n-text="index.student">考生管理</span></a></li>
-                                        <li><a href="${ctx}/admin/exam/paper" target="mainFrame"><i class="icon-book"></i><span data-i18n-text="index.paper">试卷管理</span></a></li>
+                                        <li><a href="${ctx}/admin/exam/paper" target="mainFrame"><i class="icon-book"></i><span data-i18n-text="index.paper">科目管理</span></a></li>
                                         <li><a href="${ctx}/admin/exam/scan" target="mainFrame"><i class="icon-print"></i><span data-i18n-text="index.scan">扫描进度</span></a></li>
                                         <li><a href="${ctx}/admin/exam/mark" target="mainFrame"><i class="icon-pencil"></i><span data-i18n-text="index.mark">评卷管理</span></a></li>
                                         <li><a href="${ctx}/admin/exam/score" target="mainFrame"><i class="icon-search"></i><span data-i18n-text="index.score">成绩查询</span></a></li>
+                                        <li><a href="${ctx}/admin/exam/inspected" target="mainFrame"><i class="icon-flag"></i><span data-i18n-text="index.inspected">成绩复核</span></a></li>
                                         <li><a href="${ctx}/admin/exam/problem/history" target="mainFrame"><i class="icon-tag"></i><span data-i18n-text="index.problem">问题试卷</span></a></li>
                                         <li><a href="${ctx}/admin/exam/reportSubject" target="mainFrame"><i class="icon-signal"></i><span data-i18n-text="index.report.total">总量分析</span></a></li>
                                         <li><a href="${ctx}/admin/exam/reportSubjectCollege" target="mainFrame"><i class="icon-asterisk"></i><span data-i18n-text="index.report.subject">科目分析</span></a></li>
@@ -144,6 +145,7 @@
                                     <c:if test="${web_user.subjectHeader==true}">
                                         <li><a href="${ctx}/admin/exam/mark" target="mainFrame"><i class="icon-pencil"></i><span data-i18n-text="index.mark">评卷管理</span></a></li>
                                         <li><a href="${ctx}/admin/exam/score" target="mainFrame"><i class="icon-search"></i><span data-i18n-text="index.score">成绩查询</span></a></li>
+                                        <li><a href="${ctx}/admin/exam/inspected" target="mainFrame"><i class="icon-flag"></i><span data-i18n-text="index.inspected">成绩复核</span></a></li>
                                         <li><a href="${ctx}/admin/exam/problem/history" target="mainFrame"><i class="icon-tag"></i><span data-i18n-text="index.problem">问题试卷</span></a></li>
                                         <li><a href="${ctx}/admin/exam/reportSubject" target="mainFrame"><i class="icon-signal"></i><span data-i18n-text="index.report.total">总量分析</span></a></li>
                                         <li><a href="${ctx}/admin/exam/reportSubjectCollege" target="mainFrame"><i class="icon-asterisk"></i><span data-i18n-text="index.report.subject">科目分析</span></a></li>

+ 0 - 14
stmms-web/src/main/webapp/WEB-INF/views/modules/exam/markInfo.jsp

@@ -56,9 +56,6 @@
 			</div>
 			&nbsp;
 			<input id="btnProgress" class="btn" type="button" value="总进度:${percent}%"/>
-		<c:if test="${web_user.schoolAdmin}">
-            <a href="${ctx}/admin/exam/score/calculate" class="btn">重新统分</a>
-        </c:if>
 		</div>
 	</form>
 	<tags:message content="${message}"/>
@@ -70,8 +67,6 @@
 				<th>主观总分</th>
 				<th>分组总数</th>
 				<th>完成进度</th>
-				<th>状态</th>
-				<th>操作</th>
 			</tr>
 		</thead>
 		<tbody>
@@ -86,15 +81,6 @@
 					${result.groupCount}</a>
 				</td>
 				<td>${result.percent}</td>
-				<td>
-					<c:if test="${result.locked}">正在统分</c:if>
-					<c:if test="${!result.locked}">正常</c:if>
-				</td>
-				<td>
-					<c:if test="${!result.locked}">
-					<a href="${ctx}/admin/exam/mark/calculate?subjectCode=${result.subject.code}">统分</a>
-					</c:if>
-				</td>
 			</tr>
 		</c:forEach>
 		</tbody>

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

@@ -90,6 +90,16 @@
                 <li><a href="${ctx}/admin/exam/paper/export?objective=false">主观题</a></li>
             </ul>
         </div>
+        <c:if test="${!examLock}">
+		&nbsp;
+		<a href="${ctx}/admin/exam/paper/calculate" class="btn">客观题统分</a>
+		&nbsp;
+		<a href="${ctx}/admin/exam/paper/report" class="btn">分析计算</a>
+        </c:if>
+        <c:if test="${examLock}"
+        >&nbsp;
+		<a href="#" class="btn" disabled="disabled" >正在计算</a>
+		</c:if>
     </div>
 </form>
 <tags:message content="${message}"/>
@@ -104,6 +114,7 @@
         <th>客观总分</th>
         <th>主观总分</th>
         <th>试卷总分</th>
+        <th>状态</th>
         <th>操作</th>
     </tr>
     </thead>
@@ -129,9 +140,14 @@
             <td>${subject.subjectiveScore}</td>
             <td>${subject.totalScore}</td>
             <td>
-                <c:if test="${examType!='MULTI_MEDIA'}">
-                    <a href="${ctx}/admin/exam/subject/edit?code=${subject.code}">编辑</a>
-                </c:if>
+				<c:if test="${examLock || subject.loecked}">正在计算</c:if>
+				<c:if test="${!examLock && !subject.loecked}">正常</c:if>
+			</td>
+            <td>
+                <c:if test="${!examLock && !subject.loecked}">
+	                <a href="${ctx}/admin/exam/subject/edit?code=${subject.code}">编辑</a>
+					<a href="${ctx}/admin/exam/paper/report?subjectCode=${result.subject.code}">分析计算</a>
+				</c:if>
             </td>
         </tr>
     </c:forEach>

+ 1 - 1
stmms-web/src/main/webapp/WEB-INF/views/modules/report/reportSubject.jsp

@@ -3,7 +3,7 @@
 <%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %> 
 <html>
 <head>
-	<title>成绩分析</title>
+	<title data-i18n-text="report.subject">总量统计</title>
 	<meta name="decorator" content="default"/>
 	<%@include file="/WEB-INF/views/include/head.jsp" %>
 	<%@include file="/WEB-INF/views/include/dialog.jsp" %>

+ 2 - 1
stmms-web/src/main/webapp/static/i18n/messages.properties

@@ -143,11 +143,12 @@ mark.json.question.number=\u9898\u53f7\uff1a
 index.user=\u7528\u6237\u7ba1\u7406
 index.exam=\u8003\u8bd5\u7ba1\u7406
 index.student=\u8003\u751f\u7ba1\u7406
-index.paper=\u8bd5\u5377\u7ba1\u7406
+index.paper=\u79d1\u76ee\u7ba1\u7406
 index.scan=\u626b\u63cf\u8fdb\u5ea6
 index.mark=\u8bc4\u5377\u7ba1\u7406
 index.score=\u6210\u7ee9\u67e5\u8be2
 index.problem=\u95ee\u9898\u8bd5\u5377
+index.inspected=\u6210\u7ee9\u590d\u6838
 index.report.total=\u603b\u91cf\u5206\u6790
 index.report.subject=\u79d1\u76ee\u5206\u6790
 index.check=\u6570\u636e\u68c0\u67e5

+ 1 - 0
stmms-web/src/main/webapp/static/i18n/messages_en.properties

@@ -147,6 +147,7 @@ index.paper=Subject
 index.scan=Scan Progress
 index.mark=Mark
 index.score=Score
+index.inspected=Score inspected
 index.problem=Problem Paper
 index.report.total=Total analysis
 index.report.subject=Subject analysis

+ 2 - 1
stmms-web/src/main/webapp/static/i18n/messages_ja.properties

@@ -143,10 +143,11 @@ mark.json.question.number=\u8a66\u9a13\u554f\u984c\u756a\u53f7\uff1a
 index.user=\u30e6\u30fc\u30b6\u30fc\u7ba1\u7406
 index.exam=\u8a66\u9a13\u7ba1\u7406
 index.student=\u53d7\u9a13\u751f\u7ba1\u7406
-index.paper=\u8a66\u9a13\u7528\u7d19\u7ba1\u7406
+index.paper=\u79d1\u76ee\u7ba1\u7406
 index.scan=\u30b9\u30ad\u30e3\u30f3\u9032\u5ea6
 index.mark=\u30de\u30fc\u30ad\u30f3\u30b0\u7ba1\u7406
 index.score=\u6210\u7e3e\u30af\u30a8\u30ea\u30fc
+index.inspected=\u6210\u7e3e\u590d\u6838
 index.problem=\u554f\u984c\u3042\u308b\u8a66\u9a13\u7528\u7d19
 index.report.total=\u96c6\u8a08\u5206\u6790
 index.report.subject=\u79d1\u76ee\u5225\u5206\u6790

+ 2 - 1
stmms-web/src/main/webapp/static/i18n/messages_zh.properties

@@ -143,10 +143,11 @@ mark.json.question.number=\u9898\u53f7\uff1a
 index.user=\u7528\u6237\u7ba1\u7406
 index.exam=\u8003\u8bd5\u7ba1\u7406
 index.student=\u8003\u751f\u7ba1\u7406
-index.paper=\u8bd5\u5377\u7ba1\u7406
+index.paper=\u79d1\u76ee\u7ba1\u7406
 index.scan=\u626b\u63cf\u8fdb\u5ea6
 index.mark=\u8bc4\u5377\u7ba1\u7406
 index.score=\u6210\u7ee9\u67e5\u8be2
+index.inspected=\u6210\u7ee9\u590d\u6838
 index.problem=\u95ee\u9898\u8bd5\u5377
 index.report.total=\u603b\u91cf\u5206\u6790
 index.report.subject=\u79d1\u76ee\u5206\u6790