浏览代码

奥鹏成绩查询导出特殊Excel形式

nikang 7 年之前
父节点
当前提交
6a932a198e

+ 32 - 0
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/model/ExamStudent.java

@@ -251,6 +251,15 @@ public class ExamStudent implements Serializable {
      */
     @Transient
     private boolean marked;
+    
+    @Transient
+    private int number;
+    
+    @Transient
+    private String markLogin;
+    
+    @Transient
+    private String markName;
 
     public Integer getId() {
         return id;
@@ -636,4 +645,27 @@ public class ExamStudent implements Serializable {
 		this.marked = marked;
 	}
 
+	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;
+	}
 }

+ 49 - 0
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/query/ExamStudentSearchQuery.java

@@ -55,6 +55,16 @@ public class ExamStudentSearchQuery extends BaseQuery<ExamStudent> {
     private String campusNameNotIn;
 
     private String subjectCodeNotIn;
+    
+    private String markLogin;
+    
+    private String markName;
+    
+    private String ids;
+    
+    private Double startScroe; 
+    
+    private Double endScroe; 
 
     public void orderByExamNumber() {
         setSort(new Sort(Direction.ASC, "examNumber"));
@@ -252,4 +262,43 @@ public class ExamStudentSearchQuery extends BaseQuery<ExamStudent> {
         this.examNumberIn = examNumberIn;
     }
 
+	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 getIds() {
+		return ids;
+	}
+
+	public void setIds(String ids) {
+		this.ids = ids;
+	}
+
+	public Double getStartScroe() {
+		return startScroe;
+	}
+
+	public void setStartScroe(Double startScroe) {
+		this.startScroe = startScroe;
+	}
+
+	public Double getEndScroe() {
+		return endScroe;
+	}
+
+	public void setEndScroe(Double endScroe) {
+		this.endScroe = endScroe;
+	}
 }

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

@@ -78,5 +78,9 @@ public interface ExamStudentService {
 
 	public ExamStudent findBySchoolIdAndSubjectCodeStartingWithAndStudentCode(
 			Integer schoolId, String subjectCode, String studentCode);
+	
+	public String findIdsByMarkLogin(String markLogin);
+	
+	public String findIdsByMarkName(String markName);
 
 }

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

@@ -37,5 +37,7 @@ public interface MarkerService {
     List<Marker> getMarkCount(int examId);
 
 	List<Marker> findExamAndCommon(int examId, boolean common);
+	
+	public Marker findByStudentId(int studentId);
 
 }

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

@@ -1,5 +1,6 @@
 package cn.com.qmth.stmms.biz.exam.service.impl;
 
+import java.util.ArrayList;
 import java.util.Date;
 import java.util.HashMap;
 import java.util.HashSet;
@@ -14,6 +15,7 @@ import javax.persistence.criteria.Predicate;
 import javax.persistence.criteria.Root;
 
 import org.apache.commons.lang.StringUtils;
+import javax.persistence.criteria.Expression;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.data.domain.Page;
@@ -374,9 +376,27 @@ public class ExamStudentServiceImpl extends BaseQueryService<ExamStudent> implem
             @Override
             public Predicate toPredicate(Root<ExamStudent> root, CriteriaQuery<?> cQuery, CriteriaBuilder cb) {
                 List<Predicate> predicates = new LinkedList<Predicate>();
+                Expression<Double> evaluationItemSum = cb.sum(root.get("objectiveScore").as(Double.class),root.get("subjectiveScore").as(Double.class));
+                if (query.getStartScroe()!=null ) {
+                    predicates.add(cb.ge(evaluationItemSum,  query.getStartScroe()));
+                }
+                if (query.getEndScroe()!=null  ) {
+                    predicates.add(cb.le(evaluationItemSum,  query.getEndScroe()));
+                }
+                if (query.getStartScroe()!=null && query.getEndScroe()!=null ) {
+                    predicates.add(cb.between(evaluationItemSum, query.getStartScroe(), query.getEndScroe()));
+                }
                 if (query.getExamId() > 0) {
                     predicates.add(cb.equal(root.get("examId"), query.getExamId()));
                 }
+                if (StringUtils.isNotBlank(query.getIds())) {
+                    String[] ids = query.getIds().split(",");
+                    List<String> list = new ArrayList<String>();
+                    for(String str : ids){
+                        list.add(str);
+                    }
+                    predicates.add(root.get("id").in(list));
+                }
                 if (StringUtils.isNotBlank(query.getExamNumber())) {
                     predicates.add(cb.equal(root.get("examNumber"), query.getExamNumber()));
                 } else if (StringUtils.isNotBlank(query.getExamNumberIn())) {
@@ -545,4 +565,14 @@ public class ExamStudentServiceImpl extends BaseQueryService<ExamStudent> implem
             return null;
         }
 	}
+	@Override
+	public String findIdsByMarkLogin(String markLogin) {
+	    List<String[]> o = studentDao.findIdsByMarkLogin(markLogin);
+	    return StringUtils.join(o, ",");
+	}
+	@Override
+    public String findIdsByMarkName(String MarkName) {
+        List<String[]> o = studentDao.findIdsByMarkName(MarkName);
+        return StringUtils.join(o, ",");
+    }
 }

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

@@ -233,4 +233,9 @@ public class MarkerServiceImpl extends BaseQueryService<Marker> implements Marke
         query.setSort(new Sort(Direction.DESC, "id"));
 		return markerDao.findByExamIdAndCommon(examId, commo, query);
 	}
+	
+	@Override
+	public Marker findByStudentId(int studentId){
+	    return  markerDao.findByStudentId(studentId);
+	}
 }

+ 98 - 0
stmms-web/src/main/java/cn/com/qmth/stmms/admin/dto/ExamStudentScoreDTO.java

@@ -0,0 +1,98 @@
+package cn.com.qmth.stmms.admin.dto;
+
+import cn.com.qmth.stmms.biz.exam.model.ExamStudent;
+import cn.com.qmth.stmms.common.annotation.ExcelField;
+
+public class ExamStudentScoreDTO {
+    
+    @ExcelField(title = "序号", align = 2, sort = 10)
+    private int nunber;
+
+    @ExcelField(title = "考点名称", align = 1, sort = 20)
+    private String campusName;
+
+    @ExcelField(title = "课程名称", align = 1, sort = 30)
+    private String subjectName;
+
+    @ExcelField(title = "院校学号", align = 1, sort = 40)
+    private String studentCode;
+
+    @ExcelField(title = "学生姓名", align = 2, sort = 50)
+    private String name;
+
+    @ExcelField(title = "考试成绩", align = 2, sort = 60)
+    private double totalScore;
+
+    
+    public ExamStudentScoreDTO() {
+    }
+
+    public ExamStudentScoreDTO(ExamStudent student) {
+        setNunber(student.getNumber());
+        setCampusName(student.getCampusName());
+        setSubjectName(student.getSubjectName());
+        setStudentCode(student.getStudentCode());
+        setName(student.getName());
+        setTotalScore(student.getTotalScore());
+    }
+    
+    public int getNunber() {
+        return nunber;
+    }
+
+    
+    public void setNunber(int nunber) {
+        this.nunber = nunber;
+    }
+
+    public String getCampusName() {
+        return campusName;
+    }
+
+    
+    public void setCampusName(String campusName) {
+        this.campusName = campusName;
+    }
+
+    
+    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 getName() {
+        return name;
+    }
+
+    
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    
+    public double getTotalScore() {
+        return totalScore;
+    }
+
+    
+    public void setTotalScore(double totalScore) {
+        this.totalScore = totalScore;
+    }
+    
+
+}

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

@@ -20,6 +20,7 @@ import org.springframework.web.servlet.ModelAndView;
 import org.springframework.web.servlet.mvc.support.RedirectAttributes;
 
 import cn.com.qmth.stmms.admin.dto.ExamStudentDTO;
+import cn.com.qmth.stmms.admin.dto.ExamStudentScoreDTO;
 import cn.com.qmth.stmms.admin.dto.ScoreEditDTO;
 import cn.com.qmth.stmms.admin.dto.ScoreExportDTO;
 import cn.com.qmth.stmms.admin.exam.parameter.BaseParameterController;
@@ -31,12 +32,14 @@ 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.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.ExamStudentService;
 import cn.com.qmth.stmms.biz.exam.service.ExamSubjectService;
+import cn.com.qmth.stmms.biz.exam.service.MarkerService;
 import cn.com.qmth.stmms.biz.exam.service.ScoreRateService;
 import cn.com.qmth.stmms.biz.mark.model.MarkLibrary;
 import cn.com.qmth.stmms.biz.mark.service.MarkLibraryService;
@@ -45,6 +48,7 @@ import cn.com.qmth.stmms.common.enums.ExamStatus;
 import cn.com.qmth.stmms.common.enums.LibraryStatus;
 import cn.com.qmth.stmms.common.utils.DateUtils;
 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;
 
@@ -87,6 +91,9 @@ public class ScoreController extends BaseParameterController {
 
     @Autowired
     private AsyncTaskExecutor taskExecutor;
+    
+    @Autowired
+    private MarkerService markerService;
 
     @RequestMapping
     public ModelAndView list(HttpServletRequest request, ExamStudentSearchQuery query,
@@ -110,6 +117,10 @@ public class ScoreController extends BaseParameterController {
                 query.setObjectiveScoreGt(0d);
                 query.setSubjectiveScore(0d);
             }
+            String ids = getStudentIdsByMarkLoginAndMarkName(query.getMarkLogin(),query.getMarkName());
+            if(StringUtils.isNotBlank(ids)){
+                query.setIds(ids);
+            }
             query = studentService.findByQuery(query);
             for (ExamStudent student : query.getResult()) {
                 buildSheetUrl(student);
@@ -117,6 +128,11 @@ public class ScoreController extends BaseParameterController {
                 buildAnswerUrl(student);
                 student.setSubjectRemark(subjectService.find(student.getExamId(), student.getSubjectCode()).getRemark());
                 student.setMarked(isMarked(student));
+                Marker marker = markerService.findByStudentId(student.getId());
+                if(marker != null){
+                    student.setMarkLogin(marker.getLoginName());
+                    student.setMarkName(marker.getName());
+                }
             }
             view.addObject("query", query);
             view.addObject("filter", filter);
@@ -219,7 +235,12 @@ public class ScoreController extends BaseParameterController {
             query.setAbsent(false);
             query.setPageNumber(1);
             query.setPageSize(Integer.MAX_VALUE);
+            String ids = getStudentIdsByMarkLoginAndMarkName(query.getMarkLogin(),query.getMarkName());
+            if(StringUtils.isNotBlank(ids)){
+                query.setIds(ids);
+            }
             query = studentService.findByQuery(query);
+            addStudentPropertype(query.getResult());
             String fileName = "成绩单_" + DateUtils.getDate("yyyyMMdd") + ".xlsx";
             try {
             	if(subjectCode!=null){
@@ -317,4 +338,80 @@ public class ScoreController extends BaseParameterController {
 			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()+"]成绩单";
+            }
+            String ids = getStudentIdsByMarkLoginAndMarkName(query.getMarkLogin(),query.getMarkName());
+            if(StringUtils.isNotBlank(ids)){
+                query.setIds(ids);
+            }
+            query.setExamId(examId);
+            query.setUpload(true);
+            query.setAbsent(false);
+            query.setPageNumber(1);
+            query.setPageSize(Integer.MAX_VALUE);
+            query = studentService.findByQuery(query);
+            addStudentPropertype(query.getResult());
+            String fileName = "成绩单_" + DateUtils.getDate("yyyyMMdd") + ".xls";
+            String subTitle = "负责教师签字:_______________ 交回日期:_______________";
+            try {
+                List<ExamStudentScoreDTO> list = new LinkedList<ExamStudentScoreDTO>();
+                    int i =1;
+                for (ExamStudent student : query.getResult()) {
+                    student.setNumber(i);
+                    list.add(new ExamStudentScoreDTO(student));
+                    i++;
+                }
+                new ExportExcel2(examName,subTitle, ExamStudentScoreDTO.class).setDataList(list).write(response, fileName);
+                return null;
+            } catch (Exception e) {
+                addMessage(redirectAttributes, "导出成绩失败!" + e.getMessage());
+                return "redirect:/admin/exam/score";
+            }
+        } else {
+            return "redirect:/admin/exam/list";
+        }
+    }
+    public String getStudentIdsByMarkLoginAndMarkName(String markLogin,String markName){
+        String ids = "";
+        if(StringUtils.isNotBlank(markLogin)){
+            ids += studentService.findIdsByMarkLogin(markLogin);
+            if(ids.equals("")){
+                ids = "-1";
+            }
+        }
+        if(StringUtils.isNotBlank(markName)){
+            String s =  studentService.findIdsByMarkName(markName);
+            if(StringUtils.isBlank(ids)){
+                if(s.equals("")){
+                    ids = "-1";
+                }else{
+                    ids += s;
+                }
+            }else{
+                if(!ids.equals("-1")){
+                    if(StringUtils.isBlank(s)){
+                        ids = "-1";
+                    }
+                }
+            }
+        }
+        return ids;
+    }
+    public void addStudentPropertype(List<ExamStudent> students){
+        for (ExamStudent student : students) {
+            Marker marker = markerService.findByStudentId(student.getId());
+            if(marker != null){
+                student.setMarkLogin(marker.getLoginName());
+                student.setMarkName(marker.getName());
+            }
+        }
+    }
 }

+ 499 - 0
stmms-web/src/main/java/cn/com/qmth/stmms/common/utils/ExportExcel2.java

@@ -0,0 +1,499 @@
+package cn.com.qmth.stmms.common.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.hssf.usermodel.HSSFFooter;
+import org.apache.poi.hssf.usermodel.HSSFWorkbook;
+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.usermodel.XSSFClientAnchor;
+import org.apache.poi.xssf.usermodel.XSSFRichTextString;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import cn.com.qmth.stmms.common.annotation.ExcelField;
+
+import com.google.common.collect.Lists;
+
+/**
+ * 导出Excel文件(导出“XLSX”格式,支持大数据量导出   @see org.apache.poi.ss.SpreadsheetVersion)
+ * @author XiongKaiJun
+ * @version 2016-06-12
+ */
+public class ExportExcel2 {
+	
+	private static Logger log = LoggerFactory.getLogger(ExportExcel2.class);
+			
+	/**
+	 * 工作薄对象
+	 */
+	private HSSFWorkbook wb;
+	
+	/**
+	 * 工作表对象
+	 */
+	private Sheet sheet;
+	
+	/**
+	 * 样式列表
+	 */
+	private Map<String, CellStyle> styles;
+	
+	/**
+	 * 当前行号
+	 */
+	private int rownum;
+	
+	/**
+	 * 注解列表(Object[]{ ExcelField, Field/Method })
+	 */
+	List<Object[]> annotationList = Lists.newArrayList();
+	
+	/**
+	 * 构造函数
+	 * @param title 表格标题,传“空值”,表示无标题
+	 * @param cls 实体对象,通过annotation.ExportField获取标题
+	 */
+	public ExportExcel2(String title,String subTitle, Class<?> cls){
+		this(title,subTitle, cls, 1);
+	}
+	
+	/**
+	 * 构造函数
+	 * @param title 表格标题,传“空值”,表示无标题
+	 * @param cls 实体对象,通过annotation.ExportField获取标题
+	 * @param type 导出类型(1:导出数据;2:导出模板)
+	 * @param groups 导入分组
+	 */
+	public ExportExcel2(String title,String subTitle, Class<?> cls, int type, 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);
+		}
+		initialize(title,subTitle, headerList);
+	}
+	
+	/**
+	 * 构造函数
+	 * @param title 表格标题,传“空值”,表示无标题
+	 * @param headers 表头数组
+	 */
+	public ExportExcel2(String title,String subTile, String[] headers) {
+		initialize(title,subTile, Lists.newArrayList(headers));
+	}
+	
+	/**
+	 * 构造函数
+	 * @param title 表格标题,传“空值”,表示无标题
+	 * @param headerList 表头列表
+	 */
+	public ExportExcel2(String title,String subTile, List<String> headerList) {
+		initialize(title,subTile, headerList);
+	}
+	
+	/**
+	 * 初始化函数
+	 * @param title 表格标题,传“空值”,表示无标题
+	 * @param headerList 表头列表
+	 */
+	private void initialize(String title,String subTile, List<String> headerList) {
+		this.wb = new HSSFWorkbook();
+		this.sheet = wb.createSheet("Export");
+		sheet.setMargin(sheet.BottomMargin, ScoreExportParam.SHEET_BOTTOMMARGIN);
+		sheet.setMargin(sheet.LeftMargin, ScoreExportParam.SHEET_LEFTMARGIN);
+		sheet.setMargin(sheet.RightMargin, ScoreExportParam.SHEET_RIGHTMARGIN);
+		sheet.setMargin(sheet.TopMargin, ScoreExportParam.SHEET_TOPMARGIN);
+		sheet.setMargin(sheet.HeaderMargin, ScoreExportParam.SHEET_HEADERMARGIN);
+		sheet.setMargin(sheet.FooterMargin,ScoreExportParam.SHEET_FOOTERMARGIN);
+		HSSFFooter footer = (HSSFFooter) sheet.getFooter();
+		footer.setCenter("第"+footer.page()+"页,共"+footer.numPages()+"页");//设置页脚
+		this.styles = createStyles(wb);
+		// Create title
+		if (StringUtils.isNotBlank(title)){
+			Row titleRow = sheet.createRow(rownum++);
+			//设置标题行高
+			titleRow.setHeightInPoints((float)22.6);
+			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));
+		}
+		if (headerList == null){
+			throw new RuntimeException("headerList not null!");
+		}
+		
+		Row row1 = sheet.createRow(rownum++);
+		row1.setHeightInPoints((float)22.6);
+		Cell cell2 = row1.createCell(0);
+		cell2.setCellStyle(styles.get("subTile"));
+		cell2.setCellValue(subTile);
+		sheet.addMergedRegion(new CellRangeAddress(row1.getRowNum(),
+		        row1.getRowNum(), row1.getRowNum()-1, headerList.size()-1));
+        
+		Row headerRow = sheet.createRow(rownum++);
+		headerRow.setHeightInPoints((float)22.6);
+		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++) {
+		    String value = headerList.get(i);
+			if(ScoreExportParam.SPECIAL_KSMC.equals(value)){
+			    sheet.setColumnWidth(i, 10480);  //8cm
+			}
+			if(ScoreExportParam.SPECIAL_KCMC.equals(value) || ScoreExportParam.SPECIAL_YXXH.equals(value)){
+			    sheet.setColumnWidth(i, 3930);  //3cm
+            }
+			if(ScoreExportParam.SPECIAL_XSXM.equals(value) || ScoreExportParam.SPECIAL_KSCJ.equals(value)){
+			    sheet.setColumnWidth(i, 2090);  //1.6cm
+            }
+			if(ScoreExportParam.SPECIAL_XH.equals(value)){
+			    sheet.setColumnWidth(i, 1048);  //0.8cm
+            }
+	        
+		}
+		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("宋体");
+		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("宋体");
+		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.setAlignment(CellStyle.ALIGN_CENTER);
+		Font headerFont = wb.createFont();
+		headerFont.setFontName("宋体");
+		headerFont.setFontHeightInPoints((short) 10);
+		headerFont.setBoldweight(Font.BOLDWEIGHT_BOLD);
+		style.setFont(headerFont);
+		styles.put("header", style);
+		
+		style = wb.createCellStyle();
+        style.cloneStyleFrom(styles.get("title"));
+        Font subFont = wb.createFont();
+        subFont.setFontName("宋体");
+        subFont.setFontHeightInPoints((short) 14);
+        subFont.setBoldweight(Font.BOLDWEIGHT_BOLD);
+        style.setFont(subFont);
+        styles.put("subTile", 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> ExportExcel2 setDataList(List<E> list){
+		for (E e : list){
+			int colunm = 0;
+			Row row = this.addRow();
+			row.setHeightInPoints((float)22.6);//设置行高 0.8cm
+			StringBuilder sb = new StringBuilder();
+			for (Object[] os : annotationList){
+				ExcelField ef = (ExcelField)os[0];
+				Object val = null;
+				// Get entity value
+				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 + ", ");
+			}
+			log.debug("Write success: ["+row.getRowNum()+"] "+sb.toString());
+		}
+		return this;
+	}
+	
+	/**
+	 * 输出数据流
+	 * @param os 输出数据流
+	 */
+	public ExportExcel2 write(OutputStream os) throws IOException{
+		wb.write(os);
+		os.close();
+		return this;
+	}
+	
+	/**
+	 * 输出到客户端
+	 * @param fileName 输出文件名
+	 */
+	public ExportExcel2 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 ExportExcel2 writeFile(String name) throws FileNotFoundException, IOException{
+		FileOutputStream os = new FileOutputStream(name);
+		this.write(os);
+		return this;
+	}
+	
+	/**
+	 * 导出测试
+	 */
+//	public static void main(String[] args) throws Throwable {
+//		
+//		List<String> headerList = Lists.newArrayList();
+//		headerList.add("序号");
+//        headerList.add("考点名称");
+//        headerList.add("课程名称");
+//        headerList.add("院校学号");
+//        headerList.add("学生姓名");
+//        headerList.add("考试成绩");
+//		
+//		List<String> dataRowList = Lists.newArrayList();
+//		for (int i = 1; i <= headerList.size()-1; i++) {
+//		        dataRowList.add("数据"+i);
+//		}
+//		
+//		List<List<String>> dataList = Lists.newArrayList();
+//		for (int i = 1; i <=20; i++) {
+//			dataList.add(dataRowList);
+//		}
+//
+//		ExportExcel2 ee = new ExportExcel2("[考试批次名称]成绩单","负责教师签字:_______________ 交回日期:_______________", headerList);
+//		
+//		for (int i = 0; i < dataList.size(); i++) {
+//			Row row = ee.addRow();
+//			row.setHeightInPoints((float)22.6);
+//			ee.addCell(row, 0, i);
+//			for (int j = 0;j < dataList.get(i).size(); j++) {
+//			        ee.addCell(row, j+1, dataList.get(i).get(j));
+//			}
+//		}
+//		
+//		ee.writeFile("target/export.xls");
+//
+//		log.debug("Export success.");
+//		
+//	}
+
+}

+ 20 - 0
stmms-web/src/main/java/cn/com/qmth/stmms/common/utils/ScoreExportParam.java

@@ -0,0 +1,20 @@
+package cn.com.qmth.stmms.common.utils;
+
+
+public class ScoreExportParam {
+    public static final double SHEET_BOTTOMMARGIN = 0.75; //页边距(下)相当于 1.9cm
+    public static final double SHEET_LEFTMARGIN= 0.24;// 页边距(左)    相当于  0.6cm
+    public static final double SHEET_RIGHTMARGIN= 0.24;// 页边距(右) 相当于  0.6cm
+    public static final double SHEET_TOPMARGIN= 0.75;// 页边距(上) 相当于 1.9cm
+    public static final double SHEET_HEADERMARGIN= 0.32;// 页眉边距  相当于 0.8cm
+    public static final double SHEET_FOOTERMARGIN=0.32;// 页脚边距   相当于 0.8cm
+    
+    
+    public static final String SPECIAL_KSMC="考点名称";
+    public static final String SPECIAL_KCMC="课程名称";
+    public static final String SPECIAL_YXXH="院校学号";
+    public static final String SPECIAL_XSXM="学生姓名";
+    public static final String SPECIAL_KSCJ="考试成绩";
+    public static final String SPECIAL_XH="序号";
+
+}

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

@@ -34,17 +34,35 @@
 					</c:forEach>
 				</c:if>
 			</select>
+			<label>评卷账号</label>
+			<input type="text" name="markLogin" value="${query.markLogin}"  maxlength="20" class="input-mini"/>
+			<label>评卷姓名</label>
+			<input type="text" name="markName" value="${query.markName}"  maxlength="20" class="input-mini"/>
+			<br/><br/>
 			<label>筛选</label>
 			<select class="input-medium" name="filter">
 				<option value="0">无</option>
 				<option value="1" <c:if test="${filter==1}">selected</c:if>>客观0分,主观有分</option>
 				<option value="2" <c:if test="${filter==2}">selected</c:if>>客观有分,主观0分</option>
 			</select>
+			<label>总分:从</label>
+			<input  type="text" number="true" name="startScroe"value="${query.startScroe}"  maxlength="5" class="input-mini"/>
+			<label> 到&nbsp;&nbsp;&nbsp;</label>
+			<input type="text" max="100" number="true" name="endScroe" value="${query.endScroe}"  maxlength="5" class="input-mini"/>
+			 
 			<br/><br/>
 			<input id="btnSubmit" class="btn btn-primary" type="button" value="查询" onclick="goSearch()"/>
 			&nbsp;
 			<c:if test="${web_user.type.value==0 || web_user.type.value==5}">
-			<input id="export-button" class="btn" type="button" value="导出" onclick="goExport()"/>
+			<div class="btn-group">
+				<a class="btn dropdown-toggle" data-toggle="dropdown" href="#">
+					导出<span class="caret"></span>
+				</a>
+				<ul class="dropdown-menu">
+					<li><a href="##" onclick="goExport()">列表导出</a></li>
+					<li><a href="##" onclick="goExportScore()">成绩导出</a></li>
+				</ul>
+			</div>
 			</c:if>
 			&nbsp;
 			<c:if test="${exam.status.value==0 && web_user.type.value==0}">
@@ -69,6 +87,8 @@
 				<th>客观总分</th>
 				<th>主观总分</th>
 				<th>试卷总分</th>
+				<th>阅卷账号</th>
+				<th>阅卷姓名</th>
 				<th>查看图片</th>
 			</tr>
 		</thead>
@@ -86,6 +106,8 @@
 				<td>${student.objectiveScoreString}</td>
 				<td>${student.subjectiveScoreString}</td>
 				<td>${student.totalScoreString}</td>
+				<td>${student.markLogin}</td>
+				<td>${student.markName}</td>
 				<td>
 					<a class="sheet-link" href="##" data-sheet-url="${student.sheetUrlString}" data-answer-url="<c:if test="${student.answerUrl!=null}">${cardServer}${student.answerUrl}</c:if>" data-title="${student.examNumber}&nbsp;&nbsp;${student.name}&nbsp;&nbsp;客观总分${student.objectiveScoreString}&nbsp;&nbsp;主观总分${student.subjectiveScoreString}&nbsp;&nbsp;全卷总分${student.totalScoreString}">原图</a>
 					<!--  
@@ -111,6 +133,7 @@
 	<%@include file="/WEB-INF/views/include/imageView.jsp" %>
 <script type="text/javascript">
 $(document).ready(function() {
+	$("#searchForm").validate();
     /* new jBox('Image', {
     	imageFade: 0,
     	delayOpen: 0,
@@ -164,6 +187,10 @@ function goExport(){
 	$("#searchForm").attr('action','${ctx}/admin/exam/score/export');
 	$("#searchForm").submit();
 }
+function goExportScore(){
+	$("#searchForm").attr('action','${ctx}/admin/exam/score/exportScore');
+	$("#searchForm").submit();
+}
 </script>	
 </body>
 </html>

+ 1 - 1
stmms-web/src/main/webapp/static/mark-track/js/modules/mark-board.js

@@ -7,7 +7,7 @@ var mark_board = function(option, success) {
 
 function MarkBoard(option) {
 	this.markControl = option.markControl;
-	this.timeoutSecond = 0.4;
+	this.timeoutSecond = 0.2;
 	this.needConfirm = option.needConfirm === true ? true : false;
 	this.autoSubmit = option.autoSubmit === false ? false : true;
 	this.enableSkip = option.enableSkip === true ? true : false;