ソースを参照

Merge branch 'dev0420' of https://git.oschina.net/songyue123456/comm-ques-bank

chenken 8 年 前
コミット
9b282dc848
49 ファイル変更2677 行追加949 行削除
  1. 18 4
      .gitignore
  2. 69 69
      cqb-base/src/main/java/com/qmth/cqb/base/model/Setting.java
  3. 61 61
      cqb-base/src/main/java/com/qmth/cqb/base/service/CourseService.java
  4. 45 45
      cqb-base/src/main/java/com/qmth/cqb/base/service/SettingService.java
  5. 23 1
      cqb-comm-utils/pom.xml
  6. 71 0
      cqb-comm-utils/src/main/java/com/qmth/cqb/utils/CombinationUtils.java
  7. 100 63
      cqb-comm-utils/src/main/java/com/qmth/cqb/utils/word/DocxProcessUtil.java
  8. 5 0
      cqb-gen-paper/pom.xml
  9. 10 0
      cqb-gen-paper/src/main/java/com/qmth/cqb/genpaper/model/GenPaperDto.java
  10. 94 33
      cqb-gen-paper/src/main/java/com/qmth/cqb/genpaper/service/GenPaperService.java
  11. 27 9
      cqb-gen-paper/src/main/java/com/qmth/cqb/genpaper/web/GenPaperController.java
  12. 1 2
      cqb-paper/src/main/java/com/qmth/cqb/paper/dao/ExtractConfigRepo.java
  13. 91 79
      cqb-paper/src/main/java/com/qmth/cqb/paper/dto/PaperDetailUnitExp.java
  14. 35 25
      cqb-paper/src/main/java/com/qmth/cqb/paper/model/ExamPaper.java
  15. 181 15
      cqb-paper/src/main/java/com/qmth/cqb/paper/model/ExtractConfig.java
  16. 34 24
      cqb-paper/src/main/java/com/qmth/cqb/paper/model/Paper.java
  17. 91 5
      cqb-paper/src/main/java/com/qmth/cqb/paper/model/PaperDetailUnit.java
  18. 64 42
      cqb-paper/src/main/java/com/qmth/cqb/paper/model/PaperSearchInfo.java
  19. 81 70
      cqb-paper/src/main/java/com/qmth/cqb/paper/model/PaperStruct.java
  20. 12 1
      cqb-paper/src/main/java/com/qmth/cqb/paper/model/PaperStructSearchInfo.java
  21. 17 0
      cqb-paper/src/main/java/com/qmth/cqb/paper/service/ExamPaperService.java
  22. 30 0
      cqb-paper/src/main/java/com/qmth/cqb/paper/service/ExamPaperServiceImpl.java
  23. 50 0
      cqb-paper/src/main/java/com/qmth/cqb/paper/service/ExtractConfigService.java
  24. 256 0
      cqb-paper/src/main/java/com/qmth/cqb/paper/service/ExtractConfigServiceImpl.java
  25. 147 86
      cqb-paper/src/main/java/com/qmth/cqb/paper/service/ImportPaperService.java
  26. 49 22
      cqb-paper/src/main/java/com/qmth/cqb/paper/service/PaperDetailUnitService.java
  27. 68 59
      cqb-paper/src/main/java/com/qmth/cqb/paper/service/PaperService.java
  28. 33 28
      cqb-paper/src/main/java/com/qmth/cqb/paper/service/PaperStructService.java
  29. 64 0
      cqb-paper/src/main/java/com/qmth/cqb/paper/web/ExamPaperController.java
  30. 87 0
      cqb-paper/src/main/java/com/qmth/cqb/paper/web/ExtractConfigController.java
  31. 26 14
      cqb-paper/src/main/java/com/qmth/cqb/paper/web/ImportPaperController.java
  32. 40 14
      cqb-paper/src/main/java/com/qmth/cqb/paper/web/PaperController.java
  33. 1 2
      cqb-paper/src/main/java/com/qmth/cqb/paper/web/PaperDetailUnitController.java
  34. 56 37
      cqb-paper/src/main/java/com/qmth/cqb/paper/web/PaperStructController.java
  35. 1 1
      cqb-question-resource/pom.xml
  36. 11 1
      cqb-question-resource/src/main/java/com/qmth/cqb/question/dao/QuesRepo.java
  37. 13 2
      cqb-question-resource/src/main/java/com/qmth/cqb/question/model/QuesOption.java
  38. 34 3
      cqb-question-resource/src/main/java/com/qmth/cqb/question/model/Question.java
  39. 31 0
      cqb-question-resource/src/main/java/com/qmth/cqb/question/model/QuestionBak.java
  40. 26 0
      cqb-question-resource/src/main/java/com/qmth/cqb/question/model/QuestionSearchCondition.java
  41. 293 107
      cqb-question-resource/src/main/java/com/qmth/cqb/question/service/QuesService.java
  42. 11 3
      cqb-question-resource/src/main/java/com/qmth/cqb/question/web/QuesController.java
  43. 1 1
      cqb-starter/src/main/resources/application-dev.properties
  44. 2 1
      cqb-starter/src/main/resources/application-prod.properties
  45. 2 2
      cqb-starter/src/main/resources/application-test.properties
  46. 17 17
      cqb-starter/src/main/resources/log4j2.xml
  47. 1 1
      cqb-starter/src/test/java/com/qmth/cqb/AppTest.java
  48. 140 0
      cqb-starter/src/test/java/com/qmth/cqb/ExtractConfigServiceTest.java
  49. 57 0
      cqb-starter/src/test/java/com/qmth/cqb/ProbabilityTest.java

+ 18 - 4
.gitignore

@@ -1,5 +1,19 @@
-.idea
+*.class
+
+# Proguard folder generated by ide
+.project
+.classpath
+.settings
+target/
+.idea/
 *.iml
-out
-gen
-*target
+
+# Log Files
+*.log
+*.class
+
+
+# Package Files #
+*.jar
+*.war
+*.ear

+ 69 - 69
cqb-base/src/main/java/com/qmth/cqb/base/model/Setting.java

@@ -1,69 +1,69 @@
-package com.qmth.cqb.base.model;
-
-import com.qmth.cqb.utils.enums.Switch;
-import org.springframework.data.annotation.Id;
-
-import java.io.Serializable;
-
-/**
- * Created by songyue on 17/3/27.
- */
-public class Setting implements Serializable {
-
-    private static final long serialVersionUID = 8476640757849637183L;
-
-    @Id
-    private String id;
-
-    private String code;
-
-    private String name;
-
-    private Switch status;
-
-    private String params;
-
-    public static long getSerialVersionUID() {
-        return serialVersionUID;
-    }
-
-    public String getId() {
-        return id;
-    }
-
-    public void setId(String id) {
-        this.id = id;
-    }
-
-    public String getCode() {
-        return code;
-    }
-
-    public void setCode(String code) {
-        this.code = code;
-    }
-
-    public String getName() {
-        return name;
-    }
-
-    public void setName(String name) {
-        this.name = name;
-    }
-
-    public Switch getStatus() {
-        return status;
-    }
-
-    public void setStatus(Switch status) {
-        this.status = status;
-    }
-
-    public String getParams() {
-        return params;
-    }
-
-    public void setParams(String params) {
-        this.params = params;
-    }
-}
+package com.qmth.cqb.base.model;
+
+import com.qmth.cqb.utils.enums.Switch;
+import org.springframework.data.annotation.Id;
+
+import java.io.Serializable;
+
+/**
+ * Created by songyue on 17/3/27.
+ */
+public class Setting implements Serializable {
+
+    private static final long serialVersionUID = 8476640757849637183L;
+
+    @Id
+    private String id;
+
+    private String code;
+
+    private String name;
+
+    private Switch status;
+
+    private String params;
+
+    public static long getSerialVersionUID() {
+        return serialVersionUID;
+    }
+
+    public String getId() {
+        return id;
+    }
+
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    public String getCode() {
+        return code;
+    }
+
+    public void setCode(String code) {
+        this.code = code;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public Switch getStatus() {
+        return status;
+    }
+
+    public void setStatus(Switch status) {
+        this.status = status;
+    }
+
+    public String getParams() {
+        return params;
+    }
+
+    public void setParams(String params) {
+        this.params = params;
+    }
+}

+ 61 - 61
cqb-base/src/main/java/com/qmth/cqb/base/service/CourseService.java

@@ -1,61 +1,61 @@
-package com.qmth.cqb.base.service;
-
-
-import java.util.ArrayList;
-import java.util.List;
-
-import org.apache.commons.lang3.StringUtils;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.data.domain.Example;
-import org.springframework.data.domain.Page;
-import org.springframework.data.domain.PageRequest;
-import org.springframework.data.mongodb.core.MongoTemplate;
-import org.springframework.data.mongodb.core.query.Criteria;
-import org.springframework.data.mongodb.core.query.Query;
-import org.springframework.stereotype.Service;
-
-import com.qmth.cqb.base.dao.CourseRepo;
-import com.qmth.cqb.base.model.Course;
-/**
- * Created by songyue on 16/12/28.
- */
-@Service
-public class CourseService {
-	
-	@Autowired
-	CourseRepo courseRepo;
-	
-    @Autowired
-    MongoTemplate mongoTemplate;
-    
-    /**
-     * 查询所有课程
-     * @param searchCondition
-     * @param curPage
-     * @param pageSize
-     * @return
-     */
-    public Page<Course> findAll(Course searchCondition, int curPage, int pageSize){
-        return courseRepo.findAll(Example.of(searchCondition),
-                new PageRequest(curPage - 1,pageSize));
-    }
-
-
-    /**
-     * 根据课程名称或者课程No查找课程
-     * @param 
-     * @return
-     */
-    public List<Course> findCoursesByKeyword(String keyword){
-        List<Course> courselist = new ArrayList<Course>();
-        if(StringUtils.isEmpty(keyword)){
-            return courselist;
-        }else{
-            Criteria likeNo = Criteria.where("courseNo").regex(keyword);//模糊匹配相当于SQL中“%Keyword%”
-            Criteria likeName = Criteria.where("courseName").regex(keyword);
-            Query query = new Query(new Criteria().orOperator(likeName,likeNo));
-            courselist = mongoTemplate.find(query, Course.class);
-            return courselist;
-        }
-    }
-}
+package com.qmth.cqb.base.service;
+
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.domain.Example;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.PageRequest;
+import org.springframework.data.mongodb.core.MongoTemplate;
+import org.springframework.data.mongodb.core.query.Criteria;
+import org.springframework.data.mongodb.core.query.Query;
+import org.springframework.stereotype.Service;
+
+import com.qmth.cqb.base.dao.CourseRepo;
+import com.qmth.cqb.base.model.Course;
+/**
+ * Created by songyue on 16/12/28.
+ */
+@Service
+public class CourseService {
+	
+	@Autowired
+	CourseRepo courseRepo;
+	
+    @Autowired
+    MongoTemplate mongoTemplate;
+    
+    /**
+     * 查询所有课程
+     * @param searchCondition
+     * @param curPage
+     * @param pageSize
+     * @return
+     */
+    public Page<Course> findAll(Course searchCondition, int curPage, int pageSize){
+        return courseRepo.findAll(Example.of(searchCondition),
+                new PageRequest(curPage - 1,pageSize));
+    }
+
+
+    /**
+     * 根据课程名称或者课程No查找课程
+     * @param 
+     * @return
+     */
+    public List<Course> findCoursesByKeyword(String keyword){
+        List<Course> courselist = new ArrayList<Course>();
+        if(StringUtils.isEmpty(keyword)){
+            return courselist;
+        }else{
+            Criteria likeNo = Criteria.where("courseNo").regex(keyword);//模糊匹配相当于SQL中“%Keyword%”
+            Criteria likeName = Criteria.where("courseName").regex(keyword);
+            Query query = new Query(new Criteria().orOperator(likeName,likeNo));
+            courselist = mongoTemplate.find(query, Course.class);
+            return courselist;
+        }
+    }
+}

+ 45 - 45
cqb-base/src/main/java/com/qmth/cqb/base/service/SettingService.java

@@ -1,45 +1,45 @@
-package com.qmth.cqb.base.service;
-
-
-import com.qmth.cqb.base.dao.CourseRepo;
-import com.qmth.cqb.base.dao.SettingRepo;
-import com.qmth.cqb.base.model.Course;
-import com.qmth.cqb.base.model.Setting;
-import com.qmth.cqb.utils.enums.Switch;
-import org.apache.commons.lang3.StringUtils;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.data.domain.Example;
-import org.springframework.data.domain.Page;
-import org.springframework.data.domain.PageRequest;
-import org.springframework.data.mongodb.core.MongoTemplate;
-import org.springframework.data.mongodb.core.query.Criteria;
-import org.springframework.data.mongodb.core.query.Query;
-import org.springframework.stereotype.Service;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * Created by songyue on 16/12/28.
- */
-@Service
-public class SettingService {
-	
-	@Autowired
-    SettingRepo settingRepo;
-	
-    public void initData(){
-        if(settingRepo.count() == 0){
-            Setting importSetting = new Setting();
-            Setting genSetting = new Setting();
-            importSetting.setCode("import");
-            importSetting.setName("试题入库审核");
-            importSetting.setStatus(Switch.ON);
-            genSetting.setCode("gen");
-            genSetting.setName("试卷组成审核");
-            genSetting.setStatus(Switch.ON);
-            settingRepo.save(importSetting);
-            settingRepo.save(genSetting);
-        }
-    }
-}
+package com.qmth.cqb.base.service;
+
+
+import com.qmth.cqb.base.dao.CourseRepo;
+import com.qmth.cqb.base.dao.SettingRepo;
+import com.qmth.cqb.base.model.Course;
+import com.qmth.cqb.base.model.Setting;
+import com.qmth.cqb.utils.enums.Switch;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.domain.Example;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.PageRequest;
+import org.springframework.data.mongodb.core.MongoTemplate;
+import org.springframework.data.mongodb.core.query.Criteria;
+import org.springframework.data.mongodb.core.query.Query;
+import org.springframework.stereotype.Service;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Created by songyue on 16/12/28.
+ */
+@Service
+public class SettingService {
+	
+	@Autowired
+    SettingRepo settingRepo;
+	
+    public void initData(){
+        if(settingRepo.count() == 0){
+            Setting importSetting = new Setting();
+            Setting genSetting = new Setting();
+            importSetting.setCode("import");
+            importSetting.setName("试题入库审核");
+            importSetting.setStatus(Switch.ON);
+            genSetting.setCode("gen");
+            genSetting.setName("试卷组成审核");
+            genSetting.setStatus(Switch.ON);
+            settingRepo.save(importSetting);
+            settingRepo.save(genSetting);
+        }
+    }
+}

+ 23 - 1
cqb-comm-utils/pom.xml

@@ -22,6 +22,12 @@
             <artifactId>common-dto</artifactId>
             <version>${project.version}</version>
         </dependency>
+
+        <dependency>
+            <groupId>cn.com.qmth.examcloud.common</groupId>
+            <artifactId>common-uac</artifactId>
+            <version>${project.version}</version>
+        </dependency>
         
         <dependency>
             <groupId>com.google.code.gson</groupId>
@@ -117,6 +123,22 @@
             </exclusions>
         </dependency>
 
+        <dependency>
+            <groupId>org.docx4j</groupId>
+            <artifactId>docx4j-ImportXHTML</artifactId>
+            <version>3.3.1</version>
+            <exclusions>
+                <exclusion>
+                    <groupId>org.slf4j</groupId>
+                    <artifactId>slf4j-api</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>org.slf4j</groupId>
+                    <artifactId>slf4j-log4j12</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+
         <dependency>
             <groupId>org.apache.poi</groupId>
             <artifactId>poi</artifactId>
@@ -189,4 +211,4 @@
             <version>5.1.1</version>
         </dependency>
     </dependencies>
-</project>
+</project>

+ 71 - 0
cqb-comm-utils/src/main/java/com/qmth/cqb/utils/CombinationUtils.java

@@ -0,0 +1,71 @@
+package com.qmth.cqb.utils;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class CombinationUtils {
+
+    private static List<String> combineList = new ArrayList<String>();
+
+    public static List<Integer> combiantion(List<Integer> numbers, int needNum, int needNestNum) {
+        List<Integer> returnList = new ArrayList<Integer>();
+        if (numbers == null || numbers.size() == 0) {
+            return null;
+        }
+        List<Integer> list = new ArrayList<Integer>();
+        for (int i = 1; i <= numbers.size(); i++) {
+            combine(numbers, 0, i, list);
+        }
+        for (String str : combineList) {
+            returnList = sum(str, needNum, needNestNum);
+            if (returnList.size() > 0) {
+                break;
+            }
+        }
+        return returnList;
+    }
+
+    // 从字符数组中第begin个字符开始挑选number个字符加入list中
+    private static void combine(List<Integer> cs, int begin, int number, List<Integer> list) {
+        if (number == 0) {
+            combineList.add(list.toString());
+            return;
+        }
+        if (begin == cs.size()) {
+            return;
+        }
+        list.add(cs.get(begin));
+        combine(cs, begin + 1, number - 1, list);
+        list.remove(cs.get(begin));
+        combine(cs, begin + 1, number, list);
+    }
+
+    public static void main(String args[]) {
+        // List<Integer> list = new ArrayList<Integer>();
+        // list.add(3);
+        // list.add(4);
+        // list.add(5);
+        // combiantion(list);
+        // System.out.println(combineList.toString());
+    }
+
+    private static List<Integer> sum(String str, int needNum, int needNestNum) {
+        List<Integer> list = new ArrayList<Integer>();
+        List<Integer> tempList = new ArrayList<Integer>();
+        String[] strs = str.replaceAll("\\[", "").replaceAll("\\]", "").split(",");
+        Integer sum = 0;
+        if (strs.length == needNestNum) {
+            for (String intStr : strs) {
+                intStr = intStr.trim();
+                sum += Integer.valueOf(intStr);
+                tempList.add(Integer.valueOf(intStr));
+
+            }
+            if (sum <= needNum) {
+                list.addAll(tempList);
+            }
+        }
+
+        return list;
+    }
+}

+ 100 - 63
cqb-comm-utils/src/main/java/com/qmth/cqb/utils/word/DocxProcessUtil.java

@@ -1,34 +1,14 @@
 package com.qmth.cqb.utils.word;
 
-import java.io.BufferedWriter;
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.io.OutputStreamWriter;
-import java.io.StringReader;
-import java.io.StringWriter;
-import java.io.Writer;
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.UUID;
-
-import javax.servlet.http.HttpServletResponse;
-import javax.xml.bind.JAXBElement;
-import javax.xml.parsers.DocumentBuilder;
-import javax.xml.parsers.DocumentBuilderFactory;
-import javax.xml.transform.Transformer;
-import javax.xml.transform.TransformerFactory;
-import javax.xml.transform.dom.DOMSource;
-import javax.xml.transform.stream.StreamResult;
-import javax.xml.transform.stream.StreamSource;
-
+import com.qmth.cqb.utils.CommonUtils;
+import com.qmth.cqb.utils.enums.QuesUnit;
+import freemarker.template.Configuration;
+import freemarker.template.Template;
+import net.sf.saxon.TransformerFactoryImpl;
+import net.sourceforge.jeuclid.LayoutContext;
+import net.sourceforge.jeuclid.context.LayoutContextImpl;
+import net.sourceforge.jeuclid.context.StyleAttributeLayoutContext;
+import net.sourceforge.jeuclid.converter.Converter;
 import org.apache.commons.codec.binary.Base64;
 import org.apache.commons.io.FileUtils;
 import org.apache.commons.io.IOUtils;
@@ -37,6 +17,7 @@ import org.docx4j.Docx4J;
 import org.docx4j.TraversalUtil;
 import org.docx4j.XmlUtils;
 import org.docx4j.convert.in.FlatOpcXmlImporter;
+import org.docx4j.convert.in.xhtml.XHTMLImporterImpl;
 import org.docx4j.convert.out.HTMLSettings;
 import org.docx4j.convert.out.common.preprocess.PartialDeepCopy;
 import org.docx4j.dml.CTBlip;
@@ -53,12 +34,7 @@ import org.docx4j.openpackaging.parts.WordprocessingML.MainDocumentPart;
 import org.docx4j.openpackaging.parts.relationships.Namespaces;
 import org.docx4j.openpackaging.parts.relationships.RelationshipsPart;
 import org.docx4j.relationships.Relationship;
-import org.docx4j.wml.ContentAccessor;
-import org.docx4j.wml.Drawing;
-import org.docx4j.wml.ObjectFactory;
-import org.docx4j.wml.P;
-import org.docx4j.wml.R;
-import org.docx4j.wml.Text;
+import org.docx4j.wml.*;
 import org.dom4j.Namespace;
 import org.dom4j.io.SAXReader;
 import org.jsoup.Jsoup;
@@ -66,16 +42,17 @@ import org.jsoup.nodes.Element;
 import org.jsoup.select.Elements;
 import org.xml.sax.InputSource;
 
-import com.qmth.cqb.utils.CommonUtils;
-import com.qmth.cqb.utils.enums.QuesUnit;
-
-import freemarker.template.Configuration;
-import freemarker.template.Template;
-import net.sf.saxon.TransformerFactoryImpl;
-import net.sourceforge.jeuclid.LayoutContext;
-import net.sourceforge.jeuclid.context.LayoutContextImpl;
-import net.sourceforge.jeuclid.context.StyleAttributeLayoutContext;
-import net.sourceforge.jeuclid.converter.Converter;
+import javax.servlet.http.HttpServletResponse;
+import javax.xml.bind.JAXBElement;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+import javax.xml.transform.stream.StreamSource;
+import java.io.*;
+import java.util.*;
 
 /**
  * docx处理工具类 Created by songyue on 17/3/10.
@@ -84,6 +61,7 @@ public final class DocxProcessUtil {
 
     public static final LayoutContext IMG_LAYOUT = new StyleAttributeLayoutContext(
             LayoutContextImpl.getDefaultLayoutContext(), "2em", java.awt.Color.BLACK);
+
     public static final String IMG_OUT_TYPE = "image/png";
 
     public static final String ENCODING = "utf-8";
@@ -129,6 +107,7 @@ public final class DocxProcessUtil {
 
     /**
      * 获取段落的所有文本
+     *
      * @param p
      * @return
      */
@@ -144,6 +123,7 @@ public final class DocxProcessUtil {
 
     /**
      * 校验段落中是否含有公式或图片
+     *
      * @param p
      * @return
      */
@@ -159,6 +139,7 @@ public final class DocxProcessUtil {
 
     /**
      * 获取文档包副本(去除段落)
+     *
      * @param wordMLPackage
      * @return
      * @throws Exception
@@ -168,8 +149,8 @@ public final class DocxProcessUtil {
         Set<String> relationshipTypes = new HashSet<String>();
         relationshipTypes.add(wordMLPackage.getMainDocumentPart().getRelationshipType());
         // 深拷贝
-        WordprocessingMLPackage tmpWordMlPackage = (WordprocessingMLPackage) PartialDeepCopy.process(wordMLPackage,
-                relationshipTypes);
+        WordprocessingMLPackage tmpWordMlPackage = (WordprocessingMLPackage) PartialDeepCopy
+                .process(wordMLPackage, relationshipTypes);
         // 移除所有段落
         initTmpPackage(tmpWordMlPackage);
 
@@ -178,6 +159,7 @@ public final class DocxProcessUtil {
 
     /**
      * 初始化文档包(去除所有段落)
+     *
      * @param wordMLPackage
      * @return
      * @throws Exception
@@ -190,6 +172,7 @@ public final class DocxProcessUtil {
 
     /**
      * 获得段落wordml
+     *
      * @param p
      * @return
      */
@@ -199,6 +182,7 @@ public final class DocxProcessUtil {
 
     /**
      * 转换wordMl为html
+     *
      * @param wordMl
      * @return
      * @throws Exception
@@ -238,6 +222,7 @@ public final class DocxProcessUtil {
 
     /**
      * 替换所有公式为图片
+     *
      * @param wordMLPackage
      * @throws Exception
      */
@@ -267,6 +252,7 @@ public final class DocxProcessUtil {
 
     /**
      * 替换公式为图片
+     *
      * @param p
      * @throws Exception
      */
@@ -292,6 +278,7 @@ public final class DocxProcessUtil {
 
     /**
      * 创建新图片
+     *
      * @param wordMLPackage
      * @param bytes
      * @param filenameHint
@@ -321,6 +308,7 @@ public final class DocxProcessUtil {
 
     /**
      * 获取wordMl固定节点下所有子节点
+     *
      * @param obj
      * @param toSearch
      * @return
@@ -343,6 +331,7 @@ public final class DocxProcessUtil {
 
     /**
      * omml转换成mml
+     *
      * @param omml
      * @return
      */
@@ -377,6 +366,7 @@ public final class DocxProcessUtil {
 
     /**
      * 格式化转换后的html(html字符串)
+     *
      * @param htmlStr
      * @return
      */
@@ -426,6 +416,7 @@ public final class DocxProcessUtil {
 
     /**
      * 格式化转换后的html(html临时文件)
+     *
      * @param htmlPath
      * @return
      */
@@ -440,8 +431,9 @@ public final class DocxProcessUtil {
             doc.select("div").removeAttr("class").removeAttr("style");
             doc.select("span").removeAttr("class").removeAttr("style");
             doc.select("span").stream().forEach(element -> {
-                if (!element.hasText())
+                if (!element.hasText() && element.childNodeSize() == 0) {
                     element.remove();
+                }
             });
             Elements imgs = doc.select("img");
             for (org.jsoup.nodes.Element img : imgs) {
@@ -465,6 +457,7 @@ public final class DocxProcessUtil {
 
     /**
      * 转换mathml为png图片
+     *
      * @param mathMlStr
      * @return
      */
@@ -493,6 +486,7 @@ public final class DocxProcessUtil {
 
     /**
      * 通过图片路径获取base64码
+     *
      * @param imgFilePath
      * @return
      */
@@ -516,6 +510,7 @@ public final class DocxProcessUtil {
 
     /**
      * 通过图片文件获取base64码
+     *
      * @param imgFile
      * @return
      */
@@ -537,6 +532,7 @@ public final class DocxProcessUtil {
 
     /**
      * 格式化段落wordml
+     *
      * @param pWordMl
      * @return
      * @throws Exception
@@ -556,6 +552,7 @@ public final class DocxProcessUtil {
 
     /**
      * 过滤试题单元标题
+     *
      * @param p
      * @param quesUnit
      * @return
@@ -584,13 +581,13 @@ public final class DocxProcessUtil {
                                 tmpText = tmpText.replaceFirst("\\d{1,}\\.", "");
                                 text.setValue(tmpText);
                             } else {
-                                if(index == 0){
+                                if (index == 1) {
                                     tmpText = tmpText.replaceFirst("\\d{1,}", "");
-                                }else if(index == 1){
+                                } else if (index == 2) {
                                     tmpText = tmpText.replaceFirst("\\.", "");
                                 }
                                 text.setValue(tmpText);
-                                if (index == 1) {
+                                if (index == 2) {
                                     break;
                                 }
                             }
@@ -601,27 +598,26 @@ public final class DocxProcessUtil {
                                 tmpText = tmpText.replaceFirst("[A-Z]\\.", "");
                                 text.setValue(tmpText);
                             } else {
-                                if(index == 0){
+                                if (index == 1) {
                                     tmpText = tmpText.replaceFirst("[A-Z]", "");
-                                }else if(index == 1){
+                                } else if (index == 2) {
                                     tmpText = tmpText.replaceFirst("\\.", "");
                                 }
                                 text.setValue(tmpText);
-                                if (index == 1) {
+                                if (index == 2) {
                                     break;
                                 }
                             }
 
                         } else if (quesUnit == QuesUnit.QUES_ANSWER) {
                             // 过滤答案标题
-                            if (index < 3) {
-                                tmpText = tmpText.replaceFirst("\\[|\\]", "").replaceFirst("答案", "");
+                            if (index <= 4) {
+                                tmpText = tmpText.replaceFirst("\\[", "").replaceFirst("\\]", "").replaceFirst("答案", "")
+                                        .replaceFirst("[:|:]", "");
+                                text.setValue(tmpText);
                             } else {
-                                tmpText = tmpText.replaceFirst("[:|:]", "");
-                            }
-                            text.setValue(tmpText);
-                            if (index == 3)
                                 break;
+                            }
                         }
                     }
                 }
@@ -632,6 +628,7 @@ public final class DocxProcessUtil {
 
     /**
      * 导出word
+     *
      * @param dataMap
      * @param fileName
      */
@@ -665,6 +662,7 @@ public final class DocxProcessUtil {
 
     /**
      * 导出试卷
+     *
      * @param dataMap
      * @param fileName
      */
@@ -674,6 +672,7 @@ public final class DocxProcessUtil {
 
     /**
      * 导出答案
+     *
      * @param dataMap
      * @param fileName
      */
@@ -683,6 +682,7 @@ public final class DocxProcessUtil {
 
     /**
      * 处理导出word中的图片
+     *
      * @param fileName
      * @param wordMLPackages
      * @throws Exception
@@ -722,6 +722,7 @@ public final class DocxProcessUtil {
 
     /**
      * 获取word二进制数据(空文档,只有样式和资源)
+     *
      * @param wordMLPackage
      * @return
      * @throws Exception
@@ -741,6 +742,7 @@ public final class DocxProcessUtil {
 
     /**
      * 通过二进制流获取word文档包
+     *
      * @param bytes
      * @return
      */
@@ -759,6 +761,7 @@ public final class DocxProcessUtil {
 
     /**
      * 初始化word文档图片资源路径,防止导出试卷时资源ID冲突
+     *
      * @param wordMLPackage
      */
     public static void initPkgImage(WordprocessingMLPackage wordMLPackage) {
@@ -790,21 +793,55 @@ public final class DocxProcessUtil {
 
     /**
      * 获取RldNum
+     *
      * @return
      */
     public static String getRldNum() {
         return REL_ID_HEADER + CommonUtils.getCurNum();
     }
 
-    public static void processDownload(String fileName,HttpServletResponse response) throws Exception {
+    /**
+     * 下载word文件
+     * @param fileName
+     * @param response
+     * @throws Exception
+     */
+    public static void processDownload(String fileName, HttpServletResponse response) throws Exception {
         String filePath = TEMP_FILE_EXP + fileName + DOCX_SUFFIX;
         InputStream inputStream = new FileInputStream(filePath);
         OutputStream outputStream = response.getOutputStream();
         // 设置强制下载不打开
         response.setContentType("application/octet-stream;charset=utf-8");
         // 设置文件名
-        response.addHeader("Content-Disposition", "attachment;fileName=" + new String(fileName.getBytes("UTF-8"),"iso-8859-1") + DOCX_SUFFIX);
-        IOUtils.copyLarge(inputStream,outputStream);
+        response.addHeader("Content-Disposition",
+                "attachment;fileName=" + new String(fileName.getBytes("UTF-8"), "iso-8859-1") + DOCX_SUFFIX);
+        IOUtils.copyLarge(inputStream, outputStream);
     }
 
+    /**
+     * html转word
+     * @param html
+     * @return
+     * @throws Exception
+     */
+    public static String html2Docx(WordprocessingMLPackage wordMLPackage,String html){
+        initPkgImage(wordMLPackage);
+        XHTMLImporterImpl XHTMLImporter = new XHTMLImporterImpl(wordMLPackage);
+        String wordMl = "";
+        try {
+            wordMLPackage.getMainDocumentPart().getContent().addAll(
+                    XHTMLImporter.convert( html, null) );
+            // 获取word文档中所有段落
+            List<Object> pList = getAllElementFromObject(wordMLPackage.getMainDocumentPart(), P.class);
+            for(Object p:pList){
+                wordMl += XmlUtils.marshaltoString(p);
+            }
+//            wordMl = formatPWordMl(wordMl);
+        }catch (Exception e){
+            e.printStackTrace();
+        }
+        return wordMl;
+    }
+
+
 }

+ 5 - 0
cqb-gen-paper/pom.xml

@@ -21,5 +21,10 @@
             <artifactId>cqb-paper</artifactId>
             <version>${project.version}</version>
         </dependency>
+         <dependency>
+            <groupId>com.qmth.cqb</groupId>
+            <artifactId>cqb-base</artifactId>
+            <version>${project.version}</version>
+        </dependency>
     </dependencies>
 </project>

+ 10 - 0
cqb-gen-paper/src/main/java/com/qmth/cqb/genpaper/model/GenPaperDto.java

@@ -34,6 +34,8 @@ public class GenPaperDto implements Serializable {
 
     private Integer genNumber;// 生成试卷套数
 
+    private String orgId;
+
     public static long getSerialVersionUID() {
         return serialVersionUID;
     }
@@ -122,4 +124,12 @@ public class GenPaperDto implements Serializable {
         return serialVersionUID;
     }
 
+    public String getOrgId() {
+        return orgId;
+    }
+
+    public void setOrgId(String orgId) {
+        this.orgId = orgId;
+    }
+
 }

+ 94 - 33
cqb-gen-paper/src/main/java/com/qmth/cqb/genpaper/service/GenPaperService.java

@@ -25,6 +25,8 @@ import com.qmth.cqb.paper.model.PaperDetail;
 import com.qmth.cqb.paper.model.PaperDetailUnit;
 import com.qmth.cqb.paper.model.PaperStruct;
 import com.qmth.cqb.question.model.Question;
+import com.qmth.cqb.utils.BeanCopierUtil;
+import com.qmth.cqb.utils.CombinationUtils;
 import com.qmth.cqb.utils.CommonUtils;
 import com.qmth.cqb.utils.enums.PaperType;
 
@@ -111,8 +113,10 @@ public class GenPaperService {
             paper.setCourseNo(genPaperDto.getCourseNo());
             paper.setCourseName(genPaperDto.getCourseName());
             paper.setCreator(genPaperDto.getCreator());
+            paper.setOrgId(genPaperDto.getOrgId());
             paper.setCreateTime(CommonUtils.getCurDateTime());
             paper.setUnitCount(this.getTotalQuesNum(paperDetailunits));
+            paper.setPaperType(PaperType.GENERATE);
             // 数据入库
             paper = this.persistentPaper(paperDetailunits, paperDetails, paper);
             msg = "success";
@@ -170,42 +174,44 @@ public class GenPaperService {
         Map<String, Object> paperMsgMap = new HashMap<String, Object>();
         Map<String, Double> paperMap = genPaperDto.getSimpleParams();
         List<PaperDetailUnit> selectedUnits = new ArrayList<PaperDetailUnit>();// 选中的小题
-        int totalQuesNum = 0;
         if (paperMap != null && paperMap.size() > 0) {
             for (String paperId : paperMap.keySet()) {
-                int unitNum = paperMap.get(paperId).intValue();
-                totalQuesNum += unitNum;
-                List<PaperDetailUnit> tempUnits = new ArrayList<PaperDetailUnit>();
+                int needQuesNum = paperMap.get(paperId).intValue();// 需要抽取的试题数量
                 List<PaperDetailUnit> unitList = unitRepo.findByPaper(paperRepo.findOne(paperId));
                 Collections.shuffle(unitList);// 随机乱序之后再取题
-                if (this.getTotalQuesNum(unitList) >= unitNum) {
-                    for (int i = 0; i < unitList.size(); i++) {// 假如unitNum=2,取了第一道题填空题,第二道题是套题,下面有4个子题,就直接进入下一次循环
-                        PaperDetailUnit unit = unitList.get(i);
-                        int quesNum = this.getTotalQuesNum(tempUnits);
-                        if (unit.getQuestionType() == QuesStructType.NESTED_ANSWER_QUESTION
-                                && (unit.getQuestion().getSubQuestions().size() + quesNum) > unitNum) {
-                            continue;
-                        }
-                        if (quesNum < unitNum && (!tempUnits.contains(unit))) {
-                            tempUnits.add(unit);
-                        }
-                        if (this.getTotalQuesNum(tempUnits) == unitNum) {
-                            break;
-                        }
+                List<PaperDetailUnit> nestedUnits = new ArrayList<PaperDetailUnit>();// 已选的试题集合
+                List<Integer> otherQuesNum = new ArrayList<Integer>();
+                List<Integer> nestQums = new ArrayList<Integer>();
+                if (this.getTotalQuesNum(unitList) >= needQuesNum) {
+                    for (int i = 0; i < unitList.size(); i++) {
+                        PaperDetailUnit pdu = unitList.get(i);
+                        if (pdu.getQuestionType() == QuesStructType.NESTED_ANSWER_QUESTION) {
+                            if (pdu.getQuestion().getSubQuestions().size() <= needQuesNum) {
+                                nestQums.add(pdu.getQuestion().getSubQuestions().size());
+                                nestedUnits.add(pdu);
+                            }
 
+                        } else {
+                            otherQuesNum.add(1);
+                        }
+                    }
+                    List<Integer> canChooseNestNum = this.getNestNum(nestQums, otherQuesNum.size(), needQuesNum);
+                    int size = canChooseNestNum.size();
+                    int index = (int) (Math.random() * size);
+                    int ranmdomNum = canChooseNestNum.get(index);// 取第一个
+                    if (ranmdomNum == 0) {// 假如随机到0个套题
+                        selectedUnits = this.getNeedUnits(null, unitList, needQuesNum);
+                    } else {
+                        List<Integer> sumList = new ArrayList<Integer>();
+                        sumList = CombinationUtils.combiantion(nestQums, needQuesNum, ranmdomNum);
+                        selectedUnits = this.getNeedUnits(sumList, unitList, needQuesNum);// 有套题情况
                     }
-                    selectedUnits.addAll(tempUnits);
                 } else {
-                    msg = "题源不足:需要抽取的题目数量要多于试卷中题目数量,请检查";
+                    msg = "题源不足,请检查题源";
                     paperMsgMap.put("msg", msg);
                     return paperMsgMap;
                 }
             }
-            if (this.getTotalQuesNum(selectedUnits) < totalQuesNum) {
-                msg = "题源不足:需要抽取的题目数量要多于试卷中题目数量,请检查";
-                paperMsgMap.put("msg", msg);
-                return paperMsgMap;
-            }
         }
         Paper paper = this.constuctPaper(selectedUnits, genPaperDto);
         msg = "success";
@@ -269,6 +275,7 @@ public class GenPaperService {
             paper.setPaperDetailCount(details.size());
             paper.setTotalScore(score);
             paper.setPaperType(PaperType.GENERATE);
+            paper.setOrgId(genPaperDto.getOrgId());
         }
         return paper;
 
@@ -283,10 +290,12 @@ public class GenPaperService {
      */
     public Paper constuctPaper(List<PaperDetailUnit> selectedUnits, GenPaperDto genPaperDto) {
         Collections.sort(selectedUnits);// 根据大题题型ID排序
+        List<PaperDetailUnit> saveUnits = BeanCopierUtil.copyPropertiesOfList(selectedUnits, PaperDetailUnit.class);
         List<QuesStructType> qsts = new ArrayList<QuesStructType>();
-        for (int i = 0; i < selectedUnits.size(); i++) {
-            if (!qsts.contains(selectedUnits.get(i).getQuestionType())) {
-                qsts.add(selectedUnits.get(i).getQuestionType());
+        for (int i = 0; i < saveUnits.size(); i++) {
+            saveUnits.get(i).setId(UUID.randomUUID().toString());
+            if (!qsts.contains(saveUnits.get(i).getQuestionType())) {
+                qsts.add(saveUnits.get(i).getQuestionType());
             }
 
         }
@@ -294,9 +303,9 @@ public class GenPaperService {
         Map<QuesStructType, Integer> qTypeIndexMap = new HashMap<QuesStructType, Integer>();
         for (int i = 1; i <= qsts.size(); i++) {
             List<PaperDetailUnit> tempUnits = new ArrayList<PaperDetailUnit>();
-            for (int j = 0; j < selectedUnits.size(); j++) {
-                if (qsts.get(i - 1) == selectedUnits.get(j).getQuestionType()) {
-                    tempUnits.add(selectedUnits.get(j));
+            for (int j = 0; j < saveUnits.size(); j++) {
+                if (qsts.get(i - 1) == saveUnits.get(j).getQuestionType()) {
+                    tempUnits.add(saveUnits.get(j));
                 }
             }
             unitMap.put(qsts.get(i - 1), tempUnits);
@@ -308,8 +317,8 @@ public class GenPaperService {
             details.add(this.constuctPaperDeatil(unitMap.get(qType), qTypeIndexMap.get(qType), qType.getName()));
         }
         Paper paper = this.constuctPaperByPaperDetails(details, genPaperDto);
-        paper.setUnitCount(this.getTotalQuesNum(selectedUnits));// 设置小题数量,需统计subQuestion
-        paper = this.persistentPaper(selectedUnits, details, paper);
+        paper.setUnitCount(this.getTotalQuesNum(saveUnits));// 设置小题数量,需统计subQuestion
+        paper = this.persistentPaper(saveUnits, details, paper);
         return paper;
 
     }
@@ -353,4 +362,56 @@ public class GenPaperService {
         return totalQuesNum + nestQuesNum;
     }
 
+    public List<PaperDetailUnit> getNeedUnits(List<Integer> sumList, List<PaperDetailUnit> unitList, int needQuesNum) {
+        List<PaperDetailUnit> selectedUnits = new ArrayList<PaperDetailUnit>();// 选中的小题
+        List<PaperDetailUnit> nestedUnits = new ArrayList<PaperDetailUnit>();// 套题集合
+        List<PaperDetailUnit> otherUnits = new ArrayList<PaperDetailUnit>();// 其他类型的小题
+        for (PaperDetailUnit pdu : unitList) {
+            if (pdu.getQuestionType() == QuesStructType.NESTED_ANSWER_QUESTION) {
+                nestedUnits.add(pdu);
+            } else {
+                otherUnits.add(pdu);
+            }
+        }
+        // 选的套题
+        if (sumList != null && sumList.size() > 0) {
+            for (Integer subNum : sumList) {
+                for (PaperDetailUnit pdu : nestedUnits) {
+                    if (subNum == pdu.getQuestion().getSubQuestions().size()) {
+                        selectedUnits.add(pdu);
+                        break;
+                    }
+                }
+            }
+        }
+        int otherQuesNum = needQuesNum - this.getTotalQuesNum(selectedUnits);
+        for (int i = 0; i < otherQuesNum; i++) {
+            selectedUnits.add(otherUnits.get(i));
+        }
+        return selectedUnits;
+    }
+
+    public List<Integer> getNestNum(List<Integer> nestQums, int otherQuesNum, int needQuesNum) {
+        Collections.sort(nestQums);
+        List<Integer> chooseNestNum = new ArrayList<Integer>();
+        if (needQuesNum <= otherQuesNum) {
+            chooseNestNum.add(0);
+        }
+        for (int i = 1; i <= nestQums.size(); i++) {
+            int min = 0;
+            int max = 0;
+            for (int j = 0; j < i; j++) {
+                min += nestQums.get(j);
+                max += nestQums.get(nestQums.size() - 1 - j);
+            }
+            if ((max + otherQuesNum >= needQuesNum && needQuesNum - max <= otherQuesNum && needQuesNum - max >= 0)
+                    || (min + otherQuesNum >= needQuesNum && needQuesNum - min <= otherQuesNum
+                            && needQuesNum - min >= 0)) {
+                chooseNestNum.add(i);
+            }
+        }
+
+        return chooseNestNum;
+
+    }
 }

+ 27 - 9
cqb-gen-paper/src/main/java/com/qmth/cqb/genpaper/web/GenPaperController.java

@@ -3,6 +3,8 @@ package com.qmth.cqb.genpaper.web;
 import java.util.HashMap;
 import java.util.Map;
 
+import javax.servlet.http.HttpServletRequest;
+
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.http.HttpStatus;
 import org.springframework.http.ResponseEntity;
@@ -13,7 +15,9 @@ import org.springframework.web.bind.annotation.RestController;
 
 import com.qmth.cqb.genpaper.model.GenPaperDto;
 import com.qmth.cqb.genpaper.service.GenPaperService;
+import com.qmth.cqb.utils.enums.RandomGenPaperPolicy;
 
+import cn.com.qmth.examcloud.common.uac.entity.AccessUser;
 import io.swagger.annotations.ApiOperation;
 
 /**
@@ -28,8 +32,12 @@ public class GenPaperController {
 
     @ApiOperation(value = "简易随机组卷", notes = "简易随机组卷")
     @PostMapping("/genPaper/simple")
-    public ResponseEntity genPaperSimple(@RequestBody GenPaperDto genPaperDto) {
+    public ResponseEntity genPaperSimple(HttpServletRequest request, @RequestBody GenPaperDto genPaperDto) {
+        AccessUser user = (AccessUser) request.getAttribute("accessUser");
+        genPaperDto.setOrgId(user.getOrgId().toString());
+        genPaperDto.setCreator(user.getLoginName());
         Map<String, Object> paperMap = new HashMap<String, Object>();
+        String paperName = genPaperDto.getPaperName();
         if (genPaperDto.getGenNumber() == 1) {
             if (genPaperDto.getSimpleGenPaperPolicy().getKey() == 1L) {
                 paperMap = genPaperService.genPaperByQuestionNum(genPaperDto);
@@ -37,18 +45,22 @@ public class GenPaperController {
                 paperMap = genPaperService.genPaperByScore(genPaperDto);
             }
         } else if (genPaperDto.getGenNumber() > 1) {
-            if (genPaperDto.getSimpleGenPaperPolicy().getKey() == 1L) {
+            if (genPaperDto.getSimpleGenPaperPolicy() == RandomGenPaperPolicy.BY_QUESTIONNUM) {
                 for (int i = 1; i <= genPaperDto.getGenNumber(); i++) {
-                    genPaperDto.setPaperName(genPaperDto.getPaperName() + "_" + i);
+                    genPaperDto.setPaperName(paperName + "_" + i);
                     paperMap.putAll(genPaperService.genPaperByQuestionNum(genPaperDto));
-                    genPaperDto.setPaperName("");
+                    if (!paperMap.get("msg").equals("success")) {
+                        break;
+                    }
                 }
 
-            } else if (genPaperDto.getSimpleGenPaperPolicy().getKey() == 2L) {
+            } else if (genPaperDto.getSimpleGenPaperPolicy() == RandomGenPaperPolicy.BY_SCORE) {
                 for (int i = 1; i <= genPaperDto.getGenNumber(); i++) {
                     genPaperDto.setPaperName(genPaperDto.getPaperName() + "_" + i);
                     paperMap.putAll(genPaperService.genPaperByScore(genPaperDto));
-                    genPaperDto.setPaperName("");
+                    if (!paperMap.get("msg").equals("success")) {
+                        break;
+                    }
                 }
 
             }
@@ -64,13 +76,19 @@ public class GenPaperController {
 
     @ApiOperation(value = "精细组卷", notes = "精细组卷")
     @PostMapping("/genPaper/normal")
-    public ResponseEntity genPaperNormal(@RequestBody GenPaperDto genPaperDto) {
+    public ResponseEntity genPaperNormal(HttpServletRequest request, @RequestBody GenPaperDto genPaperDto) {
+        AccessUser user = (AccessUser) request.getAttribute("accessUser");
+        genPaperDto.setOrgId(user.getOrgId().toString());
+        genPaperDto.setCreator(user.getLoginName());
         Map<String, Object> paperMap = new HashMap<String, Object>();
+        String paperName = genPaperDto.getPaperName();
         if (genPaperDto.getGenNumber() > 1) {
             for (int i = 1; i <= genPaperDto.getGenNumber(); i++) {
-                genPaperDto.setPaperName(genPaperDto.getPaperName() + "_" + i);
+                genPaperDto.setPaperName(paperName + "_" + i);
                 paperMap.putAll(genPaperService.genPaper(genPaperDto));
-                genPaperDto.setPaperName("");
+                if (!paperMap.get("msg").equals("success")) {
+                    break;
+                }
             }
         } else if (genPaperDto.getGenNumber() == 1) {
             paperMap = genPaperService.genPaper(genPaperDto);

+ 1 - 2
cqb-paper/src/main/java/com/qmth/cqb/paper/dao/ExtractConfigRepo.java

@@ -3,9 +3,8 @@ package com.qmth.cqb.paper.dao;
 import org.springframework.data.mongodb.repository.MongoRepository;
 import org.springframework.data.repository.query.QueryByExampleExecutor;
 
-import com.qmth.cqb.paper.model.ExamPaper;
 import com.qmth.cqb.paper.model.ExtractConfig;
 
-public interface ExtractConfigRepo extends MongoRepository<ExtractConfig, Long>,QueryByExampleExecutor<ExtractConfig> {
+public interface ExtractConfigRepo extends MongoRepository<ExtractConfig, String>,QueryByExampleExecutor<ExtractConfig> {
 
 }

+ 91 - 79
cqb-paper/src/main/java/com/qmth/cqb/paper/dto/PaperDetailUnitExp.java

@@ -1,79 +1,91 @@
-package com.qmth.cqb.paper.dto;
-
-import java.io.Serializable;
-
-import com.qmth.cqb.question.model.Question;
-
-import cn.com.qmth.examcloud.common.dto.question.enums.QuesStructType;
-
-/**
- * 试卷小题导出dto Created by songyue on 17/3/15.
- */
-public class PaperDetailUnitExp implements Serializable {
-
-    private static final long serialVersionUID = 6507445685386413261L;
-
-    private String id;
-
-    private Integer number;// 小题序号
-
-    private Double score;// 小题分数
-
-    private QuesStructType questionType;// 小题类型
-
-    private Question question;// 关联试题
-
-    private String quesId;// 关联试题Id
-
-    public static long getSerialVersionUID() {
-        return serialVersionUID;
-    }
-
-    public String getId() {
-        return id;
-    }
-
-    public void setId(String id) {
-        this.id = id;
-    }
-
-    public Integer getNumber() {
-        return number;
-    }
-
-    public void setNumber(Integer number) {
-        this.number = number;
-    }
-
-    public Double getScore() {
-        return score;
-    }
-
-    public void setScore(Double score) {
-        this.score = score;
-    }
-
-    public QuesStructType getQuestionType() {
-        return questionType;
-    }
-
-    public void setQuestionType(QuesStructType questionType) {
-        this.questionType = questionType;
-    }
-
-    public Question getQuestion() {
-        return question;
-    }
-
-    public void setQuestion(Question question) {
-        this.question = question;
-    }
-
-    public String getQuesId() {
-        return quesId;
-    }
-
-    public void setQuesId(String quesId) {
-        this.quesId = quesId;
-    }
-}
+package com.qmth.cqb.paper.dto;
+
+import java.io.Serializable;
+import java.util.List;
+
+import com.qmth.cqb.question.model.Question;
+
+import cn.com.qmth.examcloud.common.dto.question.enums.QuesStructType;
+
+/**
+ * 试卷小题导出dto Created by songyue on 17/3/15.
+ */
+public class PaperDetailUnitExp implements Serializable {
+
+    private static final long serialVersionUID = 6507445685386413261L;
+
+    private String id;
+
+    private Integer number;// 小题序号
+
+    private Double score;// 小题分数
+
+    private QuesStructType questionType;// 小题类型
+
+    private Question question;// 关联试题
+
+    private String quesId;// 关联试题Id
+
+    private List<Double> subScoreList;// 对应套题的情况下,各子题的分数分布
+
+    public static long getSerialVersionUID() {
+        return serialVersionUID;
+    }
+
+    public String getId() {
+        return id;
+    }
+
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    public Integer getNumber() {
+        return number;
+    }
+
+    public void setNumber(Integer number) {
+        this.number = number;
+    }
+
+    public Double getScore() {
+        return score;
+    }
+
+    public void setScore(Double score) {
+        this.score = score;
+    }
+
+    public QuesStructType getQuestionType() {
+        return questionType;
+    }
+
+    public void setQuestionType(QuesStructType questionType) {
+        this.questionType = questionType;
+    }
+
+    public Question getQuestion() {
+        return question;
+    }
+
+    public void setQuestion(Question question) {
+        this.question = question;
+    }
+
+    public String getQuesId() {
+        return quesId;
+    }
+
+    public void setQuesId(String quesId) {
+        this.quesId = quesId;
+    }
+
+    public List<Double> getSubScoreList() {
+        return subScoreList;
+    }
+
+    public void setSubScoreList(List<Double> subScoreList) {
+        this.subScoreList = subScoreList;
+    }
+
+}

+ 35 - 25
cqb-paper/src/main/java/com/qmth/cqb/paper/model/ExamPaper.java

@@ -3,7 +3,7 @@ package com.qmth.cqb.paper.model;
 import java.io.Serializable;
 
 import org.springframework.data.annotation.Id;
-import org.springframework.data.mongodb.core.index.Indexed;
+import org.springframework.data.mongodb.core.mapping.DBRef;
 
 public class ExamPaper implements Serializable {
 
@@ -11,23 +11,32 @@ public class ExamPaper implements Serializable {
 
     @Id
     private String id;
-
-    @Indexed(unique = true)
+    /**
+     * 考试ID
+     */
     private Long examId;
-
+    /**
+     * 课程代码
+     */
     private String courseCode;
-
+    /**
+     * 试卷类型
+     */
     private String groupCode;
-
-    private String paperId;
-
-    private Integer extractCount;// 抽取试卷次数
-
-    private Double weight;// 抽取权重比例
-
-    public static long getSerialVersionUID() {
-        return serialVersionUID;
-    }
+    /**
+     * 关联试卷
+     */
+    @DBRef
+    private Paper paper;
+    /**
+     * 抽取试卷次数
+     */
+    private Integer extractCount;
+    /**
+     * 抽取权重比例
+     * 整数类型 例如:70%  数据库里存70
+     */
+    private Integer weight;
 
     public String getId() {
         return id;
@@ -61,14 +70,6 @@ public class ExamPaper implements Serializable {
         this.groupCode = groupCode;
     }
 
-    public String getPaperId() {
-        return paperId;
-    }
-
-    public void setPaperId(String paperId) {
-        this.paperId = paperId;
-    }
-
     public Integer getExtractCount() {
         return extractCount;
     }
@@ -77,11 +78,20 @@ public class ExamPaper implements Serializable {
         this.extractCount = extractCount;
     }
 
-    public Double getWeight() {
+    public Integer getWeight() {
         return weight;
     }
 
-    public void setWeight(Double weight) {
+    public void setWeight(Integer weight) {
         this.weight = weight;
     }
+
+	public Paper getPaper() {
+		return paper;
+	}
+
+	public void setPaper(Paper paper) {
+		this.paper = paper;
+	}
+
 }

+ 181 - 15
cqb-paper/src/main/java/com/qmth/cqb/paper/model/ExtractConfig.java

@@ -1,27 +1,105 @@
 package com.qmth.cqb.paper.model;
 
 import java.io.Serializable;
+import java.util.List;
 import java.util.Map;
 
 import org.springframework.data.annotation.Id;
 
 import com.qmth.cqb.utils.enums.ExtractPolicy;
 
+/**
+ * 调卷规则
+ * @author chenken
+ *
+ */
 public class ExtractConfig implements Serializable {
 
     private static final long serialVersionUID = -5234564748332601375L;
-
+    /**
+     * 调卷规则ID
+     */
     @Id
     private String id;
-
+    /**
+     * 考试ID
+     */
     private Long examId;
-
+    /**
+     * 考试类型
+     * 		网络考试
+     * 		传统考试
+     */
+    private String examType;
+    /**
+     * 考试名称
+     */
+    private String examName;
+    /**
+     * 课程名称
+     */
+    private String courseName;
+    /**
+     * 课程代码
+     */
     private String courseCode;
-
-    private ExtractPolicy policy;// 抽卷规则
-
-    private Map params;// 类型参数
-
+    /**
+     * 调卷类型
+     * 		成套调用
+     * 		重组调用
+     */
+    private String callType;
+    /**
+     * 是否生成 1:生成 0:没生成
+     */
+    private Short ifFinish;
+    /**
+     * 已经生成的试卷ID Map
+     * 数据结构:
+     * {
+     * 		"A":"0001",
+     * 		"B":"0002"
+     * }
+     * A 类型下生成的paperId为 0001
+     * B 类型下生成的paperId为 0002
+     */
+    private Map<String,String> finishedPaperIdMap;
+    /**
+     * 抽取试卷对象集合
+     */
+    private List<ExamPaper> examPaperList;
+    /**
+     * 小题乱序
+     * 1:乱序
+     * 0:不乱序
+     */
+    private Short scrambling_the_question_order;
+    /**
+     * 选项乱序
+     * 1:乱序
+     * 0:不乱序
+     */
+    private Short scrambling_the_option_order;
+    
+    /**
+     * 抽卷规则
+     */
+    private ExtractPolicy policy;
+    /**
+     * 类型参数
+     */
+    private Map<String,Object> params;
+    /**
+     * 机构ID
+     */
+    private String orgId;
+    
+    public ExtractConfig(){}
+    
+    public ExtractConfig(String id){
+    	this.id = id;
+    }
+    
     public Long getExamId() {
         return examId;
     }
@@ -53,17 +131,105 @@ public class ExtractConfig implements Serializable {
     public void setPolicy(ExtractPolicy policy) {
         this.policy = policy;
     }
-
-    public Map getParams() {
+    
+    public String getExamType() {
+		return examType;
+	}
+
+	public void setExamType(String examType) {
+		this.examType = examType;
+	}
+
+	public String getExamName() {
+		return examName;
+	}
+
+	public void setExamName(String examName) {
+		this.examName = examName;
+	}
+
+	public String getCourseName() {
+		return courseName;
+	}
+
+	public void setCourseName(String courseName) {
+		this.courseName = courseName;
+	}
+
+	public String getCallType() {
+		return callType;
+	}
+
+	public void setCallType(String callType) {
+		this.callType = callType;
+	}
+
+	public Short getIfFinish() {
+		return ifFinish;
+	}
+
+	public void setIfFinish(Short ifFinish) {
+		if(ifFinish==null){
+			this.ifFinish = 0;
+		}else{
+			this.ifFinish = ifFinish;
+		}
+	}
+
+	public Map<String,Object> getParams() {
         return params;
     }
 
-    public void setParams(Map params) {
+    public void setParams(Map<String,Object> params) {
         this.params = params;
     }
 
-    public static long getSerialversionuid() {
-        return serialVersionUID;
-    }
-
+	public String getOrgId() {
+		return orgId;
+	}
+
+	public void setOrgId(String orgId) {
+		this.orgId = orgId;
+	}
+
+	public List<ExamPaper> getExamPaperList() {
+		return examPaperList;
+	}
+
+	public void setExamPaperList(List<ExamPaper> examPaperList) {
+		this.examPaperList = examPaperList;
+	}
+
+	public Short getScrambling_the_question_order() {
+		return scrambling_the_question_order;
+	}
+
+	public void setScrambling_the_question_order(Short scrambling_the_question_order) {
+		if(scrambling_the_question_order==null){
+			this.scrambling_the_question_order = 0;
+		}else{
+			this.scrambling_the_question_order = scrambling_the_question_order;
+		}
+	}
+
+	public Short getScrambling_the_option_order() {
+		return scrambling_the_option_order;
+	}
+
+	public void setScrambling_the_option_order(Short scrambling_the_option_order) {
+		if(scrambling_the_option_order==null){
+			this.scrambling_the_option_order = 0;
+		}else{
+			this.scrambling_the_option_order = scrambling_the_option_order;
+		}
+	}
+
+	public Map<String, String> getFinishedPaperIdMap() {
+		return finishedPaperIdMap;
+	}
+
+	public void setFinishedPaperIdMap(Map<String, String> finishedPaperIdMap) {
+		this.finishedPaperIdMap = finishedPaperIdMap;
+	}
+    
 }

+ 34 - 24
cqb-paper/src/main/java/com/qmth/cqb/paper/model/Paper.java

@@ -3,53 +3,56 @@ package com.qmth.cqb.paper.model;
 import java.io.Serializable;
 import java.util.Map;
 
+import org.springframework.data.annotation.Id;
+import org.springframework.data.mongodb.core.index.Indexed;
+
 import com.qmth.cqb.utils.CommonUtils;
 import com.qmth.cqb.utils.enums.PaperStatus;
 import com.qmth.cqb.utils.enums.PaperType;
-import org.springframework.data.annotation.Id;
-import org.springframework.data.mongodb.core.index.Indexed;
 
 /**
  * @author songyue
  *
  */
-public class Paper implements Serializable { 
-	
-	private static final long serialVersionUID = 5259364047220441490L;
+public class Paper implements Serializable {
+
+    private static final long serialVersionUID = 5259364047220441490L;
 
-	@Id
+    @Id
     private String id;
 
     @Indexed(unique = true)
-    private String name;//试卷名称
-    
-    private String title;//试卷标题
-    
-    private Double totalScore;//试卷总分
-    
-    private String creator;//创建人id
+    private String name;// 试卷名称
+
+    private String title;// 试卷标题
+
+    private Double totalScore;// 试卷总分
 
-    private Integer paperDetailCount;//大题数量
+    private String creator;// 创建人id
 
-    private Integer unitCount;//小题数量
+    private Integer paperDetailCount;// 大题数量
 
-    private String createTime;//创建时间
+    private Integer unitCount;// 小题数量
 
-    private String lastModifyName;//最后修改人名称
+    private String createTime;// 创建时间
 
-    private String word;//原始试卷word
+    private String lastModifyName;// 最后修改人名称
 
-    private String html;//原始试卷html
+    private String word;// 原始试卷word
 
-    private PaperStatus paperStatus;//试卷状态(待审核、通过、不通过)
+    private String html;// 原始试卷html
 
-    private PaperType paperType;//试卷类型(导入、组卷)
+    private PaperStatus paperStatus;// 试卷状态(待审核、通过、不通过)
+
+    private PaperType paperType;// 试卷类型(导入、组卷)
 
     private String courseNo;
 
     private String courseName;
 
-    private Map<String,String> params;//导入试卷属性
+    private String orgId;
+
+    private Map<String, String> params;// 导入试卷属性
 
     public static long getSerialVersionUID() {
         return serialVersionUID;
@@ -183,9 +186,16 @@ public class Paper implements Serializable {
         this.unitCount = unitCount;
     }
 
-    public Paper() {
-		this.createTime = CommonUtils.getCurDateTime();
+    public String getOrgId() {
+        return orgId;
     }
 
+    public void setOrgId(String orgId) {
+        this.orgId = orgId;
+    }
+
+    public Paper() {
+        this.createTime = CommonUtils.getCurDateTime();
+    }
 
 }

+ 91 - 5
cqb-paper/src/main/java/com/qmth/cqb/paper/model/PaperDetailUnit.java

@@ -1,18 +1,21 @@
 package com.qmth.cqb.paper.model;
 
-import java.io.Serializable;
-
+import cn.com.qmth.examcloud.common.dto.question.enums.QuesStructType;
+import com.qmth.cqb.question.model.Question;
 import org.springframework.data.annotation.Id;
 import org.springframework.data.mongodb.core.mapping.DBRef;
 
-import com.qmth.cqb.question.model.Question;
-
-import cn.com.qmth.examcloud.common.dto.question.enums.QuesStructType;
+import java.io.Serializable;
+import java.text.DecimalFormat;
+import java.util.ArrayList;
+import java.util.List;
 
 public class PaperDetailUnit implements Serializable, Comparable<PaperDetailUnit> {
 
     private static final long serialVersionUID = -8854150484922002075L;
 
+    public static DecimalFormat SCORE_FORMATER = new DecimalFormat("####.#");
+
     @Id
     private String id;
 
@@ -23,6 +26,8 @@ public class PaperDetailUnit implements Serializable, Comparable<PaperDetailUnit
 
     private Double score;// 小题分数
 
+    private List<Double> subScoreList;//对应套题的情况下,各子题的分数分布
+
     @DBRef
     private PaperDetail paperDetail;// 关联的大题
 
@@ -65,6 +70,23 @@ public class PaperDetailUnit implements Serializable, Comparable<PaperDetailUnit
 
     public void setScore(Double score) {
         this.score = score;
+        //非套题或试题未设置时,不做额外处理
+        if (questionType != QuesStructType.NESTED_ANSWER_QUESTION || question == null) {
+            return;
+        }
+        //当前分数设置为空时,同时设置子题分数为空
+        if (score == null) {
+            subScoreList = null;
+            return;
+        }
+        //总分与子题分数之和相同,则不做额外处理
+        if (subScoreList != null && subScoreList.size() > 0 && getSubScoreSum() == score) {
+            return;
+        }
+        //根据试题与总分设置情况重置子题分数
+        if (question.getSubQuestions() != null) {
+            initSubScoreList(score, question.getSubQuestions());
+        }
     }
 
     public PaperDetail getPaperDetail() {
@@ -89,6 +111,21 @@ public class PaperDetailUnit implements Serializable, Comparable<PaperDetailUnit
 
     public void setQuestion(Question question) {
         this.question = question;
+        //非套题或总分未设置时,不做额外处理
+        if (questionType != QuesStructType.NESTED_ANSWER_QUESTION || score == null) {
+            return;
+        }
+        //当前试题或子题列表为空时,同时设置子题分数为空
+        if (question == null || question.getSubQuestions() == null) {
+            subScoreList = null;
+            return;
+        }
+        //当前试题子题数量与子题分数数量相同,不做额外处理
+        if (subScoreList != null && subScoreList.size() == question.getSubQuestions().size()) {
+            return;
+        }
+        //根据试题与总分设置情况重置子题分数
+        initSubScoreList(score, question.getSubQuestions());
     }
 
     public String getCreator() {
@@ -107,6 +144,21 @@ public class PaperDetailUnit implements Serializable, Comparable<PaperDetailUnit
         this.createTime = createTime;
     }
 
+    public List<Double> getSubScoreList() {
+        return subScoreList;
+    }
+
+    public void setSubScoreList(List<Double> subScoreList) {
+        this.subScoreList = subScoreList;
+        if (subScoreList != null) {
+            double totalScore = 0;
+            for (Double score : subScoreList) {
+                totalScore += score;
+            }
+            this.score = totalScore;
+        }
+    }
+
     public PaperDetailUnit() {
     }
 
@@ -121,4 +173,38 @@ public class PaperDetailUnit implements Serializable, Comparable<PaperDetailUnit
         }
         return -1;
     }
+
+    /**
+     * 根据预设总分自动拆解套题子题的分数分布
+     * 目前采取均分后累加到最后一题的做法
+     *
+     * @param totalScore
+     * @param questionList
+     */
+    private void initSubScoreList(double totalScore, List<Question> questionList) {
+        List<Double> scoreList = new ArrayList<>();
+        int count = questionList.size();
+        if (count > 0) {
+            int baseScore = (int) (totalScore / count);
+            double leftScore = totalScore;
+            for (int i = 0; i < count; i++) {
+                scoreList.add((double) baseScore);
+                leftScore -= baseScore;
+            }
+            if (leftScore > 0) {
+                scoreList.set(count - 1, baseScore + leftScore);
+            }
+            this.subScoreList = scoreList;
+        }
+    }
+
+    private double getSubScoreSum() {
+        double totalScore = 0;
+        if (subScoreList != null) {
+            for (Double score : subScoreList) {
+                totalScore += score;
+            }
+        }
+        return totalScore;
+    }
 }

+ 64 - 42
cqb-paper/src/main/java/com/qmth/cqb/paper/model/PaperSearchInfo.java

@@ -1,63 +1,85 @@
 package com.qmth.cqb.paper.model;
 
 import java.io.Serializable;
-import java.util.Map;
 
-public class PaperSearchInfo implements Serializable{
+import com.qmth.cqb.utils.enums.PaperStatus;
 
-	private static final long serialVersionUID = 8273918442524569201L;
+public class PaperSearchInfo implements Serializable {
 
-    private String name;//试卷名称
+    private static final long serialVersionUID = 8273918442524569201L;
 
-    private String createTime;//创建时间
+    private String name;// 试卷名称
 
-    private String creator;//录入员
-    
-    private String courseNo;//课程代码
+    private String createTime;// 创建时间
 
-	private String [] paperIds;
+    private String creator;// 录入员
 
-	public static long getSerialVersionUID() {
-		return serialVersionUID;
-	}
+    private String courseNo;// 课程代码
 
-	public String getName() {
-		return name;
-	}
+    private String orgId;// 机构Id
 
-	public void setName(String name) {
-		this.name = name;
-	}
+    private PaperStatus paperStatus; // 试卷审核状态
 
-	public String getCreateTime() {
-		return createTime;
-	}
+    private String[] paperIds;
 
-	public void setCreateTime(String createTime) {
-		this.createTime = createTime;
-	}
+    public static long getSerialVersionUID() {
+        return serialVersionUID;
+    }
 
-	public String getCreator() {
-		return creator;
-	}
+    public String getName() {
+        return name;
+    }
 
-	public void setCreator(String creator) {
-		this.creator = creator;
-	}
+    public void setName(String name) {
+        this.name = name;
+    }
 
-	public String getCourseNo() {
-		return courseNo;
-	}
+    public String getCreateTime() {
+        return createTime;
+    }
 
-	public void setCourseNo(String courseNo) {
-		this.courseNo = courseNo;
-	}
+    public void setCreateTime(String createTime) {
+        this.createTime = createTime;
+    }
 
-	public String[] getPaperIds() {
-		return paperIds;
-	}
+    public String getCreator() {
+        return creator;
+    }
+
+    public void setCreator(String creator) {
+        this.creator = creator;
+    }
+
+    public String getCourseNo() {
+        return courseNo;
+    }
+
+    public void setCourseNo(String courseNo) {
+        this.courseNo = courseNo;
+    }
+
+    public String[] getPaperIds() {
+        return paperIds;
+    }
+
+    public void setPaperIds(String[] paperIds) {
+        this.paperIds = paperIds;
+    }
+
+    public String getOrgId() {
+        return orgId;
+    }
+
+    public void setOrgId(String orgId) {
+        this.orgId = orgId;
+    }
+
+    public PaperStatus getPaperStatus() {
+        return paperStatus;
+    }
+
+    public void setPaperStatus(PaperStatus paperStatus) {
+        this.paperStatus = paperStatus;
+    }
 
-	public void setPaperIds(String[] paperIds) {
-		this.paperIds = paperIds;
-	}
 }

+ 81 - 70
cqb-paper/src/main/java/com/qmth/cqb/paper/model/PaperStruct.java

@@ -1,109 +1,120 @@
 package com.qmth.cqb.paper.model;
 
 import java.io.Serializable;
-import java.util.Map;
 import java.util.List;
+import java.util.Map;
 
-import com.qmth.cqb.utils.CommonUtils;
 import org.springframework.data.annotation.Id;
 import org.springframework.data.mongodb.core.index.Indexed;
 
+import com.qmth.cqb.utils.CommonUtils;
+
 /**
- * 试卷结构
- * Created by songyue on 16/12/28.
+ * 试卷结构 Created by songyue on 16/12/28.
  */
 
-public class PaperStruct implements Serializable{
+public class PaperStruct implements Serializable {
 
-	private static final long serialVersionUID = 6380530617488717881L;
+    private static final long serialVersionUID = 6380530617488717881L;
 
-	@Id
+    @Id
     private String id;
 
     @Indexed(unique = true)
-    private String name;//试卷结构名称
-        
-    private Double totalScore;//总分
-    
-    private Integer detailCount;//大题数量
-    
+    private String name;// 试卷结构名称
+
+    private Double totalScore;// 总分
+
+    private Integer detailCount;// 大题数量
+
     private Map params;
 
-	private List<PaperDetailStruct> paperDetailStructs;//大题
+    private List<PaperDetailStruct> paperDetailStructs;// 大题
+
+    private String creator;// 创建人id
+
+    private String createTime;// 创建时间
+
+    private String orgId;// 机构ID
+
+    public static long getSerialVersionUID() {
+        return serialVersionUID;
+    }
 
-	private String creator;//创建人id
+    public String getId() {
+        return id;
+    }
 
-	private String createTime;//创建时间
+    public void setId(String id) {
+        this.id = id;
+    }
 
-	public static long getSerialVersionUID() {
-		return serialVersionUID;
-	}
+    public String getName() {
+        return name;
+    }
 
-	public String getId() {
-		return id;
-	}
+    public void setName(String name) {
+        this.name = name;
+    }
 
-	public void setId(String id) {
-		this.id = id;
-	}
+    public Double getTotalScore() {
+        return totalScore;
+    }
 
-	public String getName() {
-		return name;
-	}
+    public void setTotalScore(Double totalScore) {
+        this.totalScore = totalScore;
+    }
 
-	public void setName(String name) {
-		this.name = name;
-	}
+    public Integer getDetailCount() {
+        return detailCount;
+    }
 
-	public Double getTotalScore() {
-		return totalScore;
-	}
+    public void setDetailCount(Integer detailCount) {
+        this.detailCount = detailCount;
+    }
 
-	public void setTotalScore(Double totalScore) {
-		this.totalScore = totalScore;
-	}
+    public Map getParams() {
+        return params;
+    }
 
-	public Integer getDetailCount() {
-		return detailCount;
-	}
+    public void setParams(Map params) {
+        this.params = params;
+    }
 
-	public void setDetailCount(Integer detailCount) {
-		this.detailCount = detailCount;
-	}
+    public List<PaperDetailStruct> getPaperDetailStructs() {
+        return paperDetailStructs;
+    }
 
-	public Map getParams() {
-		return params;
-	}
+    public void setPaperDetailStructs(List<PaperDetailStruct> paperDetailStructs) {
+        this.paperDetailStructs = paperDetailStructs;
+    }
 
-	public void setParams(Map params) {
-		this.params = params;
-	}
+    public String getCreator() {
+        return creator;
+    }
 
-	public List<PaperDetailStruct> getPaperDetailStructs() {
-		return paperDetailStructs;
-	}
+    public void setCreator(String creator) {
+        this.creator = creator;
+    }
 
-	public void setPaperDetailStructs(List<PaperDetailStruct> paperDetailStructs) {
-		this.paperDetailStructs = paperDetailStructs;
-	}
+    public String getCreateTime() {
+        return createTime;
+    }
 
-	public String getCreator() {
-		return creator;
-	}
+    public void setCreateTime(String createTime) {
+        this.createTime = createTime;
+    }
 
-	public void setCreator(String creator) {
-		this.creator = creator;
-	}
+    public PaperStruct() {
+        this.createTime = CommonUtils.getCurDateTime();
+    }
 
-	public String getCreateTime() {
-		return createTime;
-	}
+    public String getOrgId() {
+        return orgId;
+    }
 
-	public void setCreateTime(String createTime) {
-		this.createTime = createTime;
-	}
+    public void setOrgId(String orgId) {
+        this.orgId = orgId;
+    }
 
-	public PaperStruct() {
-		this.createTime = CommonUtils.getCurDateTime();
-	}
 }

+ 12 - 1
cqb-paper/src/main/java/com/qmth/cqb/paper/model/PaperStructSearchInfo.java

@@ -5,7 +5,7 @@ import java.io.Serializable;
 /**
  * Created by songyue on 17/3/27.
  */
-public class PaperStructSearchInfo implements Serializable{
+public class PaperStructSearchInfo implements Serializable {
 
     private static final long serialVersionUID = 5282899855557734214L;
 
@@ -15,6 +15,8 @@ public class PaperStructSearchInfo implements Serializable{
 
     private String createtime;
 
+    private String orgId;
+
     public static long getSerialVersionUID() {
         return serialVersionUID;
     }
@@ -42,4 +44,13 @@ public class PaperStructSearchInfo implements Serializable{
     public void setCreatetime(String createtime) {
         this.createtime = createtime;
     }
+
+    public String getOrgId() {
+        return orgId;
+    }
+
+    public void setOrgId(String orgId) {
+        this.orgId = orgId;
+    }
+
 }

+ 17 - 0
cqb-paper/src/main/java/com/qmth/cqb/paper/service/ExamPaperService.java

@@ -0,0 +1,17 @@
+package com.qmth.cqb.paper.service;
+
+import java.util.List;
+
+import com.qmth.cqb.paper.model.ExamPaper;
+
+/**
+ * @author  	chenken
+ * @date    	2017年4月17日 上午10:45:26
+ * @company 	QMTH
+ * @description ExamPaperService.java
+ */
+public interface ExamPaperService {
+	
+	public List<ExamPaper> findExamPaperList(ExamPaper condition);
+}
+

+ 30 - 0
cqb-paper/src/main/java/com/qmth/cqb/paper/service/ExamPaperServiceImpl.java

@@ -0,0 +1,30 @@
+package com.qmth.cqb.paper.service;
+
+import java.util.List;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.domain.Example;
+import org.springframework.stereotype.Service;
+
+import com.qmth.cqb.paper.dao.ExamPaperRepo;
+import com.qmth.cqb.paper.model.ExamPaper;
+
+/**
+ * @author  	chenken
+ * @date    	2017年4月17日 上午10:46:40
+ * @company 	QMTH
+ * @description ExamPaperServiceImpl.java
+ */
+@Service("examPaperService")
+public class ExamPaperServiceImpl implements ExamPaperService {
+	
+	@Autowired
+	private ExamPaperRepo examPaperRepo;
+	
+	@Override
+	public List<ExamPaper> findExamPaperList(ExamPaper condition) {
+		return examPaperRepo.findAll(Example.of(condition));
+	}
+
+}
+

+ 50 - 0
cqb-paper/src/main/java/com/qmth/cqb/paper/service/ExtractConfigService.java

@@ -0,0 +1,50 @@
+package com.qmth.cqb.paper.service;
+
+import com.qmth.cqb.paper.model.ExtractConfig;
+import com.qmth.cqb.paper.model.Paper;
+
+/**
+ * 
+ * @author  	chenken
+ * @date    	2017年4月14日 下午6:08:15
+ * @company 	QMTH
+ * @description 调卷规则接口
+ */
+public interface ExtractConfigService {
+	/**
+	 * 根据考试ID和课程code获取规则
+	 * @param examId
+	 * @param courseCode
+	 * @return
+	 */
+	public ExtractConfig findConfig(ExtractConfig extractConfig);
+	/**
+	 * 根据ID获取调卷规则
+	 * @param id
+	 * @return
+	 */
+	public ExtractConfig findConfigById(String id);
+	/**
+	 * 保存调卷规则
+	 */
+	public void saveExtractConfig(ExtractConfig extractConfig);
+	/**
+	 * 按照设定调卷规则生成一套试卷
+	 * 1.根据extractConfigId取出调卷规则
+	 * 2.根据ExamPaper集合得出每个类型下应该抽取的试卷,并返回 试卷类型--->试卷的map
+	 * 3.根据小题乱序和选项乱序规则,重组试卷
+	 * 4.得到试卷类型--->试卷ID的map,设置到finishedPaperIdMap属性中
+	 * 5.如果 是第一次生成试卷,保存finishedPaperIdMap
+	 * @param extractConfigId	规则 ID
+	 * @return 
+	 */
+	public void makePaperByConfig(String extractConfigId);
+	/**
+	 * 根据给定试卷重组试卷,生成新的试卷
+	 * @param paper					给定的试卷
+	 * @param upSetQuestionOrder	小题乱序		1:乱序  0:不乱序
+	 * @param upSetOptionOrder		选项乱序		1:乱序  0:不乱序
+	 * @return
+	 */
+	public Paper recombinationPaper(Paper paper,int upSetQuestionOrder,int upSetOptionOrder);
+}

+ 256 - 0
cqb-paper/src/main/java/com/qmth/cqb/paper/service/ExtractConfigServiceImpl.java

@@ -0,0 +1,256 @@
+package com.qmth.cqb.paper.service;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Random;
+import java.util.Set;
+
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.domain.Example;
+import org.springframework.stereotype.Service;
+
+import cn.com.qmth.examcloud.common.dto.question.enums.QuesStructType;
+
+import com.qmth.cqb.paper.dao.ExtractConfigRepo;
+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.model.ExamPaper;
+import com.qmth.cqb.paper.model.ExtractConfig;
+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.question.dao.QuesRepo;
+import com.qmth.cqb.question.model.QuesOption;
+import com.qmth.cqb.question.model.Question;
+
+/**
+ * 
+ * @author  	chenken
+ * @date    	2017年4月14日 下午6:07:55
+ * @company 	QMTH
+ * @description ExtractConfigServiceImpl.java
+ */
+@Service("extractConfigService")
+public class ExtractConfigServiceImpl implements ExtractConfigService {
+	
+	@Autowired
+    private ExtractConfigRepo extractConfigRepo;
+	
+	@Autowired
+	private PaperDetailRepo paperDetailRepo;
+
+    @Autowired
+    private PaperDetailUnitRepo paperDetailUnitRepo;
+    
+    @Autowired
+    private PaperDetailUnitService paperDetailUnitService;
+    
+    @Autowired
+    PaperService paperService;
+    
+    @Autowired
+    PaperRepo paperRepo;
+    
+    @Autowired
+    QuesRepo quesRepo;
+    
+	@Override
+	public ExtractConfig findConfig(ExtractConfig condition) {
+		if(condition.getExamId()==null){
+			return null;
+		}
+		if(StringUtils.isBlank(condition.getCourseCode())){
+			return null;
+		}
+		ExtractConfig tempConfig =  extractConfigRepo.findOne(Example.of(condition));
+        return tempConfig;
+	}
+
+	@Override
+	public void saveExtractConfig(ExtractConfig extractConfig) {
+		if(extractConfig.getScrambling_the_question_order()==null){
+			extractConfig.setScrambling_the_question_order((short) 0);
+		}
+		if(extractConfig.getScrambling_the_option_order()==null){
+			extractConfig.setScrambling_the_option_order((short) 0);
+		}
+		List<ExamPaper> examPapers = extractConfig.getExamPaperList();
+		for(int i=0;i<examPapers.size();i++){
+			ExamPaper examPaper = examPapers.get(i);
+			Paper paper = examPaper.getPaper();
+			paper = paperRepo.findOne(paper.getId());
+			examPaper.setPaper(paper);
+		}
+		extractConfigRepo.save(extractConfig);
+	}
+
+	@Override
+	public ExtractConfig findConfigById(String id) {
+		if(StringUtils.isBlank(id)){
+			return null;
+		}
+		return extractConfigRepo.findOne(id);
+	}
+	
+	@Override
+	public void makePaperByConfig(String extractConfigId) {
+		Map<String, String> finishedPaperIdMap = new HashMap<String, String>();
+		//取出调卷规则
+		ExtractConfig extractConfig = this.findConfigById(extractConfigId);
+		if(extractConfig==null){
+			throw new RuntimeException("调卷规则不存在");
+		}
+		//获得抽取好的试卷
+		Map<String,Paper> paperMap = this.getExamPaperByProbability(extractConfig.getExamPaperList());
+        for (Map.Entry<String, Paper> entry : paperMap.entrySet()) {
+        	String key = entry.getKey();
+        	//根据原有试卷重新组卷得到新试卷
+        	Paper newPaper = this.recombinationPaper(entry.getValue(), 
+							        				 extractConfig.getScrambling_the_question_order(), 
+							        				 extractConfig.getScrambling_the_option_order());
+        	finishedPaperIdMap.put(key, newPaper.getId());
+        }
+        /**
+         * 设置map,并保存调卷规则
+         * 如果已经设置过了,就不再设置
+         */
+        if(extractConfig.getIfFinish()==null){
+        	extractConfig.setFinishedPaperIdMap(finishedPaperIdMap);
+        	extractConfig.setIfFinish((short)1);
+        	extractConfigRepo.save(extractConfig);
+        }
+	}
+
+	/**
+	 * 重组试卷,生成新的试卷
+	 * @param paper					选中的试卷
+	 * @param upSetQuestionOrder	小题乱序		1:乱序  0:不乱序
+	 * @param upSetOptionOrder		选项乱序		1:乱序  0:不乱序
+	 * @return
+	 */
+	public Paper recombinationPaper(Paper paper,int upSetQuestionOrder,int upSetOptionOrder){
+		List<PaperDetail> paperDetails = paperDetailRepo.findByPaper(paper);
+		paper.setId(null);
+		Paper newPaper = paperRepo.save(paper);//重新保存成新的paper
+		for(int i = 0;i<paperDetails.size();i++){
+			PaperDetail paperDetail = paperDetails.get(i);
+			List<PaperDetailUnit> paperDetailUnits = paperDetailUnitService.getUnitsByPaperDetail(paperDetail);
+			paperDetail.setPaper(newPaper);//关联新Paper
+			paperDetail.setId(null);
+			PaperDetail newPaperDetail = paperDetailRepo.save(paperDetail);//保存新的paperDetail
+			//小题乱序
+			if(upSetQuestionOrder==1){
+				Collections.shuffle(paperDetailUnits);//打乱小题List
+			}
+			for(int j = 0;j<paperDetailUnits.size();j++){
+				//重新设置保存PaperDetailUnit、question,
+				PaperDetailUnit paperDetailUnit = paperDetailUnits.get(j);
+				paperDetailUnit.setPaper(newPaper);				//关联新Paper
+				paperDetailUnit.setPaperDetail(newPaperDetail); //关联新paperDetail
+				paperDetailUnit.setNumber(j+1);					//重新设置序号
+				reSavePaperDetailUtilAndQuestion(paperDetailUnit,upSetOptionOrder);
+			}
+			
+		}
+		return newPaper;
+	}
+	
+	/**
+	 * 每个试卷类型取出一套试卷
+	 * {
+	 * 	 A:Paper,
+	 *   B:Paper
+	 * }
+	 * A是试卷类型   Paper是A类型下选定的试卷
+	 * @param examPaperList		
+	 * @return
+	 */
+	private Map<String,Paper> getExamPaperByProbability(List<ExamPaper> examPaperList){
+		Map<String,Paper> paperByTypeMap = new HashMap<String,Paper>();
+		if(examPaperList == null || examPaperList.size() == 0) {
+       	 	return null;  
+        }
+		Map<String,List<ExamPaper>> examPaperMap = new HashMap<String,List<ExamPaper>>();
+		for(int i = 0;i<examPaperList.size();i++){
+			ExamPaper examPaper = examPaperList.get(i);
+			if(!examPaperMap.containsKey(examPaper.getGroupCode())){
+				if(examPaper.getPaper()!=null){
+					List<ExamPaper> epList = new ArrayList<ExamPaper>();
+					epList.add(examPaper);
+					examPaperMap.put(examPaper.getGroupCode(), epList);
+				}
+			}else{
+				if(examPaper.getPaper()!=null){
+					List<ExamPaper> epList = examPaperMap.get(examPaper.getGroupCode());
+					epList.add(examPaper);
+				}
+			}
+		}
+		Set<String> keys = examPaperMap.keySet();
+		Iterator<String> it = keys.iterator();
+		while (it.hasNext()) {
+			String key = it.next();
+			Paper paper = this.getPaperByProbability(examPaperMap.get(key));
+			//不能用原来的paper对象,否则examPaperList中的paper对象会被覆盖
+			Paper newPaper =paperRepo.findOne(paper.getId());
+			paperByTypeMap.put(key,newPaper);
+		}
+        return paperByTypeMap;
+	}
+	
+	/**
+	 * 根据设定几率取出一套试卷
+	 * @param examPaperList
+	 * @return
+	 */
+	private Paper getPaperByProbability(List<ExamPaper> examPaperList){
+		int sum = 0;  
+        for (int i = 0;i<examPaperList.size();i++) {  
+             sum += examPaperList.get(i).getWeight();  
+        }
+        // 从1开始  
+        Integer rand = new Random().nextInt(sum) + 1;  
+        for (int i = 0;i<examPaperList.size();i++) {
+            rand -= examPaperList.get(i).getWeight();
+            // 选中
+            if (rand <= 0) {
+                return examPaperList.get(i).getPaper();
+            }
+        } 
+        return null;
+	}
+	
+	/**
+	 * 重新设置并保存paperDetailUnit和question
+	 * @param paperDetailUnit
+	 * @param upSetOptionOrder
+	 */
+	private void reSavePaperDetailUtilAndQuestion(PaperDetailUnit paperDetailUnit,Integer upSetOptionOrder){
+		Question question = paperDetailUnit.getQuestion();
+		//选项乱序
+		if(upSetOptionOrder==1){
+			//单选或多选
+			if(question.getQuestionType()==QuesStructType.SINGLE_ANSWER_QUESTION||
+			   question.getQuestionType()==QuesStructType.MULTIPLE_ANSWER_QUESTION){
+				List<QuesOption> options = question.getQuesOptions();
+				Collections.shuffle(options);//打乱选项List
+				for(int k = 0;k<options.size();k++){
+					QuesOption quesOption = options.get(k);
+					Character num = (char) (k+64+1);
+					quesOption.setNumber(String.valueOf(num));//重新设置顺序
+				}
+			}
+		}
+		question.setId(null);
+		Question newQuestion = quesRepo.save(question);
+		paperDetailUnit.setQuestion(newQuestion);	//保存新的试题
+		paperDetailUnit.setId(null);
+		paperDetailUnitRepo.save(paperDetailUnit);	//保存新的paperDetailUnit
+	}
+}

+ 147 - 86
cqb-paper/src/main/java/com/qmth/cqb/paper/service/ImportPaperService.java

@@ -14,12 +14,13 @@ import org.apache.commons.io.IOUtils;
 import org.apache.commons.lang3.StringUtils;
 import org.docx4j.openpackaging.packages.WordprocessingMLPackage;
 import org.docx4j.wml.P;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import org.springframework.web.multipart.commons.CommonsMultipartFile;
 
 import com.google.gson.Gson;
-import com.qmth.cqb.base.dao.CourseRepo;
 import com.qmth.cqb.paper.dao.PaperDetailRepo;
 import com.qmth.cqb.paper.dao.PaperDetailUnitRepo;
 import com.qmth.cqb.paper.dao.PaperRepo;
@@ -27,10 +28,10 @@ import com.qmth.cqb.paper.model.ImportPaperCheck;
 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.question.dao.QuesRepo;
 import com.qmth.cqb.question.model.QuesOption;
 import com.qmth.cqb.question.model.Question;
 import com.qmth.cqb.question.model.QuestionType;
+import com.qmth.cqb.question.service.QuesService;
 import com.qmth.cqb.utils.CommonUtils;
 import com.qmth.cqb.utils.enums.PaperStatus;
 import com.qmth.cqb.utils.enums.PaperType;
@@ -38,10 +39,13 @@ import com.qmth.cqb.utils.enums.QuesUnit;
 import com.qmth.cqb.utils.word.DocxProcessUtil;
 
 import cn.com.qmth.examcloud.common.dto.question.enums.QuesStructType;
+import cn.com.qmth.examcloud.common.uac.entity.AccessUser;
 
 @Service
 public class ImportPaperService {
 
+    protected static final Logger log = LoggerFactory.getLogger(ImportPaperService.class);
+
     @Autowired
     PaperRepo paperRepo;
 
@@ -52,7 +56,7 @@ public class ImportPaperService {
     PaperDetailUnitRepo paperDetailUnitRepo;
 
     @Autowired
-    QuesRepo quesRepo;
+    QuesService quesService;
 
     @Autowired
     Gson gson;
@@ -63,12 +67,9 @@ public class ImportPaperService {
     @Autowired
     PaperService paperService;
 
-    @Autowired
-    CourseRepo courseRepo;
-
     /**
      * 获取上传文件
-     * 
+     *
      * @param file
      * @return
      */
@@ -81,6 +82,7 @@ public class ImportPaperService {
             IOUtils.copyLarge(file.getInputStream(), os);
         } catch (Exception e) {
             e.printStackTrace();
+            log.error("上传文件异常:" + e.getMessage());
         } finally {
             IOUtils.closeQuietly(os);
         }
@@ -89,15 +91,23 @@ public class ImportPaperService {
 
     /**
      * 导入试卷
-     * 
+     *
+     * @param paperName
      * @param courseNo
+     * @param file
      * @return
      */
-    public String ImportPaper(String paperName, String courseNo, File file) {
-        String errorInfo = paperService.checkPaperName(paperName);
-        errorInfo += processImportPaper(paperName, courseNo, file);
-        if (StringUtils.isEmpty(errorInfo)) {
-            return "success";
+    public String ImportPaper(String paperName, String courseNo, String courseName, AccessUser user, File file) {
+        String errorInfo = paperService.checkPaperName(paperName, user.getOrgId().toString());
+        if (errorInfo == null) {
+            errorInfo = "";
+            errorInfo += processImportPaper(paperName, courseNo, courseName, user, file);
+            if (StringUtils.isEmpty(errorInfo)) {
+                return "success";
+            } else {
+                log.error("导入异常:" + errorInfo);
+                return errorInfo;
+            }
         } else {
             return errorInfo;
         }
@@ -105,7 +115,7 @@ public class ImportPaperService {
 
     /**
      * 保存导入试卷信息
-     * 
+     *
      * @param paper
      * @param paperDetails
      * @param paperDetailUnits
@@ -128,7 +138,7 @@ public class ImportPaperService {
         }
 
         if (questions.size() > 0) {
-            quesRepo.save(questions);
+            quesService.saveImportQuesList(questions);
         }
 
         if (paperDetailUnits.size() > 0) {
@@ -140,10 +150,10 @@ public class ImportPaperService {
 
     /**
      * 处理导入试卷
-     * 
+     *
      * @param file
      */
-    public String processImportPaper(String paperName, String courseNo, File file) {
+    public String processImportPaper(String paperName, String courseNo, String courseName, AccessUser user, File file) {
 
         WordprocessingMLPackage wordMLPackage;
         WordprocessingMLPackage tmpWordMlPackage;
@@ -166,6 +176,12 @@ public class ImportPaperService {
 
             paper.setCourseNo(courseNo);
 
+            paper.setCourseName(courseName);
+
+            paper.setOrgId(user.getOrgId().toString());
+
+            paper.setCreator(user.getLoginName());
+
             // 设置试卷
             initPaper(paper, paperName);
 
@@ -245,8 +261,10 @@ public class ImportPaperService {
                     }
                     // 设置WordMlPackage二进制数据
                     setPkgByte(question, writePkg);
-
                     // 设置question与Unit集合数据
+                    question.setCourseNo(paper.getCourseNo());
+                    question.setCourseName(paper.getCourseName());
+                    question.setOrgId(user.getOrgId().toString());
                     questions.add(question);
                     paperDetailUnits.add(paperDetailUnit);
 
@@ -264,6 +282,7 @@ public class ImportPaperService {
         } catch (Exception e) {
             e.printStackTrace();
             importPaperCheck.setErrorInfo(e.getMessage());
+            log.error("导入处理异常:" + e.getMessage());
         } finally {
             wordMLPackage = null;
             tmpWordMlPackage = null;
@@ -275,7 +294,7 @@ public class ImportPaperService {
 
     /**
      * 初始化试卷信息
-     * 
+     *
      * @param paper
      * @param paperName
      */
@@ -288,7 +307,7 @@ public class ImportPaperService {
 
     /**
      * 初始化大题头信息
-     * 
+     *
      * @param paper
      * @param paperDetail
      * @param paperDetails
@@ -299,24 +318,18 @@ public class ImportPaperService {
             ImportPaperCheck importPaperCheck) {
 
         paperDetail.setPaper(paper);
-
-        // 设置课程
-        if (StringUtils.isEmpty(paper.getCourseNo()) || StringUtils.isEmpty(paper.getCourseName())) {
-            paper.setCourseNo(getCourseNo(importPaperCheck));
-            paper.setCourseName(getCourseName(importPaperCheck));
-        }
         // 设置大题信息
         paperDetail.setName(importPaperCheck.quesName);
         paperDetail.setUnitCount(Integer.parseInt(importPaperCheck.quesCount));
         paperDetail.setNumber(mainQuesNum);
-
+        paperDetail.setCreator(paper.getCreator());
         paperDetails.add(paperDetail);
 
     }
 
     /**
      * 初始化试卷明细和试题
-     * 
+     *
      * @param paperDetail
      * @param paperDetailUnit
      * @param question
@@ -333,12 +346,13 @@ public class ImportPaperService {
         paperDetailUnit.setPaperDetail(paperDetail);
         paperDetailUnit.setQuestionType(getQuesStructType(importPaperCheck.quesType));
         paperDetailUnit.setScore(Double.parseDouble(importPaperCheck.quesScore));
+        paperDetailUnit.setCreator(paper.getCreator());
         paperDetailUnit.setPaper(paper);
     }
 
     /**
      * 校验试题头标识
-     * 
+     *
      * @param importPaperCheck
      * @return
      */
@@ -377,7 +391,7 @@ public class ImportPaperService {
 
     /**
      * 处理大题头信息
-     * 
+     *
      * @param pList
      * @param index
      * @param importPaperCheck
@@ -420,7 +434,7 @@ public class ImportPaperService {
 
     /**
      * 处理题干信息
-     * 
+     *
      * @param pList
      * @param index
      * @param question
@@ -431,38 +445,42 @@ public class ImportPaperService {
     public void processQuesBody(List pList, int index, Question question, ImportPaperCheck importPaperCheck,
             WordprocessingMLPackage wordMLPackage) throws Exception {
         // 定义题干wordml和html
-        String quesBodyWordMl = "";
-        String quesBodyHtml = "";
+        StringBuilder quesBodyWordMl = new StringBuilder();
+        StringBuilder quesBodyHtml = new StringBuilder();
         int i = 0;
 
         for (i = index; i < pList.size(); i++) {
             P pBody = (P) pList.get(i);
             String tmpText = DocxProcessUtil.getPText(pBody);
 
-            // 判断是否为题干
             if (StringUtils.isEmpty(tmpText)) {
+                // 跳过空白段落
                 continue;
-            } else if (tmpText.matches("^\\d{1,}\\.[\\s\\S]*")
-                    || (!tmpText.matches("^[a-zA-Z]\\.[\\s\\S]*") && !tmpText.startsWith("["))) {
+            } else if (tmpText.matches("^\\d{1,}\\.[\\s\\S]*")) {
+                // 题干第一段
                 // 过滤题干标题
                 pBody = DocxProcessUtil.formatP(pBody, QuesUnit.QUES_BODY);
-
                 String tmpWordMl = DocxProcessUtil.getPWordMl(pBody);
-                String tmpHtml = DocxProcessUtil.docx2Html(tmpWordMl, wordMLPackage);
-                quesBodyWordMl += DocxProcessUtil.formatPWordMl(tmpWordMl);
-                quesBodyHtml += tmpHtml;
-            } else {
+                quesBodyWordMl.append(DocxProcessUtil.formatPWordMl(tmpWordMl));
+                quesBodyHtml.append(DocxProcessUtil.docx2Html(tmpWordMl, wordMLPackage));
+            } else if (tmpText.matches("^[a-zA-Z]\\.[\\s\\S]*") || tmpText.startsWith("[")) {
+                // 检测到选项或其他特殊段落直接退出
                 break;
+            } else {
+                // 题干普通段落
+                String tmpWordMl = DocxProcessUtil.getPWordMl(pBody);
+                quesBodyWordMl.append(DocxProcessUtil.formatPWordMl(tmpWordMl));
+                quesBodyHtml.append(DocxProcessUtil.docx2Html(tmpWordMl, wordMLPackage));
             }
         }
         importPaperCheck.setIndex(i);
-        question.setQuesBody(quesBodyHtml);
-        question.setQuesBodyWord(quesBodyWordMl);
+        question.setQuesBody(quesBodyHtml.toString());
+        question.setQuesBodyWord(quesBodyWordMl.toString());
     }
 
     /**
      * 处理题目选项
-     * 
+     *
      * @param pList
      * @param index
      * @param subQuesNum
@@ -476,12 +494,14 @@ public class ImportPaperService {
             ImportPaperCheck importPaperCheck, WordprocessingMLPackage wordMLPackage) throws Exception {
 
         // 定义试题选项wordml和html
-        String quesOptionWordMl = "";
-        String quesOptionHtml = "";
+        // String quesOptionWordMl = "";
+        // String quesOptionHtml = "";
         // 定义选项集合
         List<QuesOption> quesOptions = new ArrayList<QuesOption>();
         // 定义选项数量
         int optionCount = 0;
+        // 当前所处的选项
+        QuesOption current = null;
 
         int i = 0;
 
@@ -490,21 +510,30 @@ public class ImportPaperService {
             String tmpText = DocxProcessUtil.getPText(pOption);
 
             if (StringUtils.isEmpty(tmpText)) {
+                // 跳过空白段落
                 continue;
-            } else if (tmpText.matches("^[a-zA-Z]\\.[\\s\\S]*")) {// 判断是否为选项
-                // 过滤选项标题
-                pOption = DocxProcessUtil.formatP(pOption, QuesUnit.QUES_OPTION);
-                quesOptionWordMl = DocxProcessUtil.getPWordMl(pOption);
-                quesOptionHtml = DocxProcessUtil.docx2Html(quesOptionWordMl, wordMLPackage);
+            } else if (tmpText.matches("^[a-zA-Z]\\.[\\s\\S]*")) {
+                // 检测到选项开始段落
                 // 创建试题选项
-                QuesOption quesOption = new QuesOption();
-                quesOption.setOptionBody(quesOptionHtml);
-                quesOption.setOptionBodyWord(DocxProcessUtil.formatPWordMl(quesOptionWordMl));
-                quesOption.setNumber(tmpText.substring(0, 1));
-                quesOptions.add(quesOption);
+                current = new QuesOption();
+                current.setNumber(tmpText.substring(0, 1));
+                current.setOptionBody("");
+                current.setOptionBodyWord("");
+                quesOptions.add(current);
                 optionCount++;
-            } else {
+                // 过滤选项标题
+                pOption = DocxProcessUtil.formatP(pOption, QuesUnit.QUES_OPTION);
+                String tmpWordMl = DocxProcessUtil.getPWordMl(pOption);
+                current.setOptionBody(current.getOptionBody() + DocxProcessUtil.docx2Html(tmpWordMl, wordMLPackage));
+                current.setOptionBodyWord(current.getOptionBodyWord() + DocxProcessUtil.formatPWordMl(tmpWordMl));
+            } else if (tmpText.startsWith("[")) {
+                // 非选项的其他内容直接退出
                 break;
+            } else if (current != null) {
+                // 选项的其他段落
+                String tmpWordMl = DocxProcessUtil.getPWordMl(pOption);
+                current.setOptionBody(current.getOptionBody() + DocxProcessUtil.docx2Html(tmpWordMl, wordMLPackage));
+                current.setOptionBodyWord(current.getOptionBodyWord() + DocxProcessUtil.formatPWordMl(tmpWordMl));
             }
         }
         importPaperCheck.setIndex(i);
@@ -519,7 +548,7 @@ public class ImportPaperService {
 
     /**
      * 处理小题尾信息
-     * 
+     *
      * @param pList
      * @param index
      * @param subQuesNum
@@ -531,33 +560,45 @@ public class ImportPaperService {
             PaperDetailUnit paperDetailUnit, ImportPaperCheck importPaperCheck, WordprocessingMLPackage wordMLPackage,
             boolean isNested) throws Exception {
 
-        String quesAnwserWordMl = "";
-        String quesAnwserHtml = "";
+        StringBuilder answerWordML = new StringBuilder("");
+        StringBuilder answerHTML = new StringBuilder("");
         String quesScore = "";
-        Map<String, String> quesParams = new HashMap<String, String>();
+        // Map<String, String> quesParams = new HashMap<String, String>();
         int i = 0;
+        // 是否刚刚检测到答案内容
+        boolean answerStart = false;
 
         for (i = index; i < pList.size(); i++) {
             P pAnswer = (P) pList.get(i);
             String tmpText = DocxProcessUtil.getPText(pAnswer);
             if (StringUtils.isEmpty(tmpText)) {
+                // 跳过空白段落
                 continue;
             } else if (tmpText.startsWith("[答案]")) {
+                // 检测到答案开始段落
                 pAnswer = DocxProcessUtil.formatP(pAnswer, QuesUnit.QUES_ANSWER);
-                quesAnwserWordMl = DocxProcessUtil.getPWordMl(pAnswer);
-                quesAnwserHtml = DocxProcessUtil.docx2Html(quesAnwserWordMl, wordMLPackage);
-
+                String tmpWordMl = DocxProcessUtil.getPWordMl(pAnswer);
+                answerWordML.append(DocxProcessUtil.formatPWordMl(tmpWordMl));
+                answerHTML.append(DocxProcessUtil.docx2Html(tmpWordMl, wordMLPackage));
+                answerStart = true;
             } else if (tmpText.startsWith("[小题分数]")) {
+                // 检测到分数开始段落
                 quesScore = tmpText.replaceAll("\\[小题分数\\]", "").replaceAll("[:|:]", "").trim();
-            } else {
+                answerStart = false;
+            } else if (tmpText.startsWith("[") || tmpText.matches("^\\d{1,}\\.[\\s\\S]*")) {
+                // 检测到其他特殊段落或下一题直接退出
                 break;
+            } else if (answerStart) {
+                String tmpWordMl = DocxProcessUtil.getPWordMl(pAnswer);
+                answerWordML.append(DocxProcessUtil.formatPWordMl(tmpWordMl));
+                answerHTML.append(DocxProcessUtil.docx2Html(tmpWordMl, wordMLPackage));
             }
         }
         importPaperCheck.setIndex(i);
         // 校验答案
-        if (!StringUtils.isEmpty(quesAnwserHtml)) {
-            question.setQuesAnswer(quesAnwserHtml);
-            question.setQuesAnswerWord(DocxProcessUtil.formatPWordMl(quesAnwserWordMl));
+        if (answerHTML.length() > 0) {
+            question.setQuesAnswer(answerHTML.toString());
+            question.setQuesAnswerWord(answerWordML.toString());
         } else {
             importPaperCheck.setErrorInfo(getQuesNumInfo(importPaperCheck.quesName, subQuesNum) + "答案为空或格式不正确\n");
         }
@@ -574,7 +615,7 @@ public class ImportPaperService {
 
     /**
      * 处理套题
-     * 
+     *
      * @param pList
      * @param index
      * @param question
@@ -655,11 +696,25 @@ public class ImportPaperService {
             }
         }
         question.setSubQuestions(subQuesList);
+        // 计算套题总分
+        double totalScore = 0;
+        List<Double> scoreList = new ArrayList<>();
+        for (Question child : subQuesList) {
+            Double score = child.getScore();
+            if (score != null) {
+                totalScore += score;
+                scoreList.add(score);
+            } else {
+                scoreList.add(0d);
+            }
+        }
+        question.setScore(totalScore);
+        paperDetailUnit.setSubScoreList(scoreList);
     }
 
     /**
      * 获取试题类型
-     * 
+     *
      * @param quesType
      * @return
      */
@@ -669,7 +724,7 @@ public class ImportPaperService {
 
     /**
      * 获取试题类型
-     * 
+     *
      * @param quesType
      * @param quesName
      * @return
@@ -681,7 +736,7 @@ public class ImportPaperService {
 
     /**
      * 获取试题结构类型
-     * 
+     *
      * @param quesType
      * @return
      */
@@ -691,7 +746,7 @@ public class ImportPaperService {
 
     /**
      * 获取当前试题大题小题号
-     * 
+     *
      * @param quesType
      * @param subQuesNum
      * @return
@@ -702,7 +757,7 @@ public class ImportPaperService {
 
     /**
      * 判断是否为套题
-     * 
+     *
      * @param importPaperCheck
      * @return
      */
@@ -716,7 +771,7 @@ public class ImportPaperService {
 
     /**
      * 获取课程代码
-     * 
+     *
      * @param importPaperCheck
      * @return
      */
@@ -731,7 +786,7 @@ public class ImportPaperService {
 
     /**
      * 获取课程名称
-     * 
+     *
      * @param importPaperCheck
      * @return
      */
@@ -746,7 +801,7 @@ public class ImportPaperService {
 
     /**
      * 设置wordMLPackage对象二进制数据
-     * 
+     *
      * @param question
      * @param wordMLPackage
      * @throws Exception
@@ -757,29 +812,35 @@ public class ImportPaperService {
 
     /**
      * 构造一张空白的导入类型试卷
-     * 
+     *
      * @param courseNo
-     * @param courseName
      * @param paperName
      * @return
      */
-    public String saveBlankPaper(String courseNo, String paperName) {
+    public Map<String, Object> saveBlankPaper(String courseNo, String courseName, String paperName, AccessUser user) {
+        Map<String, Object> returnMap = new HashMap<String, Object>();
         Paper paper = new Paper();
-        String courseName = courseRepo.findByCourseNo(courseNo).getCourseName();
-        String msg = paperService.checkPaperName(paperName);
+        String msg = paperService.checkPaperName(paperName, user.getOrgId().toString());
         if (msg != null) {
-            return msg;
+            returnMap.put("msg", msg);
+            return returnMap;
         }
         initPaper(paper, paperName);
         paper.setCourseNo(courseNo);
         paper.setCourseName(courseName);
+        paper.setOrgId(user.getOrgId().toString());
+        paper.setCreator(user.getLoginName());
+        paper.setCreateTime(CommonUtils.getCurDateTime());
         PaperDetail pd = new PaperDetail();
         pd.setId(UUID.randomUUID().toString());
         pd.setNumber(1);
         pd.setPaper(paper);
-        paperRepo.save(paper);
+        pd.setCreator(user.getLoginName());
+        pd.setCreateTime(CommonUtils.getCurDateTime());
+        paper = paperRepo.save(paper);
         paperDetailRepo.save(pd);
-        msg = "success";
-        return msg;
+        returnMap.put("paper", paper);
+        returnMap.put("msg", "success");
+        return returnMap;
     }
 }

+ 49 - 22
cqb-paper/src/main/java/com/qmth/cqb/paper/service/PaperDetailUnitService.java

@@ -1,19 +1,18 @@
 package com.qmth.cqb.paper.service;
 
-import java.util.ArrayList;
-import java.util.List;
-
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Service;
-
+import cn.com.qmth.examcloud.common.dto.question.enums.QuesStructType;
 import com.qmth.cqb.paper.dao.PaperDetailUnitRepo;
 import com.qmth.cqb.paper.dto.PaperDetailUnitExp;
 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.question.dao.QuesRepo;
 import com.qmth.cqb.question.model.Question;
 import com.qmth.cqb.question.service.QuesService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.ArrayList;
+import java.util.List;
 
 @Service
 public class PaperDetailUnitService {
@@ -24,15 +23,12 @@ public class PaperDetailUnitService {
     @Autowired
     QuesService quesService;
 
-    @Autowired
-    QuesRepo quesRepo;
-
     @Autowired
     PaperService paperService;
 
     /**
      * 根据Id获得对应的试题对象
-     * 
+     *
      * @param id
      * @return
      */
@@ -42,7 +38,7 @@ public class PaperDetailUnitService {
 
     /**
      * 按ID查询小题
-     * 
+     *
      * @param id
      * @return
      */
@@ -52,22 +48,53 @@ public class PaperDetailUnitService {
 
     /**
      * 保存小题
-     * 
-     * @param pdu
+     *
+     * @param pduExp
      * @return
      */
     public PaperDetailUnit savePaperDetailUnit(PaperDetailUnitExp pduExp) {
         PaperDetailUnit oldPdu = paperDetailUnitRepo.findOne(pduExp.getId());
-        oldPdu.setScore(pduExp.getScore());
-        oldPdu.setQuestion(pduExp.getQuestion());
-        Question ques = pduExp.getQuestion();
-        quesRepo.save(ques);// 同时要跟新小题里面的Qustion对象
-        return paperDetailUnitRepo.save(oldPdu);
+        if (oldPdu.getQuestionType() == QuesStructType.NESTED_ANSWER_QUESTION) {
+            if (pduExp.getQuestion().getId().equals(oldPdu.getQuestion().getId())) {
+                //更新对象为套题本身
+                oldPdu.setQuestion(quesService.saveQues(pduExp.getQuestion()));
+            } else {
+                List<Double> subScoreList = oldPdu.getSubScoreList();
+                int size = oldPdu.getQuestion().getSubQuestions().size();
+                boolean match = false;
+                // 判断更新的对象是哪个子题
+                for (int index = 1; index <= size; index++) {
+                    // 检查子题分数,确保没有错误数据
+                    if (subScoreList.size() < index) {
+                        subScoreList.add(0d);
+                    }
+                    Question sub = oldPdu.getQuestion().getSubQuestions().get(index - 1);
+                    if (pduExp.getQuestion().getId().equals(sub.getId())) {
+                        // 匹配到子题
+                        subScoreList.set(index - 1, pduExp.getScore());
+                        oldPdu.getQuestion().getSubQuestions().set(index - 1, pduExp.getQuestion());
+                        match = true;
+                    }
+                }
+                if (match) {
+                    oldPdu.setQuestion(quesService.saveQues(oldPdu.getQuestion()));
+                }
+                //更新套题unit当前总分与子题分数
+                oldPdu.setSubScoreList(subScoreList);
+            }
+        } else {
+            oldPdu.setQuestion(quesService.saveQues(pduExp.getQuestion()));
+            oldPdu.setScore(pduExp.getScore());
+        }
+        // 同时要跟新小题里面的Qustion对象
+        oldPdu = paperDetailUnitRepo.save(oldPdu);
+        paperService.formatPaper(oldPdu.getPaper());
+        return oldPdu;
     }
 
     /**
      * 删除小题
-     * 
+     *
      * @param id
      * @return
      */
@@ -79,7 +106,7 @@ public class PaperDetailUnitService {
 
     /**
      * 根据大题查小题
-     * 
+     *
      * @param paperDetail
      * @return
      */
@@ -89,7 +116,7 @@ public class PaperDetailUnitService {
 
     /**
      * 根据大题集合删除小题
-     * 
+     *
      * @param paperDetails
      */
     public void deleteUnitsByPaperDetails(List<PaperDetail> paperDetails) {

+ 68 - 59
cqb-paper/src/main/java/com/qmth/cqb/paper/service/PaperService.java

@@ -4,7 +4,6 @@ import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
-import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
@@ -33,7 +32,6 @@ import com.qmth.cqb.question.dao.QuesBakRepo;
 import com.qmth.cqb.question.dao.QuesRepo;
 import com.qmth.cqb.question.model.Question;
 import com.qmth.cqb.question.model.QuestionBak;
-import com.qmth.cqb.question.model.QuestionSearchCondition;
 import com.qmth.cqb.question.service.QuesService;
 import com.qmth.cqb.utils.BeanCopierUtil;
 import com.qmth.cqb.utils.CommonUtils;
@@ -41,6 +39,7 @@ import com.qmth.cqb.utils.enums.PaperStatus;
 import com.qmth.cqb.utils.enums.PaperType;
 
 import cn.com.qmth.examcloud.common.dto.question.enums.QuesStructType;
+import cn.com.qmth.examcloud.common.uac.entity.AccessUser;
 
 /**
  * Created by songyue on 16/12/28.
@@ -80,7 +79,7 @@ public class PaperService {
 
     /**
      * 查询所有已导入试卷
-     * 
+     *
      * @param paperSearchInfo
      * @param curPage
      * @param pageSize
@@ -95,7 +94,7 @@ public class PaperService {
 
     /**
      * 保存试卷
-     * 
+     *
      * @param paperExp
      * @return
      */
@@ -107,7 +106,7 @@ public class PaperService {
 
     /**
      * 查询所有已组试卷
-     * 
+     *
      * @param paperSearchInfo
      * @param curPage
      * @param pageSize
@@ -122,7 +121,7 @@ public class PaperService {
 
     /**
      * 查询考试试卷
-     * 
+     *
      * @param id
      * @param courseCode
      * @param groupCode
@@ -137,7 +136,7 @@ public class PaperService {
         Example<ExamPaper> example = Example.of(examPaper);
         List<ExamPaper> examPapers = examPaperRepo.findAll(example);
         for (ExamPaper ePaper : examPapers) {
-            Paper paper = paperRepo.findOne(ePaper.getPaperId());
+            Paper paper = paperRepo.findOne(ePaper.getPaper().getId());
             papers.add(paper);
         }
         return papers;
@@ -145,7 +144,7 @@ public class PaperService {
 
     /**
      * 设置考试试卷
-     * 
+     *
      * @param examId
      * @param courseCode
      * @param groupCode
@@ -157,7 +156,7 @@ public class PaperService {
         examPaper.setExamId(examId);
         examPaper.setGroupCode(groupCode);
         examPaper.setCourseCode(courseCode);
-        examPaper.setPaperId(paperId);
+//        examPaper.setPaperId(paperId);
         examPaperRepo.save(examPaper);
     }
 
@@ -166,7 +165,7 @@ public class PaperService {
         examPaper.setExamId(examId);
         examPaper.setGroupCode(groupCode);
         examPaper.setCourseCode(courseCode);
-        examPaper.setPaperId(paperId);
+//        examPaper.setPaperId(paperId);
         examPaperRepo.delete(examPaper);
     }
 
@@ -192,7 +191,7 @@ public class PaperService {
 
     /**
      * 根据试卷ID获取试卷下面的大题
-     * 
+     *
      * @param id
      * @return
      */
@@ -202,18 +201,29 @@ public class PaperService {
 
     /**
      * 批量删除试卷
-     * 
+     *
      * @param paperIds
      */
-    public void deletePapers(List<String> paperIds) {
+    public String deletePapers(List<String> paperIds) {
+        String msg = "";
         List<Paper> papers = CommonUtils.toList(paperRepo.findAll(paperIds));
+        for (Paper paper : papers) {
+            List<PaperDetailUnit> units = paperDetailUnitRepo.findByPaper(paper);
+            if (units.size() > 0) {
+                return msg = "试卷里面还有小题,不能删除";
+            }
+
+        }
         paperDetailService.deletePaperDetailsByPapers(papers);
         paperRepo.delete(papers);
+        msg = "success";
+        return msg;
+
     }
 
     /**
      * 批量通过试卷
-     * 
+     *
      * @param paperIds
      */
     public void passPapers(List<String> paperIds) {
@@ -226,7 +236,7 @@ public class PaperService {
 
     /**
      * 批量不通过试卷
-     * 
+     *
      * @param paperIds
      */
     public void noPassPapers(List<String> paperIds) {
@@ -239,7 +249,7 @@ public class PaperService {
 
     /**
      * 批量待审核试卷
-     * 
+     *
      * @param paperIds
      */
     public void backPapers(List<String> paperIds) {
@@ -252,7 +262,7 @@ public class PaperService {
 
     /**
      * 初始化导出试卷DTO
-     * 
+     *
      * @param id
      * @return
      */
@@ -287,7 +297,7 @@ public class PaperService {
 
     /**
      * 初始化试卷内容(增加序号)
-     * 
+     *
      * @param paperExp
      */
     public void initPaper(PaperExp paperExp) {
@@ -327,7 +337,7 @@ public class PaperService {
 
     /**
      * 格式化查询条件
-     * 
+     *
      * @param paperSearchInfo
      */
     public void formatPaperSearchInfo(PaperSearchInfo paperSearchInfo) {
@@ -347,7 +357,7 @@ public class PaperService {
 
     /**
      * 填充大题小题数量与分数
-     * 
+     *
      * @param paper
      */
     public void formatPaper(Paper paper) {
@@ -368,21 +378,18 @@ public class PaperService {
             if (paperDetailUnits.size() > 0) {
                 int count = 0;
                 double score = 0;
-                PaperDetailUnit firstUnit = paperDetailUnits.get(0);
-                QuesStructType questionType = firstUnit.getQuestionType();
-                if (!questionType.equals(QuesStructType.NESTED_ANSWER_QUESTION)) {
-                    for (PaperDetailUnit unit : paperDetailUnits) {
-                        if (unit.getScore() != null) {
-                            score += unit.getScore();
-                        }
+                int nestQusNum = 0;
+                for (PaperDetailUnit unit : paperDetailUnits) {
+                    if (unit.getScore() != null) {
+                        score += unit.getScore();
                     }
-                    count = paperDetailUnits.size();
-                } else {
-                    Question question = firstUnit.getQuestion();
-                    List<Question> subQuestions = question.getSubQuestions();
-                    score = subQuestions.stream().mapToDouble(Question::getScore).sum();
-                    count = subQuestions.size();
+                    if (unit.getQuestion().getSubQuestions() != null
+                            && unit.getQuestion().getSubQuestions().size() > 0) {
+                        nestQusNum += unit.getQuestion().getSubQuestions().size() - 1;
+                    }
+
                 }
+                count = paperDetailUnits.size() + nestQusNum;
                 paperDetail.setScore(score);
                 paperDetail.setUnitCount(count);
             } else {
@@ -398,7 +405,7 @@ public class PaperService {
 
     /**
      * 先备份准备删掉的试题,然后再删掉
-     * 
+     *
      * @param questionId
      * @return
      */
@@ -432,12 +439,14 @@ public class PaperService {
 
     /**
      * 向试卷中插入一个试题
-     * 
+     *
      * @param paperId
      * @param paperDetailId
      * @return
      */
-    public Paper insertQuestionToPaper(String paperId, String paperDetailId, Question question) {
+    public Paper insertQuestionToPaper(String paperId, String paperDetailId, Question question, AccessUser user) {
+        question.setOrgId(user.getOrgId().toString());
+        quesService.updateQuesWord(question);
         question = quesRepo.save(question);
         Paper paper = paperRepo.findOne(paperId);
         PaperDetail pd = paperDetailRepo.findOne(paperDetailId);
@@ -460,7 +469,7 @@ public class PaperService {
 
     /**
      * 获取试题所的试卷名称
-     * 
+     *
      * @param questionId
      * @return
      */
@@ -475,27 +484,28 @@ public class PaperService {
     }
 
     public Page<Question> listQuestionforSelect(String paperId, int curPage, int pageSize, QuesStructType quesType) {
-        List<Question> questions = new ArrayList<Question>();
+        Set<String> selectedIds = new HashSet<>();
         Paper paper = paperRepo.findOne(paperId);
-        QuestionSearchCondition ques = new QuestionSearchCondition();
-        if (quesType != null) {
-            ques.setQuestionType(quesType);
-        }
-        Map<String, String> quesParams = new HashMap<String, String>();
+        // QuestionSearchCondition ques = new QuestionSearchCondition();
+        // if (quesType != null) {
+        // ques.setQuestionType(quesType);
+        // }
+        // Map<String, String> quesParams = new HashMap<String, String>();
         // quesParams.put("courseName", paper.getCourseName());
         // ques.setQuesParams(quesParams);
         List<PaperDetailUnit> pdus = paperDetailUnitRepo.findByPaper(paper);
         for (PaperDetailUnit pdu : pdus) {
-            questions.add(pdu.getQuestion());
-        }
-        Page<Question> allQuestions = quesService.findAll(ques, curPage, pageSize);
-        Iterator<Question> que = allQuestions.iterator();
-        while (que.hasNext()) {
-            if (questions.contains(que.next())) {
-                que.remove();
-            }
+            selectedIds.add(pdu.getQuestion().getId());
         }
-        return allQuestions;
+        // Page<Question> allQuestions = quesService.findAll(ques, curPage,
+        // pageSize);
+        // Iterator<Question> que = allQuestions.iterator();
+        // while (que.hasNext()) {
+        // if (selectedIds.contains(que.next().getId())) {
+        // que.remove();
+        // }
+        // }
+        return quesService.findByIdExclude(selectedIds, paper.getCourseNo(), quesType, curPage, pageSize);
     }
 
     public Paper selectQuestionsToPaper(String paperId, String paperDetailId, List<Question> questions) {
@@ -510,12 +520,8 @@ public class PaperService {
             pdu.setQuestion(ques);
             pdu.setCreateTime(CommonUtils.getCurDateTime());
             pdu.setPaperDetail(pd);
+            pdu.setScore(0d);
             pdus.add(pdu);
-            if (ques.getScore() == null || ques.getScore() == 0d) {
-                pdu.setScore(0d);
-            } else {
-                pdu.setScore(ques.getScore());
-            }
             saveUnits.add(pdu);
         }
         Collections.sort(pdus);
@@ -528,9 +534,12 @@ public class PaperService {
         return paper;
     }
 
-    public String checkPaperName(String paperName) {
+    public String checkPaperName(String paperName, String orgId) {
         String msg = null;
-        Paper paper = paperRepo.findByName(paperName);
+        Paper paperTemp = new Paper();
+        paperTemp.setName(paperName);
+        paperTemp.setOrgId(orgId);
+        Paper paper = paperRepo.findOne(Example.of(paperTemp));
         if (paper != null) {
             msg = "试卷名称重复,请重新命名";
         }

+ 33 - 28
cqb-paper/src/main/java/com/qmth/cqb/paper/service/PaperStructService.java

@@ -1,9 +1,8 @@
 package com.qmth.cqb.paper.service;
 
+import java.util.ArrayList;
+import java.util.List;
 
-import com.qmth.cqb.paper.dto.PaperDetailUnitStructDto;
-import com.qmth.cqb.paper.model.*;
-import com.qmth.cqb.utils.BeanCopierUtil;
 import org.apache.commons.lang3.StringUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.data.domain.Example;
@@ -13,70 +12,74 @@ import org.springframework.data.domain.PageRequest;
 import org.springframework.stereotype.Service;
 
 import com.qmth.cqb.paper.dao.PaperStructRepo;
+import com.qmth.cqb.paper.dto.PaperDetailUnitStructDto;
+import com.qmth.cqb.paper.model.PaperDetailStruct;
+import com.qmth.cqb.paper.model.PaperDetailUnitStruct;
+import com.qmth.cqb.paper.model.PaperStruct;
+import com.qmth.cqb.paper.model.PaperStructSearchInfo;
+import com.qmth.cqb.utils.BeanCopierUtil;
+import com.qmth.cqb.utils.CommonUtils;
+
+import cn.com.qmth.examcloud.common.uac.entity.AccessUser;
 
-import java.util.ArrayList;
-import java.util.List;
 /**
  * Created by songyue on 16/12/28.
  */
 @Service
 public class PaperStructService {
-	
-	@Autowired
-    PaperStructRepo paperStructRepo;
 
+    @Autowired
+    PaperStructRepo paperStructRepo;
 
     /**
      * 获取所有试卷结构
+     * 
      * @param searchInfo
      * @param curPage
      * @param pageSize
      * @return
      */
-    public Page<PaperStruct> getPaperStructs(PaperStructSearchInfo searchInfo,
-                                             int curPage,
-                                             int pageSize){
+    public Page<PaperStruct> getPaperStructs(PaperStructSearchInfo searchInfo, int curPage, int pageSize,AccessUser user) {
+        searchInfo.setOrgId(user.getOrgId().toString());
         formatSearchInfo(searchInfo);
-        PaperStruct paperStruct = BeanCopierUtil.copyProperties(searchInfo,PaperStruct.class);
+        PaperStruct paperStruct = BeanCopierUtil.copyProperties(searchInfo, PaperStruct.class);
         formatPaperStruct(paperStruct);
-        ExampleMatcher matcher = ExampleMatcher.matching().
-                withStringMatcher(ExampleMatcher.StringMatcher.CONTAINING).withIgnoreNullValues();
-        return paperStructRepo.findAll(Example.of(paperStruct,matcher),
-                new PageRequest(curPage - 1,pageSize));
+        ExampleMatcher matcher = ExampleMatcher.matching().withStringMatcher(ExampleMatcher.StringMatcher.CONTAINING)
+                .withIgnoreNullValues();
+        return paperStructRepo.findAll(Example.of(paperStruct, matcher), new PageRequest(curPage - 1, pageSize));
     }
 
-    public void formatSearchInfo(PaperStructSearchInfo searchInfo){
-        if(StringUtils.isEmpty(searchInfo.getName())){
+    public void formatSearchInfo(PaperStructSearchInfo searchInfo) {
+        if (StringUtils.isEmpty(searchInfo.getName())) {
             searchInfo.setName(null);
         }
-        if(StringUtils.isEmpty(searchInfo.getCreator())){
+        if (StringUtils.isEmpty(searchInfo.getCreator())) {
             searchInfo.setCreator(null);
         }
     }
 
-    public void formatPaperStruct(PaperStruct paperStruct){
+    public void formatPaperStruct(PaperStruct paperStruct) {
         paperStruct.setCreateTime(null);
     }
 
     /**
      * 保存试卷结构
+     * 
      * @param paperStruct
      * @return
      */
-    public PaperStruct save(PaperStruct paperStruct){
-
+    public PaperStruct save(PaperStruct paperStruct, AccessUser user) {
         List<PaperDetailStruct> paperDetailStructs = paperStruct.getPaperDetailStructs();
         int number = 0;
-
-        for(PaperDetailStruct paperDetailStruct:paperDetailStructs){
+        for (PaperDetailStruct paperDetailStruct : paperDetailStructs) {
             List oldStructs = paperDetailStruct.getPaperDetailUnitStructs();
-            if(oldStructs != null && oldStructs.size() > 0){
+            if (oldStructs != null && oldStructs.size() > 0) {
                 oldStructs.clear();
             }
             List<PaperDetailUnitStruct> unitStructs = new ArrayList<PaperDetailUnitStruct>();
 
-            for(PaperDetailUnitStructDto unitStructDto:paperDetailStruct.getUnitStructs()){
-                for(int i = 0;i < unitStructDto.getCount();i++){
+            for (PaperDetailUnitStructDto unitStructDto : paperDetailStruct.getUnitStructs()) {
+                for (int i = 0; i < unitStructDto.getCount(); i++) {
                     ++number;
                     PaperDetailUnitStruct unitStruct = new PaperDetailUnitStruct();
                     unitStruct.setScore(unitStructDto.getScore());
@@ -89,8 +92,10 @@ public class PaperStructService {
             paperDetailStruct.setPaperDetailUnitStructs(unitStructs);
         }
         paperStruct.setDetailCount(paperDetailStructs.size());
+        paperStruct.setOrgId(user.getOrgId().toString());
+        paperStruct.setCreator(user.getLoginName());
+        paperStruct.setCreateTime(CommonUtils.getCurDateTime());
         return paperStructRepo.save(paperStruct);
     }
 
-
 }

+ 64 - 0
cqb-paper/src/main/java/com/qmth/cqb/paper/web/ExamPaperController.java

@@ -0,0 +1,64 @@
+package com.qmth.cqb.paper.web;
+
+import io.swagger.annotations.ApiOperation;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.commons.collections4.map.HashedMap;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestMapping;
+
+import com.qmth.cqb.paper.model.ExamPaper;
+import com.qmth.cqb.paper.model.Paper;
+import com.qmth.cqb.paper.service.ExamPaperService;
+
+/**
+ * @author  	chenken
+ * @date    	2017年4月17日 上午10:40:20
+ * @company 	QMTH
+ * @description ExamPaperController.java
+ */
+@Controller
+@RequestMapping("${api_cqb}/")
+public class ExamPaperController {
+	
+	@Autowired
+	private ExamPaperService examPaperService;
+	
+	@ApiOperation(value = "根据考试ID和课程代码获取卷库考试试卷,按试卷类型分组"
+				, notes = "根据考试ID和课程代码获取卷库考试试卷,按试卷类型分组")
+    @GetMapping(value = "/examPaper/listByGroupCode/{examId}/{courseCode}")
+	public ResponseEntity<Map<String, List<Paper>>> findExamPaper(@PathVariable Long examId, @PathVariable String courseCode){
+		ExamPaper condition = new ExamPaper();
+		condition.setExamId(examId);
+		condition.setCourseCode(courseCode);
+		//根据考试ID和课程code取出所有试卷
+		List<ExamPaper> examPaperList = examPaperService.findExamPaperList(condition);
+		//按照试卷类型分组
+		Map<String,List<Paper>> examPaperMap = new HashedMap<String,List<Paper>>();
+		for(int i = 0;i<examPaperList.size();i++){
+			ExamPaper examPaper = examPaperList.get(i);
+			if(!examPaperMap.containsKey(examPaper.getGroupCode())){
+				if(examPaper.getPaper()!=null){
+					List<Paper> epList = new ArrayList<Paper>();
+					epList.add(examPaper.getPaper());
+					examPaperMap.put(examPaper.getGroupCode(), epList);
+				}
+			}else{
+				if(examPaper.getPaper()!=null){
+					List<Paper> epList = examPaperMap.get(examPaper.getGroupCode());
+					epList.add(examPaper.getPaper());
+				}
+			}
+		}
+		return new ResponseEntity<Map<String, List<Paper>>>(examPaperMap, HttpStatus.OK);
+	}
+}
+

+ 87 - 0
cqb-paper/src/main/java/com/qmth/cqb/paper/web/ExtractConfigController.java

@@ -0,0 +1,87 @@
+package com.qmth.cqb.paper.web;
+
+import java.util.Map;
+
+import javax.servlet.http.HttpServletRequest;
+
+import io.swagger.annotations.ApiOperation;
+
+import org.apache.commons.collections4.map.HashedMap;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+
+import cn.com.qmth.examcloud.common.uac.entity.AccessUser;
+
+import com.qmth.cqb.paper.model.ExtractConfig;
+import com.qmth.cqb.paper.service.ExtractConfigService;
+
+
+/**
+ * 
+ * @author  	chenken
+ * @date    	2017年4月14日 下午6:05:37
+ * @company 	QMTH
+ * @description ExtractConfigController.java
+ */
+@Controller
+@RequestMapping("${api_cqb}/")
+public class ExtractConfigController {
+	@Autowired
+	private ExtractConfigService extractConfigService;
+	
+	@ApiOperation(value = "根据考试ID和课程ID获取调卷规则", notes = "根据考试ID和课程ID获取调卷规则")
+    @GetMapping(value = "/extractConfig/{examId}/{courseCode}")
+	public ResponseEntity<ExtractConfig> findExtractConfig(@PathVariable Long examId,@PathVariable String courseCode){
+		ExtractConfig condition = new ExtractConfig();
+		condition.setExamId(examId);
+		condition.setCourseCode(courseCode);
+		ExtractConfig extractConfig = extractConfigService.findConfig(condition);
+		return new ResponseEntity<ExtractConfig>(extractConfig,HttpStatus.OK);
+	}
+	
+	@ApiOperation(value = "根据ID获取调卷规则", notes = "根据ID获取调卷规则")
+    @GetMapping(value = "/extractConfig/{id}")
+	public ResponseEntity<ExtractConfig> findExtractConfigById(@PathVariable String id){
+		ExtractConfig extractConfig = extractConfigService.findConfigById(id);
+		return new ResponseEntity<ExtractConfig>(extractConfig,HttpStatus.OK);
+	} 
+	
+	@ApiOperation(value = "保存调卷规则", notes = "保存调卷规则")
+    @PutMapping(value = "/extractConfig")
+	public Map<String,Object> saveExtractConfig(HttpServletRequest request,@RequestBody ExtractConfig extractConfig){
+		Map<String,Object> paramsMap = new HashedMap<String,Object>();
+		try{
+			AccessUser user = (AccessUser) request.getAttribute("accessUser");
+			extractConfig.setOrgId(user.getOrgId()+"");
+			extractConfigService.saveExtractConfig(extractConfig);
+			paramsMap.put("errMsg", "保存成功");
+			paramsMap.put("status", "success");
+		}catch(Exception e){
+			paramsMap.put("errMsg", "保存失败");
+			paramsMap.put("status", "failed");
+		}
+		return paramsMap;
+	}
+	
+	@ApiOperation(value = "根据调卷规则生成试卷", notes = "根据调卷规则生成试卷")
+    @PutMapping(value = "/makePaperByConfig")
+	public Map<String,Object> makePaperByConfig(String id){
+		Map<String,Object> paramsMap = new HashedMap<String,Object>();
+		try{
+			extractConfigService.makePaperByConfig(id);
+			paramsMap.put("errMsg", "试卷生成成功");
+			paramsMap.put("status", "success");
+		}catch(Exception e){
+			paramsMap.put("errMsg", "试卷生成失败");
+			paramsMap.put("status", "failed");
+		}
+		return paramsMap;
+	}
+}	

+ 26 - 14
cqb-paper/src/main/java/com/qmth/cqb/paper/web/ImportPaperController.java

@@ -4,6 +4,10 @@ import java.io.File;
 import java.util.HashMap;
 import java.util.Map;
 
+import javax.servlet.http.HttpServletRequest;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.http.HttpStatus;
 import org.springframework.http.ResponseEntity;
@@ -18,6 +22,7 @@ import com.qmth.cqb.paper.dao.PaperRepo;
 import com.qmth.cqb.paper.service.ImportPaperService;
 import com.qmth.cqb.paper.service.PaperService;
 
+import cn.com.qmth.examcloud.common.uac.entity.AccessUser;
 import io.swagger.annotations.ApiOperation;
 
 /**
@@ -27,6 +32,8 @@ import io.swagger.annotations.ApiOperation;
 @RequestMapping("${api_cqb}/")
 public class ImportPaperController {
 
+    protected static final Logger log = LoggerFactory.getLogger(ImportPaperController.class);
+
     @Autowired
     ImportPaperService importPaperService;
 
@@ -45,35 +52,40 @@ public class ImportPaperController {
      */
     @ApiOperation(value = "导入试卷", notes = "导入试卷")
     @PostMapping(value = "/importPaper")
-    public ResponseEntity importPaper(  @RequestParam String paperName, 
-                                @RequestParam String courseNo,
-                                @RequestParam("file") CommonsMultipartFile file) {
+    public ResponseEntity importPaper(HttpServletRequest request, @RequestParam String paperName,
+            @RequestParam String courseNo, @RequestParam String courseName,
+            @RequestParam("file") CommonsMultipartFile file) {
+        AccessUser user = (AccessUser) request.getAttribute("accessUser");
+        log.info("导入开始");
         File tempFile = importPaperService.getUploadFile(file);
-        String returnStr = importPaperService.ImportPaper(paperName, courseNo, tempFile);
-        Map map = new HashMap();      
+        String returnStr = importPaperService.ImportPaper(paperName, courseNo, courseName, user, tempFile);
+        log.info("导入结束");
         if (returnStr.equals("success")) {
             return new ResponseEntity(returnStr, HttpStatus.OK);
         } else {
+            Map map = new HashMap();
             map.put("errorMsg", returnStr);
             return new ResponseEntity(map, HttpStatus.INTERNAL_SERVER_ERROR);
         }
-        //return returnStr;
     }
 
     /**
-     * 新增一张空白试卷
+     * 新增试卷
      * 
-     * @param paper
+     * @param courseNo
+     * @param paperName
      * @return
      */
     @ApiOperation(value = "保存导入类型空白试卷", notes = "保存导入类型空白试卷")
-    @PostMapping(value = "/importPaper/saveBlankPaper/{courseNo}/{paperName}")
-    public ResponseEntity saveBlankPaper(@PathVariable String courseNo, @PathVariable String paperName) {
-        String msg = importPaperService.saveBlankPaper(courseNo, paperName);
-        if (msg.equals("success")) {
-            return new ResponseEntity(msg, HttpStatus.OK);
+    @PostMapping(value = "/importPaper/saveBlankPaper/{courseNo}/{courseName}/{paperName}")
+    public ResponseEntity saveBlankPaper(HttpServletRequest request, @PathVariable String courseNo,
+            @PathVariable String courseName, @PathVariable String paperName) {
+        AccessUser user = (AccessUser) request.getAttribute("accessUser");
+        Map<String, Object> returnMap = importPaperService.saveBlankPaper(courseNo, courseName, paperName, user);
+        if (returnMap.get("msg").equals("success")) {
+            return new ResponseEntity(returnMap, HttpStatus.OK);
         } else {
-            return new ResponseEntity(msg, HttpStatus.INTERNAL_SERVER_ERROR);
+            return new ResponseEntity(returnMap, HttpStatus.INTERNAL_SERVER_ERROR);
         }
     }
 

+ 40 - 14
cqb-paper/src/main/java/com/qmth/cqb/paper/web/PaperController.java

@@ -2,12 +2,16 @@ package com.qmth.cqb.paper.web;
 
 import java.util.ArrayList;
 import java.util.Arrays;
+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 java.util.stream.Stream;
 
+import javax.servlet.http.HttpServletRequest;
+
 import org.apache.commons.lang3.StringUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Value;
@@ -36,6 +40,7 @@ import com.qmth.cqb.question.model.Question;
 import com.qmth.cqb.utils.StringSimilarityUtils;
 
 import cn.com.qmth.examcloud.common.dto.question.enums.QuesStructType;
+import cn.com.qmth.examcloud.common.uac.entity.AccessUser;
 import io.swagger.annotations.ApiOperation;
 
 /**
@@ -91,8 +96,12 @@ public class PaperController {
      */
     @ApiOperation(value = "查询所有导入试卷", notes = "查询所有导入试卷")
     @GetMapping(value = "/importPaper/{curPage}/{pageSize}")
-    public ResponseEntity getImportPapers(@ModelAttribute PaperSearchInfo paperSearchInfo, @PathVariable int curPage,
-            @PathVariable int pageSize) {
+    public ResponseEntity getImportPapers( HttpServletRequest request, 
+                                            @ModelAttribute PaperSearchInfo paperSearchInfo, 
+                                            @PathVariable int curPage,
+                                            @PathVariable int pageSize) {
+        AccessUser user = (AccessUser) request.getAttribute("accessUser");
+        paperSearchInfo.setOrgId(user.getOrgId().toString());
         return new ResponseEntity(paperService.getImportPapers(paperSearchInfo, curPage, pageSize), HttpStatus.OK);
     }
 
@@ -106,8 +115,12 @@ public class PaperController {
      */
     @ApiOperation(value = "查询所有已组试卷", notes = "查询所有已组试卷")
     @GetMapping(value = "/genPaper/{curPage}/{pageSize}")
-    public ResponseEntity getGenPapers(@ModelAttribute PaperSearchInfo paperSearchInfo, @PathVariable int curPage,
-            @PathVariable int pageSize) {
+    public ResponseEntity getGenPapers( HttpServletRequest request, 
+                                        @ModelAttribute PaperSearchInfo paperSearchInfo, 
+                                        @PathVariable int curPage,
+                                        @PathVariable int pageSize) {
+        AccessUser user = (AccessUser) request.getAttribute("accessUser");
+        paperSearchInfo.setOrgId(user.getOrgId().toString());
         return new ResponseEntity(paperService.getGenPapers(paperSearchInfo, curPage, pageSize), HttpStatus.OK);
     }
 
@@ -121,8 +134,15 @@ public class PaperController {
     @DeleteMapping(value = "/paper/{paperIds}")
     public ResponseEntity delPaper(@PathVariable String paperIds) {
         List<String> paperList = Stream.of(paperIds.split(",")).collect(Collectors.toList());
-        paperService.deletePapers(paperList);
-        return new ResponseEntity(HttpStatus.OK);
+        String msg = paperService.deletePapers(paperList);
+        if (msg.equals("success")) {
+            return new ResponseEntity(msg, HttpStatus.OK);
+        } else {
+            Map map = new HashMap();
+            map.put("errorMsg", msg);
+            return new ResponseEntity(map, HttpStatus.INTERNAL_SERVER_ERROR);
+        }
+
     }
 
     /**
@@ -266,9 +286,12 @@ public class PaperController {
      */
     @ApiOperation(value = "向导入试卷中的新增试题", notes = "向导入试卷中的新增试题")
     @PostMapping(value = "/paper/addQuestion/{paperId}/{paperDetailId}")
-    public ResponseEntity insertQuestionToPaper(@PathVariable String paperId, @PathVariable String paperDetailId,
-            @RequestBody Question question) {
-        return new ResponseEntity(paperService.insertQuestionToPaper(paperId, paperDetailId, question), HttpStatus.OK);
+    public ResponseEntity insertQuestionToPaper(HttpServletRequest request,
+                                                @PathVariable String paperId, 
+                                                @PathVariable String paperDetailId,
+                                                @RequestBody Question question) {
+        AccessUser user = (AccessUser) request.getAttribute("accessUser");
+        return new ResponseEntity(paperService.insertQuestionToPaper(paperId, paperDetailId, question,user), HttpStatus.OK);
 
     }
 
@@ -284,7 +307,10 @@ public class PaperController {
         List<PaperDetailExp> paperDetailExpList = paperExp.getPaperDetails();
         if (paperDetailExpList != null && paperDetailExpList.size() > 0) {
             for (PaperDetailExp paperDetailExp : paperDetailExpList) {
-                allPaperDetailUnitList.addAll(paperDetailExp.getPaperDetailUnits());
+                if (paperDetailExp.getPaperDetailUnits() != null) {
+                    allPaperDetailUnitList.addAll(paperDetailExp.getPaperDetailUnits());
+                }
+
             }
         }
 
@@ -376,10 +402,10 @@ public class PaperController {
      */
     @ApiOperation(value = "向导入试卷中的新增试题", notes = "向导入试卷中的新增试题")
     @PostMapping(value = "/paper/selectQuestions/{paperId}/{paperDetailId}")
-    public ResponseEntity selectQuestionsToPaper(@PathVariable String paperId, @PathVariable String paperDetailId,
-            @RequestBody List<Question> questions) {
-        return new ResponseEntity(paperService.selectQuestionsToPaper(paperId, paperDetailId, questions),
-                HttpStatus.OK);
+    public ResponseEntity selectQuestionsToPaper(@PathVariable String paperId, 
+                                                @PathVariable String paperDetailId,
+                                                @RequestBody List<Question> questions) {
+        return new ResponseEntity(paperService.selectQuestionsToPaper(paperId, paperDetailId, questions),HttpStatus.OK);
 
     }
 

+ 1 - 2
cqb-paper/src/main/java/com/qmth/cqb/paper/web/PaperDetailUnitController.java

@@ -5,7 +5,6 @@ import org.springframework.http.HttpStatus;
 import org.springframework.http.ResponseEntity;
 import org.springframework.web.bind.annotation.DeleteMapping;
 import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.ModelAttribute;
 import org.springframework.web.bind.annotation.PathVariable;
 import org.springframework.web.bind.annotation.PostMapping;
 import org.springframework.web.bind.annotation.PutMapping;
@@ -64,7 +63,7 @@ public class PaperDetailUnitController {
     @PutMapping(value = "/paperDetailUnit")
     public ResponseEntity updatePaperDetailUnit(@RequestBody PaperDetailUnitExp pdu) {
         PaperDetailUnit pdUnit = unitService.savePaperDetailUnit(pdu);
-        return new ResponseEntity(pdUnit, HttpStatus.OK);
+        return new ResponseEntity(HttpStatus.OK);
 
     }
 

+ 56 - 37
cqb-paper/src/main/java/com/qmth/cqb/paper/web/PaperStructController.java

@@ -1,20 +1,31 @@
 package com.qmth.cqb.paper.web;
 
-import com.qmth.cqb.paper.dao.PaperStructRepo;
-import com.qmth.cqb.paper.model.PaperStructSearchInfo;
-import com.qmth.cqb.utils.CommonUtils;
-import io.swagger.annotations.ApiOperation;
+import java.util.List;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import javax.servlet.http.HttpServletRequest;
+
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.http.HttpStatus;
 import org.springframework.http.ResponseEntity;
-import org.springframework.web.bind.annotation.*;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.ModelAttribute;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
 
+import com.qmth.cqb.paper.dao.PaperStructRepo;
 import com.qmth.cqb.paper.model.PaperStruct;
+import com.qmth.cqb.paper.model.PaperStructSearchInfo;
 import com.qmth.cqb.paper.service.PaperStructService;
 
-import java.util.List;
-import java.util.stream.Collectors;
-import java.util.stream.Stream;
+import cn.com.qmth.examcloud.common.uac.entity.AccessUser;
+import io.swagger.annotations.ApiOperation;
 
 /**
  * Created by songyue on 16/12/28.
@@ -22,8 +33,8 @@ import java.util.stream.Stream;
 @RestController
 @RequestMapping("${api_cqb}/")
 public class PaperStructController {
-	
-	@Autowired
+
+    @Autowired
     PaperStructService paperStructService;
 
     @Autowired
@@ -31,75 +42,83 @@ public class PaperStructController {
 
     /**
      * 获取所有试卷结构
+     * 
      * @param
      * @return
      */
-    @ApiOperation(value="获取试卷结构带分页",notes="获取试卷结构带分页")
+    @ApiOperation(value = "获取试卷结构带分页", notes = "获取试卷结构带分页")
     @GetMapping(value = "/paperStruct/{curPage}/{pageSize}")
-    public ResponseEntity getPaperStructs(@ModelAttribute PaperStructSearchInfo searchInfo,
-                                                @PathVariable int curPage,
-                                                @PathVariable int pageSize){
-        return new ResponseEntity(paperStructService.getPaperStructs(searchInfo,curPage,pageSize),
-                HttpStatus.OK);
+    public ResponseEntity getPaperStructs(  HttpServletRequest request,
+                                            @ModelAttribute PaperStructSearchInfo searchInfo, 
+                                            @PathVariable int curPage,
+                                            @PathVariable int pageSize) {
+        AccessUser user = (AccessUser) request.getAttribute("accessUser");
+        return new ResponseEntity(paperStructService.getPaperStructs(searchInfo, curPage, pageSize,user), HttpStatus.OK);
     }
 
     /**
      * 获取所有试卷结构
+     * 
      * @param
      * @return
      */
-    @ApiOperation(value="获取试卷结构",notes="获取试卷结构")
+    @ApiOperation(value = "获取试卷结构", notes = "获取试卷结构")
     @GetMapping(value = "/paperStruct")
-    public ResponseEntity findAll(){
+    public ResponseEntity findAll() {
         return new ResponseEntity(paperStructRepo.findAll(), HttpStatus.OK);
     }
-	
+
     /**
      * 根据id获取试卷结构
-     * @param 
+     * 
+     * @param
      * @return
      */
-    @ApiOperation(value="获取试卷结构",notes="获取试卷结构")
+    @ApiOperation(value = "获取试卷结构", notes = "获取试卷结构")
     @GetMapping(value = "/paperStruct/{id}")
-    public ResponseEntity getPaperStructById(@PathVariable String id){
-        return new ResponseEntity(paperStructRepo.findOne(id),HttpStatus.OK);
+    public ResponseEntity getPaperStructById(@PathVariable String id) {
+        return new ResponseEntity(paperStructRepo.findOne(id), HttpStatus.OK);
     }
-    
 
     /**
      * 更新试卷结构
-     * @param 
+     * 
+     * @param
      * @return
      */
-    @ApiOperation(value="更新试卷结构",notes="更新试卷结构")
+    @ApiOperation(value = "更新试卷结构", notes = "更新试卷结构")
     @PutMapping(value = "/paperStruct")
-    public ResponseEntity updatePaperStruct(@RequestBody PaperStruct ps){
-    	PaperStruct paperStruct = paperStructService.save(ps);
-    	return new ResponseEntity(paperStruct,HttpStatus.OK);
+    public ResponseEntity updatePaperStruct(HttpServletRequest request, @RequestBody PaperStruct ps) {
+        AccessUser user = (AccessUser) request.getAttribute("accessUser");
+        PaperStruct paperStruct = paperStructService.save(ps, user);
+        return new ResponseEntity(paperStruct, HttpStatus.OK);
     }
 
     /**
      * 新增试卷结构
+     * 
      * @param ps
      * @return
      */
-    @ApiOperation(value="新增试卷结构",notes="新增试卷结构")
+    @ApiOperation(value = "新增试卷结构", notes = "新增试卷结构")
     @PostMapping(value = "/paperStruct")
-    public ResponseEntity addPaperStruct(@RequestBody PaperStruct ps){
-        PaperStruct paperStruct = paperStructService.save(ps);
-    	return new ResponseEntity(paperStruct,HttpStatus.OK);
+    public ResponseEntity addPaperStruct(HttpServletRequest request, @RequestBody PaperStruct ps) {
+        AccessUser user = (AccessUser) request.getAttribute("accessUser");
+        PaperStruct paperStruct = paperStructService.save(ps, user);
+        return new ResponseEntity(paperStruct, HttpStatus.OK);
     }
 
     /**
      * 删除试卷结构
+     * 
      * @param ids
      * @return
      */
-    @ApiOperation(value="删除试卷结构",notes="删除试卷结构")
+    @ApiOperation(value = "删除试卷结构", notes = "删除试卷结构")
     @DeleteMapping(value = "/paperStruct/{ids}")
-    public ResponseEntity removePaperStruct(@PathVariable String ids){
+    public ResponseEntity removePaperStruct(@PathVariable String ids) {
         List<String> paperList = Stream.of(ids.split(",")).collect(Collectors.toList());
-    	paperStructRepo.delete(paperStructRepo.findAll(paperList));
-		return new ResponseEntity(HttpStatus.OK);
+        paperStructRepo.delete(paperStructRepo.findAll(paperList));
+        return new ResponseEntity(HttpStatus.OK);
     }
 }

+ 1 - 1
cqb-question-resource/pom.xml

@@ -16,7 +16,7 @@
     </properties>
 
     <dependencies>
-        <dependency>
+            <dependency>
             <groupId>com.qmth.cqb</groupId>
             <artifactId>cqb-comm-utils</artifactId>
             <version>${project.version}</version>

+ 11 - 1
cqb-question-resource/src/main/java/com/qmth/cqb/question/dao/QuesRepo.java

@@ -1,11 +1,21 @@
 package com.qmth.cqb.question.dao;
 
+import cn.com.qmth.examcloud.common.dto.question.enums.QuesStructType;
 import com.qmth.cqb.question.model.Question;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.Pageable;
 import org.springframework.data.mongodb.repository.MongoRepository;
 import org.springframework.data.repository.query.QueryByExampleExecutor;
 
+import java.util.Set;
+
 /**
  * Created by songyue on 16/12/28.
  */
-public interface QuesRepo extends MongoRepository<Question,String>,QueryByExampleExecutor<Question>{
+public interface QuesRepo extends MongoRepository<Question, String>, QueryByExampleExecutor<Question> {
+
+    public Page<Question> findByIdNotInAndCourseNo(Set<String> idSet, String courseNo, Pageable page);
+
+    public Page<Question> findByIdNotInAndCourseNoAndQuestionType(Set<String> idSet, String courseNo,
+            QuesStructType quesType, Pageable page);
 }

+ 13 - 2
cqb-question-resource/src/main/java/com/qmth/cqb/question/model/QuesOption.java

@@ -13,6 +13,10 @@ public class QuesOption implements Serializable{
     private String optionBody;//选项内容
 
     private String optionBodyWord;//选项word
+    /** 
+     * 是否是正确答案  1:是  0:否
+     */
+    private short ifRightAnswer;
 
     public static long getSerialVersionUID() {
         return serialVersionUID;
@@ -42,6 +46,13 @@ public class QuesOption implements Serializable{
         this.optionBodyWord = optionBodyWord;
     }
 
-    public QuesOption() {
-    }
+    public QuesOption() {}
+
+	public short getIfRightAnswer() {
+		return ifRightAnswer;
+	}
+
+	public void setIfRightAnswer(short ifRightAnswer) {
+		this.ifRightAnswer = ifRightAnswer;
+	}
 }

+ 34 - 3
cqb-question-resource/src/main/java/com/qmth/cqb/question/model/Question.java

@@ -48,7 +48,13 @@ public class Question implements Serializable {
 
     private List<Question> subQuestions;// 子题目,用于套题
 
-    private Double score;//预设分值
+    private Double score;// 预设分值
+
+    private String courseNo;// 课程CODE
+
+    private String courseName;// 课程名称
+
+    private String orgId; // 机构ID
 
     private Map<String, String> quesParams;// 试题属性
 
@@ -173,9 +179,9 @@ public class Question implements Serializable {
     }
 
     public WordprocessingMLPackage getPkgObj() {
-        if(this.quesPkg != null && this.quesPkg.length > 0){
+        if (this.quesPkg != null && this.quesPkg.length > 0) {
             return DocxProcessUtil.getPkg(this.quesPkg);
-        }else{
+        } else {
             return null;
         }
 
@@ -196,4 +202,29 @@ public class Question implements Serializable {
     public Question() {
         this.createTime = CommonUtils.getCurDateTime();
     }
+
+    public String getCourseNo() {
+        return courseNo;
+    }
+
+    public void setCourseNo(String courseNo) {
+        this.courseNo = courseNo;
+    }
+
+    public String getCourseName() {
+        return courseName;
+    }
+
+    public void setCourseName(String courseName) {
+        this.courseName = courseName;
+    }
+
+    public String getOrgId() {
+        return orgId;
+    }
+
+    public void setOrgId(String orgId) {
+        this.orgId = orgId;
+    }
+
 }

+ 31 - 0
cqb-question-resource/src/main/java/com/qmth/cqb/question/model/QuestionBak.java

@@ -47,6 +47,12 @@ public class QuestionBak implements Serializable {
 
     private Double score;// 预设分值
 
+    private String courseNo;// 课程CODE
+
+    private String courseName;// 课程名称
+
+    private String orgId; // 机构ID
+
     private Map<String, String> quesParams;// 试题属性
 
     public String getId() {
@@ -189,4 +195,29 @@ public class QuestionBak implements Serializable {
     public QuestionBak() {
         this.createTime = CommonUtils.getCurDateTime();
     }
+
+    public String getCourseNo() {
+        return courseNo;
+    }
+
+    public void setCourseNo(String courseNo) {
+        this.courseNo = courseNo;
+    }
+
+    public String getCourseName() {
+        return courseName;
+    }
+
+    public void setCourseName(String courseName) {
+        this.courseName = courseName;
+    }
+
+    public String getOrgId() {
+        return orgId;
+    }
+
+    public void setOrgId(String orgId) {
+        this.orgId = orgId;
+    }
+
 }

+ 26 - 0
cqb-question-resource/src/main/java/com/qmth/cqb/question/model/QuestionSearchCondition.java

@@ -2,6 +2,8 @@ package com.qmth.cqb.question.model;
 
 import java.util.Map;
 
+import org.apache.commons.lang3.StringUtils;
+
 import cn.com.qmth.examcloud.common.dto.question.enums.QuesStructType;
 
 public class QuestionSearchCondition {
@@ -16,6 +18,10 @@ public class QuestionSearchCondition {
 
     private Map<String, String> quesParams;// 试题其他属性
 
+    private String courseNo;// 课程CODE
+
+    private String orgId;
+
     public String getId() {
         return id;
     }
@@ -56,4 +62,24 @@ public class QuestionSearchCondition {
         this.quesParams = quesParams;
     }
 
+    public String getCourseNo() {
+        return courseNo;
+    }
+
+    public void setCourseNo(String courseNo) {
+        if (StringUtils.isBlank(courseNo)) {
+            this.courseNo = null;
+        } else {
+            this.courseNo = courseNo;
+        }
+    }
+
+    public String getOrgId() {
+        return orgId;
+    }
+
+    public void setOrgId(String orgId) {
+        this.orgId = orgId;
+    }
+
 }

+ 293 - 107
cqb-question-resource/src/main/java/com/qmth/cqb/question/service/QuesService.java

@@ -1,107 +1,293 @@
-package com.qmth.cqb.question.service;
-
-import java.util.List;
-
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.data.domain.Example;
-import org.springframework.data.domain.Page;
-import org.springframework.data.domain.PageRequest;
-import org.springframework.stereotype.Service;
-
-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.QuestionSearchCondition;
-import com.qmth.cqb.utils.BeanCopierUtil;
-
-/**
- * Created by songyue on 16/12/28.
- */
-@Service
-public class QuesService {
-
-    @Autowired
-    QuesRepo quesRepo;
-
-    /**
-     * 保存试题
-     * 
-     * @param question
-     */
-    public void saveQues(Question question) {
-        Question saveQues = quesRepo.findOne(question.getId());
-        saveQues.setQuesAnswer(question.getQuesAnswer());
-        saveQues.setScore(question.getScore());
-        saveQues.setQuesBody(question.getQuesBody());
-        if (question.getQuesOptions() != null && question.getQuesOptions().size() > 0) {
-            List<QuesOption> quesOptions = question.getQuesOptions();
-            List<QuesOption> saveQuesOptions = saveQues.getQuesOptions();
-            if (saveQuesOptions.size() != quesOptions.size()) {
-                saveQues.setQuesOptions(quesOptions);
-            } else {
-                for (int i = 0; i < quesOptions.size(); i++) {
-                    saveQuesOptions.get(i).setOptionBody(quesOptions.get(i).getOptionBody());
-
-                }
-            }
-
-        }
-        quesRepo.save(saveQues);
-    }
-
-    /**
-     * 查询所有试题
-     * 
-     * @param searchCondition
-     * @param curPage
-     * @param pageSize
-     * @return
-     */
-    public Page<Question> findAll(QuestionSearchCondition searchCondition, int curPage, int pageSize) {
-        Question ques = BeanCopierUtil.copyProperties(searchCondition, Question.class);
-        Page<Question> list = quesRepo.findAll(Example.of(ques), new PageRequest(curPage - 1, pageSize));
-        for (Question question : list) {
-            formatQues(question);
-        }
-        return list;
-    }
-
-    /**
-     * 按ID获取试题
-     * 
-     * @param id
-     * @return
-     */
-    public Question findById(String id) {
-        Question question = quesRepo.findOne(id);
-        formatQues(question);
-        return question;
-    }
-
-    /**
-     * 去除试题中的word
-     * 
-     * @param question
-     */
-    public void formatQues(Question question) {
-        formatQuesUnit(question);
-        if (question.getSubQuestions() != null && question.getSubQuestions().size() > 0) {
-            question.getSubQuestions().stream().forEach(subQues -> {
-                formatQuesUnit(subQues);
-            });
-        }
-    }
-
-    public void formatQuesUnit(Question question) {
-        question.setQuesBodyWord(null);
-        question.setQuesAnswerWord(null);
-        question.setQuesAnswerAnalysisWord(null);
-        question.setQuesPkg(new byte[0]);
-        if (question.getQuesOptions() != null && question.getQuesOptions().size() > 0) {
-            question.getQuesOptions().stream().forEach(quesOption -> {
-                quesOption.setOptionBodyWord(null);
-            });
-        }
-    }
-
-}
+package com.qmth.cqb.question.service;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Set;
+
+import org.apache.commons.lang3.StringEscapeUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.docx4j.openpackaging.packages.WordprocessingMLPackage;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.domain.Example;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.PageRequest;
+import org.springframework.data.domain.Pageable;
+import org.springframework.stereotype.Service;
+
+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.QuestionSearchCondition;
+import com.qmth.cqb.utils.BeanCopierUtil;
+import com.qmth.cqb.utils.CommonUtils;
+import com.qmth.cqb.utils.word.DocxProcessUtil;
+
+import cn.com.qmth.examcloud.common.dto.question.enums.QuesStructType;
+
+/**
+ * Created by songyue on 16/12/28.
+ */
+@Service
+public class QuesService {
+
+    @Autowired
+    QuesRepo quesRepo;
+
+    /**
+     * 套题子题按序号自动生成ID
+     *
+     * @param question
+     */
+    private void updateSubId(Question question) {
+        if (question.getSubQuestions() != null) {
+            int index = 0;
+            for (Question sub : question.getSubQuestions()) {
+                index++;
+                sub.setId(String.valueOf(index));
+            }
+        }
+    }
+
+    /**
+     * 更新已存在的试题信息
+     *
+     * @param previous
+     * @param update
+     */
+    private void updateMainInfo(Question previous, Question update) {
+        String now = CommonUtils.getCurDateTime();
+        if (update.getScore() != null) {
+            previous.setScore(update.getScore());
+        }
+        previous.setQuesAnswer(update.getQuesAnswer());
+        previous.setQuesAnswerAnalysis(update.getQuesAnswerAnalysis());
+        previous.setQuesBody(update.getQuesBody());
+        if (update.getQuesOptions() != null && update.getQuesOptions().size() > 0) {
+            List<QuesOption> quesOptions = update.getQuesOptions();
+            List<QuesOption> saveQuesOptions = previous.getQuesOptions();
+            if (saveQuesOptions.size() != quesOptions.size()) {
+                previous.setQuesOptions(quesOptions);
+            } else {
+                for (int i = 0; i < quesOptions.size(); i++) {
+                    saveQuesOptions.get(i).setOptionBody(quesOptions.get(i).getOptionBody());
+                }
+            }
+        }
+        if (update.getQuesParams() != null) {
+            if (previous.getQuesParams() == null) {
+                previous.setQuesParams(new HashMap<>());
+            }
+            for (String key : update.getQuesParams().keySet()) {
+                previous.getQuesParams().put(key, update.getQuesParams().get(key));
+            }
+        }
+        if (previous.getCreateTime() == null) {
+            previous.setCreateTime(now);
+        }
+        if (update.getSubQuestions() != null) {
+            if (previous.getSubQuestions() == null) {
+                previous.setSubQuestions(new ArrayList<>());
+            }
+            int previousSize = previous.getSubQuestions().size();
+            int updateSize = update.getSubQuestions().size();
+            for (int i = 0; i < updateSize; i++) {
+                if (previousSize <= i) {
+                    previous.getSubQuestions().add(update.getSubQuestions().get(i));
+                } else {
+                    updateMainInfo(previous.getSubQuestions().get(i), update.getSubQuestions().get(i));
+                }
+            }
+        }
+        previous.setUpdateTime(now);
+        updateSubId(previous);
+    }
+
+    /**
+     * 保存试题
+     *
+     * @param question
+     */
+    public Question saveQues(Question question) {
+        String now = CommonUtils.getCurDateTime();
+        Question saveQues = null;
+        if (StringUtils.isNotEmpty(question.getId())) {
+            saveQues = quesRepo.findOne(question.getId());
+        }
+        if (saveQues == null) {
+            question.setCreateTime(now);
+            question.setUpdateTime(now);
+            updateSubId(question);
+            updateQuesWord(question);
+            return quesRepo.save(question);
+        } else {
+            updateMainInfo(saveQues, question);
+            updateQuesWord(saveQues);
+            return quesRepo.save(saveQues);
+        }
+    }
+
+    /**
+     * 保存导入试题
+     * 
+     * @param question
+     * @return
+     */
+    public Question saveImportQues(Question question) {
+        String now = CommonUtils.getCurDateTime();
+        Question saveQues = null;
+        if (StringUtils.isNotEmpty(question.getId())) {
+            saveQues = quesRepo.findOne(question.getId());
+        }
+        if (saveQues == null) {
+            question.setCreateTime(now);
+            question.setUpdateTime(now);
+            updateSubId(question);
+            return quesRepo.save(question);
+        } else {
+            updateMainInfo(saveQues, question);
+            return quesRepo.save(saveQues);
+        }
+    }
+
+    /**
+     * 批量保存导入试题
+     * 
+     * @param list
+     */
+    public void saveImportQuesList(List<Question> list) {
+        if (list != null) {
+            for (Question question : list) {
+                saveImportQues(question);
+            }
+        }
+    }
+
+    /**
+     * 批量保存试题
+     *
+     * @param list
+     */
+    public void saveQuesList(List<Question> list) {
+        if (list != null) {
+            for (Question question : list) {
+                saveQues(question);
+            }
+        }
+    }
+
+    /**
+     * 查询所有试题
+     *
+     * @param searchCondition
+     * @param curPage
+     * @param pageSize
+     * @return
+     */
+    public Page<Question> findAll(QuestionSearchCondition searchCondition, int curPage, int pageSize) {
+        Question ques = BeanCopierUtil.copyProperties(searchCondition, Question.class);
+        Page<Question> list = quesRepo.findAll(Example.of(ques), new PageRequest(curPage - 1, pageSize));
+        for (Question question : list) {
+            formatQues(question);
+        }
+        return list;
+    }
+
+    /**
+     * 查询按ID过滤的试题
+     *
+     * @param idSet
+     * @param curPage
+     * @param pageSize
+     * @return
+     */
+    public Page<Question> findByIdExclude(Set<String> idSet, String courseNo, QuesStructType quesType, int curPage,
+            int pageSize) {
+        Pageable page = new PageRequest(curPage - 1, pageSize);
+        Page<Question> list = quesType != null
+                ? quesRepo.findByIdNotInAndCourseNoAndQuestionType(idSet, courseNo, quesType, page)
+                : quesRepo.findByIdNotInAndCourseNo(idSet, courseNo, page);
+        for (Question question : list) {
+            formatQues(question);
+        }
+        return list;
+    }
+
+    /**
+     * 按ID获取试题
+     *
+     * @param id
+     * @return
+     */
+    public Question findById(String id) {
+        Question question = quesRepo.findOne(id);
+        formatQues(question);
+        return question;
+    }
+
+    /**
+     * 去除试题中的word
+     *
+     * @param question
+     */
+    public void formatQues(Question question) {
+        formatQuesUnit(question);
+        if (question.getSubQuestions() != null && question.getSubQuestions().size() > 0) {
+            question.getSubQuestions().stream().forEach(subQues -> {
+                formatQuesUnit(subQues);
+            });
+        }
+    }
+
+    public void formatQuesUnit(Question question) {
+        question.setQuesBodyWord(null);
+        question.setQuesAnswerWord(null);
+        question.setQuesAnswerAnalysisWord(null);
+        question.setQuesPkg(new byte[0]);
+        if (question.getQuesOptions() != null && question.getQuesOptions().size() > 0) {
+            question.getQuesOptions().stream().forEach(quesOption -> {
+                quesOption.setOptionBodyWord(null);
+            });
+        }
+    }
+
+    /**
+     * 保存后更新word
+     * 
+     * @param question
+     */
+    public void updateQuesWord(Question question) {
+        WordprocessingMLPackage wordMLPackage = null;
+        try {
+            wordMLPackage = WordprocessingMLPackage.createPackage();
+            updateQuesWordUnit(wordMLPackage, question);
+            List<Question> subQuesList = question.getSubQuestions();
+            if (subQuesList != null && subQuesList.size() > 0) {
+                for (Question subQues : subQuesList) {
+                    updateQuesWordUnit(wordMLPackage, subQues);
+                }
+            }
+            question.setQuesPkg(DocxProcessUtil.getPkgByte(wordMLPackage));
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+    public void updateQuesWordUnit(WordprocessingMLPackage wordMLPackage, Question question) throws Exception {
+        String quesBody = StringEscapeUtils.unescapeHtml4(question.getQuesBody());
+        String quesAnswer = StringEscapeUtils.unescapeHtml4(question.getQuesAnswer());
+        question.setQuesBodyWord(DocxProcessUtil.html2Docx(wordMLPackage, quesBody));
+        DocxProcessUtil.initTmpPackage(wordMLPackage);
+        question.setQuesAnswerWord(DocxProcessUtil.html2Docx(wordMLPackage, quesAnswer));
+        DocxProcessUtil.initTmpPackage(wordMLPackage);
+        List<QuesOption> quesOptions = question.getQuesOptions();
+        if (quesOptions != null && quesOptions.size() > 0) {
+            for (QuesOption quesOption : quesOptions) {
+                quesOption.setOptionBodyWord(DocxProcessUtil.html2Docx(wordMLPackage,
+                        StringEscapeUtils.unescapeHtml4(quesOption.getOptionBody())));
+                DocxProcessUtil.initTmpPackage(wordMLPackage);
+            }
+        }
+    }
+
+}

+ 11 - 3
cqb-question-resource/src/main/java/com/qmth/cqb/question/web/QuesController.java

@@ -2,6 +2,8 @@ package com.qmth.cqb.question.web;
 
 import java.util.List;
 
+import javax.servlet.http.HttpServletRequest;
+
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.http.HttpStatus;
 import org.springframework.http.ResponseEntity;
@@ -21,6 +23,7 @@ import com.qmth.cqb.question.model.Question;
 import com.qmth.cqb.question.model.QuestionSearchCondition;
 import com.qmth.cqb.question.service.QuesService;
 
+import cn.com.qmth.examcloud.common.uac.entity.AccessUser;
 import io.swagger.annotations.ApiOperation;
 
 /**
@@ -60,8 +63,12 @@ public class QuesController {
      */
     @ApiOperation(value = "分页查询试题", notes = "分页查询试题")
     @GetMapping(value = "/question/{curPage}/{pageSize}")
-    public ResponseEntity getAllQuestion(@ModelAttribute QuestionSearchCondition searchCondition,
-            @PathVariable int curPage, @PathVariable int pageSize) {
+    public ResponseEntity getAllQuestion(HttpServletRequest request,
+                                        @ModelAttribute QuestionSearchCondition searchCondition,
+                                        @PathVariable int curPage, 
+                                        @PathVariable int pageSize) {
+        AccessUser user = (AccessUser) request.getAttribute("accessUser");
+        searchCondition.setOrgId(user.getOrgId().toString());
         return new ResponseEntity(quesService.findAll(searchCondition, curPage, pageSize), HttpStatus.OK);
     }
 
@@ -86,7 +93,8 @@ public class QuesController {
      */
     @ApiOperation(value = "新增试题", notes = "新增试题")
     @PostMapping(value = "/question")
-    public ResponseEntity addQuestion(@RequestBody Question question) {
+    public ResponseEntity addQuestion(HttpServletRequest request,
+                                      @RequestBody Question question) {
         return new ResponseEntity(quesRepo.save(question), HttpStatus.CREATED);
     }
 

+ 1 - 1
cqb-starter/src/main/resources/application-dev.properties

@@ -1,3 +1,3 @@
 spring.data.mongodb.uri=mongodb://192.168.1.99:27017/comm-ques-bank
 spring.data.mongodb.grid-fs-database=comm-ques-bank
-eureka.client.serviceUrl.defaultZone=http://192.168.1.88:1111/eureka/
+eureka.client.serviceUrl.defaultZone=http://192.168.1.161:1111/eureka/

+ 2 - 1
cqb-starter/src/main/resources/application-prod.properties

@@ -1,3 +1,4 @@
-spring.data.mongodb.uri=mongodb://119.23.127.95:3718/comm-ques-bank
+spring.data.mongodb.uri=mongodb://root:Qmth87863577@119.23.127.95:3717/?authSource=admin&authMechanism=SCRAM-SHA-1
+spring.data.mongodb.database=comm-ques-bank
 spring.data.mongodb.grid-fs-database=comm-ques-bank
 eureka.client.serviceUrl.defaultZone=http://localhost:1111/eureka/

+ 2 - 2
cqb-starter/src/main/resources/application-test.properties

@@ -1,3 +1,3 @@
-spring.data.mongodb.uri=mongodb://192.168.1.99:27017/comm-ques-bank
-spring.data.mongodb.grid-fs-database=comm-ques-bank
+spring.data.mongodb.uri=mongodb://192.168.1.74:27017/comm-ques-bank
+spring.data.mongodb.grid-fs-database=comm-ques-bank
 eureka.client.serviceUrl.defaultZone=http://localhost:1111/eureka/

+ 17 - 17
cqb-starter/src/main/resources/log4j2.xml

@@ -1,18 +1,18 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<Configuration status="WARN">
-    <Appenders>
-        <Console name="Console" target="SYSTEM_OUT" follow="true">
-            <PatternLayout>
-                <pattern>%d %p %C{1.} [%t] %m%n</pattern>
-            </PatternLayout>
-        </Console>
-    </Appenders>
-    <Loggers>
-        <!-- 输出info级别信息 -->
-        <Root level="info">
-            <AppenderRef ref="Console" />
-        </Root>
-        <Logger name="org.docx4j" level="off" />
-
-    </Loggers>
+<?xml version="1.0" encoding="UTF-8"?>
+<Configuration status="WARN">
+    <Appenders>
+        <Console name="Console" target="SYSTEM_OUT" follow="true">
+            <PatternLayout charset="UTF-8">
+                <pattern>%d %p %C{1.} [%t] %m%n</pattern>
+            </PatternLayout>
+        </Console>
+    </Appenders>
+    <Loggers>
+        <!-- 输出info级别信息 -->
+        <Root level="info">
+            <AppenderRef ref="Console" />
+        </Root>
+        <Logger name="org.docx4j" level="debug" />
+
+    </Loggers>
 </Configuration>

+ 1 - 1
cqb-starter/src/test/java/com/qmth/cqb/AppTest.java

@@ -174,7 +174,7 @@ public class AppTest {
         examPaper.setCourseCode("1");
         examPaper.setExtractCount(1);
         examPaper.setGroupCode("1");
-        examPaper.setPaperId("58b3e0b06def240e05b0c0e1");
+//        examPaper.setPaperId("58b3e0b06def240e05b0c0e1");
         examPaperRepo.save(examPaper);
 
         ExtractConfig extractConfig = new ExtractConfig();

+ 140 - 0
cqb-starter/src/test/java/com/qmth/cqb/ExtractConfigServiceTest.java

@@ -0,0 +1,140 @@
+package com.qmth.cqb;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.junit4.SpringRunner;
+
+import com.qmth.cqb.paper.dao.PaperRepo;
+import com.qmth.cqb.paper.model.ExamPaper;
+import com.qmth.cqb.paper.model.ExtractConfig;
+import com.qmth.cqb.paper.model.Paper;
+import com.qmth.cqb.paper.service.ExtractConfigService;
+
+/**
+ * @author  	chenken
+ * @date    	2017年4月18日 下午3:32:25
+ * @company 	QMTH
+ * @description PaperServiceTest.java
+ */
+@RunWith(SpringRunner.class)
+@SpringBootTest
+public class ExtractConfigServiceTest {
+	
+	@Autowired
+	private PaperRepo paperRepo;
+	@Autowired
+	private ExtractConfigService extractConfigService;
+	
+	/**
+	 * 测试保存调卷规则
+	 */
+	@Test
+	public void testSaveExtractConfig(){
+		ExtractConfig extractConfig = new ExtractConfig();
+		extractConfig.setExamId(2L);
+		extractConfig.setExamName("测试考试0419");
+		extractConfig.setExamType("TRANDITION");
+		extractConfig.setCourseCode("03013750");
+		extractConfig.setCourseName("测试课程0419");
+		extractConfig.setCallType("WHOLE_SET");
+		extractConfig.setScrambling_the_question_order((short)1);
+		extractConfig.setScrambling_the_option_order((short)1);
+		//List<ExamPaper> examPaperList = buildOnlineExamPaper();
+		List<ExamPaper> examPaperList = buildTraditionExamPaper();
+		extractConfig.setExamPaperList(examPaperList);
+		extractConfigService.saveExtractConfig(extractConfig);
+	}
+	/**
+	 * 测试根据调卷规则ID生成试卷
+	 */
+	@Test
+	public void testMakePaperByConfig(){
+		extractConfigService.makePaperByConfig("58f6d77aaa9e290d805befa3");
+	}
+	
+	private List<ExamPaper> buildOnlineExamPaper(){
+		List<ExamPaper> examPaperList = new ArrayList<ExamPaper>();
+		/*******************A类型********************/
+		ExamPaper examPaper1 = new ExamPaper();
+		examPaper1.setExamId(1L);
+		examPaper1.setCourseCode("03013750");
+		examPaper1.setGroupCode("A");
+		examPaper1.setWeight(80);
+		Paper paper1 = new Paper();
+		paper1.setId("58f0a15258e31a0d7448d58c");
+		examPaper1.setPaper(paper1);
+		examPaperList.add(examPaper1);
+		ExamPaper examPaper2 = new ExamPaper();
+		examPaper2.setExamId(1L);
+		examPaper2.setCourseCode("03013750");
+		examPaper2.setGroupCode("A");
+		examPaper2.setWeight(20);
+		Paper paper2 = new Paper();
+		paper2.setId("58f42fcd58e31a025844bfff");
+		examPaper2.setPaper(paper2);
+		examPaperList.add(examPaper2);
+		/*******************B类型********************/
+		ExamPaper examPaper3 = new ExamPaper();
+		examPaper3.setExamId(1L);
+		examPaper3.setCourseCode("03013750");
+		examPaper3.setGroupCode("B");
+		examPaper3.setWeight(60);
+		Paper paper3 = new Paper();
+		paper3.setId("58f4300c58e31a025844c02f");
+		examPaper3.setPaper(paper3);
+		examPaperList.add(examPaper3);
+		ExamPaper examPaper4 = new ExamPaper();
+		examPaper4.setExamId(1L);
+		examPaper4.setCourseCode("03013750");
+		examPaper4.setGroupCode("B");
+		examPaper4.setWeight(40);
+		Paper paper4 = new Paper();
+		paper4.setId("e483c730-921e-4212-a67e-42235a0aec00");
+		examPaper4.setPaper(paper4);
+		examPaperList.add(examPaper4);
+		return examPaperList;
+	}
+	
+	private List<ExamPaper> buildTraditionExamPaper(){
+		List<ExamPaper> examPaperList = new ArrayList<ExamPaper>();
+		/*******************A类型********************/
+		ExamPaper examPaper1 = new ExamPaper();
+		examPaper1.setExamId(1L);
+		examPaper1.setCourseCode("03013750");
+		examPaper1.setGroupCode("A");
+		examPaper1.setWeight(100);
+		Paper paper1 = new Paper();
+		paper1.setId("58f0a15258e31a0d7448d58c");
+		examPaper1.setPaper(paper1);
+		examPaperList.add(examPaper1);
+		/*******************B类型********************/
+		ExamPaper examPaper2 = new ExamPaper();
+		examPaper2.setExamId(1L);
+		examPaper2.setCourseCode("03013750");
+		examPaper2.setGroupCode("B");
+		examPaper2.setWeight(100);
+		Paper paper2 = new Paper();
+		paper1.setId("58f0a15258e31a0d7448d58c");
+		examPaper1.setPaper(paper2);
+		examPaperList.add(examPaper2);
+		return examPaperList;
+	}
+	
+	public static void main(String[] args) {
+		List<String> newList = new ArrayList<String>();
+		newList.add("a");
+		newList.add("b");
+		newList.add("c");
+		newList.add("d");
+		newList.add("e");
+		Collections.shuffle(newList);
+		System.out.println(newList);
+	}
+}
+

+ 57 - 0
cqb-starter/src/test/java/com/qmth/cqb/ProbabilityTest.java

@@ -0,0 +1,57 @@
+package com.qmth.cqb;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Random;
+
+/**
+ * Java 从一组数据随机选择并可设置出现概率
+ * @author pc
+ *
+ */
+public class ProbabilityTest {
+  
+     //String 可以为任意类型 也可以自定义类型
+     static Map<Object, Integer> keyChanceMap = new HashMap<Object,Integer>();
+     static{
+    	 keyChanceMap.put("试卷A", 100);
+     }
+     
+     public static void main(String[] args) {
+         Map<String, Integer> count = new HashMap<String,Integer>();
+         for (int i = 0; i < 100; i++) {
+             String item = chanceSelect(keyChanceMap);
+             if (count.containsKey(item)) {
+                 count.put(item, count.get(item) + 1);
+             } else {
+                 count.put(item, 1);
+             }
+         }
+         for(String id : count.keySet()){
+             System.out.println(id+"\t被选中了 "+count.get(id)+" 次");
+         }
+     }
+ 
+     
+     public static String chanceSelect(Map<Object, Integer> keyChanceMap) { 
+         if(keyChanceMap == null || keyChanceMap.size() == 0) {
+        	 return null;  
+         }
+         Integer sum = 0;  
+         for (Integer value : keyChanceMap.values()) {  
+              sum += value;  
+         }  
+         // 从1开始  
+         Integer rand = new Random().nextInt(sum) + 1;  
+           
+         for (Map.Entry<Object, Integer> entry : keyChanceMap.entrySet()) {
+             rand -= entry.getValue();
+             // 选中
+             if (rand <= 0) {
+                 String item = entry.getKey()+"";
+                 return item;
+             }
+         } 
+           
+         return null;  
+    }
+ }