Browse Source

新增选做题和试评

ting.yin 3 years ago
parent
commit
8fbf04914f
71 changed files with 1581 additions and 754 deletions
  1. 1 1
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/dao/ExamStudentDao.java
  2. 7 2
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/dao/ExamSubjectDao.java
  3. 8 8
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/dao/MarkGroupDao.java
  4. 26 0
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/dao/SelectiveGroupDao.java
  5. 11 0
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/model/ExamQuestion.java
  6. 31 6
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/model/ExamSubject.java
  7. 18 22
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/model/MarkGroup.java
  8. 79 0
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/model/SelectiveGroup.java
  9. 85 0
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/model/SelectiveGroupPK.java
  10. 0 1
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/model/SubjectiveScore.java
  11. 4 0
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/service/ExamStudentService.java
  12. 2 0
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/service/ExamSubjectService.java
  13. 2 2
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/service/InspectedService.java
  14. 2 4
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/service/MarkGroupService.java
  15. 19 0
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/service/SelectiveGroupService.java
  16. 7 0
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/service/impl/ExamQuestionServiceImpl.java
  17. 28 5
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/service/impl/ExamStudentServiceImpl.java
  18. 6 0
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/service/impl/ExamSubjectServiceImpl.java
  19. 59 36
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/service/impl/InspectedServiceImpl.java
  20. 5 11
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/service/impl/MarkGroupServiceImpl.java
  21. 48 0
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/service/impl/SelectiveGroupServiceImpl.java
  22. 24 11
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/file/service/impl/FileServiceImpl.java
  23. 0 49
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/mark/dao/TrialHistoryDao.java
  24. 28 6
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/mark/dao/TrialLibraryDao.java
  25. 1 1
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/mark/dao/TrialTagDao.java
  26. 1 1
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/mark/dao/TrialTrackDao.java
  27. 14 4
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/mark/model/MarkResult.java
  28. 3 3
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/mark/model/SpecialTagDTO.java
  29. 8 8
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/mark/model/TrackDTO.java
  30. 0 188
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/mark/model/TrialHistory.java
  31. 0 66
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/mark/model/TrialHistoryPK.java
  32. 75 8
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/mark/model/TrialLibrary.java
  33. 20 0
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/mark/query/ArbitrateHistorySearchQuery.java
  34. 10 0
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/mark/query/MarkLibrarySearchQuery.java
  35. 7 0
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/mark/service/Impl/ArbitrateHistoryServiceImpl.java
  36. 19 4
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/mark/service/Impl/MarkCronService.java
  37. 11 0
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/mark/service/Impl/MarkLibraryServiceImpl.java
  38. 177 72
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/mark/service/Impl/MarkServiceImpl.java
  39. 25 13
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/mark/service/Impl/TaskServiceImpl.java
  40. 36 57
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/mark/service/Impl/TrialServiceImpl.java
  41. 15 5
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/mark/service/MarkService.java
  42. 1 2
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/mark/service/TaskService.java
  43. 9 15
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/mark/service/TrialService.java
  44. 2 2
      stmms-common/src/main/java/cn/com/qmth/stmms/common/enums/HistoryStatus.java
  45. 1 1
      stmms-common/src/main/java/cn/com/qmth/stmms/common/enums/LibraryStatus.java
  46. 1 1
      stmms-common/src/main/java/cn/com/qmth/stmms/common/enums/SubjectiveStatus.java
  47. 12 4
      stmms-web/src/main/java/cn/com/qmth/stmms/admin/dto/ExamStudentDTO.java
  48. 35 5
      stmms-web/src/main/java/cn/com/qmth/stmms/admin/dto/SubjectQuestionDTO.java
  49. 12 1
      stmms-web/src/main/java/cn/com/qmth/stmms/admin/dto/SubjectiveQuestionDTO.java
  50. 11 6
      stmms-web/src/main/java/cn/com/qmth/stmms/admin/exam/ArbitrateController.java
  51. 12 8
      stmms-web/src/main/java/cn/com/qmth/stmms/admin/exam/InspectedController.java
  52. 99 6
      stmms-web/src/main/java/cn/com/qmth/stmms/admin/exam/MarkGroupController.java
  53. 4 8
      stmms-web/src/main/java/cn/com/qmth/stmms/admin/exam/MarkQualityController.java
  54. 2 0
      stmms-web/src/main/java/cn/com/qmth/stmms/admin/exam/PaperController.java
  55. 15 16
      stmms-web/src/main/java/cn/com/qmth/stmms/admin/exam/ScoreController.java
  56. 123 0
      stmms-web/src/main/java/cn/com/qmth/stmms/admin/exam/SelectiveGroupController.java
  57. 41 31
      stmms-web/src/main/java/cn/com/qmth/stmms/admin/exam/TrialController.java
  58. 1 1
      stmms-web/src/main/java/cn/com/qmth/stmms/admin/thread/OnlineExamThread.java
  59. 4 4
      stmms-web/src/main/java/cn/com/qmth/stmms/admin/utils/ExportStudentExcel.java
  60. 11 12
      stmms-web/src/main/java/cn/com/qmth/stmms/mark/MarkController.java
  61. 5 0
      stmms-web/src/main/webapp/WEB-INF/views/modules/exam/arbitrateList.jsp
  62. 4 0
      stmms-web/src/main/webapp/WEB-INF/views/modules/exam/groupAdd.jsp
  63. 2 2
      stmms-web/src/main/webapp/WEB-INF/views/modules/exam/groupEditFull.jsp
  64. 2 2
      stmms-web/src/main/webapp/WEB-INF/views/modules/exam/groupEditSimple.jsp
  65. 136 1
      stmms-web/src/main/webapp/WEB-INF/views/modules/exam/groupList.jsp
  66. 12 4
      stmms-web/src/main/webapp/WEB-INF/views/modules/exam/inspectedList.jsp
  67. 7 1
      stmms-web/src/main/webapp/WEB-INF/views/modules/exam/libraryList.jsp
  68. 1 0
      stmms-web/src/main/webapp/WEB-INF/views/modules/exam/paperList.jsp
  69. 1 1
      stmms-web/src/main/webapp/WEB-INF/views/modules/exam/scoreList.jsp
  70. 70 0
      stmms-web/src/main/webapp/WEB-INF/views/modules/exam/selectiveList.jsp
  71. 23 26
      stmms-web/src/main/webapp/sql/stmms_ft.sql

+ 1 - 1
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/dao/ExamStudentDao.java

@@ -152,7 +152,7 @@ public interface ExamStudentDao extends PagingAndSortingRepository<ExamStudent,
             Date minUploadTime, Pageable page);
 
     @Query("select s from ExamStudent s where s.examId=?1 and s.subjectCode=?2 and s.upload=true and s.absent=false and s.breach=false "
-            + "and not exists (select l.id from TrialLibrary l where l.studentId=s.id and l.groupNumber=?3)")
+            + "and s.subjectiveStatus='TRIAL' and not exists (select l.id from TrialLibrary l where l.studentId=s.id and l.groupNumber=?3)")
     public List<ExamStudent> findUnTrialStudent(Integer examId, String subjectCode, Integer groupNumber, Pageable page);
 
     @Query("select s from ExamStudent s where s.examId=?1 and s.subjectCode=?2 and s.upload=true and (s.absent=true or s.breach=true) and "

+ 7 - 2
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/dao/ExamSubjectDao.java

@@ -2,6 +2,7 @@ package cn.com.qmth.stmms.biz.exam.dao;
 
 import cn.com.qmth.stmms.biz.exam.model.ExamSubject;
 import cn.com.qmth.stmms.biz.exam.model.ExamSubjectPK;
+
 import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
 import org.springframework.data.jpa.repository.Modifying;
 import org.springframework.data.jpa.repository.Query;
@@ -10,8 +11,8 @@ import org.springframework.data.repository.PagingAndSortingRepository;
 import java.util.List;
 import java.util.Set;
 
-public interface ExamSubjectDao
-        extends PagingAndSortingRepository<ExamSubject, ExamSubjectPK>, JpaSpecificationExecutor<ExamSubject> {
+public interface ExamSubjectDao extends PagingAndSortingRepository<ExamSubject, ExamSubjectPK>,
+        JpaSpecificationExecutor<ExamSubject> {
 
     @Query("select s from ExamSubject s where s.pk.examId=?1")
     public List<ExamSubject> findByExamId(int examId);
@@ -65,4 +66,8 @@ public interface ExamSubjectDao
     @Query("update ExamSubject s set s.sliceConfig=?3 where s.pk.examId=?1 and s.pk.code=?2")
     public void updateSliceConfig(Integer examId, String subjectCode, String configString);
 
+    @Modifying
+    @Query("update ExamSubject s set s.trialCount=?3 where s.pk.examId=?1 and s.pk.code=?2")
+    public void updateTrialCount(int examId, String subjectCode, int trialCount);
+
 }

+ 8 - 8
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/dao/MarkGroupDao.java

@@ -6,6 +6,7 @@ import cn.com.qmth.stmms.common.enums.MarkMode;
 import cn.com.qmth.stmms.common.enums.MarkStatus;
 import cn.com.qmth.stmms.common.enums.ScorePolicy;
 import cn.com.qmth.stmms.common.enums.ThirdPolicy;
+
 import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
 import org.springframework.data.jpa.repository.Modifying;
 import org.springframework.data.jpa.repository.Query;
@@ -60,10 +61,6 @@ public interface MarkGroupDao extends PagingAndSortingRepository<MarkGroup, Mark
     @Query("select count(q) from MarkGroup q where q.pk.examId=?1 and q.pk.subjectCode=?2")
     long countByExamIdAndSubjectCode(Integer examId, String subjectCode);
 
-    @Query("select count(q) from MarkGroup q where q.pk.examId=?1 and q.pk.subjectCode=?2 and q.pk.number=?3 "
-            + "and q.status=?4 and q.trialCount>q.libraryCount")
-    long countByStatusAndTrailCount(Integer examId, String subjectCode, Integer number, MarkStatus status);
-
     @Query("select sum(g.totalScore) from MarkGroup g where g.pk.examId=?1 and g.pk.subjectCode=?2")
     Double sumTotalScore(Integer examId, String subjectCode);
 
@@ -112,10 +109,6 @@ public interface MarkGroupDao extends PagingAndSortingRepository<MarkGroup, Mark
     @Query("update MarkGroup g set g.arbitrateThreshold=?4 where g.pk.examId=?1 and g.pk.subjectCode=?2 and g.pk.number=?3")
     void updateArbitrateThreshold(Integer examId, String subjectCode, Integer number, Double arbitrateThreshold);
 
-    @Modifying(clearAutomatically = true)
-    @Query("update MarkGroup g set g.trialCount=?4 where g.pk.examId=?1 and g.pk.subjectCode=?2 and g.pk.number=?3")
-    void updateTrialCount(Integer examId, String subjectCode, Integer number, Integer trialCount);
-
     @Modifying(clearAutomatically = true)
     @Query("update MarkGroup g set g.sheetView=?4 where g.pk.examId=?1 and g.pk.subjectCode=?2 and g.pk.number=?3")
     void updateSheetView(Integer examId, String subjectCode, Integer number, boolean sheetView);
@@ -134,4 +127,11 @@ public interface MarkGroupDao extends PagingAndSortingRepository<MarkGroup, Mark
     @Query("update MarkGroup g set g.thirdPolicy=?4 where g.pk.examId=?1 and g.pk.subjectCode=?2 and g.pk.number=?3")
     void updateThirdPolicy(Integer examId, String subjectCode, Integer number, ThirdPolicy third);
 
+    @Modifying(clearAutomatically = true)
+    @Query("update MarkGroup g set g.selective=?4 where g.pk.examId=?1 and g.pk.subjectCode=?2 and g.pk.number=?3")
+    void updateSelective(Integer examId, String subjectCode, Integer number, boolean selective);
+
+    @Query("select q from MarkGroup q where q.pk.examId=?1 and q.pk.subjectCode=?2 and q.selective=?3 order by q.pk.number")
+    List<MarkGroup> findByExamAndSubjectAndSelective(Integer examId, String subjectCode, boolean selective);
+
 }

+ 26 - 0
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/dao/SelectiveGroupDao.java

@@ -0,0 +1,26 @@
+package cn.com.qmth.stmms.biz.exam.dao;
+
+import java.util.List;
+
+import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
+import org.springframework.data.jpa.repository.Modifying;
+import org.springframework.data.jpa.repository.Query;
+import org.springframework.data.repository.PagingAndSortingRepository;
+
+import cn.com.qmth.stmms.biz.exam.model.MarkGroupPK;
+import cn.com.qmth.stmms.biz.exam.model.SelectiveGroup;
+
+public interface SelectiveGroupDao extends PagingAndSortingRepository<SelectiveGroup, MarkGroupPK>,
+        JpaSpecificationExecutor<SelectiveGroup> {
+
+    @Query("select q from SelectiveGroup q where q.pk.examId=?1 and q.pk.subjectCode=?2 and q.pk.mainNumber=?3")
+    SelectiveGroup findOne(Integer examId, String subjectCode, Integer mainNumber);
+
+    @Modifying(clearAutomatically = true)
+    @Query("delete from SelectiveGroup q where q.pk.examId=?1 and q.pk.subjectCode=?2")
+    void deleteByExamIdAndSubjectCode(Integer examId, String subjectCode);
+
+    @Query("select q from SelectiveGroup q where q.pk.examId=?1 and q.pk.subjectCode=?2 order by q.pk.mainNumber")
+    List<SelectiveGroup> findByExamIdAndSubjectCode(Integer examId, String subjectCode);
+
+}

+ 11 - 0
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/model/ExamQuestion.java

@@ -78,6 +78,9 @@ public class ExamQuestion implements Serializable {
     @Transient
     private Integer trialCount;
 
+    @Transient
+    private boolean selective;
+
     public Integer getId() {
         return id;
     }
@@ -276,4 +279,12 @@ public class ExamQuestion implements Serializable {
         this.objectivePolicy = objectivePolicy;
     }
 
+    public boolean isSelective() {
+        return selective;
+    }
+
+    public void setSelective(boolean selective) {
+        this.selective = selective;
+    }
+
 }

+ 31 - 6
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/model/ExamSubject.java

@@ -1,14 +1,23 @@
 package cn.com.qmth.stmms.biz.exam.model;
 
-import cn.com.qmth.stmms.biz.file.enums.FormatType;
-import cn.com.qmth.stmms.biz.file.service.FileService;
-import cn.com.qmth.stmms.biz.mark.model.PictureConfigItem;
+import java.io.Serializable;
+import java.util.List;
+
+import javax.persistence.Column;
+import javax.persistence.EmbeddedId;
+import javax.persistence.Entity;
+import javax.persistence.EnumType;
+import javax.persistence.Enumerated;
+import javax.persistence.Table;
+import javax.persistence.Transient;
+
 import net.sf.json.JSONObject;
+
 import org.apache.commons.lang.StringUtils;
 
-import javax.persistence.*;
-import java.io.Serializable;
-import java.util.List;
+import cn.com.qmth.stmms.biz.file.enums.FormatType;
+import cn.com.qmth.stmms.biz.file.service.FileService;
+import cn.com.qmth.stmms.biz.mark.model.PictureConfigItem;
 
 @Entity
 @Table(name = "eb_exam_subject")
@@ -84,6 +93,12 @@ public class ExamSubject implements Serializable {
      */
     @Column(name = "sas_config", nullable = true)
     private String sasConfig;
+    
+    /**
+     * 试评数量
+     */
+    @Column(name = "trial_count", nullable = true)
+    private Integer trialCount;
 
     /**
      * 大题数量
@@ -343,4 +358,14 @@ public class ExamSubject implements Serializable {
         this.paperType = paperType;
     }
 
+    
+    public Integer getTrialCount() {
+        return trialCount;
+    }
+
+    
+    public void setTrialCount(Integer trialCount) {
+        this.trialCount = trialCount;
+    }
+
 }

+ 18 - 22
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/model/MarkGroup.java

@@ -40,12 +40,6 @@ public class MarkGroup implements Serializable {
     @Column(name = "total_score", nullable = false)
     private Double totalScore;
 
-    /**
-     * 试评数量
-     */
-    @Column(name = "trial_count", nullable = true)
-    private Integer trialCount;
-
     /**
      * 双评比例(0~1)
      */
@@ -114,6 +108,9 @@ public class MarkGroup implements Serializable {
     @Column(name = "left_count")
     private Integer leftCount;
 
+    @Column(name = "is_selective", nullable = false)
+    private boolean selective;
+
     @Transient
     private int currentCount;
 
@@ -150,14 +147,13 @@ public class MarkGroup implements Serializable {
 
     public MarkGroup(Integer examId, String subjectCode, Integer number, List<PictureConfigItem> configList,
             Double totalScore, Double doubleRate, Double arbitrateThreshold, Integer scorePolicy, String markMode,
-            Integer trialCount, boolean sheetView, boolean enableAllZero, Integer thirdPolicy) {
+            Integer trialCount, boolean sheetView, boolean enableAllZero, Integer thirdPolicy, boolean selective) {
         this.pk = new MarkGroupPK();
         this.pk.setExamId(examId);
         this.pk.setNumber(number);
         this.pk.setSubjectCode(subjectCode);
-        this.picList = configList != null && configList.size() > 0 ?
-                StringUtils.join(configList, PictureConfigItem.DB_ITEM_JOINER) :
-                "";
+        this.picList = configList != null && configList.size() > 0 ? StringUtils.join(configList,
+                PictureConfigItem.DB_ITEM_JOINER) : "";
         this.totalScore = totalScore;
         this.libraryCount = 0;
         this.markedCount = 0;
@@ -179,7 +175,6 @@ public class MarkGroup implements Serializable {
         }
         if (trialCount != null && trialCount > 0) {
             this.status = MarkStatus.TRIAL;
-            this.trialCount = trialCount;
         } else {
             this.status = MarkStatus.FORMAL;
         }
@@ -191,6 +186,7 @@ public class MarkGroup implements Serializable {
         } else {
             this.thirdPolicy = ThirdPolicy.DISABLE;
         }
+        this.selective = selective;
     }
 
     public Integer getExamId() {
@@ -226,9 +222,8 @@ public class MarkGroup implements Serializable {
     }
 
     public void setPicList(List<PictureConfigItem> configList) {
-        this.picList = configList != null && configList.size() > 0 ?
-                StringUtils.join(configList, PictureConfigItem.DB_ITEM_JOINER) :
-                "";
+        this.picList = configList != null && configList.size() > 0 ? StringUtils.join(configList,
+                PictureConfigItem.DB_ITEM_JOINER) : "";
     }
 
     public List<PictureConfigItem> getPictureConfigList() {
@@ -389,14 +384,6 @@ public class MarkGroup implements Serializable {
         this.status = status;
     }
 
-    public Integer getTrialCount() {
-        return trialCount;
-    }
-
-    public void setTrialCount(Integer trialCount) {
-        this.trialCount = trialCount;
-    }
-
     public boolean isSheetView() {
         return sheetView;
     }
@@ -444,4 +431,13 @@ public class MarkGroup implements Serializable {
     public void setDeleting(boolean deleting) {
         this.deleting = deleting;
     }
+
+    public boolean isSelective() {
+        return selective;
+    }
+
+    public void setSelective(boolean selective) {
+        this.selective = selective;
+    }
+
 }

+ 79 - 0
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/model/SelectiveGroup.java

@@ -0,0 +1,79 @@
+package cn.com.qmth.stmms.biz.exam.model;
+
+import java.io.Serializable;
+
+import javax.persistence.Column;
+import javax.persistence.EmbeddedId;
+import javax.persistence.Entity;
+import javax.persistence.Table;
+
+@Entity
+@Table(name = "eb_selective_group")
+public class SelectiveGroup implements Serializable {
+
+    private static final long serialVersionUID = 7866856607752769258L;
+
+    @EmbeddedId
+    private SelectiveGroupPK pk;
+
+    @Column(name = "selective_index", nullable = false)
+    private Integer selectiveIndex;
+
+    @Column(name = "selective_count", nullable = false)
+    private Integer selectiveCount;
+
+    public SelectiveGroup() {
+        this.pk = new SelectiveGroupPK();
+    }
+
+    public SelectiveGroup(Integer examId, String subjectCode, Integer mainNumber, Integer selectiveIndex,
+            Integer selectiveCount) {
+        this.pk = new SelectiveGroupPK();
+        this.pk.setExamId(examId);
+        this.pk.setSubjectCode(subjectCode);
+        this.pk.setMainNumber(mainNumber);
+        this.selectiveCount = selectiveCount;
+        this.selectiveIndex = selectiveIndex;
+    }
+
+    public Integer getExamId() {
+        return pk.getExamId();
+    }
+
+    public void setExamId(Integer examId) {
+        pk.setExamId(examId);
+    }
+
+    public String getSubjectCode() {
+        return pk.getSubjectCode();
+    }
+
+    public void setSubjectCode(String subjectCode) {
+        pk.setSubjectCode(subjectCode);
+    }
+
+    public Integer getMainNumber() {
+        return pk.getMainNumber();
+    }
+
+    public void setMainNumber(Integer mainNumber) {
+        pk.setMainNumber(mainNumber);
+    }
+
+    public Integer getSelectiveIndex() {
+        return selectiveIndex;
+    }
+
+    public void setSelectiveIndex(Integer selectiveIndex) {
+        this.selectiveIndex = selectiveIndex;
+    }
+
+    public Integer getSelectiveCount() {
+        return selectiveCount;
+    }
+
+    public void setSelectiveCount(Integer selectiveCount) {
+        this.selectiveCount = selectiveCount;
+    }
+
+}

+ 85 - 0
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/model/SelectiveGroupPK.java

@@ -0,0 +1,85 @@
+package cn.com.qmth.stmms.biz.exam.model;
+
+import java.io.Serializable;
+
+import javax.persistence.Column;
+import javax.persistence.Embeddable;
+
+@Embeddable
+public class SelectiveGroupPK implements Serializable {
+
+    private static final long serialVersionUID = -6741844373808204701L;
+
+    @Column(name = "exam_id", nullable = false)
+    private Integer examId;
+
+    @Column(name = "subject_code", nullable = false, length = 32)
+    private String subjectCode;
+
+    @Column(name = "main_number", nullable = false)
+    private Integer mainNumber;
+
+    public Integer getExamId() {
+        return examId;
+    }
+
+    public void setExamId(Integer examId) {
+        this.examId = examId;
+    }
+
+    public String getSubjectCode() {
+        return subjectCode;
+    }
+
+    public void setSubjectCode(String subjectCode) {
+        this.subjectCode = subjectCode;
+    }
+
+    public Integer getMainNumber() {
+        return mainNumber;
+    }
+
+    public void setMainNumber(Integer mainNumber) {
+        this.mainNumber = mainNumber;
+    }
+
+    @Override
+    public int hashCode() {
+        final int PRIME = 31;
+        int result = 1;
+        result = PRIME * result + ((examId == null) ? 0 : examId.hashCode());
+        result = PRIME * result + ((subjectCode == null) ? 0 : subjectCode.hashCode());
+        result = PRIME * result + ((mainNumber == null) ? 0 : mainNumber.hashCode());
+        return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj)
+            return true;
+        if (obj == null)
+            return false;
+        if (getClass() != obj.getClass())
+            return false;
+        final SelectiveGroupPK other = (SelectiveGroupPK) obj;
+        if (examId == null) {
+            if (other.examId != null)
+                return false;
+        } else if (!examId.equals(other.examId))
+            return false;
+        if (subjectCode == null) {
+            if (other.subjectCode != null)
+                return false;
+        } else if (!subjectCode.equals(other.subjectCode))
+            return false;
+
+        if (mainNumber == null) {
+            if (other.mainNumber != null)
+                return false;
+        } else if (!mainNumber.equals(other.mainNumber))
+            return false;
+
+        return true;
+    }
+
+}

+ 0 - 1
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/model/SubjectiveScore.java

@@ -129,5 +129,4 @@ public class SubjectiveScore implements Serializable {
     public void setMainScore(Double mainScore) {
         this.mainScore = mainScore;
     }
-
 }

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

@@ -144,4 +144,8 @@ public interface ExamStudentService {
             Date inspectTime, Integer inspectorId);
 
     public List<ExamStudent> findByExamIdAndStudentCode(int examId, String studentCode);
+
+    long countByExamIdAndSubjectCodeAndStatus(int examId, String subjectCode, SubjectiveStatus status);
+
+    public ExamStudent randomStudent(Integer examId, String code);
 }

+ 2 - 0
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/service/ExamSubjectService.java

@@ -43,4 +43,6 @@ public interface ExamSubjectService {
 
     void updateSliceConfig(Integer examId, String subjectCode, List<PictureConfigItem> configList);
 
+    void updateTrialCount(int examId, String subjectCode, int trialCount);
+
 }

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

@@ -9,10 +9,10 @@ import java.util.List;
 public interface InspectedService {
 
     List<ExamStudent> findByQuery(ExamStudentSearchQuery query, SubjectiveStatus status, Integer mainNumber,
-            Double mainStartScore, Double mainEndScore, Double questionScore);
+            Double mainStartScore, Double mainEndScore, Double questionScore, boolean unselective);
 
     Integer countByQuery(ExamStudentSearchQuery query, SubjectiveStatus status, Integer mainNumber,
-            Double mainStartScore, Double mainEndScore, Double questionScore);
+            Double mainStartScore, Double mainEndScore, Double questionScore, boolean unselective);
 
     void releaseByUserId(Integer examId, String subjectCode, Integer userId);
 

+ 2 - 4
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/service/MarkGroupService.java

@@ -36,8 +36,6 @@ public interface MarkGroupService {
 
     void updateMarkMode(int examId, String subjectCode, Integer number, MarkMode markMode);
 
-    void updateTrialCount(int examId, String subjectCode, Integer number, Integer trialCount);
-
     void updateSheetView(int examId, String subjectCode, Integer number, boolean sheetView);
 
     void updateEnableAllZero(int examId, String subjectCode, Integer number, boolean enableAllZero);
@@ -51,12 +49,12 @@ public interface MarkGroupService {
 
     List<MarkGroup> findByExamAndSubjectAndStatus(Integer examId, String subjectCode, MarkStatus... status);
 
-    boolean needTrialLibrary(Integer examId, String subjectCode, Integer number);
-
     long countByExamAndStatus(Integer examId, MarkStatus... status);
 
     boolean validateStatus(Integer examId, String subjectCode, Integer number, MarkStatus... status);
 
     int findMaxNumberByExamIdAndSubjectCode(int examId, String subjectCode);
 
+    List<MarkGroup> findByExamAndSubjectAndSelective(Integer examId, String subjectCode, boolean selective);
+
 }

+ 19 - 0
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/service/SelectiveGroupService.java

@@ -0,0 +1,19 @@
+package cn.com.qmth.stmms.biz.exam.service;
+
+import java.util.List;
+
+import cn.com.qmth.stmms.biz.exam.model.SelectiveGroup;
+
+public interface SelectiveGroupService {
+
+    SelectiveGroup save(SelectiveGroup s);
+
+    void save(List<SelectiveGroup> list);
+
+    SelectiveGroup findOne(int examId, String subjectCode, int mainNumber);
+
+    List<SelectiveGroup> findByExamIdAndSubjectCode(int examId, String code);
+
+    void deleteByExamIdAndSubjectCode(int examId, String subjectCode);
+
+}

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

@@ -269,6 +269,13 @@ public class ExamQuestionServiceImpl extends BaseQueryService<ExamQuestion> impl
         for (ExamQuestion q : all) {
             if (!mainNumbers.contains(q.getMainNumber())) {
                 mainNumbers.add(q.getMainNumber());
+                List<ExamQuestion> questions = questionDao.findByExamIdAndSubjectCodeAndObjectiveAndMainNumber(examId,
+                        subjectCode, objective, q.getMainNumber());
+                double totalScore = 0;
+                for (ExamQuestion examQuestion : questions) {
+                    totalScore = totalScore + examQuestion.getTotalScore();
+                }
+                q.setTotalScore(totalScore);
                 list.add(q);
             }
         }

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

@@ -731,13 +731,10 @@ public class ExamStudentServiceImpl extends BaseQueryService<ExamStudent> implem
     public ExamStudent randomUnTrialStudent(Integer examId, String subjectCode, Integer groupNumber) {
         ExamStudentSearchQuery query = new ExamStudentSearchQuery();
         query.setPageNumber(1);
-        query.setPageSize(200);
+        query.setPageSize(1);
         query.setSort(new Sort(Direction.ASC, "uploadTime", "id"));
         List<ExamStudent> list = studentDao.findUnTrialStudent(examId, subjectCode, groupNumber, query);
-        if (list.isEmpty()) {
-            return null;
-        }
-        return list.get(RandomUtils.nextInt(list.size()));
+        return list.isEmpty() ? null : list.get(0);
     }
 
     @Override
@@ -1035,4 +1032,30 @@ public class ExamStudentServiceImpl extends BaseQueryService<ExamStudent> implem
     public List<ExamStudent> findByExamIdAndStudentCode(int examId, String studentCode) {
         return studentDao.findByExamIdAndStudentCode(examId, studentCode);
     }
+
+    @Override
+    public long countByExamIdAndSubjectCodeAndStatus(int examId, String subjectCode, SubjectiveStatus status) {
+        ExamStudentSearchQuery query = new ExamStudentSearchQuery();
+        query.setExamId(examId);
+        query.setSubjectCode(subjectCode);
+        query.addStatus(status);
+        return countByQuery(query);
+    }
+
+    @Override
+    public ExamStudent randomStudent(Integer examId, String code) {
+        ExamStudentSearchQuery query = new ExamStudentSearchQuery();
+        query.setAbsent(false);
+        query.setUpload(true);
+        query.setBreach(false);
+        query.setPageNumber(1);
+        query.setPageSize(200);
+        query.setSort(new Sort(Direction.ASC, "uploadTime", "id"));
+        List<ExamStudent> list = findByQuery(query).getResult();
+        if (list.isEmpty()) {
+            return null;
+        }
+        return list.get(RandomUtils.nextInt(list.size()));
+
+    }
 }

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

@@ -6,6 +6,7 @@ import cn.com.qmth.stmms.biz.exam.model.ExamSubject;
 import cn.com.qmth.stmms.biz.exam.service.ExamSubjectService;
 import cn.com.qmth.stmms.biz.exam.service.query.ExamSubjectSearchQuery;
 import cn.com.qmth.stmms.biz.mark.model.PictureConfigItem;
+
 import org.apache.commons.lang.StringUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.data.domain.Page;
@@ -17,6 +18,7 @@ import javax.persistence.criteria.CriteriaBuilder;
 import javax.persistence.criteria.CriteriaQuery;
 import javax.persistence.criteria.Predicate;
 import javax.persistence.criteria.Root;
+
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Set;
@@ -196,7 +198,11 @@ public class ExamSubjectServiceImpl extends BaseQueryService<ExamSubject> implem
     public void updateSliceConfig(Integer examId, String subjectCode, List<PictureConfigItem> configList) {
         subjectDao.updateSliceConfig(examId, subjectCode,
                 configList != null ? StringUtils.join(configList, PictureConfigItem.DB_ITEM_JOINER) : "");
+    }
 
+    @Override
+    public void updateTrialCount(int examId, String subjectCode, int trialCount) {
+        subjectDao.updateTrialCount(examId, subjectCode, trialCount);
     }
 
 }

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

@@ -1,23 +1,27 @@
 package cn.com.qmth.stmms.biz.exam.service.impl;
 
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.persistence.EntityManager;
+import javax.persistence.PersistenceContext;
+import javax.persistence.Query;
+
+import org.apache.commons.lang.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
 import cn.com.qmth.stmms.biz.common.BaseQueryService;
 import cn.com.qmth.stmms.biz.exam.model.ExamStudent;
+import cn.com.qmth.stmms.biz.exam.model.MarkGroup;
 import cn.com.qmth.stmms.biz.exam.query.ExamStudentSearchQuery;
 import cn.com.qmth.stmms.biz.exam.service.ExamStudentService;
 import cn.com.qmth.stmms.biz.exam.service.InspectedService;
+import cn.com.qmth.stmms.biz.exam.service.MarkGroupService;
 import cn.com.qmth.stmms.biz.user.service.UserService;
 import cn.com.qmth.stmms.biz.utils.TaskLock;
 import cn.com.qmth.stmms.biz.utils.TaskLockUtil;
 import cn.com.qmth.stmms.common.enums.SubjectiveStatus;
-import org.apache.commons.lang.StringUtils;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Service;
-
-import javax.persistence.EntityManager;
-import javax.persistence.PersistenceContext;
-import javax.persistence.Query;
-import java.util.ArrayList;
-import java.util.List;
 
 @Service
 public class InspectedServiceImpl extends BaseQueryService<ExamStudent> implements InspectedService {
@@ -31,25 +35,28 @@ public class InspectedServiceImpl extends BaseQueryService<ExamStudent> implemen
     @Autowired
     private UserService userService;
 
+    @Autowired
+    private MarkGroupService groupService;
+
     @SuppressWarnings("unchecked")
     @Override
     public List<ExamStudent> findByQuery(ExamStudentSearchQuery query, SubjectiveStatus status, Integer mainNumber,
-            Double mainStartScore, Double mainEndScore, Double questionScore) {
-        StringBuilder dataSql = new StringBuilder("select distinct s.id , s.inspect_time "
-                + " from eb_exam_student s left join eb_subjective_score e on e.student_id = s.id ");
+            Double mainStartScore, Double mainEndScore, Double questionScore, boolean unselective) {
+        StringBuilder dataSql = new StringBuilder("select s.id from eb_exam_student s ");
         StringBuilder limitSql = new StringBuilder(" limit :offset,:pageSize");
-        Query dataQuery = getQuery(query, status, mainNumber, mainStartScore, mainEndScore, questionScore, dataSql,
-                limitSql);
+        Query dataQuery = getQuery(query, status, mainNumber, mainStartScore, mainEndScore, questionScore, unselective,
+                dataSql, limitSql);
         dataQuery.setParameter("offset", (query.getPageNumber() - 1) * query.getPageSize());
         dataQuery.setParameter("pageSize", query.getPageSize());
-        List<Object[]> list = dataQuery.getResultList();
+        List<Integer> list = dataQuery.getResultList();
         List<ExamStudent> resultList = new ArrayList<ExamStudent>();
         if (list != null && !list.isEmpty()) {
-            for (Object[] array : list) {
-                ExamStudent e = studentService.findById((Integer) array[0]);
+            for (Integer id : list) {
+                ExamStudent e = studentService.findById(id);
                 if (e.getInspectorId() != null) {
                     e.setInspector(userService.findById(e.getInspectorId()));
                 }
+                e.setSubjectiveScoreList(e.getSubjectiveScoreList().replace("-1", "/"));
                 resultList.add(e);
             }
         }
@@ -58,8 +65,8 @@ public class InspectedServiceImpl extends BaseQueryService<ExamStudent> implemen
     }
 
     private Query getQuery(ExamStudentSearchQuery query, SubjectiveStatus status, Integer mainNumber,
-            Double mainStartScore, Double mainEndScore, Double questionScore, StringBuilder dataSql,
-            StringBuilder limitSql) {
+            Double mainStartScore, Double mainEndScore, Double questionScore, boolean unselective,
+            StringBuilder dataSql, StringBuilder limitSql) {
         StringBuilder whereSql = new StringBuilder(" WHERE s.is_upload = 1 and s.is_absent = 0 and s.is_breach = 0 ");
         if (query.getExamId() != null) {
             whereSql.append(" and s.exam_id = :examId");
@@ -78,21 +85,31 @@ public class InspectedServiceImpl extends BaseQueryService<ExamStudent> implemen
         if (query.getEndScore() != null) {
             whereSql.append(" and (s.objective_score+s.subjective_score) <= :endScore");
         }
-        if (mainNumber != null) {
-            whereSql.append(" and e.main_number = :mainNumber");
-        }
-        if (mainStartScore != null) {
-            whereSql.append(" and e.main_score >= :mainStartScore");
-        }
-        if (mainEndScore != null) {
-            whereSql.append(" and e.main_score <= :mainEndScore");
-        }
-        if (questionScore != null) {
-            whereSql.append(" and e.score = :questionScore");
-        }
         if (StringUtils.isNotBlank(query.getSecretNumber())) {
             whereSql.append(" and s.secret_number = :secretNumber");
         }
+        if (mainNumber != null || mainStartScore != null || mainEndScore != null || questionScore != null) {
+            whereSql.append(" and exists (select e.student_id from eb_subjective_score e where e.student_id = s.id ");
+            if (mainNumber != null) {
+                whereSql.append(" and e.main_number = :mainNumber");
+            }
+            if (mainStartScore != null) {
+                whereSql.append(" and e.main_score >= :mainStartScore");
+            }
+            if (mainEndScore != null) {
+                whereSql.append(" and e.main_score <= :mainEndScore");
+            }
+            if (questionScore != null) {
+                whereSql.append(" and e.score = :questionScore");
+            }
+            whereSql.append(" ) ");
+        }
+        // 全部选做题为未选做
+        List<MarkGroup> groups = groupService.findByExamAndSubjectAndSelective(query.getExamId(),
+                query.getSubjectCode(), true);
+        if (unselective && !groups.isEmpty()) {
+            whereSql.append(" and not exists (select e.student_id from eb_subjective_score e where e.student_id = s.id and e.group_number in (:groupNumbers) and e.group_score != -1 )");
+        }
         dataSql.append(whereSql);
         StringBuilder orderSql = new StringBuilder(" order by s.inspect_time desc ");
         dataSql.append(orderSql);
@@ -131,16 +148,22 @@ public class InspectedServiceImpl extends BaseQueryService<ExamStudent> implemen
         if (StringUtils.isNotBlank(query.getSecretNumber())) {
             dataQuery.setParameter("secretNumber", query.getSecretNumber());
         }
+        if (unselective && !groups.isEmpty()) {
+            List<Integer> groupNumbers = new ArrayList<Integer>();
+            for (int i = 0; i < groups.size(); i++) {
+                groupNumbers.add(groups.get(i).getNumber());
+            }
+            dataQuery.setParameter("groupNumbers", groupNumbers);
+        }
         return dataQuery;
     }
 
     @Override
     public Integer countByQuery(ExamStudentSearchQuery query, SubjectiveStatus status, Integer mainNumber,
-            Double mainStartScore, Double mainEndScore, Double questionScore) {
-        StringBuilder countSql = new StringBuilder("select count(distinct s.id) "
-                + "from eb_exam_student s left join eb_subjective_score e on e.student_id = s.id ");
-        Query countQuery = getQuery(query, status, mainNumber, mainStartScore, mainEndScore, questionScore, countSql,
-                null);
+            Double mainStartScore, Double mainEndScore, Double questionScore, boolean unselective) {
+        StringBuilder countSql = new StringBuilder("select count(s.id) from eb_exam_student s ");
+        Query countQuery = getQuery(query, status, mainNumber, mainStartScore, mainEndScore, questionScore,
+                unselective, countSql, null);
         Object singleResult = countQuery.getResultList().get(0);
         Integer count = singleResult == null ? 0 : Integer.valueOf(singleResult.toString());
         return count;

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

@@ -70,12 +70,6 @@ public class MarkGroupServiceImpl extends BaseQueryService<MarkGroup> implements
         groupDao.updateArbitrateThreshold(examId, subjectCode, number, arbitrateThreshold);
     }
 
-    @Transactional
-    @Override
-    public void updateTrialCount(int examId, String subjectCode, Integer number, Integer trialCount) {
-        groupDao.updateTrialCount(examId, subjectCode, number, trialCount);
-    }
-
     @Transactional
     @Override
     public void updateSheetView(int examId, String subjectCode, Integer number, boolean sheetView) {
@@ -95,11 +89,6 @@ public class MarkGroupServiceImpl extends BaseQueryService<MarkGroup> implements
         return groupDao.updateStatus(examId, subjectCode, number, newStatus, currentStatus) > 0;
     }
 
-    @Override
-    public boolean needTrialLibrary(Integer examId, String subjectCode, Integer number) {
-        return groupDao.countByStatusAndTrailCount(examId, subjectCode, number, MarkStatus.TRIAL) > 0;
-    }
-
     @Override
     public MarkGroup findOne(int examId, String subjectCode, int number) {
         MarkGroupPK pk = new MarkGroupPK();
@@ -172,4 +161,9 @@ public class MarkGroupServiceImpl extends BaseQueryService<MarkGroup> implements
         return number;
     }
 
+    @Override
+    public List<MarkGroup> findByExamAndSubjectAndSelective(Integer examId, String subjectCode, boolean selective) {
+        return groupDao.findByExamAndSubjectAndSelective(examId, subjectCode, selective);
+    }
+
 }

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

@@ -0,0 +1,48 @@
+package cn.com.qmth.stmms.biz.exam.service.impl;
+
+import java.util.List;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import cn.com.qmth.stmms.biz.common.BaseQueryService;
+import cn.com.qmth.stmms.biz.exam.dao.SelectiveGroupDao;
+import cn.com.qmth.stmms.biz.exam.model.SelectiveGroup;
+import cn.com.qmth.stmms.biz.exam.service.SelectiveGroupService;
+
+@Service("selectiveGroupService")
+public class SelectiveGroupServiceImpl extends BaseQueryService<SelectiveGroup> implements SelectiveGroupService {
+
+    @Autowired
+    private SelectiveGroupDao selectiveGroupDao;
+
+    @Transactional
+    @Override
+    public SelectiveGroup save(SelectiveGroup group) {
+        return selectiveGroupDao.save(group);
+    }
+
+    @Transactional
+    @Override
+    public void save(List<SelectiveGroup> list) {
+        selectiveGroupDao.save(list);
+    }
+
+    @Override
+    public SelectiveGroup findOne(int examId, String subjectCode, int mainNumber) {
+        return selectiveGroupDao.findOne(examId, subjectCode, mainNumber);
+    }
+
+    @Override
+    public List<SelectiveGroup> findByExamIdAndSubjectCode(int examId, String code) {
+        return selectiveGroupDao.findByExamIdAndSubjectCode(examId, code);
+    }
+
+    @Transactional
+    @Override
+    public void deleteByExamIdAndSubjectCode(int examId, String subjectCode) {
+        selectiveGroupDao.deleteByExamIdAndSubjectCode(examId, subjectCode);
+    }
+
+}

+ 24 - 11
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/file/service/impl/FileServiceImpl.java

@@ -9,15 +9,18 @@ import org.apache.commons.lang.math.RandomUtils;
 import org.apache.commons.lang3.StringUtils;
 import org.springframework.beans.factory.DisposableBean;
 import org.springframework.beans.factory.InitializingBean;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.stereotype.Service;
 
+import cn.com.qmth.stmms.biz.config.service.SystemConfigService;
 import cn.com.qmth.stmms.biz.file.enums.FileType;
 import cn.com.qmth.stmms.biz.file.enums.FormatType;
 import cn.com.qmth.stmms.biz.file.service.FileService;
 import cn.com.qmth.stmms.biz.file.store.FileStore;
 import cn.com.qmth.stmms.biz.file.store.impl.DiskStore;
 import cn.com.qmth.stmms.biz.file.store.impl.OssStore;
+import cn.com.qmth.stmms.common.enums.ConfigType;
 
 @Service("fileService")
 public class FileServiceImpl implements FileService, InitializingBean, DisposableBean {
@@ -28,8 +31,8 @@ public class FileServiceImpl implements FileService, InitializingBean, Disposabl
 
     public static final String SERVER_SPLIT = ",";
 
-    @Value("${file.server}")
-    private String fileServerString;
+    @Autowired
+    private SystemConfigService configService;
 
     private List<String> fileServers;
 
@@ -53,21 +56,32 @@ public class FileServiceImpl implements FileService, InitializingBean, Disposabl
 
     @Override
     public String getFileServer() {
-        return fileServers.get(0);
+        return getFileServers().get(0);
 
     }
 
     @Override
     public String getRandomFileServer() {
-        return fileServers.get(RandomUtils.nextInt(fileServers.size()));
+        return getFileServers().get(RandomUtils.nextInt(fileServers.size()));
     }
 
-    public String getFileServerString() {
-        return fileServerString;
+    public List<String> getFileServers() {
+        fileServers = new ArrayList<>();
+        String[] servers = StringUtils.split(configService.findByType(ConfigType.FILE_SERVER), SERVER_SPLIT);
+        for (String server : servers) {
+            server = StringUtils.trimToNull(server);
+            if (server != null) {
+                if (!server.endsWith("/")) {
+                    server = server.concat("/");
+                }
+                fileServers.add(server);
+            }
+        }
+        return fileServers;
     }
 
-    public void setFileServerString(String fileServerString) {
-        this.fileServerString = fileServerString;
+    public void setFileServers(List<String> fileServers) {
+        this.fileServers = fileServers;
     }
 
     public String getFileStore() {
@@ -233,9 +247,8 @@ public class FileServiceImpl implements FileService, InitializingBean, Disposabl
 
     @Override
     public void afterPropertiesSet() {
-        fileServerString = StringUtils.trimToNull(fileServerString);
+        String fileServerString = configService.findByType(ConfigType.FILE_SERVER);
         fileStore = StringUtils.trimToNull(fileStore);
-
         if (fileServerString == null) {
             throw new RuntimeException("invald property: ${file.server} should not be empty");
         }
@@ -287,7 +300,7 @@ public class FileServiceImpl implements FileService, InitializingBean, Disposabl
 
     public static void main(String[] args) throws Exception {
         FileServiceImpl service = new FileServiceImpl();
-        service.fileServerString = "123";
+        // service.fileServerString = "123";
 
         service.fileStore = "oss://LTAI4FnJ2pgV6aGceYcCkeEi:ktrMEVE7PfoxRPeJUPDFeygOIH4aU7@qmth-test.oss-cn-shenzhen.aliyuncs.com";
         service.afterPropertiesSet();

+ 0 - 49
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/mark/dao/TrialHistoryDao.java

@@ -1,49 +0,0 @@
-package cn.com.qmth.stmms.biz.mark.dao;
-
-import cn.com.qmth.stmms.biz.mark.model.TrialHistory;
-import org.springframework.data.domain.Pageable;
-import org.springframework.data.jpa.repository.JpaRepository;
-import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
-import org.springframework.data.jpa.repository.Modifying;
-import org.springframework.data.jpa.repository.Query;
-
-import java.util.List;
-
-public interface TrialHistoryDao extends JpaRepository<TrialHistory, Integer>, JpaSpecificationExecutor<TrialHistory> {
-
-    List<TrialHistory> findByPkLibraryId(Integer libraryId);
-
-    TrialHistory findByPkLibraryIdAndPkMarkerId(Integer libraryId, Integer markerId);
-
-    List<TrialHistory> findByExamIdAndSubjectCodeAndGroupNumberAndPkMarkerId(Integer examId, String subjectCode,
-            Integer groupNumber, Integer markerId, Pageable page);
-
-    @Query("select count(*) from TrialHistory f where f.pk.libraryId=?1")
-    long countByLibraryId(Integer libraryId);
-
-    @Query("select count(*) from TrialHistory f where f.pk.markerId=?1")
-    long countByMarkerId(Integer markerId);
-
-    @Modifying
-    @Query("delete TrialHistory m where m.examId=?1 and m.subjectCode=?2 and m.groupNumber=?3")
-    void deleteByExamIdAndSubjectCodeAndGroupNumber(Integer examId, String subjectCode, Integer groupNumber);
-
-    @Modifying
-    @Query("delete TrialHistory m where m.pk.libraryId=?1")
-    void deleteByLibraryId(Integer libraryId);
-
-    @Modifying
-    @Query("delete TrialHistory m where m.studentId=?1")
-    void deleteByStudentId(Integer studentId);
-
-    @Modifying
-    @Query("delete TrialHistory m where m.pk.markerId=?1")
-    void deleteByMarkerId(Integer markerId);
-
-    List<TrialHistory> findByExamIdAndSubjectCodeAndGroupNumberAndPkMarkerIdAndSecretNumber(Integer examId,
-            String subjectCode, Integer groupNumber, Integer markerId, String secretNumber, Pageable query);
-
-    List<TrialHistory> findByExamIdAndSubjectCodeAndGroupNumberAndPkMarkerIdAndMarkerScore(Integer examId,
-            String subjectCode, Integer groupNumber, Integer markerId, Double markerScore, Pageable query);
-
-}

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

@@ -14,16 +14,16 @@ public interface TrialLibraryDao extends JpaRepository<TrialLibrary, Integer>, J
 
     List<TrialLibrary> findByExamIdAndSubjectCode(Integer examId, String subjectCode, Pageable page);
 
-    List<TrialLibrary> findByExamIdAndSubjectCodeAndGroupNumber(Integer examId, String subjectCode, Integer groupNumber,
-            Pageable page);
+    List<TrialLibrary> findByExamIdAndSubjectCodeAndGroupNumber(Integer examId, String subjectCode,
+            Integer groupNumber, Pageable page);
 
-    @Query("select l1 from TrialLibrary l1 where l1.examId=?1 and l1.subjectCode=?2 and l1.groupNumber=?3 "
-            + "and not exists (select l2.pk.libraryId from TrialHistory l2 where l2.pk.libraryId=l1.id and l2.pk.markerId=?4)")
+    @Query("select l from TrialLibrary l where l.examId=?1 and l.subjectCode=?2 and l.groupNumber=?3 "
+            + "and l.markerId is null ")
     List<TrialLibrary> findUnMarked(Integer examId, String subjectCode, Integer groupNumber, Integer markerId,
             Pageable page);
 
     @Query("select count(l) from TrialLibrary l where l.examId=?1 and l.subjectCode=?2 and l.groupNumber=?3 "
-    		 + "and exists (select l2.pk.libraryId from TrialHistory l2 where l2.pk.libraryId=l.id )")
+            + "and l.markerId is not null ")
     long countMarked(Integer examId, String subjectCode, Integer groupNumber);
 
     @Query("select l from TrialLibrary l where l.studentId=?1 order by l.groupNumber ")
@@ -44,5 +44,27 @@ public interface TrialLibraryDao extends JpaRepository<TrialLibrary, Integer>, J
     @Modifying
     @Query("delete TrialLibrary m where m.studentId=?1")
     void deleteByStudentId(Integer studentId);
-    
+
+    List<TrialLibrary> findByExamIdAndSubjectCodeAndGroupNumberAndMarkerId(Integer examId, String subjectCode,
+            Integer groupNumber, Integer markerId, Pageable page);
+
+    List<TrialLibrary> findByExamIdAndSubjectCodeAndGroupNumberAndMarkerIdAndSecretNumber(Integer examId,
+            String subjectCode, Integer groupNumber, Integer markerId, String secretNumber, Pageable query);
+
+    List<TrialLibrary> findByExamIdAndSubjectCodeAndGroupNumberAndMarkerIdAndMarkerScore(Integer examId,
+            String subjectCode, Integer groupNumber, Integer markerId, Double markerScore, Pageable query);
+
+    @Query("select count(*) from TrialLibrary f where f.markerId=?1")
+    long countByMarkerId(Integer markerId);
+
+    @Modifying(clearAutomatically = true)
+    @Query("update TrialLibrary m set m.markerId=null, m.markerTime=null, m.markerScore=null, m.markerScoreList=null "
+            + "where m.markerId=?1 ")
+    void resetByMarkerId(Integer markerId);
+
+    @Modifying(clearAutomatically = true)
+    @Query("update TrialLibrary m set m.markerId=null, m.markerTime=null, m.markerScore=null, m.markerScoreList=null "
+            + "where m.id=?1")
+    void resetById(Integer id);
+
 }

+ 1 - 1
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/mark/dao/TrialTagDao.java

@@ -24,7 +24,7 @@ public interface TrialTagDao extends PagingAndSortingRepository<TrialTag, Intege
             + "(select l.id from TrialLibrary l where l.studentId=?1 and s.libraryId=l.id)")
     public void deleteByStudentId(Integer studentId);
 
-    public List<TrialTag> findByLibraryIdAndMarkerIdOrderByIdAsc(Integer libraryId, Integer markerId);
+    public List<TrialTag> findByLibraryIdOrderByIdAsc(Integer libraryId);
 
     @Modifying
     @Query("delete from TrialTag s where s.markerId=?1")

+ 1 - 1
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/mark/dao/TrialTrackDao.java

@@ -12,7 +12,7 @@ import cn.com.qmth.stmms.biz.mark.model.TrialTrackPK;
 
 public interface TrialTrackDao extends JpaRepository<TrialTrack, TrialTrackPK>, JpaSpecificationExecutor<TrialTrack> {
 
-    List<TrialTrack> findByPkLibraryIdAndPkMarkerId(Integer libraryId, Integer markerId);
+    List<TrialTrack> findByPkLibraryId(Integer libraryId);
 
     List<TrialTrack> findByStudentId(Integer studentId);
 

+ 14 - 4
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/mark/model/MarkResult.java

@@ -69,6 +69,8 @@ public class MarkResult {
      */
     private Integer problemTypeId;
 
+    private boolean unselective;
+
     public String getStatusValue() {
         return statusValue;
     }
@@ -175,11 +177,11 @@ public class MarkResult {
         return list;
     }
 
-    public List<TrialTrack> getTrackList(TrialHistory history) {
+    public List<TrialTrack> getTrackList(TrialLibrary library) {
         List<TrialTrack> list = new LinkedList<>();
         if (trackList != null) {
             for (TrackDTO dto : trackList) {
-                list.add(dto.transform(history));
+                list.add(dto.transform(library));
             }
         }
         return list;
@@ -195,11 +197,11 @@ public class MarkResult {
         return list;
     }
 
-    public List<TrialTag> getTagList(TrialHistory history) {
+    public List<TrialTag> getTagList(TrialLibrary library) {
         List<TrialTag> list = new LinkedList<>();
         if (specialTagList != null) {
             for (SpecialTagDTO dto : specialTagList) {
-                list.add(dto.transform(history));
+                list.add(dto.transform(library));
             }
         }
         return list;
@@ -221,4 +223,12 @@ public class MarkResult {
         this.problemTypeId = problemTypeId;
     }
 
+    public boolean isUnselective() {
+        return unselective;
+    }
+
+    public void setUnselective(boolean unselective) {
+        this.unselective = unselective;
+    }
+
 }

+ 3 - 3
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/mark/model/SpecialTagDTO.java

@@ -34,10 +34,10 @@ public class SpecialTagDTO implements Serializable {
         return markSpecialTag;
     }
 
-    public TrialTag transform(TrialHistory history) {
+    public TrialTag transform(TrialLibrary library) {
         TrialTag tag = new TrialTag();
-        tag.setLibraryId(history.getLibraryId());
-        tag.setMarkerId(history.getMarkerId());
+        tag.setLibraryId(library.getId());
+        tag.setMarkerId(library.getMarkerId());
         tag.setContent(tagName);
         tag.setPositionX(positionX);
         tag.setPositionY(positionY);

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

@@ -81,17 +81,17 @@ public class TrackDTO implements Serializable {
         return track;
     }
 
-    public TrialTrack transform(TrialHistory history) {
+    public TrialTrack transform(TrialLibrary library) {
         TrialTrack track = new TrialTrack();
-        track.setLibraryId(history.getLibraryId());
-        track.setMarkerId(history.getMarkerId());
+        track.setLibraryId(library.getId());
+        track.setMarkerId(library.getMarkerId());
         track.setQuestionNumber(getMainNumber() + "." + getSubNumber());
         track.setNumber(getNumber());
-        track.setStudentId(history.getStudentId());
-        track.setExamId(history.getExamId());
-        track.setSubjectCode(history.getSubjectCode());
-        track.setGroupNumber(history.getGroupNumber());
-        track.setMarkerId(history.getMarkerId());
+        track.setStudentId(library.getStudentId());
+        track.setExamId(library.getExamId());
+        track.setSubjectCode(library.getSubjectCode());
+        track.setGroupNumber(library.getGroupNumber());
+        track.setMarkerId(library.getMarkerId());
         track.setScore(getScore());
         track.setPositionX(getPositionX());
         track.setPositionY(getPositionY());

+ 0 - 188
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/mark/model/TrialHistory.java

@@ -1,188 +0,0 @@
-package cn.com.qmth.stmms.biz.mark.model;
-
-import cn.com.qmth.stmms.biz.exam.model.Marker;
-import cn.com.qmth.stmms.biz.utils.ScoreItem;
-
-import javax.persistence.*;
-
-import org.apache.commons.lang.StringUtils;
-
-import java.io.Serializable;
-import java.util.Date;
-import java.util.LinkedList;
-import java.util.List;
-
-/**
- * 试评任务给分记录表
- *
- * @author luoshi
- */
-@Entity
-@Table(name = "m_trial_history")
-public class TrialHistory implements Serializable {
-
-    private static final long serialVersionUID = 1077169224382148814L;
-
-    @EmbeddedId
-    private TrialHistoryPK pk;
-
-    /**
-     * 考试ID
-     */
-    @Column(name = "exam_id")
-    private Integer examId;
-
-    /**
-     * 科目CODE
-     */
-    @Column(name = "subject_code")
-    private String subjectCode;
-
-    /**
-     * 大题序号
-     */
-    @Column(name = "group_number")
-    private Integer groupNumber;
-
-    /**
-     * 考生编号
-     */
-    @Column(name = "student_id")
-    private Integer studentId;
-
-    /**
-     * 考生密号
-     */
-    @Column(name = "secret_number")
-    private String secretNumber;
-
-    /**
-     * 评卷时间
-     */
-    @Column(name = "marker_time")
-    private Date markerTime;
-
-    /**
-     * 评卷员给分总分
-     */
-    @Column(name = "marker_score")
-    private Double markerScore;
-
-    /**
-     * 评卷员给分明细
-     */
-    @Column(name = "marker_score_list")
-    private String markerScoreList;
-
-    @Transient
-    private Marker marker;
-
-    public TrialHistory() {
-        this.pk = new TrialHistoryPK();
-    }
-
-    public Integer getExamId() {
-        return examId;
-    }
-
-    public void setExamId(Integer examId) {
-        this.examId = examId;
-    }
-
-    public String getSubjectCode() {
-        return subjectCode;
-    }
-
-    public void setSubjectCode(String subjectCode) {
-        this.subjectCode = subjectCode;
-    }
-
-    public Integer getStudentId() {
-        return studentId;
-    }
-
-    public void setStudentId(Integer studentId) {
-        this.studentId = studentId;
-    }
-
-    public Integer getLibraryId() {
-        return pk.getLibraryId();
-    }
-
-    public void setLibraryId(Integer libraryId) {
-        pk.setLibraryId(libraryId);
-    }
-
-    public Integer getMarkerId() {
-        return pk.getMarkerId();
-    }
-
-    public void setMarkerId(Integer markerId) {
-        pk.setMarkerId(markerId);
-    }
-
-    public Date getMarkerTime() {
-        return markerTime;
-    }
-
-    public void setMarkerTime(Date markerTime) {
-        this.markerTime = markerTime;
-    }
-
-    public Double getMarkerScore() {
-        return markerScore;
-    }
-
-    public void setMarkerScore(Double markerScore) {
-        this.markerScore = markerScore;
-    }
-
-    public String getMarkerScoreList() {
-        return markerScoreList;
-    }
-
-    public void setMarkerScoreList(String markerScoreList) {
-        this.markerScoreList = markerScoreList;
-    }
-
-    public Integer getGroupNumber() {
-        return groupNumber;
-    }
-
-    public void setGroupNumber(Integer groupNumber) {
-        this.groupNumber = groupNumber;
-    }
-
-    public Marker getMarker() {
-        return marker;
-    }
-
-    public void setMarker(Marker marker) {
-        this.marker = marker;
-    }
-
-    public String getSecretNumber() {
-        return secretNumber;
-    }
-
-    public void setSecretNumber(String secretNumber) {
-        this.secretNumber = secretNumber;
-    }
-
-    public List<ScoreItem> getScoreList() {
-        List<ScoreItem> list = new LinkedList<ScoreItem>();
-        if (StringUtils.isNotBlank(markerScoreList)) {
-            try {
-                String[] values = markerScoreList.split(",");
-                for (String value : values) {
-                    ScoreItem item = ScoreItem.parse(value, false);
-                    if (item != null) {
-                        list.add(item);
-                    }
-                }
-            } catch (Exception e) {
-            }
-        }
-        return list;
-    }
-}

+ 0 - 66
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/mark/model/TrialHistoryPK.java

@@ -1,66 +0,0 @@
-package cn.com.qmth.stmms.biz.mark.model;
-
-import java.io.Serializable;
-
-import javax.persistence.Column;
-import javax.persistence.Embeddable;
-
-@Embeddable
-public class TrialHistoryPK implements Serializable {
-
-    private static final long serialVersionUID = 7082004881704656373L;
-
-    @Column(name = "library_id", nullable = false)
-    private Integer libraryId;
-
-    @Column(name = "marker_id", nullable = false)
-    private Integer markerId;
-
-    public Integer getLibraryId() {
-        return libraryId;
-    }
-
-    public void setLibraryId(Integer libraryId) {
-        this.libraryId = libraryId;
-    }
-
-    public Integer getMarkerId() {
-        return markerId;
-    }
-
-    public void setMarkerId(Integer markerId) {
-        this.markerId = markerId;
-    }
-
-    @Override
-    public int hashCode() {
-        final int PRIME = 31;
-        int result = 1;
-        result = PRIME * result + ((libraryId == null) ? 0 : libraryId.hashCode());
-        result = PRIME * result + ((markerId == null) ? 0 : markerId.hashCode());
-        return result;
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (this == obj)
-            return true;
-        if (obj == null)
-            return false;
-        if (getClass() != obj.getClass())
-            return false;
-        final TrialHistoryPK other = (TrialHistoryPK) obj;
-        if (libraryId == null) {
-            if (other.libraryId != null)
-                return false;
-        } else if (!libraryId.equals(other.libraryId))
-            if (markerId == null) {
-                if (other.markerId != null)
-                    return false;
-            } else if (!markerId.equals(other.markerId))
-                return false;
-
-        return true;
-    }
-
-}

+ 75 - 8
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/mark/model/TrialLibrary.java

@@ -1,7 +1,19 @@
 package cn.com.qmth.stmms.biz.mark.model;
 
-import javax.persistence.*;
 import java.io.Serializable;
+import java.util.Date;
+import java.util.LinkedList;
+import java.util.List;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.Id;
+import javax.persistence.Table;
+
+import org.apache.commons.lang.StringUtils;
+
+import cn.com.qmth.stmms.biz.utils.ScoreItem;
 
 /**
  * 试评任务表
@@ -54,11 +66,26 @@ public class TrialLibrary implements Serializable {
     @Column(name = "secret_number")
     private String secretNumber;
 
+    @Column(name = "marker_id", nullable = false)
+    private Integer markerId;
+
+    /**
+     * 评卷时间
+     */
+    @Column(name = "marker_time")
+    private Date markerTime;
+
+    /**
+     * 评卷员给分总分
+     */
+    @Column(name = "marker_score")
+    private Double markerScore;
+
     /**
-     * 已评人数
+     * 评卷员给分明细
      */
-    @Transient
-    private Long markCount;
+    @Column(name = "marker_score_list")
+    private String markerScoreList;
 
     public Integer getId() {
         return id;
@@ -116,12 +143,52 @@ public class TrialLibrary implements Serializable {
         this.groupNumber = groupNumber;
     }
 
-    public Long getMarkCount() {
-        return markCount;
+    public Integer getMarkerId() {
+        return markerId;
+    }
+
+    public void setMarkerId(Integer markerId) {
+        this.markerId = markerId;
     }
 
-    public void setMarkCount(Long markCount) {
-        this.markCount = markCount;
+    public Date getMarkerTime() {
+        return markerTime;
     }
 
+    public void setMarkerTime(Date markerTime) {
+        this.markerTime = markerTime;
+    }
+
+    public Double getMarkerScore() {
+        return markerScore;
+    }
+
+    public void setMarkerScore(Double markerScore) {
+        this.markerScore = markerScore;
+    }
+
+    public String getMarkerScoreList() {
+        return markerScoreList;
+    }
+
+    public void setMarkerScoreList(String markerScoreList) {
+        this.markerScoreList = markerScoreList;
+    }
+
+    public List<ScoreItem> getScoreList() {
+        List<ScoreItem> list = new LinkedList<ScoreItem>();
+        if (StringUtils.isNotBlank(markerScoreList)) {
+            try {
+                String[] values = markerScoreList.split(",");
+                for (String value : values) {
+                    ScoreItem item = ScoreItem.parse(value, false);
+                    if (item != null) {
+                        list.add(item);
+                    }
+                }
+            } catch (Exception e) {
+            }
+        }
+        return list;
+    }
 }

+ 20 - 0
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/mark/query/ArbitrateHistorySearchQuery.java

@@ -25,6 +25,10 @@ public class ArbitrateHistorySearchQuery extends BaseQuery<ArbitrateHistory> {
 
     private String secretNumber;
 
+    private Double startScroe;
+
+    private boolean unselective;
+
     public void orderByIdDesc() {
         setSort(new Sort(Direction.DESC, "id"));
     }
@@ -97,4 +101,20 @@ public class ArbitrateHistorySearchQuery extends BaseQuery<ArbitrateHistory> {
         this.secretNumber = secretNumber;
     }
 
+    public boolean isUnselective() {
+        return unselective;
+    }
+
+    public void setUnselective(boolean unselective) {
+        this.unselective = unselective;
+    }
+
+    public Double getStartScroe() {
+        return startScroe;
+    }
+
+    public void setStartScroe(Double startScroe) {
+        this.startScroe = startScroe;
+    }
+
 }

+ 10 - 0
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/mark/query/MarkLibrarySearchQuery.java

@@ -35,6 +35,8 @@ public class MarkLibrarySearchQuery extends BaseQuery<MarkLibrary> {
 
     private Double endScroe;
 
+    private boolean unselective;
+
     public MarkLibrarySearchQuery() {
         super();
         this.statusSet = new HashSet<>();
@@ -152,4 +154,12 @@ public class MarkLibrarySearchQuery extends BaseQuery<MarkLibrary> {
         this.endScroe = endScroe;
     }
 
+    public boolean isUnselective() {
+        return unselective;
+    }
+
+    public void setUnselective(boolean unselective) {
+        this.unselective = unselective;
+    }
+
 }

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

@@ -102,6 +102,13 @@ public class ArbitrateHistoryServiceImpl extends BaseQueryService<ArbitrateHisto
                 if (StringUtils.isNotBlank(query.getSecretNumber())) {
                     predicates.add(cb.equal(root.get("secretNumber"), query.getSecretNumber()));
                 }
+                if (query.isUnselective()) {
+                    predicates.add(cb.equal(root.get("totalScore"), -1));
+                }
+                if (query.getStartScroe() != null) {
+                    Predicate predicate1 = cb.ge(root.get("totalScore"), query.getStartScroe());
+                    predicates.add(predicate1);
+                }
                 return predicates.isEmpty() ? cb.conjunction() : cb.and(predicates.toArray(new Predicate[predicates
                         .size()]));
             }

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

@@ -25,6 +25,7 @@ import cn.com.qmth.stmms.biz.utils.TaskLockUtil;
 import cn.com.qmth.stmms.common.enums.ConfigType;
 import cn.com.qmth.stmms.common.enums.LockType;
 import cn.com.qmth.stmms.common.enums.MarkStatus;
+import cn.com.qmth.stmms.common.enums.SubjectiveStatus;
 
 /**
  * 与评卷相关的所有定时任务
@@ -167,8 +168,22 @@ public class MarkCronService {
             // 生成试评任务
             List<MarkGroup> groups = groupService.findByExamAndSubjectAndStatus(subject.getExamId(), subject.getCode(),
                     MarkStatus.TRIAL);
+            long trialCount = studentService.countByExamIdAndSubjectCodeAndStatus(examId, subject.getCode(),
+                    SubjectiveStatus.TRIAL);
+            if (!groups.isEmpty() && trialCount < subject.getTrialCount()) {
+                while (trialCount < subject.getTrialCount()) {
+                    // 取一个的考生
+                    ExamStudent student = studentService.randomStudent(examId, subject.getCode());
+                    if (student == null) {
+                        return;
+                    }
+                    studentService.updateSubjectiveStatusAndTimeAndInspectorId(student.getId(), SubjectiveStatus.TRIAL,
+                            null, null);
+                    trialCount++;
+                }
+            }
             for (MarkGroup group : groups) {
-                buildTrialLibrary(group);
+                buildTrialLibrary(subject.getTrialCount(), group);
             }
             // 生成正评任务
             // 试评状态的分组也提前生成
@@ -223,9 +238,9 @@ public class MarkCronService {
         }
     }
 
-    private void buildTrialLibrary(MarkGroup group) {
-        while (group.getTrialCount() > group.getLibraryCount()) {
-            // 随机取一个未生成试评任务的考生
+    private void buildTrialLibrary(int trialCount, MarkGroup group) {
+        while (trialCount > group.getLibraryCount()) {
+            // 取一个未生成试评任务的考生
             ExamStudent student = studentService.randomUnTrialStudent(group.getExamId(), group.getSubjectCode(),
                     group.getNumber());
             if (student == null) {

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

@@ -132,10 +132,21 @@ public class MarkLibraryServiceImpl extends BaseQueryService<MarkLibrary> implem
                     predicates.add(cb.equal(root.get("markerScore"), query.getMarkerScore()));
                 }
                 if (query.getStartScroe() != null) {
+                    Predicate predicate1 = cb.ge(root.get("markerScore"), query.getStartScroe());
+                    predicates.add(predicate1);
+                }
+                if (query.getEndScroe() != null) {
+                    Predicate predicate2 = cb.le(root.get("markerScore"), query.getEndScroe());
+                    predicates.add(predicate2);
+                }
+                if (query.getMarkerScore() != null && query.getStartScroe() != null) {
                     Predicate predicate1 = cb.ge(root.get("markerScore"), query.getStartScroe());
                     Predicate predicate2 = cb.le(root.get("markerScore"), query.getEndScroe());
                     predicates.add(cb.and(predicate1, predicate2));
                 }
+                if (query.isUnselective()) {
+                    predicates.add(cb.equal(root.get("markerScore"), -1));
+                }
                 return predicates.isEmpty() ? cb.conjunction() : cb.and(predicates.toArray(new Predicate[predicates
                         .size()]));
             }

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

@@ -1,30 +1,68 @@
 package cn.com.qmth.stmms.biz.mark.service.Impl;
 
-import cn.com.qmth.stmms.biz.exam.dao.*;
-import cn.com.qmth.stmms.biz.exam.model.*;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.apache.commons.lang.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.domain.Sort;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import cn.com.qmth.stmms.biz.exam.dao.ExamQuestionDao;
+import cn.com.qmth.stmms.biz.exam.dao.MarkGroupDao;
+import cn.com.qmth.stmms.biz.exam.dao.MarkGroupStudentDao;
+import cn.com.qmth.stmms.biz.exam.dao.MarkerDao;
+import cn.com.qmth.stmms.biz.exam.dao.SubjectiveScoreDao;
+import cn.com.qmth.stmms.biz.exam.model.ExamQuestion;
+import cn.com.qmth.stmms.biz.exam.model.ExamStudent;
+import cn.com.qmth.stmms.biz.exam.model.ExamSubject;
+import cn.com.qmth.stmms.biz.exam.model.MarkGroup;
+import cn.com.qmth.stmms.biz.exam.model.MarkGroupStudent;
+import cn.com.qmth.stmms.biz.exam.model.Marker;
+import cn.com.qmth.stmms.biz.exam.model.SelectiveGroup;
+import cn.com.qmth.stmms.biz.exam.model.SubjectiveScore;
 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.mark.dao.*;
-import cn.com.qmth.stmms.biz.mark.model.*;
+import cn.com.qmth.stmms.biz.exam.service.SelectiveGroupService;
+import cn.com.qmth.stmms.biz.mark.dao.ArbitrateHistoryDao;
+import cn.com.qmth.stmms.biz.mark.dao.MarkLibraryDao;
+import cn.com.qmth.stmms.biz.mark.dao.MarkSpecialTagDao;
+import cn.com.qmth.stmms.biz.mark.dao.MarkTrackDao;
+import cn.com.qmth.stmms.biz.mark.dao.ProblemHistoryDao;
+import cn.com.qmth.stmms.biz.mark.dao.TrialLibraryDao;
+import cn.com.qmth.stmms.biz.mark.dao.TrialTagDao;
+import cn.com.qmth.stmms.biz.mark.dao.TrialTrackDao;
+import cn.com.qmth.stmms.biz.mark.model.ArbitrateHistory;
+import cn.com.qmth.stmms.biz.mark.model.MarkLibrary;
+import cn.com.qmth.stmms.biz.mark.model.MarkResult;
+import cn.com.qmth.stmms.biz.mark.model.MarkStepDTO;
+import cn.com.qmth.stmms.biz.mark.model.MarkTrack;
+import cn.com.qmth.stmms.biz.mark.model.ProblemHistory;
+import cn.com.qmth.stmms.biz.mark.model.SubmitResult;
+import cn.com.qmth.stmms.biz.mark.model.TrialLibrary;
 import cn.com.qmth.stmms.biz.mark.query.MarkLibrarySearchQuery;
 import cn.com.qmth.stmms.biz.mark.service.MarkService;
 import cn.com.qmth.stmms.biz.utils.ScoreItem;
 import cn.com.qmth.stmms.biz.utils.TaskLock;
 import cn.com.qmth.stmms.biz.utils.TaskLockUtil;
-import cn.com.qmth.stmms.common.enums.*;
+import cn.com.qmth.stmms.common.enums.HistoryStatus;
+import cn.com.qmth.stmms.common.enums.LibraryStatus;
+import cn.com.qmth.stmms.common.enums.MarkStatus;
+import cn.com.qmth.stmms.common.enums.ObjectiveStatus;
+import cn.com.qmth.stmms.common.enums.ScorePolicy;
+import cn.com.qmth.stmms.common.enums.SubjectiveStatus;
+import cn.com.qmth.stmms.common.enums.ThirdPolicy;
 import cn.com.qmth.stmms.common.utils.BigDecimalUtils;
-import org.apache.commons.lang.StringUtils;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.data.domain.Sort;
-import org.springframework.stereotype.Service;
-import org.springframework.transaction.annotation.Transactional;
-
-import java.util.*;
-import java.util.concurrent.ConcurrentHashMap;
 
 /**
  * 与评卷相关的所有修改操作(非传播性的新增操作除外),全部汇总到这里进行集中控制
@@ -36,6 +74,8 @@ public class MarkServiceImpl implements MarkService {
 
     protected static final Logger log = LoggerFactory.getLogger(MarkServiceImpl.class);
 
+    public static final int UN_SELECTIVE_SCORE = -1;
+
     @Autowired
     private ExamStudentService studentService;
 
@@ -72,9 +112,6 @@ public class MarkServiceImpl implements MarkService {
     @Autowired
     private TrialLibraryDao trialLibraryDao;
 
-    @Autowired
-    private TrialHistoryDao trialHistoryDao;
-
     @Autowired
     private TrialTrackDao trialTrackDao;
 
@@ -90,6 +127,9 @@ public class MarkServiceImpl implements MarkService {
     @Autowired
     private ExamQuestionService questionService;
 
+    @Autowired
+    private SelectiveGroupService selectiveGroupService;
+
     private Map<Integer, Long> markerLastUpdateTime = new ConcurrentHashMap<>();
 
     /**
@@ -152,7 +192,7 @@ public class MarkServiceImpl implements MarkService {
         }
         if (group != null) {
             if (group.getStatus() == MarkStatus.TRIAL) {
-                return trialHistoryDao.countByMarkerId(marker.getId());
+                return trialLibraryDao.countByMarkerId(marker.getId());
             } else {
                 return libraryDao.countByMarkerAndStatus(marker.getId(), LibraryStatus.MARKED,
                         LibraryStatus.ARBITRATED, LibraryStatus.INSPECTED);
@@ -203,8 +243,6 @@ public class MarkServiceImpl implements MarkService {
         trialTrackDao.deleteByExamIdAndSubjectCodeAndGroupNumber(group.getExamId(), group.getSubjectCode(),
                 group.getNumber());
         trialTagDao.deleteByExamAndSubjectAndGroup(group.getExamId(), group.getSubjectCode(), group.getNumber());
-        trialHistoryDao.deleteByExamIdAndSubjectCodeAndGroupNumber(group.getExamId(), group.getSubjectCode(),
-                group.getNumber());
         trialLibraryDao.deleteByExamIdAndSubjectCodeAndGroupNumber(group.getExamId(), group.getSubjectCode(),
                 group.getNumber());
         // 正评相关数据
@@ -257,7 +295,8 @@ public class MarkServiceImpl implements MarkService {
      */
     @Override
     @Transactional
-    public void updateGroup(MarkGroup group, List<ExamQuestion> questionList, ScorePolicy policy, ThirdPolicy third) {
+    public void updateGroup(MarkGroup group, List<ExamQuestion> questionList, ScorePolicy policy, ThirdPolicy third,
+            boolean selective) {
         List<ExamQuestion> old = questionDao.findByExamIdAndSubjectCodeAndObjectiveAndGroupNumber(group.getExamId(),
                 group.getSubjectCode(), false, group.getNumber());
         for (ExamQuestion question : old) {
@@ -273,6 +312,8 @@ public class MarkServiceImpl implements MarkService {
         groupDao.updateTotalScore(group.getExamId(), group.getSubjectCode(), group.getNumber(), totalScore);
         groupDao.updateScorePolicy(group.getExamId(), group.getSubjectCode(), group.getNumber(), policy);
         groupDao.updateThirdPolicy(group.getExamId(), group.getSubjectCode(), group.getNumber(), third);
+        groupDao.updateSelective(group.getExamId(), group.getSubjectCode(), group.getNumber(), selective);
+
         subjectService.updateScore(group.getExamId(), group.getSubjectCode(), false,
                 sumTotalScore(group.getExamId(), group.getSubjectCode()));
         resetGroup(group);
@@ -451,7 +492,7 @@ public class MarkServiceImpl implements MarkService {
         } else if (group.getStatus() == MarkStatus.TRIAL) {
             trialTagDao.deleteByMarkerId(marker.getId());
             trialTrackDao.deleteByMarkerId(marker.getId());
-            trialHistoryDao.deleteByMarkerId(marker.getId());
+            trialLibraryDao.resetByMarkerId(marker.getId());
         }
         updateMarkedCount(group);
         releaseByMarker(marker);
@@ -475,7 +516,6 @@ public class MarkServiceImpl implements MarkService {
         // 试评相关数据
         trialTrackDao.deleteByStudentId(student.getId());
         trialTagDao.deleteByStudentId(student.getId());
-        trialHistoryDao.deleteByStudentId(student.getId());
         trialLibraryDao.deleteByStudentId(student.getId());
         // 主观状态与得分明细
         groupStudentDao.deleteByStudentId(student.getId());
@@ -502,12 +542,13 @@ public class MarkServiceImpl implements MarkService {
             return SubmitResult.faile();
         }
 
+        Date now = new Date();
         // 根据评卷状态选择读取不同的评卷任务
         if (group.getStatus() == MarkStatus.FORMAL) {
             MarkLibrary library = libraryDao.findOne(result.getLibraryId());
+            // 问题卷
             if (library != null && result.isProblem()) {
                 // 状态更新
-                Date now = new Date();
                 if (libraryDao.updateProblemResult(library.getId(), LibraryStatus.PROBLEM, marker.getId(), now,
                         result.getSpent(), LibraryStatus.WAITING, LibraryStatus.MARKED, LibraryStatus.INSPECTED,
                         LibraryStatus.REJECTED) != 0) {
@@ -524,8 +565,7 @@ public class MarkServiceImpl implements MarkService {
             if (library != null && library.getExamId().equals(group.getExamId())
                     && library.getSubjectCode().equals(group.getSubjectCode())
                     && library.getGroupNumber().equals(group.getNumber())
-                    && result.getMarkerScore() <= group.getTotalScore()
-                    && StringUtils.isNotBlank(result.getScoreList())) {
+                    && result.getMarkerScore() <= group.getTotalScore()) {
                 if (submitLibrary(library, marker, group, result)) {
                     updateMarkedCount(group);
                     return SubmitResult.success(library);
@@ -533,36 +573,27 @@ 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())
+            if (library != null && hasApplied(library, marker) && library.getExamId().equals(group.getExamId())
                     && library.getSubjectCode().equals(group.getSubjectCode())
                     && library.getGroupNumber().equals(group.getNumber())
                     && result.getMarkerScore() <= group.getTotalScore()
                     && StringUtils.isNotBlank(result.getScoreList())) {
-                TrialHistory history = new TrialHistory();
-                history.setExamId(library.getExamId());
-                history.setSubjectCode(library.getSubjectCode());
-                history.setGroupNumber(library.getGroupNumber());
-                history.setLibraryId(library.getId());
-                history.setStudentId(library.getStudentId());
-                history.setMarkerId(marker.getId());
-                history.setMarkerTime(new Date());
-                history.setMarkerScore(result.getMarkerScore());
-                history.setMarkerScoreList(result.getScoreList());
-                history.setSecretNumber(library.getSecretNumber());
-                history = trialHistoryDao.save(history);
-                if (history != null) {
-                    if (result.getTrackList() != null) {
-                        trialTrackDao.deleteByLibraryIdAndMarkerId(history.getLibraryId(), history.getMarkerId());
-                        trialTrackDao.save(result.getTrackList(history));
-                    }
-                    if (result.getSpecialTagList() != null) {
-                        trialTagDao.deleteByLibraryIdAndMarkerId(history.getLibraryId(), history.getMarkerId());
-                        trialTagDao.save(result.getTagList(history));
-                    }
-                    updateMarkedCount(group);
-                    // releaseLibrary(library, marker);
-                    return SubmitResult.success(library);
+                library.setMarkerId(marker.getId());
+                library.setMarkerTime(new Date());
+                library.setMarkerScore(result.getMarkerScore());
+                library.setMarkerScoreList(result.getScoreList());
+                library = trialLibraryDao.save(library);
+                if (result.getTrackList() != null) {
+                    trialTrackDao.deleteByLibraryIdAndMarkerId(library.getId(), library.getMarkerId());
+                    trialTrackDao.save(result.getTrackList(library));
+                }
+                if (result.getSpecialTagList() != null) {
+                    trialTagDao.deleteByLibraryIdAndMarkerId(library.getId(), library.getMarkerId());
+                    trialTagDao.save(result.getTagList(library));
                 }
+                checkStudentTrial(library, group);
+                updateMarkedCount(group);
+                return SubmitResult.success(library);
             }
         }
         return SubmitResult.faile();
@@ -614,6 +645,11 @@ public class MarkServiceImpl implements MarkService {
                 .countByStudentIdAndMarkerIdAndIdNotEqual(library.getStudentId(), marker.getId(), library.getId()) > 0) {
             return false;
         }
+        // 未选做
+        if (result.isUnselective()) {
+            result.setMarkerScore(UN_SELECTIVE_SCORE);
+            result.setScoreList(null);
+        }
         // 尝试提交评卷结果
         Date now = new Date();
         if (libraryDao.updateMarkerResult(library.getId(), LibraryStatus.MARKED, marker.getId(),
@@ -623,7 +659,7 @@ public class MarkServiceImpl implements MarkService {
             return false;
         }
         // 保存阅卷轨迹
-        if (result.getTrackList() != null) {
+        if (result.getTrackList() != null && !result.isUnselective()) {
             trackDao.deleteByLibraryId(library.getId());
             List<MarkTrack> tracks = result.getTrackList(library, marker);
             for (MarkTrack markTrack : tracks) {
@@ -631,7 +667,7 @@ public class MarkServiceImpl implements MarkService {
             }
         }
         // 保存特殊标记
-        if (result.getSpecialTagList() != null) {
+        if (result.getSpecialTagList() != null && !result.isUnselective()) {
             specialTagDao.deleteByLibraryId(library.getId());
             specialTagDao.save(result.getSpecialTagList(library, marker));
         }
@@ -642,11 +678,21 @@ public class MarkServiceImpl implements MarkService {
             List<MarkLibrary> list = libraryDao.findByStudentIdAndGroupNumberAndStatus(library.getStudentId(),
                     library.getGroupNumber(), LibraryStatus.MARKED, LibraryStatus.INSPECTED);
             for (MarkLibrary other : list) {
+                // 本评卷任务或组长已打分,则跳过该任务
                 if (other.getId().equals(library.getId()) || other.getHeaderScore() != null) {
-                    // 本评卷任务或组长已打分,则跳过该任务
                     continue;
                 }
-                // 分差超过阀值,
+                // 均为未选做,跳过该任务
+                if (other.getMarkerScore() == UN_SELECTIVE_SCORE && result.getMarkerScore() == UN_SELECTIVE_SCORE) {
+                    continue;
+                }
+                // 其中一个有分另一个未选做 直接进入仲裁
+                if ((other.getMarkerScore() != UN_SELECTIVE_SCORE && result.getMarkerScore() == UN_SELECTIVE_SCORE)
+                        || (other.getMarkerScore() == UN_SELECTIVE_SCORE && result.getMarkerScore() != UN_SELECTIVE_SCORE)) {
+                    history = buildArbitrateHistory(library, now);
+                    break;
+                }
+                // 分差超过阀值
                 if (Math.abs(other.getMarkerScore() - result.getMarkerScore()) > group.getArbitrateThreshold()) {
                     // 开启三评
                     if (group.getThirdPolicy().equals(ThirdPolicy.LOW_DIFF_HIGH_AVG)) {
@@ -782,7 +828,7 @@ public class MarkServiceImpl implements MarkService {
     @Transactional
     public boolean resetLibrary(TrialLibrary library) {
         if (library != null) {
-            trialHistoryDao.deleteByLibraryId(library.getId());
+            trialLibraryDao.resetById(library.getId());
             trialTrackDao.deleteByLibraryId(library.getId());
             trialTagDao.deleteByLibraryId(library.getId());
             return true;
@@ -847,23 +893,23 @@ public class MarkServiceImpl implements MarkService {
 
     private void scoreCalculate(Integer studentId) {
         List<ScoreItem> scoreList = new ArrayList<>();
-        Map<Integer, List<SubjectiveScore>> map = new HashMap<Integer, List<SubjectiveScore>>();
-        double totalScore = 0.0;
+        Map<Integer, List<SubjectiveScore>> mainScoreMap = new HashMap<Integer, List<SubjectiveScore>>();
+        Map<Integer, Double> scoreMap = new HashMap<Integer, Double>();
+
         // 循环所有主观得分明细
         List<SubjectiveScore> list = scoreDao.findByStudentId(studentId);
         for (SubjectiveScore ss : list) {
-            totalScore = BigDecimalUtils.add(totalScore, ss.getScore());
-            scoreList.add(new ScoreItem(ss));
-            List<SubjectiveScore> mainScoreList = map.get(ss.getMainNumber());
+            List<SubjectiveScore> mainScoreList = mainScoreMap.get(ss.getMainNumber());
             if (mainScoreList == null) {
                 mainScoreList = new ArrayList<SubjectiveScore>();
             }
             mainScoreList.add(ss);
-            map.put(ss.getMainNumber(), mainScoreList);
+            mainScoreMap.put(ss.getMainNumber(), mainScoreList);
+            scoreList.add(new ScoreItem(ss));
         }
         // 计算大题分
-        for (Integer mainNumber : map.keySet()) {
-            List<SubjectiveScore> mainScoreList = map.get(mainNumber);
+        for (Integer mainNumber : mainScoreMap.keySet()) {
+            List<SubjectiveScore> mainScoreList = mainScoreMap.get(mainNumber);
             double mainScore = 0.0;
             for (SubjectiveScore subjectiveScore : mainScoreList) {
                 mainScore = BigDecimalUtils.add(mainScore, subjectiveScore.getScore());
@@ -872,6 +918,34 @@ public class MarkServiceImpl implements MarkService {
                 subjectiveScore.setMainScore(mainScore);
                 scoreDao.saveAndFlush(subjectiveScore);
             }
+            scoreMap.put(mainNumber, mainScore);
+        }
+        // 计算选做题分数
+        ExamStudent student = studentService.findById(studentId);
+        List<SelectiveGroup> selectiveGroups = selectiveGroupService.findByExamIdAndSubjectCode(student.getExamId(),
+                student.getSubjectCode());
+
+        List<Double> selectiveList = new ArrayList<Double>();
+        Integer selectiveCount = 0;
+        for (SelectiveGroup selectiveGroup : selectiveGroups) {
+            double mainScore = scoreMap.get(selectiveGroup.getMainNumber());
+            scoreMap.remove(selectiveGroup.getMainNumber());
+            selectiveList.add(mainScore);
+            if (selectiveCount == 0) {
+                selectiveCount = selectiveGroup.getSelectiveCount();
+            }
+        }
+        Collections.sort(selectiveList);
+        Collections.reverse(selectiveList);
+        // 计算总分
+        double totalScore = 0.0;
+        for (Integer mainNumber : scoreMap.keySet()) {
+            totalScore = BigDecimalUtils.add(totalScore, scoreMap.get(mainNumber));
+        }
+        for (int i = 0; i < selectiveList.size(); i++) {
+            if (i < selectiveCount) {
+                totalScore = BigDecimalUtils.add(totalScore, selectiveList.get(i));
+            }
         }
         // 全部评完,更新考生主观题得分
         studentService.updateSubjectiveStatusAndScore(studentId, SubjectiveStatus.MARKED, totalScore,
@@ -888,12 +962,22 @@ public class MarkServiceImpl implements MarkService {
         if (list.isEmpty()) {
             return false;
         }
+        boolean selectiveAll = false;
         for (MarkLibrary library : list) {
             if (library.getStatus() != LibraryStatus.MARKED && library.getStatus() != LibraryStatus.ARBITRATED
                     && library.getStatus() != LibraryStatus.INSPECTED) {
                 // 有非完成状态的评卷任务,直接返回
                 return false;
             }
+            double markerScore = library.getStatus() == LibraryStatus.ARBITRATED ? library.getHeaderScore() : library
+                    .getMarkerScore();
+            if (markerScore == UN_SELECTIVE_SCORE) {
+                selectiveAll = true;
+            }
+        }
+        if (selectiveAll) {
+            group.setMarkScore(UN_SELECTIVE_SCORE);
+            return true;
         }
         // 开启三评
         if (ThirdPolicy.LOW_DIFF_HIGH_AVG.equals(group.getThirdPolicy()) && list.size() == 3) {
@@ -921,7 +1005,7 @@ public class MarkServiceImpl implements MarkService {
         }
         for (MarkLibrary library : list) {
             count++;
-            Double current = (library.getHeaderScore() != null ? library.getHeaderScore() : library.getMarkerScore());
+            Double current = library.getHeaderScore() != null ? library.getHeaderScore() : library.getMarkerScore();
             List<ScoreItem> scores = library.getScoreList();
             if (count == 1) {
                 // 首份评卷任务,直接取总分与明细
@@ -1160,8 +1244,6 @@ public class MarkServiceImpl implements MarkService {
             trialTrackDao.deleteByExamIdAndSubjectCodeAndGroupNumber(group.getExamId(), group.getSubjectCode(),
                     group.getNumber());
             trialTagDao.deleteByExamAndSubjectAndGroup(group.getExamId(), group.getSubjectCode(), group.getNumber());
-            trialHistoryDao.deleteByExamIdAndSubjectCodeAndGroupNumber(group.getExamId(), group.getSubjectCode(),
-                    group.getNumber());
         }
         updateLibraryCount(group);
         groupDao.resetCount(group.getExamId(), group.getSubjectCode(), group.getNumber());
@@ -1250,6 +1332,24 @@ public class MarkServiceImpl implements MarkService {
         }
     }
 
+    /**
+     * 考生分组判断是否评卷完成,以及后续的统一处理动作
+     *
+     * @param studentId
+     * @param group
+     */
+    private void checkStudentTrial(TrialLibrary library, MarkGroup group) {
+        updateStudentGroupStatus(library.getStudentId(), group.getExamId(), group.getSubjectCode(), group.getNumber(),
+                SubjectiveStatus.MARKED);
+        updateStudentGroupScore(library.getStudentId(), group.getExamId(), group.getSubjectCode(), group.getNumber(),
+                library.getMarkerScore(), library.getScoreList());
+        // 未分组的题目
+        long unGroupQuestionCount = questionDao.countByExamIdAndSubjectAndObjectiveAndGroupNumberIsNull(
+                group.getExamId(), group.getSubjectCode(), false);
+        long groupCount = groupDao.countByExamIdAndSubjectCode(group.getExamId(), group.getSubjectCode());
+        checkStudentSubjective(library.getStudentId(), groupCount, unGroupQuestionCount);
+    }
+
     /**
      * 考生分组判断是否评卷完成,以及后续的统一处理动作
      *
@@ -1319,8 +1419,7 @@ public class MarkServiceImpl implements MarkService {
         // scoreDao.deleteByStudentIdAndGroupNumber(studentId, groupNumber);
         List<ExamQuestion> questions = questionDao.findByExamIdAndSubjectCodeAndObjectiveAndGroupNumber(examId,
                 subjectCode, false, groupNumber);
-        for (int i = 0; i < scoreList.size(); i++) {
-            ScoreItem item = scoreList.get(i);
+        for (int i = 0; i < questions.size(); i++) {
             ExamQuestion question = questions.get(i);
             SubjectiveScore ss = new SubjectiveScore();
             ss.setStudentId(studentId);
@@ -1328,10 +1427,16 @@ public class MarkServiceImpl implements MarkService {
             ss.setSubjectCode(subjectCode);
             ss.setGroupNumber(groupNumber);
             ss.setGroupScore(score);
-            ss.setMainScore(0.0);
             ss.setMainNumber(question.getMainNumber());
             ss.setSubNumber(question.getSubNumber());
-            ss.setScore(item.getScore());
+            if (score != UN_SELECTIVE_SCORE) {
+                ScoreItem item = scoreList.get(i);
+                ss.setScore(item.getScore());
+                ss.setMainScore(0.0);
+            } else {
+                ss.setScore(score);
+                ss.setMainScore(score);
+            }
             scoreDao.saveAndFlush(ss);
         }
     }

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

@@ -30,7 +30,6 @@ import cn.com.qmth.stmms.biz.mark.model.MarkTrack;
 import cn.com.qmth.stmms.biz.mark.model.SpecialTagDTO;
 import cn.com.qmth.stmms.biz.mark.model.Task;
 import cn.com.qmth.stmms.biz.mark.model.TrackDTO;
-import cn.com.qmth.stmms.biz.mark.model.TrialHistory;
 import cn.com.qmth.stmms.biz.mark.model.TrialLibrary;
 import cn.com.qmth.stmms.biz.mark.model.TrialTag;
 import cn.com.qmth.stmms.biz.mark.model.TrialTrack;
@@ -56,6 +55,8 @@ public class TaskServiceImpl implements TaskService {
 
     private static Logger log = LoggerFactory.getLogger(TaskServiceImpl.class);
 
+    public static final double UN_SELECTIVE_SCORE = -1;
+
     @Autowired
     private MarkLibraryService libraryService;
 
@@ -142,6 +143,10 @@ public class TaskServiceImpl implements TaskService {
                 if (!sItems.isEmpty() && sItems.size() == sList.size()) {
                     step.setScore(sItems.get(i).getScore());
                 }
+                // 未选做
+                if (history.getTotalScore() != null && history.getTotalScore() == UN_SELECTIVE_SCORE) {
+                    step.setScore(UN_SELECTIVE_SCORE);
+                }
                 // 增加阅卷轨迹列表获取
                 String questionNumber = question.getQuestionNumber();
                 for (MarkTrack track : tracks) {
@@ -196,7 +201,7 @@ public class TaskServiceImpl implements TaskService {
     }
 
     @Override
-    public Task build(TrialLibrary library, TrialHistory history) {
+    public Task build(TrialLibrary library) {
         Exam exam = examService.findById(library.getExamId());
         ExamSubject subject = subjectService.find(library.getExamId(), library.getSubjectCode());
         ExamStudent student = studentService.findByExamIdAndExamNumber(library.getExamId(), library.getExamNumber());
@@ -210,7 +215,7 @@ public class TaskServiceImpl implements TaskService {
         task.setStudentName(student.getName());
         task.setExamNumber(library.getExamNumber());
         task.setSubject(subject);
-        task.setQuestionList(buildTrialStep(group, history));
+        task.setQuestionList(buildTrialStep(group, library));
         if (StringUtils.isNotBlank(student.getObjectiveScoreList())) {
             task.setObjectiveScore(student.getObjectiveScore());
         }
@@ -223,10 +228,10 @@ public class TaskServiceImpl implements TaskService {
             task.setSheetUrls(fileService.getSheetUris(library.getExamId(), library.getExamNumber(), 1,
                     student.getSheetCount()));
         }
-        if (history != null) {
-            task.setSpecialTagList(getTrialTagList(history));
-            task.setMarkTime(history.getMarkerTime());
-            task.setMarkerScore(history.getMarkerScore());
+        if (library.getMarkerId() != null) {
+            task.setSpecialTagList(getTrialTagList(library));
+            task.setMarkTime(library.getMarkerTime());
+            task.setMarkerScore(library.getMarkerScore());
             task.setPrevious(true);
         }
         return task;
@@ -249,6 +254,10 @@ public class TaskServiceImpl implements TaskService {
                 if (!sItems.isEmpty() && sItems.size() == sList.size()) {
                     step.setScore(sItems.get(i).getScore());
                 }
+                // 未选做
+                if (library.getMarkerScore() != null && library.getMarkerScore() == UN_SELECTIVE_SCORE) {
+                    step.setScore(UN_SELECTIVE_SCORE);
+                }
                 // 增加阅卷轨迹列表获取
                 String questionNumber = question.getQuestionNumber();
                 for (MarkTrack track : tracks) {
@@ -262,15 +271,15 @@ public class TaskServiceImpl implements TaskService {
         return list;
     }
 
-    private List<MarkStepDTO> buildTrialStep(MarkGroup group, TrialHistory history) {
+    private List<MarkStepDTO> buildTrialStep(MarkGroup group, TrialLibrary library) {
         List<MarkStepDTO> list = new LinkedList<MarkStepDTO>();
         List<ExamQuestion> sList = questionService.findByExamAndSubjectAndObjectiveAndGroupNumber(group.getExamId(),
                 group.getSubjectCode(), false, group.getNumber());
         List<TrialTrack> tracks = new ArrayList<TrialTrack>();
         List<ScoreItem> sItems = new ArrayList<ScoreItem>();
-        if (history != null) {
-            tracks = trialService.findTrack(history.getLibraryId(), history.getMarkerId());
-            sItems = history.getScoreList();
+        if (library.getMarkerId() != null) {
+            tracks = trialService.findTrack(library.getId());
+            sItems = library.getScoreList();
         }
         for (int i = 0; i < sList.size(); i++) {
             ExamQuestion question = sList.get(i);
@@ -278,6 +287,9 @@ public class TaskServiceImpl implements TaskService {
             if (!sItems.isEmpty() && sItems.size() == sList.size()) {
                 step.setScore(sItems.get(i).getScore());
             }
+            if (library.getMarkerScore() != null && library.getMarkerScore() == UN_SELECTIVE_SCORE) {
+                step.setScore(UN_SELECTIVE_SCORE);
+            }
             // 增加阅卷轨迹列表获取
             String questionNumber = question.getQuestionNumber();
             for (TrialTrack track : tracks) {
@@ -322,9 +334,9 @@ public class TaskServiceImpl implements TaskService {
         return specialTags;
     }
 
-    public SpecialTagDTO[] getTrialTagList(TrialHistory history) {
+    public SpecialTagDTO[] getTrialTagList(TrialLibrary library) {
         SpecialTagDTO[] specialTags = null;
-        List<TrialTag> list = trialService.findTag(history.getLibraryId(), history.getMarkerId());
+        List<TrialTag> list = trialService.findTag(library.getId());
         if (!list.isEmpty()) {
             specialTags = new SpecialTagDTO[list.size()];
             for (int i = 0; i < list.size(); i++) {

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

@@ -1,31 +1,31 @@
 package cn.com.qmth.stmms.biz.mark.service.Impl;
 
+import java.util.LinkedList;
+import java.util.List;
+
+import javax.persistence.criteria.CriteriaBuilder;
+import javax.persistence.criteria.CriteriaQuery;
+import javax.persistence.criteria.Predicate;
+import javax.persistence.criteria.Root;
+
+import org.apache.commons.lang.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.Sort;
+import org.springframework.data.domain.Sort.Direction;
+import org.springframework.data.jpa.domain.Specification;
+import org.springframework.stereotype.Service;
+
 import cn.com.qmth.stmms.biz.common.BaseQuery;
 import cn.com.qmth.stmms.biz.common.BaseQueryService;
-import cn.com.qmth.stmms.biz.mark.dao.TrialHistoryDao;
 import cn.com.qmth.stmms.biz.mark.dao.TrialLibraryDao;
 import cn.com.qmth.stmms.biz.mark.dao.TrialTagDao;
 import cn.com.qmth.stmms.biz.mark.dao.TrialTrackDao;
-import cn.com.qmth.stmms.biz.mark.model.TrialHistory;
 import cn.com.qmth.stmms.biz.mark.model.TrialLibrary;
 import cn.com.qmth.stmms.biz.mark.model.TrialTag;
 import cn.com.qmth.stmms.biz.mark.model.TrialTrack;
 import cn.com.qmth.stmms.biz.mark.query.TrialLibrarySearchQuery;
 import cn.com.qmth.stmms.biz.mark.service.TrialService;
-import org.apache.commons.lang.StringUtils;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.data.domain.Page;
-import org.springframework.data.domain.Sort;
-import org.springframework.data.domain.Sort.Direction;
-import org.springframework.data.jpa.domain.Specification;
-import org.springframework.stereotype.Service;
-
-import javax.persistence.criteria.CriteriaBuilder;
-import javax.persistence.criteria.CriteriaQuery;
-import javax.persistence.criteria.Predicate;
-import javax.persistence.criteria.Root;
-import java.util.LinkedList;
-import java.util.List;
 
 @Service
 public class TrialServiceImpl extends BaseQueryService<TrialLibrary> implements TrialService {
@@ -33,9 +33,6 @@ public class TrialServiceImpl extends BaseQueryService<TrialLibrary> implements
     @Autowired
     private TrialLibraryDao libraryDao;
 
-    @Autowired
-    private TrialHistoryDao historyDao;
-
     @Autowired
     private TrialTrackDao trackDao;
 
@@ -71,9 +68,9 @@ public class TrialServiceImpl extends BaseQueryService<TrialLibrary> implements
     }
 
     @Override
-    public List<TrialHistory> findHistory(Integer examId, String subjectCode, Integer groupNumber, Integer markerId,
+    public List<TrialLibrary> findHistory(Integer examId, String subjectCode, Integer groupNumber, Integer markerId,
             int pageNumber, int pageSize, Sort sort, Double markerScore) {
-        BaseQuery<TrialHistory> query = new BaseQuery<>();
+        BaseQuery<TrialLibrary> query = new BaseQuery<>();
         query.setPageNumber(pageNumber);
         query.setPageSize(pageSize);
         if (sort != null) {
@@ -82,43 +79,22 @@ public class TrialServiceImpl extends BaseQueryService<TrialLibrary> implements
             query.setSort(new Sort(Direction.DESC, "markerTime"));
         }
         if (markerScore != null) {
-            return historyDao.findByExamIdAndSubjectCodeAndGroupNumberAndPkMarkerIdAndMarkerScore(examId, subjectCode,
+            return libraryDao.findByExamIdAndSubjectCodeAndGroupNumberAndMarkerIdAndMarkerScore(examId, subjectCode,
                     groupNumber, markerId, markerScore, query);
         } else {
-            return historyDao
-                    .findByExamIdAndSubjectCodeAndGroupNumberAndPkMarkerId(examId, subjectCode, groupNumber, markerId,
-                            query);
+            return libraryDao.findByExamIdAndSubjectCodeAndGroupNumberAndMarkerId(examId, subjectCode, groupNumber,
+                    markerId, query);
         }
     }
 
     @Override
-    public List<TrialHistory> findHistory(Integer libraryId) {
-        return historyDao.findByPkLibraryId(libraryId);
-    }
-
-    @Override
-    public TrialHistory findHistory(Integer libraryId, Integer markerId) {
-        return historyDao.findByPkLibraryIdAndPkMarkerId(libraryId, markerId);
+    public List<TrialTrack> findTrack(Integer libraryId) {
+        return trackDao.findByPkLibraryId(libraryId);
     }
 
     @Override
-    public long countHistory(Integer libraryId) {
-        return historyDao.countByLibraryId(libraryId);
-    }
-
-    @Override
-    public long countMarkerHistory(Integer markerId) {
-        return historyDao.countByMarkerId(markerId);
-    }
-
-    @Override
-    public List<TrialTrack> findTrack(Integer libraryId, Integer markerId) {
-        return trackDao.findByPkLibraryIdAndPkMarkerId(libraryId, markerId);
-    }
-
-    @Override
-    public List<TrialTag> findTag(Integer libraryId, Integer markerId) {
-        return tagDao.findByLibraryIdAndMarkerIdOrderByIdAsc(libraryId, markerId);
+    public List<TrialTag> findTag(Integer libraryId) {
+        return tagDao.findByLibraryIdOrderByIdAsc(libraryId);
     }
 
     private Specification<TrialLibrary> buildSpecification(final TrialLibrarySearchQuery query) {
@@ -145,17 +121,16 @@ public class TrialServiceImpl extends BaseQueryService<TrialLibrary> implements
                 if (query.getStudentId() != null) {
                     predicates.add(cb.equal(root.get("studentId"), query.getStudentId()));
                 }
-                return predicates.isEmpty() ?
-                        cb.conjunction() :
-                        cb.and(predicates.toArray(new Predicate[predicates.size()]));
+                return predicates.isEmpty() ? cb.conjunction() : cb.and(predicates.toArray(new Predicate[predicates
+                        .size()]));
             }
         };
     }
 
     @Override
-    public List<TrialHistory> findHistory(Integer examId, String subjectCode, Integer groupNumber, Integer markerId,
+    public List<TrialLibrary> findHistory(Integer examId, String subjectCode, Integer groupNumber, Integer markerId,
             String secretNumber, int pageNumber, int pageSize, Sort sort) {
-        BaseQuery<TrialHistory> query = new BaseQuery<>();
+        BaseQuery<TrialLibrary> query = new BaseQuery<>();
         query.setPageNumber(pageNumber);
         query.setPageSize(pageSize);
         if (sort != null) {
@@ -163,8 +138,12 @@ public class TrialServiceImpl extends BaseQueryService<TrialLibrary> implements
         } else {
             query.setSort(new Sort(Direction.DESC, "markerTime"));
         }
-        return historyDao
-                .findByExamIdAndSubjectCodeAndGroupNumberAndPkMarkerIdAndSecretNumber(examId, subjectCode, groupNumber,
-                        markerId, secretNumber, query);
+        return libraryDao.findByExamIdAndSubjectCodeAndGroupNumberAndMarkerIdAndSecretNumber(examId, subjectCode,
+                groupNumber, markerId, secretNumber, query);
+    }
+
+    @Override
+    public long countByMarkerId(Integer markerId) {
+        return libraryDao.countByMarkerId(markerId);
     }
 }

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

@@ -1,12 +1,21 @@
 package cn.com.qmth.stmms.biz.mark.service;
 
-import cn.com.qmth.stmms.biz.exam.model.*;
-import cn.com.qmth.stmms.biz.mark.model.*;
+import java.util.List;
+
+import cn.com.qmth.stmms.biz.exam.model.ExamQuestion;
+import cn.com.qmth.stmms.biz.exam.model.ExamStudent;
+import cn.com.qmth.stmms.biz.exam.model.ExamSubject;
+import cn.com.qmth.stmms.biz.exam.model.MarkGroup;
+import cn.com.qmth.stmms.biz.exam.model.Marker;
+import cn.com.qmth.stmms.biz.mark.model.ArbitrateHistory;
+import cn.com.qmth.stmms.biz.mark.model.MarkLibrary;
+import cn.com.qmth.stmms.biz.mark.model.MarkResult;
+import cn.com.qmth.stmms.biz.mark.model.MarkStepDTO;
+import cn.com.qmth.stmms.biz.mark.model.SubmitResult;
+import cn.com.qmth.stmms.biz.mark.model.TrialLibrary;
 import cn.com.qmth.stmms.common.enums.ScorePolicy;
 import cn.com.qmth.stmms.common.enums.ThirdPolicy;
 
-import java.util.List;
-
 public interface MarkService {
 
     /**
@@ -44,7 +53,8 @@ public interface MarkService {
      * @param group
      * @param third
      */
-    void updateGroup(MarkGroup group, List<ExamQuestion> questionList, ScorePolicy policy, ThirdPolicy third);
+    void updateGroup(MarkGroup group, List<ExamQuestion> questionList, ScorePolicy policy, ThirdPolicy third,
+            boolean selective);
 
     /**
      * 评卷员申请领取某个正式评卷任务

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

@@ -7,7 +7,6 @@ import cn.com.qmth.stmms.biz.exam.model.MarkGroup;
 import cn.com.qmth.stmms.biz.mark.model.ArbitrateHistory;
 import cn.com.qmth.stmms.biz.mark.model.MarkLibrary;
 import cn.com.qmth.stmms.biz.mark.model.Task;
-import cn.com.qmth.stmms.biz.mark.model.TrialHistory;
 import cn.com.qmth.stmms.biz.mark.model.TrialLibrary;
 import cn.com.qmth.stmms.biz.mark.query.MarkLibrarySearchQuery;
 
@@ -17,7 +16,7 @@ public interface TaskService {
 
     Task build(ArbitrateHistory history, MarkGroup group);
 
-    Task build(TrialLibrary library, TrialHistory history);
+    Task build(TrialLibrary library);
 
     Task build(MarkLibrary library);
 

+ 9 - 15
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/mark/service/TrialService.java

@@ -1,13 +1,13 @@
 package cn.com.qmth.stmms.biz.mark.service;
 
-import cn.com.qmth.stmms.biz.mark.model.TrialHistory;
+import java.util.List;
+
+import org.springframework.data.domain.Sort;
+
 import cn.com.qmth.stmms.biz.mark.model.TrialLibrary;
 import cn.com.qmth.stmms.biz.mark.model.TrialTag;
 import cn.com.qmth.stmms.biz.mark.model.TrialTrack;
 import cn.com.qmth.stmms.biz.mark.query.TrialLibrarySearchQuery;
-import org.springframework.data.domain.Sort;
-
-import java.util.List;
 
 public interface TrialService {
 
@@ -20,22 +20,16 @@ public interface TrialService {
 
     long countLibrary(Integer examId, String subjectCode, Integer groupNumber);
 
-    List<TrialHistory> findHistory(Integer libraryId);
-
-    TrialHistory findHistory(Integer libraryId, Integer markerId);
-
-    long countHistory(Integer libraryId);
-
-    long countMarkerHistory(Integer markerId);
+    long countByMarkerId(Integer markerId);
 
-    List<TrialHistory> findHistory(Integer examId, String subjectCode, Integer groupNumber, Integer markerId,
+    List<TrialLibrary> findHistory(Integer examId, String subjectCode, Integer groupNumber, Integer markerId,
             int pageNumber, int pageSize, Sort sort, Double markerScore);
 
-    List<TrialTrack> findTrack(Integer libraryId, Integer markerId);
+    List<TrialTrack> findTrack(Integer libraryId);
 
-    List<TrialTag> findTag(Integer libraryId, Integer markerId);
+    List<TrialTag> findTag(Integer libraryId);
 
-    List<TrialHistory> findHistory(Integer examId, String subjectCode, Integer groupNumber, Integer markerId,
+    List<TrialLibrary> findHistory(Integer examId, String subjectCode, Integer groupNumber, Integer markerId,
             String secretNumber, int pageNumber, int pageSize, Sort querySort);
 
 }

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

@@ -10,7 +10,7 @@ public enum HistoryStatus {
     private String name;
 
     private int value;
-    
+
     private static List<HistoryStatus> options;
 
     private HistoryStatus(String name, int value) {
@@ -34,7 +34,7 @@ public enum HistoryStatus {
         }
         return null;
     }
-    
+
     public static List<HistoryStatus> getOptionList() {
         if (options == null) {
             options = new LinkedList<>();

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

@@ -4,7 +4,7 @@ import java.util.LinkedList;
 import java.util.List;
 
 public enum LibraryStatus {
-    WAITING("未处理", 0), MARKED("已给分", 1), REJECTED("已打回", 2), WAIT_ARBITRATE("等待仲裁", 3), ARBITRATED("已仲裁", 4), PROBLEM(
+    WAITING("未处理", 0), MARKED("已", 1), REJECTED("已打回", 2), WAIT_ARBITRATE("等待仲裁", 3), ARBITRATED("已仲裁", 4), PROBLEM(
             "问题卷", 5), INSPECTED("已复核", 6);
 
     private String name;

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

@@ -5,7 +5,7 @@ import java.util.List;
 
 public enum SubjectiveStatus {
 
-    UNMARK("未评完"), MARKED("已评完"), INSPECTED("已复核");
+    UNMARK("未评完"), TRIAL("试评"), MARKED("已评完"), INSPECTED("已复核");
 
     private String name;
 

+ 12 - 4
stmms-web/src/main/java/cn/com/qmth/stmms/admin/dto/ExamStudentDTO.java

@@ -1,5 +1,6 @@
 package cn.com.qmth.stmms.admin.dto;
 
+import java.util.LinkedList;
 import java.util.List;
 
 import org.apache.commons.lang.StringUtils;
@@ -57,7 +58,9 @@ public class ExamStudentDTO {
 
     private List<ScoreItem> objectiveList;
 
-    private List<ScoreItem> subjectiveList;
+    private List<String> subjectiveList;
+
+    public static final String SPLIT = ";";
 
     public ExamStudentDTO(ExamStudent student) {
         setSubjectCode(student.getSubjectCode());
@@ -76,7 +79,12 @@ public class ExamStudentDTO {
         setCollege(student.getCollege());
         setTeacher(student.getTeacher());
         setObjectiveList(student.getScoreList(true));
-        setSubjectiveList(student.getScoreList(false));
+        List<String> subjectiveList = new LinkedList<String>();
+        String[] values = StringUtils.split(student.getSubjectiveScoreList(), SPLIT);
+        for (String value : values) {
+            subjectiveList.add(value);
+        }
+        setSubjectiveList(subjectiveList);
     }
 
     public String getSubjectCode() {
@@ -207,11 +215,11 @@ public class ExamStudentDTO {
         this.objectiveList = objectiveList;
     }
 
-    public List<ScoreItem> getSubjectiveList() {
+    public List<String> getSubjectiveList() {
         return subjectiveList;
     }
 
-    public void setSubjectiveList(List<ScoreItem> subjectiveList) {
+    public void setSubjectiveList(List<String> subjectiveList) {
         this.subjectiveList = subjectiveList;
     }
 

+ 35 - 5
stmms-web/src/main/java/cn/com/qmth/stmms/admin/dto/SubjectQuestionDTO.java

@@ -1,12 +1,19 @@
 package cn.com.qmth.stmms.admin.dto;
 
+import java.util.ArrayList;
+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 org.apache.commons.lang.StringUtils;
+
 import cn.com.qmth.stmms.biz.exam.model.ExamQuestion;
 import cn.com.qmth.stmms.biz.exam.model.MarkGroup;
 import cn.com.qmth.stmms.biz.mark.model.PictureConfigItem;
-import org.apache.commons.lang.StringUtils;
-
-import java.util.*;
-import java.util.Map.Entry;
 
 public class SubjectQuestionDTO {
 
@@ -22,6 +29,8 @@ public class SubjectQuestionDTO {
 
     private boolean objective;
 
+    private Integer trialCount;
+
     private Map<String, List<ExamQuestion>> paperTypeList;
 
     private Map<Integer, MarkGroup> groups;
@@ -34,6 +43,7 @@ public class SubjectQuestionDTO {
         this.groups = new HashMap<Integer, MarkGroup>();
         this.totalScore = 0d;
         this.objective = objective;
+        this.trialCount = 0;
     }
 
     public void addQuestion(ExamQuestion question) {
@@ -58,11 +68,12 @@ public class SubjectQuestionDTO {
                     group = new MarkGroup(examId, subjectCode, question.getGroupNumber(),
                             PictureConfigItem.parse(question.getPicList()), 0d, question.getDoubleRate(),
                             question.getArbitrateThreshold(), question.getScorePolicy(), question.getMarkMode(),
-                            question.getTrialCount(), false, false, 1);
+                            question.getTrialCount(), false, false, 1, false);
                     group.setImportQuestionList(new LinkedList<>());
                     groups.put(question.getGroupNumber(), group);
                 }
                 group.getImportQuestionList().add(question);
+                this.trialCount = question.getTrialCount();
                 // group.setTotalScore(group.getTotalScore() +
                 // question.getTotalScore());
                 // totalScore += question.getTotalScore();
@@ -86,6 +97,14 @@ public class SubjectQuestionDTO {
         return groups;
     }
 
+    public Integer getTrialCount() {
+        return trialCount;
+    }
+
+    public void setTrialCount(Integer trialCount) {
+        this.trialCount = trialCount;
+    }
+
     public boolean validate(List<String> error, Map<Integer, String> titleMap) {
         if (list.size() > 0) {
             Set<String> numberSet = new HashSet<String>();
@@ -238,12 +257,23 @@ public class SubjectQuestionDTO {
     }
 
     public boolean validateGroupNumber(List<String> error) {
+        Map<String, Integer> trialMap = new HashMap<String, Integer>();
         for (ExamQuestion question : list) {
             if (question.getGroupNumber() == null || question.getGroupNumber() < 0) {
                 error.add("[" + subjectCode + "] 有评卷分组为空的记录");
                 return false;
             }
+            Integer trialCount = trialMap.get(question.getSubjectCode());
+            if (trialCount == null) {
+                trialCount = question.getTrialCount();
+                trialMap.put(question.getSubjectCode(), question.getTrialCount());
+            }
+            if (question.getTrialCount() != trialCount) {
+                error.add("[" + subjectCode + "] 有试评数量不一致的记录");
+                return false;
+            }
         }
         return true;
     }
+
 }

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

@@ -54,6 +54,9 @@ public class SubjectiveQuestionDTO implements QuestionDTO {
     @ExcelField(title = "试评数量(0-跳过试评)", align = 2, sort = 140)
     private Integer trialCount;
 
+    @ExcelField(title = "选做题数量", align = 2, sort = 150)
+    private Integer selectiveCount;
+
     public SubjectiveQuestionDTO() {
 
     }
@@ -74,7 +77,7 @@ public class SubjectiveQuestionDTO implements QuestionDTO {
         setScorePolicy(group != null && group.getScorePolicy() != null ? group.getScorePolicy().getValue()
                 : ScorePolicy.AVG.getValue());
         setMarkMode(group != null && group.getMarkMode() != null ? group.getMarkMode().toString() : "");
-        setTrialCount(group != null && group.getTrialCount() != null ? group.getTrialCount() : 0);
+        setTrialCount(subject != null && subject.getTrialCount() != null ? subject.getTrialCount() : 0);
     }
 
     public ExamQuestion transform() {
@@ -222,4 +225,12 @@ public class SubjectiveQuestionDTO implements QuestionDTO {
         this.groupNumber = groupNumber;
     }
 
+    public Integer getSelectiveCount() {
+        return selectiveCount;
+    }
+
+    public void setSelectiveCount(Integer selectiveCount) {
+        this.selectiveCount = selectiveCount;
+    }
+
 }

+ 11 - 6
stmms-web/src/main/java/cn/com/qmth/stmms/admin/exam/ArbitrateController.java

@@ -159,7 +159,12 @@ public class ArbitrateController extends BaseExamController {
         if (historyId != null) {
             ArbitrateHistory history = arbitrateService.findById(historyId);
             subjectCode = history.getSubjectCode();
-            groupNumber = history.getGroupNumber();
+            MarkGroup group = groupService.findOne(examId, subjectCode, history.getGroupNumber());
+            setting.accumulate("selective", group.isSelective());
+        }
+        if (subjectCode != null && groupNumber != null) {
+            MarkGroup group = groupService.findOne(examId, subjectCode, groupNumber);
+            setting.accumulate("selective", group.isSelective());
         }
         ExamSubject examSubject = subjectService.find(examId, subjectCode);
         setting.accumulate("fileServer", fileService.getFileServer());
@@ -242,9 +247,10 @@ public class ArbitrateController extends BaseExamController {
             query.setGroupNumber(groupNumber);
             query.setStatus(HistoryStatus.MARKED);
             query.setUserId(wu.getUser().getId());
+            query.setSecretNumber(secretNumber);
+            query.setStartScroe(0.0);
             query.setPageNumber(pageNumber);
             query.setPageSize(pageSize);
-            query.setSecretNumber(secretNumber);
             if (querySort != null) {
                 query.setSort(querySort);
             } else {
@@ -312,15 +318,14 @@ public class ArbitrateController extends BaseExamController {
         WebUser wu = RequestUtils.getWebUser(request);
         JSONObject result = new JSONObject();
         ArbitrateHistory history = arbitrateService.findById(markResult.getLibraryId());
-        if (history != null && subjectCheck(history.getSubjectCode(), wu) && markResult.getMarkerScore() >= 0) {
+        if (history != null && subjectCheck(history.getSubjectCode(), wu)) {
             try {
                 lockService.watch(LockType.EXAM_SUBJECT, history.getExamId(), history.getSubjectCode());
                 lockService.watch(LockType.GROUP, history.getExamId(), history.getSubjectCode(),
                         history.getGroupNumber());
-
                 history.setUserId(wu.getUser().getId());
-                history.setTotalScore(markResult.getMarkerScore());
-                history.setScoreList(markResult.getScoreList());
+                history.setTotalScore(markResult.isUnselective() ? -1 : markResult.getMarkerScore());
+                history.setScoreList(markResult.isUnselective() ? null : markResult.getScoreList());
                 history.setStatus(HistoryStatus.MARKED);
                 history.setUpdateTime(new Date());
                 markService.processArbitrate(history);

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

@@ -71,6 +71,7 @@ public class InspectedController extends BaseExamController {
     @RequestMapping
     public String list(Model model, HttpServletRequest request, ExamStudentSearchQuery query,
             @RequestParam(required = false) SubjectiveStatus status,
+            @RequestParam(required = false, defaultValue = "false") boolean unselective,
             @RequestParam(required = false) Integer mainNumber, @RequestParam(required = false) Double mainStartScore,
             @RequestParam(required = false) Double mainEndScore, @RequestParam(required = false) Double questionScore) {
         int examId = getSessionExamId(request);
@@ -85,11 +86,11 @@ public class InspectedController extends BaseExamController {
             query.setSubjectCode(subjectList.get(0).getCode());
         }
         List<ExamStudent> list = inspectedService.findByQuery(query, status, mainNumber, mainStartScore, mainEndScore,
-                questionScore);
+                questionScore, unselective);
         Integer totalCount = inspectedService.countByQuery(query, null, mainNumber, mainStartScore, mainEndScore,
-                questionScore);
+                questionScore, unselective);
         Integer inspectCount = inspectedService.countByQuery(query, SubjectiveStatus.MARKED, mainNumber,
-                mainStartScore, mainEndScore, questionScore);
+                mainStartScore, mainEndScore, questionScore, unselective);
         query.setResult(list);
         query.setTotalCount(totalCount);
         model.addAttribute("query", query);
@@ -103,6 +104,7 @@ public class InspectedController extends BaseExamController {
         model.addAttribute("subjectList", subjectList);
         model.addAttribute("statusList", SubjectiveStatus.getOptionList());
         model.addAttribute("status", status);
+        model.addAttribute("unselective", unselective);
         model.addAttribute("exam", exam);
         return "modules/exam/inspectedList";
     }
@@ -111,9 +113,10 @@ public class InspectedController extends BaseExamController {
     @RequestMapping(value = "/getTask", method = RequestMethod.POST)
     @ResponseBody
     public Task getTask(HttpServletRequest request, RedirectAttributes redirectAttributes,
-            ExamStudentSearchQuery query, @RequestParam(required = false) Integer mainNumber,
-            @RequestParam(required = false) Double mainStartScore, @RequestParam(required = false) Double mainEndScore,
-            @RequestParam(required = false) Double questionScore, @RequestParam(required = false) Integer studentId) {
+            ExamStudentSearchQuery query, @RequestParam(required = false, defaultValue = "false") boolean unselective,
+            @RequestParam(required = false) Integer mainNumber, @RequestParam(required = false) Double mainStartScore,
+            @RequestParam(required = false) Double mainEndScore, @RequestParam(required = false) Double questionScore,
+            @RequestParam(required = false) Integer studentId) {
         int examId = getSessionExamId(request);
         WebUser wu = RequestUtils.getWebUser(request);
         Task task = null;
@@ -136,7 +139,7 @@ public class InspectedController extends BaseExamController {
                 query.setSubjectCode(subjectList.get(0).getCode());
             }
             list = inspectedService.findByQuery(query, SubjectiveStatus.MARKED, mainNumber, mainStartScore,
-                    mainEndScore, questionScore);
+                    mainEndScore, questionScore, unselective);
             if (list.isEmpty()) {
                 break;
             }
@@ -306,13 +309,14 @@ public class InspectedController extends BaseExamController {
     @RequestMapping(value = "/getStatus", method = RequestMethod.POST)
     @ResponseBody
     public JSONObject status(HttpServletRequest request, ExamStudentSearchQuery query,
+            @RequestParam(required = false, defaultValue = "false") boolean unselective,
             @RequestParam(required = false) Integer mainNumber, @RequestParam(required = false) Double mainStartScore,
             @RequestParam(required = false) Double mainEndScore, @RequestParam(required = false) Double questionScore) {
         JSONObject status = new JSONObject();
         int examId = getSessionExamId(request);
         query.setExamId(examId);
         Integer totalCount = inspectedService.countByQuery(query, SubjectiveStatus.MARKED, mainNumber, mainStartScore,
-                mainEndScore, questionScore);
+                mainEndScore, questionScore, unselective);
         status.accumulate("totalCount", totalCount);
         status.accumulate("valid", true);
         return status;

+ 99 - 6
stmms-web/src/main/java/cn/com/qmth/stmms/admin/exam/MarkGroupController.java

@@ -1,7 +1,9 @@
 package cn.com.qmth.stmms.admin.exam;
 
 import java.util.ArrayList;
+import java.util.HashSet;
 import java.util.List;
+import java.util.Set;
 
 import javax.servlet.http.HttpServletRequest;
 
@@ -20,6 +22,7 @@ import org.springframework.stereotype.Controller;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.ui.Model;
 import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
 import org.springframework.web.bind.annotation.RequestParam;
 import org.springframework.web.bind.annotation.ResponseBody;
 import org.springframework.web.servlet.mvc.support.RedirectAttributes;
@@ -30,6 +33,7 @@ import cn.com.qmth.stmms.biz.exam.model.ExamQuestion;
 import cn.com.qmth.stmms.biz.exam.model.ExamStudent;
 import cn.com.qmth.stmms.biz.exam.model.ExamSubject;
 import cn.com.qmth.stmms.biz.exam.model.MarkGroup;
+import cn.com.qmth.stmms.biz.exam.model.SelectiveGroup;
 import cn.com.qmth.stmms.biz.exam.query.ExamStudentSearchQuery;
 import cn.com.qmth.stmms.biz.exam.service.ExamQuestionService;
 import cn.com.qmth.stmms.biz.exam.service.ExamService;
@@ -37,6 +41,7 @@ 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.SelectiveGroupService;
 import cn.com.qmth.stmms.biz.file.service.FileService;
 import cn.com.qmth.stmms.biz.lock.LockService;
 import cn.com.qmth.stmms.biz.mark.model.PictureConfigItem;
@@ -91,6 +96,9 @@ public class MarkGroupController extends BaseExamController {
     @Autowired
     private FileService fileService;
 
+    @Autowired
+    private SelectiveGroupService selectiveGroupService;
+
     @Qualifier("task-executor")
     @Autowired
     private AsyncTaskExecutor taskExecutor;
@@ -272,7 +280,19 @@ public class MarkGroupController extends BaseExamController {
         model.addAttribute("scorePolicyList", ScorePolicy.values());
         model.addAttribute("thirdPolicyList", ThirdPolicy.values());
         model.addAttribute("exam", examService.findById(examId));
-        model.addAttribute("questionList", questionService.findByExamAndSubjectAndObjective(examId, subjectCode, false));
+        List<ExamQuestion> questions = questionService.findByExamAndSubjectAndObjective(examId, subjectCode, false);
+        List<SelectiveGroup> list = selectiveGroupService.findByExamIdAndSubjectCode(examId, subjectCode);
+        Set<Integer> mainNumbers = new HashSet<Integer>();
+        for (SelectiveGroup selectiveGroup : list) {
+            mainNumbers.add(selectiveGroup.getMainNumber());
+        }
+        for (ExamQuestion examQuestion : questions) {
+            if (mainNumbers.contains(examQuestion.getMainNumber())) {
+                examQuestion.setSelective(true);
+            }
+        }
+        model.addAttribute("questionList", questions);
+        model.addAttribute("groupCount", groupService.countByExamAndSubject(examId, subjectCode));
         return "modules/exam/groupAdd";
     }
 
@@ -312,9 +332,19 @@ public class MarkGroupController extends BaseExamController {
         MarkGroup group = groupService.findOne(examId, subjectCode, number);
         if (group != null) {
             group.setPicList(buildPictureConfig(group));
-            List<ExamQuestion> list = questionService.findByExamAndSubjectAndObjective(examId, subjectCode, false);
+            List<ExamQuestion> questions = questionService.findByExamAndSubjectAndObjective(examId, subjectCode, false);
+            List<SelectiveGroup> list = selectiveGroupService.findByExamIdAndSubjectCode(examId, subjectCode);
+            Set<Integer> mainNumbers = new HashSet<Integer>();
+            for (SelectiveGroup selectiveGroup : list) {
+                mainNumbers.add(selectiveGroup.getMainNumber());
+            }
+            for (ExamQuestion examQuestion : questions) {
+                if (mainNumbers.contains(examQuestion.getMainNumber())) {
+                    examQuestion.setSelective(true);
+                }
+            }
             model.addAttribute("group", group);
-            model.addAttribute("questionList", list);
+            model.addAttribute("questionList", questions);
             model.addAttribute("pictureConfig", group.getPicList());
             model.addAttribute("markModeList", MarkMode.values());
             model.addAttribute("scorePolicyList", ScorePolicy.values());
@@ -388,10 +418,21 @@ public class MarkGroupController extends BaseExamController {
             try {
                 if (questionIds != null && reset.booleanValue()) {
                     // advance update
+                    if (!checkSelective(examId, subjectCode, questionIds)) {
+                        addMessage(redirectAttributes, "选做题和非选做题不能在一组");
+                        redirectAttributes.addAttribute("subjectCode", subjectCode);
+                        redirectAttributes.addAttribute("number", number);
+                        return "redirect:/admin/exam/group/edit-simple";
+                    }
                     List<ExamQuestion> questionList = new ArrayList<ExamQuestion>();
+                    boolean selective = false;
                     for (Integer questionId : questionIds) {
                         ExamQuestion question = questionService.findById(questionId);
                         questionList.add(question);
+                        if (selective == false
+                                && selectiveGroupService.findOne(examId, subjectCode, question.getMainNumber()) != null) {
+                            selective = true;
+                        }
                     }
                     if (!questionList.isEmpty()) {
                         ScorePolicy policy = scorePolicy != null ? ScorePolicy.findByValue(scorePolicy) : null;
@@ -400,7 +441,7 @@ public class MarkGroupController extends BaseExamController {
                         try {
                             lockService.waitlock(LockType.GROUP, true, group.getExamId(), group.getSubjectCode(),
                                     group.getNumber());
-                            markService.updateGroup(group, questionList, policy, third);
+                            markService.updateGroup(group, questionList, policy, third, selective);
                         } catch (Exception e) {
                             log.error("update group error", e);
                             throw new RuntimeException("重置更新大题失败", e);
@@ -433,7 +474,7 @@ public class MarkGroupController extends BaseExamController {
                 groupService.updateArbitrateThreshold(examId, subjectCode, number, arbitrateThreshold);
                 groupService.updateMarkMode(examId, subjectCode, number, markMode);
                 if (trialCount != null && trialCount > 0 && group.getStatus() == MarkStatus.TRIAL) {
-                    groupService.updateTrialCount(examId, subjectCode, number, trialCount);
+                    subjectService.updateTrialCount(examId, subjectCode, trialCount);
                 }
                 if (sheetView != null) {
                     groupService.updateSheetView(examId, subjectCode, number, sheetView);
@@ -460,6 +501,28 @@ public class MarkGroupController extends BaseExamController {
         }
     }
 
+    private boolean checkSelective(Integer examId, String subjectCode, Integer[] questionIds) {
+        Set<Integer> mainNumbers = new HashSet<Integer>();
+        List<SelectiveGroup> list = selectiveGroupService.findByExamIdAndSubjectCode(examId, subjectCode);
+        for (SelectiveGroup selectiveGroup : list) {
+            mainNumbers.add(selectiveGroup.getMainNumber());
+        }
+        List<ExamQuestion> selectives = new ArrayList<ExamQuestion>();
+        for (Integer questionId : questionIds) {
+            ExamQuestion question = questionService.findById(questionId);
+            if (mainNumbers.contains(question.getMainNumber())) {
+                selectives.add(question);
+            }
+        }
+        if (questionIds.length == selectives.size()) {
+            return true;
+        }
+        if (selectives.size() == 0) {
+            return true;
+        }
+        return false;
+    }
+
     @Logging(menu = "新增大题", type = LogType.ADD)
     @SuppressWarnings("unchecked")
     @RequestMapping("/insert")
@@ -484,6 +547,10 @@ public class MarkGroupController extends BaseExamController {
             addMessage(redirectAttributes, "题目不能为空");
             redirectAttributes.addAttribute("subjectCode", subjectCode);
             return "redirect:/admin/exam/group/add";
+        } else if (!checkSelective(examId, subjectCode, questionIds)) {
+            addMessage(redirectAttributes, "选做题和非选做题不能在一组");
+            redirectAttributes.addAttribute("subjectCode", subjectCode);
+            return "redirect:/admin/exam/group/add";
         } else {
             try {
                 // create group
@@ -497,20 +564,28 @@ public class MarkGroupController extends BaseExamController {
                 if (questionIds != null && questionIds.length > 0) {
                     List<ExamQuestion> list = new ArrayList<ExamQuestion>();
                     double totalScore = 0d;
+                    boolean selective = false;
                     for (Integer questionId : questionIds) {
                         ExamQuestion question = questionService.findById(questionId);
                         question.setGroupNumber(number);
                         list.add(question);
                         totalScore = totalScore + question.getTotalScore();
+                        if (selective == false
+                                && selectiveGroupService.findOne(examId, subjectCode, question.getMainNumber()) != null) {
+                            selective = true;
+                        }
                     }
                     group = new MarkGroup(examId, subjectCode, number, picConfigList, totalScore, doubleRate,
                             arbitrateThreshold, scorePolicy, markMode, trialCount, sheetView, enableAllZero,
-                            thirdPolicy);
+                            thirdPolicy, selective);
                     // clear and replace exam_question
                     questionService.save(list);
                     groupService.save(group);
                     studentService.updateSubjectiveStatusAndScoreAndInspectorId(examId, subjectCode,
                             SubjectiveStatus.UNMARK, 0, null, null, null);
+                    if (trialCount != null) {
+                        subjectService.updateTrialCount(examId, subjectCode, trialCount);
+                    }
                     redirectAttributes.addAttribute("subjectCode", subjectCode);
                     return "redirect:/admin/exam/group";
                 } else {
@@ -613,4 +688,22 @@ public class MarkGroupController extends BaseExamController {
         redirectAttributes.addAttribute("subjectCode", subjectCode);
         return "redirect:/admin/exam/group";
     }
+
+    @Logging(menu = "设置试评数量", type = LogType.UPDATE)
+    @RequestMapping(value = "/updateTrialCount", method = RequestMethod.POST)
+    @ResponseBody
+    public JSONObject updateTrialCount(HttpServletRequest request, @RequestParam String subjectCode,
+            @RequestParam Integer trialCount) {
+        int examId = getSessionExamId(request);
+        ExamSubject subject = subjectService.find(examId, subjectCode);
+        JSONObject obj = new JSONObject();
+        if (subject != null && subject.getTrialCount() <= trialCount) {
+            subjectService.updateTrialCount(examId, subjectCode, trialCount);
+            obj.accumulate("success", true);
+        } else {
+            obj.accumulate("success", false);
+            obj.accumulate("message", "设置数量请大于" + subject.getTrialCount());
+        }
+        return obj;
+    }
 }

+ 4 - 8
stmms-web/src/main/java/cn/com/qmth/stmms/admin/exam/MarkQualityController.java

@@ -34,7 +34,6 @@ import cn.com.qmth.stmms.biz.exam.service.MarkerService;
 import cn.com.qmth.stmms.biz.file.service.FileService;
 import cn.com.qmth.stmms.biz.lock.LockService;
 import cn.com.qmth.stmms.biz.mark.model.Task;
-import cn.com.qmth.stmms.biz.mark.model.TrialHistory;
 import cn.com.qmth.stmms.biz.mark.model.TrialLibrary;
 import cn.com.qmth.stmms.biz.mark.query.MarkLibrarySearchQuery;
 import cn.com.qmth.stmms.biz.mark.service.MarkLibraryService;
@@ -259,15 +258,12 @@ public class MarkQualityController extends BaseExamController {
             list = taskService.findByQuery(query);
         } else if (group != null && group.getStatus() == MarkStatus.TRIAL) {
             // 试评查找给分历史记录
-            List<TrialHistory> historyList = new ArrayList<TrialHistory>();
+            List<TrialLibrary> historyList = new ArrayList<TrialLibrary>();
             historyList = trialService.findHistory(marker.getExamId(), marker.getSubjectCode(),
                     marker.getGroupNumber(), marker.getId(), pageNumber, pageSize, null, markerScore);
-            for (TrialHistory history : historyList) {
-                TrialLibrary library = trialService.findLibrary(history.getLibraryId());
-                if (library != null) {
-                    Task task = taskService.build(library, history);
-                    list.add(task);
-                }
+            for (TrialLibrary library : historyList) {
+                Task task = taskService.build(library);
+                list.add(task);
             }
         }
         return list;

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

@@ -353,6 +353,7 @@ public class PaperController extends BaseExamController {
         int examId = getSessionExamId(request);
         List<String> error = new LinkedList<String>();
         Map<String, SubjectQuestionDTO> map = parseQuestion(file, examId, false, error);
+
         if (error.isEmpty()) {
             int success = 0;
             for (SubjectQuestionDTO dto : map.values()) {
@@ -413,6 +414,7 @@ public class PaperController extends BaseExamController {
                         }
                         if (successGroup > 0) {
                             success++;
+                            subjectService.updateTrialCount(examId, subject.getCode(), dto.getTrialCount());
                         }
                     }
                 } else {

+ 15 - 16
stmms-web/src/main/java/cn/com/qmth/stmms/admin/exam/ScoreController.java

@@ -84,9 +84,8 @@ public class ScoreController extends BaseExamController {
             buildPackageUrl(student);
             buildAnswerUrl(student);
         }
-        String exportMessage = StringUtils.isNotBlank(query.getSubjectCode()) ?
-                enableExport(examId, query.getSubjectCode()) :
-                null;
+        String exportMessage = StringUtils.isNotBlank(query.getSubjectCode()) ? enableExport(examId,
+                query.getSubjectCode()) : null;
         if (exportMessage != null) {
             view.addObject("exportMessage", exportMessage);
             view.addObject("enableExport", false);
@@ -207,6 +206,7 @@ public class ScoreController extends BaseExamController {
                         student.setObjectiveScore(0d);
                         student.setSubjectiveScore(0d);
                     }
+                    student.setSubjectiveScoreList(student.getSubjectiveScoreList().replace("-1", "/"));
                     list.add(new ExamStudentDTO(student));
                 }
             }
@@ -228,8 +228,8 @@ public class ScoreController extends BaseExamController {
 
     private List<String> getOptionHeader(int examId, String subjectCode) {
         List<String> headerList = new ArrayList<String>();
-        List<ExamQuestion> oQuestions = questionService
-                .findByExamAndSubjectAndObjectiveGroupByNumber(examId, subjectCode, true);
+        List<ExamQuestion> oQuestions = questionService.findByExamAndSubjectAndObjectiveGroupByNumber(examId,
+                subjectCode, true);
         List<ExamQuestion> sQestions = questionService.findByExamAndSubjectAndObjective(examId, subjectCode, false);
         for (ExamQuestion examQuestion : oQuestions) {
             headerList.add(getTitle(examQuestion) + "选项");
@@ -263,9 +263,8 @@ public class ScoreController extends BaseExamController {
     private List<ScoreItem> buildScoreList(ExamStudent student) {
         List<ScoreItem> scoreList = new LinkedList<ScoreItem>();
 
-        List<ExamQuestion> oList = questionService
-                .findByExamAndSubjectAndObjectiveAndPaperType(student.getExamId(), student.getSubjectCode(), true,
-                        student.getPaperType());
+        List<ExamQuestion> oList = questionService.findByExamAndSubjectAndObjectiveAndPaperType(student.getExamId(),
+                student.getSubjectCode(), true, student.getPaperType());
         List<ScoreItem> list1 = student.getScoreList(true);
         int index = 0;
         for (ExamQuestion question : oList) {
@@ -280,8 +279,8 @@ public class ScoreController extends BaseExamController {
         }
         scoreList.addAll(list1);
 
-        List<ExamQuestion> sList = questionService
-                .findByExamAndSubjectAndObjective(student.getExamId(), student.getSubjectCode(), false);
+        List<ExamQuestion> sList = questionService.findByExamAndSubjectAndObjective(student.getExamId(),
+                student.getSubjectCode(), false);
         List<ScoreItem> list2 = student.getScoreList(false);
         index = 0;
         for (ExamQuestion question : sList) {
@@ -304,8 +303,8 @@ public class ScoreController extends BaseExamController {
         // student.setSheetUrls(PictureUrlBuilder
         // .getInnerSheetUrls(student.getExamId(), student.getExamNumber(),
         // student.getSheetCount()));
-        student.setSheetUrls(
-                fileService.getSheetUris(student.getExamId(), student.getExamNumber(), 1, student.getSheetCount()));
+        student.setSheetUrls(fileService.getSheetUris(student.getExamId(), student.getExamNumber(), 1,
+                student.getSheetCount()));
     }
 
     private void buildPackageUrl(ExamStudent student) {
@@ -320,8 +319,8 @@ public class ScoreController extends BaseExamController {
     private void buildAnswerUrl(ExamStudent student) {
         ExamSubject subject = subjectService.find(student.getExamId(), student.getSubjectCode());
         if (subject != null && subject.getAnswerFileType() != null) {
-            student.setAnswerUrl(
-                    fileService.getAnswerUri(subject.getExamId(), subject.getCode(), subject.getAnswerFileType()));
+            student.setAnswerUrl(fileService.getAnswerUri(subject.getExamId(), subject.getCode(),
+                    subject.getAnswerFileType()));
         }
         if (subject != null) {
             student.setSubjectRemark(StringUtils.trimToEmpty(subject.getRemark()));
@@ -334,8 +333,8 @@ public class ScoreController extends BaseExamController {
             return "该科目不存在";
         }
 
-        List<MarkGroup> groups = groupService
-                .findByExamAndSubjectAndStatus(examId, subjectCode, MarkStatus.FORMAL, MarkStatus.TRIAL);
+        List<MarkGroup> groups = groupService.findByExamAndSubjectAndStatus(examId, subjectCode, MarkStatus.FORMAL,
+                MarkStatus.TRIAL);
         if (groups != null && !groups.isEmpty()) {
             return subjectCode + "评卷未完成";
         }

+ 123 - 0
stmms-web/src/main/java/cn/com/qmth/stmms/admin/exam/SelectiveGroupController.java

@@ -0,0 +1,123 @@
+package cn.com.qmth.stmms.admin.exam;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Controller;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.ui.Model;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.servlet.mvc.support.RedirectAttributes;
+
+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.model.SelectiveGroup;
+import cn.com.qmth.stmms.biz.exam.service.ExamQuestionService;
+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.SelectiveGroupService;
+import cn.com.qmth.stmms.common.annotation.Logging;
+import cn.com.qmth.stmms.common.enums.LogType;
+
+@Controller("selectiveGroupController")
+@RequestMapping("/admin/exam/selectiveGroup")
+public class SelectiveGroupController extends BaseExamController {
+
+    protected static Logger log = LoggerFactory.getLogger(SelectiveGroupController.class);
+
+    @Autowired
+    private ExamQuestionService questionService;
+
+    @Autowired
+    private MarkGroupService groupService;
+
+    @Autowired
+    private ExamSubjectService subjectService;
+
+    @Autowired
+    private SelectiveGroupService selectiveGroupService;
+
+    @Logging(menu = "选做题查询", type = LogType.QUERY)
+    @RequestMapping
+    public String list(HttpServletRequest request, Model model, @RequestParam String subjectCode) {
+        int examId = getSessionExamId(request);
+        ExamSubject subject = subjectService.find(examId, subjectCode);
+        List<ExamQuestion> questions = questionService.findMainByExamAndSubjectAndObjective(examId, subjectCode, false);
+        List<SelectiveGroup> list = selectiveGroupService.findByExamIdAndSubjectCode(examId, subjectCode);
+        Set<Integer> mainNumbers = new HashSet<Integer>();
+        for (SelectiveGroup selectiveGroup : list) {
+            mainNumbers.add(selectiveGroup.getMainNumber());
+        }
+        for (ExamQuestion examQuestion : questions) {
+            if (mainNumbers.contains(examQuestion.getMainNumber())) {
+                examQuestion.setSelective(true);
+            }
+        }
+        if (!list.isEmpty()) {
+            model.addAttribute("selectiveCount", list.get(0).getSelectiveCount());
+        }
+        model.addAttribute("subject", subject);
+        model.addAttribute("list", list);
+        model.addAttribute("questions", questions);
+        return "modules/exam/selectiveList";
+    }
+
+    @Logging(menu = "选做题设置", type = LogType.ADD)
+    @RequestMapping("/add")
+    @Transactional
+    public String add(HttpServletRequest request, RedirectAttributes redirectAttributes,
+            @RequestParam String subjectCode, @RequestParam Integer[] mainNumbers, @RequestParam Integer selectiveCount) {
+        int examId = getSessionExamId(request);
+        if (selectiveCount >= mainNumbers.length) {
+            addMessage(redirectAttributes, "选做题数量不能大于已选择题目数量");
+            return "redirect:/admin/exam/paper";
+        }
+        List<MarkGroup> groups = groupService.findByExamAndSubject(examId, subjectCode);
+        if (groups != null && groups.size() > 0) {
+            addMessage(redirectAttributes, "该科目已经存在分组,无法设置");
+            return "redirect:/admin/exam/paper";
+        }
+        if (!checkTotalScore(examId, subjectCode, mainNumbers)) {
+            addMessage(redirectAttributes, "选做题分数必须一样");
+            return "redirect:/admin/exam/paper";
+        }
+        selectiveGroupService.deleteByExamIdAndSubjectCode(examId, subjectCode);
+        if (mainNumbers.length > 0) {
+            List<SelectiveGroup> list = new ArrayList<SelectiveGroup>();
+            for (Integer mainNumber : mainNumbers) {
+                list.add(new SelectiveGroup(examId, subjectCode, mainNumber, 1, selectiveCount));
+            }
+            selectiveGroupService.save(list);
+        }
+        return "redirect:/admin/exam/paper";
+    }
+
+    private boolean checkTotalScore(int examId, String subjectCode, Integer[] mainNumbers) {
+        List<ExamQuestion> questions = questionService.findMainByExamAndSubjectAndObjective(examId, subjectCode, false);
+        Map<Integer, ExamQuestion> map = new HashMap<Integer, ExamQuestion>();
+        for (ExamQuestion examQuestion : questions) {
+            map.put(examQuestion.getMainNumber(), examQuestion);
+        }
+        Double totalScore = null;
+        for (Integer mainNumber : mainNumbers) {
+            if (totalScore == null) {
+                totalScore = map.get(mainNumber).getTotalScore();
+            }
+            if (totalScore.doubleValue() != map.get(mainNumber).getTotalScore().doubleValue()) {
+                return false;
+            }
+        }
+        return true;
+    }
+}

+ 41 - 31
stmms-web/src/main/java/cn/com/qmth/stmms/admin/exam/TrialController.java

@@ -1,23 +1,11 @@
 package cn.com.qmth.stmms.admin.exam;
 
-import cn.com.qmth.stmms.biz.exam.model.*;
-import cn.com.qmth.stmms.biz.exam.service.*;
-import cn.com.qmth.stmms.biz.file.enums.FormatType;
-import cn.com.qmth.stmms.biz.file.service.FileService;
-import cn.com.qmth.stmms.biz.lock.LockService;
-import cn.com.qmth.stmms.biz.mark.model.TrialHistory;
-import cn.com.qmth.stmms.biz.mark.model.TrialLibrary;
-import cn.com.qmth.stmms.biz.mark.query.TrialLibrarySearchQuery;
-import cn.com.qmth.stmms.biz.mark.service.MarkService;
-import cn.com.qmth.stmms.biz.mark.service.TrialService;
-import cn.com.qmth.stmms.biz.user.model.User;
-import cn.com.qmth.stmms.biz.user.service.UserService;
-import cn.com.qmth.stmms.common.annotation.Logging;
-import cn.com.qmth.stmms.common.annotation.RoleRequire;
-import cn.com.qmth.stmms.common.domain.WebUser;
-import cn.com.qmth.stmms.common.enums.*;
-import cn.com.qmth.stmms.common.utils.DateUtils;
-import cn.com.qmth.stmms.common.utils.RequestUtils;
+import java.text.DecimalFormat;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.servlet.http.HttpServletRequest;
+
 import net.sf.json.JSONArray;
 import net.sf.json.JSONObject;
 
@@ -32,11 +20,37 @@ 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.text.DecimalFormat;
-import java.util.ArrayList;
-import java.util.List;
+import cn.com.qmth.stmms.biz.exam.model.Exam;
+import cn.com.qmth.stmms.biz.exam.model.ExamQuestion;
+import cn.com.qmth.stmms.biz.exam.model.ExamStudent;
+import cn.com.qmth.stmms.biz.exam.model.ExamSubject;
+import cn.com.qmth.stmms.biz.exam.model.MarkGroup;
+import cn.com.qmth.stmms.biz.exam.model.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.MarkGroupService;
+import cn.com.qmth.stmms.biz.exam.service.MarkerService;
+import cn.com.qmth.stmms.biz.file.enums.FormatType;
+import cn.com.qmth.stmms.biz.file.service.FileService;
+import cn.com.qmth.stmms.biz.lock.LockService;
+import cn.com.qmth.stmms.biz.mark.model.TrialLibrary;
+import cn.com.qmth.stmms.biz.mark.query.TrialLibrarySearchQuery;
+import cn.com.qmth.stmms.biz.mark.service.MarkService;
+import cn.com.qmth.stmms.biz.mark.service.TrialService;
+import cn.com.qmth.stmms.biz.user.model.User;
+import cn.com.qmth.stmms.biz.user.service.UserService;
+import cn.com.qmth.stmms.common.annotation.Logging;
+import cn.com.qmth.stmms.common.annotation.RoleRequire;
+import cn.com.qmth.stmms.common.domain.WebUser;
+import cn.com.qmth.stmms.common.enums.ExamType;
+import cn.com.qmth.stmms.common.enums.LibraryStatus;
+import cn.com.qmth.stmms.common.enums.LockType;
+import cn.com.qmth.stmms.common.enums.LogType;
+import cn.com.qmth.stmms.common.enums.MarkStatus;
+import cn.com.qmth.stmms.common.enums.Role;
+import cn.com.qmth.stmms.common.utils.DateUtils;
+import cn.com.qmth.stmms.common.utils.RequestUtils;
 
 @Controller("trialController")
 @RequestMapping("/admin/exam/trial")
@@ -96,9 +110,6 @@ public class TrialController extends BaseExamController {
             }
             query.orderById();
             query = trialService.findLibrary(query);
-            for (TrialLibrary library : query.getResult()) {
-                library.setMarkCount(trialService.countHistory(library.getId()));
-            }
             for (MarkGroup group : groupList) {
                 group.setQuestionList(questionService.findByExamAndSubjectAndObjectiveAndGroupNumber(examId,
                         group.getSubjectCode(), false, group.getNumber()));
@@ -192,16 +203,15 @@ public class TrialController extends BaseExamController {
                 }
                 // 评卷记录集合
                 JSONArray array = new JSONArray();
-                List<TrialHistory> list = trialService.findHistory(libraryId);
                 DecimalFormat format = new DecimalFormat("####.###");
-                for (TrialHistory history : list) {
-                    Marker marker = markerService.findById(history.getMarkerId());
+                if (library.getMarkerId() != null) {
+                    Marker marker = markerService.findById(library.getMarkerId());
                     User user = userService.findById(marker.getUserId());
                     JSONObject item = new JSONObject();
                     item.accumulate("loginName", marker != null ? user.getLoginName() : "");
                     item.accumulate("name", marker != null ? user.getName() : "");
-                    item.accumulate("score", format.format(history.getMarkerScore()));
-                    item.accumulate("time", DateUtils.formatDateTime(history.getMarkerTime()));
+                    item.accumulate("score", format.format(library.getMarkerScore()));
+                    item.accumulate("time", DateUtils.formatDateTime(library.getMarkerTime()));
                     array.add(item);
                 }
                 obj.accumulate("historyList", array);

+ 1 - 1
stmms-web/src/main/java/cn/com/qmth/stmms/admin/thread/OnlineExamThread.java

@@ -289,7 +289,7 @@ public class OnlineExamThread implements Runnable {
         questionService.save(list);
         // 保存group
         MarkGroup group = new MarkGroup(examId, subjectCode, 1, null, totalScore, 0d, null, null,
-                MarkMode.COMMON.toString(), 0, false, false, null);
+                MarkMode.COMMON.toString(), 0, false, false, null, false);
         groupService.save(group);
 
         subjectService.updateScore(examId, subjectCode, false, totalScore);

+ 4 - 4
stmms-web/src/main/java/cn/com/qmth/stmms/admin/utils/ExportStudentExcel.java

@@ -392,7 +392,7 @@ public class ExportStudentExcel {
      * 
      * @return list 数据列表
      */
-    public <E> ExportStudentExcel setDataList(List<ExamStudentDTO> list,boolean addOptions) {
+    public <E> ExportStudentExcel setDataList(List<ExamStudentDTO> list, boolean addOptions) {
         for (ExamStudentDTO e : list) {
             int colunm = 0;
             Row row = this.addRow();
@@ -426,13 +426,13 @@ public class ExportStudentExcel {
                 this.addCell(row, colunm++, val, ef.align(), ef.fieldType());
                 sb.append(val + ", ");
             }
-            if(addOptions){
+            if (addOptions) {
                 for (ScoreItem item : e.getObjectiveList()) {
                     this.addCell(row, colunm++, item.getAnswer());
                     this.addCell(row, colunm++, item.getScore());
                 }
-                for (ScoreItem item : e.getSubjectiveList()) {
-                    this.addCell(row, colunm++, item.getScore());
+                for (String score : e.getSubjectiveList()) {
+                    this.addCell(row, colunm++, score);
                 }
             }
             log.debug("Write success: [" + row.getRowNum() + "] " + sb.toString());

+ 11 - 12
stmms-web/src/main/java/cn/com/qmth/stmms/mark/MarkController.java

@@ -49,7 +49,6 @@ import cn.com.qmth.stmms.biz.mark.model.PictureConfigItem;
 import cn.com.qmth.stmms.biz.mark.model.ProblemType;
 import cn.com.qmth.stmms.biz.mark.model.SubmitResult;
 import cn.com.qmth.stmms.biz.mark.model.Task;
-import cn.com.qmth.stmms.biz.mark.model.TrialHistory;
 import cn.com.qmth.stmms.biz.mark.model.TrialLibrary;
 import cn.com.qmth.stmms.biz.mark.query.MarkLibrarySearchQuery;
 import cn.com.qmth.stmms.biz.mark.service.MarkLibraryService;
@@ -297,6 +296,7 @@ public class MarkController extends BaseController {
         setSubjectAndSheetConfig(setting, marker, exam);
         setting.accumulate("userName", RequestUtils.getWebUser(request).getName());
         setProblemType(setting, marker);
+        setting.accumulate("selective", group.isSelective());
         return setting;
     }
 
@@ -350,7 +350,7 @@ public class MarkController extends BaseController {
             arbitrateCount = libraryService.countByQuery(query);
         } else if (group.getStatus() == MarkStatus.TRIAL) {
             totalCount = trialService.countLibrary(group.getExamId(), group.getSubjectCode(), group.getNumber());
-            personCount = trialService.countMarkerHistory(marker.getId());
+            personCount = trialService.countByMarkerId(marker.getId());
             markedCount = personCount;
         }
         status.accumulate("personCount", personCount);
@@ -379,7 +379,7 @@ public class MarkController extends BaseController {
             json.accumulate("title", group.getTitle());
             json.accumulate("totalCount", group.getLibraryCount());
             if (group.getStatus() == MarkStatus.TRIAL) {
-                json.accumulate("markedCount", trialService.countMarkerHistory(m.getId()));
+                json.accumulate("markedCount", trialService.countByMarkerId(m.getId()));
             } else {
                 json.accumulate("markedCount", group.getMarkedCount());
             }
@@ -462,7 +462,7 @@ public class MarkController extends BaseController {
             }
             for (TrialLibrary library : list) {
                 if (markService.applyLibrary(library, marker)) {
-                    task = taskService.build(library, null);
+                    task = taskService.build(library);
                     break;
                 }
             }
@@ -535,6 +535,7 @@ public class MarkController extends BaseController {
             query.setSecretNumber(secretNumber);
             query.setPageNumber(pageNumber);
             query.setPageSize(pageSize);
+            query.setStartScroe(0.0);
             if (querySort != null) {
                 query.setSort(querySort);
             } else {
@@ -543,7 +544,7 @@ public class MarkController extends BaseController {
             list = taskService.findByQuery(query);
         } else if (group != null && group.getStatus() == MarkStatus.TRIAL) {
             // 试评查找给分历史记录
-            List<TrialHistory> historyList = new ArrayList<TrialHistory>();
+            List<TrialLibrary> historyList = new ArrayList<TrialLibrary>();
             if (StringUtils.isNotBlank(secretNumber)) {
                 historyList = trialService.findHistory(marker.getExamId(), marker.getSubjectCode(),
                         marker.getGroupNumber(), marker.getId(), secretNumber, pageNumber, pageSize, querySort);
@@ -551,13 +552,10 @@ public class MarkController extends BaseController {
                 historyList = trialService.findHistory(marker.getExamId(), marker.getSubjectCode(),
                         marker.getGroupNumber(), marker.getId(), pageNumber, pageSize, querySort, null);
             }
-            for (TrialHistory history : historyList) {
-                TrialLibrary library = trialService.findLibrary(history.getLibraryId());
-                if (library != null) {
-                    Task task = taskService.build(library, history);
-                    task.setPrevious(true);
-                    list.add(task);
-                }
+            for (TrialLibrary library : historyList) {
+                Task task = taskService.build(library);
+                task.setPrevious(true);
+                list.add(task);
             }
         }
         return list;
@@ -726,4 +724,5 @@ public class MarkController extends BaseController {
         setting.accumulate("mode", mode);
         setting.accumulate("forceMode", forceMode);
     }
+
 }

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

@@ -40,6 +40,11 @@
 	            <option value="${item.value}" <c:if test="${query.status!=null && item.value==query.status.value}">selected</c:if>>${item.name}</option>
                 </c:forEach>
             </select>
+            <label>选做题</label>
+            <select class="input-small"  name="unselective">
+                <option value="false"<c:if test="${!query.unselective}">selected</c:if>>不限</option>
+	            <option value="true" <c:if test="${query.unselective}">selected</c:if>>未选做</option>
+            </select>
             <c:if test="${web_user.schoolAdmin==true || forbiddenScore==false}">
             <label>准考证号</label>
             <input type="text" name="examNumber" value="${query.examNumber}" maxlength="20" class="input-medium"/>

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

@@ -82,6 +82,7 @@
        			 <th>大题号</th>
         		 <th>小题号</th>
         		 <th>分数</th>
+        		 <th>是否选做题</th>
         		 <th></th>
 			</tr>
         	</thead>
@@ -91,6 +92,7 @@
 		    <td>${item.subNumber }</td>
 			<td>${item.mainTitle }</td>
 			<td><fmt:formatNumber pattern="###.#" value="${item.totalScore}"/></td>
+			<td><c:if test="${item.selective }">选做题</c:if></td>
 			<td><input type="checkbox" name="questionIds" value="${item.id }" <c:if test="${item.groupNumber!=null}"> disabled="disabled"</c:if>></td>
 			</tr>
 			</c:forEach>
@@ -108,6 +110,7 @@
             <form:input path="number" type="number" htmlEscape="false" max="100" min="1" class="required digits" value="${group.number }"/>
         </div>
     </div>
+    <c:if test="${groupCount==0 }">
     <div class="control-group">
         <label class="control-label">试评数量</label>
         <div class="controls">
@@ -115,6 +118,7 @@
             <label>0表示跳过试评</label>
         </div>
     </div>
+    </c:if>
     <c:if test="${examType!='MULTI_MEDIA'}">
 	    <div class="control-group">
 	        <label class="control-label">评卷模式</label>

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

@@ -121,14 +121,14 @@
             <form:input path="number" htmlEscape="false" class="required" readonly="true"/>
         </div>
     </div>
-    <c:if test="${group.status.value==1}">
+   <%--  <c:if test="${group.status.value==1}">
         <div class="control-group">
             <label class="control-label">试评数量</label>
             <div class="controls">
                 <form:input path="trialCount" htmlEscape="false" min="1" class="required digits" type="number"/>
             </div>
         </div>
-    </c:if>
+    </c:if> --%>
     <div class="control-group">
         <label class="control-label">评卷模式</label>
         <div class="controls">

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

@@ -78,14 +78,14 @@
             <form:input path="title" htmlEscape="false" class="required" readonly="true"/>
         </div>
     </div>
-    <c:if test="${group.status.value==1}">
+   <%--  <c:if test="${group.status.value==1}">
         <div class="control-group">
             <label class="control-label">试评数量</label>
             <div class="controls">
                 <form:input path="trialCount" htmlEscape="false" min="1" class="required digits" type="number"/>
             </div>
         </div>
-    </c:if>
+    </c:if> --%>
     <div class="control-group">
         <label class="control-label">评卷模式</label>
         <div class="controls">

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

@@ -23,7 +23,7 @@
 <form id="searchForm" action="${ctx}/admin/exam/group" method="post" class="breadcrumb form-search">
     <div>
         <label>科目</label>
-        <select class="input-large" name="subjectCode">
+        <select class="input-large subjectCode" name="subjectCode">
             <c:forEach items="${subjectList}" var="item">
                 <option value="${item.code}" <c:if test="${item.code==subject.code}">selected</c:if>>${item.code}-${item.name}</option>
             </c:forEach>
@@ -38,6 +38,8 @@
 	            <a href="${ctx}/admin/exam/group/check-count?subjectCode=${subject.code}" class="btn">数量校对</a>
             &nbsp;
             <input id="btnFinish" class="btn" type="button" value="关闭" onclick="goFinish()"/>
+            <a href="javascript:void(0)" class="trial-button"
+                       onclick="updateTrialCount();">设置试评数量</a>
         </c:if>
     </div>
 </form>
@@ -126,6 +128,13 @@
     </c:forEach>
     </tbody>
 </table>
+<div class="trialCountWin" style="display:none">
+    <div class="task-header">
+        <p class="title">设置试评数</p>
+        <p class="image-close"><img src="${ctxStatic}/mark-new/images/images-close.png"/></p></div>
+    <div class="task-content"><input type="text" class="trial-count" placeholder="请输入试评数"/><i class="wrong"></i></div>
+    <a href="#" class="btn btn-small btn-info save-btn">确定</a>
+</div>
 </form>
 <script type="text/javascript">
     function page(n, s) {
@@ -178,6 +187,132 @@
         $("#groupForm").submit();
         return false;
     }
+    
+    function updateTrialCount() {
+        $('.trialCount-value').val('');
+        $('.trialCountWin').show();
+        $('#cover').show();
+    }
+    $('.image-close').click(function () {
+        $('.trialCountWin').hide();
+        $('#cover').hide();
+    });
+    $('.save-btn').click(function () {
+    	var trialCount = $('.trial-count').val();
+        var wrongMessage = $('.wrong');
+        trialCount = trialCount.replace(/(^\s*)|(\s*$)/g, "");
+        if (trialCount.length == 0) {
+            wrongMessage.html('数量不能为空!');
+            return false;
+        } else {
+            if (!/^\+?[1-9][0-9]*$/.test(trialCount)) {
+                wrongMessage.html('请输入正整数!');
+                return false;
+            }
+            if (trialCount > 2147483647) {
+                wrongMessage.html('数量不合法!');
+                return false;
+            }
+        }
+        var subjectCode = $('.subjectCode').val();
+        $.post('${ctx}/admin/exam/group/updateTrialCount', {subjectCode: subjectCode, trialCount: trialCount}, function (result) {
+            if (result.success == true) {
+                alert('修改成功');
+                $("#searchForm").submit();
+            } else {
+                alert(result.message);
+            }
+            $('.trialCountWin').hide();
+        });
+    });
 </script>
+
+<style type="text/css">
+	.sort {
+        color: #0663A2;
+        cursor: pointer;
+    }
+</style>
+    <style type="text/css">
+        .sort {
+            color: #0663A2;
+            cursor: pointer;
+        }
+        
+        .trialCountWin {
+            width: 400px;
+            min-height: 150px;
+            background: #fff;
+            font-family: "微软雅黑", Fixedsys;
+            border: #5d6d7d solid 1px;
+            position: absolute;
+            left: 50%;
+            top: 50%;
+            margin: -150px 0 0 -200px;
+            text-align: center;
+            z-index: 99999;
+        }
+        
+        .task-header{
+            width: 100%;
+            height: 46px;
+            background: #5d6d7d;
+            color: #fff;
+        }
+        
+        .task-content{
+            font-size: 18px;
+            color: #005277;
+            text-align: left;
+            padding: 15px;
+            line-height: 30px;
+            word-wrap: break-word;
+        }
+        
+        .image-close {
+            margin-top: 15px;
+            margin-right: 15px;
+            cursor: pointer;
+            float: right;
+        }
+        
+        .title {
+            font-size: 22px;
+            font-weight: bold;
+            color: #fff;
+            margin: 0px;
+            padding: 13px 0 0 13px;
+            float: left;
+        }
+
+        .task-count{
+            width: 150px;
+        }
+
+        .btn-info {
+            height: 25px;
+            margin-left: 320px;
+            margin-bottom: 20px;
+        }
+        
+        .wrong {
+            font-size: 12px;
+            color: #f00;
+            line-height: 30px;
+            padding-left: 20px;
+        }
+        
+        #cover {
+            position: fixed;
+            z-index: 9999;
+            top: 0px;
+            left: 0px;
+            display: none;
+            width: 100%;
+            height: 100%;
+            opacity: 0.5;
+            background: #000 none repeat scroll 0% 0%;
+        }
+    </style>
 </body>
 </html>

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

@@ -43,7 +43,12 @@
         <input type="text" number="true" id="startScore" name="startScore" value="${query.startScore}" class="input-mini"/>
         <label> 到&nbsp;&nbsp;&nbsp;</label>
         <input type="text" number="true" id="endScore" name="endScore" value="${query.endScore}" class="input-mini"/>
-        
+        &nbsp;
+        <label>选做题</label>
+            <select class="input-small"  name="unselective" id="unselective">
+                <option value="false"<c:if test="${!unselective}">selected</c:if>>不限</option>
+	            <option value="true" <c:if test="${unselective}">selected</c:if>>全卷未选做</option>
+            </select>
         <br/><br/>
 		<label>大题</label>
         <select class="input-medium" id="question-select" name="mainNumber">
@@ -52,16 +57,15 @@
                 <option value="${result.mainNumber}" <c:if test="${result.mainNumber==mainNumber}">selected</c:if>>${result.mainNumber}-${result.mainTitle}</option>
             </c:forEach>
         </select>
-        &nbsp;
+
         <label>大题得分:从</label>
         <input type="text" number="true" name="mainStartScore" id="mainStartScore" value="${mainStartScore }" class="input-mini"/>
         <label> 到&nbsp;&nbsp;&nbsp;</label>
         <input type="text" number="true" id="mainEndScore" name="mainEndScore" value="${mainEndScore }" class="input-mini"/>
-        &nbsp;
         
         <label>小题得分</label>
         <input type="text" number="true" name="questionScore" id="questionScore" value="${questionScore }" class="input-mini"/>
-        &nbsp;
+
         <label>考生编号</label>
         <input type="text" name="secretNumber" id="secretNumber" value="${query.secretNumber}" class="input-medium"/>
         &nbsp;
@@ -223,6 +227,10 @@
     	if(questionScore!=undefined && questionScore!=""){
     		url = url+'&questionScore='+questionScore;
     	}
+    	var unselective =  $("#unselective").val();
+    	if(unselective!=undefined && unselective!=""){
+    		url = url+'&unselective='+unselective;
+    	}
     	window.open(url, '_blank');
         return false;
     }

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

@@ -50,6 +50,11 @@
                 <option value="${item.id}" <c:if test="${item.id==query.markerId}">selected</c:if>>${item.loginName}</option>
             </c:forEach>
         </select>
+        <label>选做题</label>
+        <select class="input-small"  name="unselective">
+            <option value="false"<c:if test="${!query.unselective}">selected</c:if>>不限</option>
+	        <option value="true" <c:if test="${query.unselective}">selected</c:if>>未选做</option>
+        </select>
         <br/><br/>
         <c:if test="${web_user.schoolAdmin==true || forbiddenScore==false}">
         <label>准考证号</label>
@@ -105,7 +110,8 @@
             <td>${result.markerLoginName}</td>
             <td>
                 <c:if test="${result.markerScore!=null}">
-                    <fmt:formatNumber pattern="###.#" value="${result.markerScore}"/>
+                	<c:if test="${result.markerScore==-1}">未选做</c:if>
+                    <c:if test="${result.markerScore!=-1}"><fmt:formatNumber pattern="###.#" value="${result.markerScore}"/></c:if>
                 </c:if>
                 <c:if test="${result.markerScore==null}">
                     &nbsp;

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

@@ -167,6 +167,7 @@
                     <a href="${ctx}/admin/exam/subject/edit?code=${subject.code}">编辑</a>
                     <a href="${ctx}/admin/exam/paper/report?subjectCode=${subject.code}">分析计算</a>
                 </c:if>
+                <a href="${ctx}/admin/exam/selectiveGroup?subjectCode=${subject.code}">设置选做题</a>
             </td>
         </tr>
     </c:forEach>

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

@@ -97,7 +97,7 @@
     <c:forEach items="${query.result}" var="student">
         <tr>
             <td>
-                   <%--  <a href="##" class="detail-link" data-exam-number="${student.examNumber}">${student.examNumber}</a> --%>
+                   <a href="##" class="detail-link" data-exam-number="${student.examNumber}">${student.examNumber}</a> 
 	            <c:if test="${(web_user.subjectHeader==true||web_user.schoolViewer==true) && forbiddenInfo==true}">
 	            ${fn:substring(student.examNumber,0,1)}***
 	            </c:if>

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

@@ -0,0 +1,70 @@
+<%@ page contentType="text/html;charset=UTF-8" %>
+<%@ include file="/WEB-INF/views/include/taglib.jsp"%>
+<html>
+<head>
+	<title>试题列表</title>
+	<meta name="decorator" content="default"/>
+	<%@include file="/WEB-INF/views/include/head.jsp" %>
+	<style type="text/css">.sort{color:#0663A2;cursor:pointer;}</style>
+</head>
+<body>
+	<%-- <%@include file="/WEB-INF/views/include/examInfoNavTabs.jsp" %> --%>
+	<form id="inputForm" action="${ctx}/admin/exam/selectiveGroup/add" method="post" class="breadcrumb form-search">
+		<input name="subjectCode" value="${subject.code}" type="hidden"/>
+		<div>
+			<label>科目:${subject.code}-${subject.name}</label>
+			<label>客观总分:${subject.objectiveScore}</label>
+			<label>主观总分:${subject.subjectiveScore}</label>
+			<label>试卷总分:${subject.totalScore}</label>
+			&nbsp;		
+			<a class="btn" href="${ctx}/admin/exam/paper">返回</a>
+		</div>
+		<div>
+		<label>合分数量:</label><input name="selectiveCount" type="text" id="selectiveCount" value="${selectiveCount }"/> 
+		<a id="btnSubmit" href="##" class="btn btn-primary">确定</a>
+		</div>
+		<br/>
+	<tags:message content="${message}"/>
+	<table id="contentTable" class="table table-striped table-bordered table-condensed">
+		<thead>
+			<tr>
+				<th>大题名称</th>
+				<th>大题号</th>
+				<th>满分</th>
+				<th>选择</th>
+			</tr>
+		</thead>
+		<tbody>
+		<c:forEach items="${questions}" var="question">
+			<tr>
+				<td>${question.mainTitle}</td>
+				<td>${question.mainNumber}</td>
+				<td><fmt:formatNumber pattern="###.#" value="${question.totalScore}"/></td>
+				<td><input type="checkbox" name="mainNumbers" value = ${question.mainNumber }  <c:if test="${question.selective}"> checked</c:if>/>
+				</td>
+			</tr>
+		</c:forEach>
+		</tbody>
+	</table>
+	</form>
+<script type="text/javascript">
+$('#btnSubmit').click(function () {
+	var check_list = []
+	$("input[name='mainNumbers']:checked").each(function(){
+    	if($(this).val()!=""){
+    		check_list.push($(this).val())
+		}
+	})
+    if(check_list.length==0) {
+        alert('请选择题目');
+        return false;
+    }
+	if($("#selectiveCount").val()>=check_list.length){
+		alert("合分数量必须小于选择的题目数量");
+		return;
+	}
+   $('#inputForm').submit();
+});
+</script>	
+</body>
+</html>

+ 23 - 26
stmms-web/src/main/webapp/sql/stmms_ft.sql

@@ -301,6 +301,7 @@ CREATE TABLE `eb_exam_subject`
     `subjective_score` double      NOT NULL COMMENT '主观题满分',
     `total_score`      double      NOT NULL COMMENT '全卷满分',
     `upload_count`     int(11)     NOT NULL COMMENT '已上传人数',
+	`trial_count`      int(11)      DEFAULT NULL COMMENT '试评数量',
     `remark`           varchar(128) DEFAULT NULL COMMENT '备注',
     `slice_config`     text         DEFAULT NULL COMMENT '裁切图配置',
     `sheet_config`     text         DEFAULT NULL COMMENT '原图遮盖配置',
@@ -369,7 +370,6 @@ CREATE TABLE `eb_mark_group`
     `number`              int(11)     NOT NULL COMMENT '序号',
     `pic_list`            varchar(255) DEFAULT NULL COMMENT '小图配置',
     `total_score`         double      NOT NULL COMMENT '满分',
-    `trial_count`         int(11)      DEFAULT NULL COMMENT '试评数量',
     `double_rate`         double       DEFAULT NULL COMMENT '双评比例',
     `arbitrate_threshold` double       DEFAULT NULL COMMENT '仲裁阈值',
     `score_policy`        varchar(16)  DEFAULT NULL COMMENT '合分策略',
@@ -426,6 +426,23 @@ CREATE TABLE `eb_subjective_score`
 ) ENGINE = InnoDB
   DEFAULT CHARSET = utf8mb4 COMMENT ='主观题得分明细表';
 
+  
+# Dump of table eb_mark_group
+# ------------------------------------------------------------
+
+DROP TABLE IF EXISTS `eb_selective_group`;
+
+CREATE TABLE `eb_selective_group`
+(
+    `exam_id`             int(11)     NOT NULL COMMENT '考试ID',
+    `subject_code`        varchar(32) NOT NULL COMMENT '科目代码',
+    `main_number`         int(11)     NOT NULL COMMENT '大题号',
+    `selective_count`     int(11)     NOT NULL COMMENT '选做数量',
+    `selective_index`     int(11)     NOT NULL COMMENT '选做分组序号',
+    PRIMARY KEY (`exam_id`, `subject_code`, `main_number`)
+) ENGINE = InnoDB
+  DEFAULT CHARSET = utf8mb4 COMMENT ='选做题分组表';
+
 
 # Dump of table eb_operation_log
 # ------------------------------------------------------------
@@ -499,7 +516,7 @@ CREATE TABLE `m_library`
     `marker_time`       datetime     DEFAULT NULL COMMENT '评卷时间',
     `marker_score`      double       DEFAULT NULL COMMENT '评卷总分',
     `marker_score_list` varchar(255) DEFAULT NULL COMMENT '评卷给分明细',
-    `marker_spent`      int(11)      DEFAULT NULL COMMENT '最新评卷时间',
+    `marker_spent`      int(11)      DEFAULT NULL COMMENT '评卷时长',
     `header_id`         int(11)      DEFAULT NULL COMMENT '科组长ID',
     `header_time`       datetime     DEFAULT NULL COMMENT '科组长评卷时间',
     `header_score`      double       DEFAULT NULL COMMENT '科组长总分',
@@ -607,30 +624,6 @@ CREATE TABLE `m_problem_history`
   DEFAULT CHARSET = utf8mb4 COMMENT ='问题卷历史表';
 
 
-# Dump of table m_trial_history
-# ------------------------------------------------------------
-
-DROP TABLE IF EXISTS `m_trial_history`;
-CREATE TABLE `m_trial_history`
-(
-    `library_id`        int(11)      NOT NULL COMMENT '评卷任务ID',
-    `marker_id`         int(11)      NOT NULL COMMENT '评卷员ID',
-    `exam_id`           int(11)      NOT NULL COMMENT '考试ID',
-    `subject_code`      varchar(32)  NOT NULL COMMENT '科目代码',
-    `group_number`      int(11)      NOT NULL COMMENT '分组序号',
-    `student_id`        int(11)      NOT NULL COMMENT '考生ID',
-    `secret_number`     varchar(64)  NOT NULL COMMENT '考生密号',
-    `marker_time`       datetime     NOT NULL COMMENT '评卷时间',
-    `marker_score`      double       NOT NULL COMMENT '评卷总分',
-    `marker_score_list` varchar(255) NOT NULL COMMENT '评卷总分明细',
-    PRIMARY KEY (`library_id`, `marker_id`),
-    KEY `index1` (`exam_id`, `subject_code`, `group_number`),
-    KEY `index2` (`student_id`),
-    KEY `index3` (`marker_id`)
-) ENGINE = InnoDB
-  DEFAULT CHARSET = utf8mb4 COMMENT ='试评记录表';
-
-
 # Dump of table m_trial_library
 # ------------------------------------------------------------
 
@@ -644,6 +637,10 @@ CREATE TABLE `m_trial_library`
     `student_id`    int(11)     NOT NULL COMMENT '考生ID',
     `exam_number`   varchar(64) NOT NULL COMMENT '准考证号',
     `secret_number` varchar(64) NOT NULL COMMENT '考生密号',
+	`marker_id`         int(11)      DEFAULT NULL COMMENT '评卷员ID',
+    `marker_time`       datetime     DEFAULT NULL COMMENT '评卷时间',
+    `marker_score`      double       DEFAULT NULL COMMENT '评卷总分',
+    `marker_score_list` varchar(255) DEFAULT NULL COMMENT '评卷给分明细',
     PRIMARY KEY (`id`),
     KEY `index1` (`exam_id`, `subject_code`, `group_number`),
     UNIQUE KEY `index2` (`student_id`, `group_number`)