1
0
Pārlūkot izejas kodu

全卷复核导出

xiatian 1 gadu atpakaļ
vecāks
revīzija
9dd4b35924

+ 884 - 0
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/bean/ExamStudentVo.java

@@ -0,0 +1,884 @@
+package cn.com.qmth.stmms.biz.exam.bean;
+
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+import javax.persistence.EnumType;
+import javax.persistence.Enumerated;
+import javax.persistence.Temporal;
+import javax.persistence.TemporalType;
+
+import org.apache.commons.lang.StringUtils;
+import org.springframework.beans.BeanUtils;
+
+import cn.com.qmth.stmms.biz.exam.model.ExamQuestion;
+import cn.com.qmth.stmms.biz.exam.model.ExamStudent;
+import cn.com.qmth.stmms.biz.exam.model.ExamSubject;
+import cn.com.qmth.stmms.biz.exam.model.InspectHistory;
+import cn.com.qmth.stmms.biz.mark.model.ProblemType;
+import cn.com.qmth.stmms.biz.utils.ScoreItem;
+import cn.com.qmth.stmms.common.annotation.ExcelField;
+import cn.com.qmth.stmms.common.enums.SubjectiveStatus;
+import cn.com.qmth.stmms.common.utils.BigDecimalUtils;
+
+public class ExamStudentVo {
+
+    public static final String ANSWER_SPLIT = ",";
+
+    public static final String SPLIT = ";";
+
+
+    private Integer id;
+
+    /**
+     * 考试ID
+     */
+    private Integer examId;
+
+    /**
+     * 学校ID
+     */
+    private Integer schoolId;
+
+    /**
+     * 学习中心
+     */
+    private String campusName;
+
+    /**
+     * 科目代码
+     */
+    @ExcelField(title = "科目代码*", align = 2, sort = 1)
+    private String subjectCode;
+
+    /**
+     * 科目名称
+     */
+    @ExcelField(title = "科目名称*", align = 2, sort = 2)
+    private String subjectName;
+
+    /**
+     * 试卷类型
+     */
+    private String paperType;
+
+    /**
+     * 准考证号
+     */
+    private String examNumber;
+
+    /**
+     * 学号
+     */
+    private String studentCode;
+
+    /**
+     * 密号
+     */
+    @ExcelField(title = "密号*", align = 2, sort = 3)
+    private String secretNumber;
+
+    /**
+     * 姓名
+     */
+    private String name;
+
+    /**
+     * 试卷袋签到表编号
+     */
+    private String packageCode;
+
+    /**
+     * 考生考点信息
+     */
+    private String examSite;
+
+    /**
+     * 考生考场信息
+     */
+    private String examRoom;
+
+    /**
+     * 考生备注信息
+     */
+    private String remark;
+
+    /**
+     * 扫描批次编号
+     */
+    private String batchCode;
+
+    /**
+     * 原图数量
+     */
+    private Integer sheetCount;
+
+    /**
+     * 裁切图数量
+     */
+    private Integer sliceCount;
+
+    /**
+     * 客观答案
+     */
+    private String answers;
+
+    /**
+     * 是否已上传
+     */
+    private boolean upload;
+
+    /**
+     * 是否缺考
+     */
+    private boolean absent;
+
+    /**
+     * 是否人工指定缺考
+     */
+    private boolean manualAbsent;
+
+    private boolean breach;
+
+    /**
+     * 是否数据校验异常
+     */
+    private boolean exception;
+
+    /**
+     * 上传时间
+     */
+    @Temporal(TemporalType.TIMESTAMP)
+    private Date uploadTime;
+
+    /**
+     * 客观总分
+     */
+    private Double objectiveScore;
+
+    /**
+     * 客观题得分明细
+     */
+    private String objectiveScoreList;
+
+    /**
+     * 主观题状态
+     */
+    @Enumerated(EnumType.STRING)
+    private SubjectiveStatus subjectiveStatus;
+
+    /**
+     * 主观总分
+     */
+    private Double subjectiveScore;
+    
+    
+    @ExcelField(title = "客观分*", align = 2, sort = 4)
+    private String objectiveScoreString;
+    
+    @ExcelField(title = "主观分*", align = 2, sort = 5)
+    private String subjectiveScoreString;
+    @ExcelField(title = "试卷总分*", align = 2, sort = 6)
+    private String totalScoreString;
+
+    /**
+     * 主观题得分明细
+     */
+    @ExcelField(title = "得分明细*", align = 2, sort =7)
+    private String subjectiveScoreList;
+
+    /**
+     * 科目层次信息
+     */
+    private String subjectLevel;
+
+    /**
+     * 专业类型信息
+     */
+    private String subjectCategory;
+
+    /**
+     * 学院
+     */
+    private String college;
+
+    /**
+     * 班级
+     */
+    private String className;
+
+    /**
+     * 任课老师
+     */
+    private String teacher;
+
+    @Temporal(TemporalType.TIMESTAMP)
+    private Date inspectTime;
+
+    /**
+     * 复核人id
+     */
+    private Integer inspectorId;
+
+    private Integer cardNumber;
+
+    private Integer inspectCount;
+    
+    /**
+     * 当前轮次是否已复核
+     */
+    private boolean inspected;
+    
+    /**
+     * 成绩校验人ID
+     */
+    private Integer scoreVerifyUser;
+    
+    /**
+     * 成绩校验时间
+     */
+    @Temporal(TemporalType.TIMESTAMP)
+    private Date scoreVerifyTime;
+    
+    /**
+     * 成绩校验标记结果
+     */
+    private Boolean scoreVerifyFlagged;
+    
+
+    /**
+     * 科目备注信息
+     */
+    private String subjectRemark;
+
+    private ExamSubject subject;
+
+    private List<String> sheetUrls;
+
+    private List<String> packageUrls;
+
+    private String answerUrl;
+
+    private String markTime;
+
+    private Integer libraryId;
+
+    private int number;
+
+    private String markLogin;
+
+    private String markName;
+
+    private String tagValue;
+
+    private String examName;
+
+    private List<ExamQuestion> subjectiveQuestionList;
+
+    private List<ExamQuestion> objectiveQuestionList;
+
+    private ProblemType problemType;
+
+    private String problemUserName;
+
+    private String problemRestTime;
+
+    private Map<String,InspectHistory> inspectHistoryMap;
+
+    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 = BigDecimalUtils.add(score, objectiveScore);
+        }
+        if (subjectiveScore != null) {
+            score = BigDecimalUtils.add(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;
+    }
+
+    public String getCollege() {
+        return college;
+    }
+
+    public void setCollege(String college) {
+        this.college = college;
+    }
+
+    public String getClassName() {
+        return className;
+    }
+
+    public void setClassName(String className) {
+        this.className = className;
+    }
+
+    public String getTeacher() {
+        return teacher;
+    }
+
+    public void setTeacher(String teacher) {
+        this.teacher = teacher;
+    }
+
+    public List<ExamQuestion> getSubjectiveQuestionList() {
+        return subjectiveQuestionList;
+    }
+
+    public void setSubjectiveQuestionList(List<ExamQuestion> subjectiveQuestionList) {
+        this.subjectiveQuestionList = subjectiveQuestionList;
+    }
+
+    public List<ExamQuestion> getObjectiveQuestionList() {
+        return objectiveQuestionList;
+    }
+
+    public void setObjectiveQuestionList(List<ExamQuestion> objectiveQuestionList) {
+        this.objectiveQuestionList = objectiveQuestionList;
+    }
+
+    public ProblemType getProblemType() {
+        return problemType;
+    }
+
+    public void setProblemType(ProblemType problemType) {
+        this.problemType = problemType;
+    }
+
+    public SubjectiveStatus getSubjectiveStatus() {
+        return subjectiveStatus;
+    }
+
+    public void setSubjectiveStatus(String subjectiveStatusStr) {
+        this.subjectiveStatus = SubjectiveStatus.valueOf(subjectiveStatusStr);
+    }
+
+    public String getSecretNumber() {
+        return secretNumber;
+    }
+
+
+    public Date getInspectTime() {
+        return inspectTime;
+    }
+
+    public void setInspectTime(Date inspectTime) {
+        this.inspectTime = inspectTime;
+    }
+
+    public void setSecretNumber(String secretNumber) {
+        this.secretNumber = secretNumber;
+    }
+
+    public String getExamName() {
+        return examName;
+    }
+
+    public void setExamName(String examName) {
+        this.examName = examName;
+    }
+
+    public Integer getInspectorId() {
+        return inspectorId;
+    }
+
+    public void setInspectorId(Integer inspectorId) {
+        this.inspectorId = inspectorId;
+    }
+
+
+    public String getProblemUserName() {
+        return problemUserName;
+    }
+
+    public void setProblemUserName(String problemUserName) {
+        this.problemUserName = problemUserName;
+    }
+
+    public String getProblemRestTime() {
+        return problemRestTime;
+    }
+
+    public void setProblemRestTime(String problemRestTime) {
+        this.problemRestTime = problemRestTime;
+    }
+
+    public Integer getCardNumber() {
+        return cardNumber;
+    }
+
+    public void setCardNumber(Integer cardNumber) {
+        this.cardNumber = cardNumber;
+    }
+
+
+    public Map<String, InspectHistory> getInspectHistoryMap() {
+		return inspectHistoryMap;
+	}
+
+	public void setInspectHistoryMap(Map<String, InspectHistory> inspectHistoryMap) {
+		this.inspectHistoryMap = inspectHistoryMap;
+	}
+
+	public Integer getInspectCount() {
+        return inspectCount;
+    }
+
+    public void setInspectCount(Integer inspectCount) {
+        this.inspectCount = inspectCount;
+    }
+
+	public Integer getScoreVerifyUser() {
+		return scoreVerifyUser;
+	}
+
+	public void setScoreVerifyUser(Integer scoreVerifyUser) {
+		this.scoreVerifyUser = scoreVerifyUser;
+	}
+
+	public Date getScoreVerifyTime() {
+		return scoreVerifyTime;
+	}
+
+	public void setScoreVerifyTime(Date scoreVerifyTime) {
+		this.scoreVerifyTime = scoreVerifyTime;
+	}
+
+	public Boolean getScoreVerifyFlagged() {
+		return scoreVerifyFlagged;
+	}
+
+	public void setScoreVerifyFlagged(Boolean scoreVerifyFlagged) {
+		this.scoreVerifyFlagged = scoreVerifyFlagged;
+	}
+
+	public boolean getInspected() {
+		return inspected;
+	}
+
+	public void setInspected(boolean inspected) {
+		this.inspected = inspected;
+	}
+	
+	public static ExamStudentVo of(ExamStudent e) {
+		ExamStudentVo vo=new ExamStudentVo();
+		BeanUtils.copyProperties(e, vo);
+		return vo;
+	}
+}

+ 7 - 13
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/model/ExamStudent.java

@@ -5,7 +5,6 @@ import java.util.ArrayList;
 import java.util.Date;
 import java.util.LinkedList;
 import java.util.List;
-import java.util.Map;
 
 import javax.persistence.Column;
 import javax.persistence.Entity;
@@ -20,7 +19,9 @@ import javax.persistence.Transient;
 
 import org.apache.commons.lang.StringUtils;
 import org.apache.commons.lang.math.RandomUtils;
+import org.springframework.beans.BeanUtils;
 
+import cn.com.qmth.stmms.biz.exam.bean.ExamStudentVo;
 import cn.com.qmth.stmms.biz.mark.model.ProblemType;
 import cn.com.qmth.stmms.biz.user.model.User;
 import cn.com.qmth.stmms.biz.utils.ScoreItem;
@@ -368,9 +369,6 @@ public class ExamStudent implements Serializable {
     @Transient
     private String problemRestTime;
 
-    @Transient
-    private Map<String,InspectHistory> inspectHistoryMap;
-
     public Integer getId() {
         return id;
     }
@@ -920,15 +918,6 @@ public class ExamStudent implements Serializable {
         this.cardNumber = cardNumber;
     }
 
-
-    public Map<String, InspectHistory> getInspectHistoryMap() {
-		return inspectHistoryMap;
-	}
-
-	public void setInspectHistoryMap(Map<String, InspectHistory> inspectHistoryMap) {
-		this.inspectHistoryMap = inspectHistoryMap;
-	}
-
 	public Integer getInspectCount() {
         return inspectCount;
     }
@@ -969,4 +958,9 @@ public class ExamStudent implements Serializable {
 		this.inspected = inspected;
 	}
 
+	public static ExamStudent of(ExamStudentVo vo) {
+		ExamStudent e=new ExamStudent();
+		BeanUtils.copyProperties(vo, e);
+		return e;
+	}
 }

+ 560 - 0
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/query/InspectQuery.java

@@ -0,0 +1,560 @@
+package cn.com.qmth.stmms.biz.exam.query;
+
+import java.util.Date;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.springframework.data.domain.Sort;
+import org.springframework.data.domain.Sort.Direction;
+
+import cn.com.qmth.stmms.biz.common.BaseQuery;
+import cn.com.qmth.stmms.biz.exam.bean.ExamStudentVo;
+import cn.com.qmth.stmms.common.enums.SubjectiveStatus;
+
+public class InspectQuery extends BaseQuery<ExamStudentVo> {
+
+    private Integer examId;
+
+    private Integer schoolId;
+
+    private String campusName;
+
+    private String name;
+
+    private String examNumberIn;
+
+    private String examNumber;
+
+    private String secretNumber;
+
+    private String studentCode;
+
+    private String subjectCode;
+
+    private String batchCode;
+
+    private String packageCode;
+
+    private String subjectLevel;
+
+    private String subjectCategory;
+
+    private String examSite;
+
+    private String examRoom;
+
+    private Double objectiveScore;
+
+    private Double objectiveScoreGt;
+
+    private Double objectiveScoreLt;
+
+    private Set<SubjectiveStatus> statusSet;
+
+    private Double subjectiveScore;
+
+    private Double subjectiveScoreGt;
+
+    private Double subjectiveScoreLt;
+
+    private Boolean upload;
+
+    private Boolean absent;
+
+    private Boolean manualAbsent;
+
+    private Boolean exception;
+
+    private Boolean uploadTimeNotNull;
+
+    private Date minUploadTime;
+
+    private Date maxUploadTime;
+
+    private String campusNameIn;
+
+    private String subjectCodeIn;
+
+    private String examSiteIn;
+
+    private String campusNameNotIn;
+
+    private String subjectCodeNotIn;
+
+    private String examSiteNotIn;
+
+    private String ids;
+
+    private Double startScore;
+
+    private Double endScore;
+
+    private Boolean breach;
+
+    private String college;
+
+    private String className;
+
+    private String teacher;
+
+    private String paperType;
+
+    private List<Integer> studentIds;
+
+    private Integer inspectorId;
+    
+    private String inspectorName;
+
+    private Integer sheetCount;
+    
+    //是否已复核
+    private Boolean inspected;
+    
+    private Double questionScore;
+    
+    private Boolean questionScoreEmpty;
+    
+    //不可重复
+    private Boolean inspectUnrepeated;
+    
+    private boolean export;
+
+    public InspectQuery() {
+        super();
+        this.statusSet = new HashSet<>();
+    }
+
+    public void orderByExamNumber() {
+        setSort(new Sort(Direction.ASC, "examNumber"));
+    }
+
+    public void orderByExamIdDesc() {
+        setSort(new Sort(Direction.DESC, "examId"));
+    }
+
+    public void orderByInspectTimeDesc() {
+        setSort(new Sort(Direction.DESC, "inspectTime"));
+    }
+
+    public Integer getExamId() {
+        return examId;
+    }
+
+    public void setExamId(Integer examId) {
+        this.examId = examId;
+    }
+
+    public Integer getSchoolId() {
+        return schoolId;
+    }
+
+    public void setSchoolId(Integer schoolId) {
+        this.schoolId = schoolId;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    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 getSecretNumber() {
+        return secretNumber;
+    }
+
+    public void setSecretNumber(String secretNumber) {
+        this.secretNumber = secretNumber;
+    }
+
+    public String getStudentCode() {
+        return studentCode;
+    }
+
+    public void setStudentCode(String studentCode) {
+        this.studentCode = studentCode;
+    }
+
+    public Boolean getUpload() {
+        return upload;
+    }
+
+    public void setUpload(Boolean upload) {
+        this.upload = upload;
+    }
+
+    public Boolean getAbsent() {
+        return absent;
+    }
+
+    public void setAbsent(Boolean absent) {
+        this.absent = absent;
+    }
+
+    public String getCampusName() {
+        return campusName;
+    }
+
+    public void setCampusName(String campusName) {
+        this.campusName = campusName;
+    }
+
+    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 Boolean getException() {
+        return exception;
+    }
+
+    public void setException(Boolean exception) {
+        this.exception = exception;
+    }
+
+    public Double getObjectiveScore() {
+        return objectiveScore;
+    }
+
+    public void setObjectiveScore(Double objectiveScore) {
+        this.objectiveScore = objectiveScore;
+    }
+
+    public Double getObjectiveScoreGt() {
+        return objectiveScoreGt;
+    }
+
+    public void setObjectiveScoreGt(Double objectiveScoreGt) {
+        this.objectiveScoreGt = objectiveScoreGt;
+    }
+
+    public Double getSubjectiveScore() {
+        return subjectiveScore;
+    }
+
+    public void setSubjectiveScore(Double subjectiveScore) {
+        this.subjectiveScore = subjectiveScore;
+    }
+
+    public Double getSubjectiveScoreGt() {
+        return subjectiveScoreGt;
+    }
+
+    public void setSubjectiveScoreGt(Double subjectiveScoreGt) {
+        this.subjectiveScoreGt = subjectiveScoreGt;
+    }
+
+    public String getSubjectLevel() {
+        return subjectLevel;
+    }
+
+    public void setSubjectLevel(String subjectLevel) {
+        this.subjectLevel = subjectLevel;
+    }
+
+    public String getSubjectCategory() {
+        return subjectCategory;
+    }
+
+    public void setSubjectCategory(String subjectCategory) {
+        this.subjectCategory = subjectCategory;
+    }
+
+    public Boolean getUploadTimeNotNull() {
+        return uploadTimeNotNull;
+    }
+
+    public void setUploadTimeNotNull(Boolean uploadTimeNotNull) {
+        this.uploadTimeNotNull = uploadTimeNotNull;
+    }
+
+    public Date getMinUploadTime() {
+        return minUploadTime;
+    }
+
+    public void setMinUploadTime(Date minUploadTime) {
+        this.minUploadTime = minUploadTime;
+    }
+
+    public Date getMaxUploadTime() {
+        return maxUploadTime;
+    }
+
+    public void setMaxUploadTime(Date maxUploadTime) {
+        this.maxUploadTime = maxUploadTime;
+    }
+
+    public String getExamNumberIn() {
+        return examNumberIn;
+    }
+
+    public void setExamNumberIn(String examNumberIn) {
+        this.examNumberIn = examNumberIn;
+    }
+
+    public Double getObjectiveScoreLt() {
+        return objectiveScoreLt;
+    }
+
+    public void setObjectiveScoreLt(Double objectiveScoreLt) {
+        this.objectiveScoreLt = objectiveScoreLt;
+    }
+
+    public Double getSubjectiveScoreLt() {
+        return subjectiveScoreLt;
+    }
+
+    public void setSubjectiveScoreLt(Double subjectiveScoreLt) {
+        this.subjectiveScoreLt = subjectiveScoreLt;
+    }
+
+    public String getCampusNameIn() {
+        return campusNameIn;
+    }
+
+    public void setCampusNameIn(String campusNameIn) {
+        this.campusNameIn = campusNameIn;
+    }
+
+    public String getSubjectCodeIn() {
+        return subjectCodeIn;
+    }
+
+    public void setSubjectCodeIn(String subjectCodeIn) {
+        this.subjectCodeIn = subjectCodeIn;
+    }
+
+    public String getCampusNameNotIn() {
+        return campusNameNotIn;
+    }
+
+    public void setCampusNameNotIn(String campusNameNotIn) {
+        this.campusNameNotIn = campusNameNotIn;
+    }
+
+    public String getSubjectCodeNotIn() {
+        return subjectCodeNotIn;
+    }
+
+    public void setSubjectCodeNotIn(String subjectCodeNotIn) {
+        this.subjectCodeNotIn = subjectCodeNotIn;
+    }
+
+    public String getIds() {
+        return ids;
+    }
+
+    public void setIds(String ids) {
+        this.ids = ids;
+    }
+
+    public Double getStartScore() {
+        return startScore;
+    }
+
+    public void setStartScore(Double startScore) {
+        this.startScore = startScore;
+    }
+
+    public Double getEndScore() {
+        return endScore;
+    }
+
+    public void setEndScore(Double endScore) {
+        this.endScore = endScore;
+    }
+
+    public Boolean getBreach() {
+        return breach;
+    }
+
+    public void setBreach(Boolean breach) {
+        this.breach = breach;
+    }
+
+    public Boolean getManualAbsent() {
+        return manualAbsent;
+    }
+
+    public void setManualAbsent(Boolean manualAbsent) {
+        this.manualAbsent = manualAbsent;
+    }
+
+    public String getCollege() {
+        return college;
+    }
+
+    public void setCollege(String college) {
+        this.college = college;
+    }
+
+    public String getClassName() {
+        return className;
+    }
+
+    public void setClassName(String className) {
+        this.className = className;
+    }
+
+    public String getTeacher() {
+        return teacher;
+    }
+
+    public void setTeacher(String teacher) {
+        this.teacher = teacher;
+    }
+
+    public String getPaperType() {
+        return paperType;
+    }
+
+    public void setPaperType(String paperType) {
+        this.paperType = paperType;
+    }
+
+    public Set<SubjectiveStatus> getStatusSet() {
+        return statusSet;
+    }
+
+    public void clearStatus() {
+        this.statusSet.clear();
+    }
+
+    public void addStatus(SubjectiveStatus status) {
+        this.statusSet.add(status);
+    }
+
+    public List<Integer> getStudentIds() {
+        return studentIds;
+    }
+
+    public void setStudentIds(List<Integer> studentIds) {
+        this.studentIds = studentIds;
+    }
+
+    public Integer getInspectorId() {
+        return inspectorId;
+    }
+
+    public void setInspectorId(Integer inspectorId) {
+        this.inspectorId = inspectorId;
+    }
+
+    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 getExamSiteIn() {
+        return examSiteIn;
+    }
+
+    public void setExamSiteIn(String examSiteIn) {
+        this.examSiteIn = examSiteIn;
+    }
+
+    public String getExamSiteNotIn() {
+        return examSiteNotIn;
+    }
+
+    public void setExamSiteNotIn(String examSiteNotIn) {
+        this.examSiteNotIn = examSiteNotIn;
+    }
+
+    public Integer getSheetCount() {
+        return sheetCount;
+    }
+
+    public void setSheetCount(Integer sheetCount) {
+        this.sheetCount = sheetCount;
+    }
+
+	public Boolean getInspected() {
+		return inspected;
+	}
+
+	public void setInspected(Boolean inspected) {
+		this.inspected = inspected;
+	}
+
+	public String getInspectorName() {
+		return inspectorName;
+	}
+
+	public void setInspectorName(String inspectorName) {
+		this.inspectorName = inspectorName;
+	}
+
+	public Double getQuestionScore() {
+		return questionScore;
+	}
+
+	public void setQuestionScore(Double questionScore) {
+		this.questionScore = questionScore;
+	}
+
+	public Boolean getQuestionScoreEmpty() {
+		return questionScoreEmpty;
+	}
+
+	public void setQuestionScoreEmpty(Boolean questionScoreEmpty) {
+		this.questionScoreEmpty = questionScoreEmpty;
+	}
+
+	public Boolean getInspectUnrepeated() {
+		return inspectUnrepeated;
+	}
+
+	public void setInspectUnrepeated(Boolean inspectUnrepeated) {
+		this.inspectUnrepeated = inspectUnrepeated;
+	}
+
+	public boolean isExport() {
+		return export;
+	}
+
+	public void setExport(boolean export) {
+		this.export = export;
+	}
+
+}

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

@@ -45,7 +45,7 @@ public interface ExamSubjectService {
 
     void updateTrialCount(int examId, String subjectCode, int trialCount);
 
-	int findMaxInspectRound(int examId, List<String> subjectCodes);
+	int findMaxInspectRound(int examId, Set<String> subjectCodes);
 
 	void nextInspectRound(int examId, String subjectCode);
 

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

@@ -1,18 +1,19 @@
 package cn.com.qmth.stmms.biz.exam.service;
 
+import java.util.List;
+
+import cn.com.qmth.stmms.biz.exam.bean.ExamStudentVo;
 import cn.com.qmth.stmms.biz.exam.model.ExamStudent;
-import cn.com.qmth.stmms.biz.exam.query.ExamStudentSearchQuery;
+import cn.com.qmth.stmms.biz.exam.query.InspectQuery;
 import cn.com.qmth.stmms.common.enums.SelectiveStatus;
 import cn.com.qmth.stmms.common.enums.SubjectiveStatus;
 
-import java.util.List;
-
 public interface InspectedService {
 
-	List<ExamStudent> findByQuery(ExamStudentSearchQuery query, SubjectiveStatus status, Integer mainNumber,
+	List<ExamStudentVo> findByQuery(InspectQuery query, SubjectiveStatus status, Integer mainNumber,
 			Double mainStartScore, Double mainEndScore, SelectiveStatus selectiveStatus);
 
-	Integer countByQuery(ExamStudentSearchQuery query, SubjectiveStatus status, Integer mainNumber,
+	Integer countByQuery(InspectQuery query, SubjectiveStatus status, Integer mainNumber,
 			Double mainStartScore, Double mainEndScore, SelectiveStatus selectiveStatus);
 
 	void releaseByUserId(Integer examId, String subjectCode, Integer userId);
@@ -22,7 +23,7 @@ public interface InspectedService {
 	/**
 	 * 申请领取某个任务
 	 */
-	boolean applyStudent(ExamStudent student, Integer userId);
+	boolean applyStudent(ExamStudentVo student, Integer userId);
 
 	/**
 	 * 是否已领取了某个任务
@@ -42,10 +43,10 @@ public interface InspectedService {
 	 */
 	boolean cancel(Integer studentId);
 
-	Integer needInspectCount(ExamStudentSearchQuery query, Integer mainNumber, Double mainStartScore,
+	Integer needInspectCount(InspectQuery query, Integer mainNumber, Double mainStartScore,
 			Double mainEndScore, SelectiveStatus selectiveStatus);
 
-	void fillInspectHistoryMap(List<ExamStudent> list, int maxInspectRound);
+	void fillInspectHistoryMap(List<ExamStudentVo> list, int maxInspectRound);
 
 	boolean inspectFinish(Integer examId, String subjectCode, Integer inspectRound);
 

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

@@ -214,7 +214,7 @@ public class ExamSubjectServiceImpl extends BaseQueryService<ExamSubject> implem
     }
 
 	@Override
-	public int findMaxInspectRound(int examId, List<String> subjectCodes) {
+	public int findMaxInspectRound(int examId, Set<String> subjectCodes) {
 		StringBuilder sql = new StringBuilder("select max(s.inspect_round) from eb_exam_subject s ");
 		sql.append(" where s.exam_id="+examId+" and s.code in ('"+StringUtils.join(subjectCodes,"','")+"')");
         Query countQuery = entityManager.createNativeQuery(sql.toString());

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

@@ -12,24 +12,27 @@ import javax.persistence.PersistenceContext;
 import javax.persistence.Query;
 
 import org.apache.commons.lang.StringUtils;
+import org.hibernate.SQLQuery;
+import org.hibernate.transform.Transformers;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
 import cn.com.qmth.stmms.biz.common.BaseQueryService;
+import cn.com.qmth.stmms.biz.exam.bean.ExamStudentVo;
 import cn.com.qmth.stmms.biz.exam.model.ExamStudent;
 import cn.com.qmth.stmms.biz.exam.model.ExamSubject;
 import cn.com.qmth.stmms.biz.exam.model.InspectHistory;
 import cn.com.qmth.stmms.biz.exam.model.MarkGroup;
 import cn.com.qmth.stmms.biz.exam.model.SelectiveGroup;
 import cn.com.qmth.stmms.biz.exam.query.ExamStudentSearchQuery;
+import cn.com.qmth.stmms.biz.exam.query.InspectQuery;
 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.InspectHistoryService;
 import cn.com.qmth.stmms.biz.exam.service.InspectedService;
 import cn.com.qmth.stmms.biz.exam.service.MarkGroupService;
 import cn.com.qmth.stmms.biz.exam.service.SelectiveGroupService;
-import cn.com.qmth.stmms.biz.user.service.UserService;
 import cn.com.qmth.stmms.biz.utils.TaskLock;
 import cn.com.qmth.stmms.biz.utils.TaskLockUtil;
 import cn.com.qmth.stmms.common.enums.SelectiveStatus;
@@ -47,9 +50,6 @@ public class InspectedServiceImpl extends BaseQueryService<ExamStudent> implemen
     @Autowired
     private ExamSubjectService examSubjectService;
 
-    @Autowired
-    private UserService userService;
-
     @Autowired
     private MarkGroupService groupService;
 
@@ -61,29 +61,35 @@ public class InspectedServiceImpl extends BaseQueryService<ExamStudent> implemen
 
     @SuppressWarnings("unchecked")
     @Override
-    public List<ExamStudent> findByQuery(ExamStudentSearchQuery query, SubjectiveStatus status, Integer mainNumber,
+    public List<ExamStudentVo> findByQuery(InspectQuery query, SubjectiveStatus status, Integer mainNumber,
             Double mainStartScore, Double mainEndScore, SelectiveStatus selectiveStatus) {
     	int offset=(query.getPageNumber() - 1) * query.getPageSize();
-        StringBuilder dataSql = new StringBuilder("select s.id from eb_exam_student s ");
+        StringBuilder sql = new StringBuilder();
+        sql.append(" select s.id,s.exam_id examId,s.school_id schoolId,s.subject_code subjectCode,");
+        sql.append(" s.subject_name subjectName,s.paper_type paperType,s.exam_number examNumber,s.secret_number secretNumber,");
+        sql.append(" s.student_code studentCode,s.name,s.package_code packageCode,s.campus_name campusName,s.exam_site examSite,");
+        sql.append(" s.exam_room examRoom,s.remark,s.batch_code batchCode,s.sheet_count sheetCount,s.slice_count sliceCount,s.answers,");
+        sql.append(" s.is_upload upload,s.is_absent absent,s.is_manual_absent manualAbsent,s.is_breach breach,s.is_exception exception,");
+        sql.append(" s.upload_time uploadTime,s.objective_score objectiveScore,s.objective_score_list objectiveScoreList,");
+        sql.append(" s.subjective_status subjectiveStatus,s.subjective_score subjectiveScore,s.subjective_score_list subjectiveScoreList,");
+        sql.append(" s.subject_level subjectLevel,s.subject_category subjectCategory,s.college,s.class_name className,s.teacher,");
+        sql.append(" s.card_number cardNumber,s.inspect_count inspectCount,s.score_verify_user scoreVerifyUser,");
+        sql.append(" s.score_verify_time scoreVerifyTime,s.score_verify_flagged scoreVerifyFlagged,s.inspect_time inspectTime,");
+        sql.append(" s.inspector_id inspectorId,s.inspected ");
+        sql.append(" from eb_exam_student s ");
         String whereSql = getWhereSql(query, status, mainNumber, mainStartScore, mainEndScore,selectiveStatus);
-        dataSql.append(whereSql).append(" order by s.inspect_time desc ").append(" limit "+offset+","+query.getPageSize());
-        Query dataQuery = entityManager.createNativeQuery(dataSql.toString());
-        List<Integer> list = dataQuery.getResultList();
-        List<ExamStudent> resultList = new ArrayList<ExamStudent>();
-        if (list != null && !list.isEmpty()) {
-            for (Integer id : list) {
-                ExamStudent e = studentService.findById(id);
-                if (e.getInspectorId() != null) {
-                    e.setInspector(userService.findById(e.getInspectorId()));
-                }
-                resultList.add(e);
-            }
+        sql.append(whereSql).append(" order by s.inspect_time desc ");
+        if(!query.isExport()) {
+        	sql.append(" limit "+offset+","+query.getPageSize());
         }
+        Query dataQuery = entityManager.createNativeQuery(sql.toString());
+        dataQuery.unwrap(SQLQuery.class).setResultTransformer(Transformers.aliasToBean(ExamStudentVo.class));
+        List<ExamStudentVo> resultList = dataQuery.getResultList();
         return resultList;
 
     }
 
-    private String getWhereSql(ExamStudentSearchQuery query, SubjectiveStatus status, Integer mainNumber,
+    private String getWhereSql(InspectQuery query, SubjectiveStatus status, Integer mainNumber,
             Double mainStartScore, Double mainEndScore, SelectiveStatus selectiveStatus) {
         StringBuilder whereSql = new StringBuilder(" WHERE s.is_upload = 1 and s.is_absent = 0 and s.is_breach = 0 ");
         if (query.getExamId() != null) {
@@ -182,7 +188,7 @@ public class InspectedServiceImpl extends BaseQueryService<ExamStudent> implemen
     }
 
     @Override
-    public Integer countByQuery(ExamStudentSearchQuery query, SubjectiveStatus status, Integer mainNumber,
+    public Integer countByQuery(InspectQuery query, SubjectiveStatus status, Integer mainNumber,
             Double mainStartScore, Double mainEndScore,SelectiveStatus selectiveStatus) {
         StringBuilder countSql = new StringBuilder("select count(s.id) from eb_exam_student s ");
         String whereSql = getWhereSql(query, status, mainNumber, mainStartScore, mainEndScore, selectiveStatus);
@@ -194,7 +200,7 @@ public class InspectedServiceImpl extends BaseQueryService<ExamStudent> implemen
     }
     
     @Override
-    public Integer needInspectCount(ExamStudentSearchQuery query, Integer mainNumber,
+    public Integer needInspectCount(InspectQuery query, Integer mainNumber,
             Double mainStartScore, Double mainEndScore,SelectiveStatus selectiveStatus) {
     	StringBuilder countSql = new StringBuilder("select count(s.id) from eb_exam_student s ");
         String whereSql = getWhereSql(query, SubjectiveStatus.MARKED, mainNumber, mainStartScore, mainEndScore,selectiveStatus);
@@ -219,7 +225,7 @@ public class InspectedServiceImpl extends BaseQueryService<ExamStudent> implemen
     }
 
     @Override
-    public boolean applyStudent(ExamStudent student, Integer userId) {
+    public boolean applyStudent(ExamStudentVo student, Integer userId) {
         TaskLock taskLock = TaskLockUtil.getInspectedStudentTask(getKey(student));
         boolean lock = taskLock.add(student.getId(), 1, userId);
         // 上锁失败直接返回
@@ -240,7 +246,10 @@ public class InspectedServiceImpl extends BaseQueryService<ExamStudent> implemen
         TaskLock taskLock = TaskLockUtil.getInspectedStudentTask(getKey(student));
         return taskLock.exist(student.getId(), 1, userId);
     }
-
+    
+    private String getKey(ExamStudentVo student) {
+        return student.getExamId() + "_" + student.getSubjectCode();
+    }
     private String getKey(ExamStudent student) {
         return student.getExamId() + "_" + student.getSubjectCode();
     }
@@ -289,7 +298,7 @@ public class InspectedServiceImpl extends BaseQueryService<ExamStudent> implemen
     }
 
 	@Override
-	public void fillInspectHistoryMap(List<ExamStudent> list, int maxInspectRound) {
+	public void fillInspectHistoryMap(List<ExamStudentVo> list, int maxInspectRound) {
 		List<Integer> sids=list.stream().map(e->e.getId()).collect(Collectors.toList());
 		List<InspectHistory> ihs=inspectHistoryService.findByStudentIdIn(sids);
 		if(ihs==null||ihs.size()==0) {
@@ -304,7 +313,7 @@ public class InspectedServiceImpl extends BaseQueryService<ExamStudent> implemen
 			}
 			tem.put(ih.getInspectRound().toString(),ih);
 		}
-		for(ExamStudent es:list) {
+		for(ExamStudentVo es:list) {
 			es.setInspectHistoryMap(map.get(es.getId()));
 		}
 	}

+ 9 - 0
stmms-web/src/main/java/cn/com/qmth/stmms/admin/exam/BaseExamController.java

@@ -75,6 +75,15 @@ public class BaseExamController extends BaseController {
         }
         redirectAttributes.addFlashAttribute("message", sb.toString());
     }
+    
+    protected void addErrMessage(RedirectAttributes redirectAttributes,Throwable e, String... messages) {
+        StringBuilder sb = new StringBuilder();
+        for (String message : messages) {
+            sb.append(message).append(messages.length > 1 ? "<br/>" : "");
+        }
+        redirectAttributes.addFlashAttribute("message", sb.toString());
+        log.error(sb.toString(),e);
+    }
 
     protected List<Exam> getExamList(WebUser wu, ExamType type) {
         return examService.findBySchoolIdAndTypeAndStatus(wu.getUser().getSchoolId(), type);

+ 66 - 31
stmms-web/src/main/java/cn/com/qmth/stmms/admin/exam/InspectedController.java

@@ -25,12 +25,15 @@ import org.springframework.web.bind.annotation.ResponseBody;
 import org.springframework.web.servlet.mvc.support.RedirectAttributes;
 
 import cn.com.qmth.stmms.admin.dto.RejectResult;
+import cn.com.qmth.stmms.admin.utils.ExportInspectExcel;
 import cn.com.qmth.stmms.admin.vo.InspectedSubjectVO;
+import cn.com.qmth.stmms.biz.exam.bean.ExamStudentVo;
 import cn.com.qmth.stmms.biz.exam.bean.InspectWorkVo;
 import cn.com.qmth.stmms.biz.exam.model.Exam;
 import cn.com.qmth.stmms.biz.exam.model.ExamStudent;
 import cn.com.qmth.stmms.biz.exam.model.ExamSubject;
 import cn.com.qmth.stmms.biz.exam.query.ExamStudentSearchQuery;
+import cn.com.qmth.stmms.biz.exam.query.InspectQuery;
 import cn.com.qmth.stmms.biz.exam.service.ExamQuestionService;
 import cn.com.qmth.stmms.biz.exam.service.ExamService;
 import cn.com.qmth.stmms.biz.exam.service.ExamStudentService;
@@ -98,7 +101,7 @@ public class InspectedController extends BaseExamController {
     public static final String UN_SELECTIVE_SCORE = "-1";
 
     @RequestMapping(value = "/list")
-    public String list(Model model, HttpServletRequest request, ExamStudentSearchQuery query,
+    public String list(Model model, HttpServletRequest request, InspectQuery query,
             @RequestParam(required = false) SubjectiveStatus status,
             @RequestParam(required = false) SelectiveStatus selectiveStatus,
             @RequestParam(required = false) Integer mainNumber, @RequestParam(required = false) Double mainStartScore,
@@ -116,15 +119,15 @@ public class InspectedController extends BaseExamController {
             subjectList.forEach(e -> subjectCodeIn.add(e.getCode()));
             query.setSubjectCodeIn(StringUtils.join(subjectCodeIn, ","));
         }
-        List<ExamStudent> list = inspectedService
+        List<ExamStudentVo> list = inspectedService
                 .findByQuery(query, status, mainNumber, mainStartScore, mainEndScore,  selectiveStatus);
-        for (ExamStudent e : list) {
+        for (ExamStudentVo e : list) {
             e.setSubjectiveScoreList(e.getSubjectiveScoreList().replace(UN_SELECTIVE_SCORE, "/"));
 //            e.setInspectHistoryList(inspectHistoryService.findByStudentIdLimit3(e.getId()));
         }
         int maxInspectRound=1;
         if(list!=null&&list.size()>0) {
-        	List<String> subjectCodes=list.stream().map(e->e.getSubjectCode()).collect(Collectors.toList());
+        	Set<String> subjectCodes=list.stream().map(e->e.getSubjectCode()).collect(Collectors.toSet());
         	maxInspectRound=subjectService.findMaxInspectRound(examId,subjectCodes);
         	inspectedService.fillInspectHistoryMap(list,maxInspectRound);
         }
@@ -164,7 +167,7 @@ public class InspectedController extends BaseExamController {
     @Logging(menu = "开始考生复核", type = LogType.QUERY)
     @RequestMapping(value = "/getTask", method = RequestMethod.POST)
     @ResponseBody
-    public Task getTask(HttpServletRequest request,HttpServletResponse response, RedirectAttributes ra, ExamStudentSearchQuery query,
+    public Task getTask(HttpServletRequest request,HttpServletResponse response, RedirectAttributes ra, InspectQuery query,
             @RequestParam(required = false, defaultValue = "false") SelectiveStatus selectiveStatus,
             @RequestParam(required = false) Integer mainNumber, @RequestParam(required = false) Double mainStartScore,
             @RequestParam(required = false) Double mainEndScore, @RequestParam(required = false) Double questionScore,
@@ -180,7 +183,7 @@ public class InspectedController extends BaseExamController {
         		return null;
         	}
             releaseStudent(studentId);
-            if (inspectedService.applyStudent(student, wu.getId())) {
+            if (inspectedService.applyStudent(ExamStudentVo.of(student), wu.getId())) {
                 task = taskService.build(student);
             }
         }
@@ -194,13 +197,13 @@ public class InspectedController extends BaseExamController {
             	return null;
             }
             releaseStudent(student.getId());
-            if (inspectedService.applyStudent(student, wu.getId())) {
+            if (inspectedService.applyStudent(ExamStudentVo.of(student), wu.getId())) {
                 task = taskService.build(student);
             }
         }
         int retry = 1;
         while (task == null) {
-            List<ExamStudent> list = new ArrayList<ExamStudent>();
+            List<ExamStudentVo> list = new ArrayList<>();
             // 需要判断评卷员是否绑定了班级
             query.setExamId(examId);
             query.setPageNumber(retry);
@@ -217,9 +220,9 @@ public class InspectedController extends BaseExamController {
             if (list.isEmpty()) {
                 break;
             }
-            for (ExamStudent student : list) {
+            for (ExamStudentVo student : list) {
                 if (inspectedService.applyStudent(student, wu.getId())) {
-                    task = taskService.build(student);
+                    task = taskService.build(ExamStudent.of(student));
                     break;
                 }
             }
@@ -238,8 +241,7 @@ public class InspectedController extends BaseExamController {
         ExamStudent student = studentService.findById(studentId);
         JSONObject obj = new JSONObject();
         try {
-            if (student != null && lockService.trylock(LockType.STUDENT, studentId) && inspectedService
-                    .inspect(student, wu.getId())) {
+            if (student != null && lockService.trylock(LockType.STUDENT, studentId) && inspectedService.inspect(student, wu.getId())) {
                 inspectedService.releaseByStudent(student);
                 obj.accumulate("success", true);
             } else {
@@ -388,7 +390,7 @@ public class InspectedController extends BaseExamController {
 
     @RequestMapping(value = "/getStatus", method = RequestMethod.POST)
     @ResponseBody
-    public JSONObject status(HttpServletRequest request, ExamStudentSearchQuery query,
+    public JSONObject status(HttpServletRequest request, InspectQuery query,
             @RequestParam(required = false) SelectiveStatus selectiveStatus,
             @RequestParam(required = false) Integer mainNumber, @RequestParam(required = false) Double mainStartScore,
             @RequestParam(required = false) Double mainEndScore, @RequestParam(required = false) Double questionScore) {
@@ -563,25 +565,58 @@ public class InspectedController extends BaseExamController {
     
     @RequestMapping(value = "list/export", method = RequestMethod.POST)
     public String exportListFile(HttpServletRequest request, HttpServletResponse response,
-            RedirectAttributes redirectAttributes) {
-//    	Integer examId = getSessionExamId(request);
-//		Exam exam = examService.findById(examId);
-//		if (ExamType.MULTI_MEDIA.equals(exam.getType())) {
-//			return "modules/exam/permission";
-//		}
-//		WebUser wu = RequestUtils.getWebUser(request);
-//        try {
-//        	List<ScoreVerifyVo> list = scoreVerifyService.findFlagged(examId,wu.getId());
-//            String fileName = "标记卷数据.xlsx";
-//            new ExportExcel("标记卷数据", ScoreVerifyVo.class).setDataList(list).write(response, fileName)
-//                    .dispose();
-//            return null;
-//        } catch (Exception e) {
-//            addMessage(redirectAttributes, "导出数据失败" + e.getMessage());
-//        }
+            RedirectAttributes redirectAttributes,InspectQuery query,
+            @RequestParam(required = false) SubjectiveStatus status,
+            @RequestParam(required = false) SelectiveStatus selectiveStatus,
+            @RequestParam(required = false) Integer mainNumber, @RequestParam(required = false) Double mainStartScore,
+            @RequestParam(required = false) Double mainEndScore) {
+    	int examId = getSessionExamId(request);
+        Exam exam = examService.findById(examId);
+        if (ExamType.MULTI_MEDIA.equals(exam.getType())) {
+            return "modules/exam/permission";
+        }
+        WebUser wu = RequestUtils.getWebUser(request);
+        query.setExamId(examId);
+        List<ExamSubject> subjectList = getExamSubject(examId, wu);
+        if (StringUtils.isBlank(query.getSubjectCode()) && wu.getRole() != Role.SCHOOL_ADMIN) {
+            List<String> subjectCodeIn = new ArrayList<String>();
+            subjectList.forEach(e -> subjectCodeIn.add(e.getCode()));
+            query.setSubjectCodeIn(StringUtils.join(subjectCodeIn, ","));
+        }
+        query.setExport(true);
+        List<ExamStudentVo> list = inspectedService
+                .findByQuery(query, status, mainNumber, mainStartScore, mainEndScore,  selectiveStatus);
+        for (ExamStudentVo e : list) {
+            e.setSubjectiveScoreList(e.getSubjectiveScoreList().replace(UN_SELECTIVE_SCORE, "/"));
+        }
+        int maxInspectRound=1;
+        if(list!=null&&list.size()>0) {
+        	Set<String> subjectCodes=list.stream().map(e->e.getSubjectCode()).collect(Collectors.toSet());
+        	maxInspectRound=subjectService.findMaxInspectRound(examId,subjectCodes);
+        	inspectedService.fillInspectHistoryMap(list,maxInspectRound);
+        }
+        try {
+        	String fileName = "复核列表.xlsx";
+        	List<String> headerList = getInspectHeader(maxInspectRound);
+        	ExportInspectExcel excel = new ExportInspectExcel("复核列表", headerList, ExamStudentVo.class);
+            excel.setDataList(list);
+            excel.write(response, fileName).dispose();
+            return null;
+        } catch (Exception e) {
+        	addErrMessage(redirectAttributes,e, "导出数据失败");
+        }
         return "redirect:/admin/exam/inspected/list";
     }
-    @RequestMapping(value = "work/export", method = RequestMethod.POST)
+    private List<String> getInspectHeader(int maxInspectRound) {
+    	List<String> ret=new ArrayList<>();
+    	for(int i=1;i<=maxInspectRound;i++) {
+    		ret.add("复核人"+i);
+    		ret.add("复核时间"+i);
+    	}
+		return ret;
+	}
+
+	@RequestMapping(value = "work/export", method = RequestMethod.POST)
     public String exportWorkFile(HttpServletRequest request, HttpServletResponse response,
             RedirectAttributes redirectAttributes) {
     	Integer examId = getSessionExamId(request);
@@ -596,7 +631,7 @@ public class InspectedController extends BaseExamController {
                     .dispose();
             return null;
         } catch (Exception e) {
-            addMessage(redirectAttributes, "导出数据失败" + e.getMessage());
+        	addErrMessage(redirectAttributes,e, "导出数据失败");
         }
         return "redirect:/admin/exam/inspected/list";
     }

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

@@ -177,7 +177,7 @@ public class ScoreVerifyController extends BaseExamController {
                     .dispose();
             return null;
         } catch (Exception e) {
-            addMessage(redirectAttributes, "导出数据失败" + e.getMessage());
+        	addErrMessage(redirectAttributes,e, "导出数据失败");
         }
         return "redirect:/admin/exam/score/verify/init";
     }

+ 500 - 0
stmms-web/src/main/java/cn/com/qmth/stmms/admin/utils/ExportInspectExcel.java

@@ -0,0 +1,500 @@
+package cn.com.qmth.stmms.admin.utils;
+
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.commons.lang.StringUtils;
+import org.apache.poi.ss.usermodel.Cell;
+import org.apache.poi.ss.usermodel.CellStyle;
+import org.apache.poi.ss.usermodel.Comment;
+import org.apache.poi.ss.usermodel.DataFormat;
+import org.apache.poi.ss.usermodel.Font;
+import org.apache.poi.ss.usermodel.IndexedColors;
+import org.apache.poi.ss.usermodel.Row;
+import org.apache.poi.ss.usermodel.Sheet;
+import org.apache.poi.ss.usermodel.Workbook;
+import org.apache.poi.ss.util.CellRangeAddress;
+import org.apache.poi.xssf.streaming.SXSSFWorkbook;
+import org.apache.poi.xssf.usermodel.XSSFClientAnchor;
+import org.apache.poi.xssf.usermodel.XSSFRichTextString;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.collect.Lists;
+
+import cn.com.qmth.stmms.admin.dto.ExamStudentDTO;
+import cn.com.qmth.stmms.biz.exam.bean.ExamStudentVo;
+import cn.com.qmth.stmms.biz.exam.model.ExamQuestion;
+import cn.com.qmth.stmms.common.annotation.ExcelField;
+import cn.com.qmth.stmms.common.utils.DateUtils;
+import cn.com.qmth.stmms.common.utils.Encodes;
+import cn.com.qmth.stmms.common.utils.Reflections;
+
+public class ExportInspectExcel {
+
+    private static Logger log = LoggerFactory.getLogger(ExportInspectExcel.class);
+
+    /**
+     * 工作薄对象
+     */
+    private SXSSFWorkbook wb;
+
+    /**
+     * 工作表对象
+     */
+    private Sheet sheet;
+
+    /**
+     * 样式列表
+     */
+    private Map<String, CellStyle> styles;
+
+    /**
+     * 当前行号
+     */
+    private int rownum;
+
+    /**
+     * 注解列表(Object[]{ ExcelField, Field/Method })
+     */
+    private List<Object[]> annotationList = Lists.newArrayList();
+
+    /**
+     * 构造函数
+     * 
+     * @param title
+     *            表格标题,传“空值”,表示无标题
+     * @param cls
+     *            实体对象,通过annotation.ExportField获取标题
+     */
+    public ExportInspectExcel(String title, List<String> headerList, Class<?> cls) {
+        this(title, cls, 1, headerList);
+    }
+
+    /**
+     * 构造函数
+     * 
+     * @param title
+     *            表格标题,传“空值”,表示无标题
+     * @param cls
+     *            实体对象,通过annotation.ExportField获取标题
+     * @param type
+     *            导出类型(1:导出数据;2:导出模板)
+     * @param groups
+     *            导入分组
+     */
+    public ExportInspectExcel(String title, Class<?> cls, int type, List<String> addHeaderList, int... groups) {
+        // Get annotation field
+        Field[] fs = cls.getDeclaredFields();
+        for (Field f : fs) {
+            ExcelField ef = f.getAnnotation(ExcelField.class);
+            if (ef != null && (ef.type() == 0 || ef.type() == type)) {
+                if (groups != null && groups.length > 0) {
+                    boolean inGroup = false;
+                    for (int g : groups) {
+                        if (inGroup) {
+                            break;
+                        }
+                        for (int efg : ef.groups()) {
+                            if (g == efg) {
+                                inGroup = true;
+                                annotationList.add(new Object[] { ef, f });
+                                break;
+                            }
+                        }
+                    }
+                } else {
+                    annotationList.add(new Object[] { ef, f });
+                }
+            }
+        }
+        // Get annotation method
+        Method[] ms = cls.getDeclaredMethods();
+        for (Method m : ms) {
+            ExcelField ef = m.getAnnotation(ExcelField.class);
+            if (ef != null && (ef.type() == 0 || ef.type() == type)) {
+                if (groups != null && groups.length > 0) {
+                    boolean inGroup = false;
+                    for (int g : groups) {
+                        if (inGroup) {
+                            break;
+                        }
+                        for (int efg : ef.groups()) {
+                            if (g == efg) {
+                                inGroup = true;
+                                annotationList.add(new Object[] { ef, m });
+                                break;
+                            }
+                        }
+                    }
+                } else {
+                    annotationList.add(new Object[] { ef, m });
+                }
+            }
+        }
+        // Field sorting
+        Collections.sort(annotationList, new Comparator<Object[]>() {
+
+            public int compare(Object[] o1, Object[] o2) {
+                return new Integer(((ExcelField) o1[0]).sort()).compareTo(new Integer(((ExcelField) o2[0]).sort()));
+            };
+        });
+        // Initialize
+        List<String> headerList = Lists.newArrayList();
+        for (Object[] os : annotationList) {
+            String t = ((ExcelField) os[0]).title();
+            // 如果是导出,则去掉注释
+            if (type == 1) {
+                String[] ss = StringUtils.split(t, "**", 2);
+                if (ss.length == 2) {
+                    t = ss[0];
+                }
+            }
+            headerList.add(t);
+        }
+        headerList.addAll(addHeaderList);
+        initialize(title, headerList);
+    }
+
+    /**
+     * 构造函数
+     * 
+     * @param title
+     *            表格标题,传“空值”,表示无标题
+     * @param headers
+     *            表头数组
+     */
+    public ExportInspectExcel(String title, String[] headers) {
+        initialize(title, Lists.newArrayList(headers));
+    }
+
+    /**
+     * 构造函数
+     * 
+     * @param title
+     *            表格标题,传“空值”,表示无标题
+     * @param headerList
+     *            表头列表
+     */
+    public ExportInspectExcel(String title, List<String> headerList) {
+        initialize(title, headerList);
+    }
+
+    /**
+     * 初始化函数
+     * 
+     * @param title
+     *            表格标题,传“空值”,表示无标题
+     * @param headerList
+     *            表头列表
+     */
+    public void initialize(String title, List<String> headerList) {
+        this.wb = new SXSSFWorkbook(500);
+        this.sheet = wb.createSheet("Export");
+        this.styles = createStyles(wb);
+        // Create title
+        if (StringUtils.isNotBlank(title)) {
+            Row titleRow = sheet.createRow(rownum++);
+            titleRow.setHeightInPoints(30);
+            Cell titleCell = titleRow.createCell(0);
+            titleCell.setCellStyle(styles.get("title"));
+            titleCell.setCellValue(title);
+            sheet.addMergedRegion(new CellRangeAddress(titleRow.getRowNum(), titleRow.getRowNum(),
+                    titleRow.getRowNum(), headerList.size() - 1));
+        }
+        // Create header
+        if (headerList == null) {
+            throw new RuntimeException("headerList not null!");
+        }
+        Row headerRow = sheet.createRow(rownum++);
+        headerRow.setHeightInPoints(16);
+        for (int i = 0; i < headerList.size(); i++) {
+            Cell cell = headerRow.createCell(i);
+            cell.setCellStyle(styles.get("header"));
+            String[] ss = StringUtils.split(headerList.get(i), "**", 2);
+            if (ss.length == 2) {
+                cell.setCellValue(ss[0]);
+                Comment comment = this.sheet.createDrawingPatriarch().createCellComment(
+                        new XSSFClientAnchor(0, 0, 0, 0, (short) 3, 3, (short) 5, 6));
+                comment.setString(new XSSFRichTextString(ss[1]));
+                cell.setCellComment(comment);
+            } else {
+                cell.setCellValue(headerList.get(i));
+            }
+            sheet.autoSizeColumn(i);
+        }
+        for (int i = 0; i < headerList.size(); i++) {
+            int colWidth = sheet.getColumnWidth(i) * 2;
+            sheet.setColumnWidth(i, colWidth < 3000 ? 3000 : colWidth);
+        }
+        log.debug("Initialize success.");
+    }
+
+    /**
+     * 创建表格样式
+     * 
+     * @param wb
+     *            工作薄对象
+     * @return 样式列表
+     */
+    private Map<String, CellStyle> createStyles(Workbook wb) {
+        Map<String, CellStyle> styles = new HashMap<String, CellStyle>();
+
+        CellStyle style = wb.createCellStyle();
+        style.setAlignment(CellStyle.ALIGN_CENTER);
+        style.setVerticalAlignment(CellStyle.VERTICAL_CENTER);
+        Font titleFont = wb.createFont();
+        titleFont.setFontName("Arial");
+        titleFont.setFontHeightInPoints((short) 16);
+        titleFont.setBoldweight(Font.BOLDWEIGHT_BOLD);
+        style.setFont(titleFont);
+        styles.put("title", style);
+
+        style = wb.createCellStyle();
+        style.setVerticalAlignment(CellStyle.VERTICAL_CENTER);
+        style.setBorderRight(CellStyle.BORDER_THIN);
+        style.setRightBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
+        style.setBorderLeft(CellStyle.BORDER_THIN);
+        style.setLeftBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
+        style.setBorderTop(CellStyle.BORDER_THIN);
+        style.setTopBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
+        style.setBorderBottom(CellStyle.BORDER_THIN);
+        style.setBottomBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
+        Font dataFont = wb.createFont();
+        dataFont.setFontName("Arial");
+        dataFont.setFontHeightInPoints((short) 10);
+        style.setFont(dataFont);
+        styles.put("data", style);
+
+        style = wb.createCellStyle();
+        style.cloneStyleFrom(styles.get("data"));
+        style.setAlignment(CellStyle.ALIGN_LEFT);
+        styles.put("data1", style);
+
+        style = wb.createCellStyle();
+        style.cloneStyleFrom(styles.get("data"));
+        style.setAlignment(CellStyle.ALIGN_CENTER);
+        styles.put("data2", style);
+
+        style = wb.createCellStyle();
+        style.cloneStyleFrom(styles.get("data"));
+        style.setAlignment(CellStyle.ALIGN_RIGHT);
+        styles.put("data3", style);
+
+        style = wb.createCellStyle();
+        style.cloneStyleFrom(styles.get("data"));
+        // style.setWrapText(true);
+        style.setAlignment(CellStyle.ALIGN_CENTER);
+        style.setFillForegroundColor(IndexedColors.GREY_50_PERCENT.getIndex());
+        style.setFillPattern(CellStyle.SOLID_FOREGROUND);
+        Font headerFont = wb.createFont();
+        headerFont.setFontName("Arial");
+        headerFont.setFontHeightInPoints((short) 10);
+        headerFont.setBoldweight(Font.BOLDWEIGHT_BOLD);
+        headerFont.setColor(IndexedColors.WHITE.getIndex());
+        style.setFont(headerFont);
+        styles.put("header", style);
+
+        return styles;
+    }
+
+    /**
+     * 添加一行
+     * 
+     * @return 行对象
+     */
+    public Row addRow() {
+        return sheet.createRow(rownum++);
+    }
+
+    /**
+     * 添加一个单元格
+     * 
+     * @param row
+     *            添加的行
+     * @param column
+     *            添加列号
+     * @param val
+     *            添加值
+     * @return 单元格对象
+     */
+    public Cell addCell(Row row, int column, Object val) {
+        return this.addCell(row, column, val, 0, Class.class);
+    }
+
+    /**
+     * 添加一个单元格
+     * 
+     * @param row
+     *            添加的行
+     * @param column
+     *            添加列号
+     * @param val
+     *            添加值
+     * @param align
+     *            对齐方式(1:靠左;2:居中;3:靠右)
+     * @return 单元格对象
+     */
+    public Cell addCell(Row row, int column, Object val, int align, Class<?> fieldType) {
+        Cell cell = row.createCell(column);
+        CellStyle style = styles.get("data" + (align >= 1 && align <= 3 ? align : ""));
+        try {
+            if (val == null) {
+                cell.setCellValue("");
+            } else if (val instanceof String) {
+                cell.setCellValue((String) val);
+            } else if (val instanceof Integer) {
+                cell.setCellValue((Integer) val);
+            } else if (val instanceof Long) {
+                cell.setCellValue((Long) val);
+            } else if (val instanceof Double) {
+                cell.setCellValue((Double) val);
+            } else if (val instanceof Float) {
+                cell.setCellValue((Float) val);
+            } else if (val instanceof Date) {
+                DataFormat format = wb.createDataFormat();
+                style.setDataFormat(format.getFormat("yyyy-MM-dd"));
+                cell.setCellValue((Date) val);
+            } else {
+                if (fieldType != Class.class) {
+                    cell.setCellValue((String) fieldType.getMethod("setValue", Object.class).invoke(null, val));
+                } else {
+                    cell.setCellValue((String) Class
+                            .forName(
+                                    this.getClass()
+                                            .getName()
+                                            .replaceAll(this.getClass().getSimpleName(),
+                                                    "fieldtype." + val.getClass().getSimpleName() + "Type"))
+                            .getMethod("setValue", Object.class).invoke(null, val));
+                }
+            }
+        } catch (Exception ex) {
+            log.info("Set cell value [" + row.getRowNum() + "," + column + "] error: " + ex.toString());
+            cell.setCellValue(val.toString());
+        }
+        cell.setCellStyle(style);
+        return cell;
+    }
+
+    /**
+     * 添加数据(通过annotation.ExportField添加数据)
+     * 
+     * @return list 数据列表
+     */
+    public <E> ExportInspectExcel setDataList(List<ExamStudentVo> list) {
+        for (ExamStudentVo e : list) {
+            int colunm = 0;
+            Row row = this.addRow();
+            StringBuilder sb = new StringBuilder();
+            for (Object[] os : annotationList) {
+                ExcelField ef = (ExcelField) os[0];
+                Object val = null;
+                try {
+                    if (StringUtils.isNotBlank(ef.value())) {
+                        val = Reflections.invokeGetter(e, ef.value());
+                    } else {
+                        if (os[1] instanceof Field) {
+                            val = Reflections.invokeGetter(e, ((Field) os[1]).getName());
+                        } else if (os[1] instanceof Method) {
+                            val = Reflections.invokeMethod(e, ((Method) os[1]).getName(), new Class[] {},
+                                    new Object[] {});
+                        }
+                    }
+                } catch (Exception ex) {
+                    log.info(ex.toString());
+                    val = "";
+                }
+                this.addCell(row, colunm++, val, ef.align(), ef.fieldType());
+                sb.append(val + ", ");
+            }
+            if(e.getInspectHistoryMap()!=null&&e.getInspectHistoryMap().size()>0) {
+            	for(String key:e.getInspectHistoryMap().keySet()) {
+            		int index=Integer.valueOf(key);
+            		int temCol=(index-1)*2;
+            		this.addCell(row, colunm+temCol, e.getInspectHistoryMap().get(key).getInspectorName());
+                    this.addCell(row, colunm+temCol+1, DateUtils.formatDateTime(e.getInspectHistoryMap().get(key).getInspectTime()));
+            	}
+            }
+            log.debug("Write success: [" + row.getRowNum() + "] " + sb.toString());
+        }
+        return this;
+    }
+
+    /**
+     * 输出数据流
+     * 
+     * @param os
+     *            输出数据流
+     */
+    public ExportInspectExcel write(OutputStream os) throws IOException {
+        wb.write(os);
+        return this;
+    }
+
+    /**
+     * 输出到客户端
+     * 
+     * @param fileName
+     *            输出文件名
+     */
+    public ExportInspectExcel write(HttpServletResponse response, String fileName) throws IOException {
+        response.reset();
+        response.setContentType("application/octet-stream; charset=utf-8");
+        response.setHeader("Content-Disposition", "attachment; filename=" + Encodes.urlEncode(fileName));
+        write(response.getOutputStream());
+        return this;
+    }
+
+    /**
+     * 输出到文件
+     * 
+     * @param fileName
+     *            输出文件名
+     */
+    public ExportInspectExcel writeFile(String name) throws FileNotFoundException, IOException {
+        FileOutputStream os = new FileOutputStream(name);
+        this.write(os);
+        return this;
+    }
+
+    /**
+     * 清理临时文件
+     */
+    public ExportInspectExcel dispose() {
+        wb.dispose();
+        return this;
+    }
+
+
+    public void setOptions(List<ExamStudentDTO> list, List<ExamQuestion> oQuestions, List<ExamQuestion> sQestions) {
+        List<String> headerList = Lists.newArrayList();
+        for (Object[] os : annotationList) {
+            String t = ((ExcelField) os[0]).title();
+            headerList.add(t);
+        }
+
+        for (ExamQuestion examQuestion : oQuestions) {
+            String val = examQuestion.getMainTitle() + "." + examQuestion.getQuestionNumber();
+            headerList.add(val);
+        }
+        for (ExamQuestion examQuestion : sQestions) {
+            String val = examQuestion.getMainTitle() + "." + examQuestion.getQuestionNumber();
+            headerList.add(val);
+        }
+        initialize("", headerList);
+
+    }
+
+}