|
@@ -6,15 +6,28 @@ import java.io.FileOutputStream;
|
|
import java.io.IOException;
|
|
import java.io.IOException;
|
|
import java.math.BigDecimal;
|
|
import java.math.BigDecimal;
|
|
import java.util.ArrayList;
|
|
import java.util.ArrayList;
|
|
|
|
+import java.util.HashMap;
|
|
import java.util.HashSet;
|
|
import java.util.HashSet;
|
|
import java.util.List;
|
|
import java.util.List;
|
|
|
|
+import java.util.Map;
|
|
import java.util.Set;
|
|
import java.util.Set;
|
|
|
|
+import java.util.regex.Matcher;
|
|
|
|
+import java.util.regex.Pattern;
|
|
import java.util.stream.Collectors;
|
|
import java.util.stream.Collectors;
|
|
|
|
|
|
|
|
+import javax.xml.bind.JAXBElement;
|
|
|
|
+
|
|
import main.java.com.UpYun;
|
|
import main.java.com.UpYun;
|
|
|
|
|
|
import org.apache.commons.io.FileUtils;
|
|
import org.apache.commons.io.FileUtils;
|
|
|
|
+import org.apache.commons.lang3.StringUtils;
|
|
|
|
+import org.docx4j.XmlUtils;
|
|
|
|
+import org.docx4j.jaxb.Context;
|
|
import org.docx4j.openpackaging.packages.WordprocessingMLPackage;
|
|
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.springframework.beans.factory.annotation.Autowired;
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
import org.springframework.beans.factory.annotation.Value;
|
|
import org.springframework.beans.factory.annotation.Value;
|
|
import org.springframework.data.domain.Example;
|
|
import org.springframework.data.domain.Example;
|
|
@@ -51,6 +64,7 @@ import com.qmth.cqb.paper.service.ExamFileService;
|
|
import com.qmth.cqb.paper.service.PaperDetailService;
|
|
import com.qmth.cqb.paper.service.PaperDetailService;
|
|
import com.qmth.cqb.paper.service.PaperService;
|
|
import com.qmth.cqb.paper.service.PaperService;
|
|
import com.qmth.cqb.question.dao.QuesRepo;
|
|
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.question.model.Question;
|
|
import com.qmth.cqb.question.model.QuestionAudio;
|
|
import com.qmth.cqb.question.model.QuestionAudio;
|
|
import com.qmth.cqb.question.service.QuestionAudioService;
|
|
import com.qmth.cqb.question.service.QuestionAudioService;
|
|
@@ -235,10 +249,317 @@ public abstract class ExportPaperAbstractService {
|
|
|
|
|
|
public PaperExp initPaperExp(String paperId) throws Exception{
|
|
public PaperExp initPaperExp(String paperId) throws Exception{
|
|
PaperExp paperExp = initPaperExpService.initPaperExp(paperId);
|
|
PaperExp paperExp = initPaperExpService.initPaperExp(paperId);
|
|
|
|
+ //给新的大题下所有小题排序
|
|
|
|
+ sortPaperDetailUnitExps(paperExp.getPaperDetails());
|
|
|
|
+ //如果每个小题分数不一样,题干后面添加分数
|
|
|
|
+ appendScoreToQuestionBody(paperExp.getPaperDetails());
|
|
|
|
+ //给每个小题选项排序
|
|
|
|
+ setUnitExpNumber(paperExp.getPaperDetails());
|
|
setExpDtoTitle(paperExp.getPaperDetails());
|
|
setExpDtoTitle(paperExp.getPaperDetails());
|
|
return paperExp;
|
|
return paperExp;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ /**
|
|
|
|
+ * 设置选项号
|
|
|
|
+ * @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();
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 将数字1,2,3,4转化成A,B,C,D
|
|
|
|
+ * @param number
|
|
|
|
+ * @return
|
|
|
|
+ */
|
|
|
|
+ public String getOptionNum(int number){
|
|
|
|
+ char optionNum = (char)(65 + number);
|
|
|
|
+ return String.valueOf(optionNum);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 替换填空
|
|
|
|
+ * 将###替换为下划线_______
|
|
|
|
+ * @param wordMl
|
|
|
|
+ * @param num
|
|
|
|
+ * @return
|
|
|
|
+ * @throws Exception
|
|
|
|
+ */
|
|
|
|
+ public 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();
|
|
|
|
+ //1
|
|
|
|
+ str = str.replaceAll("###","______");
|
|
|
|
+ text.setValue(str);
|
|
|
|
+ //2
|
|
|
|
+ Pattern pattern = Pattern.compile("##\\d{1,}##");
|
|
|
|
+ Matcher m = pattern.matcher(str);
|
|
|
|
+ while(m.find()){
|
|
|
|
+ int curNum = num + index;
|
|
|
|
+ String a = m.group();
|
|
|
|
+ str = str.replaceAll(a, "___"+(curNum)+"___");
|
|
|
|
+ text.setValue(str);
|
|
|
|
+ index++;
|
|
|
|
+ }
|
|
|
|
+ //3
|
|
|
|
+ if(str.startsWith("#") || str.equals("___")){
|
|
|
|
+ curMap.put(cur,str);
|
|
|
|
+ text.setValue("");
|
|
|
|
+ }
|
|
|
|
+ //4
|
|
|
|
+ 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();
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 设置题号
|
|
|
|
+ * @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 paperDetails
|
|
|
|
+ * @param startIndxt
|
|
|
|
+ * @throws Exception
|
|
|
|
+ */
|
|
|
|
+ public void setUnitExpNumber(List<PaperDetailExp> paperDetails) throws Exception {
|
|
|
|
+ for (PaperDetailExp paperDetail : paperDetails) {
|
|
|
|
+ List<PaperDetailUnitExp> paperDetailUnitExpList = paperDetail.getPaperDetailUnits();
|
|
|
|
+ for (PaperDetailUnitExp paperDetailUnit:paperDetailUnitExpList) {
|
|
|
|
+ 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(),subQuesList.get(0).getNumber()));
|
|
|
|
+ for (Question subQues : subQuesList) {
|
|
|
|
+ subQues.setQuesBodyWord(setSubQuesNum(subQues.getQuesBodyWord(),subQues.getNumber()));
|
|
|
|
+ subQues.setQuesAnswerWord(setSubQuesNum(subQues.getQuesAnswerWord(),subQues.getNumber()));
|
|
|
|
+ subQues.setQuesBodyWord(replaceQuesBlank(subQues.getQuesBodyWord(),subQues.getNumber()));
|
|
|
|
+ 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 {
|
|
|
|
+ question.setQuesBodyWord(setSubQuesNum(question.getQuesBodyWord(), paperDetailUnit.getNumber()));
|
|
|
|
+ question.setQuesAnswerWord(setSubQuesNum(question.getQuesAnswerWord(),paperDetailUnit.getNumber()));
|
|
|
|
+ question.setQuesBodyWord(replaceQuesBlank(question.getQuesBodyWord(),paperDetailUnit.getNumber()));
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 在题干上设置分数
|
|
|
|
+ * @throws Exception
|
|
|
|
+ */
|
|
|
|
+ public 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();
|
|
|
|
+ text.setValue("("+score+"分)");
|
|
|
|
+ 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();
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 当大题下小题分数不是全部一样时,在小题题干后面加上小题的分数
|
|
|
|
+ * @param details
|
|
|
|
+ * @throws Exception
|
|
|
|
+ */
|
|
|
|
+ public void appendScoreToQuestionBody(List<PaperDetailExp> details) throws Exception{
|
|
|
|
+ for(PaperDetailExp paperDetailExp:details){
|
|
|
|
+ if(checkPaperDetailUnitScore(paperDetailExp)==null){
|
|
|
|
+ for(PaperDetailUnitExp paperDetailUnit:paperDetailExp.getPaperDetailUnits()){
|
|
|
|
+ //判断小题是否为套题
|
|
|
|
+ if(paperDetailUnit.getQuestionType() == QuesStructType.NESTED_ANSWER_QUESTION){
|
|
|
|
+ List<Question> subQuestions = paperDetailUnit.getQuestion().getSubQuestions();
|
|
|
|
+ for(Question subQuestion:subQuestions){
|
|
|
|
+ String questionBodyWord = appendScoreToQuestionBody(subQuestion.getQuesBodyWord(),subQuestion.getScore());
|
|
|
|
+ subQuestion.setQuesBodyWord(questionBodyWord);
|
|
|
|
+ }
|
|
|
|
+ }else {
|
|
|
|
+ Question question = paperDetailUnit.getQuestion();
|
|
|
|
+ String questionBodyWord = appendScoreToQuestionBody(question.getQuesBodyWord(),paperDetailUnit.getScore());
|
|
|
|
+ question.setQuesBodyWord(questionBodyWord);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 小题排序
|
|
|
|
+ * @describle 大题排序完成之后,放在一个集合里面。然后对相同类型的大题分组,生成不同的结合,在对小题进行
|
|
|
|
+ * @param paperDetailExps
|
|
|
|
+ */
|
|
|
|
+ public void sortPaperDetailUnitExps(List<PaperDetailExp> paperDetailExps) {
|
|
|
|
+ Map<Long,List<PaperDetailUnitExp>> map = new HashMap<Long, List<PaperDetailUnitExp>>();
|
|
|
|
+ //循环所有大题,将同类型的小题放到同一个集合下面
|
|
|
|
+ int index = 0;
|
|
|
|
+ for(PaperDetailExp paperDetailExp:paperDetailExps){
|
|
|
|
+ List<PaperDetailUnitExp> paperDetailUnitExps = null;
|
|
|
|
+ //单选,多选,判断放在同一集合下排序
|
|
|
|
+ if(paperDetailExp.getSortNumber()<4L){
|
|
|
|
+ //通过map的key去取value,如果没有,就添加
|
|
|
|
+ if(map.get(paperDetailExp.getSortNumber()) == null){
|
|
|
|
+ paperDetailUnitExps = new ArrayList<PaperDetailUnitExp>();
|
|
|
|
+ }else {
|
|
|
|
+ paperDetailUnitExps = map.get(paperDetailExp.getSortNumber());
|
|
|
|
+ }
|
|
|
|
+ paperDetailUnitExps.addAll(paperDetailExp.getPaperDetailUnits());
|
|
|
|
+ map.put(paperDetailExp.getSortNumber(), paperDetailUnitExps);
|
|
|
|
+ }else {
|
|
|
|
+ paperDetailUnitExps = new ArrayList<PaperDetailUnitExp>();
|
|
|
|
+ paperDetailUnitExps.addAll(paperDetailExp.getPaperDetailUnits());
|
|
|
|
+ map.put(paperDetailExp.getSortNumber() + index, paperDetailUnitExps);
|
|
|
|
+ index++;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ //循环所有小题,给小题排序
|
|
|
|
+ for(Long sortNumber:map.keySet()){
|
|
|
|
+ List<PaperDetailUnitExp> paperDetailUnitExps = map.get(sortNumber);
|
|
|
|
+ int number = 1;
|
|
|
|
+ if(paperDetailUnitExps != null && paperDetailUnitExps.size()>0){
|
|
|
|
+ for(int i = 0;i<paperDetailUnitExps.size();i++){
|
|
|
|
+ PaperDetailUnitExp paperDetailUnitExp = paperDetailUnitExps.get(i);
|
|
|
|
+ if(paperDetailUnitExp.getQuestionType() == QuesStructType.NESTED_ANSWER_QUESTION){
|
|
|
|
+ List<Question> subQuestions = paperDetailUnitExp.getQuestion().getSubQuestions();
|
|
|
|
+ for(int j = 0;j<subQuestions.size();j++){
|
|
|
|
+ subQuestions.get(j).setNumber(number+j);
|
|
|
|
+ }
|
|
|
|
+ number += subQuestions.size();
|
|
|
|
+ }else {
|
|
|
|
+ paperDetailUnitExp.setNumber(number);
|
|
|
|
+ number++;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+
|
|
/**
|
|
/**
|
|
* 设置大题标题
|
|
* 设置大题标题
|
|
* @param paperDetailExps
|
|
* @param paperDetailExps
|