Browse Source

Merge remote-tracking branch 'origin/dev0410' into dev0410

宋悦 8 years ago
parent
commit
dd8262cf0e

+ 481 - 481
cqb-paper/src/main/java/com/qmth/cqb/paper/service/export/ExportPaperAbstractService.java

@@ -1,481 +1,481 @@
-package com.qmth.cqb.paper.service.export;
-
-import java.math.BigDecimal;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.stream.Collectors;
-
-import javax.servlet.http.HttpServletResponse;
-import javax.xml.bind.JAXBElement;
-
-import org.apache.commons.lang3.StringUtils;
-import org.docx4j.XmlUtils;
-import org.docx4j.jaxb.Context;
-import org.docx4j.openpackaging.packages.WordprocessingMLPackage;
-import org.docx4j.wml.Body;
-import org.docx4j.wml.P;
-import org.docx4j.wml.R;
-import org.docx4j.wml.Text;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Autowired;
-
-import cn.com.qmth.examcloud.common.dto.core.enums.CourseLevel;
-import cn.com.qmth.examcloud.common.dto.question.enums.QuesStructType;
-
-import com.qmth.cqb.paper.dao.PaperDetailRepo;
-import com.qmth.cqb.paper.dao.PaperDetailUnitRepo;
-import com.qmth.cqb.paper.dao.PaperRepo;
-import com.qmth.cqb.paper.dto.PaperDetailExp;
-import com.qmth.cqb.paper.dto.PaperDetailUnitExp;
-import com.qmth.cqb.paper.dto.PaperExp;
-import com.qmth.cqb.paper.model.Paper;
-import com.qmth.cqb.paper.model.PaperDetail;
-import com.qmth.cqb.paper.model.PaperDetailUnit;
-import com.qmth.cqb.paper.service.PaperService;
-import com.qmth.cqb.question.dao.QuesRepo;
-import com.qmth.cqb.question.model.QuesOption;
-import com.qmth.cqb.question.model.Question;
-import com.qmth.cqb.utils.BeanCopierUtil;
-import com.qmth.cqb.utils.CommonUtils;
-import com.qmth.cqb.utils.exception.PaperException;
-import com.qmth.cqb.utils.word.DocxProcessUtil;
-
-import freemarker.template.Configuration;
-import freemarker.template.Template;
-
-public abstract class ExportPaperAbstractService {
-	
-	private static final Logger logger = LoggerFactory.getLogger(ExportPaperAbstractService.class);
-
-	@Autowired
-	PaperRepo paperRepo;
-
-	@Autowired
-	PaperService paperService;
-
-	@Autowired
-	PaperDetailRepo paperDetailRepo;
-
-	@Autowired
-	PaperDetailUnitRepo paperDetailUnitRepo;
-
-	@Autowired
-	QuesRepo quesRepo;
-
-	private static final String FILL_BLANK_QUESTION_FLAG = "###";
-
-	public static Configuration CONFIGURATION;
-
-	public static final String ENCODING = "UTF-8";
-
-	//陕西师范模板
-	protected static Template SXSF_TEMPLATE_PAPER;
-	protected static Template SXSF_TEMPLATE_ANSWER;
-	//电子科大模板
-	protected static Template DZKD_TEMPLATE_PAPER;
-	protected static Template DZKD_TEMPLATE_ANSWER;
-	//石油大学模板
-	//protected static Template SYDX_TEMPLATE_NORMAL;
-
-	static {
-		try {
-			CONFIGURATION = new Configuration(Configuration.VERSION_2_3_25);
-			// 设置编码
-			CONFIGURATION.setDefaultEncoding(ENCODING);
-			// 设置ftl模板路径
-			CONFIGURATION.setClassForTemplateLoading(DocxProcessUtil.class, "/");
-			
-			SXSF_TEMPLATE_PAPER = CONFIGURATION.getTemplate("sxsf_paper_template.ftl", ENCODING);
-			SXSF_TEMPLATE_ANSWER = CONFIGURATION.getTemplate("sxsf_answer_template.ftl", ENCODING);
-			
-			DZKD_TEMPLATE_PAPER = CONFIGURATION.getTemplate("dzkd_paper_template.ftl", ENCODING);
-			DZKD_TEMPLATE_ANSWER = CONFIGURATION.getTemplate("dzkd_answer_template.ftl", ENCODING);
-			
-			//SYDX_TEMPLATE_NORMAL = CONFIGURATION.getTemplate("paper_template.ftl", ENCODING);
-		} catch (Exception e) {
-			e.printStackTrace();
-		}
-	}
-	
-	/**
-	 * 下载试卷
-	 * @param id
-	 * @param response
-	 * @throws Exception
-	 */
-	public abstract void downloadPaper(String id, HttpServletResponse response)throws Exception;
-	
-	/**
-	 * 初始化导出试卷DTO
-	 * 
-	 * @param id
-	 * @return
-	 */
-	protected Map<String,Object> initExportPaper(String id) throws Exception {
-		// 创建返回Map
-		Map<String,Object> returnMap = new HashMap<String,Object>();
-		// 获取paper
-		Paper paper = paperRepo.findOne(id);
-		paperService.formatPaper(paper, null);
-		if (paper == null) {
-			throw new PaperException("该试卷不存在");
-		}
-		// 创建paperDto
-		PaperExp paperExp = BeanCopierUtil.copyProperties(paper, PaperExp.class);
-		paperExp.setCourseLevel(paper.getLevel()==null?CourseLevel.ALL.name():paper.getLevel().name());
-		List<PaperDetailExp> objectiveDetails = new ArrayList<PaperDetailExp>();// 客观题
-		List<PaperDetailExp> subjectiveDetails = new ArrayList<PaperDetailExp>();// 主观题
-		double objectiveScore = 0;
-		double subjectiveScore = 0;
-		paperExp.setTitle(CommonUtils.PAPER_TITLE);
-		paperExp.setSubTitle(CommonUtils.PAPER_SUB_TITLE);
-		// 获取大题
-		List<PaperDetail> paperDetails = paperDetailRepo.findByPaper(paper);
-		int objectNumber = 1;// 客观题大题序号
-		int objetcUnitSum = 0;
-		for (int i = 0; i < paperDetails.size(); i++) {
-			PaperDetailExp paperDetailExp = BeanCopierUtil.copyProperties(paperDetails.get(i), PaperDetailExp.class);
-			List<PaperDetailUnit> paperDetailUnits = paperDetailUnitRepo.findByPaperDetail(paperDetails.get(i));
-			// 把大题分类 :客观题和主观题
-			List<PaperDetailUnitExp> paperDetailUnitExps = BeanCopierUtil.copyPropertiesOfList(paperDetailUnits,PaperDetailUnitExp.class);
-			// 选择题,套题下选择题 选项顺序重新排列
-			paperService.reorderChoicequestionOption(paperDetailUnitExps);
-			paperDetailExp.setPaperDetailUnits(paperDetailUnitExps);
-			boolean hasTextAnswer = false;// 判断主观题
-			if (paperDetailUnits.get(0).getQuestionType() == QuesStructType.NESTED_ANSWER_QUESTION) {
-				for (Question ques : paperDetailUnits.get(0).getQuestion().getSubQuestions()) {
-					if (ques.getQuestionType() == QuesStructType.TEXT_ANSWER_QUESTION) {
-						hasTextAnswer = true;
-						break;
-					}
-				}
-			} else if (paperDetailUnits.get(0).getQuestionType() == QuesStructType.TEXT_ANSWER_QUESTION
-					 ||paperDetailUnits.get(0).getQuestionType() == QuesStructType.FILL_BLANK_QUESTION) {
-				hasTextAnswer = true;
-			}
-			if (hasTextAnswer) {
-				subjectiveDetails.add(paperDetailExp);
-				subjectiveScore += paperDetailExp.getScore();
-			} else {
-				objectiveDetails.add(paperDetailExp);
-				paperDetailExp.setNumber(objectNumber);
-				paperDetailExp.setCnNum(CommonUtils.toCHNum(objectNumber));
-				objectiveScore += paperDetailExp.getScore();
-				objetcUnitSum += paperDetailExp.getUnitCount();
-				objectNumber++;
-			}
-			setExpTitle(paperDetailExp);
-		}
-
-		paperExp.setObjectiveDetails(objectiveDetails);
-		paperExp.setSubjectiveDetails(subjectiveDetails);
-		paperExp.setObjectiveScore(objectiveScore);
-		paperExp.setSubjectiveScore(subjectiveScore);
-		if (objectiveDetails.size() > 0) {
-			setUnitExpNumber(objectiveDetails, 0);
-			setScore(objectiveDetails);
-		}
-		if (subjectiveDetails.size() > 0) {
-			for (PaperDetailExp subDetail : subjectiveDetails) {
-				subDetail.setNumber(objectNumber);
-				subDetail.setCnNum(CommonUtils.toCHNum(objectNumber));
-				objectNumber++;
-			}
-			setUnitExpNumber(subjectiveDetails, objetcUnitSum);
-			setScore(subjectiveDetails);
-		}
-		returnMap.put("paper", paperExp);
-		returnMap.put("fileName", paperExp.getName());
-
-		return returnMap;
-	}
-
-	protected void setExpTitle(PaperDetailExp paperDetailExp) {
-		String title = "";
-		String totalScore = BigDecimal.valueOf(paperDetailExp.getScore()).stripTrailingZeros().toPlainString();
-		String unitScore = BigDecimal.valueOf(paperDetailExp.getPaperDetailUnits().get(0).getScore()).stripTrailingZeros().toPlainString();
-		QuesStructType type = paperDetailExp.getPaperDetailUnits().get(0).getQuestionType();
-		String scoreString = checkPaperDetailUnitScore(paperDetailExp) ? "每小题"+ unitScore + "分" : "";
-		if (type == QuesStructType.SINGLE_ANSWER_QUESTION) {
-			paperDetailExp.setName("单项选择题");
-			title = "(本大题共" + paperDetailExp.getUnitCount() + "小题,"
-					+ scoreString + "共" + totalScore + "分)。"
-					+ "在每小题列出的四个备选中只有一个符合题目要求的,请将其选出并将“答题卡”的相应代码涂黑,错涂、多涂或未涂均无分";
-		} else if (type == QuesStructType.BOOL_ANSWER_QUESTION) {
-			paperDetailExp.setName("判断题");
-			title = "(本大题共" + paperDetailExp.getUnitCount() + "小题,"+ scoreString + "共" + totalScore+ "分。正确的填涂A、错误填涂B。错涂、多涂或未涂均无分)";
-		} else if (type == QuesStructType.FILL_BLANK_QUESTION) {
-			paperDetailExp.setName("填空题");
-			int blankNum = 0;
-			for (PaperDetailUnitExp unit:paperDetailExp.getPaperDetailUnits()){
-				String tempStr = unit.getQuestion().getQuesBody().replaceAll(FILL_BLANK_QUESTION_FLAG, "");
-				int lenTimes = (unit.getQuestion().getQuesBody().length() - tempStr.length()) / FILL_BLANK_QUESTION_FLAG.length();// 出现的次数
-				blankNum += lenTimes;
-			}
-			title = "(本大题共"+blankNum+"个空格,将每空答在答题卡 “1—" +blankNum+"”相应的序号上。"+"共"+totalScore + "分)";
-		} else {
-			title = "(本大题共"+paperDetailExp.getUnitCount()+"小题,"+scoreString+"共"+totalScore+"分)";
-		}
-		paperDetailExp.setTitle(title);
-	}
-
-	/**
-	 * 校验大题下的小题分数是不是一样
-	 * 
-	 * @param paperDetailExp
-	 * @return
-	 */
-	protected boolean checkPaperDetailUnitScore(PaperDetailExp paperDetailExp) {
-		List<PaperDetailUnitExp> paperDetailUnitExps = paperDetailExp.getPaperDetailUnits();
-		Set<Double> scoreSet = new HashSet<Double>();
-		for (PaperDetailUnitExp unitExp : paperDetailUnitExps) {
-			scoreSet.add(unitExp.getScore());
-		}
-		return scoreSet.size() == 1;
-	}
-
-	protected void setUnitExpNumber(List<PaperDetailExp> paperDetails,int startIndxt) throws Exception {
-		int subNum = startIndxt;
-		for (PaperDetailExp paperDetail : paperDetails) {
-			for (PaperDetailUnitExp paperDetailUnit : paperDetail.getPaperDetailUnits()) {
-				List<QuesOption> optionList = paperDetailUnit.getQuestion().getQuesOptions();
-				if (optionList != null && optionList.size() > 0) {
-					int index = 0;
-					for (QuesOption quesOption : optionList) {
-						quesOption.setOptionBodyWord(setOptionNum(quesOption.getOptionBodyWord(),getOptionNum(index)));
-						index++;
-					}
-				}
-				List<Question> subQuesList = paperDetailUnit.getQuestion().getSubQuestions();
-				Question question = paperDetailUnit.getQuestion();
-				// 套题序号
-				if (subQuesList != null && subQuesList.size() > 0) {
-					question.setQuesBodyWord(replaceQuesBlank(question.getQuesBodyWord(),subNum + 1));
-					for (Question subQues : subQuesList) {
-						int curSubNum = ++subNum;
-						subQues.setQuesBodyWord(setSubQuesNum(subQues.getQuesBodyWord(),curSubNum));
-						subQues.setQuesAnswerWord(setSubQuesNum(subQues.getQuesAnswerWord(),curSubNum));
-						subQues.setQuesBodyWord(replaceQuesBlank(subQues.getQuesBodyWord(),curSubNum));
-						List<QuesOption> subOptionList = subQues.getQuesOptions();
-						if (subOptionList != null && subOptionList.size() > 0) {
-							int sub_index = 0;
-							for (QuesOption quesOption : subOptionList) {
-								quesOption.setOptionBodyWord(setOptionNum(quesOption.getOptionBodyWord(),getOptionNum(sub_index)));
-								sub_index++;
-							}
-						}
-					}
-				} else {
-					int curSubNum = ++subNum;
-					question.setQuesBodyWord(setSubQuesNum(question.getQuesBodyWord(), curSubNum));
-					question.setQuesAnswerWord(setSubQuesNum(question.getQuesAnswerWord(),curSubNum));
-					question.setQuesBodyWord(replaceQuesBlank(question.getQuesBodyWord(),curSubNum));
-				}
-			}
-		}
-	}
-	
-	/**
-     * 替换填空
-     * 将###替换为下划线_______
-     * @param wordMl
-     * @param num
-     * @return
-     * @throws Exception
-     */
-	protected String replaceQuesBlank(String wordMl,int num) throws Exception {
-        String tmpStr = DocxProcessUtil.BODY_HEADER + wordMl + DocxProcessUtil.BODY_TAIL;
-        Body body = (Body)XmlUtils.unmarshalString(tmpStr,Context.jc,Body.class);
-        List<Object> pList = body.getContent();
-        int index = 0;
-        int cur = 0;
-        Map<Integer,String> curMap = new HashMap<Integer,String>();
-        for(Object pObj:pList){
-            if(pObj.getClass().equals(P.class)){
-                List<Object> pContent = ((P)pObj).getContent();
-                for(Object rObj:pContent){
-                    if(rObj.getClass().equals(R.class)){
-                        List<Object> rContent = ((R)rObj).getContent();
-                        for(Object tObj:rContent){
-                            if (tObj instanceof JAXBElement)
-                                tObj = ((JAXBElement<?>) tObj).getValue();
-                            if(tObj.getClass().equals(Text.class)){
-                                Text text = (Text)tObj;
-                                String str = text.getValue().trim();
-                                if(str.equals("###")){
-                                    text.setValue("______");
-                                }else if(str.equals("(###)")){
-                                	text.setValue("(______)");
-                                }else if(str.equals("(###)")){
-                                	text.setValue("(______)");
-                                }else if(str.matches("##\\d{1,}##")){
-                                    int curNum = num + index;
-                                    text.setValue("___"+(curNum)+"___");
-                                    index++;
-                                }else if(str.startsWith("#") || str.equals("___")){
-                                    curMap.put(cur,str);
-                                    text.setValue("");
-                                }else if(str.matches("^\\d{1,}$")){
-                                    String preStr = curMap.get(cur - 1);
-                                    if(!StringUtils.isEmpty(preStr) && preStr.startsWith("#")){
-                                        int curNum = num + index;
-                                        text.setValue("___"+(curNum)+"___");
-                                        index++;
-                                    }
-                                }
-                                cur++;
-                            }
-                        }
-                    }
-                }
-            }
-        }
-        StringBuffer pWordMl = new StringBuffer();
-        for(Object pObj:pList){
-            if(pObj instanceof P){
-                pWordMl.append(DocxProcessUtil.formatPWordMl(XmlUtils.marshaltoString(pObj)));
-            }
-        }
-        return pWordMl.toString();
-    }
-	
-    public String getOptionNum(int number){
-        char optionNum = (char)(65 + number);
-        return String.valueOf(optionNum);
-    }
-
-    /**
-     * 获取当前试卷下所有试题WordPkg
-     * @param id
-     * @return
-     */
-    public List<WordprocessingMLPackage> getPkgList(String id){
-        Paper paper = paperRepo.findOne(id);
-        List<WordprocessingMLPackage> wordMLPackages = paperDetailUnitRepo.findByPaper(paper)
-                .stream().map(PaperDetailUnit::getQuestion).collect(Collectors.toList())
-                .stream().map(Question::getPkgObj).collect(Collectors.toList());
-        return wordMLPackages;
-    }
-
-    /**
-     * 设置题号
-     * @param quesBodyWordMl
-     * @param num
-     * @return
-     * @throws Exception
-     */
-    public String setSubQuesNum(String quesBodyWordMl,int num) throws Exception {
-        String tmpStr = DocxProcessUtil.BODY_HEADER + quesBodyWordMl + DocxProcessUtil.BODY_TAIL;
-        Body body = (Body)XmlUtils.unmarshalString(tmpStr,Context.jc,Body.class);
-        List<Object> pList = body.getContent();
-        int index = 0;
-        for(Object pObj:pList){
-            if(index > 0){
-                break;
-            }
-            P p = (P) pObj;
-            List<Object> pContent = p.getContent();
-            R run = new R();
-            Text text = new Text();
-            text.setValue(num+". ");
-            run.getContent().add(text);
-            pContent.add(0,run);
-            index++;
-        }
-        StringBuffer pWordMl = new StringBuffer();
-        for(Object pObj:pList){
-            if(pObj instanceof P){
-                pWordMl.append(DocxProcessUtil.formatPWordMl(XmlUtils.marshaltoString(pObj)));
-            }
-        }
-        return pWordMl.toString();
-    }
-
-    /**
-     * 设置选项号
-     * @param optionWordMl
-     * @param num
-     * @return
-     * @throws Exception
-     */
-    public String setOptionNum(String optionWordMl,String num) throws Exception {
-        String tmpStr = DocxProcessUtil.BODY_HEADER + optionWordMl + DocxProcessUtil.BODY_TAIL;
-        Body body = (Body)XmlUtils.unmarshalString(tmpStr,Context.jc,Body.class);
-        List<Object> pList = body.getContent();
-        int index = 0;
-        for(Object pObj:pList){
-            if(index > 0){
-                break;
-            }
-            P p = (P) pObj;
-            List<Object> pContent = p.getContent();
-            R run = new R();
-            Text text = new Text();
-            text.setValue(num+". ");
-            run.getContent().add(text);
-            pContent.add(0,run);
-            index++;
-        }
-        StringBuffer pWordMl = new StringBuffer();
-        for(Object pObj:pList){
-            if(pObj instanceof P){
-                pWordMl.append(DocxProcessUtil.formatPWordMl(XmlUtils.marshaltoString(pObj)));
-            }
-        }
-        return pWordMl.toString();
-    }
-    
-    /**
-     * 当大题下小题分数不是全部一样时,在小题题干后面加上小题的分数
-     * @param details
-     * @throws Exception
-     */
-    protected void setScore(List<PaperDetailExp> details) throws Exception{
-    	for(PaperDetailExp paperDetailExp:details){
-    		if(!checkPaperDetailUnitScore(paperDetailExp)){
-    			for(PaperDetailUnitExp paperDetailUnit:paperDetailExp.getPaperDetailUnits()){
-    				Question question = paperDetailUnit.getQuestion();
-    				String questionBodyWord = appendScoreToQuestionBody(question.getQuesBodyWord(),paperDetailUnit.getScore());
-    				question.setQuesBodyWord(questionBodyWord);
-    			}
-    		}
-    	}
-    }
-    
-    /**
-     * 在题干上设置分数
-     * @throws Exception 
-     */
-    protected String appendScoreToQuestionBody(String quesBodyWordMl,double score) throws Exception{
-    	String tmpStr = DocxProcessUtil.BODY_HEADER + quesBodyWordMl + DocxProcessUtil.BODY_TAIL;
-        Body body = (Body)XmlUtils.unmarshalString(tmpStr,Context.jc,Body.class);
-        List<Object> pList = body.getContent();
-        int index = 0;
-        for(Object pObj:pList){
-            if(index < pList.size()-1){
-                break;
-            }
-            P p = (P) pObj;
-            List<Object> pContent = p.getContent();
-            R run = new R();
-            Text text = new Text();
-            int scoreInt = (int)score;
-            text.setValue("("+scoreInt+"分)");
-            run.getContent().add(text);
-            pContent.add(run);
-            index++;
-        }
-        StringBuffer pWordMl = new StringBuffer();
-        for(Object pObj:pList){
-            if(pObj instanceof P){
-                pWordMl.append(DocxProcessUtil.formatPWordMl(XmlUtils.marshaltoString(pObj)));
-            }
-        }
-        return pWordMl.toString();
-    }
-}
+package com.qmth.cqb.paper.service.export;
+
+import java.math.BigDecimal;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+import javax.servlet.http.HttpServletResponse;
+import javax.xml.bind.JAXBElement;
+
+import org.apache.commons.lang3.StringUtils;
+import org.docx4j.XmlUtils;
+import org.docx4j.jaxb.Context;
+import org.docx4j.openpackaging.packages.WordprocessingMLPackage;
+import org.docx4j.wml.Body;
+import org.docx4j.wml.P;
+import org.docx4j.wml.R;
+import org.docx4j.wml.Text;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+
+import cn.com.qmth.examcloud.common.dto.core.enums.CourseLevel;
+import cn.com.qmth.examcloud.common.dto.question.enums.QuesStructType;
+
+import com.qmth.cqb.paper.dao.PaperDetailRepo;
+import com.qmth.cqb.paper.dao.PaperDetailUnitRepo;
+import com.qmth.cqb.paper.dao.PaperRepo;
+import com.qmth.cqb.paper.dto.PaperDetailExp;
+import com.qmth.cqb.paper.dto.PaperDetailUnitExp;
+import com.qmth.cqb.paper.dto.PaperExp;
+import com.qmth.cqb.paper.model.Paper;
+import com.qmth.cqb.paper.model.PaperDetail;
+import com.qmth.cqb.paper.model.PaperDetailUnit;
+import com.qmth.cqb.paper.service.PaperService;
+import com.qmth.cqb.question.dao.QuesRepo;
+import com.qmth.cqb.question.model.QuesOption;
+import com.qmth.cqb.question.model.Question;
+import com.qmth.cqb.utils.BeanCopierUtil;
+import com.qmth.cqb.utils.CommonUtils;
+import com.qmth.cqb.utils.exception.PaperException;
+import com.qmth.cqb.utils.word.DocxProcessUtil;
+
+import freemarker.template.Configuration;
+import freemarker.template.Template;
+
+public abstract class ExportPaperAbstractService {
+	
+	private static final Logger logger = LoggerFactory.getLogger(ExportPaperAbstractService.class);
+
+	@Autowired
+	PaperRepo paperRepo;
+
+	@Autowired
+	PaperService paperService;
+
+	@Autowired
+	PaperDetailRepo paperDetailRepo;
+
+	@Autowired
+	PaperDetailUnitRepo paperDetailUnitRepo;
+
+	@Autowired
+	QuesRepo quesRepo;
+
+	private static final String FILL_BLANK_QUESTION_FLAG = "###";
+
+	public static Configuration CONFIGURATION;
+
+	public static final String ENCODING = "UTF-8";
+
+	//陕西师范模板
+	protected static Template SXSF_TEMPLATE_PAPER;
+	protected static Template SXSF_TEMPLATE_ANSWER;
+	//电子科大模板
+	protected static Template DZKD_TEMPLATE_PAPER;
+	protected static Template DZKD_TEMPLATE_ANSWER;
+	//石油大学模板
+	//protected static Template SYDX_TEMPLATE_NORMAL;
+
+	static {
+		try {
+			CONFIGURATION = new Configuration(Configuration.VERSION_2_3_25);
+			// 设置编码
+			CONFIGURATION.setDefaultEncoding(ENCODING);
+			// 设置ftl模板路径
+			CONFIGURATION.setClassForTemplateLoading(DocxProcessUtil.class, "/");
+			
+			SXSF_TEMPLATE_PAPER = CONFIGURATION.getTemplate("sxsf_paper_template.ftl", ENCODING);
+			SXSF_TEMPLATE_ANSWER = CONFIGURATION.getTemplate("sxsf_answer_template.ftl", ENCODING);
+			
+			DZKD_TEMPLATE_PAPER = CONFIGURATION.getTemplate("dzkd_paper_template.ftl", ENCODING);
+			DZKD_TEMPLATE_ANSWER = CONFIGURATION.getTemplate("dzkd_answer_template.ftl", ENCODING);
+			
+			//SYDX_TEMPLATE_NORMAL = CONFIGURATION.getTemplate("paper_template.ftl", ENCODING);
+		} catch (Exception e) {
+			e.printStackTrace();
+		}
+	}
+	
+	/**
+	 * 下载试卷
+	 * @param id
+	 * @param response
+	 * @throws Exception
+	 */
+	public abstract void downloadPaper(String paperId, HttpServletResponse response)throws Exception;
+	
+	/**
+	 * 初始化导出试卷DTO
+	 * 
+	 * @param id
+	 * @return
+	 */
+	protected Map<String,Object> initExportPaper(String paperId) throws Exception {
+		// 创建返回Map
+		Map<String,Object> returnMap = new HashMap<String,Object>();
+		// 获取paper
+		Paper paper = paperRepo.findOne(paperId);
+		paperService.formatPaper(paper, null);
+		if (paper == null) {
+			throw new PaperException("该试卷不存在");
+		}
+		// 创建paperDto
+		PaperExp paperExp = BeanCopierUtil.copyProperties(paper, PaperExp.class);
+		paperExp.setCourseLevel(paper.getLevel()==null?CourseLevel.ALL.name():paper.getLevel().name());
+		List<PaperDetailExp> objectiveDetails = new ArrayList<PaperDetailExp>();// 客观题
+		List<PaperDetailExp> subjectiveDetails = new ArrayList<PaperDetailExp>();// 主观题
+		double objectiveScore = 0;
+		double subjectiveScore = 0;
+		paperExp.setTitle(CommonUtils.PAPER_TITLE);
+		paperExp.setSubTitle(CommonUtils.PAPER_SUB_TITLE);
+		// 获取大题
+		List<PaperDetail> paperDetails = paperDetailRepo.findByPaper(paper);
+		int objectNumber = 1;// 客观题大题序号
+		int objetcUnitSum = 0;
+		for (int i = 0; i < paperDetails.size(); i++) {
+			PaperDetailExp paperDetailExp = BeanCopierUtil.copyProperties(paperDetails.get(i), PaperDetailExp.class);
+			List<PaperDetailUnit> paperDetailUnits = paperDetailUnitRepo.findByPaperDetail(paperDetails.get(i));
+			// 把大题分类 :客观题和主观题
+			List<PaperDetailUnitExp> paperDetailUnitExps = BeanCopierUtil.copyPropertiesOfList(paperDetailUnits,PaperDetailUnitExp.class);
+			// 选择题,套题下选择题 选项顺序重新排列
+			paperService.reorderChoicequestionOption(paperDetailUnitExps);
+			paperDetailExp.setPaperDetailUnits(paperDetailUnitExps);
+			boolean hasTextAnswer = false;// 判断主观题
+			if (paperDetailUnits.get(0).getQuestionType() == QuesStructType.NESTED_ANSWER_QUESTION) {
+				for (Question ques : paperDetailUnits.get(0).getQuestion().getSubQuestions()) {
+					if (ques.getQuestionType() == QuesStructType.TEXT_ANSWER_QUESTION) {
+						hasTextAnswer = true;
+						break;
+					}
+				}
+			} else if (paperDetailUnits.get(0).getQuestionType() == QuesStructType.TEXT_ANSWER_QUESTION
+					 ||paperDetailUnits.get(0).getQuestionType() == QuesStructType.FILL_BLANK_QUESTION) {
+				hasTextAnswer = true;
+			}
+			if (hasTextAnswer) {
+				subjectiveDetails.add(paperDetailExp);
+				subjectiveScore += paperDetailExp.getScore();
+			} else {
+				objectiveDetails.add(paperDetailExp);
+				paperDetailExp.setNumber(objectNumber);
+				paperDetailExp.setCnNum(CommonUtils.toCHNum(objectNumber));
+				objectiveScore += paperDetailExp.getScore();
+				objetcUnitSum += paperDetailExp.getUnitCount();
+				objectNumber++;
+			}
+			setExpTitle(paperDetailExp);
+		}
+
+		paperExp.setObjectiveDetails(objectiveDetails);
+		paperExp.setSubjectiveDetails(subjectiveDetails);
+		paperExp.setObjectiveScore(objectiveScore);
+		paperExp.setSubjectiveScore(subjectiveScore);
+		if (objectiveDetails.size() > 0) {
+			setUnitExpNumber(objectiveDetails, 0);
+			setScore(objectiveDetails);
+		}
+		if (subjectiveDetails.size() > 0) {
+			for (PaperDetailExp subDetail : subjectiveDetails) {
+				subDetail.setNumber(objectNumber);
+				subDetail.setCnNum(CommonUtils.toCHNum(objectNumber));
+				objectNumber++;
+			}
+			setUnitExpNumber(subjectiveDetails, objetcUnitSum);
+			setScore(subjectiveDetails);
+		}
+		returnMap.put("paper", paperExp);
+		returnMap.put("fileName", paperExp.getName());
+
+		return returnMap;
+	}
+
+	protected void setExpTitle(PaperDetailExp paperDetailExp) {
+		String title = "";
+		String totalScore = BigDecimal.valueOf(paperDetailExp.getScore()).stripTrailingZeros().toPlainString();
+		String unitScore = BigDecimal.valueOf(paperDetailExp.getPaperDetailUnits().get(0).getScore()).stripTrailingZeros().toPlainString();
+		QuesStructType type = paperDetailExp.getPaperDetailUnits().get(0).getQuestionType();
+		String scoreString = checkPaperDetailUnitScore(paperDetailExp) ? "每小题"+ unitScore + "分" : "";
+		if (type == QuesStructType.SINGLE_ANSWER_QUESTION) {
+			paperDetailExp.setName("单项选择题");
+			title = "(本大题共" + paperDetailExp.getUnitCount() + "小题,"
+					+ scoreString + "共" + totalScore + "分)。"
+					+ "在每小题列出的四个备选中只有一个符合题目要求的,请将其选出并将“答题卡”的相应代码涂黑,错涂、多涂或未涂均无分";
+		} else if (type == QuesStructType.BOOL_ANSWER_QUESTION) {
+			paperDetailExp.setName("判断题");
+			title = "(本大题共" + paperDetailExp.getUnitCount() + "小题,"+ scoreString + "共" + totalScore+ "分。正确的填涂A、错误填涂B。错涂、多涂或未涂均无分)";
+		} else if (type == QuesStructType.FILL_BLANK_QUESTION) {
+			paperDetailExp.setName("填空题");
+			int blankNum = 0;
+			for (PaperDetailUnitExp unit:paperDetailExp.getPaperDetailUnits()){
+				String tempStr = unit.getQuestion().getQuesBody().replaceAll(FILL_BLANK_QUESTION_FLAG, "");
+				int lenTimes = (unit.getQuestion().getQuesBody().length() - tempStr.length()) / FILL_BLANK_QUESTION_FLAG.length();// 出现的次数
+				blankNum += lenTimes;
+			}
+			title = "(本大题共"+blankNum+"个空格,将每空答在答题卡 “1—" +blankNum+"”相应的序号上。"+"共"+totalScore + "分)";
+		} else {
+			title = "(本大题共"+paperDetailExp.getUnitCount()+"小题,"+scoreString+"共"+totalScore+"分)";
+		}
+		paperDetailExp.setTitle(title);
+	}
+
+	/**
+	 * 校验大题下的小题分数是不是一样
+	 * 
+	 * @param paperDetailExp
+	 * @return
+	 */
+	protected boolean checkPaperDetailUnitScore(PaperDetailExp paperDetailExp) {
+		List<PaperDetailUnitExp> paperDetailUnitExps = paperDetailExp.getPaperDetailUnits();
+		Set<Double> scoreSet = new HashSet<Double>();
+		for (PaperDetailUnitExp unitExp : paperDetailUnitExps) {
+			scoreSet.add(unitExp.getScore());
+		}
+		return scoreSet.size() == 1;
+	}
+
+	protected void setUnitExpNumber(List<PaperDetailExp> paperDetails,int startIndxt) throws Exception {
+		int subNum = startIndxt;
+		for (PaperDetailExp paperDetail : paperDetails) {
+			for (PaperDetailUnitExp paperDetailUnit : paperDetail.getPaperDetailUnits()) {
+				List<QuesOption> optionList = paperDetailUnit.getQuestion().getQuesOptions();
+				if (optionList != null && optionList.size() > 0) {
+					int index = 0;
+					for (QuesOption quesOption : optionList) {
+						quesOption.setOptionBodyWord(setOptionNum(quesOption.getOptionBodyWord(),getOptionNum(index)));
+						index++;
+					}
+				}
+				List<Question> subQuesList = paperDetailUnit.getQuestion().getSubQuestions();
+				Question question = paperDetailUnit.getQuestion();
+				// 套题序号
+				if (subQuesList != null && subQuesList.size() > 0) {
+					question.setQuesBodyWord(replaceQuesBlank(question.getQuesBodyWord(),subNum + 1));
+					for (Question subQues : subQuesList) {
+						int curSubNum = ++subNum;
+						subQues.setQuesBodyWord(setSubQuesNum(subQues.getQuesBodyWord(),curSubNum));
+						subQues.setQuesAnswerWord(setSubQuesNum(subQues.getQuesAnswerWord(),curSubNum));
+						subQues.setQuesBodyWord(replaceQuesBlank(subQues.getQuesBodyWord(),curSubNum));
+						List<QuesOption> subOptionList = subQues.getQuesOptions();
+						if (subOptionList != null && subOptionList.size() > 0) {
+							int sub_index = 0;
+							for (QuesOption quesOption : subOptionList) {
+								quesOption.setOptionBodyWord(setOptionNum(quesOption.getOptionBodyWord(),getOptionNum(sub_index)));
+								sub_index++;
+							}
+						}
+					}
+				} else {
+					int curSubNum = ++subNum;
+					question.setQuesBodyWord(setSubQuesNum(question.getQuesBodyWord(), curSubNum));
+					question.setQuesAnswerWord(setSubQuesNum(question.getQuesAnswerWord(),curSubNum));
+					question.setQuesBodyWord(replaceQuesBlank(question.getQuesBodyWord(),curSubNum));
+				}
+			}
+		}
+	}
+	
+	/**
+     * 替换填空
+     * 将###替换为下划线_______
+     * @param wordMl
+     * @param num
+     * @return
+     * @throws Exception
+     */
+	protected String replaceQuesBlank(String wordMl,int num) throws Exception {
+        String tmpStr = DocxProcessUtil.BODY_HEADER + wordMl + DocxProcessUtil.BODY_TAIL;
+        Body body = (Body)XmlUtils.unmarshalString(tmpStr,Context.jc,Body.class);
+        List<Object> pList = body.getContent();
+        int index = 0;
+        int cur = 0;
+        Map<Integer,String> curMap = new HashMap<Integer,String>();
+        for(Object pObj:pList){
+            if(pObj.getClass().equals(P.class)){
+                List<Object> pContent = ((P)pObj).getContent();
+                for(Object rObj:pContent){
+                    if(rObj.getClass().equals(R.class)){
+                        List<Object> rContent = ((R)rObj).getContent();
+                        for(Object tObj:rContent){
+                            if (tObj instanceof JAXBElement)
+                                tObj = ((JAXBElement<?>) tObj).getValue();
+                            if(tObj.getClass().equals(Text.class)){
+                                Text text = (Text)tObj;
+                                String str = text.getValue().trim();
+                                if(str.equals("###")){
+                                    text.setValue("______");
+                                }else if(str.equals("(###)")){
+                                	text.setValue("(______)");
+                                }else if(str.equals("(###)")){
+                                	text.setValue("(______)");
+                                }else if(str.matches("##\\d{1,}##")){
+                                    int curNum = num + index;
+                                    text.setValue("___"+(curNum)+"___");
+                                    index++;
+                                }else if(str.startsWith("#") || str.equals("___")){
+                                    curMap.put(cur,str);
+                                    text.setValue("");
+                                }else if(str.matches("^\\d{1,}$")){
+                                    String preStr = curMap.get(cur - 1);
+                                    if(!StringUtils.isEmpty(preStr) && preStr.startsWith("#")){
+                                        int curNum = num + index;
+                                        text.setValue("___"+(curNum)+"___");
+                                        index++;
+                                    }
+                                }
+                                cur++;
+                            }
+                        }
+                    }
+                }
+            }
+        }
+        StringBuffer pWordMl = new StringBuffer();
+        for(Object pObj:pList){
+            if(pObj instanceof P){
+                pWordMl.append(DocxProcessUtil.formatPWordMl(XmlUtils.marshaltoString(pObj)));
+            }
+        }
+        return pWordMl.toString();
+    }
+	
+    public String getOptionNum(int number){
+        char optionNum = (char)(65 + number);
+        return String.valueOf(optionNum);
+    }
+
+    /**
+     * 获取当前试卷下所有试题WordPkg
+     * @param id
+     * @return
+     */
+    public List<WordprocessingMLPackage> getPkgList(String id){
+        Paper paper = paperRepo.findOne(id);
+        List<WordprocessingMLPackage> wordMLPackages = paperDetailUnitRepo.findByPaper(paper)
+                .stream().map(PaperDetailUnit::getQuestion).collect(Collectors.toList())
+                .stream().map(Question::getPkgObj).collect(Collectors.toList());
+        return wordMLPackages;
+    }
+
+    /**
+     * 设置题号
+     * @param quesBodyWordMl
+     * @param num
+     * @return
+     * @throws Exception
+     */
+    public String setSubQuesNum(String quesBodyWordMl,int num) throws Exception {
+        String tmpStr = DocxProcessUtil.BODY_HEADER + quesBodyWordMl + DocxProcessUtil.BODY_TAIL;
+        Body body = (Body)XmlUtils.unmarshalString(tmpStr,Context.jc,Body.class);
+        List<Object> pList = body.getContent();
+        int index = 0;
+        for(Object pObj:pList){
+            if(index > 0){
+                break;
+            }
+            P p = (P) pObj;
+            List<Object> pContent = p.getContent();
+            R run = new R();
+            Text text = new Text();
+            text.setValue(num+". ");
+            run.getContent().add(text);
+            pContent.add(0,run);
+            index++;
+        }
+        StringBuffer pWordMl = new StringBuffer();
+        for(Object pObj:pList){
+            if(pObj instanceof P){
+                pWordMl.append(DocxProcessUtil.formatPWordMl(XmlUtils.marshaltoString(pObj)));
+            }
+        }
+        return pWordMl.toString();
+    }
+
+    /**
+     * 设置选项号
+     * @param optionWordMl
+     * @param num
+     * @return
+     * @throws Exception
+     */
+    public String setOptionNum(String optionWordMl,String num) throws Exception {
+        String tmpStr = DocxProcessUtil.BODY_HEADER + optionWordMl + DocxProcessUtil.BODY_TAIL;
+        Body body = (Body)XmlUtils.unmarshalString(tmpStr,Context.jc,Body.class);
+        List<Object> pList = body.getContent();
+        int index = 0;
+        for(Object pObj:pList){
+            if(index > 0){
+                break;
+            }
+            P p = (P) pObj;
+            List<Object> pContent = p.getContent();
+            R run = new R();
+            Text text = new Text();
+            text.setValue(num+". ");
+            run.getContent().add(text);
+            pContent.add(0,run);
+            index++;
+        }
+        StringBuffer pWordMl = new StringBuffer();
+        for(Object pObj:pList){
+            if(pObj instanceof P){
+                pWordMl.append(DocxProcessUtil.formatPWordMl(XmlUtils.marshaltoString(pObj)));
+            }
+        }
+        return pWordMl.toString();
+    }
+    
+    /**
+     * 当大题下小题分数不是全部一样时,在小题题干后面加上小题的分数
+     * @param details
+     * @throws Exception
+     */
+    protected void setScore(List<PaperDetailExp> details) throws Exception{
+    	for(PaperDetailExp paperDetailExp:details){
+    		if(!checkPaperDetailUnitScore(paperDetailExp)){
+    			for(PaperDetailUnitExp paperDetailUnit:paperDetailExp.getPaperDetailUnits()){
+    				Question question = paperDetailUnit.getQuestion();
+    				String questionBodyWord = appendScoreToQuestionBody(question.getQuesBodyWord(),paperDetailUnit.getScore());
+    				question.setQuesBodyWord(questionBodyWord);
+    			}
+    		}
+    	}
+    }
+    
+    /**
+     * 在题干上设置分数
+     * @throws Exception 
+     */
+    protected String appendScoreToQuestionBody(String quesBodyWordMl,double score) throws Exception{
+    	String tmpStr = DocxProcessUtil.BODY_HEADER + quesBodyWordMl + DocxProcessUtil.BODY_TAIL;
+        Body body = (Body)XmlUtils.unmarshalString(tmpStr,Context.jc,Body.class);
+        List<Object> pList = body.getContent();
+        int index = 0;
+        for(Object pObj:pList){
+            if(index < pList.size()-1){
+                break;
+            }
+            P p = (P) pObj;
+            List<Object> pContent = p.getContent();
+            R run = new R();
+            Text text = new Text();
+            int scoreInt = (int)score;
+            text.setValue("("+scoreInt+"分)");
+            run.getContent().add(text);
+            pContent.add(run);
+            index++;
+        }
+        StringBuffer pWordMl = new StringBuffer();
+        for(Object pObj:pList){
+            if(pObj instanceof P){
+                pWordMl.append(DocxProcessUtil.formatPWordMl(XmlUtils.marshaltoString(pObj)));
+            }
+        }
+        return pWordMl.toString();
+    }
+}

+ 38 - 38
cqb-paper/src/main/java/com/qmth/cqb/paper/service/export/SxsfExportPaperService.java

@@ -1,38 +1,38 @@
-package com.qmth.cqb.paper.service.export;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-
-import javax.servlet.http.HttpServletResponse;
-import org.springframework.stereotype.Service;
-import com.qmth.cqb.utils.word.DocxProcessUtil;
-
-/**
- * @author  	chenken
- * @date    	2017年7月7日 上午11:29:49
- * @company 	QMTH
- * @description 陕西师范试卷导出service
- */
-@Service("sxsfExportPaperService")
-public class SxsfExportPaperService extends ExportPaperAbstractService {
-    
-    @Override
-    public void downloadPaper(String id, HttpServletResponse response) throws Exception {
-        Map<String,Object> dataMap = initExportPaper(id);
-        List<String> fileList = new ArrayList<String>();
-        if (dataMap.get("fileName") != null) {
-            String paperfileName = (String) dataMap.get("fileName");
-            String answerFileName = paperfileName+"__答案";
-            DocxProcessUtil.exportPaper(dataMap, paperfileName,SXSF_TEMPLATE_PAPER);
-            DocxProcessUtil.exportAnswer(dataMap,answerFileName,SXSF_TEMPLATE_ANSWER);
-            DocxProcessUtil.processImage(paperfileName,getPkgList(id));
-            DocxProcessUtil.processImage(answerFileName,getPkgList(id));
-            fileList.add(paperfileName);
-            fileList.add(answerFileName);
-            DocxProcessUtil.processDownload(fileList, response);
-        }
-    }
-
-}
-
+package com.qmth.cqb.paper.service.export;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import javax.servlet.http.HttpServletResponse;
+import org.springframework.stereotype.Service;
+import com.qmth.cqb.utils.word.DocxProcessUtil;
+
+/**
+ * @author  	chenken
+ * @date    	2017年7月7日 上午11:29:49
+ * @company 	QMTH
+ * @description 陕西师范试卷导出service
+ */
+@Service("sxsfExportPaperService")
+public class SxsfExportPaperService extends ExportPaperAbstractService {
+    
+    @Override
+    public void downloadPaper(String paperId, HttpServletResponse response) throws Exception {
+        Map<String,Object> dataMap = initExportPaper(paperId);
+        List<String> fileList = new ArrayList<String>();
+        if (dataMap.get("fileName") != null) {
+            String paperfileName = (String) dataMap.get("fileName");
+            String answerFileName = paperfileName+"__答案";
+            DocxProcessUtil.exportPaper(dataMap, paperfileName,SXSF_TEMPLATE_PAPER);
+            DocxProcessUtil.exportAnswer(dataMap,answerFileName,SXSF_TEMPLATE_ANSWER);
+            DocxProcessUtil.processImage(paperfileName,getPkgList(paperId));
+            DocxProcessUtil.processImage(answerFileName,getPkgList(paperId));
+            fileList.add(paperfileName);
+            fileList.add(answerFileName);
+            DocxProcessUtil.processDownload(fileList, response);
+        }
+    }
+
+}
+