Browse Source

增加客观题多种试卷类型支持

luoshi 6 năm trước cách đây
mục cha
commit
17e9939bed
31 tập tin đã thay đổi với 1536 bổ sung1368 xóa
  1. 27 10
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/dao/ExamQuestionDao.java
  2. 3 3
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/dao/ExamStudentDao.java
  3. 5 2
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/dao/MarkGroupDao.java
  4. 8 0
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/model/ExamQuestion.java
  5. 688 674
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/model/ExamStudent.java
  6. 211 211
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/model/ExamSubject.java
  7. 17 4
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/model/QuestionPK.java
  8. 16 7
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/service/ExamQuestionService.java
  9. 1 1
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/service/ExamSubjectService.java
  10. 2 0
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/service/MarkGroupService.java
  11. 188 165
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/service/impl/ExamQuestionServiceImpl.java
  12. 6 6
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/service/impl/ExamStudentServiceImpl.java
  13. 6 9
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/service/impl/ExamSubjectServiceImpl.java
  14. 6 0
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/service/impl/MarkGroupServiceImpl.java
  15. 10 0
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/service/query/ExamQuestionSearchQuery.java
  16. 13 6
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/mark/service/Impl/MarkServiceImpl.java
  17. 6 6
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/mark/service/Impl/TaskServiceImpl.java
  18. 18 22
      stmms-web/src/main/java/cn/com/qmth/stmms/admin/dto/ObjectiveQuestionDTO.java
  19. 0 2
      stmms-web/src/main/java/cn/com/qmth/stmms/admin/dto/QuestionDTO.java
  20. 83 43
      stmms-web/src/main/java/cn/com/qmth/stmms/admin/dto/SubjectQuestionDTO.java
  21. 1 18
      stmms-web/src/main/java/cn/com/qmth/stmms/admin/dto/SubjectiveQuestionDTO.java
  22. 2 2
      stmms-web/src/main/java/cn/com/qmth/stmms/admin/exam/AnswerCheckController.java
  23. 11 10
      stmms-web/src/main/java/cn/com/qmth/stmms/admin/exam/MarkGroupController.java
  24. 10 8
      stmms-web/src/main/java/cn/com/qmth/stmms/admin/exam/PaperController.java
  25. 5 5
      stmms-web/src/main/java/cn/com/qmth/stmms/admin/exam/ScoreController.java
  26. 11 8
      stmms-web/src/main/java/cn/com/qmth/stmms/admin/thread/ScoreCalculateThread.java
  27. 101 75
      stmms-web/src/main/java/cn/com/qmth/stmms/api/controller/ExamQuestionController.java
  28. 4 4
      stmms-web/src/main/java/cn/com/qmth/stmms/api/controller/ExamStudentController.java
  29. 1 0
      stmms-web/src/main/java/cn/com/qmth/stmms/api/controller/ScanController.java
  30. 74 64
      stmms-web/src/main/java/cn/com/qmth/stmms/api/utils/ScanStudentParameter.java
  31. 2 3
      stmms-web/src/main/java/cn/com/qmth/stmms/common/controller/BaseController.java

+ 27 - 10
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/dao/ExamQuestionDao.java

@@ -13,15 +13,24 @@ import cn.com.qmth.stmms.biz.exam.model.QuestionPK;
 public interface ExamQuestionDao
         extends JpaRepository<ExamQuestion, QuestionPK>, JpaSpecificationExecutor<ExamQuestion> {
 
-    @Query("select q from ExamQuestion q where q.pk.examId=?1 and q.pk.subjectCode=?2 and q.pk.objective=?3 order by q.pk.mainNumber, q.pk.subNumber")
+    @Query("select q from ExamQuestion q where q.pk.examId=?1 and q.pk.subjectCode=?2 "
+            + "and q.pk.objective=?3 order by q.pk.mainNumber, q.pk.subNumber")
     public List<ExamQuestion> findByExamIdAndSubjectCodeAndObjective(int examId, String subjectCode, boolean objective);
 
-    @Query("select q from ExamQuestion q where q.pk.examId=?1 and q.pk.subjectCode=?2 and q.pk.objective=?3 and q.pk.mainNumber=?4 order by q.pk.subNumber")
-    public List<ExamQuestion> findByExamIdAndSubjectCodeAndObjectiveAndMainNumber(int examId, String subjectCode,
-            boolean objective, int mainNumber);
+    @Query("select q from ExamQuestion q where q.pk.examId=?1 and q.pk.subjectCode=?2 and q.pk.paperType=?3 "
+            + "and q.pk.objective=?4 order by q.pk.mainNumber, q.pk.subNumber")
+    public List<ExamQuestion> findByExamIdAndSubjectCodeAndPaperTypeAndObjective(int examId, String subjectCode,
+            String paperType, boolean objective);
 
-    @Query("select sum(q.totalScore) from ExamQuestion q where q.pk.examId=?1 and q.pk.subjectCode=?2 and q.pk.objective=?3")
-    public Double sumScoreByExamIdAndSubjectCodeAndObjective(int examId, String subjectCode, boolean objective);
+    @Query("select q from ExamQuestion q where q.pk.examId=?1 and q.pk.subjectCode=?2 and q.pk.paperType=?3 "
+            + "and q.pk.objective=?4 and q.pk.mainNumber=?5 order by q.pk.subNumber")
+    public List<ExamQuestion> findByExamIdAndSubjectCodeAndPaperTypeAndObjectiveAndMainNumber(int examId,
+            String subjectCode, String paperType, boolean objective, int mainNumber);
+
+    @Query("select sum(q.totalScore) from ExamQuestion q where q.pk.examId=?1 and q.pk.subjectCode=?2 "
+            + "and q.pk.paperType=?3 and q.pk.objective=?4")
+    public Double sumScoreByExamIdAndSubjectCodeAndPaperTypeAndObjective(int examId, String subjectCode,
+            String paperType, boolean objective);
 
     @Modifying
     @Query("delete from ExamQuestion q where q.pk.examId=?1")
@@ -35,13 +44,21 @@ public interface ExamQuestionDao
     @Query("delete from ExamQuestion q where q.pk.examId=?1 and q.pk.subjectCode=?2 and q.pk.objective=?3")
     public void deleteByExamIdAndSubjectCodeAndObjective(int examId, String subjectCode, boolean objective);
 
+    @Modifying
+    @Query("delete from ExamQuestion q where q.pk.examId=?1 and q.pk.subjectCode=?2 "
+            + "and q.pk.paperType=?3 and q.pk.objective=?4")
+    public void deleteByExamIdAndSubjectCodeAndPaperTypeAndObjective(int examId, String subjectCode, String paperType,
+            boolean objective);
+
     @Modifying(clearAutomatically = true)
-    @Query("delete from ExamQuestion q where q.pk.examId=?1 and q.pk.subjectCode=?2 and q.pk.objective=?3 and q.pk.mainNumber=?4")
-    public void deleteByExamIdAndSubjectCodeAndObjectiveAndMainNumber(int examId, String subjectCode, boolean objective,
-            int mainNumber);
+    @Query("delete from ExamQuestion q where q.pk.examId=?1 and q.pk.subjectCode=?2 "
+            + "and q.pk.paperType=?3 and q.pk.objective=?4 and q.pk.mainNumber=?5")
+    public void deleteByExamIdAndSubjectCodeAndPaperTypeAndObjectiveAndMainNumber(int examId, String subjectCode,
+            String paperType, boolean objective, int mainNumber);
 
     @Modifying
-    @Query("update ExamQuestion q set q.mainTitle=?5 where q.pk.examId=?1 and q.pk.subjectCode=?2 and q.pk.objective=?3 and q.pk.mainNumber=?4")
+    @Query("update ExamQuestion q set q.mainTitle=?5 where q.pk.examId=?1 and q.pk.subjectCode=?2 "
+            + "and q.pk.objective=?3 and q.pk.mainNumber=?4")
     public void updateMainTitleByExamIdAndSubjectCodeAndObjectiveAndMainNumber(int examId, String subjectCode,
             boolean objective, int mainNumber, String mainTitle);
 

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

@@ -78,10 +78,10 @@ public interface ExamStudentDao
     public void updateManualAbsent(int examId, String examNumber, boolean manualAbsent);
 
     @Modifying
-    @Query("update ExamStudent s set s.sheetCount=?2, s.sliceCount=?3, s.answers=?4, s.batchCode=?5, s.absent=?6,"
-            + " s.upload=true, s.uploadTime=?7, s.objectiveScore=?8, s.objectiveScoreList=?9 where s.id=?1")
+    @Query("update ExamStudent s set s.sheetCount=?2, s.sliceCount=?3, s.answers=?4, s.batchCode=?5, s.paperType=?6,"
+            + " s.absent=?7, s.upload=true, s.uploadTime=?8, s.objectiveScore=?9, s.objectiveScoreList=?10 where s.id=?1")
     public int updateScanInfo(Integer id, Integer sheetCount, Integer sliceCount, String answers, String batchCode,
-            boolean absent, Date uploadTime, Double objectiveScore, String objectiveScoreList);
+            String paperType, boolean absent, Date uploadTime, Double objectiveScore, String objectiveScoreList);
 
     @Modifying
     @Query("update ExamStudent s set s.manualAbsent=0 where s.examId=?1")

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

@@ -34,15 +34,18 @@ public interface MarkGroupDao
     List<MarkGroup> findByExamId(int examId);
 
     @Query("select q from MarkGroup q where q.pk.examId=?1 and q.pk.subjectCode=?2 order by q.pk.number")
-    List<MarkGroup> findByExamIdAndSubjectCode(int examId, String code);
+    List<MarkGroup> findByExamIdAndSubjectCode(int examId, String subjectCode);
 
     @Query("select q from MarkGroup q where q.pk.examId=?1 and q.pk.subjectCode=?2 "
             + "and q.doubleRate!=null and q.doubleRate>0 order by q.pk.number")
-    List<MarkGroup> findByExamIdAndSubjectCodeWithDouble(int examId, String code);
+    List<MarkGroup> findByExamIdAndSubjectCodeWithDouble(int examId, String subjectCode);
 
     @Query("select count(q) from MarkGroup q where q.pk.examId=?1")
     long countByExamId(int examId);
 
+    @Query("select sum(g.totalScore) from MarkGroup g where g.pk.examId=?1 and g.pk.subjectCode=?2")
+    Double sumTotalScore(Integer examId, String subjectCode);
+
     @Query("select sum(g.libraryCount) from MarkGroup g where g.pk.examId=?1")
     Integer sumLibraryCount(Integer examId);
 

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

@@ -87,6 +87,14 @@ public class ExamQuestion implements Serializable {
         pk.setSubjectCode(subjectCode);
     }
 
+    public String getPaperType() {
+        return pk.getPaperType();
+    }
+
+    public void setPaperType(String paperType) {
+        pk.setPaperType(paperType);
+    }
+
     public Integer getMainNumber() {
         return pk.getMainNumber();
     }

+ 688 - 674
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/model/ExamStudent.java

@@ -1,674 +1,688 @@
-package cn.com.qmth.stmms.biz.exam.model;
-
-import java.io.Serializable;
-import java.util.ArrayList;
-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 javax.persistence.Temporal;
-import javax.persistence.TemporalType;
-import javax.persistence.Transient;
-
-import org.apache.commons.lang.StringUtils;
-
-import cn.com.qmth.stmms.biz.utils.ScoreItem;
-import cn.com.qmth.stmms.common.annotation.ExcelField;
-
-/**
- * 针对某次考试的考生信息
- * 
- * @author LS
- * 
- */
-@Entity
-@Table(name = "eb_exam_student")
-public class ExamStudent implements Serializable {
-
-    protected static final long serialVersionUID = 2944870647483950851L;
-
-    public static final String ANSWER_SPLIT = ",";
-
-    public static final String SPLIT = ";";
-
-    @Id
-    @GeneratedValue
-    private Integer id;
-
-    /**
-     * 考试ID
-     */
-    @Column(name = "exam_id")
-    private Integer examId;
-
-    /**
-     * 学校ID
-     */
-    @Column(name = "school_id")
-    private Integer schoolId;
-
-    /**
-     * 学习中心
-     */
-    @Column(name = "campus_name")
-    @ExcelField(title = "学习中心", align = 2, sort = 10)
-    private String campusName;
-
-    /**
-     * 科目代码
-     */
-    @Column(name = "subject_code")
-    @ExcelField(title = "课程代码", align = 2, sort = 20)
-    private String subjectCode;
-
-    /**
-     * 科目名称
-     */
-    @Column(name = "subject_name")
-    @ExcelField(title = "课程名称", align = 2, sort = 30)
-    private String subjectName;
-
-    /**
-     * 准考证号
-     */
-    @Column(name = "exam_number")
-    @ExcelField(title = "准考证号", align = 2, sort = 40)
-    private String examNumber;
-
-    /**
-     * 学号
-     */
-    @Column(name = "student_code")
-    @ExcelField(title = "学号", align = 2, sort = 50)
-    private String studentCode;
-
-    /**
-     * 姓名
-     */
-    @Column(name = "name")
-    @ExcelField(title = "姓名", align = 2, sort = 60)
-    private String name;
-
-    /**
-     * 试卷袋签到表编号
-     */
-    @Column(name = "package_code")
-    @ExcelField(title = "签到表编号", align = 2, sort = 70)
-    private String packageCode;
-
-    /**
-     * 考生考点信息
-     */
-    @Column(name = "exam_site")
-    @ExcelField(title = "考点信息", align = 2, sort = 80)
-    private String examSite;
-
-    /**
-     * 考生考场信息
-     */
-    @Column(name = "exam_room")
-    @ExcelField(title = "考场信息", align = 2, sort = 90)
-    private String examRoom;
-
-    /**
-     * 考生备注信息
-     */
-    @Column(name = "remark")
-    @ExcelField(title = "考生备注信息", align = 2, sort = 100)
-    private String remark;
-
-    /**
-     * 扫描批次编号
-     */
-    @Column(name = "batch_code")
-    private String batchCode;
-
-    /**
-     * 原图数量
-     */
-    @Column(name = "sheet_count")
-    private Integer sheetCount;
-
-    /**
-     * 小图数量
-     */
-    @Column(name = "slice_count")
-    private Integer sliceCount;
-
-    /**
-     * 客观答案
-     */
-    @Column(name = "answers")
-    private String answers;
-
-    /**
-     * 是否已上传
-     */
-    @Column(name = "is_upload")
-    private boolean upload;
-
-    /**
-     * 是否缺考
-     */
-    @Column(name = "is_absent")
-    private boolean absent;
-    
-    /**
-     * 是否人工指定缺考
-     */
-    @Column(name = "is_manual_absent")
-    private boolean manualAbsent;
-
-    @Column(name = "is_breach")
-    private boolean breach;
-
-    /**
-     * 是否数据校验异常
-     */
-    @Column(name = "is_exception")
-    private boolean exception;
-
-    /**
-     * 上传时间
-     */
-    @Temporal(TemporalType.TIMESTAMP)
-    @Column(name = "upload_time")
-    private Date uploadTime;
-
-    /**
-     * 客观总分
-     */
-    @Column(name = "objective_score")
-    private Double objectiveScore;
-
-    /**
-     * 客观题得分明细
-     */
-    @Column(name = "objective_score_list")
-    private String objectiveScoreList;
-
-    /**
-     * 主观总分
-     */
-    @Column(name = "subjective_score")
-    private Double subjectiveScore;
-
-    /**
-     * 主观题得分明细
-     */
-    @Column(name = "subjective_score_list")
-    private String subjectiveScoreList;
-
-    /**
-     * 科目层次信息
-     */
-    @ExcelField(title = "层次", align = 2, sort = 110)
-    @Column(name = "subject_level")
-    private String subjectLevel;
-
-    /**
-     * 专业类型信息
-     */
-    @ExcelField(title = "专业类型", align = 2, sort = 120)
-    @Column(name = "subject_category")
-    private String subjectCategory;
-
-    /**
-     * 科目备注信息
-     */
-    @ExcelField(title = "科目备注信息", align = 2, sort = 130)
-    @Transient
-    private String subjectRemark;
-
-    @Transient
-    private ExamSubject subject;
-
-    @Transient
-    private List<String> sheetUrls;
-
-    @Transient
-    private List<String> packageUrls;
-
-    @Transient
-    private String answerUrl;
-
-    @Transient
-    private String markTime;
-
-    @Transient
-    private Integer libraryId;
-    
-    @Transient
-    private int number;
-    
-    @Transient
-    private String markLogin;
-    
-    @Transient
-    private String markName;
-    
-    @Transient
-    private String tagValue;
-
-    public Integer getId() {
-        return id;
-    }
-
-    public void setId(Integer id) {
-        this.id = id;
-    }
-
-    public Integer getExamId() {
-        return examId;
-    }
-
-    public void setExamId(Integer examId) {
-        this.examId = examId;
-    }
-
-    public String getCampusName() {
-        return campusName;
-    }
-
-    public void setCampusName(String campusName) {
-        this.campusName = campusName;
-    }
-
-    public String getSubjectCode() {
-        return subjectCode;
-    }
-
-    public void setSubjectCode(String subjectCode) {
-        this.subjectCode = subjectCode;
-    }
-
-    public String getExamNumber() {
-        return examNumber;
-    }
-
-    public void setExamNumber(String examNumber) {
-        this.examNumber = examNumber;
-    }
-
-    public String getName() {
-        return name;
-    }
-
-    public void setName(String name) {
-        this.name = name;
-    }
-
-    public String getSubjectName() {
-        return subjectName;
-    }
-
-    public void setSubjectName(String subjectName) {
-        this.subjectName = subjectName;
-    }
-
-    public String getStudentCode() {
-        return studentCode;
-    }
-
-    public void setStudentCode(String studentCode) {
-        this.studentCode = studentCode;
-    }
-
-    public String getAnswers() {
-        return answers;
-    }
-
-    public void setAnswers(String answers) {
-        this.answers = answers;
-    }
-
-    public boolean isUpload() {
-        return upload;
-    }
-
-    public void setUpload(boolean upload) {
-        this.upload = upload;
-    }
-
-    public Date getUploadTime() {
-        return uploadTime;
-    }
-
-    public void setUploadTime(Date uploadTime) {
-        this.uploadTime = uploadTime;
-    }
-
-    public List<String> getAnswerList() {
-        String[] values = StringUtils.split(StringUtils.trimToNull(answers), ANSWER_SPLIT);
-        List<String> list = new ArrayList<String>();
-        if (values != null && values.length > 0) {
-            for (String answer : values) {
-                list.add(StringUtils.trim(answer));
-            }
-        }
-        return list;
-    }
-
-    public Double getObjectiveScore() {
-        return objectiveScore;
-    }
-
-    public void setObjectiveScore(Double objectiveScore) {
-        this.objectiveScore = objectiveScore;
-    }
-
-    public Double getSubjectiveScore() {
-        return subjectiveScore;
-    }
-
-    public void setSubjectiveScore(Double subjectiveScore) {
-        this.subjectiveScore = subjectiveScore;
-    }
-
-    public String getObjectiveScoreList() {
-        return objectiveScoreList;
-    }
-
-    public void setObjectiveScoreList(String objectiveScoreList) {
-        this.objectiveScoreList = objectiveScoreList;
-    }
-
-    public String getSubjectiveScoreList() {
-        return subjectiveScoreList;
-    }
-
-    public void setSubjectiveScoreList(String subjectiveScoreList) {
-        this.subjectiveScoreList = subjectiveScoreList;
-    }
-
-    public static String buildScoreList(List<ScoreItem> scoreList) {
-        if (scoreList != null) {
-            return StringUtils.join(scoreList, SPLIT);
-        } else {
-            return null;
-        }
-    }
-
-    public void setScoreList(List<ScoreItem> scoreList, boolean objective) {
-        if (scoreList != null) {
-            if (objective) {
-                setObjectiveScoreList(StringUtils.join(scoreList, SPLIT));
-            } else {
-                setSubjectiveScoreList(StringUtils.join(scoreList, SPLIT));
-            }
-        }
-    }
-
-    public List<ScoreItem> getScoreList(boolean objective) {
-        List<ScoreItem> scoreList = new LinkedList<ScoreItem>();
-        try {
-            String[] values = StringUtils.split(objective ? objectiveScoreList : subjectiveScoreList, SPLIT);
-            for (String value : values) {
-                ScoreItem item = ScoreItem.parse(value, objective);
-                item.setObjective(objective);
-                if (item != null) {
-                    scoreList.add(item);
-                }
-            }
-        } catch (Exception e) {
-        }
-        return scoreList;
-    }
-
-    public List<String> getSheetUrls() {
-        return sheetUrls;
-    }
-
-    public void setSheetUrls(List<String> sheetUrls) {
-        this.sheetUrls = sheetUrls;
-    }
-
-    public boolean isAbsent() {
-        return absent;
-    }
-
-    public void setAbsent(boolean absent) {
-        this.absent = absent;
-    }
-
-    public Integer getSheetCount() {
-        return sheetCount;
-    }
-
-    public void setSheetCount(Integer sheetCount) {
-        this.sheetCount = sheetCount;
-    }
-
-    public Integer getSliceCount() {
-        return sliceCount;
-    }
-
-    public void setSliceCount(Integer sliceCount) {
-        this.sliceCount = sliceCount;
-    }
-
-    public double getTotalScore() {
-        double score = 0;
-        if (objectiveScore != null) {
-            score += objectiveScore;
-        }
-        if (subjectiveScore != null) {
-            score += subjectiveScore;
-        }
-        return score;
-    }
-
-    public Integer getSchoolId() {
-        return schoolId;
-    }
-
-    public void setSchoolId(Integer schoolId) {
-        this.schoolId = schoolId;
-    }
-
-    public String getBatchCode() {
-        return batchCode;
-    }
-
-    public void setBatchCode(String batchCode) {
-        this.batchCode = batchCode;
-    }
-
-    public String getPackageCode() {
-        return packageCode;
-    }
-
-    public void setPackageCode(String packageCode) {
-        this.packageCode = packageCode;
-    }
-
-    public List<String> getPackageUrls() {
-        return packageUrls;
-    }
-
-    public void setPackageUrls(List<String> packageUrls) {
-        this.packageUrls = packageUrls;
-    }
-
-    public String getRemark() {
-        return remark;
-    }
-
-    public void setRemark(String remark) {
-        this.remark = remark;
-    }
-
-    public String getMarkTime() {
-        return markTime;
-    }
-
-    public void setMarkTime(String markTime) {
-        this.markTime = markTime;
-    }
-
-    public boolean isException() {
-        return exception;
-    }
-
-    public void setException(boolean exception) {
-        this.exception = exception;
-    }
-
-    public String getObjectiveScoreString() {
-        try {
-            return ScoreItem.NUMBER_FORMAT.format(objectiveScore);
-        } catch (Exception e) {
-            return "";
-        }
-    }
-
-    public String getSubjectiveScoreString() {
-        try {
-            return ScoreItem.NUMBER_FORMAT.format(subjectiveScore);
-        } catch (Exception e) {
-            return "";
-        }
-    }
-
-    public String getTotalScoreString() {
-        try {
-            return ScoreItem.NUMBER_FORMAT.format(getTotalScore());
-        } catch (Exception e) {
-            return "";
-        }
-    }
-
-    public String getSubjectRemark() {
-        return subjectRemark;
-    }
-
-    public void setSubjectRemark(String subjectRemark) {
-        this.subjectRemark = subjectRemark;
-    }
-
-    public String getSheetUrlString() {
-        if (sheetUrls != null) {
-            return StringUtils.join(sheetUrls, ",");
-        } else {
-            return "";
-        }
-    }
-
-    public String getPackageUrlString() {
-        if (packageUrls != null) {
-            return StringUtils.join(packageUrls, ",");
-        } else {
-            return "";
-        }
-    }
-
-    public String getAnswerUrl() {
-        return answerUrl;
-    }
-
-    public void setAnswerUrl(String answerUrl) {
-        this.answerUrl = answerUrl;
-    }
-
-    public String getSubjectLevel() {
-        return subjectLevel;
-    }
-
-    public void setSubjectLevel(String subjectLevel) {
-        this.subjectLevel = subjectLevel;
-    }
-
-    public String getExamSite() {
-        return examSite;
-    }
-
-    public void setExamSite(String examSite) {
-        this.examSite = examSite;
-    }
-
-    public String getExamRoom() {
-        return examRoom;
-    }
-
-    public void setExamRoom(String examRoom) {
-        this.examRoom = examRoom;
-    }
-
-    public String getSubjectCategory() {
-        return subjectCategory;
-    }
-
-    public void setSubjectCategory(String subjectCategory) {
-        this.subjectCategory = subjectCategory;
-    }
-
-    public Integer getLibraryId() {
-        return libraryId;
-    }
-
-    public void setLibraryId(Integer libraryId) {
-        this.libraryId = libraryId;
-    }
-
-    public ExamSubject getSubject() {
-        return subject;
-    }
-
-    public void setSubject(ExamSubject subject) {
-        this.subject = subject;
-    }
-
-	public boolean isBreach() {
-		return breach;
-	}
-
-	public void setBreach(boolean breach) {
-		this.breach = breach;
-	}
-
-	public int getNumber() {
-		return number;
-	}
-
-	public void setNumber(int number) {
-		this.number = number;
-	}
-
-	public String getMarkLogin() {
-		return markLogin;
-	}
-
-	public void setMarkLogin(String markLogin) {
-		this.markLogin = markLogin;
-	}
-
-	public String getMarkName() {
-		return markName;
-	}
-
-	public void setMarkName(String markName) {
-		this.markName = markName;
-	}
-
-	public String getTagValue() {
-		return tagValue;
-	}
-
-	public void setTagValue(String tagValue) {
-		this.tagValue = tagValue;
-	}
-
-	public boolean isManualAbsent() {
-		return manualAbsent;
-	}
-
-	public void setManualAbsent(boolean manualAbsent) {
-		this.manualAbsent = manualAbsent;
-	}
-
-}
+package cn.com.qmth.stmms.biz.exam.model;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+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 javax.persistence.Temporal;
+import javax.persistence.TemporalType;
+import javax.persistence.Transient;
+
+import org.apache.commons.lang.StringUtils;
+
+import cn.com.qmth.stmms.biz.utils.ScoreItem;
+import cn.com.qmth.stmms.common.annotation.ExcelField;
+
+/**
+ * 针对某次考试的考生信息
+ * 
+ * @author LS
+ * 
+ */
+@Entity
+@Table(name = "eb_exam_student")
+public class ExamStudent implements Serializable {
+
+    protected static final long serialVersionUID = 2944870647483950851L;
+
+    public static final String ANSWER_SPLIT = ",";
+
+    public static final String SPLIT = ";";
+
+    @Id
+    @GeneratedValue
+    private Integer id;
+
+    /**
+     * 考试ID
+     */
+    @Column(name = "exam_id")
+    private Integer examId;
+
+    /**
+     * 学校ID
+     */
+    @Column(name = "school_id")
+    private Integer schoolId;
+
+    /**
+     * 学习中心
+     */
+    @Column(name = "campus_name")
+    @ExcelField(title = "学习中心", align = 2, sort = 10)
+    private String campusName;
+
+    /**
+     * 科目代码
+     */
+    @Column(name = "subject_code")
+    @ExcelField(title = "课程代码", align = 2, sort = 20)
+    private String subjectCode;
+
+    /**
+     * 科目名称
+     */
+    @Column(name = "subject_name")
+    @ExcelField(title = "课程名称", align = 2, sort = 30)
+    private String subjectName;
+
+    /**
+     * 试卷类型
+     */
+    @Column(name = "paper_type", length = 32, nullable = true)
+    private String paperType;
+
+    /**
+     * 准考证号
+     */
+    @Column(name = "exam_number")
+    @ExcelField(title = "准考证号", align = 2, sort = 40)
+    private String examNumber;
+
+    /**
+     * 学号
+     */
+    @Column(name = "student_code")
+    @ExcelField(title = "学号", align = 2, sort = 50)
+    private String studentCode;
+
+    /**
+     * 姓名
+     */
+    @Column(name = "name")
+    @ExcelField(title = "姓名", align = 2, sort = 60)
+    private String name;
+
+    /**
+     * 试卷袋签到表编号
+     */
+    @Column(name = "package_code")
+    @ExcelField(title = "签到表编号", align = 2, sort = 70)
+    private String packageCode;
+
+    /**
+     * 考生考点信息
+     */
+    @Column(name = "exam_site")
+    @ExcelField(title = "考点信息", align = 2, sort = 80)
+    private String examSite;
+
+    /**
+     * 考生考场信息
+     */
+    @Column(name = "exam_room")
+    @ExcelField(title = "考场信息", align = 2, sort = 90)
+    private String examRoom;
+
+    /**
+     * 考生备注信息
+     */
+    @Column(name = "remark")
+    @ExcelField(title = "考生备注信息", align = 2, sort = 100)
+    private String remark;
+
+    /**
+     * 扫描批次编号
+     */
+    @Column(name = "batch_code")
+    private String batchCode;
+
+    /**
+     * 原图数量
+     */
+    @Column(name = "sheet_count")
+    private Integer sheetCount;
+
+    /**
+     * 小图数量
+     */
+    @Column(name = "slice_count")
+    private Integer sliceCount;
+
+    /**
+     * 客观答案
+     */
+    @Column(name = "answers")
+    private String answers;
+
+    /**
+     * 是否已上传
+     */
+    @Column(name = "is_upload")
+    private boolean upload;
+
+    /**
+     * 是否缺考
+     */
+    @Column(name = "is_absent")
+    private boolean absent;
+
+    /**
+     * 是否人工指定缺考
+     */
+    @Column(name = "is_manual_absent")
+    private boolean manualAbsent;
+
+    @Column(name = "is_breach")
+    private boolean breach;
+
+    /**
+     * 是否数据校验异常
+     */
+    @Column(name = "is_exception")
+    private boolean exception;
+
+    /**
+     * 上传时间
+     */
+    @Temporal(TemporalType.TIMESTAMP)
+    @Column(name = "upload_time")
+    private Date uploadTime;
+
+    /**
+     * 客观总分
+     */
+    @Column(name = "objective_score")
+    private Double objectiveScore;
+
+    /**
+     * 客观题得分明细
+     */
+    @Column(name = "objective_score_list")
+    private String objectiveScoreList;
+
+    /**
+     * 主观总分
+     */
+    @Column(name = "subjective_score")
+    private Double subjectiveScore;
+
+    /**
+     * 主观题得分明细
+     */
+    @Column(name = "subjective_score_list")
+    private String subjectiveScoreList;
+
+    /**
+     * 科目层次信息
+     */
+    @ExcelField(title = "层次", align = 2, sort = 110)
+    @Column(name = "subject_level")
+    private String subjectLevel;
+
+    /**
+     * 专业类型信息
+     */
+    @ExcelField(title = "专业类型", align = 2, sort = 120)
+    @Column(name = "subject_category")
+    private String subjectCategory;
+
+    /**
+     * 科目备注信息
+     */
+    @ExcelField(title = "科目备注信息", align = 2, sort = 130)
+    @Transient
+    private String subjectRemark;
+
+    @Transient
+    private ExamSubject subject;
+
+    @Transient
+    private List<String> sheetUrls;
+
+    @Transient
+    private List<String> packageUrls;
+
+    @Transient
+    private String answerUrl;
+
+    @Transient
+    private String markTime;
+
+    @Transient
+    private Integer libraryId;
+
+    @Transient
+    private int number;
+
+    @Transient
+    private String markLogin;
+
+    @Transient
+    private String markName;
+
+    @Transient
+    private String tagValue;
+
+    public Integer getId() {
+        return id;
+    }
+
+    public void setId(Integer id) {
+        this.id = id;
+    }
+
+    public Integer getExamId() {
+        return examId;
+    }
+
+    public void setExamId(Integer examId) {
+        this.examId = examId;
+    }
+
+    public String getCampusName() {
+        return campusName;
+    }
+
+    public void setCampusName(String campusName) {
+        this.campusName = campusName;
+    }
+
+    public String getSubjectCode() {
+        return subjectCode;
+    }
+
+    public void setSubjectCode(String subjectCode) {
+        this.subjectCode = subjectCode;
+    }
+
+    public String getExamNumber() {
+        return examNumber;
+    }
+
+    public void setExamNumber(String examNumber) {
+        this.examNumber = examNumber;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public String getSubjectName() {
+        return subjectName;
+    }
+
+    public void setSubjectName(String subjectName) {
+        this.subjectName = subjectName;
+    }
+
+    public String getStudentCode() {
+        return studentCode;
+    }
+
+    public void setStudentCode(String studentCode) {
+        this.studentCode = studentCode;
+    }
+
+    public String getAnswers() {
+        return answers;
+    }
+
+    public void setAnswers(String answers) {
+        this.answers = answers;
+    }
+
+    public boolean isUpload() {
+        return upload;
+    }
+
+    public void setUpload(boolean upload) {
+        this.upload = upload;
+    }
+
+    public Date getUploadTime() {
+        return uploadTime;
+    }
+
+    public void setUploadTime(Date uploadTime) {
+        this.uploadTime = uploadTime;
+    }
+
+    public List<String> getAnswerList() {
+        String[] values = StringUtils.split(StringUtils.trimToNull(answers), ANSWER_SPLIT);
+        List<String> list = new ArrayList<String>();
+        if (values != null && values.length > 0) {
+            for (String answer : values) {
+                list.add(StringUtils.trim(answer));
+            }
+        }
+        return list;
+    }
+
+    public Double getObjectiveScore() {
+        return objectiveScore;
+    }
+
+    public void setObjectiveScore(Double objectiveScore) {
+        this.objectiveScore = objectiveScore;
+    }
+
+    public Double getSubjectiveScore() {
+        return subjectiveScore;
+    }
+
+    public void setSubjectiveScore(Double subjectiveScore) {
+        this.subjectiveScore = subjectiveScore;
+    }
+
+    public String getObjectiveScoreList() {
+        return objectiveScoreList;
+    }
+
+    public void setObjectiveScoreList(String objectiveScoreList) {
+        this.objectiveScoreList = objectiveScoreList;
+    }
+
+    public String getSubjectiveScoreList() {
+        return subjectiveScoreList;
+    }
+
+    public void setSubjectiveScoreList(String subjectiveScoreList) {
+        this.subjectiveScoreList = subjectiveScoreList;
+    }
+
+    public static String buildScoreList(List<ScoreItem> scoreList) {
+        if (scoreList != null) {
+            return StringUtils.join(scoreList, SPLIT);
+        } else {
+            return null;
+        }
+    }
+
+    public void setScoreList(List<ScoreItem> scoreList, boolean objective) {
+        if (scoreList != null) {
+            if (objective) {
+                setObjectiveScoreList(StringUtils.join(scoreList, SPLIT));
+            } else {
+                setSubjectiveScoreList(StringUtils.join(scoreList, SPLIT));
+            }
+        }
+    }
+
+    public List<ScoreItem> getScoreList(boolean objective) {
+        List<ScoreItem> scoreList = new LinkedList<ScoreItem>();
+        try {
+            String[] values = StringUtils.split(objective ? objectiveScoreList : subjectiveScoreList, SPLIT);
+            for (String value : values) {
+                ScoreItem item = ScoreItem.parse(value, objective);
+                item.setObjective(objective);
+                if (item != null) {
+                    scoreList.add(item);
+                }
+            }
+        } catch (Exception e) {
+        }
+        return scoreList;
+    }
+
+    public List<String> getSheetUrls() {
+        return sheetUrls;
+    }
+
+    public void setSheetUrls(List<String> sheetUrls) {
+        this.sheetUrls = sheetUrls;
+    }
+
+    public boolean isAbsent() {
+        return absent;
+    }
+
+    public void setAbsent(boolean absent) {
+        this.absent = absent;
+    }
+
+    public Integer getSheetCount() {
+        return sheetCount;
+    }
+
+    public void setSheetCount(Integer sheetCount) {
+        this.sheetCount = sheetCount;
+    }
+
+    public Integer getSliceCount() {
+        return sliceCount;
+    }
+
+    public void setSliceCount(Integer sliceCount) {
+        this.sliceCount = sliceCount;
+    }
+
+    public double getTotalScore() {
+        double score = 0;
+        if (objectiveScore != null) {
+            score += objectiveScore;
+        }
+        if (subjectiveScore != null) {
+            score += subjectiveScore;
+        }
+        return score;
+    }
+
+    public Integer getSchoolId() {
+        return schoolId;
+    }
+
+    public void setSchoolId(Integer schoolId) {
+        this.schoolId = schoolId;
+    }
+
+    public String getBatchCode() {
+        return batchCode;
+    }
+
+    public void setBatchCode(String batchCode) {
+        this.batchCode = batchCode;
+    }
+
+    public String getPackageCode() {
+        return packageCode;
+    }
+
+    public void setPackageCode(String packageCode) {
+        this.packageCode = packageCode;
+    }
+
+    public List<String> getPackageUrls() {
+        return packageUrls;
+    }
+
+    public void setPackageUrls(List<String> packageUrls) {
+        this.packageUrls = packageUrls;
+    }
+
+    public String getRemark() {
+        return remark;
+    }
+
+    public void setRemark(String remark) {
+        this.remark = remark;
+    }
+
+    public String getMarkTime() {
+        return markTime;
+    }
+
+    public void setMarkTime(String markTime) {
+        this.markTime = markTime;
+    }
+
+    public boolean isException() {
+        return exception;
+    }
+
+    public void setException(boolean exception) {
+        this.exception = exception;
+    }
+
+    public String getObjectiveScoreString() {
+        try {
+            return ScoreItem.NUMBER_FORMAT.format(objectiveScore);
+        } catch (Exception e) {
+            return "";
+        }
+    }
+
+    public String getSubjectiveScoreString() {
+        try {
+            return ScoreItem.NUMBER_FORMAT.format(subjectiveScore);
+        } catch (Exception e) {
+            return "";
+        }
+    }
+
+    public String getTotalScoreString() {
+        try {
+            return ScoreItem.NUMBER_FORMAT.format(getTotalScore());
+        } catch (Exception e) {
+            return "";
+        }
+    }
+
+    public String getSubjectRemark() {
+        return subjectRemark;
+    }
+
+    public void setSubjectRemark(String subjectRemark) {
+        this.subjectRemark = subjectRemark;
+    }
+
+    public String getSheetUrlString() {
+        if (sheetUrls != null) {
+            return StringUtils.join(sheetUrls, ",");
+        } else {
+            return "";
+        }
+    }
+
+    public String getPackageUrlString() {
+        if (packageUrls != null) {
+            return StringUtils.join(packageUrls, ",");
+        } else {
+            return "";
+        }
+    }
+
+    public String getAnswerUrl() {
+        return answerUrl;
+    }
+
+    public void setAnswerUrl(String answerUrl) {
+        this.answerUrl = answerUrl;
+    }
+
+    public String getSubjectLevel() {
+        return subjectLevel;
+    }
+
+    public void setSubjectLevel(String subjectLevel) {
+        this.subjectLevel = subjectLevel;
+    }
+
+    public String getExamSite() {
+        return examSite;
+    }
+
+    public void setExamSite(String examSite) {
+        this.examSite = examSite;
+    }
+
+    public String getExamRoom() {
+        return examRoom;
+    }
+
+    public void setExamRoom(String examRoom) {
+        this.examRoom = examRoom;
+    }
+
+    public String getSubjectCategory() {
+        return subjectCategory;
+    }
+
+    public void setSubjectCategory(String subjectCategory) {
+        this.subjectCategory = subjectCategory;
+    }
+
+    public Integer getLibraryId() {
+        return libraryId;
+    }
+
+    public void setLibraryId(Integer libraryId) {
+        this.libraryId = libraryId;
+    }
+
+    public ExamSubject getSubject() {
+        return subject;
+    }
+
+    public void setSubject(ExamSubject subject) {
+        this.subject = subject;
+    }
+
+    public boolean isBreach() {
+        return breach;
+    }
+
+    public void setBreach(boolean breach) {
+        this.breach = breach;
+    }
+
+    public int getNumber() {
+        return number;
+    }
+
+    public void setNumber(int number) {
+        this.number = number;
+    }
+
+    public String getMarkLogin() {
+        return markLogin;
+    }
+
+    public void setMarkLogin(String markLogin) {
+        this.markLogin = markLogin;
+    }
+
+    public String getMarkName() {
+        return markName;
+    }
+
+    public void setMarkName(String markName) {
+        this.markName = markName;
+    }
+
+    public String getTagValue() {
+        return tagValue;
+    }
+
+    public void setTagValue(String tagValue) {
+        this.tagValue = tagValue;
+    }
+
+    public boolean isManualAbsent() {
+        return manualAbsent;
+    }
+
+    public void setManualAbsent(boolean manualAbsent) {
+        this.manualAbsent = manualAbsent;
+    }
+
+    public String getPaperType() {
+        return paperType;
+    }
+
+    public void setPaperType(String paperType) {
+        this.paperType = paperType;
+    }
+
+}

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

@@ -1,211 +1,211 @@
-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.EnumType;
-import javax.persistence.Enumerated;
-import javax.persistence.Table;
-import javax.persistence.Transient;
-
-import org.apache.commons.lang.StringUtils;
-
-import cn.com.qmth.stmms.common.enums.ExamSubjectStatus;
-import cn.com.qmth.stmms.common.utils.PictureUrlBuilder;
-
-@Entity
-@Table(name = "eb_exam_subject")
-public class ExamSubject implements Serializable {
-
-    private static final long serialVersionUID = -6942849844435873366L;
-
-    @EmbeddedId
-    private ExamSubjectPK pk;
-
-    @Column(name = "name")
-    private String name;
-
-    @Column(name = "level")
-    private String level;
-
-    @Column(name = "category")
-    private String category;
-
-    @Enumerated(EnumType.ORDINAL)
-    @Column(name = "status")
-    private ExamSubjectStatus status;
-
-    @Column(name = "objective_score")
-    private Double objectiveScore;
-
-    @Column(name = "subjective_score")
-    private Double subjectiveScore;
-
-    @Column(name = "total_score")
-    private Double totalScore;
-
-    /**
-     * 上传学生数量
-     */
-    @Column(name = "upload_count")
-    private Integer uploadCount;
-
-    @Column(name = "has_paper")
-    private Boolean hasPaper;
-
-    @Column(name = "has_answer")
-    private Boolean hasAnswer;
-
-    @Column(name = "remark")
-    private String remark;
-
-    /**
-     * 大题数量
-     */
-    @Transient
-    private long groupCount;
-
-    public ExamSubject() {
-        this.pk = new ExamSubjectPK();
-    }
-
-    public Integer getExamId() {
-        return pk.getExamId();
-    }
-
-    public void setExamId(Integer examId) {
-        pk.setExamId(examId);
-    }
-
-    public String getCode() {
-        return pk.getCode();
-    }
-
-    public void setCode(String code) {
-        pk.setCode(code);
-    }
-
-    public String getName() {
-        return name;
-    }
-
-    public void setName(String name) {
-        this.name = name;
-    }
-
-    public ExamSubjectStatus getStatus() {
-        return status;
-    }
-
-    public void setStatus(ExamSubjectStatus status) {
-        this.status = status;
-    }
-
-    public Double getObjectiveScore() {
-        return objectiveScore;
-    }
-
-    public void setObjectiveScore(Double objectiveScore) {
-        this.objectiveScore = objectiveScore;
-    }
-
-    public Double getSubjectiveScore() {
-        return subjectiveScore;
-    }
-
-    public void setSubjectiveScore(Double subjectiveScore) {
-        this.subjectiveScore = subjectiveScore;
-    }
-
-    public void setScore(double score, boolean objective) {
-        if (objective) {
-            setObjectiveScore(score);
-        } else {
-            setSubjectiveScore(score);
-        }
-    }
-
-    public Double getTotalScore() {
-        return totalScore;
-    }
-
-    public void setTotalScore(Double totalScore) {
-        this.totalScore = totalScore;
-    }
-
-    public Boolean getHasPaper() {
-        return hasPaper;
-    }
-
-    public void setHasPaper(Boolean hasPaper) {
-        this.hasPaper = hasPaper;
-    }
-
-    public Boolean getHasAnswer() {
-        return hasAnswer;
-    }
-
-    public void setHasAnswer(Boolean hasAnswer) {
-        this.hasAnswer = hasAnswer;
-    }
-
-    public String getRemark() {
-        return remark;
-    }
-
-    public void setRemark(String remark) {
-        this.remark = remark;
-    }
-
-    public String getDisplayName() {
-        StringBuilder sb = new StringBuilder();
-        sb.append(name);
-        if (StringUtils.isNotBlank(remark)) {
-            sb.append("_").append(remark);
-        }
-        return sb.toString();
-    }
-
-    public String getPaperUrl() {
-        return PictureUrlBuilder.getPaperUrl(getExamId(), getCode());
-    }
-
-    public String getAnswerUrl() {
-        return PictureUrlBuilder.getAnswerUrl(getExamId(), getCode());
-    }
-
-    public String getLevel() {
-        return level;
-    }
-
-    public void setLevel(String level) {
-        this.level = level;
-    }
-
-    public String getCategory() {
-        return category;
-    }
-
-    public void setCategory(String category) {
-        this.category = category;
-    }
-
-    public Integer getUploadCount() {
-        return uploadCount;
-    }
-
-    public void setUploadCount(Integer uploadCount) {
-        this.uploadCount = uploadCount;
-    }
-
-    public long getGroupCount() {
-        return groupCount;
-    }
-
-    public void setGroupCount(long groupCount) {
-        this.groupCount = groupCount;
-    }
-
-}
+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.EnumType;
+import javax.persistence.Enumerated;
+import javax.persistence.Table;
+import javax.persistence.Transient;
+
+import org.apache.commons.lang.StringUtils;
+
+import cn.com.qmth.stmms.common.enums.ExamSubjectStatus;
+import cn.com.qmth.stmms.common.utils.PictureUrlBuilder;
+
+@Entity
+@Table(name = "eb_exam_subject")
+public class ExamSubject implements Serializable {
+
+    private static final long serialVersionUID = -6942849844435873366L;
+
+    @EmbeddedId
+    private ExamSubjectPK pk;
+
+    @Column(name = "name")
+    private String name;
+
+    @Column(name = "level")
+    private String level;
+
+    @Column(name = "category")
+    private String category;
+
+    @Enumerated(EnumType.ORDINAL)
+    @Column(name = "status")
+    private ExamSubjectStatus status;
+
+    @Column(name = "objective_score")
+    private Double objectiveScore;
+
+    @Column(name = "subjective_score")
+    private Double subjectiveScore;
+
+    @Column(name = "total_score")
+    private Double totalScore;
+
+    /**
+     * 上传学生数量
+     */
+    @Column(name = "upload_count")
+    private Integer uploadCount;
+
+    @Column(name = "has_paper")
+    private boolean hasPaper;
+
+    @Column(name = "has_answer")
+    private boolean hasAnswer;
+
+    @Column(name = "remark")
+    private String remark;
+
+    /**
+     * 大题数量
+     */
+    @Transient
+    private long groupCount;
+
+    public ExamSubject() {
+        this.pk = new ExamSubjectPK();
+    }
+
+    public Integer getExamId() {
+        return pk.getExamId();
+    }
+
+    public void setExamId(Integer examId) {
+        pk.setExamId(examId);
+    }
+
+    public String getCode() {
+        return pk.getCode();
+    }
+
+    public void setCode(String code) {
+        pk.setCode(code);
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public ExamSubjectStatus getStatus() {
+        return status;
+    }
+
+    public void setStatus(ExamSubjectStatus status) {
+        this.status = status;
+    }
+
+    public Double getObjectiveScore() {
+        return objectiveScore;
+    }
+
+    public void setObjectiveScore(Double objectiveScore) {
+        this.objectiveScore = objectiveScore;
+    }
+
+    public Double getSubjectiveScore() {
+        return subjectiveScore;
+    }
+
+    public void setSubjectiveScore(Double subjectiveScore) {
+        this.subjectiveScore = subjectiveScore;
+    }
+
+    public void setScore(double score, boolean objective) {
+        if (objective) {
+            setObjectiveScore(score);
+        } else {
+            setSubjectiveScore(score);
+        }
+    }
+
+    public Double getTotalScore() {
+        return totalScore;
+    }
+
+    public void setTotalScore(Double totalScore) {
+        this.totalScore = totalScore;
+    }
+
+    public String getRemark() {
+        return remark;
+    }
+
+    public void setRemark(String remark) {
+        this.remark = remark;
+    }
+
+    public String getDisplayName() {
+        StringBuilder sb = new StringBuilder();
+        sb.append(name);
+        if (StringUtils.isNotBlank(remark)) {
+            sb.append("_").append(remark);
+        }
+        return sb.toString();
+    }
+
+    public String getPaperUrl() {
+        return PictureUrlBuilder.getPaperUrl(getExamId(), getCode());
+    }
+
+    public String getAnswerUrl() {
+        return PictureUrlBuilder.getAnswerUrl(getExamId(), getCode());
+    }
+
+    public String getLevel() {
+        return level;
+    }
+
+    public void setLevel(String level) {
+        this.level = level;
+    }
+
+    public String getCategory() {
+        return category;
+    }
+
+    public void setCategory(String category) {
+        this.category = category;
+    }
+
+    public Integer getUploadCount() {
+        return uploadCount;
+    }
+
+    public void setUploadCount(Integer uploadCount) {
+        this.uploadCount = uploadCount;
+    }
+
+    public long getGroupCount() {
+        return groupCount;
+    }
+
+    public void setGroupCount(long groupCount) {
+        this.groupCount = groupCount;
+    }
+
+    public boolean isHasPaper() {
+        return hasPaper;
+    }
+
+    public void setHasPaper(boolean hasPaper) {
+        this.hasPaper = hasPaper;
+    }
+
+    public boolean isHasAnswer() {
+        return hasAnswer;
+    }
+
+    public void setHasAnswer(boolean hasAnswer) {
+        this.hasAnswer = hasAnswer;
+    }
+
+}

+ 17 - 4
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/model/QuestionPK.java

@@ -16,6 +16,9 @@ public class QuestionPK implements Serializable {
     @Column(name = "subject_code")
     private String subjectCode;
 
+    @Column(name = "paper_type")
+    private String paperType;
+
     @Column(name = "main_number")
     private Integer mainNumber;
 
@@ -41,6 +44,14 @@ public class QuestionPK implements Serializable {
         this.subjectCode = subjectCode;
     }
 
+    public String getPaperType() {
+        return paperType;
+    }
+
+    public void setPaperType(String paperType) {
+        this.paperType = paperType;
+    }
+
     public Integer getMainNumber() {
         return mainNumber;
     }
@@ -71,6 +82,7 @@ public class QuestionPK implements Serializable {
         int result = 1;
         result = PRIME * result + ((examId == null) ? 0 : examId.hashCode());
         result = PRIME * result + ((subjectCode == null) ? 0 : subjectCode.hashCode());
+        result = PRIME * result + ((paperType == null) ? 0 : paperType.hashCode());
         result = PRIME * result + ((mainNumber == null) ? 0 : mainNumber.hashCode());
         result = PRIME * result + ((subNumber == null) ? 0 : subNumber.hashCode());
         result = PRIME * result + (objective ? 1 : 0);
@@ -96,23 +108,24 @@ public class QuestionPK implements Serializable {
                 return false;
         } else if (!subjectCode.equals(other.subjectCode))
             return false;
-
+        if (paperType == null) {
+            if (other.paperType != null)
+                return false;
+        } else if (!paperType.equals(other.paperType))
+            return false;
         if (mainNumber == null) {
             if (other.mainNumber != null)
                 return false;
         } else if (!mainNumber.equals(other.mainNumber))
             return false;
-
         if (subNumber == null) {
             if (other.subNumber != null)
                 return false;
         } else if (!subNumber.equals(other.subNumber))
             return false;
-
         if (objective != other.objective) {
             return false;
         }
-
         return true;
     }
 

+ 16 - 7
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/service/ExamQuestionService.java

@@ -15,19 +15,27 @@ public interface ExamQuestionService {
 
     void deleteByExamAndSubjectAndObjective(int examId, String subjectCode, boolean objective);
 
-    void deleteByExamAndSubjectAndObjectiveAndMainNumber(int examId, String subjectCode, boolean objective,
-            int mainNumber);
+    void deleteByExamAndSubjectAndPaperTypeAndObjective(int examId, String subjectCode, String paperType,
+            boolean objective);
 
-    ExamQuestion findOne(int examId, String subjectCode, boolean objective, int mainNumber, int subNumber);
+    void deleteByExamAndSubjectAndPaperTypeAndObjectiveAndMainNumber(int examId, String subjectCode, String paperType,
+            boolean objective, int mainNumber);
+
+    ExamQuestion findOne(int examId, String subjectCode, String paperType, boolean objective, int mainNumber,
+            int subNumber);
 
     List<ExamQuestion> findByExamAndSubjectAndObjective(int examId, String subjectCode, boolean objective);
 
-    List<ExamQuestion> findByExamAndSubjectAndObjectiveAndMainNumber(int examId, String subjectCode, boolean objective,
-            int mainNumber);
+    List<ExamQuestion> findByExamAndSubjectAndPaperTypeAndObjective(int examId, String subjectCode, String paperType,
+            boolean objective);
+
+    List<ExamQuestion> findByExamAndSubjectAndPaperTypeAndObjectiveAndMainNumber(int examId, String subjectCode,
+            String paperType, boolean objective, int mainNumber);
 
     long countByExamAndSubject(int examId, String subjectCode);
 
-    long countByExamAndSubjectAndObjective(int examId, String subjectCode, boolean objective);
+    long countByExamAndSubjectAndPaperTypeAndObjective(int examId, String subjectCode, String paperType,
+            boolean objective);
 
     ExamQuestionSearchQuery findByQuery(ExamQuestionSearchQuery query);
 
@@ -35,6 +43,7 @@ public interface ExamQuestionService {
 
     void updateMainTitle(int examId, String subjectCode, boolean objective, int mainNumber, String mainTitle);
 
-    double sumScoreByExamAndSubjectAndObjective(int examId, String subjectCode, boolean objective);
+    double sumScoreByExamAndSubjectAndPaperTypeAndObjective(int examId, String subjectCode, String paperType,
+            boolean objective);
 
 }

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

@@ -49,6 +49,6 @@ public interface ExamSubjectService {
 
     void updateTotalScore(int examId);
 
-    void updateScore(int examId, String code);
+    void updateScore(int examId, String code, boolean objective, double score);
 
 }

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

@@ -41,4 +41,6 @@ public interface MarkGroupService {
 
     long sumMarkedCount(Integer examId);
 
+    double sumTotalScore(Integer examId, String subjectCode);
+
 }

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

@@ -1,165 +1,188 @@
-package cn.com.qmth.stmms.biz.exam.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.jpa.domain.Specification;
-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.ExamQuestionDao;
-import cn.com.qmth.stmms.biz.exam.model.ExamQuestion;
-import cn.com.qmth.stmms.biz.exam.model.QuestionPK;
-import cn.com.qmth.stmms.biz.exam.service.ExamQuestionService;
-import cn.com.qmth.stmms.biz.exam.service.query.ExamQuestionSearchQuery;
-
-@Service
-public class ExamQuestionServiceImpl extends BaseQueryService<ExamQuestion> implements ExamQuestionService {
-
-    @Autowired
-    private ExamQuestionDao questionDao;
-
-    @Transactional
-    @Override
-    public ExamQuestion save(ExamQuestion question) {
-        return questionDao.saveAndFlush(question);
-    }
-
-    @Transactional
-    @Override
-    public void updateMainTitle(int examId, String subjectCode, boolean objective, int mainNumber, String mainTitle) {
-        questionDao.updateMainTitleByExamIdAndSubjectCodeAndObjectiveAndMainNumber(examId, subjectCode, objective,
-                mainNumber, mainTitle);
-    }
-
-    @Transactional
-    @Override
-    public void deleteByExam(int examId) {
-        questionDao.deleteByExamId(examId);
-    }
-
-    @Transactional
-    @Override
-    public void deleteByExamAndSubject(int examId, String subjectCode) {
-        questionDao.deleteByExamIdAndSubjectCode(examId, subjectCode);
-    }
-
-    @Transactional
-    @Override
-    public void deleteByExamAndSubjectAndObjective(int examId, String subjectCode, boolean objective) {
-        questionDao.deleteByExamIdAndSubjectCodeAndObjective(examId, subjectCode, objective);
-    }
-
-    @Transactional
-    @Override
-    public void deleteByExamAndSubjectAndObjectiveAndMainNumber(int examId, String subjectCode, boolean objective,
-            int mainNumber) {
-        questionDao.deleteByExamIdAndSubjectCodeAndObjectiveAndMainNumber(examId, subjectCode, objective, mainNumber);
-    }
-
-    @Override
-    public ExamQuestion findOne(int examId, String subjectCode, boolean objective, int mainNumber, int subNumber) {
-        QuestionPK pk = new QuestionPK();
-        pk.setExamId(examId);
-        pk.setSubjectCode(subjectCode);
-        pk.setMainNumber(mainNumber);
-        pk.setSubNumber(subNumber);
-        pk.setObjective(objective);
-        return questionDao.findOne(pk);
-    }
-
-    @Override
-    public List<ExamQuestion> findByExamAndSubjectAndObjective(int examId, String subjectCode, boolean objective) {
-        return questionDao.findByExamIdAndSubjectCodeAndObjective(examId, subjectCode, objective);
-    }
-
-    @Override
-    public List<ExamQuestion> findByExamAndSubjectAndObjectiveAndMainNumber(int examId, String subjectCode,
-            boolean objective, int mainNumber) {
-        return questionDao.findByExamIdAndSubjectCodeAndObjectiveAndMainNumber(examId, subjectCode, objective,
-                mainNumber);
-    }
-
-    @Override
-    public long countByExamAndSubject(int examId, String subjectCode) {
-        ExamQuestionSearchQuery query = new ExamQuestionSearchQuery();
-        query.setExamId(examId);
-        query.setSubjectCode(subjectCode);
-        return countByQuery(query);
-    }
-
-    @Override
-    public long countByExamAndSubjectAndObjective(int examId, String subjectCode, boolean objective) {
-        ExamQuestionSearchQuery query = new ExamQuestionSearchQuery();
-        query.setExamId(examId);
-        query.setSubjectCode(subjectCode);
-        query.setObjective(objective);
-        return countByQuery(query);
-    }
-
-    @Override
-    public double sumScoreByExamAndSubjectAndObjective(int examId, String subjectCode, boolean objective) {
-        long count = countByExamAndSubjectAndObjective(examId, subjectCode, objective);
-        if (count > 0) {
-            Double score = questionDao.sumScoreByExamIdAndSubjectCodeAndObjective(examId, subjectCode, objective);
-            return score != null ? score.doubleValue() : 0;
-        } else {
-            return 0;
-        }
-    }
-
-    @Override
-    public ExamQuestionSearchQuery findByQuery(ExamQuestionSearchQuery query) {
-        checkQuery(query);
-        Page<ExamQuestion> result = questionDao.findAll(buildSpecification(query), query);
-        fillResult(result, query);
-        return query;
-    }
-
-    @Override
-    public long countByQuery(ExamQuestionSearchQuery query) {
-        return questionDao.count(buildSpecification(query));
-    }
-
-    private Specification<ExamQuestion> buildSpecification(final ExamQuestionSearchQuery query) {
-        return new Specification<ExamQuestion>() {
-
-            @Override
-            public Predicate toPredicate(Root<ExamQuestion> root, CriteriaQuery<?> cQuery, CriteriaBuilder cb) {
-
-                List<Predicate> predicates = new LinkedList<Predicate>();
-                if (query.getExamId() > 0) {
-                    predicates.add(cb.equal(root.get("pk").get("examId"), query.getExamId()));
-                }
-                if (StringUtils.isNotEmpty(query.getSubjectCode())) {
-                    predicates.add(cb.equal(root.get("pk").get("subjectCode"), query.getSubjectCode()));
-                }
-                if (query.getObjective() != null) {
-                    predicates.add(cb.equal(root.get("pk").get("objective"), query.getObjective()));
-                }
-                if (query.getTotalCountGt() != null) {
-                    predicates.add(cb.gt(root.get("totalCount").as(Integer.class), query.getTotalCountGt()));
-                }
-                if (query.getTotalScoreGt() != null) {
-                    predicates.add(cb.gt(root.get("totalScore").as(Double.class), query.getTotalScoreGt()));
-                }
-                if (query.getZeroRateGt() != null) {
-                    predicates.add(cb.ge(root.get("zeroCount").as(Integer.class),
-                            cb.prod(root.get("totalCount").as(Integer.class), query.getZeroRateGt())));
-                }
-                return predicates.isEmpty() ? cb.conjunction()
-                        : cb.and(predicates.toArray(new Predicate[predicates.size()]));
-            }
-        };
-    }
-
-}
+package cn.com.qmth.stmms.biz.exam.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.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.domain.Page;
+import org.springframework.data.jpa.domain.Specification;
+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.ExamQuestionDao;
+import cn.com.qmth.stmms.biz.exam.model.ExamQuestion;
+import cn.com.qmth.stmms.biz.exam.model.QuestionPK;
+import cn.com.qmth.stmms.biz.exam.service.ExamQuestionService;
+import cn.com.qmth.stmms.biz.exam.service.query.ExamQuestionSearchQuery;
+
+@Service
+public class ExamQuestionServiceImpl extends BaseQueryService<ExamQuestion> implements ExamQuestionService {
+
+    @Autowired
+    private ExamQuestionDao questionDao;
+
+    @Transactional
+    @Override
+    public ExamQuestion save(ExamQuestion question) {
+        return questionDao.saveAndFlush(question);
+    }
+
+    @Transactional
+    @Override
+    public void updateMainTitle(int examId, String subjectCode, boolean objective, int mainNumber, String mainTitle) {
+        questionDao.updateMainTitleByExamIdAndSubjectCodeAndObjectiveAndMainNumber(examId, subjectCode, objective,
+                mainNumber, mainTitle);
+    }
+
+    @Transactional
+    @Override
+    public void deleteByExam(int examId) {
+        questionDao.deleteByExamId(examId);
+    }
+
+    @Transactional
+    @Override
+    public void deleteByExamAndSubject(int examId, String subjectCode) {
+        questionDao.deleteByExamIdAndSubjectCode(examId, subjectCode);
+    }
+
+    @Transactional
+    @Override
+    public void deleteByExamAndSubjectAndObjective(int examId, String subjectCode, boolean objective) {
+        questionDao.deleteByExamIdAndSubjectCodeAndObjective(examId, subjectCode, objective);
+    }
+
+    @Transactional
+    @Override
+    public void deleteByExamAndSubjectAndPaperTypeAndObjective(int examId, String subjectCode, String paperType,
+            boolean objective) {
+        questionDao.deleteByExamIdAndSubjectCodeAndPaperTypeAndObjective(examId, subjectCode, paperType, objective);
+    }
+
+    @Transactional
+    @Override
+    public void deleteByExamAndSubjectAndPaperTypeAndObjectiveAndMainNumber(int examId, String subjectCode,
+            String paperType, boolean objective, int mainNumber) {
+        questionDao.deleteByExamIdAndSubjectCodeAndPaperTypeAndObjectiveAndMainNumber(examId, subjectCode, paperType,
+                objective, mainNumber);
+    }
+
+    @Override
+    public ExamQuestion findOne(int examId, String subjectCode, String paperType, boolean objective, int mainNumber,
+            int subNumber) {
+        QuestionPK pk = new QuestionPK();
+        pk.setExamId(examId);
+        pk.setSubjectCode(subjectCode);
+        pk.setPaperType(paperType);
+        pk.setMainNumber(mainNumber);
+        pk.setSubNumber(subNumber);
+        pk.setObjective(objective);
+        return questionDao.findOne(pk);
+    }
+
+    @Override
+    public List<ExamQuestion> findByExamAndSubjectAndObjective(int examId, String subjectCode, boolean objective) {
+        return questionDao.findByExamIdAndSubjectCodeAndObjective(examId, subjectCode, objective);
+    }
+
+    @Override
+    public List<ExamQuestion> findByExamAndSubjectAndPaperTypeAndObjective(int examId, String subjectCode,
+            String paperType, boolean objective) {
+        return questionDao.findByExamIdAndSubjectCodeAndPaperTypeAndObjective(examId, subjectCode, paperType,
+                objective);
+    }
+
+    @Override
+    public List<ExamQuestion> findByExamAndSubjectAndPaperTypeAndObjectiveAndMainNumber(int examId, String subjectCode,
+            String paperType, boolean objective, int mainNumber) {
+        return questionDao.findByExamIdAndSubjectCodeAndPaperTypeAndObjectiveAndMainNumber(examId, subjectCode,
+                paperType, objective, mainNumber);
+    }
+
+    @Override
+    public long countByExamAndSubject(int examId, String subjectCode) {
+        ExamQuestionSearchQuery query = new ExamQuestionSearchQuery();
+        query.setExamId(examId);
+        query.setSubjectCode(subjectCode);
+        return countByQuery(query);
+    }
+
+    @Override
+    public long countByExamAndSubjectAndPaperTypeAndObjective(int examId, String subjectCode, String paperType,
+            boolean objective) {
+        ExamQuestionSearchQuery query = new ExamQuestionSearchQuery();
+        query.setExamId(examId);
+        query.setSubjectCode(subjectCode);
+        query.setPaperType(paperType);
+        query.setObjective(objective);
+        return countByQuery(query);
+    }
+
+    @Override
+    public double sumScoreByExamAndSubjectAndPaperTypeAndObjective(int examId, String subjectCode, String paperType,
+            boolean objective) {
+        long count = countByExamAndSubjectAndPaperTypeAndObjective(examId, subjectCode, paperType, objective);
+        if (count > 0) {
+            Double score = questionDao.sumScoreByExamIdAndSubjectCodeAndPaperTypeAndObjective(examId, subjectCode,
+                    paperType, objective);
+            return score != null ? score.doubleValue() : 0;
+        } else {
+            return 0;
+        }
+    }
+
+    @Override
+    public ExamQuestionSearchQuery findByQuery(ExamQuestionSearchQuery query) {
+        checkQuery(query);
+        Page<ExamQuestion> result = questionDao.findAll(buildSpecification(query), query);
+        fillResult(result, query);
+        return query;
+    }
+
+    @Override
+    public long countByQuery(ExamQuestionSearchQuery query) {
+        return questionDao.count(buildSpecification(query));
+    }
+
+    private Specification<ExamQuestion> buildSpecification(final ExamQuestionSearchQuery query) {
+        return new Specification<ExamQuestion>() {
+
+            @Override
+            public Predicate toPredicate(Root<ExamQuestion> root, CriteriaQuery<?> cQuery, CriteriaBuilder cb) {
+
+                List<Predicate> predicates = new LinkedList<Predicate>();
+                if (query.getExamId() > 0) {
+                    predicates.add(cb.equal(root.get("pk").get("examId"), query.getExamId()));
+                }
+                if (query.getSubjectCode() != null) {
+                    predicates.add(cb.equal(root.get("pk").get("subjectCode"), query.getSubjectCode()));
+                }
+                if (query.getPaperType() != null) {
+                    predicates.add(cb.equal(root.get("pk").get("paperType"), query.getPaperType()));
+                }
+                if (query.getObjective() != null) {
+                    predicates.add(cb.equal(root.get("pk").get("objective"), query.getObjective()));
+                }
+                if (query.getTotalCountGt() != null) {
+                    predicates.add(cb.gt(root.get("totalCount").as(Integer.class), query.getTotalCountGt()));
+                }
+                if (query.getTotalScoreGt() != null) {
+                    predicates.add(cb.gt(root.get("totalScore").as(Double.class), query.getTotalScoreGt()));
+                }
+                if (query.getZeroRateGt() != null) {
+                    predicates.add(cb.ge(root.get("zeroCount").as(Integer.class),
+                            cb.prod(root.get("totalCount").as(Integer.class), query.getZeroRateGt())));
+                }
+                return predicates.isEmpty() ? cb.conjunction()
+                        : cb.and(predicates.toArray(new Predicate[predicates.size()]));
+            }
+        };
+    }
+
+}

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

@@ -385,8 +385,8 @@ public class ExamStudentServiceImpl extends BaseQueryService<ExamStudent> implem
     public boolean updateScanInfo(ExamStudent student) {
         student.setUploadTime(new Date());
         return studentDao.updateScanInfo(student.getId(), student.getSheetCount(), student.getSliceCount(),
-                student.getAnswers(), student.getBatchCode(), student.isAbsent(), student.getUploadTime(),
-                student.getObjectiveScore(), student.getObjectiveScoreList()) > 0;
+                student.getAnswers(), student.getBatchCode(), student.getPaperType(), student.isAbsent(),
+                student.getUploadTime(), student.getObjectiveScore(), student.getObjectiveScoreList()) > 0;
     }
 
     @Override
@@ -782,8 +782,8 @@ public class ExamStudentServiceImpl extends BaseQueryService<ExamStudent> implem
     @Override
     public Map<MarkGroup, List<OriginTag>> getSliceTags(ExamStudent student) {
         Map<MarkGroup, List<OriginTag>> tagMap = new HashMap<MarkGroup, List<OriginTag>>();
-        List<ExamQuestion> questions = questionService.findByExamAndSubjectAndObjective(student.getExamId(),
-                student.getSubjectCode(), false);
+        List<ExamQuestion> questions = questionService.findByExamAndSubjectAndPaperTypeAndObjective(student.getExamId(),
+                student.getSubjectCode(), student.getPaperType(), false);
         List<ScoreItem> scoreList = student.getScoreList(false);
         List<MarkGroup> markGroups = groupService.findByExamAndSubject(student.getExamId(), student.getSubjectCode());
         for (MarkGroup group : markGroups) {
@@ -809,8 +809,8 @@ public class ExamStudentServiceImpl extends BaseQueryService<ExamStudent> implem
                 + format.format(student.getSubjectiveScore() != null ? student.getSubjectiveScore() : 0));
         // 客观题得分明细
         List<String> objectives = new LinkedList<>();
-        List<ExamQuestion> questions = questionService.findByExamAndSubjectAndObjective(student.getExamId(),
-                student.getSubjectCode(), true);
+        List<ExamQuestion> questions = questionService.findByExamAndSubjectAndPaperTypeAndObjective(student.getExamId(),
+                student.getSubjectCode(), student.getPaperType(), true);
         List<ScoreItem> scoreList = student.getScoreList(true);
         List<String> details = new ArrayList<>();
         int i = 0;

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

@@ -20,7 +20,6 @@ import org.springframework.transaction.annotation.Transactional;
 import cn.com.qmth.stmms.biz.common.BaseQueryService;
 import cn.com.qmth.stmms.biz.exam.dao.ExamSubjectDao;
 import cn.com.qmth.stmms.biz.exam.model.ExamSubject;
-import cn.com.qmth.stmms.biz.exam.service.ExamQuestionService;
 import cn.com.qmth.stmms.biz.exam.service.ExamSubjectService;
 import cn.com.qmth.stmms.biz.exam.service.query.ExamSubjectSearchQuery;
 import cn.com.qmth.stmms.common.enums.ExamSubjectStatus;
@@ -31,9 +30,6 @@ public class ExamSubjectServiceImpl extends BaseQueryService<ExamSubject> implem
     @Autowired
     private ExamSubjectDao subjectDao;
 
-    @Autowired
-    private ExamQuestionService questionService;
-
     @Transactional
     @Override
     // @CachePut(value = "exam_subject_cache", key =
@@ -179,11 +175,12 @@ public class ExamSubjectServiceImpl extends BaseQueryService<ExamSubject> implem
     @Override
     // @CacheEvict(value = "exam_subject_cache", beforeInvocation = true,
     // allEntries = true)
-    public void updateScore(int examId, String code) {
-        subjectDao.updateObjectiveScore(examId, code,
-                questionService.sumScoreByExamAndSubjectAndObjective(examId, code, true));
-        subjectDao.updateSubjectiveScore(examId, code,
-                questionService.sumScoreByExamAndSubjectAndObjective(examId, code, false));
+    public void updateScore(int examId, String code, boolean objective, double score) {
+        if (objective) {
+            subjectDao.updateObjectiveScore(examId, code, score);
+        } else {
+            subjectDao.updateSubjectiveScore(examId, code, score);
+        }
         subjectDao.updateTotalScoreByExamIdAndCode(examId, code);
     }
 

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

@@ -124,4 +124,10 @@ public class MarkGroupServiceImpl extends BaseQueryService<MarkGroup> implements
         return count != null ? count : 0;
     }
 
+    @Override
+    public double sumTotalScore(Integer examId, String subjectCode) {
+        Double score = groupDao.sumTotalScore(examId, subjectCode);
+        return score != null ? score.doubleValue() : 0d;
+    }
+
 }

+ 10 - 0
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/service/query/ExamQuestionSearchQuery.java

@@ -12,6 +12,8 @@ public class ExamQuestionSearchQuery extends BaseQuery<ExamQuestion> {
 
     private String subjectCode;
 
+    private String paperType;
+
     private Boolean objective;
 
     private Integer totalCountGt;
@@ -72,4 +74,12 @@ public class ExamQuestionSearchQuery extends BaseQuery<ExamQuestion> {
         this.totalScoreGt = totalScoreGt;
     }
 
+    public String getPaperType() {
+        return paperType;
+    }
+
+    public void setPaperType(String paperType) {
+        this.paperType = paperType;
+    }
+
 }

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

@@ -138,15 +138,16 @@ public class MarkServiceImpl implements MarkService {
     public void deleteGroup(MarkGroup group) {
         try {
             lockService.lockGroup(group.getExamId(), group.getSubjectCode(), group.getNumber());
-            questionDao.deleteByExamIdAndSubjectCodeAndObjectiveAndMainNumber(group.getExamId(), group.getSubjectCode(),
-                    false, group.getNumber());
+            questionDao.deleteByExamIdAndSubjectCodeAndPaperTypeAndObjectiveAndMainNumber(group.getExamId(),
+                    group.getSubjectCode(), null, false, group.getNumber());
             libraryDao.deleteByExamIdAndSubjectCodeAndGroupNumber(group.getExamId(), group.getSubjectCode(),
                     group.getNumber());
             arbitrateDao.deleteByExamIdAndSubjectCodeAndGroupNumber(group.getExamId(), group.getSubjectCode(),
                     group.getNumber());
             markerDao.deleteByExamIdAndSubjectCodeAndGroupNumber(group.getExamId(), group.getSubjectCode(),
                     group.getNumber());
-            subjectService.updateScore(group.getExamId(), group.getSubjectCode());
+            subjectService.updateScore(group.getExamId(), group.getSubjectCode(), false,
+                    sumTotalScore(group.getExamId(), group.getSubjectCode()));
 
             releaseByGroup(group);
             groupDao.delete(group);
@@ -168,8 +169,8 @@ public class MarkServiceImpl implements MarkService {
         try {
             lockService.lockGroup(group.getExamId(), group.getSubjectCode(), group.getNumber());
 
-            questionDao.deleteByExamIdAndSubjectCodeAndObjectiveAndMainNumber(group.getExamId(), group.getSubjectCode(),
-                    false, group.getNumber());
+            questionDao.deleteByExamIdAndSubjectCodeAndPaperTypeAndObjectiveAndMainNumber(group.getExamId(),
+                    group.getSubjectCode(), null, false, group.getNumber());
             int i = 0;
             double totalScore = 0d;
             for (Double score : scores) {
@@ -188,7 +189,8 @@ public class MarkServiceImpl implements MarkService {
             }
             groupDao.updateTotalScore(group.getExamId(), group.getSubjectCode(), group.getNumber(), totalScore);
             groupDao.updateScorePolicy(group.getExamId(), group.getSubjectCode(), group.getNumber(), policy);
-            subjectService.updateScore(group.getExamId(), group.getSubjectCode());
+            subjectService.updateScore(group.getExamId(), group.getSubjectCode(), false,
+                    sumTotalScore(group.getExamId(), group.getSubjectCode()));
             resetGroup(group);
         } catch (Exception e) {
             log.error("update group error", e);
@@ -643,4 +645,9 @@ public class MarkServiceImpl implements MarkService {
         releaseByGroup(group);
     }
 
+    private double sumTotalScore(Integer examId, String subjectCode) {
+        Double score = groupDao.sumTotalScore(examId, subjectCode);
+        return score != null ? score.doubleValue() : 0d;
+    }
+
 }

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

@@ -159,8 +159,8 @@ public class TaskServiceImpl implements TaskService {
 
     private List<MarkStepDTO> buildMarkStep(MarkGroup group, Integer libraryId) {
         List<MarkStepDTO> list = new LinkedList<MarkStepDTO>();
-        List<ExamQuestion> sList = questionService.findByExamAndSubjectAndObjectiveAndMainNumber(group.getExamId(),
-                group.getSubjectCode(), false, group.getNumber());
+        List<ExamQuestion> sList = questionService.findByExamAndSubjectAndPaperTypeAndObjectiveAndMainNumber(
+                group.getExamId(), group.getSubjectCode(), null, false, group.getNumber());
         int number = 0;
         for (ExamQuestion question : sList) {
             number++;
@@ -243,8 +243,8 @@ public class TaskServiceImpl implements TaskService {
 
     private List<MarkStepDTO> buildMarkStep(ExamStudent student) {
         List<MarkStepDTO> list = new LinkedList<MarkStepDTO>();
-        List<ExamQuestion> sList = questionService.findByExamAndSubjectAndObjective(student.getExamId(),
-                student.getSubjectCode(), false);
+        List<ExamQuestion> sList = questionService.findByExamAndSubjectAndPaperTypeAndObjective(student.getExamId(),
+                student.getSubjectCode(), null, false);
         int number = 0;
         for (ExamQuestion question : sList) {
             number++;
@@ -286,8 +286,8 @@ public class TaskServiceImpl implements TaskService {
                 stepTask.setLibraryId(library.getId());
                 stepTask.setHeaderId(task.getHeaderId());
                 stepTask.setTags(task.getTags());
-                List<ExamQuestion> sList = questionService.findByExamAndSubjectAndObjectiveAndMainNumber(
-                        library.getExamId(), library.getSubjectCode(), false, library.getGroupNumber());
+                List<ExamQuestion> sList = questionService.findByExamAndSubjectAndPaperTypeAndObjectiveAndMainNumber(
+                        library.getExamId(), library.getSubjectCode(), null, false, library.getGroupNumber());
                 if (start == end) {
                     end = end + sList.size() * 2 - 1;
                 } else {

+ 18 - 22
stmms-web/src/main/java/cn/com/qmth/stmms/admin/dto/ObjectiveQuestionDTO.java

@@ -14,19 +14,22 @@ public class ObjectiveQuestionDTO implements QuestionDTO {
     @ExcelField(title = "科目名称", align = 2, sort = 20)
     private String subjectName;
 
-    @ExcelField(title = "大题名称", align = 2, sort = 30)
+    @ExcelField(title = "试卷类型", align = 2, sort = 30)
+    private String paperType;
+
+    @ExcelField(title = "大题名称", align = 2, sort = 40)
     private String title;
 
-    @ExcelField(title = "大题号(只能用小写数字)", align = 2, sort = 40)
+    @ExcelField(title = "大题号(只能用小写数字)", align = 2, sort = 50)
     private Integer mainNumber;
 
-    @ExcelField(title = "小题号(只能用小写数字)", align = 2, sort = 50)
+    @ExcelField(title = "小题号(只能用小写数字)", align = 2, sort = 60)
     private Integer subNumber;
 
-    @ExcelField(title = "标准答案", align = 2, sort = 60)
+    @ExcelField(title = "标准答案", align = 2, sort = 70)
     private String answer;
 
-    @ExcelField(title = "小题满分", align = 2, sort = 70)
+    @ExcelField(title = "小题满分", align = 2, sort = 80)
     private Double totalScore;
 
     public ObjectiveQuestionDTO() {
@@ -36,6 +39,7 @@ public class ObjectiveQuestionDTO implements QuestionDTO {
     public ObjectiveQuestionDTO(ExamQuestion question, ExamSubject subject) {
         setSubjectCode(question.getSubjectCode());
         setSubjectName(subject != null ? subject.getName() : "");
+        setPaperType(question.getPaperType());
         setMainNumber(question.getMainNumber());
         setSubNumber(question.getSubNumber());
         setTitle(question.getMainTitle());
@@ -46,6 +50,7 @@ public class ObjectiveQuestionDTO implements QuestionDTO {
     public ExamQuestion transform() {
         ExamQuestion question = new ExamQuestion();
         question.setSubjectCode(StringUtils.trimToNull(subjectCode));
+        question.setPaperType(StringUtils.trimToNull(paperType));
         question.setMainNumber(mainNumber);
         question.setSubNumber(subNumber);
         question.setObjective(true);
@@ -59,23 +64,6 @@ public class ObjectiveQuestionDTO implements QuestionDTO {
         return question;
     }
 
-    public boolean validate() {
-        // 只校验科目代码,其他留待后续校验
-        if (StringUtils.isBlank(subjectCode)) {
-            return false;
-        }
-        // if (StringUtils.isBlank(title)) {
-        // return false;
-        // }
-        // if (StringUtils.isBlank(answer)) {
-        // return false;
-        // }
-        // if (mainNumber == null || subNumber == null || totalScore == null) {
-        // return false;
-        // }
-        return true;
-    }
-
     public String getSubjectCode() {
         return subjectCode;
     }
@@ -132,4 +120,12 @@ public class ObjectiveQuestionDTO implements QuestionDTO {
         this.totalScore = totalScore;
     }
 
+    public String getPaperType() {
+        return paperType;
+    }
+
+    public void setPaperType(String paperType) {
+        this.paperType = paperType;
+    }
+
 }

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

@@ -6,8 +6,6 @@ public interface QuestionDTO {
 
     public String getSubjectCode();
 
-    public boolean validate();
-
     public ExamQuestion transform();
 
 }

+ 83 - 43
stmms-web/src/main/java/cn/com/qmth/stmms/admin/dto/SubjectQuestionDTO.java

@@ -1,10 +1,12 @@
 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;
@@ -15,6 +17,8 @@ import cn.com.qmth.stmms.biz.mark.model.PictureConfigItem;
 
 public class SubjectQuestionDTO {
 
+    private static final String NULL_PAPER_TYPE_PLACEHOLDER = "#";
+
     private int examId;
 
     private String subjectCode;
@@ -25,24 +29,37 @@ public class SubjectQuestionDTO {
 
     private boolean objective;
 
+    private Map<String, List<ExamQuestion>> paperTypeList;
+
     private Map<Integer, MarkGroup> groups;
 
     public SubjectQuestionDTO(int examId, String subjectCode, boolean objective) {
         this.examId = examId;
         this.subjectCode = subjectCode;
         this.list = new LinkedList<ExamQuestion>();
+        this.paperTypeList = new HashMap<>();
         this.groups = new HashMap<Integer, MarkGroup>();
         this.totalScore = 0d;
         this.objective = objective;
     }
 
     public void addQuestion(ExamQuestion question) {
-        if (question != null && question.getSubjectCode().equals(subjectCode)) {
+        if (question != null && question.getTotalScore() != null) {
             question.setExamId(examId);
-            totalScore += question.getTotalScore();
-
             list.add(question);
-            if (!question.isObjective()) {
+
+            if (objective) {
+                String paperType = question.getPaperType();
+                if (paperType == null) {
+                    paperType = NULL_PAPER_TYPE_PLACEHOLDER;
+                }
+                List<ExamQuestion> list = paperTypeList.get(paperType);
+                if (list == null) {
+                    list = new ArrayList<>();
+                    paperTypeList.put(paperType, list);
+                }
+                list.add(question);
+            } else {
                 MarkGroup group = groups.get(question.getMainNumber());
                 if (group == null) {
                     group = new MarkGroup(examId, subjectCode, question.getMainNumber(), question.getMainTitle(),
@@ -53,6 +70,7 @@ public class SubjectQuestionDTO {
                 }
                 group.getQuestionList().add(question);
                 group.setTotalScore(group.getTotalScore() + question.getTotalScore());
+                totalScore += question.getTotalScore();
             }
         }
     }
@@ -77,51 +95,73 @@ public class SubjectQuestionDTO {
         if (list.size() > 0) {
             Set<String> numberSet = new HashSet<String>();
             Map<Integer, String> titleMap = new HashMap<Integer, String>();
-            for (ExamQuestion question : list) {
-                if (StringUtils.isBlank(question.getMainTitle())) {
-                    error.add("[" + subjectCode + "] 有大题名称为空的记录");
-                    return false;
-                }
-                if (question.getMainTitle().length() > 30) {
-                    error.add("[" + subjectCode + "] 有大题名称超过30个字的记录");
-                    return false;
-                }
-                if (question.getMainNumber() == null || question.getSubNumber() == null) {
-                    error.add("[" + subjectCode + "] 有题号为空的记录");
-                    return false;
-                }
-                if (question.getTotalScore() == null) {
-                    error.add("[" + subjectCode + "] 有满分为空的记录");
-                    return false;
-                }
-                if (objective && StringUtils.isBlank(question.getAnswer())) {
-                    error.add("[" + subjectCode + "] 有答案为空的记录");
-                    return false;
+            try {
+                // 基本字段合法性校验
+                for (ExamQuestion question : list) {
+                    if (StringUtils.isBlank(question.getMainTitle())) {
+                        error.add("[" + subjectCode + "] 有大题名称为空的记录");
+                        return false;
+                    }
+                    if (question.getMainTitle().length() > 30) {
+                        error.add("[" + subjectCode + "] 有大题名称超过30个字的记录");
+                        return false;
+                    }
+                    if (question.getMainNumber() == null || question.getSubNumber() == null) {
+                        error.add("[" + subjectCode + "] 有题号为空的记录");
+                        return false;
+                    }
+                    if (question.getTotalScore() == null) {
+                        error.add("[" + subjectCode + "] 有满分为空的记录");
+                        return false;
+                    }
+                    if (objective && StringUtils.isBlank(question.getAnswer())) {
+                        error.add("[" + subjectCode + "] 有答案为空的记录");
+                        return false;
+                    }
+
+                    String title = titleMap.get(question.getMainNumber());
+                    if (title != null && !title.equals(question.getMainTitle())) {
+                        error.add("[" + subjectCode + "] 大题号" + question.getMainNumber() + "有名称不一致的记录");
+                        return false;
+                    } else {
+                        titleMap.put(question.getMainNumber(), question.getMainTitle());
+                    }
+
+                    String number = question.getQuestionNumber();
+                    if (objective) {
+                        number = StringUtils.trimToEmpty(question.getPaperType()) + " " + number;
+                    }
+                    if (numberSet.contains(number)) {
+                        error.add("[" + subjectCode + "] 题号" + number + "有重复记录");
+                        return false;
+                    } else {
+                        numberSet.add(number);
+                    }
                 }
 
-                String title = titleMap.get(question.getMainNumber());
-                if (title != null && !title.equals(question.getMainTitle())) {
-                    error.add("[" + subjectCode + "] 大题号" + question.getMainNumber() + "有名称不一致的记录");
-                    return false;
-                } else {
-                    titleMap.put(question.getMainNumber(), question.getMainTitle());
-                }
-
-                String number = question.getMainNumber() + "-" + question.getSubNumber();
-                if (numberSet.contains(number)) {
-                    error.add("[" + subjectCode + "] 题号" + number + "有重复记录");
-                    return false;
-                } else {
-                    numberSet.add(number);
+                // 客观题时额外校验不同试卷类型的总分需要一致
+                if (objective) {
+                    totalScore = -1;
+                    for (Entry<String, List<ExamQuestion>> entry : paperTypeList.entrySet()) {
+                        double score = 0;
+                        for (ExamQuestion question : entry.getValue()) {
+                            score += question.getTotalScore();
+                        }
+                        if (totalScore == -1) {
+                            totalScore = score;
+                        } else if (totalScore != score) {
+                            error.add("[" + subjectCode + "] 多个试卷类型总分不一致");
+                            return false;
+                        }
+                    }
                 }
+                return true;
+            } finally {
+                numberSet.clear();
+                titleMap.clear();
             }
-
-            numberSet.clear();
-            titleMap.clear();
-            return true;
         } else {
             return false;
         }
     }
-
 }

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

@@ -70,10 +70,10 @@ public class SubjectiveQuestionDTO implements QuestionDTO {
     public ExamQuestion transform() {
         ExamQuestion question = new ExamQuestion();
         question.setSubjectCode(StringUtils.trimToNull(subjectCode));
+        question.setMainTitle(StringUtils.trimToNull(title));
         question.setMainNumber(mainNumber);
         question.setSubNumber(subNumber);
         question.setObjective(false);
-        question.setMainTitle(StringUtils.trimToNull(title));
         question.setTotalScore(totalScore);
         question.setIntervalScore(intervalScore != null && intervalScore > 0 ? intervalScore : 1d);
         question.setTotalCount(0);
@@ -87,23 +87,6 @@ public class SubjectiveQuestionDTO implements QuestionDTO {
         return question;
     }
 
-    public boolean validate() {
-        // 只校验科目代码,其他留待后续校验
-        if (StringUtils.isBlank(subjectCode)) {
-            return false;
-        }
-        // if (StringUtils.isBlank(title)) {
-        // return false;
-        // }
-        // if (intervalScore == null) {
-        // return false;
-        // }
-        // if (mainNumber == null || subNumber == null || totalScore == null) {
-        // return false;
-        // }
-        return true;
-    }
-
     /**
      * 判断是否总分含小数点
      * 

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

@@ -135,8 +135,8 @@ public class AnswerCheckController extends BaseExamController {
 
         JSONArray array = new JSONArray();
         Map<Integer, String> titles = new HashMap<Integer, String>();
-        List<ExamQuestion> questions = questionService.findByExamAndSubjectAndObjective(student.getExamId(),
-                student.getSubjectCode(), true);
+        List<ExamQuestion> questions = questionService.findByExamAndSubjectAndPaperTypeAndObjective(student.getExamId(),
+                student.getSubjectCode(), student.getPaperType(), true);
         List<String> answers = student.getAnswerList();
         if (questions.isEmpty()) {
             // 未设置客观题或无客观题

+ 11 - 10
stmms-web/src/main/java/cn/com/qmth/stmms/admin/exam/MarkGroupController.java

@@ -90,8 +90,8 @@ public class MarkGroupController extends BaseExamController {
         }
         List<MarkGroup> list = groupService.findByExamAndSubject(examId, subjectCode);
         for (MarkGroup group : list) {
-            group.setScoreList(questionService.findByExamAndSubjectAndObjectiveAndMainNumber(examId, subjectCode, false,
-                    group.getNumber()));
+            group.setScoreList(questionService.findByExamAndSubjectAndPaperTypeAndObjectiveAndMainNumber(examId,
+                    subjectCode, null, false, group.getNumber()));
             group.setMarkerCount(markerService.countByExamAndSubjectAndGroup(examId, subjectCode, group.getNumber()));
             group.setCurrentCount(markService.applyCount(group));
             int percent = group.getLibraryCount() > 0
@@ -196,8 +196,8 @@ public class MarkGroupController extends BaseExamController {
             String pictureConfig = buildPictureConfig(group);
             group.setPicList(pictureConfig);
             model.addAttribute("group", group);
-            model.addAttribute("questions", questionService.findByExamAndSubjectAndObjectiveAndMainNumber(
-                    group.getExamId(), group.getSubjectCode(), false, group.getNumber()));
+            model.addAttribute("questions", questionService.findByExamAndSubjectAndPaperTypeAndObjectiveAndMainNumber(
+                    group.getExamId(), group.getSubjectCode(), null, false, group.getNumber()));
             model.addAttribute("pictureConfig", pictureConfig);
             model.addAttribute("markModeList", MarkMode.values());
             model.addAttribute("scorePolicyList", ScorePolicy.values());
@@ -217,8 +217,8 @@ public class MarkGroupController extends BaseExamController {
         if (group != null) {
             String pictureConfig = buildPictureConfig(group);
             group.setPicList(pictureConfig);
-            group.setScoreList(
-                    questionService.findByExamAndSubjectAndObjectiveAndMainNumber(examId, subjectCode, false, number));
+            group.setScoreList(questionService.findByExamAndSubjectAndPaperTypeAndObjectiveAndMainNumber(examId,
+                    subjectCode, null, false, number));
             model.addAttribute("group", group);
             model.addAttribute("pictureConfig", pictureConfig);
             model.addAttribute("markModeList", MarkMode.values());
@@ -257,8 +257,8 @@ public class MarkGroupController extends BaseExamController {
             @RequestParam(required = false) Integer scorePolicy, @RequestParam(required = false) String markMode) {
         int examId = getSessionExamId(request);
         MarkGroup group = groupService.findOne(examId, subjectCode, number);
-        List<ExamQuestion> questionList = questionService.findByExamAndSubjectAndObjectiveAndMainNumber(examId,
-                subjectCode, false, number);
+        List<ExamQuestion> questionList = questionService
+                .findByExamAndSubjectAndPaperTypeAndObjectiveAndMainNumber(examId, subjectCode, null, false, number);
         if (group != null) {
             // quick update
             picList = StringEscapeUtils.unescapeHtml(picList);
@@ -336,7 +336,8 @@ public class MarkGroupController extends BaseExamController {
             List<Double> scores = buildDoubleList(scoreList);
             if (group.getTitle() != null && group.getPicList() != null && scores.size() > 0) {
                 // clear and replace exam_question
-                questionService.deleteByExamAndSubjectAndObjectiveAndMainNumber(examId, subjectCode, false, number);
+                questionService.deleteByExamAndSubjectAndPaperTypeAndObjectiveAndMainNumber(examId, subjectCode, null,
+                        false, number);
                 int i = 0;
                 double totalScore = 0d;
                 for (Double score : scores) {
@@ -355,7 +356,7 @@ public class MarkGroupController extends BaseExamController {
                 }
                 group.setTotalScore(totalScore);
                 groupService.save(group);
-                subjectService.updateScore(examId, subjectCode);
+                subjectService.updateScore(examId, subjectCode, false, groupService.sumTotalScore(examId, subjectCode));
                 redirectAttributes.addAttribute("subjectCode", subjectCode);
                 return "redirect:/admin/exam/group";
             } else {

+ 10 - 8
stmms-web/src/main/java/cn/com/qmth/stmms/admin/exam/PaperController.java

@@ -82,7 +82,7 @@ public class PaperController extends BaseExamController {
 
     @RequestMapping("/detail")
     public String detail(Model model, HttpServletRequest request, @RequestParam String subjectCode,
-            @RequestParam(required = false) Boolean objective) {
+            @RequestParam(required = false) String paperType, @RequestParam(required = false) Boolean objective) {
         WebUser wu = RequestUtils.getWebUser(request);
         int examId = getSessionExamId(request);
         if (wu.isSubjectHeader() && !subjectCode.equals(wu.getUser().getSubjectCode())) {
@@ -92,10 +92,12 @@ public class PaperController extends BaseExamController {
         if (subject != null) {
             List<ExamQuestion> list = new LinkedList<ExamQuestion>();
             if (objective == null || objective.booleanValue() == true) {
-                list.addAll(questionService.findByExamAndSubjectAndObjective(examId, subjectCode, true));
+                list.addAll(questionService.findByExamAndSubjectAndPaperTypeAndObjective(examId, subjectCode, paperType,
+                        true));
             }
             if (objective == null || objective.booleanValue() == false) {
-                list.addAll(questionService.findByExamAndSubjectAndObjective(examId, subjectCode, false));
+                list.addAll(questionService.findByExamAndSubjectAndPaperTypeAndObjective(examId, subjectCode, paperType,
+                        false));
             }
             model.addAttribute("questionList", list);
             model.addAttribute("subject", subject);
@@ -203,8 +205,8 @@ public class PaperController extends BaseExamController {
                         } else {
                             for (MarkGroup group : dto.getGroups().values()) {
                                 if (groupService.findOne(examId, group.getSubjectCode(), group.getNumber()) == null) {
-                                    questionService.deleteByExamAndSubjectAndObjectiveAndMainNumber(group.getExamId(),
-                                            group.getSubjectCode(), false, group.getNumber());
+                                    questionService.deleteByExamAndSubjectAndPaperTypeAndObjectiveAndMainNumber(
+                                            group.getExamId(), group.getSubjectCode(), null, false, group.getNumber());
                                     for (ExamQuestion question : group.getQuestionList()) {
                                         questionService.save(question);
                                     }
@@ -212,7 +214,7 @@ public class PaperController extends BaseExamController {
                                 }
                             }
                         }
-                        subjectService.updateScore(examId, subject.getCode());
+                        subjectService.updateScore(examId, subject.getCode(), objective, dto.getTotalScore());
                         success++;
                     }
                 } else {
@@ -240,8 +242,8 @@ public class PaperController extends BaseExamController {
                     .getDataList(objective ? ObjectiveQuestionDTO.class : SubjectiveQuestionDTO.class);
             if (list != null) {
                 for (QuestionDTO dto : list) {
-                    if (dto.validate()) {
-                        String subjectCode = dto.getSubjectCode();
+                    String subjectCode = StringUtils.trimToNull(dto.getSubjectCode());
+                    if (subjectCode != null) {
                         SubjectQuestionDTO subject = map.get(subjectCode);
                         if (subject == null) {
                             subject = new SubjectQuestionDTO(examId, subjectCode, objective);

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

@@ -233,8 +233,8 @@ public class ScoreController extends BaseExamController {
     private List<ScoreItem> buildScoreList(ExamStudent student) {
         List<ScoreItem> scoreList = new LinkedList<ScoreItem>();
 
-        List<ExamQuestion> oList = questionService.findByExamAndSubjectAndObjective(student.getExamId(),
-                student.getSubjectCode(), true);
+        List<ExamQuestion> oList = questionService.findByExamAndSubjectAndPaperTypeAndObjective(student.getExamId(),
+                student.getSubjectCode(), student.getPaperType(), true);
         List<ScoreItem> list1 = student.getScoreList(true);
         int index = 0;
         for (ExamQuestion question : oList) {
@@ -249,8 +249,8 @@ public class ScoreController extends BaseExamController {
         }
         scoreList.addAll(list1);
 
-        List<ExamQuestion> sList = questionService.findByExamAndSubjectAndObjective(student.getExamId(),
-                student.getSubjectCode(), false);
+        List<ExamQuestion> sList = questionService.findByExamAndSubjectAndPaperTypeAndObjective(student.getExamId(),
+                student.getSubjectCode(), null, false);
         List<ScoreItem> list2 = student.getScoreList(false);
         index = 0;
         for (ExamQuestion question : sList) {
@@ -286,7 +286,7 @@ public class ScoreController extends BaseExamController {
 
     private void buildAnswerUrl(ExamStudent student) {
         ExamSubject subject = subjectService.find(student.getExamId(), student.getSubjectCode());
-        if (subject != null && subject.getHasAnswer().booleanValue()) {
+        if (subject != null && subject.isHasAnswer()) {
             student.setAnswerUrl(subject.getAnswerUrl());
         }
         if (subject != null) {

+ 11 - 8
stmms-web/src/main/java/cn/com/qmth/stmms/admin/thread/ScoreCalculateThread.java

@@ -112,7 +112,7 @@ public class ScoreCalculateThread implements Runnable {
                 continue;
             }
             for (String campusName : campusNameList) {
-                List<ExamQuestion> questions = this.findQuestionList(examSubject.getCode(), false);
+                List<ExamQuestion> questions = this.findQuestionList(examSubject.getCode(), null, false);
                 Long count = studentService.countByExamIdAndSubjectCodeAndCampus(examId, examSubject.getCode(),
                         campusName, true, false);
                 for (ExamQuestion examQuestion : questions) {
@@ -147,7 +147,8 @@ public class ScoreCalculateThread implements Runnable {
     private void calculate(ExamStudent student) {
         try {
             ScoreCalculateUtil util = ScoreCalculateUtil.instance(student);
-            ScoreInfo info = util.calculate(findQuestionList(student.getSubjectCode(), true), null);
+            ScoreInfo info = util.calculate(findQuestionList(student.getSubjectCode(), student.getPaperType(), true),
+                    null);
 
             student.setObjectiveScore(info.getObjectiveScore());
             student.setScoreList(info.getScoreList(), true);
@@ -170,7 +171,7 @@ public class ScoreCalculateThread implements Runnable {
         if (items.isEmpty()) {
             return;
         }
-        List<ExamQuestion> list = this.findQuestionList(student.getSubjectCode(), false);
+        List<ExamQuestion> list = this.findQuestionList(student.getSubjectCode(), student.getPaperType(), false);
         int count = list.size();
         for (int i = 0; i < count; i++) {
             ScoreItem scoreItem = items.size() > i ? items.get(i) : null;
@@ -200,18 +201,20 @@ public class ScoreCalculateThread implements Runnable {
         return StringUtils.join(list, "-");
     }
 
-    private List<ExamQuestion> findQuestionList(String subjectCode, boolean objective) {
+    private List<ExamQuestion> findQuestionList(String subjectCode, String paperType, boolean objective) {
         if (objective) {
-            List<ExamQuestion> list = objectiveMap.get(subjectCode);
+            String key = subjectCode + "_" + StringUtils.trimToEmpty(paperType);
+            List<ExamQuestion> list = objectiveMap.get(key);
             if (list == null) {
-                list = questionService.findByExamAndSubjectAndObjective(examId, subjectCode, true);
-                objectiveMap.put(subjectCode, list);
+                list = questionService.findByExamAndSubjectAndPaperTypeAndObjective(examId, subjectCode, paperType,
+                        true);
+                objectiveMap.put(key, list);
             }
             return list;
         } else {
             List<ExamQuestion> list = subjectiveMap.get(subjectCode);
             if (list == null) {
-                list = questionService.findByExamAndSubjectAndObjective(examId, subjectCode, false);
+                list = questionService.findByExamAndSubjectAndPaperTypeAndObjective(examId, subjectCode, null, false);
                 subjectiveMap.put(subjectCode, list);
             }
             return list;

+ 101 - 75
stmms-web/src/main/java/cn/com/qmth/stmms/api/controller/ExamQuestionController.java

@@ -1,75 +1,101 @@
-package cn.com.qmth.stmms.api.controller;
-
-import java.util.List;
-
-import javax.servlet.http.HttpServletRequest;
-
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Controller;
-import org.springframework.web.bind.annotation.PathVariable;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RequestMethod;
-import org.springframework.web.bind.annotation.ResponseBody;
-
-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.service.ExamQuestionService;
-import cn.com.qmth.stmms.biz.exam.service.ExamSubjectService;
-import net.sf.json.JSONArray;
-import net.sf.json.JSONObject;
-
-@Controller("examQuestionApiController")
-@RequestMapping("/api")
-public class ExamQuestionController extends BaseApiController {
-
-    @Autowired
-    private ExamQuestionService questionService;
-
-    @Autowired
-    private ExamSubjectService subjectService;
-
-    @RequestMapping(value = "/objective/{examId}", method = RequestMethod.GET)
-    @ResponseBody
-    public JSONArray getObjectiveQuestion(HttpServletRequest request, @PathVariable Integer examId) {
-        JSONArray result = new JSONArray();
-        List<ExamSubject> subjectList = subjectService.list(examId);
-        if (subjectList != null) {
-            for (ExamSubject subject : subjectList) {
-                List<ExamQuestion> list = questionService.findByExamAndSubjectAndObjective(examId, subject.getCode(),
-                        true);
-                if (list == null || list.isEmpty()) {
-                    continue;
-                }
-
-                JSONArray array = new JSONArray();
-                int index = 0;
-                JSONObject current = null;
-                for (ExamQuestion question : list) {
-                    index++;
-                    if (question.getTotalScore() > 0) {
-                        if (current == null) {
-                            current = new JSONObject();
-                            current.accumulate("start", index);
-                        }
-                    } else {
-                        if (current != null) {
-                            current.accumulate("end", index - 1);
-                            array.add(current);
-                            current = null;
-                        }
-                    }
-                }
-                if (current != null) {
-                    current.accumulate("end", index);
-                    array.add(current);
-                }
-
-                JSONObject obj = new JSONObject();
-                obj.accumulate("subjectCode", subject.getCode());
-                obj.accumulate("index", array);
-                result.add(obj);
-            }
-        }
-        return result;
-    }
-}
+package cn.com.qmth.stmms.api.controller;
+
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Set;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.ResponseBody;
+
+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.service.ExamQuestionService;
+import cn.com.qmth.stmms.biz.exam.service.ExamSubjectService;
+import net.sf.json.JSONArray;
+import net.sf.json.JSONObject;
+
+@Controller("examQuestionApiController")
+@RequestMapping("/api")
+public class ExamQuestionController extends BaseApiController {
+
+    @Autowired
+    private ExamQuestionService questionService;
+
+    @Autowired
+    private ExamSubjectService subjectService;
+
+    @RequestMapping(value = "/objective/{examId}", method = RequestMethod.GET)
+    @ResponseBody
+    public JSONArray getObjectiveQuestion(HttpServletRequest request, @PathVariable Integer examId) {
+        JSONArray result = new JSONArray();
+        List<ExamSubject> subjectList = subjectService.list(examId);
+        if (subjectList != null) {
+            for (ExamSubject subject : subjectList) {
+                List<ExamQuestion> list = distinct(
+                        questionService.findByExamAndSubjectAndObjective(examId, subject.getCode(), true));
+                if (list.isEmpty()) {
+                    continue;
+                }
+
+                JSONArray array = new JSONArray();
+                int index = 0;
+                JSONObject current = null;
+                for (ExamQuestion question : list) {
+                    index++;
+                    if (question.getTotalScore() > 0) {
+                        if (current == null) {
+                            current = new JSONObject();
+                            current.accumulate("start", index);
+                        }
+                    } else {
+                        if (current != null) {
+                            current.accumulate("end", index - 1);
+                            array.add(current);
+                            current = null;
+                        }
+                    }
+                }
+                if (current != null) {
+                    current.accumulate("end", index);
+                    array.add(current);
+                }
+
+                JSONObject obj = new JSONObject();
+                obj.accumulate("subjectCode", subject.getCode());
+                obj.accumulate("index", array);
+                result.add(obj);
+            }
+        }
+        return result;
+    }
+
+    /**
+     * 针对客观题存在多种paperType的情况,只过滤出其中的一种paperType,获取一份完整的小题集合
+     * 
+     * @param list
+     * @return
+     */
+    private List<ExamQuestion> distinct(List<ExamQuestion> origin) {
+        List<ExamQuestion> list = new LinkedList<>();
+        if (origin != null) {
+            Set<String> numbers = new HashSet<>();
+            for (ExamQuestion question : origin) {
+                String number = question.getQuestionNumber();
+                if (numbers.contains(number)) {
+                    continue;
+                } else {
+                    list.add(question);
+                    numbers.add(number);
+                }
+            }
+        }
+        return list;
+    }
+}

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

@@ -264,8 +264,8 @@ public class ExamStudentController extends BaseApiController {
                         // 构造客观题得分明细
                         JSONArray objective = new JSONArray();
                         List<ScoreItem> scoreList = student.getScoreList(true);
-                        List<ExamQuestion> questionList = questionService
-                                .findByExamAndSubjectAndObjective(student.getExamId(), student.getSubjectCode(), true);
+                        List<ExamQuestion> questionList = questionService.findByExamAndSubjectAndPaperTypeAndObjective(
+                                student.getExamId(), student.getSubjectCode(), student.getPaperType(), true);
                         int i = 0;
                         for (ScoreItem item : scoreList) {
                             i++;
@@ -288,8 +288,8 @@ public class ExamStudentController extends BaseApiController {
                         // 构造主观题得分明细
                         JSONArray subjective = new JSONArray();
                         scoreList = student.getScoreList(false);
-                        questionList = questionService.findByExamAndSubjectAndObjective(student.getExamId(),
-                                student.getSubjectCode(), false);
+                        questionList = questionService.findByExamAndSubjectAndPaperTypeAndObjective(student.getExamId(),
+                                student.getSubjectCode(), null, false);
                         i = 0;
                         for (ScoreItem item : scoreList) {
                             i++;

+ 1 - 0
stmms-web/src/main/java/cn/com/qmth/stmms/api/controller/ScanController.java

@@ -70,6 +70,7 @@ public class ScanController extends BaseApiController {
                     student.setBatchCode(sc.getBatchCode());
                     student.setSliceCount(sc.getSliceCount());
                     student.setSheetCount(sc.getSheetCount());
+                    student.setPaperType(sc.getPaperType());
                     // 同步更新评卷任务
                     if (saveUploadStudent(student)) {
                         JSONObject obj = new JSONObject();

+ 74 - 64
stmms-web/src/main/java/cn/com/qmth/stmms/api/utils/ScanStudentParameter.java

@@ -1,64 +1,74 @@
-package cn.com.qmth.stmms.api.utils;
-
-public class ScanStudentParameter {
-
-    private String examNumber;
-
-    private int sliceCount;
-
-    private int sheetCount;
-
-    private String answers;
-
-    private boolean absent;
-
-    private String batchCode;
-
-    public String getExamNumber() {
-        return examNumber;
-    }
-
-    public void setExamNumber(String examNumber) {
-        this.examNumber = examNumber;
-    }
-
-    public int getSliceCount() {
-        return sliceCount;
-    }
-
-    public void setSliceCount(int sliceCount) {
-        this.sliceCount = sliceCount;
-    }
-
-    public int getSheetCount() {
-        return sheetCount;
-    }
-
-    public void setSheetCount(int sheetCount) {
-        this.sheetCount = sheetCount;
-    }
-
-    public boolean isAbsent() {
-        return absent;
-    }
-
-    public void setAbsent(boolean absent) {
-        this.absent = absent;
-    }
-
-    public String getAnswers() {
-        return answers;
-    }
-
-    public void setAnswers(String answers) {
-        this.answers = answers;
-    }
-
-    public String getBatchCode() {
-        return batchCode;
-    }
-
-    public void setBatchCode(String batchCode) {
-        this.batchCode = batchCode;
-    }
-}
+package cn.com.qmth.stmms.api.utils;
+
+public class ScanStudentParameter {
+
+    private String examNumber;
+
+    private int sliceCount;
+
+    private int sheetCount;
+
+    private String answers;
+
+    private boolean absent;
+
+    private String batchCode;
+
+    private String paperType;
+
+    public String getExamNumber() {
+        return examNumber;
+    }
+
+    public void setExamNumber(String examNumber) {
+        this.examNumber = examNumber;
+    }
+
+    public int getSliceCount() {
+        return sliceCount;
+    }
+
+    public void setSliceCount(int sliceCount) {
+        this.sliceCount = sliceCount;
+    }
+
+    public int getSheetCount() {
+        return sheetCount;
+    }
+
+    public void setSheetCount(int sheetCount) {
+        this.sheetCount = sheetCount;
+    }
+
+    public boolean isAbsent() {
+        return absent;
+    }
+
+    public void setAbsent(boolean absent) {
+        this.absent = absent;
+    }
+
+    public String getAnswers() {
+        return answers;
+    }
+
+    public void setAnswers(String answers) {
+        this.answers = answers;
+    }
+
+    public String getBatchCode() {
+        return batchCode;
+    }
+
+    public void setBatchCode(String batchCode) {
+        this.batchCode = batchCode;
+    }
+
+    public String getPaperType() {
+        return paperType;
+    }
+
+    public void setPaperType(String paperType) {
+        this.paperType = paperType;
+    }
+}

+ 2 - 3
stmms-web/src/main/java/cn/com/qmth/stmms/common/controller/BaseController.java

@@ -123,9 +123,8 @@ public class BaseController {
     private void calculateObjectiveScore(ExamStudent student) {
         ScoreCalculateUtil util = ScoreCalculateUtil.instance(student);
 
-        ScoreInfo info = util.calculate(
-                questionService.findByExamAndSubjectAndObjective(student.getExamId(), student.getSubjectCode(), true),
-                null);
+        ScoreInfo info = util.calculate(questionService.findByExamAndSubjectAndPaperTypeAndObjective(
+                student.getExamId(), student.getSubjectCode(), student.getPaperType(), true), null);
 
         student.setObjectiveScore(info.getObjectiveScore());
         student.setScoreList(info.getScoreList(), true);