瀏覽代碼

Merge branch 'dev0619_luoshi' into dev0926_luoshi

Conflicts:
	stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/service/impl/ExamSubjectPaperServiceImpl.java
	stmms-web/src/main/java/cn/com/qmth/stmms/admin/exam/ScoreController.java
	stmms-web/src/main/java/cn/com/qmth/stmms/admin/thread/ScoreCalculateThread.java
luoshi 6 年之前
父節點
當前提交
567936af75
共有 19 個文件被更改,包括 1041 次插入452 次删除
  1. 11 0
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/dao/ExamStudentPaperDao.java
  2. 84 0
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/model/ExamNumberPK.java
  3. 156 0
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/model/ExamStudentPaper.java
  4. 99 75
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/model/ExamSubjectPaper.java
  5. 55 0
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/model/QuestionDetail.java
  6. 39 0
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/model/QuestionUnit.java
  7. 15 0
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/service/ExamStudentPaperService.java
  8. 14 17
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/service/ExamSubjectPaperService.java
  9. 22 14
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/service/impl/ExamQuestionServiceImpl.java
  10. 36 0
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/service/impl/ExamStudentPaperServiceImpl.java
  11. 103 99
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/service/impl/ExamSubjectPaperServiceImpl.java
  12. 24 10
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/mark/service/Impl/TaskServiceImpl.java
  13. 86 64
      stmms-web/src/main/java/cn/com/qmth/stmms/admin/exam/ScoreController.java
  14. 18 3
      stmms-web/src/main/java/cn/com/qmth/stmms/admin/exam/parameter/BaseParameterController.java
  15. 9 8
      stmms-web/src/main/java/cn/com/qmth/stmms/admin/exam/parameter/ExamPaperController.java
  16. 159 150
      stmms-web/src/main/java/cn/com/qmth/stmms/admin/exam/parameter/ExamSubjectPaperController.java
  17. 9 9
      stmms-web/src/main/java/cn/com/qmth/stmms/admin/quartz/ScheduleRunner.java
  18. 22 3
      stmms-web/src/main/java/cn/com/qmth/stmms/admin/thread/ScoreCalculateThread.java
  19. 80 0
      stmms-web/src/main/java/cn/com/qmth/stmms/api/controller/ExamStudentController.java

+ 11 - 0
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/dao/ExamStudentPaperDao.java

@@ -0,0 +1,11 @@
+package cn.com.qmth.stmms.biz.exam.dao;
+
+import org.springframework.data.repository.PagingAndSortingRepository;
+
+import cn.com.qmth.stmms.biz.exam.model.ExamNumberPK;
+import cn.com.qmth.stmms.biz.exam.model.ExamStudentPaper;
+
+public interface ExamStudentPaperDao extends PagingAndSortingRepository<ExamStudentPaper, ExamNumberPK> {
+
+    ExamStudentPaper findByPkExamIdAndPkExamNumberAndPkObjective(Integer examId, String examNumber, boolean objective);
+}

+ 84 - 0
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/model/ExamNumberPK.java

@@ -0,0 +1,84 @@
+package cn.com.qmth.stmms.biz.exam.model;
+
+import java.io.Serializable;
+
+import javax.persistence.Column;
+import javax.persistence.Embeddable;
+
+@Embeddable
+public class ExamNumberPK implements Serializable {
+
+    private static final long serialVersionUID = -4806329348030887113L;
+
+    @Column(name = "exam_id", nullable = false)
+    private Integer examId;
+
+    @Column(name = "exam_number", nullable = false, length = 128)
+    private String examNumber;
+
+    @Column(name = "is_objective", nullable = false, columnDefinition = "tinyint(1)")
+    private boolean objective;
+
+    public Integer getExamId() {
+        return examId;
+    }
+
+    public void setExamId(Integer examId) {
+        this.examId = examId;
+    }
+
+    public String getExamNumber() {
+        return examNumber;
+    }
+
+    public void setExamNumber(String examNumber) {
+        this.examNumber = examNumber;
+    }
+
+    public boolean isObjective() {
+        return objective;
+    }
+
+    public void setObjective(boolean objective) {
+        this.objective = objective;
+    }
+
+    @Override
+    public int hashCode() {
+        final int PRIME = 31;
+        int result = 1;
+        result = PRIME * result + ((examId == null) ? 0 : examId.hashCode());
+        result = PRIME * result + ((examNumber == null) ? 0 : examNumber.hashCode());
+        result = PRIME * result + (objective ? 1 : 0);
+        return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj)
+            return true;
+        if (obj == null)
+            return false;
+        if (getClass() != obj.getClass())
+            return false;
+        final ExamNumberPK other = (ExamNumberPK) obj;
+        if (examId == null) {
+            if (other.examId != null)
+                return false;
+        } else if (!examId.equals(other.examId))
+            return false;
+
+        if (examNumber == null) {
+            if (other.examNumber != null)
+                return false;
+        } else if (!examNumber.equals(other.examNumber))
+            return false;
+
+        if (objective != other.objective) {
+            return false;
+        }
+
+        return true;
+    }
+
+}

+ 156 - 0
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/model/ExamStudentPaper.java

@@ -0,0 +1,156 @@
+package cn.com.qmth.stmms.biz.exam.model;
+
+import java.io.Serializable;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+import javax.persistence.Column;
+import javax.persistence.EmbeddedId;
+import javax.persistence.Entity;
+import javax.persistence.Table;
+
+import org.apache.commons.lang3.StringUtils;
+
+import net.sf.json.JSONArray;
+import net.sf.json.JsonConfig;
+
+/**
+ * 针对个人专属的试卷结构,对接分布式印刷模式
+ * 
+ * @author luoshi
+ *
+ */
+@Entity
+@Table(name = "eb_exam_student_paper")
+public class ExamStudentPaper implements Serializable {
+
+    private static final long serialVersionUID = -8728455437479640113L;
+
+    @EmbeddedId
+    private ExamNumberPK pk;
+
+    @Column(name = "struct", nullable = false, columnDefinition = "text")
+    private String struct;
+
+    public ExamStudentPaper() {
+        this.pk = new ExamNumberPK();
+    }
+
+    public Integer getExamId() {
+        return pk.getExamId();
+    }
+
+    public void setExamId(Integer examId) {
+        pk.setExamId(examId);
+    }
+
+    public String getExamNumber() {
+        return pk.getExamNumber();
+    }
+
+    public void setExamNumber(String examNumber) {
+        pk.setExamNumber(examNumber);
+    }
+
+    public void setObjective(boolean objective) {
+        pk.setObjective(objective);
+    }
+
+    public boolean isObjective() {
+        return pk.isObjective();
+    }
+
+    public String getStruct() {
+        return struct;
+    }
+
+    public void setStruct(String struct) {
+        this.struct = struct;
+    }
+
+    public List<QuestionDetail> getDetailList() {
+        return parseFromJson(struct);
+    }
+
+    public List<ExamQuestion> getQuestionList() {
+        List<ExamQuestion> list = null;
+        List<QuestionDetail> details = getDetailList();
+        if (details != null && !details.isEmpty()) {
+            list = new LinkedList<>();
+            int index = 1;
+            QuestionDetail lastDetail = null;
+            for (QuestionDetail detail : details) {
+                Collections.sort(detail.getQuestions());
+                int offset = detail.getIndex() - index;
+                for (int i = 0; i < offset; i++) {
+                    ExamQuestion q = new ExamQuestion();
+                    if (lastDetail != null) {
+                        q.setMainNumber(lastDetail.getNumber());
+                        q.setMainTitle(lastDetail.getTitle());
+                        q.setSubNumber(index - lastDetail.getIndex() + 1);
+                    }
+                    q.setExamId(getExamId());
+                    q.setObjective(isObjective());
+                    q.setAnswer("#");
+                    q.setTotalScore(0.0);
+                    q.setIntervalScore(0.0);
+                    list.add(q);
+                    index++;
+                }
+                for (QuestionUnit unit : detail.getQuestions()) {
+                    ExamQuestion q = new ExamQuestion();
+                    q.setExamId(getExamId());
+                    q.setObjective(isObjective());
+                    q.setMainNumber(detail.getNumber());
+                    q.setMainTitle(detail.getTitle());
+                    q.setSubNumber(unit.getNumber());
+                    q.setAnswer(unit.getAnswer());
+                    q.setTotalScore(unit.getScore());
+                    // 根据本题总分是否有小数决定间隔分是1还是0.5
+                    q.setIntervalScore(
+                            q.getTotalScore() != null && q.getTotalScore() > ((int) q.getTotalScore().doubleValue())
+                                    ? 0.5
+                                    : 1.0);
+                    list.add(q);
+                    index++;
+                }
+                lastDetail = detail;
+            }
+        }
+        return list;
+    }
+
+    @SuppressWarnings({ "rawtypes", "unchecked" })
+    public static List<QuestionDetail> parseFromJson(String struct) {
+        List<QuestionDetail> list = null;
+        try {
+            JsonConfig config = new JsonConfig();
+            Map classMap = new HashMap();
+            classMap.put("questions", QuestionUnit.class);
+            config.setClassMap(classMap);
+            list = JSONArray.toList(JSONArray.fromObject(StringUtils.trimToEmpty(struct)), new QuestionDetail(),
+                    config);
+            if (list != null) {
+                Collections.sort(list);
+            }
+        } catch (Exception e) {
+        }
+        return list;
+    }
+
+    public static void main(String[] args) {
+        ExamStudentPaper paper = new ExamStudentPaper();
+        paper.struct = "[{\"title\":\"多选题\",\"number\":2,\"index\":1,\"questions\":[{\"number\":1,\"answer\":\"ACD\",\"score\":2.0},{\"number\":2,\"answer\":\"ABD\",\"score\":2.0},{\"number\":3,\"answer\":\"ABD\",\"score\":2.0},{\"number\":4,\"answer\":\"ABC\",\"score\":2.0},{\"number\":5,\"answer\":\"ABD\",\"score\":2.0}]},{\"title\":\"单选题\",\"number\":1,\"index\":21,\"questions\":[{\"number\":1,\"answer\":\"A\",\"score\":1.0},{\"number\":2,\"answer\":\"A\",\"score\":1.0},{\"number\":3,\"answer\":\"B\",\"score\":1.0},{\"number\":4,\"answer\":\"C\",\"score\":1.0},{\"number\":5,\"answer\":\"A\",\"score\":1.0},{\"number\":6,\"answer\":\"D\",\"score\":1.0},{\"number\":7,\"answer\":\"B\",\"score\":1.0},{\"number\":8,\"answer\":\"D\",\"score\":1.0},{\"number\":9,\"answer\":\"D\",\"score\":1.0},{\"number\":10,\"answer\":\"A\",\"score\":1.0},{\"number\":11,\"answer\":\"C\",\"score\":2.0},{\"number\":12,\"answer\":\"C\",\"score\":2.0},{\"number\":13,\"answer\":\"C\",\"score\":2.0},{\"number\":14,\"answer\":\"C\",\"score\":2.0},{\"number\":15,\"answer\":\"C\",\"score\":2.0}]}]";
+        // paper.struct =
+        // "[{\"title\":\"填空题\",\"number\":1,\"questions\":[{\"number\":1,\"score\":2.0},{\"number\":2,\"score\":2.0},{\"number\":3,\"score\":2.0},{\"number\":4,\"score\":2.0},{\"number\":5,\"score\":2.0}]},{\"title\":\"问答题\",\"number\":2,\"questions\":[{\"number\":1,\"score\":5.0},{\"number\":2,\"score\":5.0},{\"number\":3,\"score\":5.0},{\"number\":4,\"score\":5.0},{\"number\":5,\"score\":5.0}]},{\"title\":\"套题_1\",\"number\":3,\"questions\":[{\"number\":1,\"score\":2.0},{\"number\":2,\"score\":3.0}]},{\"title\":\"套题_3\",\"number\":4,\"questions\":[{\"number\":1,\"answer\":\"C\",\"score\":2.0},{\"number\":2,\"answer\":\"C\",\"score\":2.0},{\"number\":3,\"answer\":\"C\",\"score\":2.0},{\"number\":4,\"answer\":\"C\",\"score\":2.0},{\"number\":5,\"answer\":\"C\",\"score\":2.0},{\"number\":6,\"score\":2.0},{\"number\":7,\"score\":3.0}]}]";
+        List<ExamQuestion> list = paper.getQuestionList();
+        for (ExamQuestion q : list) {
+            System.out.println(q.getMainTitle() + "," + q.getMainNumber() + "," + q.getSubNumber() + "," + q.getAnswer()
+                    + "," + q.getTotalScore());
+        }
+    }
+
+}

+ 99 - 75
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/model/ExamSubjectPaper.java

@@ -3,7 +3,6 @@ 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.GeneratedValue;
 import javax.persistence.Id;
@@ -16,9 +15,9 @@ import javax.persistence.Table;
 @Table(name = "eb_exam_subject_paper")
 public class ExamSubjectPaper implements Serializable {
 
-	private static final long serialVersionUID = 8097130416465761643L;
-	
-	@Id
+    private static final long serialVersionUID = 8097130416465761643L;
+
+    @Id
     @GeneratedValue
     private Integer id;
 
@@ -27,88 +26,113 @@ public class ExamSubjectPaper implements Serializable {
 
     @Column(name = "code")
     private String code;
-    
-    //题型名称
+
+    // 题型名称
     @Column(name = "question_type_name")
     private String questionTypeName;
-    //题型总个数(包括有效个数和无效个数)
-    @Column(name="total_count")
+
+    // 题型总个数(包括有效个数和无效个数)
+    @Column(name = "total_count")
     private Integer totalCount;
-    //题型有效个数
+
+    // 题型有效个数
     @Column(name = "count")
     private Integer count;
-    //题型总分
+
+    // 题型总分
     @Column(name = "total_score")
     private Double totalScore;
-    //题型间隔分
+
+    // 题型间隔分
     @Column(name = "interval_score")
     private Double intervalScore;
-    //大题号
+
+    // 大题号
     @Column(name = "main_number")
     private Integer mainNumber;
-    //客观(主观)
+
+    // 客观(主观)
     @Column(name = "is_objective")
-    //1:客观;0:主观
+    // 1:客观;0:主观
     private Integer objective;
-	public String getQuestionTypeName() {
-		return questionTypeName;
-	}
-	public void setQuestionTypeName(String questionTypeName) {
-		this.questionTypeName = questionTypeName;
-	}
-	
-	public Integer getTotalCount() {
-		return totalCount;
-	}
-	public void setTotalCount(Integer totalCount) {
-		this.totalCount = totalCount;
-	}
-	public Integer getCount() {
-		return count;
-	}
-	public void setCount(Integer count) {
-		this.count = count;
-	}
-	public Double getTotalScore() {
-		return totalScore;
-	}
-	public void setTotalScore(Double totalScore) {
-		this.totalScore = totalScore;
-	}
-	public Double getIntervalScore() {
-		return intervalScore;
-	}
-	public void setIntervalScore(Double intervalScore) {
-		this.intervalScore = intervalScore;
-	}
-	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 getCode() {
-		return code;
-	}
-	public void setCode(String code) {
-		this.code = code;
-	}
-	public Integer getMainNumber() {
-		return mainNumber;
-	}
-	public void setMainNumber(Integer mainNumber) {
-		this.mainNumber = mainNumber;
-	}
-	public Integer getObjective() {
-		return objective;
-	}
-	public void setObjective(Integer objective) {
-		this.objective = objective;
-	}
+
+    public String getQuestionTypeName() {
+        return questionTypeName;
+    }
+
+    public void setQuestionTypeName(String questionTypeName) {
+        this.questionTypeName = questionTypeName;
+    }
+
+    public Integer getTotalCount() {
+        return totalCount;
+    }
+
+    public void setTotalCount(Integer totalCount) {
+        this.totalCount = totalCount;
+    }
+
+    public Integer getCount() {
+        return count;
+    }
+
+    public void setCount(Integer count) {
+        this.count = count;
+    }
+
+    public Double getTotalScore() {
+        return totalScore;
+    }
+
+    public void setTotalScore(Double totalScore) {
+        this.totalScore = totalScore;
+    }
+
+    public Double getIntervalScore() {
+        return intervalScore;
+    }
+
+    public void setIntervalScore(Double intervalScore) {
+        this.intervalScore = intervalScore;
+    }
+
+    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 getCode() {
+        return code;
+    }
+
+    public void setCode(String code) {
+        this.code = code;
+    }
+
+    public Integer getMainNumber() {
+        return mainNumber;
+    }
+
+    public void setMainNumber(Integer mainNumber) {
+        this.mainNumber = mainNumber;
+    }
+
+    public Integer getObjective() {
+        return objective;
+    }
+
+    public void setObjective(Integer objective) {
+        this.objective = objective;
+    }
 }

+ 55 - 0
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/model/QuestionDetail.java

@@ -0,0 +1,55 @@
+package cn.com.qmth.stmms.biz.exam.model;
+
+import java.util.List;
+
+public class QuestionDetail implements Comparable<QuestionDetail> {
+
+    private int number;
+
+    private String title;
+
+    private int index;
+
+    private List<QuestionUnit> questions;
+
+    public int getNumber() {
+        return number;
+    }
+
+    public void setNumber(int number) {
+        this.number = number;
+    }
+
+    public String getTitle() {
+        return title;
+    }
+
+    public void setTitle(String title) {
+        this.title = title;
+    }
+
+    public int getIndex() {
+        return index;
+    }
+
+    public void setIndex(int index) {
+        this.index = index;
+    }
+
+    public List<QuestionUnit> getQuestions() {
+        return questions;
+    }
+
+    public void setQuestions(List<QuestionUnit> questions) {
+        this.questions = questions;
+    }
+
+    @Override
+    public int compareTo(QuestionDetail o) {
+        if (index > 0 && o.getIndex() > 0) {
+            return index - o.getIndex();
+        } else {
+            return number - o.getNumber();
+        }
+    }
+}

+ 39 - 0
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/model/QuestionUnit.java

@@ -0,0 +1,39 @@
+package cn.com.qmth.stmms.biz.exam.model;
+
+public class QuestionUnit implements Comparable<QuestionUnit> {
+
+    private int number;
+
+    private double score;
+
+    private String answer;
+
+    public int getNumber() {
+        return number;
+    }
+
+    public void setNumber(int number) {
+        this.number = number;
+    }
+
+    public double getScore() {
+        return score;
+    }
+
+    public void setScore(double score) {
+        this.score = score;
+    }
+
+    public String getAnswer() {
+        return answer;
+    }
+
+    public void setAnswer(String answer) {
+        this.answer = answer;
+    }
+
+    @Override
+    public int compareTo(QuestionUnit o) {
+        return number - o.getNumber();
+    }
+}

+ 15 - 0
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/service/ExamStudentPaperService.java

@@ -0,0 +1,15 @@
+package cn.com.qmth.stmms.biz.exam.service;
+
+import java.util.List;
+
+import cn.com.qmth.stmms.biz.exam.model.ExamStudentPaper;
+
+public interface ExamStudentPaperService {
+
+    ExamStudentPaper save(ExamStudentPaper paper);
+
+    int save(List<ExamStudentPaper> paperList);
+
+    ExamStudentPaper find(int examId, String examNumber, boolean objective);
+
+}

+ 14 - 17
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/service/ExamSubjectPaperService.java

@@ -1,8 +1,6 @@
 package cn.com.qmth.stmms.biz.exam.service;
 
-
 import java.util.List;
-import java.util.Map;
 
 import cn.com.qmth.stmms.biz.exam.model.ExamSubjectPaper;
 import cn.com.qmth.stmms.biz.exam.model.ExamSubjectPaperDTO;
@@ -10,20 +8,19 @@ import cn.com.qmth.stmms.biz.exam.service.query.ExamSubjectPaperSearchQuery;
 
 public interface ExamSubjectPaperService {
 
+    ExamSubjectPaperSearchQuery findByQuery(ExamSubjectPaperSearchQuery query);
+
+    ExamSubjectPaper save(ExamSubjectPaper examSubjectPaper);
+
+    void deleteById(Integer id);
+
+    List<ExamSubjectPaperDTO> getExamSubjectPaper(Integer id);
+
+    ExamSubjectPaper getExamSubjectPaperById(Integer id);
+
+    void deleteByExamAndCodeAndObjective(int examId, String subjectCode, int objective);
+
+    Long getExamSubjectPaperCountBy(int examId, String subjectCode, int objective);
 
-	ExamSubjectPaperSearchQuery findByQuery(ExamSubjectPaperSearchQuery query);
-	
-	ExamSubjectPaper save(ExamSubjectPaper examSubjectPaper);
-	
-	void deleteById(Integer id);
-	
-	List<ExamSubjectPaperDTO> getExamSubjectPaper(Integer id);
-	
-	ExamSubjectPaper getExamSubjectPaperById(Integer id);
-	
-	void deleteByExamAndCodeAndObjective(int examId, String subjectCode, int objective);
-	
-	Long getExamSubjectPaperCountBy(int examId, String subjectCode, int objective);
-	
-	String getMainNumbersByExamIdAndCodeAndType(int examId,String subjectCode,boolean objective);
+    String getMainNumbersByExamIdAndCodeAndType(int examId, String subjectCode, boolean objective);
 }

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

@@ -18,7 +18,6 @@ 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.ExamStudent;
 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;
@@ -34,12 +33,14 @@ public class ExamQuestionServiceImpl extends BaseQueryService<ExamQuestion> impl
     public ExamQuestion save(ExamQuestion question) {
         return questionDao.save(question);
     }
+
     @Transactional
     public void batchSave(List<ExamQuestion> list) {
-    	for (ExamQuestion question : list) {
-    		questionDao.save(question);
-    	}
+        for (ExamQuestion question : list) {
+            questionDao.save(question);
+        }
     }
+
     @Transactional
     @Override
     public void deleteByExam(int examId) {
@@ -57,10 +58,12 @@ public class ExamQuestionServiceImpl extends BaseQueryService<ExamQuestion> impl
     public void deleteByExamAndSubjectAndObjective(int examId, String subjectCode, boolean objective) {
         questionDao.deleteByExamIdAndSubjectCodeAndObjective(examId, subjectCode, objective);
     }
+
     @Transactional
     @Override
-    public void deleteByExamIdAndSubjectCodeAndObjectiveAndMainNumber(int examId, String subjectCode, boolean objective,int mainNumber) {
-    	questionDao.deleteByExamIdAndSubjectCodeAndObjectiveAndMainNumber(examId, subjectCode, objective,mainNumber);
+    public void deleteByExamIdAndSubjectCodeAndObjectiveAndMainNumber(int examId, String subjectCode, boolean objective,
+            int mainNumber) {
+        questionDao.deleteByExamIdAndSubjectCodeAndObjectiveAndMainNumber(examId, subjectCode, objective, mainNumber);
     }
 
     @Override
@@ -135,22 +138,27 @@ public class ExamQuestionServiceImpl extends BaseQueryService<ExamQuestion> impl
                     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()]));
+                return predicates.isEmpty() ? cb.conjunction()
+                        : cb.and(predicates.toArray(new Predicate[predicates.size()]));
             }
         };
     }
+
     @Override
     public double scoreByExamIdAndSubjectCode(int examId, String subjectCode) {
-    	return  questionDao.scoreByExamIdAndSubjectCode(examId, subjectCode);
-    	
+        return questionDao.scoreByExamIdAndSubjectCode(examId, subjectCode);
+
     }
+
     @Override
-    public double scoreByExamIdAndSubjectCodeAndObjective(int examId, String subjectCode,boolean objective) {
-    	return questionDao.scoreByExamIdAndSubjectCodeAndObjective(examId, subjectCode,objective);
+    public double scoreByExamIdAndSubjectCodeAndObjective(int examId, String subjectCode, boolean objective) {
+        return questionDao.scoreByExamIdAndSubjectCodeAndObjective(examId, subjectCode, objective);
     }
+
     @Override
-    public double scoreByExamIdAndSubjectCodeAndMainNumberAndObjective(int examId, String subjectCode,int mainNumber,boolean objective) {
-    	return questionDao.scoreByExamIdAndSubjectCodeAndMainNumberAndObjective(examId, subjectCode,mainNumber,objective);
+    public double scoreByExamIdAndSubjectCodeAndMainNumberAndObjective(int examId, String subjectCode, int mainNumber,
+            boolean objective) {
+        return questionDao.scoreByExamIdAndSubjectCodeAndMainNumberAndObjective(examId, subjectCode, mainNumber,
+                objective);
     }
 }

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

@@ -0,0 +1,36 @@
+package cn.com.qmth.stmms.biz.exam.service.impl;
+
+import java.util.List;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import cn.com.qmth.stmms.biz.exam.dao.ExamStudentPaperDao;
+import cn.com.qmth.stmms.biz.exam.model.ExamStudentPaper;
+import cn.com.qmth.stmms.biz.exam.service.ExamStudentPaperService;
+
+@Service
+public class ExamStudentPaperServiceImpl implements ExamStudentPaperService {
+
+    @Autowired
+    private ExamStudentPaperDao examStudentPaperDao;
+
+    @Transactional
+    @Override
+    public ExamStudentPaper save(ExamStudentPaper paper) {
+        return examStudentPaperDao.save(paper);
+    }
+
+    @Transactional
+    @Override
+    public int save(List<ExamStudentPaper> paperList) {
+        examStudentPaperDao.save(paperList);
+        return paperList.size();
+    }
+
+    @Override
+    public ExamStudentPaper find(int examId, String examNumber, boolean objective) {
+        return examStudentPaperDao.findByPkExamIdAndPkExamNumberAndPkObjective(examId, examNumber, objective);
+    }
+}

+ 103 - 99
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/service/impl/ExamSubjectPaperServiceImpl.java

@@ -1,10 +1,9 @@
 package cn.com.qmth.stmms.biz.exam.service.impl;
+
 import java.text.DecimalFormat;
 import java.util.ArrayList;
-import java.util.HashMap;
 import java.util.LinkedList;
 import java.util.List;
-import java.util.Map;
 
 import javax.persistence.criteria.CriteriaBuilder;
 import javax.persistence.criteria.CriteriaQuery;
@@ -32,10 +31,10 @@ public class ExamSubjectPaperServiceImpl extends BaseQueryService<ExamSubjectPap
 
     @Autowired
     private ExamSubjectPaperDao examSubjectPaperDao;
-    
+
     @Autowired
     private ExamQuestionDao examQuestionDao;
-    
+
     @Override
     public ExamSubjectPaperSearchQuery findByQuery(ExamSubjectPaperSearchQuery query) {
         checkQuery(query);
@@ -43,6 +42,7 @@ public class ExamSubjectPaperServiceImpl extends BaseQueryService<ExamSubjectPap
         fillResult(result, query);
         return query;
     }
+
     private Specification<ExamSubjectPaper> buildSpecification(final ExamSubjectPaperSearchQuery query) {
         return new Specification<ExamSubjectPaper>() {
 
@@ -62,105 +62,109 @@ public class ExamSubjectPaperServiceImpl extends BaseQueryService<ExamSubjectPap
             }
         };
     }
-	@Override
-	public ExamSubjectPaper save(ExamSubjectPaper examSubjectPaper) {
-		// TODO Auto-generated method stub
-		return examSubjectPaperDao.save(examSubjectPaper);
-	}
-	@Override
-	public void deleteById(Integer id) {
-		examSubjectPaperDao.delete(id);
-	}
-	@Override
-	public List<ExamSubjectPaperDTO> getExamSubjectPaper(Integer id) {
-		ExamSubjectPaper examSubjectPaper = getExamSubjectPaperById(id);
-		Integer newCount = 0;
-		List<ExamSubjectPaperDTO> list = new ArrayList<ExamSubjectPaperDTO>();
-		if(examSubjectPaper != null){
-			double totalScore = examSubjectPaper.getTotalScore();
-			Integer n = examSubjectPaper.getObjective();
-			Integer m =1;
-			DecimalFormat df   = new DecimalFormat("####.00");
-			//先查询eb_exam_subject 表中是否有对应的试卷详细结构信息
-			List<ExamQuestion> examQuestionList = examQuestionDao.findByExamIdAndSubjectCodeAndObjectiveAndMainNumber(examSubjectPaper.getExamId(), examSubjectPaper.getCode(), (n.equals(1))?true:false, examSubjectPaper.getMainNumber());
-				
-			if(examQuestionList.isEmpty()){//则表示第一次编辑试卷详细结构信息(包括:试卷小标题的分数和标答)
-				if(m.equals(n)){//客观题则补充无效的个数
-					newCount = examSubjectPaper.getTotalCount();
-				}else{//主观题不用补充
-					newCount = examSubjectPaper.getCount();
-				}
-				for(int i = 1; i <= newCount; i++){
-					ExamSubjectPaperDTO examSubjectPaperDTO = new ExamSubjectPaperDTO();
-					examSubjectPaperDTO.setTitle(examSubjectPaper.getQuestionTypeName());
-					examSubjectPaperDTO.setMainNumber(examSubjectPaper.getMainNumber());
-					examSubjectPaperDTO.setSubNumber(i);
-					examSubjectPaperDTO.setObjective(examSubjectPaper.getObjective());
-					examSubjectPaperDTO.setCount(examSubjectPaper.getCount());
-					examSubjectPaperDTO.setIntervalScore(examSubjectPaper.getIntervalScore());
-					examSubjectPaperDTO.setSocre(Double.parseDouble(df.format(totalScore/examSubjectPaper.getCount())));
-					if(i > examSubjectPaper.getCount()){//补充无效个数
-						examSubjectPaperDTO.setAnswer("#");
-						examSubjectPaperDTO.setSocre(0d);
-					}
-					examSubjectPaperDTO.setAnswerClass("answer"+i);
-					examSubjectPaperDTO.setScoreClass("score"+i);
-					list.add(examSubjectPaperDTO);
-				}
-			}else{//表示进来修改
-				for(int i =0 ;i < examQuestionList.size();i++){
-					ExamSubjectPaperDTO examSubjectPaperDTO = new ExamSubjectPaperDTO();
-					ExamQuestion examQuestion = examQuestionList.get(i);
-					examSubjectPaperDTO.setTitle(examQuestion.getMainTitle());
-					examSubjectPaperDTO.setMainNumber(examQuestion.getMainNumber());
-					examSubjectPaperDTO.setCount(examSubjectPaper.getCount());
-					examSubjectPaperDTO.setSubNumber(examQuestion.getSubNumber());
-					examSubjectPaperDTO.setIntervalScore(examQuestion.getIntervalScore());
-					examSubjectPaperDTO.setAnswer(examQuestion.getAnswer());
-					examSubjectPaperDTO.setSocre(examQuestion.getTotalScore());
-					examSubjectPaperDTO.setAnswerClass("answer"+examQuestion.getSubNumber());
-					examSubjectPaperDTO.setScoreClass("score"+examQuestion.getSubNumber());
-					examSubjectPaperDTO.setObjective(examSubjectPaper.getObjective());
-					list.add(examSubjectPaperDTO);
-				}
-			}
-		}
-		return list;
-	}
-	@Override
-	public ExamSubjectPaper getExamSubjectPaperById(Integer id) {
-		return examSubjectPaperDao.findOne(id);
-	}
-	
-	@Override
-	public String getMainNumbersByExamIdAndCodeAndType(int examId,String subjectCode,boolean objective){
-		if(objective){
-			List<String> objectivelist 	= examSubjectPaperDao.getMainNumbersByExamIdAndCodeAndType(examId, subjectCode,1);
-			if(!"[null]".equals(objectivelist.toString())){
-				return objectivelist.get(0).toString();
-			}
-		}else{
-			List<String> subjectivelist = examSubjectPaperDao.getMainNumbersByExamIdAndCodeAndType(examId, subjectCode,0);
-			if(!"[null]".equals(subjectivelist.toString())){
-				return subjectivelist.get(0).toString();
-			}
-		}
-		return "";
-	}
-	
+
+    @Override
+    public ExamSubjectPaper save(ExamSubjectPaper examSubjectPaper) {
+        return examSubjectPaperDao.save(examSubjectPaper);
+    }
+
+    @Override
+    public void deleteById(Integer id) {
+        examSubjectPaperDao.delete(id);
+    }
+
+    @Override
+    public List<ExamSubjectPaperDTO> getExamSubjectPaper(Integer id) {
+        ExamSubjectPaper examSubjectPaper = getExamSubjectPaperById(id);
+        Integer newCount = 0;
+        List<ExamSubjectPaperDTO> list = new ArrayList<ExamSubjectPaperDTO>();
+        if (examSubjectPaper != null) {
+            double totalScore = examSubjectPaper.getTotalScore();
+            Integer n = examSubjectPaper.getObjective();
+            Integer m = 1;
+            DecimalFormat df = new DecimalFormat("####.00");
+            // 先查询eb_exam_subject 表中是否有对应的试卷详细结构信息
+            List<ExamQuestion> examQuestionList = examQuestionDao.findByExamIdAndSubjectCodeAndObjectiveAndMainNumber(
+                    examSubjectPaper.getExamId(), examSubjectPaper.getCode(), (n.equals(1)) ? true : false,
+                    examSubjectPaper.getMainNumber());
+
+            if (examQuestionList.isEmpty()) {// 则表示第一次编辑试卷详细结构信息(包括:试卷小标题的分数和标答)
+                if (m.equals(n)) {// 客观题则补充无效的个数
+                    newCount = examSubjectPaper.getTotalCount();
+                } else {// 主观题不用补充
+                    newCount = examSubjectPaper.getCount();
+                }
+                for (int i = 1; i <= newCount; i++) {
+                    ExamSubjectPaperDTO examSubjectPaperDTO = new ExamSubjectPaperDTO();
+                    examSubjectPaperDTO.setTitle(examSubjectPaper.getQuestionTypeName());
+                    examSubjectPaperDTO.setMainNumber(examSubjectPaper.getMainNumber());
+                    examSubjectPaperDTO.setSubNumber(i);
+                    examSubjectPaperDTO.setObjective(examSubjectPaper.getObjective());
+                    examSubjectPaperDTO.setCount(examSubjectPaper.getCount());
+                    examSubjectPaperDTO.setIntervalScore(examSubjectPaper.getIntervalScore());
+                    examSubjectPaperDTO
+                            .setSocre(Double.parseDouble(df.format(totalScore / examSubjectPaper.getCount())));
+                    if (i > examSubjectPaper.getCount()) {// 补充无效个数
+                        examSubjectPaperDTO.setAnswer("#");
+                        examSubjectPaperDTO.setSocre(0d);
+                    }
+                    examSubjectPaperDTO.setAnswerClass("answer" + i);
+                    examSubjectPaperDTO.setScoreClass("score" + i);
+                    list.add(examSubjectPaperDTO);
+                }
+            } else {// 表示进来修改
+                for (int i = 0; i < examQuestionList.size(); i++) {
+                    ExamSubjectPaperDTO examSubjectPaperDTO = new ExamSubjectPaperDTO();
+                    ExamQuestion examQuestion = examQuestionList.get(i);
+                    examSubjectPaperDTO.setTitle(examQuestion.getMainTitle());
+                    examSubjectPaperDTO.setMainNumber(examQuestion.getMainNumber());
+                    examSubjectPaperDTO.setCount(examSubjectPaper.getCount());
+                    examSubjectPaperDTO.setSubNumber(examQuestion.getSubNumber());
+                    examSubjectPaperDTO.setIntervalScore(examQuestion.getIntervalScore());
+                    examSubjectPaperDTO.setAnswer(examQuestion.getAnswer());
+                    examSubjectPaperDTO.setSocre(examQuestion.getTotalScore());
+                    examSubjectPaperDTO.setAnswerClass("answer" + examQuestion.getSubNumber());
+                    examSubjectPaperDTO.setScoreClass("score" + examQuestion.getSubNumber());
+                    examSubjectPaperDTO.setObjective(examSubjectPaper.getObjective());
+                    list.add(examSubjectPaperDTO);
+                }
+            }
+        }
+        return list;
+    }
+
+    @Override
+    public String getMainNumbersByExamIdAndCodeAndType(int examId, String subjectCode, boolean objective) {
+        if (objective) {
+            List<String> objectivelist = examSubjectPaperDao.getMainNumbersByExamIdAndCodeAndType(examId, subjectCode,
+                    1);
+            if (!"[null]".equals(objectivelist.toString())) {
+                return objectivelist.get(0).toString();
+            }
+        } else {
+            List<String> subjectivelist = examSubjectPaperDao.getMainNumbersByExamIdAndCodeAndType(examId, subjectCode,
+                    0);
+            if (!"[null]".equals(subjectivelist.toString())) {
+                return subjectivelist.get(0).toString();
+            }
+        }
+        return "";
+    }
+
+    @Override
+    public ExamSubjectPaper getExamSubjectPaperById(Integer id) {
+        return examSubjectPaperDao.findOne(id);
+    }
+
     @Transactional
     @Override
     public void deleteByExamAndCodeAndObjective(int examId, String subjectCode, int objective) {
-    	examSubjectPaperDao.deleteByExamAndCodeAndObjective(examId, subjectCode, objective);
+        examSubjectPaperDao.deleteByExamAndCodeAndObjective(examId, subjectCode, objective);
     }
+
     @Override
-    public Long getExamSubjectPaperCountBy(int examId, String subjectCode, int objective){
-    	return examSubjectPaperDao.getExamSubjectPaperCountBy(examId, subjectCode, objective);
+    public Long getExamSubjectPaperCountBy(int examId, String subjectCode, int objective) {
+        return examSubjectPaperDao.getExamSubjectPaperCountBy(examId, subjectCode, objective);
     }
-    public static void main(String[] args) {
-		List<String> list = new ArrayList<String>();
-		list.add("null");
-		
-		System.out.println();
-	}
+
 }

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

@@ -24,8 +24,10 @@ import org.springframework.transaction.annotation.Transactional;
 
 import cn.com.qmth.stmms.biz.exam.model.ExamQuestion;
 import cn.com.qmth.stmms.biz.exam.model.ExamStudent;
+import cn.com.qmth.stmms.biz.exam.model.ExamStudentPaper;
 import cn.com.qmth.stmms.biz.exam.model.Marker;
 import cn.com.qmth.stmms.biz.exam.service.ExamQuestionService;
+import cn.com.qmth.stmms.biz.exam.service.ExamStudentPaperService;
 import cn.com.qmth.stmms.biz.exam.service.ExamStudentService;
 import cn.com.qmth.stmms.biz.exam.service.ExamSubjectService;
 import cn.com.qmth.stmms.biz.mark.query.MarkLibrarySearchQuery;
@@ -55,6 +57,9 @@ public class TaskServiceImpl implements TaskService, ApplicationContextAware, In
     @Autowired
     private ExamStudentService studentService;
 
+    @Autowired
+    private ExamStudentPaperService studentPaperService;
+
     @Autowired
     private ExamSubjectService subjectService;
 
@@ -73,8 +78,7 @@ public class TaskServiceImpl implements TaskService, ApplicationContextAware, In
 
     @Value("${use.redis}")
     private boolean useRedis;
-    
-    
+
     @Override
     public List<Task> findByQuery(MarkLibrarySearchQuery query) {
         List<Task> list = new LinkedList<Task>();
@@ -123,8 +127,17 @@ public class TaskServiceImpl implements TaskService, ApplicationContextAware, In
 
     private List<MarkStepDTO> buildMarkStep(MarkLibrary library) {
         List<MarkStepDTO> list = new LinkedList<MarkStepDTO>();
-        List<ExamQuestion> sList = questionService.findByExamAndSubjectAndObjective(library.getExamId(),
-                library.getSubjectCode(), false);
+        List<ExamQuestion> sList = null;
+        // 首先尝试获取考生专属试题结构
+        ExamStudentPaper paper = studentPaperService.find(library.getExamId(), library.getExamNumber(), false);
+        if (paper != null) {
+            sList = paper.getQuestionList();
+        }
+        // 没有的情况下再去读科目通用试题结构
+        if (sList == null || sList.isEmpty()) {
+            sList = questionService.findByExamAndSubjectAndObjective(library.getExamId(), library.getSubjectCode(),
+                    false);
+        }
         int number = 0;
         for (ExamQuestion question : sList) {
             number++;
@@ -344,17 +357,18 @@ public class TaskServiceImpl implements TaskService, ApplicationContextAware, In
             this.redisTemplate = (StringRedisTemplate) context.getBean("stringRedisTemplate");
         }
     }
+
     /*
      * 客户端非正常情况下退出系统时,对内存中的没有及时清除的任务进行处理
      * 
      */
     @Override
-    public void clearTaskMap(long cleanMapinterval) throws Exception{
-    	if(useRedis){//Redis
-    	    MarkRedisUtil.QuartzClearTask(redisTemplate,cleanMapinterval);
-    	}else{//内存方式
-    		CurrentTaskUtil.QuartzClearMap(cleanMapinterval);
-    	}
+    public void clearTaskMap(long cleanMapinterval) throws Exception {
+        if (useRedis) {// Redis
+            MarkRedisUtil.QuartzClearTask(redisTemplate, cleanMapinterval);
+        } else {// 内存方式
+            CurrentTaskUtil.QuartzClearMap(cleanMapinterval);
+        }
     }
 
     public SpecialTagDTO [] getMarkSpecialTagList(Integer libraryId){

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

@@ -6,8 +6,6 @@ import java.util.List;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
-import net.sf.json.JSONObject;
-
 import org.apache.commons.lang.StringUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Value;
@@ -31,12 +29,14 @@ import cn.com.qmth.stmms.biz.exam.model.Exam;
 import cn.com.qmth.stmms.biz.exam.model.ExamPackage;
 import cn.com.qmth.stmms.biz.exam.model.ExamQuestion;
 import cn.com.qmth.stmms.biz.exam.model.ExamStudent;
+import cn.com.qmth.stmms.biz.exam.model.ExamStudentPaper;
 import cn.com.qmth.stmms.biz.exam.model.ExamSubject;
 import cn.com.qmth.stmms.biz.exam.model.Marker;
 import cn.com.qmth.stmms.biz.exam.query.ExamStudentSearchQuery;
 import cn.com.qmth.stmms.biz.exam.service.ExamPackageService;
 import cn.com.qmth.stmms.biz.exam.service.ExamQuestionService;
 import cn.com.qmth.stmms.biz.exam.service.ExamService;
+import cn.com.qmth.stmms.biz.exam.service.ExamStudentPaperService;
 import cn.com.qmth.stmms.biz.exam.service.ExamStudentService;
 import cn.com.qmth.stmms.biz.exam.service.ExamSubjectService;
 import cn.com.qmth.stmms.biz.exam.service.MarkerService;
@@ -51,6 +51,7 @@ import cn.com.qmth.stmms.common.utils.ExportExcel;
 import cn.com.qmth.stmms.common.utils.ExportExcel2;
 import cn.com.qmth.stmms.common.utils.PictureUrlBuilder;
 import cn.com.qmth.stmms.common.utils.RequestUtils;
+import net.sf.json.JSONObject;
 
 @Controller
 @RequestMapping("/admin/exam/score")
@@ -62,6 +63,9 @@ public class ScoreController extends BaseParameterController {
     @Autowired
     private CampusService campusService;
 
+    @Autowired
+    private ExamStudentPaperService studentPaperService;
+
     @Autowired
     private ExamSubjectService subjectService;
 
@@ -73,10 +77,10 @@ public class ScoreController extends BaseParameterController {
 
     @Autowired
     private ExamPackageService packageService;
-    
+
     @Autowired
     private MarkLibraryService markLibraryService;
-    
+
     @Autowired
     private ScoreRateService scoreRateService;
 
@@ -94,7 +98,7 @@ public class ScoreController extends BaseParameterController {
 
     @Autowired
     private AsyncTaskExecutor taskExecutor;
-    
+
     @Autowired
     private MarkerService markerService;
 
@@ -106,12 +110,12 @@ public class ScoreController extends BaseParameterController {
         if (examId > 0) {
             Exam exam = examService.findById(examId);
             ModelAndView view = new ModelAndView("modules/exam/scoreList");
-            if(subjectCode!=null){
-            	query.setSubjectCode(subjectCode);
+            if (subjectCode != null) {
+                query.setSubjectCode(subjectCode);
             }
             query.setExamId(examId);
-//            query.setUpload(true);
-//            query.setAbsent(false);
+            // query.setUpload(true);
+            // query.setAbsent(false);
             query.orderByExamNumber();
             if (filter == 1) {
                 query.setObjectiveScore(0d);
@@ -120,8 +124,8 @@ public class ScoreController extends BaseParameterController {
                 query.setObjectiveScoreGt(0d);
                 query.setSubjectiveScore(0d);
             }
-            String ids = getStudentIdsByMarkLoginAndMarkName(query.getMarkLogin(),query.getMarkName());
-            if(StringUtils.isNotBlank(ids)){
+            String ids = getStudentIdsByMarkLoginAndMarkName(query.getMarkLogin(), query.getMarkName());
+            if (StringUtils.isNotBlank(ids)) {
                 query.setIds(ids);
             }
             query = studentService.findByQuery(query);
@@ -129,15 +133,16 @@ public class ScoreController extends BaseParameterController {
                 buildSheetUrl(student);
                 buildPackageUrl(student);
                 buildAnswerUrl(student);
-                student.setSubjectRemark(subjectService.find(student.getExamId(), student.getSubjectCode()).getRemark());
+                student.setSubjectRemark(
+                        subjectService.find(student.getExamId(), student.getSubjectCode()).getRemark());
                 student.setMarked(isMarked(student));
                 Marker marker = markerService.findByStudentId(student.getId());
-                if(marker != null){
+                if (marker != null) {
                     student.setMarkLogin(marker.getLoginName());
                     student.setMarkName(marker.getName());
                 }
                 MarkLibrary markLibrary = markLibraryService.findByStudentId(student.getId());
-                if(markLibrary != null){
+                if (markLibrary != null) {
                     student.setTagValue(markLibrary.getTags());
                 }
             }
@@ -148,7 +153,7 @@ public class ScoreController extends BaseParameterController {
             view.addObject("imageServer", imageServer);
             view.addObject("packageServer", packageServer);
             view.addObject("cardServer", cardServer);
-            view.addObject("showExportScore",showExportScore);
+            view.addObject("showExportScore", showExportScore);
             return view;
         } else {
             return new ModelAndView("redirect:/admin/exam/list");
@@ -223,7 +228,7 @@ public class ScoreController extends BaseParameterController {
                 examService.save(exam);
 
                 ScoreCalculateThread thread = new ScoreCalculateThread(exam, examService, studentService,
-                        questionService,subjectService,scoreRateService,markLibraryService);
+                        studentPaperService, questionService, subjectService, scoreRateService, markLibraryService);
                 taskExecutor.submit(thread);
             }
             return new ModelAndView("redirect:/admin/exam/score");
@@ -231,7 +236,7 @@ public class ScoreController extends BaseParameterController {
             return new ModelAndView("redirect:/admin/exam/list");
         }
     }
-    
+
     @RequestMapping("/export")
     public String export(ExamStudentSearchQuery query, HttpServletRequest request, HttpServletResponse response,
             RedirectAttributes redirectAttributes) {
@@ -239,38 +244,39 @@ public class ScoreController extends BaseParameterController {
         String subjectCode = RequestUtils.getSession(request).getParameter("subjectCode");
         if (examId > 0) {
             query.setExamId(examId);
-//            query.setUpload(true);
-//            query.setAbsent(false);
+            // query.setUpload(true);
+            // query.setAbsent(false);
             query.setPageNumber(1);
             query.setPageSize(Integer.MAX_VALUE);
-            String ids = getStudentIdsByMarkLoginAndMarkName(query.getMarkLogin(),query.getMarkName());
-            if(StringUtils.isNotBlank(ids)){
+            String ids = getStudentIdsByMarkLoginAndMarkName(query.getMarkLogin(), query.getMarkName());
+            if (StringUtils.isNotBlank(ids)) {
                 query.setIds(ids);
             }
             query = studentService.findByQuery(query);
             String fileName = "成绩单_" + DateUtils.getDate("yyyyMMdd") + ".xlsx";
             try {
-            	if(subjectCode!=null){
-            		fileName = subjectService.find(examId, subjectCode).getName()+"-机阅考试成绩表";
-            		List<ScoreExportDTO> list = new LinkedList<ScoreExportDTO>();
-            		for (ExamStudent student : query.getResult()) {
-                        if(student.isBreach() || student.isAbsent()){
+                if (subjectCode != null) {
+                    fileName = subjectService.find(examId, subjectCode).getName() + "-机阅考试成绩表";
+                    List<ScoreExportDTO> list = new LinkedList<ScoreExportDTO>();
+                    for (ExamStudent student : query.getResult()) {
+                        if (student.isBreach() || student.isAbsent()) {
                             student.setObjectiveScore(0d);
                             student.setSubjectiveScore(0d);
                         }
                         list.add(new ScoreExportDTO(student));
                     }
-            		new ExportExcel(subjectCode+"-"+subjectService.find(examId, subjectCode).getName(), ScoreExportDTO.class).setDataList(list).write(response, fileName + ".xlsx").dispose();
-            		return null;
-            	}
-            	List<ExamStudentDTO> list = new LinkedList<ExamStudentDTO>();
-            	for (ExamStudent student : query.getResult()) {
-                    if(student.isBreach() || student.isAbsent()){
+                    new ExportExcel(subjectCode + "-" + subjectService.find(examId, subjectCode).getName(),
+                            ScoreExportDTO.class).setDataList(list).write(response, fileName + ".xlsx").dispose();
+                    return null;
+                }
+                List<ExamStudentDTO> list = new LinkedList<ExamStudentDTO>();
+                for (ExamStudent student : query.getResult()) {
+                    if (student.isBreach() || student.isAbsent()) {
                         student.setObjectiveScore(0d);
                         student.setSubjectiveScore(0d);
                     }
-            		list.add(new ExamStudentDTO(student));
-            	}
+                    list.add(new ExamStudentDTO(student));
+                }
                 new ExportExcel("成绩单", ExamStudentDTO.class).setDataList(list).write(response, fileName).dispose();
                 return null;
             } catch (Exception e) {
@@ -285,8 +291,15 @@ public class ScoreController extends BaseParameterController {
     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 = null;
+        ExamStudentPaper oPaper = studentPaperService.find(student.getExamId(), student.getExamNumber(), true);
+        if (oPaper != null) {
+            oList = oPaper.getQuestionList();
+        }
+        if (oList == null || oList.isEmpty()) {
+            oList = questionService.findByExamAndSubjectAndObjective(student.getExamId(), student.getSubjectCode(),
+                    true);
+        }
         List<ScoreItem> list1 = student.getScoreList(true);
         int index = 0;
         for (ExamQuestion question : oList) {
@@ -301,8 +314,15 @@ public class ScoreController extends BaseParameterController {
         }
         scoreList.addAll(list1);
 
-        List<ExamQuestion> sList = questionService.findByExamAndSubjectAndObjective(student.getExamId(),
-                student.getSubjectCode(), false);
+        List<ExamQuestion> sList = null;
+        ExamStudentPaper sPaper = studentPaperService.find(student.getExamId(), student.getExamNumber(), false);
+        if (sPaper != null) {
+            sList = sPaper.getQuestionList();
+        }
+        if (sList == null || sList.isEmpty()) {
+            sList = questionService.findByExamAndSubjectAndObjective(student.getExamId(), student.getSubjectCode(),
+                    false);
+        }
         List<ScoreItem> list2 = student.getScoreList(false);
         index = 0;
         for (ExamQuestion question : sList) {
@@ -342,37 +362,37 @@ public class ScoreController extends BaseParameterController {
             student.setAnswerUrl(subject.getAnswerUrl());
         }
     }
-    
+
     private boolean isMarked(ExamStudent student) {
-		MarkLibrary markLibrary = markLibraryService.findByStudentId(student
-				.getId());
-		if(markLibrary != null){
+        MarkLibrary markLibrary = markLibraryService.findByStudentId(student.getId());
+        if (markLibrary != null) {
             if (StringUtils.isNotEmpty(markLibrary.getMarkerScoreList())
                     && markLibrary.getStatus().equals(LibraryStatus.MARKED)) {
                 return true;
-            }else {
+            } else {
                 return false;
             }
         }
         return false;
     }
+
     @RequestMapping("/exportScore")
     public String exportScore(ExamStudentSearchQuery query, HttpServletRequest request, HttpServletResponse response,
             RedirectAttributes redirectAttributes) {
         int examId = getSessionExamId(request);
         String examName = "[考试批次名称]成绩单";
         if (examId > 0) {
-            Exam exam =examService.findById(examId);
-            if(exam != null){
-                examName = "["+exam.getName()+"]成绩单";
+            Exam exam = examService.findById(examId);
+            if (exam != null) {
+                examName = "[" + exam.getName() + "]成绩单";
             }
-            String ids = getStudentIdsByMarkLoginAndMarkName(query.getMarkLogin(),query.getMarkName());
-            if(StringUtils.isNotBlank(ids)){
+            String ids = getStudentIdsByMarkLoginAndMarkName(query.getMarkLogin(), query.getMarkName());
+            if (StringUtils.isNotBlank(ids)) {
                 query.setIds(ids);
             }
             query.setExamId(examId);
-//            query.setUpload(true);
-//            query.setAbsent(false);
+            // query.setUpload(true);
+            // query.setAbsent(false);
             query.setPageNumber(1);
             query.setPageSize(Integer.MAX_VALUE);
             query = studentService.findByQuery(query);
@@ -380,9 +400,9 @@ public class ScoreController extends BaseParameterController {
             String subTitle = "负责教师签字:_______________ 交回日期:_______________";
             try {
                 List<ExamStudentScoreDTO> list = new LinkedList<ExamStudentScoreDTO>();
-                    int i =1;
+                int i = 1;
                 for (ExamStudent student : query.getResult()) {
-                    if(student.isBreach() || student.isAbsent()){
+                    if (student.isBreach() || student.isAbsent()) {
                         student.setObjectiveScore(0d);
                         student.setSubjectiveScore(0d);
                     }
@@ -390,7 +410,8 @@ public class ScoreController extends BaseParameterController {
                     list.add(new ExamStudentScoreDTO(student));
                     i++;
                 }
-                new ExportExcel2(examName,subTitle, ExamStudentScoreDTO.class).setDataList(list).write(response, fileName);
+                new ExportExcel2(examName, subTitle, ExamStudentScoreDTO.class).setDataList(list).write(response,
+                        fileName);
                 return null;
             } catch (Exception e) {
                 addMessage(redirectAttributes, "导出成绩失败!" + e.getMessage());
@@ -400,25 +421,26 @@ public class ScoreController extends BaseParameterController {
             return "redirect:/admin/exam/list";
         }
     }
-    public String getStudentIdsByMarkLoginAndMarkName(String markLogin,String markName){
+
+    public String getStudentIdsByMarkLoginAndMarkName(String markLogin, String markName) {
         String ids = "";
-        if(StringUtils.isNotBlank(markLogin)){
+        if (StringUtils.isNotBlank(markLogin)) {
             ids += studentService.findIdsByMarkLogin(markLogin);
-            if(ids.equals("")){
+            if (ids.equals("")) {
                 ids = "-1";
             }
         }
-        if(StringUtils.isNotBlank(markName)){
-            String s =  studentService.findIdsByMarkName(markName);
-            if(StringUtils.isBlank(ids)){
-                if(s.equals("")){
+        if (StringUtils.isNotBlank(markName)) {
+            String s = studentService.findIdsByMarkName(markName);
+            if (StringUtils.isBlank(ids)) {
+                if (s.equals("")) {
                     ids = "-1";
-                }else{
+                } else {
                     ids += s;
                 }
-            }else{
-                if(!ids.equals("-1")){
-                    if(StringUtils.isBlank(s)){
+            } else {
+                if (!ids.equals("-1")) {
+                    if (StringUtils.isBlank(s)) {
                         ids = "-1";
                     }
                 }

+ 18 - 3
stmms-web/src/main/java/cn/com/qmth/stmms/admin/exam/parameter/BaseParameterController.java

@@ -12,10 +12,13 @@ import org.springframework.web.servlet.mvc.support.RedirectAttributes;
 import cn.com.qmth.stmms.biz.campus.model.Campus;
 import cn.com.qmth.stmms.biz.campus.service.CampusService;
 import cn.com.qmth.stmms.biz.exam.model.Exam;
+import cn.com.qmth.stmms.biz.exam.model.ExamQuestion;
 import cn.com.qmth.stmms.biz.exam.model.ExamStudent;
+import cn.com.qmth.stmms.biz.exam.model.ExamStudentPaper;
 import cn.com.qmth.stmms.biz.exam.model.ExamSubject;
 import cn.com.qmth.stmms.biz.exam.service.ExamQuestionService;
 import cn.com.qmth.stmms.biz.exam.service.ExamService;
+import cn.com.qmth.stmms.biz.exam.service.ExamStudentPaperService;
 import cn.com.qmth.stmms.biz.exam.service.ExamSubjectService;
 import cn.com.qmth.stmms.biz.mark.model.MarkLibrary;
 import cn.com.qmth.stmms.biz.mark.service.MarkLibraryService;
@@ -42,6 +45,9 @@ public class BaseParameterController extends BaseController {
     @Autowired
     private ExamSubjectService subjectService;
 
+    @Autowired
+    private ExamStudentPaperService studentPaperService;
+
     @Autowired
     private ExamQuestionService questionService;
 
@@ -133,9 +139,18 @@ public class BaseParameterController extends BaseController {
     protected void calculateObjectiveScore(ExamStudent student) {
         ScoreCalculateUtil util = ScoreCalculateUtil.instance(student);
 
-        ScoreInfo info = util.calculate(
-                questionService.findByExamAndSubjectAndObjective(student.getExamId(), student.getSubjectCode(), true),
-                null);
+        List<ExamQuestion> list = null;
+        // 优先取考生专属客观题结构
+        ExamStudentPaper paper = studentPaperService.find(student.getExamId(), student.getExamNumber(), true);
+        if (paper != null) {
+            list = paper.getQuestionList();
+        }
+        // 没有再取科目通用客观题结构
+        if (list == null || list.isEmpty()) {
+            list = questionService.findByExamAndSubjectAndObjective(student.getExamId(), student.getSubjectCode(),
+                    true);
+        }
+        ScoreInfo info = util.calculate(list, null);
 
         student.setObjectiveScore(info.getObjectiveScore());
         student.setScoreList(info.getScoreList(), true);

+ 9 - 8
stmms-web/src/main/java/cn/com/qmth/stmms/admin/exam/parameter/ExamPaperController.java

@@ -44,7 +44,7 @@ public class ExamPaperController extends BaseParameterController {
 
     @Autowired
     private ExamQuestionService questionService;
-    
+
     @Autowired
     private ExamSubjectPaperService examSubjectPaperService;
 
@@ -194,10 +194,11 @@ public class ExamPaperController extends BaseParameterController {
                 if (subject != null) {
                     if (dto.validate(error)) {
                         questionService.deleteByExamAndSubjectAndObjective(examId, dto.getSubjectCode(), objective);
-                        
-                        //删除通过页面操作生产的试卷结构表:eb_exam_subject_paper
-                        examSubjectPaperService.deleteByExamAndCodeAndObjective(examId,dto.getSubjectCode(),objective ? 1 : 0);
-                        
+
+                        // 删除通过页面操作生产的试卷结构表:eb_exam_subject_paper
+                        examSubjectPaperService.deleteByExamAndCodeAndObjective(examId, dto.getSubjectCode(),
+                                objective ? 1 : 0);
+
                         for (ExamQuestion question : dto.getQuestionList()) {
                             questionService.save(question);
                         }
@@ -216,7 +217,7 @@ public class ExamPaperController extends BaseParameterController {
             }
         }
         if (error.size() > 0) {
-        	error.add("<br\\>导入完毕后请重新统分!");
+            error.add("<br\\>导入完毕后请重新统分!");
             addMessage(redirectAttributes, StringUtils.join(error, "<br\\>"));
         }
         return "redirect:/admin/exam-param/paper";
@@ -227,8 +228,8 @@ public class ExamPaperController extends BaseParameterController {
         Map<String, SubjectQuestionDTO> map = new HashMap<String, SubjectQuestionDTO>();
         try {
             ImportExcel excel = new ImportExcel(file, 1, 0);
-            List<? extends QuestionDTO> list = excel.getDataList(objective ? ObjectiveQuestionDTO.class
-                    : SubjectiveQuestionDTO.class);
+            List<? extends QuestionDTO> list = excel
+                    .getDataList(objective ? ObjectiveQuestionDTO.class : SubjectiveQuestionDTO.class);
             if (list != null) {
                 for (QuestionDTO dto : list) {
                     if (dto.validate()) {

+ 159 - 150
stmms-web/src/main/java/cn/com/qmth/stmms/admin/exam/parameter/ExamSubjectPaperController.java

@@ -1,14 +1,11 @@
 package cn.com.qmth.stmms.admin.exam.parameter;
 
-import java.text.DecimalFormat;
 import java.util.ArrayList;
 import java.util.LinkedList;
 import java.util.List;
-import java.util.Map;
 
 import javax.servlet.http.HttpServletRequest;
 
-import org.apache.commons.lang.StringUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.stereotype.Controller;
@@ -17,7 +14,6 @@ import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RequestMethod;
 import org.springframework.web.bind.annotation.RequestParam;
 import org.springframework.web.bind.annotation.ResponseBody;
-import org.springframework.web.servlet.mvc.support.RedirectAttributes;
 
 import cn.com.qmth.stmms.biz.exam.model.ExamQuestion;
 import cn.com.qmth.stmms.biz.exam.model.ExamSubject;
@@ -40,7 +36,7 @@ public class ExamSubjectPaperController extends BaseParameterController {
 
     @Autowired
     private ExamQuestionService questionService;
-    
+
     @Autowired
     private ExamSubjectPaperService examSubjectPaperService;
 
@@ -90,7 +86,7 @@ public class ExamSubjectPaperController extends BaseParameterController {
                 model.addAttribute("questionList", list);
                 model.addAttribute("subject", subject);
                 model.addAttribute("objective", objective);
-                model.addAttribute("subjectPaper","1");
+                model.addAttribute("subjectPaper", "1");
                 return "modules/exam/param/paperDetail";
             } else {
                 return "redirect:/admin/exam-param/subjectPaper";
@@ -99,164 +95,177 @@ public class ExamSubjectPaperController extends BaseParameterController {
             return "redirect:/admin/exam/list";
         }
     }
-    //试卷题型
+
+    // 试卷题型
     @RequestMapping(value = "/examQuestionTypeEdit")
-    public String examQuestionTypeEdit(Model model, HttpServletRequest request,ExamSubjectPaperSearchQuery query, @RequestParam(required = false) String subjectCode) {
-    	int examId = getSessionExamId(request);
-    	if(examId>0){
-    		ExamSubject subject = subjectService.find(examId, subjectCode);
-        	//通过考试ID获取该考试批次下所有的科目名称及科目代码
-        	model.addAttribute("subjectCode",subjectCode);
-        	model.addAttribute("subjectName",subject.getName());
-        	query.setExamId(examId);
-        	query.setCode(subjectCode);
-        	query = examSubjectPaperService.findByQuery(query);
-        	String objectiveNumber = examSubjectPaperService.getMainNumbersByExamIdAndCodeAndType(examId, subjectCode,true);
-        	String subjectiveNumber = examSubjectPaperService.getMainNumbersByExamIdAndCodeAndType(examId, subjectCode,false);
-        	model.addAttribute("query", query);
-        	model.addAttribute("objectiveNumber",objectiveNumber);
-        	model.addAttribute("subjectiveNumber",subjectiveNumber);
-    	}
+    public String examQuestionTypeEdit(Model model, HttpServletRequest request, ExamSubjectPaperSearchQuery query,
+            @RequestParam(required = false) String subjectCode) {
+        int examId = getSessionExamId(request);
+        if (examId > 0) {
+            ExamSubject subject = subjectService.find(examId, subjectCode);
+            // 通过考试ID获取该考试批次下所有的科目名称及科目代码
+            model.addAttribute("subjectCode", subjectCode);
+            model.addAttribute("subjectName", subject.getName());
+            query.setExamId(examId);
+            query.setCode(subjectCode);
+            query = examSubjectPaperService.findByQuery(query);
+            String objectiveNumber = examSubjectPaperService.getMainNumbersByExamIdAndCodeAndType(examId, subjectCode,
+                    true);
+            String subjectiveNumber = examSubjectPaperService.getMainNumbersByExamIdAndCodeAndType(examId, subjectCode,
+                    false);
+            model.addAttribute("query", query);
+            model.addAttribute("objectiveNumber", objectiveNumber);
+            model.addAttribute("subjectiveNumber", subjectiveNumber);
+        }
         return "modules/exam/param/subjectPaperForm";
     }
-    //新增 或 修改
-    @RequestMapping(value = "/save",method = RequestMethod.POST)
-    public String saveSubjectPaper(ExamSubjectPaper examPaper, HttpServletRequest request){
-    	int examId = getSessionExamId(request);
-    	if(examId>0){
-    		examPaper.setExamId(examId);
-    		
-    		//后商定根据页面保存的情况,需要去eb_exam_question表中将起对应的数据删除。
-    		boolean objective = examPaper.getObjective() == 1?true:false;
-    		Long count = examSubjectPaperService.getExamSubjectPaperCountBy(examId, examPaper.getCode(), examPaper.getObjective());
-    		if(count == 0){
-    			//当通过页面维护一个科目的客观题或主观题时,第一次进来需要删除eb_exam_question表中对应的数据
-    			questionService.deleteByExamAndSubjectAndObjective(examId, examPaper.getCode(), objective);
-    		}
-    		if(examPaper.getId() != null){//表示修改情况,将eb_exam_question表中对应的数据删除
-    			questionService.deleteByExamIdAndSubjectCodeAndObjectiveAndMainNumber(examPaper.getExamId(), examPaper.getCode(), objective,examPaper.getMainNumber());
-    		}
-    		ExamSubjectPaper examSubjectPaper = examSubjectPaperService.save(examPaper);
-    		return "redirect:/admin/exam-param/subjectPaper/examQuestionTypeEdit?subjectCode="+examPaper.getCode();
-    	}
-    	return null;
+
+    // 新增 或 修改
+    @RequestMapping(value = "/save", method = RequestMethod.POST)
+    public String saveSubjectPaper(ExamSubjectPaper examPaper, HttpServletRequest request) {
+        int examId = getSessionExamId(request);
+        if (examId > 0) {
+            examPaper.setExamId(examId);
+
+            // 后商定根据页面保存的情况,需要去eb_exam_question表中将起对应的数据删除。
+            boolean objective = examPaper.getObjective() == 1 ? true : false;
+            Long count = examSubjectPaperService.getExamSubjectPaperCountBy(examId, examPaper.getCode(),
+                    examPaper.getObjective());
+            if (count == 0) {
+                // 当通过页面维护一个科目的客观题或主观题时,第一次进来需要删除eb_exam_question表中对应的数据
+                questionService.deleteByExamAndSubjectAndObjective(examId, examPaper.getCode(), objective);
+            }
+            if (examPaper.getId() != null) {// 表示修改情况,将eb_exam_question表中对应的数据删除
+                questionService.deleteByExamIdAndSubjectCodeAndObjectiveAndMainNumber(examPaper.getExamId(),
+                        examPaper.getCode(), objective, examPaper.getMainNumber());
+            }
+            examSubjectPaperService.save(examPaper);
+            return "redirect:/admin/exam-param/subjectPaper/examQuestionTypeEdit?subjectCode=" + examPaper.getCode();
+        }
+        return null;
     }
-    //删除
+
+    // 删除
     @RequestMapping(value = "/delete", method = RequestMethod.POST)
     @ResponseBody
-    public JSONObject deleteMarker(@RequestParam Integer id,@RequestParam boolean objective) {
-    	JSONObject obj = new JSONObject();
-    	//将question表中的数据也一并删除
-    	ExamSubjectPaper examSubjectPaper = examSubjectPaperService.getExamSubjectPaperById(id);
-    	if(examSubjectPaper != null){
-    		
-    		double score = questionService.scoreByExamIdAndSubjectCodeAndMainNumberAndObjective(examSubjectPaper.getExamId(), examSubjectPaper.getCode(), examSubjectPaper.getMainNumber(), objective);
-    		
-    		questionService.deleteByExamIdAndSubjectCodeAndObjectiveAndMainNumber(examSubjectPaper.getExamId(), examSubjectPaper.getCode(), objective,examSubjectPaper.getMainNumber());
-    		//并更新subject表中的分数
-    		ExamSubject subject = subjectService.find(examSubjectPaper.getExamId(), examSubjectPaper.getCode());
-//    		double score = examSubjectPaper.getTotalScore();
-    		subject.setTotalScore(subject.getTotalScore()-score);
-    		if(objective){
-    			subject.setObjectiveScore(subject.getObjectiveScore()-score);
-    		}else{
-    			subject.setSubjectiveScore(subject.getSubjectiveScore()-score);
-    		}
-    		subjectService.save(subject);
-    		examSubjectPaperService.deleteById(id);
-    		obj.accumulate("success", true);
-    	}else{
-    		obj.accumulate("success", false);
-    		obj.accumulate("msg", "删除失败!");
-    	}
+    public JSONObject deleteMarker(@RequestParam Integer id, @RequestParam boolean objective) {
+        JSONObject obj = new JSONObject();
+        // 将question表中的数据也一并删除
+        ExamSubjectPaper examSubjectPaper = examSubjectPaperService.getExamSubjectPaperById(id);
+        if (examSubjectPaper != null) {
+
+            double score = questionService.scoreByExamIdAndSubjectCodeAndMainNumberAndObjective(
+                    examSubjectPaper.getExamId(), examSubjectPaper.getCode(), examSubjectPaper.getMainNumber(),
+                    objective);
+
+            questionService.deleteByExamIdAndSubjectCodeAndObjectiveAndMainNumber(examSubjectPaper.getExamId(),
+                    examSubjectPaper.getCode(), objective, examSubjectPaper.getMainNumber());
+            // 并更新subject表中的分数
+            ExamSubject subject = subjectService.find(examSubjectPaper.getExamId(), examSubjectPaper.getCode());
+            // double score = examSubjectPaper.getTotalScore();
+            subject.setTotalScore(subject.getTotalScore() - score);
+            if (objective) {
+                subject.setObjectiveScore(subject.getObjectiveScore() - score);
+            } else {
+                subject.setSubjectiveScore(subject.getSubjectiveScore() - score);
+            }
+            subjectService.save(subject);
+            examSubjectPaperService.deleteById(id);
+            obj.accumulate("success", true);
+        } else {
+            obj.accumulate("success", false);
+            obj.accumulate("msg", "删除失败!");
+        }
         return obj;
     }
-    //详细编辑 每个科目下的试卷结构(标准答案和分数)
+
+    // 详细编辑 每个科目下的试卷结构(标准答案和分数)
     @RequestMapping(value = "/editPaperDetail")
-    public String editPaperDetail(Model model,HttpServletRequest request, @RequestParam Integer id,@RequestParam String subjectCode,@RequestParam String objective) {
-    	int examId = getSessionExamId(request);
-    	if(examId > 0){
-    		ExamSubject subject = subjectService.find(examId, subjectCode);
-    		List<ExamSubjectPaperDTO> ExamSubjectPaperDTOList = examSubjectPaperService.getExamSubjectPaper(id);
-    		model.addAttribute("ExamSubjectPaperDTOList", ExamSubjectPaperDTOList);
-    		model.addAttribute("subjectCode", subjectCode);
-    		model.addAttribute("subjectName", subject.getName());
-    		model.addAttribute("examSubjectPaperId", id);
-    		model.addAttribute("objective", objective);
-    		return "modules/exam/param/editSubjectPaperDetail";
-    	}else{
-    		return "redirect:/admin/exam/list";
-    	}
+    public String editPaperDetail(Model model, HttpServletRequest request, @RequestParam Integer id,
+            @RequestParam String subjectCode, @RequestParam String objective) {
+        int examId = getSessionExamId(request);
+        if (examId > 0) {
+            ExamSubject subject = subjectService.find(examId, subjectCode);
+            List<ExamSubjectPaperDTO> ExamSubjectPaperDTOList = examSubjectPaperService.getExamSubjectPaper(id);
+            model.addAttribute("ExamSubjectPaperDTOList", ExamSubjectPaperDTOList);
+            model.addAttribute("subjectCode", subjectCode);
+            model.addAttribute("subjectName", subject.getName());
+            model.addAttribute("examSubjectPaperId", id);
+            model.addAttribute("objective", objective);
+            return "modules/exam/param/editSubjectPaperDetail";
+        } else {
+            return "redirect:/admin/exam/list";
+        }
     }
-    
-    //保存 详细 题型中的分数和查考答案等信息
-    @RequestMapping(value = "/detailSave",method = RequestMethod.POST)
+
+    // 保存 详细 题型中的分数和查考答案等信息
+    @RequestMapping(value = "/detailSave", method = RequestMethod.POST)
     @ResponseBody
-    public JSONObject detailSave(HttpServletRequest request){
-    	JSONObject obj = new JSONObject();
-    	String jsonString = request.getParameter("jsonString");
-    	JSONObject jsonObject = JSONObject.fromObject(jsonString);
-    	String subjectCode = (String)jsonObject.get("subjectCode");
-    	int examSubjectPaperId = Integer.parseInt(jsonObject.get("examSubjectPaperId").toString());
-    	String tempObjective = (String)jsonObject.get("objective");
-    	boolean objective = "1".equals(tempObjective)?true:false;//true 表示 客观题 false 表示 主观题
-    	int examId = getSessionExamId(request);
-    	ExamSubjectPaper examSubjectPaper = examSubjectPaperService.getExamSubjectPaperById(examSubjectPaperId);
-    	if(examSubjectPaper != null){
-    		ExamSubject subject = subjectService.find(examId, subjectCode);
-    		if (subject != null) {
-    		//此次编辑的题型所有的分数
-    		double questionTypeScroe = 0;
-    		List<ExamQuestion> list = new ArrayList<ExamQuestion>();
-	    	JSONArray jsonArray =jsonObject.getJSONArray("data");
-		    	for (int i = 0; i < jsonArray.size(); i++) {
-		    		ExamQuestion examQuestion = new ExamQuestion();
-		    		JSONObject jo = jsonArray.getJSONObject(i);
-		    		 int subNumber = Integer.parseInt(jo.getString("subNumber"));
-		    		 String answer = jo.getString("answer");
-		    		 double score = Double.parseDouble(jo.getString("score"));
-		    		 examQuestion.setExamId(examId);
-		    		 examQuestion.setSubjectCode(subjectCode);
-		    		 examQuestion.setMainNumber(examSubjectPaper.getMainNumber());
-		    		 examQuestion.setSubNumber(subNumber);
-		    		 examQuestion.setObjective(objective);
-		    		 examQuestion.setMainTitle(examSubjectPaper.getQuestionTypeName());
-		    		 examQuestion.setAnswer(answer);
-		    		 examQuestion.setTotalScore(score);
-		    		 examQuestion.setIntervalScore(examSubjectPaper.getIntervalScore());
-		    		 examQuestion.setFullCount(0);
-		    		 examQuestion.setTotalCount(0);
-		    		 examQuestion.setZeroCount(0);
-		    		 questionTypeScroe = questionTypeScroe + score;
-		    		 list.add(examQuestion);
-		    	}
-		    	if(questionTypeScroe != examSubjectPaper.getTotalScore()){
-		    		obj.accumulate("success", false);
-		    		obj.accumulate("msg", "各项分数总和("+examSubjectPaper.getTotalScore()+")不等于单项题型设置的总分");
-		    		return obj;
-		    	}
-		    	//删除question表中关于本次大题号的所有信息
-		    	questionService.deleteByExamIdAndSubjectCodeAndObjectiveAndMainNumber(examId, subjectCode, objective,examSubjectPaper.getMainNumber());
-		    	//获取在question表中除去本次编辑的大题号以外的分数
-		    	double oldScore = questionService.scoreByExamIdAndSubjectCode(examId, subjectCode);
-		    	//批量保存question表中本次大题号的所有信息
-		    	questionService.batchSave(list);
-		    	//获取(主观题或客观题)题型下所有的分数
-		    	double objectiveScore = questionService.scoreByExamIdAndSubjectCodeAndObjective(examId, subjectCode, objective);
-                //总分 =  本次分数 + 非本次分数
-                subject.setTotalScore(oldScore+questionTypeScroe);
+    public JSONObject detailSave(HttpServletRequest request) {
+        JSONObject obj = new JSONObject();
+        String jsonString = request.getParameter("jsonString");
+        JSONObject jsonObject = JSONObject.fromObject(jsonString);
+        String subjectCode = (String) jsonObject.get("subjectCode");
+        int examSubjectPaperId = Integer.parseInt(jsonObject.get("examSubjectPaperId").toString());
+        String tempObjective = (String) jsonObject.get("objective");
+        boolean objective = "1".equals(tempObjective) ? true : false;// true 表示
+                                                                     // 客观题
+                                                                     // false 表示
+                                                                     // 主观题
+        int examId = getSessionExamId(request);
+        ExamSubjectPaper examSubjectPaper = examSubjectPaperService.getExamSubjectPaperById(examSubjectPaperId);
+        if (examSubjectPaper != null) {
+            ExamSubject subject = subjectService.find(examId, subjectCode);
+            if (subject != null) {
+                // 此次编辑的题型所有的分数
+                double questionTypeScroe = 0;
+                List<ExamQuestion> list = new ArrayList<ExamQuestion>();
+                JSONArray jsonArray = jsonObject.getJSONArray("data");
+                for (int i = 0; i < jsonArray.size(); i++) {
+                    ExamQuestion examQuestion = new ExamQuestion();
+                    JSONObject jo = jsonArray.getJSONObject(i);
+                    int subNumber = Integer.parseInt(jo.getString("subNumber"));
+                    String answer = jo.getString("answer");
+                    double score = Double.parseDouble(jo.getString("score"));
+                    examQuestion.setExamId(examId);
+                    examQuestion.setSubjectCode(subjectCode);
+                    examQuestion.setMainNumber(examSubjectPaper.getMainNumber());
+                    examQuestion.setSubNumber(subNumber);
+                    examQuestion.setObjective(objective);
+                    examQuestion.setMainTitle(examSubjectPaper.getQuestionTypeName());
+                    examQuestion.setAnswer(answer);
+                    examQuestion.setTotalScore(score);
+                    examQuestion.setIntervalScore(examSubjectPaper.getIntervalScore());
+                    examQuestion.setFullCount(0);
+                    examQuestion.setTotalCount(0);
+                    examQuestion.setZeroCount(0);
+                    questionTypeScroe = questionTypeScroe + score;
+                    list.add(examQuestion);
+                }
+                if (questionTypeScroe != examSubjectPaper.getTotalScore()) {
+                    obj.accumulate("success", false);
+                    obj.accumulate("msg", "各项分数总和(" + examSubjectPaper.getTotalScore() + ")不等于单项题型设置的总分");
+                    return obj;
+                }
+                // 删除question表中关于本次大题号的所有信息
+                questionService.deleteByExamIdAndSubjectCodeAndObjectiveAndMainNumber(examId, subjectCode, objective,
+                        examSubjectPaper.getMainNumber());
+                // 获取在question表中除去本次编辑的大题号以外的分数
+                double oldScore = questionService.scoreByExamIdAndSubjectCode(examId, subjectCode);
+                // 批量保存question表中本次大题号的所有信息
+                questionService.batchSave(list);
+                // 获取(主观题或客观题)题型下所有的分数
+                double objectiveScore = questionService.scoreByExamIdAndSubjectCodeAndObjective(examId, subjectCode,
+                        objective);
+                // 总分 = 本次分数 + 非本次分数
+                subject.setTotalScore(oldScore + questionTypeScroe);
                 subject.setScore(objectiveScore, objective);
                 subjectService.save(subject);
                 obj.accumulate("success", true);
                 obj.accumulate("msg", "保存成功!");
-    		}
-    	}
-    	return obj;
+            }
+        }
+        return obj;
     }
-    public static void main(String[] args) {
-    	boolean objective = true;
-		String b = "bb";
-		String d = "cc";
-		String c = objective?b:d;
-	}
+
 }

+ 9 - 9
stmms-web/src/main/java/cn/com/qmth/stmms/admin/quartz/ScheduleRunner.java

@@ -1,6 +1,5 @@
 package cn.com.qmth.stmms.admin.quartz;
 
-import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.scheduling.annotation.Scheduled;
 import org.springframework.stereotype.Component;
@@ -10,16 +9,17 @@ import cn.com.qmth.stmms.biz.mark.service.Impl.TaskServiceImpl;
 
 @Component
 public class ScheduleRunner {
-    
+
     @Value("${jvm.cleanMapinterval}")
     private long cleanMapinterval;
-	@Scheduled(cron = "${jvm.cleanMapTimer}")
+
+    @Scheduled(cron = "${jvm.cleanMapTimer}")
     public void schClearTaskMap() {
-	    TaskService taskServiceImpl = new TaskServiceImpl();
-		try {
-			taskServiceImpl.clearTaskMap(cleanMapinterval);
-		} catch (Exception e) {
-			e.printStackTrace();
-		}
+        TaskService taskServiceImpl = new TaskServiceImpl();
+        try {
+            taskServiceImpl.clearTaskMap(cleanMapinterval);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
     }
 }

+ 22 - 3
stmms-web/src/main/java/cn/com/qmth/stmms/admin/thread/ScoreCalculateThread.java

@@ -15,10 +15,12 @@ import org.slf4j.LoggerFactory;
 import cn.com.qmth.stmms.biz.exam.model.Exam;
 import cn.com.qmth.stmms.biz.exam.model.ExamQuestion;
 import cn.com.qmth.stmms.biz.exam.model.ExamStudent;
+import cn.com.qmth.stmms.biz.exam.model.ExamStudentPaper;
 import cn.com.qmth.stmms.biz.exam.model.ExamSubject;
 import cn.com.qmth.stmms.biz.exam.model.ScoreRate;
 import cn.com.qmth.stmms.biz.exam.service.ExamQuestionService;
 import cn.com.qmth.stmms.biz.exam.service.ExamService;
+import cn.com.qmth.stmms.biz.exam.service.ExamStudentPaperService;
 import cn.com.qmth.stmms.biz.exam.service.ExamStudentService;
 import cn.com.qmth.stmms.biz.exam.service.ExamSubjectService;
 import cn.com.qmth.stmms.biz.exam.service.ScoreRateService;
@@ -36,6 +38,8 @@ public class ScoreCalculateThread implements Runnable {
 
     private ExamStudentService studentService;
 
+    private ExamStudentPaperService studentPaperService;
+
     private ExamService examService;
 
     private ExamQuestionService questionService;
@@ -57,11 +61,12 @@ public class ScoreCalculateThread implements Runnable {
     private Map<String, Double> scoreRateMap;
 
     public ScoreCalculateThread(Exam exam, ExamService examService, ExamStudentService studentService,
-            ExamQuestionService questionService, ExamSubjectService subjectService, ScoreRateService scoreRateService,
-            MarkLibraryService libraryService) {
+            ExamStudentPaperService studentPaperService, ExamQuestionService questionService,
+            ExamSubjectService subjectService, ScoreRateService scoreRateService, MarkLibraryService libraryService) {
         this.exam = exam;
         this.examService = examService;
         this.studentService = studentService;
+        this.studentPaperService = studentPaperService;
         this.questionService = questionService;
         this.subjectService = subjectService;
         this.scoreRateService = scoreRateService;
@@ -145,7 +150,7 @@ public class ScoreCalculateThread implements Runnable {
 
     private void calculate(ExamStudent student) {
         ScoreCalculateUtil util = ScoreCalculateUtil.instance(student);
-        ScoreInfo info = util.calculate(findQuestionList(student.getSubjectCode(), true), null);
+        ScoreInfo info = util.calculate(findQuestionList(student, true), null);
 
         student.setObjectiveScore(info.getObjectiveScore());
         student.setScoreList(info.getScoreList(), true);
@@ -202,6 +207,20 @@ public class ScoreCalculateThread implements Runnable {
         return StringUtils.join(list, "-");
     }
 
+    private List<ExamQuestion> findQuestionList(ExamStudent student, boolean objective) {
+        List<ExamQuestion> list = null;
+        // 优先取考生专属试题结构
+        ExamStudentPaper paper = studentPaperService.find(student.getExamId(), student.getExamNumber(), objective);
+        if (paper != null) {
+            list = paper.getQuestionList();
+        }
+        // 没有再取科目通用客观题结构
+        if (list == null || list.isEmpty()) {
+            list = findQuestionList(student.getSubjectCode(), objective);
+        }
+        return list;
+    }
+
     private List<ExamQuestion> findQuestionList(String subjectCode, boolean objective) {
         if (objective) {
             List<ExamQuestion> list = objectiveMap.get(subjectCode);

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

@@ -27,10 +27,14 @@ import cn.com.qmth.stmms.biz.campus.service.CampusService;
 import cn.com.qmth.stmms.biz.exam.model.Exam;
 import cn.com.qmth.stmms.biz.exam.model.ExamPackage;
 import cn.com.qmth.stmms.biz.exam.model.ExamStudent;
+import cn.com.qmth.stmms.biz.exam.model.ExamStudentPaper;
 import cn.com.qmth.stmms.biz.exam.model.ExamSubject;
+import cn.com.qmth.stmms.biz.exam.model.QuestionDetail;
+import cn.com.qmth.stmms.biz.exam.model.QuestionUnit;
 import cn.com.qmth.stmms.biz.exam.query.ExamStudentSearchQuery;
 import cn.com.qmth.stmms.biz.exam.service.ExamPackageService;
 import cn.com.qmth.stmms.biz.exam.service.ExamService;
+import cn.com.qmth.stmms.biz.exam.service.ExamStudentPaperService;
 import cn.com.qmth.stmms.biz.exam.service.ExamStudentService;
 import cn.com.qmth.stmms.biz.exam.service.ExamSubjectService;
 import cn.com.qmth.stmms.biz.mark.model.MarkLibrary;
@@ -65,6 +69,9 @@ public class ExamStudentController {
     @Autowired
     private MarkLibraryService markLibraryService;
 
+    @Autowired
+    private ExamStudentPaperService studentPaperService;
+
     @AuthValidate("adminUser")
     @RequestMapping(value = "/package/{examId}", method = RequestMethod.GET)
     @ResponseBody
@@ -537,4 +544,77 @@ public class ExamStudentController {
             }
         }
     }
+
+    /**
+     * 上传考生个人试卷结构接口
+     * 
+     * @param request
+     * @param examId
+     * @param examNumber
+     * @param objective
+     * @param struct
+     * @return
+     */
+    @AuthValidate("adminUser")
+    @RequestMapping(value = "/student/struct", method = RequestMethod.POST)
+    @ResponseBody
+    private boolean uploadStruct(HttpServletRequest request, @RequestParam Integer examId,
+            @RequestParam String examNumber, @RequestParam Boolean objective, @RequestParam String struct) {
+        // 验证考试与管理员账号
+        User user = RequestUtils.getApiUser(request);
+        Exam exam = examService.findById(examId);
+        if (exam == null || !exam.getSchoolId().equals(user.getSchoolId())) {
+            throw new ExamNotAccessibleException();
+        }
+        // 验证考生是否存在
+        ExamStudent student = examStudentService.findByExamIdAndExamNumber(examId, examNumber);
+        if (student == null) {
+            return false;
+        }
+        // 尝试解析试卷结构
+        struct = StringUtils.trimToEmpty(struct);
+        List<QuestionDetail> list = ExamStudentPaper.parseFromJson(struct);
+        if (list == null || list.isEmpty()) {
+            return false;
+        }
+        // 保存个人试卷结构
+        ExamStudentPaper paper = studentPaperService.find(examId, examNumber, objective);
+        if (paper == null) {
+            paper = new ExamStudentPaper();
+            paper.setExamId(examId);
+            paper.setExamNumber(examNumber);
+            paper.setObjective(objective);
+        }
+        paper.setStruct(struct);
+        studentPaperService.save(paper);
+        // 同步科目总分信息
+        ExamSubject subject = examSubjectService.find(examId, student.getSubjectCode());
+        if (objective.booleanValue() && subject.getObjectiveScore() == null) {
+            subject.setObjectiveScore(sumTotalScore(list));
+            examSubjectService.save(subject);
+        } else if (!objective.booleanValue() && subject.getSubjectiveScore() == null) {
+            subject.setSubjectiveScore(sumTotalScore(list));
+            examSubjectService.save(subject);
+        }
+        return true;
+    }
+
+    /**
+     * 计算个人试卷结构中的总分
+     * 
+     * @param list
+     * @return
+     */
+    private double sumTotalScore(List<QuestionDetail> list) {
+        double score = 0d;
+        for (QuestionDetail detail : list) {
+            if (detail.getQuestions() == null) {
+                continue;
+            }
+            for (QuestionUnit unit : detail.getQuestions()) {
+                score += unit.getScore();
+            }
+        }
+        return score;
+    }
 }