xiatian пре 2 година
родитељ
комит
06b088426b

+ 4 - 6
examcloud-core-questions-api-provider/src/main/java/cn/com/qmth/examcloud/core/questions/api/controller/PaperController.java

@@ -430,10 +430,9 @@ public class PaperController extends ControllerSupport {
     @ResponseBody
     @ApiOperation(value = "删除试卷中的试题", notes = "删除试卷中的试题")
     @DeleteMapping(value = "/paper/deleteQuestion/{questionId}")
-    public ResponseEntity<Object> deletePaperQuestion(@PathVariable String questionId) {
+    public void deletePaperQuestion(@PathVariable String questionId) {
         User user = getAccessUser();
-        List<String> paperNames = paperService.deleteImportQuestionById(null, questionId, user);
-        return new ResponseEntity<>(paperNames, HttpStatus.OK);
+        paperService.deleteImportQuestionById(null, questionId, user);
     }
 
     /**
@@ -445,10 +444,9 @@ public class PaperController extends ControllerSupport {
     @ResponseBody
     @ApiOperation(value = "删除导入试卷中的试题", notes = "删除导入试卷中的试题")
     @DeleteMapping(value = "/paper/deleteQuestion/{detailUnitId}/{questionId}")
-    public ResponseEntity<Object> deleteImportPaperQuestion(@PathVariable String detailUnitId, @PathVariable String questionId) {
+    public void deleteImportPaperQuestion(@PathVariable String detailUnitId, @PathVariable String questionId) {
         User user = getAccessUser();
-        List<String> paperNames = paperService.deleteImportQuestionById(detailUnitId, questionId, user);
-        return new ResponseEntity<>(paperNames, HttpStatus.OK);
+        paperService.deleteImportQuestionById(detailUnitId, questionId, user);
     }
 
     /**

+ 9 - 2
examcloud-core-questions-api-provider/src/main/java/cn/com/qmth/examcloud/core/questions/api/controller/PaperStructController.java

@@ -9,6 +9,7 @@ import cn.com.qmth.examcloud.core.questions.dao.PaperStructRepo;
 import cn.com.qmth.examcloud.core.questions.dao.entity.PaperStruct;
 import cn.com.qmth.examcloud.core.questions.dao.entity.PaperStructSearchInfo;
 import cn.com.qmth.examcloud.core.questions.service.PaperStructService;
+import cn.com.qmth.examcloud.core.questions.service.RandomPaperService;
 import cn.com.qmth.examcloud.core.questions.service.bean.dto.QuesNameDto;
 import cn.com.qmth.examcloud.web.security.DataRule;
 import cn.com.qmth.examcloud.web.support.ControllerSupport;
@@ -32,10 +33,13 @@ import java.util.stream.Stream;
 public class PaperStructController extends ControllerSupport {
 
     @Autowired
-    PaperStructService paperStructService;
+    private PaperStructService paperStructService;
+    
+    @Autowired
+    private RandomPaperService randomPaperService;
 
     @Autowired
-    PaperStructRepo paperStructRepo;
+    private PaperStructRepo paperStructRepo;
 
     /**
      * 获取所有试卷结构
@@ -100,6 +104,9 @@ public class PaperStructController extends ControllerSupport {
     public ResponseEntity<Object> updatePaperStruct(@RequestBody PaperStruct ps) {
         User user = getAccessUser();
         ps.setOrgId(user.getRootOrgId()+"");
+        if(randomPaperService.existStruct(ps.getId())) {
+        	throw new StatusException("该组卷结构已被抽题模板使用,不能修改");
+        }
         PaperStruct paperStruct = paperStructService.save(ps, user);
         if (paperStruct == null) {
             return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);

+ 138 - 143
examcloud-core-questions-api-provider/src/main/java/cn/com/qmth/examcloud/core/questions/api/controller/QuesController.java

@@ -7,7 +7,6 @@ import java.util.stream.Stream;
 import org.springframework.beans.factory.annotation.Autowired;
 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;
@@ -40,147 +39,143 @@ import io.swagger.annotations.ApiOperation;
 @RequestMapping("${api_cqb}/")
 public class QuesController extends ControllerSupport {
 
-    @Autowired
-    QuesService quesService;
-
-    @Autowired
-    QuesRepo quesRepo;
-
-    @Autowired
-    Gson gson;
-    
-    @Autowired
-    PaperDetailUnitService paperDetailUnitService;
-
-    /**
-     * 获取试题
-     *
-     * @param id
-     * @return
-     */
-    @ApiOperation(value = "获取试题", notes = "获取试题")
-    @GetMapping(value = "/question/{id}")
-    public ResponseEntity<Object> getQuesById(@PathVariable String id) {
-        Question ques = cn.com.qmth.examcloud.core.questions.base.Model.of(quesRepo.findById(id));
-        quesService.formatQues(ques);
-        return new ResponseEntity<>(ques, HttpStatus.OK);
-    }
-
-    /**
-     * 分页查询试题
-     *
-     * @return
-     */
-    @DataRule(type = DataRuleType.COURSE)
-    @ApiOperation(value = "分页查询试题", notes = "分页查询试题")
-    @GetMapping(value = "/question/{curPage}/{pageSize}")
-    public ResponseEntity<Object> getAllQuestion(@ModelAttribute QuestionSearchCondition searchCondition,
-                                                 @PathVariable int curPage,
-                                                 @PathVariable int pageSize) {
-        User user = getAccessUser();
-        UserDataRule ud = getUserDataRule(DataRuleType.COURSE);
-        searchCondition.setOrgId(user.getRootOrgId().toString());
-        return new ResponseEntity<>(quesService.findAll(searchCondition, curPage, pageSize,ud), HttpStatus.OK);
-    }
-
-    /**
-     * 更新试题信息
-     *
-     * @param
-     * @return
-     */
-    @ApiOperation(value = "更新试题", notes = "更新试题")
-    @PutMapping(value = "/question")
-    public ResponseEntity<Object> updateQuestion(@RequestBody Question question) {
-        quesService.saveQues(question);
-
-        //清除缓存
-        paperDetailUnitService.clearQuestionCache(question.getId());
-
-        return new ResponseEntity<>(HttpStatus.OK);
-    }
-
-    /**
-     * 新增试题
-     *
-     * @param question
-     * @return
-     */
-    @ApiOperation(value = "新增试题", notes = "新增试题")
-    @PostMapping(value = "/question")
-    public ResponseEntity<Object> addQuestion(@RequestBody Question question) {
-    	ResponseEntity<Object> ret=new ResponseEntity<>(quesService.saveQues(question), HttpStatus.CREATED);
-        return  ret;
-    }
-
-    /**
-     * 删除试题
-     *
-     * @param id
-     * @return
-     */
-    @ApiOperation(value = "删除试题", notes = "删除试题")
-    @DeleteMapping(value = "/question/{id}")
-    public ResponseEntity<Object> removeQuestion(@PathVariable String id) {
-        quesRepo.deleteById(id);
-
-        //清除缓存
-        paperDetailUnitService.clearQuestionCache(id);
-
-        return new ResponseEntity<>(HttpStatus.OK);
-    }
-
-    /**
-     * 删除套题子题
-     *
-     * @param id
-     * @return
-     */
-    @ApiOperation(value = "删除套题子题", notes = "删除套题子题")
-    @PutMapping(value = "/question/{id}/{number}")
-    public ResponseEntity<Object> removeQuestion(@PathVariable String id, @PathVariable String number) {
-        Question question = cn.com.qmth.examcloud.core.questions.base.Model.of(quesRepo.findById(id));
-        List<Question> subQuestions = question.getSubQuestions();
-        subQuestions.remove(Integer.parseInt(number));
-        quesRepo.save(question);
-
-        //清除缓存
-        paperDetailUnitService.clearQuestionCache(id);
-
-        return new ResponseEntity<>(question, HttpStatus.OK);
-    }
-
-    @ApiOperation(value = "查询题目数量", notes = "查询题目数量")
-    @GetMapping(value = "/question/count")
-    public ResponseEntity<Object> getQuesCount(@ModelAttribute QuestionSearchCondition searchCondition) {
-        User user = getAccessUser();
-        searchCondition.setOrgId(user.getRootOrgId().toString());
-        long count = quesService.findQuesCount(searchCondition); 
-        return new ResponseEntity<>(count, HttpStatus.OK);
-    }
-
-    @ApiOperation(value = "根据试卷ids更新试题属性", notes = "根据试卷ids更新试题属性")
-    @PutMapping(value = "/question/updatePro/paperIds")
-    public void updateProByPapers(@RequestParam String ids,
-            @RequestParam(required = false) Double difficultyDegree,
-            @RequestParam(required = false) Boolean publicity) {
-        if(difficultyDegree==null&&publicity==null) {
-            throw new StatusException("10001", "难度和公开度不能都为空");
-        }
-        User user = getAccessUser();
-        List<String> paperList = Stream.of(ids.split(",")).collect(Collectors.toList());
-        quesService.updateProByPapers(paperList, difficultyDegree, publicity, user);
-    }
-
-    @ApiOperation(value = "根据课程代码更新试题属性", notes = "根据课程代码更新试题属性")
-    @PutMapping(value = "/question/updatePro/courseCode/{courseCode}/{difficultyDegree}/{publicity}/{orgId}")
-    public ResponseEntity<Object> updateProByCourse(@PathVariable String courseCode,
-                                                    @PathVariable Double difficultyDegree,
-                                                    @PathVariable Boolean publicity,
-                                                    @PathVariable String orgId) {
-        quesService.updateProByCourse(courseCode, difficultyDegree, publicity, orgId);
-        return new ResponseEntity<>(HttpStatus.OK);
-    }
-
+	@Autowired
+	QuesService quesService;
+
+	@Autowired
+	QuesRepo quesRepo;
+
+	@Autowired
+	Gson gson;
+
+	@Autowired
+	PaperDetailUnitService paperDetailUnitService;
+
+	/**
+	 * 获取试题
+	 *
+	 * @param id
+	 * @return
+	 */
+	@ApiOperation(value = "获取试题", notes = "获取试题")
+	@GetMapping(value = "/question/{id}")
+	public ResponseEntity<Object> getQuesById(@PathVariable String id) {
+		Question ques = cn.com.qmth.examcloud.core.questions.base.Model.of(quesRepo.findById(id));
+		quesService.formatQues(ques);
+		return new ResponseEntity<>(ques, HttpStatus.OK);
+	}
+
+	/**
+	 * 分页查询试题
+	 *
+	 * @return
+	 */
+	@DataRule(type = DataRuleType.COURSE)
+	@ApiOperation(value = "分页查询试题", notes = "分页查询试题")
+	@GetMapping(value = "/question/{curPage}/{pageSize}")
+	public ResponseEntity<Object> getAllQuestion(@ModelAttribute QuestionSearchCondition searchCondition,
+			@PathVariable int curPage, @PathVariable int pageSize) {
+		User user = getAccessUser();
+		UserDataRule ud = getUserDataRule(DataRuleType.COURSE);
+		searchCondition.setOrgId(user.getRootOrgId().toString());
+		return new ResponseEntity<>(quesService.findAll(searchCondition, curPage, pageSize, ud), HttpStatus.OK);
+	}
+
+	/**
+	 * 更新试题信息
+	 *
+	 * @param
+	 * @return
+	 */
+	@ApiOperation(value = "更新试题", notes = "更新试题")
+	@PutMapping(value = "/question")
+	public ResponseEntity<Object> updateQuestion(@RequestBody Question question) {
+		quesService.saveQues(question);
+
+		// 清除缓存
+		paperDetailUnitService.clearQuestionCache(question.getId());
+
+		return new ResponseEntity<>(HttpStatus.OK);
+	}
+
+	/**
+	 * 新增试题
+	 *
+	 * @param question
+	 * @return
+	 */
+	@ApiOperation(value = "新增试题", notes = "新增试题")
+	@PostMapping(value = "/question")
+	public ResponseEntity<Object> addQuestion(@RequestBody Question question) {
+		ResponseEntity<Object> ret = new ResponseEntity<>(quesService.saveQues(question), HttpStatus.CREATED);
+		return ret;
+	}
+
+	/**
+	 * 删除试题
+	 *
+	 * @param id
+	 * @return
+	 */
+	/*
+	 * @ApiOperation(value = "删除试题", notes = "删除试题")
+	 * 
+	 * @DeleteMapping(value = "/question/{id}") public ResponseEntity<Object>
+	 * removeQuestion(@PathVariable String id) { quesRepo.deleteById(id);
+	 * 
+	 * // 清除缓存 paperDetailUnitService.clearQuestionCache(id);
+	 * 
+	 * return new ResponseEntity<>(HttpStatus.OK); }
+	 */
+
+	/**
+	 * 删除套题子题
+	 *
+	 * @param id
+	 * @return
+	 */
+	/*
+	 * @ApiOperation(value = "删除套题子题", notes = "删除套题子题")
+	 * 
+	 * @PutMapping(value = "/question/{id}/{number}") public ResponseEntity<Object>
+	 * removeQuestion(@PathVariable String id, @PathVariable String number) {
+	 * Question question =
+	 * cn.com.qmth.examcloud.core.questions.base.Model.of(quesRepo.findById(id));
+	 * List<Question> subQuestions = question.getSubQuestions();
+	 * subQuestions.remove(Integer.parseInt(number)); quesRepo.save(question);
+	 * 
+	 * //清除缓存 paperDetailUnitService.clearQuestionCache(id);
+	 * 
+	 * return new ResponseEntity<>(question, HttpStatus.OK); }
+	 */
+
+	@ApiOperation(value = "查询题目数量", notes = "查询题目数量")
+	@GetMapping(value = "/question/count")
+	public ResponseEntity<Object> getQuesCount(@ModelAttribute QuestionSearchCondition searchCondition) {
+		User user = getAccessUser();
+		searchCondition.setOrgId(user.getRootOrgId().toString());
+		long count = quesService.findQuesCount(searchCondition);
+		return new ResponseEntity<>(count, HttpStatus.OK);
+	}
+
+	@ApiOperation(value = "根据试卷ids更新试题属性", notes = "根据试卷ids更新试题属性")
+	@PutMapping(value = "/question/updatePro/paperIds")
+	public void updateProByPapers(@RequestParam String ids, @RequestParam(required = false) Double difficultyDegree,
+			@RequestParam(required = false) Boolean publicity) {
+		if (difficultyDegree == null && publicity == null) {
+			throw new StatusException("10001", "难度和公开度不能都为空");
+		}
+		User user = getAccessUser();
+		List<String> paperList = Stream.of(ids.split(",")).collect(Collectors.toList());
+		quesService.updateProByPapers(paperList, difficultyDegree, publicity, user);
+	}
+
+	@ApiOperation(value = "根据课程代码更新试题属性", notes = "根据课程代码更新试题属性")
+	@PutMapping(value = "/question/updatePro/courseCode/{courseCode}/{difficultyDegree}/{publicity}/{orgId}")
+	public ResponseEntity<Object> updateProByCourse(@PathVariable String courseCode,
+			@PathVariable Double difficultyDegree, @PathVariable Boolean publicity, @PathVariable String orgId) {
+		quesService.updateProByCourse(courseCode, difficultyDegree, publicity, orgId);
+		return new ResponseEntity<>(HttpStatus.OK);
+	}
 
 }

+ 1 - 1
examcloud-core-questions-service/src/main/java/cn/com/qmth/examcloud/core/questions/service/PaperService.java

@@ -184,7 +184,7 @@ public interface PaperService {
      * @param questionId
      * @return
      */
-    public List<String> deleteImportQuestionById(String detailUnitId, String questionId, User user);
+    public void deleteImportQuestionById(String detailUnitId, String questionId, User user);
 
     /**
      * 向试卷中插入一个试题

+ 446 - 431
examcloud-core-questions-service/src/main/java/cn/com/qmth/examcloud/core/questions/service/PaperStructService.java

@@ -40,459 +40,474 @@ import java.util.stream.Collectors;
  */
 @Service
 public class PaperStructService {
-	
-	private static int cacheTimeOut=2*60*60;
-
-    @Autowired
-    PaperStructRepo paperStructRepo;
-
-    @Autowired
-    QuesTypeNameRepo quesTypeNameRepo;
-
-    @Autowired
-    MongoTemplate mongoTemplate;
-
-    @Autowired
-    CourseCloudService courseCloudService;
-    
-    @Autowired
-    private RedisClient redisClient;
-
-    /**
-     * 获取所有试卷结构(分页)
-     *
-     * @param searchInfo
-     * @param curPage
-     * @param pageSize
-     * @return
-     */
-    public Page<PaperStruct> getPaperStructs(PaperStructSearchInfo searchInfo, int curPage, int pageSize, UserDataRule userDataRule) {
-         if (userDataRule.assertEmptyQueryResult()) {
-             return Page.empty();
-         }
-
-
-        Query query = new Query();
-        query.addCriteria(Criteria.where("orgId").is(searchInfo.getOrgId()));
-        if (userDataRule.assertNeedQueryRefIds()) {
+
+	private static int cacheTimeOut = 2 * 60 * 60;
+	@Autowired
+	private RandomPaperService randomPaperService;
+
+	@Autowired
+	private PaperStructRepo paperStructRepo;
+
+	@Autowired
+	private QuesTypeNameRepo quesTypeNameRepo;
+
+	@Autowired
+	private MongoTemplate mongoTemplate;
+
+	@Autowired
+	private CourseCloudService courseCloudService;
+
+	@Autowired
+	private RedisClient redisClient;
+
+	/**
+	 * 获取所有试卷结构(分页)
+	 *
+	 * @param searchInfo
+	 * @param curPage
+	 * @param pageSize
+	 * @return
+	 */
+	public Page<PaperStruct> getPaperStructs(PaperStructSearchInfo searchInfo, int curPage, int pageSize,
+			UserDataRule userDataRule) {
+		if (userDataRule.assertEmptyQueryResult()) {
+			return Page.empty();
+		}
+
+		Query query = new Query();
+		query.addCriteria(Criteria.where("orgId").is(searchInfo.getOrgId()));
+		if (userDataRule.assertNeedQueryRefIds()) {
 			Criteria c1 = Criteria.where("courseId").in(userDataRule.getRefIds());
 			Criteria c2 = Criteria.where("courseId").exists(false);
 			Criteria cr = new Criteria();
 			query.addCriteria(cr.orOperator(c1, c2));
 		}
-        query.addCriteria(Criteria.where("type").is(searchInfo.getType()));
-
-        // 判断试卷结构
-        if (PaperStructType.EXACT.name().equals(searchInfo.getType())) {
-            if (StringUtils.isNotBlank(searchInfo.getCourseNo())) {
-                if (!"ALL".equals(searchInfo.getCourseNo())) {
-                    query.addCriteria(Criteria.where("courseNo").is(searchInfo.getCourseNo()));
-                }
-            } else {
-                // “公用”情况
-                query.addCriteria(Criteria.where("courseNo").is(""));
-            }
-        } else {
-            if (StringUtils.isNotBlank(searchInfo.getCourseNo())) {
-                query.addCriteria(Criteria.where("courseNo").is(searchInfo.getCourseNo()));
-            }
-        }
-
-        if (StringUtils.isNotBlank(searchInfo.getName())) {
-            String paperStructName = CommonUtils.escapeExprSpecialWord(searchInfo.getName());
-            query.addCriteria(Criteria.where("name").regex(".*?" + paperStructName + ".*"));
-        }
-
-        if (StringUtils.isNotBlank(searchInfo.getCreator())) {
-            String userName = CommonUtils.escapeExprSpecialWord(searchInfo.getCreator());
-            query.addCriteria(Criteria.where("creator").regex(".*?" + userName + ".*"));
-        }
-
-        long total = this.mongoTemplate.count(query, PaperStruct.class);
-        if (total == 0) {
-            return Page.empty();
-        }
-
-        PageRequest pageable = PageRequest.of(curPage - 1, pageSize);
-        query.with(Sort.by(Sort.Order.desc("createTime")));
-        query.skip(pageable.getOffset());
-        query.limit(pageable.getPageSize());
-
-        List<PaperStruct> paperStructs = this.mongoTemplate.find(query, PaperStruct.class);
-        if (CollectionUtils.isEmpty(paperStructs)) {
-            return Page.empty();
-        }
-
-        Map<String, String> courseNameMaps = new HashMap<>();
-
-        for (PaperStruct paperStruct : paperStructs) {
-            if (StringUtils.isBlank(paperStruct.getCourseNo())) {
-                paperStruct.setCourseName("公用");
-            } else {
-                String courseName = courseNameMaps.get(paperStruct.getCourseNo());
-
-                if (StringUtils.isEmpty(courseName)) {
-                    GetCourseReq req = new GetCourseReq();
-                    req.setRootOrgId(Long.valueOf(paperStruct.getOrgId()));
-                    req.setCode(paperStruct.getCourseNo());
-                    GetCourseResp resp = courseCloudService.getCourse(req);
-                    courseName = resp.getCourseBean().getName();
-                    courseNameMaps.put(paperStruct.getCourseNo(), courseName);
-                }
-
-                paperStruct.setCourseName(courseName);
-            }
-        }
-
-        return new PageImpl<>(paperStructs, pageable, total);
-    }
-
-    /**
-     * 获取所有试卷结构(分页)
-     *
-     * @param searchInfo
-     * @return
-     */
-    public List<PaperStruct> getPaperStructs(PaperStructSearchInfo searchInfo,UserDataRule ud) {
-    	if (ud.assertEmptyQueryResult()) {
+		query.addCriteria(Criteria.where("type").is(searchInfo.getType()));
+
+		// 判断试卷结构
+		if (PaperStructType.EXACT.name().equals(searchInfo.getType())) {
+			if (StringUtils.isNotBlank(searchInfo.getCourseNo())) {
+				if (!"ALL".equals(searchInfo.getCourseNo())) {
+					query.addCriteria(Criteria.where("courseNo").is(searchInfo.getCourseNo()));
+				}
+			} else {
+				// “公用”情况
+				query.addCriteria(Criteria.where("courseNo").is(""));
+			}
+		} else {
+			if (StringUtils.isNotBlank(searchInfo.getCourseNo())) {
+				query.addCriteria(Criteria.where("courseNo").is(searchInfo.getCourseNo()));
+			}
+		}
+
+		if (StringUtils.isNotBlank(searchInfo.getName())) {
+			String paperStructName = CommonUtils.escapeExprSpecialWord(searchInfo.getName());
+			query.addCriteria(Criteria.where("name").regex(".*?" + paperStructName + ".*"));
+		}
+
+		if (StringUtils.isNotBlank(searchInfo.getCreator())) {
+			String userName = CommonUtils.escapeExprSpecialWord(searchInfo.getCreator());
+			query.addCriteria(Criteria.where("creator").regex(".*?" + userName + ".*"));
+		}
+
+		long total = this.mongoTemplate.count(query, PaperStruct.class);
+		if (total == 0) {
+			return Page.empty();
+		}
+
+		PageRequest pageable = PageRequest.of(curPage - 1, pageSize);
+		query.with(Sort.by(Sort.Order.desc("createTime")));
+		query.skip(pageable.getOffset());
+		query.limit(pageable.getPageSize());
+
+		List<PaperStruct> paperStructs = this.mongoTemplate.find(query, PaperStruct.class);
+		if (CollectionUtils.isEmpty(paperStructs)) {
+			return Page.empty();
+		}
+
+		Map<String, String> courseNameMaps = new HashMap<>();
+
+		for (PaperStruct paperStruct : paperStructs) {
+			if (StringUtils.isBlank(paperStruct.getCourseNo())) {
+				paperStruct.setCourseName("公用");
+			} else {
+				String courseName = courseNameMaps.get(paperStruct.getCourseNo());
+
+				if (StringUtils.isEmpty(courseName)) {
+					GetCourseReq req = new GetCourseReq();
+					req.setRootOrgId(Long.valueOf(paperStruct.getOrgId()));
+					req.setCode(paperStruct.getCourseNo());
+					GetCourseResp resp = courseCloudService.getCourse(req);
+					courseName = resp.getCourseBean().getName();
+					courseNameMaps.put(paperStruct.getCourseNo(), courseName);
+				}
+
+				paperStruct.setCourseName(courseName);
+			}
+		}
+
+		return new PageImpl<>(paperStructs, pageable, total);
+	}
+
+	/**
+	 * 获取所有试卷结构(分页)
+	 *
+	 * @param searchInfo
+	 * @return
+	 */
+	public List<PaperStruct> getPaperStructs(PaperStructSearchInfo searchInfo, UserDataRule ud) {
+		if (ud.assertEmptyQueryResult()) {
 			return new ArrayList<>();
 		}
-        Query query = new Query();
-        if (StringUtils.isNotBlank(searchInfo.getCourseNo())) {
-            query.addCriteria(Criteria.where("courseNo")
-                    .in("", searchInfo.getCourseNo()));
-        }
-        query.addCriteria(Criteria.where("orgId").is(searchInfo.getOrgId()));
+		Query query = new Query();
+		if (StringUtils.isNotBlank(searchInfo.getCourseNo())) {
+			query.addCriteria(Criteria.where("courseNo").in("", searchInfo.getCourseNo()));
+		}
+		query.addCriteria(Criteria.where("orgId").is(searchInfo.getOrgId()));
 		if (ud.assertNeedQueryRefIds()) {
 			Criteria c1 = Criteria.where("courseId").in(ud.getRefIds());
 			Criteria c2 = Criteria.where("courseId").exists(false);
 			Criteria cr = new Criteria();
 			cr.orOperator(c1, c2);
 		}
-        query.with(Sort.by(Sort.Order.desc("createTime")));
-        List<PaperStruct> paperList = this.mongoTemplate.find(query, PaperStruct.class);
-        return paperList;
-    }
-
-    public void formatSearchInfo(PaperStructSearchInfo searchInfo) {
-        if (StringUtils.isEmpty(searchInfo.getName())) {
-            searchInfo.setName(null);
-        }
-        if (StringUtils.isEmpty(searchInfo.getCreator())) {
-            searchInfo.setCreator(null);
-        }
-        if (StringUtils.isEmpty(searchInfo.getCourseNo())) {
-            searchInfo.setCourseNo(null);
-        }
-    }
-
-    public void formatPaperStruct(PaperStruct paperStruct) {
-        paperStruct.setCreateTime(null);
-    }
-
-    /**
-     * 保存试卷结构
-     *
-     * @param paperStruct
-     * @return
-     */
-    public PaperStruct save(PaperStruct paperStruct, User user) {
-    	if (StringUtils.isNotBlank(paperStruct.getCourseNo())) {
-    		GetCourseReq req = new GetCourseReq();
-            req.setRootOrgId(Long.valueOf(paperStruct.getOrgId()));
-            req.setCode(paperStruct.getCourseNo());
-            GetCourseResp resp = courseCloudService.getCourse(req);
+		if (StringUtils.isNotBlank(searchInfo.getType())) {
+			query.addCriteria(Criteria.where("type").is(searchInfo.getType()));
+		}
+		query.with(Sort.by(Sort.Order.desc("createTime")));
+		List<PaperStruct> paperList = this.mongoTemplate.find(query, PaperStruct.class);
+		return paperList;
+	}
+
+	public void formatSearchInfo(PaperStructSearchInfo searchInfo) {
+		if (StringUtils.isEmpty(searchInfo.getName())) {
+			searchInfo.setName(null);
+		}
+		if (StringUtils.isEmpty(searchInfo.getCreator())) {
+			searchInfo.setCreator(null);
+		}
+		if (StringUtils.isEmpty(searchInfo.getCourseNo())) {
+			searchInfo.setCourseNo(null);
+		}
+	}
+
+	public void formatPaperStruct(PaperStruct paperStruct) {
+		paperStruct.setCreateTime(null);
+	}
+
+	/**
+	 * 保存试卷结构
+	 *
+	 * @param paperStruct
+	 * @return
+	 */
+	public PaperStruct save(PaperStruct paperStruct, User user) {
+		if (StringUtils.isNotBlank(paperStruct.getCourseNo())) {
+			GetCourseReq req = new GetCourseReq();
+			req.setRootOrgId(Long.valueOf(paperStruct.getOrgId()));
+			req.setCode(paperStruct.getCourseNo());
+			GetCourseResp resp = courseCloudService.getCourse(req);
 			if (resp.getCourseBean() == null) {
-				throw new StatusException("500","课程不存在");
+				throw new StatusException("500", "课程不存在");
 			}
 			paperStruct.setCourseId(resp.getCourseBean().getId());
 		} else {
 			paperStruct.setCourseId(null);
 		}
-        if (StringUtils.isNotBlank(paperStruct.getId())) {
-            PaperStruct oldPaperStruct = Model.of(paperStructRepo.findById(paperStruct.getId()));
-            PaperStruct rps = null;
-            if (oldPaperStruct != null && !paperStruct.getName().equals(oldPaperStruct.getName())) {// 那么就是更新操作
-                rps = this.checkNameUnique(paperStruct.getName(), user.getRootOrgId().toString(), oldPaperStruct.getType());
-            }
-            if (rps != null) {
-                return null;
-            }
-        }
-        List<PaperDetailStruct> paperDetailStructs = paperStruct.getPaperDetailStructs();
-        int number = 0;
-        //新增精确试卷结构
-        if (paperStruct.getType().equals("EXACT")) {
-            for (PaperDetailStruct paperDetailStruct : paperDetailStructs) {
-                List<PaperDetailUnitStruct> oldStructs = paperDetailStruct.getPaperDetailUnitStructs();
-                if (oldStructs != null && oldStructs.size() > 0) {
-                    oldStructs.clear();
-                }
-                List<PaperDetailUnitStruct> unitStructs = new ArrayList<>();
-                for (PaperDetailUnitStructDto unitStructDto : paperDetailStruct.getUnitStructs()) {
-                    //公开简单总数
-                    for (int i = 0; i < unitStructDto.getPublicSimple(); i++) {
-                        ++number;
-                        PaperDetailUnitStruct unitStruct = new PaperDetailUnitStruct();
-                        unitStruct.setDifficulty("易");
-                        unitStruct.setPublicity(true);
-                        unitStruct.setId(String.valueOf(number));
-                        unitStruct.setNumber(number);
-                        unitStruct.setScore(unitStructDto.getScore());
-                        unitStruct.setQuestionType(unitStructDto.getQuestionType());
-                        unitStruct.setQuesNames(unitStructDto.getQuesNames());
-                        unitStruct.setPropertyGroup(buildGroup(unitStruct));
-                        unitStructs.add(unitStruct);
-                    }
-                    //公开中等总数
-                    for (int i = 0; i < unitStructDto.getPublicMedium(); i++) {
-                        ++number;
-                        PaperDetailUnitStruct unitStruct = new PaperDetailUnitStruct();
-                        unitStruct.setDifficulty("中");
-                        unitStruct.setPublicity(true);
-                        unitStruct.setId(String.valueOf(number));
-                        unitStruct.setNumber(number);
-                        unitStruct.setScore(unitStructDto.getScore());
-                        unitStruct.setQuestionType(unitStructDto.getQuestionType());
-                        unitStruct.setQuesNames(unitStructDto.getQuesNames());
-                        unitStruct.setPropertyGroup(buildGroup(unitStruct));
-                        unitStructs.add(unitStruct);
-                    }
-                    //公开困难总数
-                    for (int i = 0; i < unitStructDto.getPublicDifficulty(); i++) {
-                        ++number;
-                        PaperDetailUnitStruct unitStruct = new PaperDetailUnitStruct();
-                        unitStruct.setDifficulty("难");
-                        unitStruct.setPublicity(true);
-                        unitStruct.setId(String.valueOf(number));
-                        unitStruct.setNumber(number);
-                        unitStruct.setScore(unitStructDto.getScore());
-                        unitStruct.setQuestionType(unitStructDto.getQuestionType());
-                        unitStruct.setQuesNames(unitStructDto.getQuesNames());
-                        unitStruct.setPropertyGroup(buildGroup(unitStruct));
-                        unitStructs.add(unitStruct);
-                    }
-                    //非公开简单总数
-                    for (int i = 0; i < unitStructDto.getNoPublicSimple(); i++) {
-                        ++number;
-                        PaperDetailUnitStruct unitStruct = new PaperDetailUnitStruct();
-                        unitStruct.setDifficulty("易");
-                        unitStruct.setPublicity(false);
-                        unitStruct.setId(String.valueOf(number));
-                        unitStruct.setNumber(number);
-                        unitStruct.setScore(unitStructDto.getScore());
-                        unitStruct.setQuestionType(unitStructDto.getQuestionType());
-                        unitStruct.setQuesNames(unitStructDto.getQuesNames());
-                        unitStruct.setPropertyGroup(buildGroup(unitStruct));
-                        unitStructs.add(unitStruct);
-                    }
-                    //非公开中等总数
-                    for (int i = 0; i < unitStructDto.getNoPublicMedium(); i++) {
-                        ++number;
-                        PaperDetailUnitStruct unitStruct = new PaperDetailUnitStruct();
-                        unitStruct.setDifficulty("中");
-                        unitStruct.setPublicity(false);
-                        unitStruct.setId(String.valueOf(number));
-                        unitStruct.setNumber(number);
-                        unitStruct.setScore(unitStructDto.getScore());
-                        unitStruct.setQuestionType(unitStructDto.getQuestionType());
-                        unitStruct.setQuesNames(unitStructDto.getQuesNames());
-                        unitStruct.setPropertyGroup(buildGroup(unitStruct));
-                        unitStructs.add(unitStruct);
-                    }
-                    //非公开困难总数
-                    for (int i = 0; i < unitStructDto.getNoPublicDifficulty(); i++) {
-                        ++number;
-                        PaperDetailUnitStruct unitStruct = new PaperDetailUnitStruct();
-                        unitStruct.setDifficulty("难");
-                        unitStruct.setPublicity(false);
-                        unitStruct.setId(String.valueOf(number));
-                        unitStruct.setNumber(number);
-                        unitStruct.setScore(unitStructDto.getScore());
-                        unitStruct.setQuestionType(unitStructDto.getQuestionType());
-                        unitStruct.setQuesNames(unitStructDto.getQuesNames());
-                        unitStruct.setPropertyGroup(buildGroup(unitStruct));
-                        unitStructs.add(unitStruct);
-                    }
-                }
-                paperDetailStruct.setPaperDetailUnitStructs(unitStructs);
-            }
-            paperStruct.setPaperStrucType(PaperStructType.EXACT);
-            paperStruct.setDetailUnitCount(paperDetailStructs.stream().mapToInt(PaperDetailStruct::getDetailCount).sum());
-        } else {
-            //新增蓝图试卷结构
-            for (PaperDetailStruct paperDetailStruct : paperDetailStructs) {
-                List<PaperDetailUnitStruct> oldStructs = paperDetailStruct.getPaperDetailUnitStructs();
-                if (oldStructs != null && oldStructs.size() > 0) {
-                    oldStructs.clear();
-                }
-                List<PaperDetailUnitStruct> unitStructs = new ArrayList<>();
-                for (CoursePropertyNumberDto coursePropertyNumberDto : paperDetailStruct.getCoursePropertyNumberDtos()) {
-                    //取到子节点上的题目
-                    if (!coursePropertyNumberDto.getDisable()) {
-                        //公开简单数量
-                        for (int i = 0; i < coursePropertyNumberDto.getPublicSimple(); i++) {
-                            ++number;
-                            PaperDetailUnitStruct unitStruct = new PaperDetailUnitStruct(paperDetailStruct, number, coursePropertyNumberDto);
-                            unitStruct.setDifficulty("易");
-                            unitStruct.setPublicity(true);
-                            unitStruct.setPropertyGroup(buildPropertyGroup(unitStruct));
-                            unitStructs.add(unitStruct);
-                        }
-                        //公开中等数量
-                        for (int i = 0; i < coursePropertyNumberDto.getPublicMedium(); i++) {
-                            ++number;
-                            PaperDetailUnitStruct unitStruct = new PaperDetailUnitStruct(paperDetailStruct, number, coursePropertyNumberDto);
-                            unitStruct.setDifficulty("中");
-                            unitStruct.setPublicity(true);
-                            unitStruct.setPropertyGroup(buildPropertyGroup(unitStruct));
-                            unitStructs.add(unitStruct);
-                        }
-                        //公开困难数量
-                        for (int i = 0; i < coursePropertyNumberDto.getPublicDifficulty(); i++) {
-                            ++number;
-                            PaperDetailUnitStruct unitStruct = new PaperDetailUnitStruct(paperDetailStruct, number, coursePropertyNumberDto);
-                            unitStruct.setDifficulty("难");
-                            unitStruct.setPublicity(true);
-                            unitStruct.setPropertyGroup(buildPropertyGroup(unitStruct));
-                            unitStructs.add(unitStruct);
-                        }
-                        //非公开简单数量
-                        for (int i = 0; i < coursePropertyNumberDto.getNoPublicSimple(); i++) {
-                            ++number;
-                            PaperDetailUnitStruct unitStruct = new PaperDetailUnitStruct(paperDetailStruct, number, coursePropertyNumberDto);
-                            unitStruct.setDifficulty("易");
-                            unitStruct.setPublicity(false);
-                            unitStruct.setPropertyGroup(buildPropertyGroup(unitStruct));
-                            unitStructs.add(unitStruct);
-                        }
-                        //非公开中等数量
-                        for (int i = 0; i < coursePropertyNumberDto.getNoPublicMedium(); i++) {
-                            ++number;
-                            PaperDetailUnitStruct unitStruct = new PaperDetailUnitStruct(paperDetailStruct, number, coursePropertyNumberDto);
-                            unitStruct.setDifficulty("中");
-                            unitStruct.setPublicity(false);
-                            unitStruct.setPropertyGroup(buildPropertyGroup(unitStruct));
-                            unitStructs.add(unitStruct);
-                        }
-                        //非公开困难
-                        for (int i = 0; i < coursePropertyNumberDto.getNoPublicDifficulty(); i++) {
-                            ++number;
-                            PaperDetailUnitStruct unitStruct = new PaperDetailUnitStruct(paperDetailStruct, number, coursePropertyNumberDto);
-                            unitStruct.setDifficulty("难");
-                            unitStruct.setPublicity(false);
-                            unitStruct.setPropertyGroup(buildPropertyGroup(unitStruct));
-                            unitStructs.add(unitStruct);
-                        }
-                    }
-                }
-                paperDetailStruct.setPaperDetailUnitStructs(unitStructs);
-            }
-            paperStruct.setPaperStrucType(PaperStructType.BLUEPRINT);
-            //计算试卷结构难度
-            Double difficulty = getDifficulty(paperDetailStructs, paperStruct.getTotalScore());
-            paperStruct.setDifficulty(difficulty);
-        }
-        paperStruct.setOrgId(user.getRootOrgId().toString());
-        paperStruct.setCreator(user.getDisplayName());
-        paperStruct.setCreateTime(CommonUtils.getCurDateTime());
-        paperStruct.setDetailCount(paperDetailStructs.size());
-        PaperStruct ret=paperStructRepo.save(paperStruct);
-        String key=CacheConstants.CACHE_Q_PAPER_STRUCT+paperStruct.getId();
-    	redisClient.delete(key);
-        return ret;
-    }
-
-    /**
-     * 构建精确组建筛选条件
-     *
-     * @param unitStruct
-     * @return
-     */
-    private String buildGroup(PaperDetailUnitStruct unitStruct) {
-        return String.valueOf(unitStruct.getPublicity()) + "-" + unitStruct.getDifficulty();
-    }
-
-    /**
-     * 构建单个属性组(用来筛选题目)
-     *
-     * @param unitStruct
-     */
-    private String buildPropertyGroup(PaperDetailUnitStruct unitStruct) {
-        return unitStruct.getPropertyId() + "-" + String.valueOf(unitStruct.getPublicity()) + "-" + unitStruct.getDifficulty();
-    }
-
-    public Double getDifficulty(List<PaperDetailStruct> paperDetailStructs, Double totalScore) {
-        Double sum = 0.0;
-        if (paperDetailStructs != null && paperDetailStructs.size() > 0) {
-            Integer simpleCount = 0;
-            Integer mediumCount = 0;
-            Integer difficultyCount = 0;
-            for (PaperDetailStruct paperDetailStruct : paperDetailStructs) {
-                simpleCount = paperDetailStruct.getPublicSimpleCount() + paperDetailStruct.getNoPublicSimpleCount();
-                mediumCount = paperDetailStruct.getPublicMediumCount() + paperDetailStruct.getNoPublicMediumCount();
-                difficultyCount = paperDetailStruct.getPublicDifficultyCount() + paperDetailStruct.getNoPublicDifficultyCount();
-                sum = simpleCount * paperDetailStruct.getScore() * 0.8 + mediumCount * paperDetailStruct.getScore() * 0.5 + difficultyCount * paperDetailStruct.getScore() * 0.2 + sum;
-            }
-
-            Double dif = sum / totalScore;
-            BigDecimal b = BigDecimal.valueOf(dif);
-            Double difficulty = b.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
-            return difficulty;
-        }
-        return (double) 0;
-    }
-
-    public PaperStruct checkNameUnique(String name, String orgId, String type) {
-        Query query = new Query();
-        query.addCriteria(Criteria.where("orgId").is(orgId));
-        query.addCriteria(Criteria.where("name").is(name.trim()));
-        query.addCriteria(Criteria.where("type").is(type));
-        PaperStruct paperStruct = this.mongoTemplate.findOne(query, PaperStruct.class);
-        return paperStruct;
-    }
-
-    public List<QuesNameDto> getQuesNameList(String orgId,
-                                             String courseNo,
-                                             QuesStructType quesType) {
-        List<QuesNameDto> quesNameList = new ArrayList<>();
-        List<QuesTypeName> quesTypeNames = new ArrayList<>();
-        if (StringUtils.isEmpty(courseNo)) {
-            quesTypeNames = quesTypeNameRepo.findQuesName(orgId, quesType);
-        } else {
-            quesTypeNames = quesTypeNameRepo.findQuesName(orgId, courseNo, quesType);
-        }
-        quesNameList = quesTypeNames.stream()
-                .map(QuesTypeName::getQuesNames)
-                .flatMap(Collection::stream)
-                .distinct()
-                .map(this::getQuesName)
-                .collect(Collectors.toList());
-        return quesNameList;
-    }
-
-    private QuesNameDto getQuesName(String name) {
-        return new QuesNameDto(name, name);
-    }
-    
-    public PaperStruct getByCache(String id) {
-    	String key=CacheConstants.CACHE_Q_PAPER_STRUCT+id;
-    	PaperStruct ps=redisClient.get(key, PaperStruct.class, cacheTimeOut);
-    	if(ps==null){
-    		ps=Model.of(paperStructRepo.findById(id));
-    		if(ps==null){
-    			throw new StatusException("未找到试卷结构:"+id);
-    		}
-    		redisClient.set(key, ps, cacheTimeOut);
-    	}
-    	return ps;
-    }
+		if (StringUtils.isNotBlank(paperStruct.getId())) {
+			PaperStruct oldPaperStruct = Model.of(paperStructRepo.findById(paperStruct.getId()));
+			PaperStruct rps = null;
+			if (oldPaperStruct != null && !paperStruct.getName().equals(oldPaperStruct.getName())) {// 那么就是更新操作
+				rps = this.checkNameUnique(paperStruct.getName(), user.getRootOrgId().toString(),
+						oldPaperStruct.getType());
+			}
+			if (rps != null) {
+				return null;
+			}
+		}
+		List<PaperDetailStruct> paperDetailStructs = paperStruct.getPaperDetailStructs();
+		int number = 0;
+		// 新增精确试卷结构
+		if (paperStruct.getType().equals("EXACT")) {
+			for (PaperDetailStruct paperDetailStruct : paperDetailStructs) {
+				List<PaperDetailUnitStruct> oldStructs = paperDetailStruct.getPaperDetailUnitStructs();
+				if (oldStructs != null && oldStructs.size() > 0) {
+					oldStructs.clear();
+				}
+				List<PaperDetailUnitStruct> unitStructs = new ArrayList<>();
+				for (PaperDetailUnitStructDto unitStructDto : paperDetailStruct.getUnitStructs()) {
+					// 公开简单总数
+					for (int i = 0; i < unitStructDto.getPublicSimple(); i++) {
+						++number;
+						PaperDetailUnitStruct unitStruct = new PaperDetailUnitStruct();
+						unitStruct.setDifficulty("易");
+						unitStruct.setPublicity(true);
+						unitStruct.setId(String.valueOf(number));
+						unitStruct.setNumber(number);
+						unitStruct.setScore(unitStructDto.getScore());
+						unitStruct.setQuestionType(unitStructDto.getQuestionType());
+						unitStruct.setQuesNames(unitStructDto.getQuesNames());
+						unitStruct.setPropertyGroup(buildGroup(unitStruct));
+						unitStructs.add(unitStruct);
+					}
+					// 公开中等总数
+					for (int i = 0; i < unitStructDto.getPublicMedium(); i++) {
+						++number;
+						PaperDetailUnitStruct unitStruct = new PaperDetailUnitStruct();
+						unitStruct.setDifficulty("中");
+						unitStruct.setPublicity(true);
+						unitStruct.setId(String.valueOf(number));
+						unitStruct.setNumber(number);
+						unitStruct.setScore(unitStructDto.getScore());
+						unitStruct.setQuestionType(unitStructDto.getQuestionType());
+						unitStruct.setQuesNames(unitStructDto.getQuesNames());
+						unitStruct.setPropertyGroup(buildGroup(unitStruct));
+						unitStructs.add(unitStruct);
+					}
+					// 公开困难总数
+					for (int i = 0; i < unitStructDto.getPublicDifficulty(); i++) {
+						++number;
+						PaperDetailUnitStruct unitStruct = new PaperDetailUnitStruct();
+						unitStruct.setDifficulty("难");
+						unitStruct.setPublicity(true);
+						unitStruct.setId(String.valueOf(number));
+						unitStruct.setNumber(number);
+						unitStruct.setScore(unitStructDto.getScore());
+						unitStruct.setQuestionType(unitStructDto.getQuestionType());
+						unitStruct.setQuesNames(unitStructDto.getQuesNames());
+						unitStruct.setPropertyGroup(buildGroup(unitStruct));
+						unitStructs.add(unitStruct);
+					}
+					// 非公开简单总数
+					for (int i = 0; i < unitStructDto.getNoPublicSimple(); i++) {
+						++number;
+						PaperDetailUnitStruct unitStruct = new PaperDetailUnitStruct();
+						unitStruct.setDifficulty("易");
+						unitStruct.setPublicity(false);
+						unitStruct.setId(String.valueOf(number));
+						unitStruct.setNumber(number);
+						unitStruct.setScore(unitStructDto.getScore());
+						unitStruct.setQuestionType(unitStructDto.getQuestionType());
+						unitStruct.setQuesNames(unitStructDto.getQuesNames());
+						unitStruct.setPropertyGroup(buildGroup(unitStruct));
+						unitStructs.add(unitStruct);
+					}
+					// 非公开中等总数
+					for (int i = 0; i < unitStructDto.getNoPublicMedium(); i++) {
+						++number;
+						PaperDetailUnitStruct unitStruct = new PaperDetailUnitStruct();
+						unitStruct.setDifficulty("中");
+						unitStruct.setPublicity(false);
+						unitStruct.setId(String.valueOf(number));
+						unitStruct.setNumber(number);
+						unitStruct.setScore(unitStructDto.getScore());
+						unitStruct.setQuestionType(unitStructDto.getQuestionType());
+						unitStruct.setQuesNames(unitStructDto.getQuesNames());
+						unitStruct.setPropertyGroup(buildGroup(unitStruct));
+						unitStructs.add(unitStruct);
+					}
+					// 非公开困难总数
+					for (int i = 0; i < unitStructDto.getNoPublicDifficulty(); i++) {
+						++number;
+						PaperDetailUnitStruct unitStruct = new PaperDetailUnitStruct();
+						unitStruct.setDifficulty("难");
+						unitStruct.setPublicity(false);
+						unitStruct.setId(String.valueOf(number));
+						unitStruct.setNumber(number);
+						unitStruct.setScore(unitStructDto.getScore());
+						unitStruct.setQuestionType(unitStructDto.getQuestionType());
+						unitStruct.setQuesNames(unitStructDto.getQuesNames());
+						unitStruct.setPropertyGroup(buildGroup(unitStruct));
+						unitStructs.add(unitStruct);
+					}
+				}
+				paperDetailStruct.setPaperDetailUnitStructs(unitStructs);
+			}
+			paperStruct.setPaperStrucType(PaperStructType.EXACT);
+			paperStruct
+					.setDetailUnitCount(paperDetailStructs.stream().mapToInt(PaperDetailStruct::getDetailCount).sum());
+		} else {
+			// 新增蓝图试卷结构
+			for (PaperDetailStruct paperDetailStruct : paperDetailStructs) {
+				List<PaperDetailUnitStruct> oldStructs = paperDetailStruct.getPaperDetailUnitStructs();
+				if (oldStructs != null && oldStructs.size() > 0) {
+					oldStructs.clear();
+				}
+				List<PaperDetailUnitStruct> unitStructs = new ArrayList<>();
+				for (CoursePropertyNumberDto coursePropertyNumberDto : paperDetailStruct
+						.getCoursePropertyNumberDtos()) {
+					// 取到子节点上的题目
+					if (!coursePropertyNumberDto.getDisable()) {
+						// 公开简单数量
+						for (int i = 0; i < coursePropertyNumberDto.getPublicSimple(); i++) {
+							++number;
+							PaperDetailUnitStruct unitStruct = new PaperDetailUnitStruct(paperDetailStruct, number,
+									coursePropertyNumberDto);
+							unitStruct.setDifficulty("易");
+							unitStruct.setPublicity(true);
+							unitStruct.setPropertyGroup(buildPropertyGroup(unitStruct));
+							unitStructs.add(unitStruct);
+						}
+						// 公开中等数量
+						for (int i = 0; i < coursePropertyNumberDto.getPublicMedium(); i++) {
+							++number;
+							PaperDetailUnitStruct unitStruct = new PaperDetailUnitStruct(paperDetailStruct, number,
+									coursePropertyNumberDto);
+							unitStruct.setDifficulty("中");
+							unitStruct.setPublicity(true);
+							unitStruct.setPropertyGroup(buildPropertyGroup(unitStruct));
+							unitStructs.add(unitStruct);
+						}
+						// 公开困难数量
+						for (int i = 0; i < coursePropertyNumberDto.getPublicDifficulty(); i++) {
+							++number;
+							PaperDetailUnitStruct unitStruct = new PaperDetailUnitStruct(paperDetailStruct, number,
+									coursePropertyNumberDto);
+							unitStruct.setDifficulty("难");
+							unitStruct.setPublicity(true);
+							unitStruct.setPropertyGroup(buildPropertyGroup(unitStruct));
+							unitStructs.add(unitStruct);
+						}
+						// 非公开简单数量
+						for (int i = 0; i < coursePropertyNumberDto.getNoPublicSimple(); i++) {
+							++number;
+							PaperDetailUnitStruct unitStruct = new PaperDetailUnitStruct(paperDetailStruct, number,
+									coursePropertyNumberDto);
+							unitStruct.setDifficulty("易");
+							unitStruct.setPublicity(false);
+							unitStruct.setPropertyGroup(buildPropertyGroup(unitStruct));
+							unitStructs.add(unitStruct);
+						}
+						// 非公开中等数量
+						for (int i = 0; i < coursePropertyNumberDto.getNoPublicMedium(); i++) {
+							++number;
+							PaperDetailUnitStruct unitStruct = new PaperDetailUnitStruct(paperDetailStruct, number,
+									coursePropertyNumberDto);
+							unitStruct.setDifficulty("中");
+							unitStruct.setPublicity(false);
+							unitStruct.setPropertyGroup(buildPropertyGroup(unitStruct));
+							unitStructs.add(unitStruct);
+						}
+						// 非公开困难
+						for (int i = 0; i < coursePropertyNumberDto.getNoPublicDifficulty(); i++) {
+							++number;
+							PaperDetailUnitStruct unitStruct = new PaperDetailUnitStruct(paperDetailStruct, number,
+									coursePropertyNumberDto);
+							unitStruct.setDifficulty("难");
+							unitStruct.setPublicity(false);
+							unitStruct.setPropertyGroup(buildPropertyGroup(unitStruct));
+							unitStructs.add(unitStruct);
+						}
+					}
+				}
+				paperDetailStruct.setPaperDetailUnitStructs(unitStructs);
+			}
+			paperStruct.setPaperStrucType(PaperStructType.BLUEPRINT);
+			// 计算试卷结构难度
+			Double difficulty = getDifficulty(paperDetailStructs, paperStruct.getTotalScore());
+			paperStruct.setDifficulty(difficulty);
+		}
+		paperStruct.setOrgId(user.getRootOrgId().toString());
+		paperStruct.setCreator(user.getDisplayName());
+		paperStruct.setCreateTime(CommonUtils.getCurDateTime());
+		paperStruct.setDetailCount(paperDetailStructs.size());
+		PaperStruct ret = paperStructRepo.save(paperStruct);
+		String key = CacheConstants.CACHE_Q_PAPER_STRUCT + paperStruct.getId();
+		redisClient.delete(key);
+		return ret;
+	}
+
+	/**
+	 * 构建精确组建筛选条件
+	 *
+	 * @param unitStruct
+	 * @return
+	 */
+	private String buildGroup(PaperDetailUnitStruct unitStruct) {
+		return String.valueOf(unitStruct.getPublicity()) + "-" + unitStruct.getDifficulty();
+	}
+
+	/**
+	 * 构建单个属性组(用来筛选题目)
+	 *
+	 * @param unitStruct
+	 */
+	private String buildPropertyGroup(PaperDetailUnitStruct unitStruct) {
+		return unitStruct.getPropertyId() + "-" + String.valueOf(unitStruct.getPublicity()) + "-"
+				+ unitStruct.getDifficulty();
+	}
+
+	public Double getDifficulty(List<PaperDetailStruct> paperDetailStructs, Double totalScore) {
+		Double sum = 0.0;
+		if (paperDetailStructs != null && paperDetailStructs.size() > 0) {
+			Integer simpleCount = 0;
+			Integer mediumCount = 0;
+			Integer difficultyCount = 0;
+			for (PaperDetailStruct paperDetailStruct : paperDetailStructs) {
+				simpleCount = paperDetailStruct.getPublicSimpleCount() + paperDetailStruct.getNoPublicSimpleCount();
+				mediumCount = paperDetailStruct.getPublicMediumCount() + paperDetailStruct.getNoPublicMediumCount();
+				difficultyCount = paperDetailStruct.getPublicDifficultyCount()
+						+ paperDetailStruct.getNoPublicDifficultyCount();
+				sum = simpleCount * paperDetailStruct.getScore() * 0.8
+						+ mediumCount * paperDetailStruct.getScore() * 0.5
+						+ difficultyCount * paperDetailStruct.getScore() * 0.2 + sum;
+			}
+
+			Double dif = sum / totalScore;
+			BigDecimal b = BigDecimal.valueOf(dif);
+			Double difficulty = b.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
+			return difficulty;
+		}
+		return (double) 0;
+	}
+
+	public PaperStruct checkNameUnique(String name, String orgId, String type) {
+		Query query = new Query();
+		query.addCriteria(Criteria.where("orgId").is(orgId));
+		query.addCriteria(Criteria.where("name").is(name.trim()));
+		query.addCriteria(Criteria.where("type").is(type));
+		PaperStruct paperStruct = this.mongoTemplate.findOne(query, PaperStruct.class);
+		return paperStruct;
+	}
+
+	public List<QuesNameDto> getQuesNameList(String orgId, String courseNo, QuesStructType quesType) {
+		List<QuesNameDto> quesNameList = new ArrayList<>();
+		List<QuesTypeName> quesTypeNames = new ArrayList<>();
+		if (StringUtils.isEmpty(courseNo)) {
+			quesTypeNames = quesTypeNameRepo.findQuesName(orgId, quesType);
+		} else {
+			quesTypeNames = quesTypeNameRepo.findQuesName(orgId, courseNo, quesType);
+		}
+		quesNameList = quesTypeNames.stream().map(QuesTypeName::getQuesNames).flatMap(Collection::stream).distinct()
+				.map(this::getQuesName).collect(Collectors.toList());
+		return quesNameList;
+	}
+
+	private QuesNameDto getQuesName(String name) {
+		return new QuesNameDto(name, name);
+	}
+
+	public PaperStruct getByCache(String id) {
+		String key = CacheConstants.CACHE_Q_PAPER_STRUCT + id;
+		PaperStruct ps = redisClient.get(key, PaperStruct.class, cacheTimeOut);
+		if (ps == null) {
+			ps = Model.of(paperStructRepo.findById(id));
+			if (ps == null) {
+				throw new StatusException("未找到试卷结构:" + id);
+			}
+			redisClient.set(key, ps, cacheTimeOut);
+		}
+		return ps;
+	}
 
 	public void removePaperStruct(List<String> ids) {
-		for(String id:ids) {
+		for (String id : ids) {
+			if (randomPaperService.existStruct(id)) {
+				PaperStruct ps = Model.of(paperStructRepo.findById(id));
+				throw new StatusException(ps.getName()+"已被抽题模板使用,不能删除");
+			}
 			paperStructRepo.deleteById(id);
-			String key=CacheConstants.CACHE_Q_PAPER_STRUCT+id;
-	    	redisClient.delete(key);
+			String key = CacheConstants.CACHE_Q_PAPER_STRUCT + id;
+			redisClient.delete(key);
 		}
 	}
 

+ 2 - 0
examcloud-core-questions-service/src/main/java/cn/com/qmth/examcloud/core/questions/service/RandomPaperQuestionService.java

@@ -2,5 +2,7 @@ package cn.com.qmth.examcloud.core.questions.service;
 
 public interface RandomPaperQuestionService {
 
+	boolean existQuestion(String questionId);
+
 
 }

+ 2 - 0
examcloud-core-questions-service/src/main/java/cn/com/qmth/examcloud/core/questions/service/RandomPaperService.java

@@ -26,5 +26,7 @@ public interface RandomPaperService {
 
 	DefaultPaper getRandomPaper(String randomPaperId, Integer playTime);
 
+	boolean existStruct(String id);
+
 
 }

+ 2256 - 2209
examcloud-core-questions-service/src/main/java/cn/com/qmth/examcloud/core/questions/service/impl/PaperServiceImpl.java

@@ -96,6 +96,7 @@ import cn.com.qmth.examcloud.core.questions.service.PaperDetailService;
 import cn.com.qmth.examcloud.core.questions.service.PaperDetailUnitService;
 import cn.com.qmth.examcloud.core.questions.service.PaperService;
 import cn.com.qmth.examcloud.core.questions.service.QuesService;
+import cn.com.qmth.examcloud.core.questions.service.RandomPaperQuestionService;
 import cn.com.qmth.examcloud.core.questions.service.bean.PaperId;
 import cn.com.qmth.examcloud.core.questions.service.bean.dto.DownloadPaperDto;
 import cn.com.qmth.examcloud.core.questions.service.bean.dto.ObjectiveQuestionStructure;
@@ -129,278 +130,275 @@ import cn.com.qmth.examcloud.web.support.SpringContextHolder;
 @Service("paperService")
 public class PaperServiceImpl implements PaperService {
 
-    private static final Logger LOG = LoggerFactory.getLogger(PaperServiceImpl.class);
+	private static final Logger LOG = LoggerFactory.getLogger(PaperServiceImpl.class);
 	@Autowired
 	private PropertyRepo propertyRepo;
-    @Autowired
-    PaperRepo paperRepo;
-
-    @Autowired
-    PaperDetailService paperDetailService;
-
-    @Autowired
-    ExamPaperRepo examPaperRepo;
+	@Autowired
+	PaperRepo paperRepo;
 
-    @Autowired
-    PaperDetailRepo paperDetailRepo;
+	@Autowired
+	PaperDetailService paperDetailService;
 
-    @Autowired
-    PaperDetailUnitRepo paperDetailUnitRepo;
+	@Autowired
+	ExamPaperRepo examPaperRepo;
 
-    @Autowired
-    QuesRepo quesRepo;
+	@Autowired
+	PaperDetailRepo paperDetailRepo;
 
-    @Autowired
-    QuesBakRepo quesBakRepo;
+	@Autowired
+	PaperDetailUnitRepo paperDetailUnitRepo;
 
-    @Autowired
-    Gson gson;
+	@Autowired
+	QuesRepo quesRepo;
 
-    @Autowired
-    PaperDetailUnitService paperDetailUnitService;
+	@Autowired
+	QuesBakRepo quesBakRepo;
 
-    @Autowired
-    QuesService quesService;
+	@Autowired
+	Gson gson;
 
-    @Autowired
-    ExtractConfigService extractConfigService;
+	@Autowired
+	PaperDetailUnitService paperDetailUnitService;
 
-    @Autowired
-    private MongoTemplate mongoTemplate;
+	@Autowired
+	QuesService quesService;
 
-    @Autowired
-    private QuestionAudioServiceImpl questionAudioService;
+	@Autowired
+	ExtractConfigService extractConfigService;
 
-    @Autowired
-    private SysProperty sysProperty;
+	@Autowired
+	private MongoTemplate mongoTemplate;
 
-    @Autowired
-    private CoursePaperCloudService coursePaperCloudService;
+	@Autowired
+	private QuestionAudioServiceImpl questionAudioService;
 
-    @Autowired
-    private CourseService courseService;
+	@Autowired
+	private SysProperty sysProperty;
 
-    @Autowired
-    private ExtractConfigPaperCache extractConfigPaperCache;
+	@Autowired
+	private CoursePaperCloudService coursePaperCloudService;
 
-    @Autowired
-    private BasePaperCache basePaperCache;
+	@Autowired
+	private CourseService courseService;
 
-    @Autowired
-    private QuestionCache questionCache;
+	@Autowired
+	private ExtractConfigPaperCache extractConfigPaperCache;
 
-    @Autowired
-    private QuestionAnswerCache questionAnswerCache;
+	@Autowired
+	private BasePaperCache basePaperCache;
+	@Autowired
+	private RandomPaperQuestionService randomPaperQuestionService;
+	
+	@Autowired
+	private QuestionCache questionCache;
 
-    @Autowired
-    private SystemProperties systemProperties;
+	@Autowired
+	private QuestionAnswerCache questionAnswerCache;
 
-    private Random random = new Random();
+	@Autowired
+	private SystemProperties systemProperties;
 
-    public static final String TEMP_FILE_EXP = "docxExport/";
+	private Random random = new Random();
 
+	public static final String TEMP_FILE_EXP = "docxExport/";
 
-    /**
-     * 查询所有已导入试卷
-     */
-    @Override
-    public Page<Paper> getImportPapers(PaperSearchInfo paperSearchInfo, int curPage, int pageSize, UserDataRule ud) {
-    	
+	/**
+	 * 查询所有已导入试卷
+	 */
+	@Override
+	public Page<Paper> getImportPapers(PaperSearchInfo paperSearchInfo, int curPage, int pageSize, UserDataRule ud) {
 
-    	if (ud.assertEmptyQueryResult()) {
+		if (ud.assertEmptyQueryResult()) {
 			return Page.empty();
 		}
 		Query query = new Query();
-		
+
 		query.addCriteria(Criteria.where("orgId").is(paperSearchInfo.getOrgId()));
-		
+
 		if (ud.assertNeedQueryRefIds()) {
 			query.addCriteria(Criteria.where("course.id").in(ud.stringRefIds()));
 		}
-        
 
-       
+		query.addCriteria(Criteria.where("paperType").is(PaperType.IMPORT));
 
-        query.addCriteria(Criteria.where("paperType").is(PaperType.IMPORT));
+		query.addCriteria(Criteria.where("course.enable").is("true"));
 
-        query.addCriteria(Criteria.where("course.enable").is("true"));
+		if (StringUtils.isNotBlank(paperSearchInfo.getCourseNo())) {
+			query.addCriteria(Criteria.where("course.code").is(paperSearchInfo.getCourseNo()));
+		}
 
-        if (StringUtils.isNotBlank(paperSearchInfo.getCourseNo())) {
-            query.addCriteria(Criteria.where("course.code").is(paperSearchInfo.getCourseNo()));
-        }
+		if (StringUtils.isNotBlank(paperSearchInfo.getLevel())) {
+			query.addCriteria(Criteria.where("course.level").is(paperSearchInfo.getLevel()));
+		}
 
-        if (StringUtils.isNotBlank(paperSearchInfo.getLevel())) {
-            query.addCriteria(Criteria.where("course.level").is(paperSearchInfo.getLevel()));
-        }
+		if (StringUtils.isNoneBlank(paperSearchInfo.getName())) {
+			String paperName = CommonUtils.escapeExprSpecialWord(paperSearchInfo.getName());
+			query.addCriteria(Criteria.where("name").regex(".*?\\.*" + paperName + ".*"));
+		}
 
-        if (StringUtils.isNoneBlank(paperSearchInfo.getName())) {
-            String paperName = CommonUtils.escapeExprSpecialWord(paperSearchInfo.getName());
-            query.addCriteria(Criteria.where("name").regex(".*?\\.*" + paperName + ".*"));
-        }
+		if (StringUtils.isNoneBlank(paperSearchInfo.getCreator())) {
+			String creator = CommonUtils.escapeExprSpecialWord(paperSearchInfo.getCreator());
+			query.addCriteria(Criteria.where("creator").regex(".*?\\.*" + creator + ".*"));
+		}
 
-        if (StringUtils.isNoneBlank(paperSearchInfo.getCreator())) {
-            String creator = CommonUtils.escapeExprSpecialWord(paperSearchInfo.getCreator());
-            query.addCriteria(Criteria.where("creator").regex(".*?\\.*" + creator + ".*"));
-        }
+		if (StringUtils.isNoneBlank(paperSearchInfo.getLastModifyName())) {
+			String lastModifyName = CommonUtils.escapeExprSpecialWord(paperSearchInfo.getLastModifyName());
+			query.addCriteria(Criteria.where("lastModifyName").regex(".*?\\.*" + lastModifyName + ".*"));
+		}
 
-        if (StringUtils.isNoneBlank(paperSearchInfo.getLastModifyName())) {
-            String lastModifyName = CommonUtils.escapeExprSpecialWord(paperSearchInfo.getLastModifyName());
-            query.addCriteria(Criteria.where("lastModifyName").regex(".*?\\.*" + lastModifyName + ".*"));
-        }
+		if (StringUtils.isNotBlank(paperSearchInfo.getSpecialtyNo())) {
+			query.addCriteria(Criteria.where("specialty.code").is(paperSearchInfo.getSpecialtyNo()));
+		}
 
-        if (StringUtils.isNotBlank(paperSearchInfo.getSpecialtyNo())) {
-            query.addCriteria(Criteria.where("specialty.code").is(paperSearchInfo.getSpecialtyNo()));
-        }
+		long total = this.mongoTemplate.count(query, Paper.class);
+		if (total == 0) {
+			return Page.empty();
+		}
 
-        long total = this.mongoTemplate.count(query, Paper.class);
-        if (total == 0) {
-            return Page.empty();
-        }
+		PageRequest pageable = PageRequest.of(curPage - 1, pageSize);
+		query.with(Sort.by(Sort.Order.desc("createTime")));
+		query.skip(pageable.getOffset());
+		query.limit(pageable.getPageSize());
 
-        PageRequest pageable = PageRequest.of(curPage - 1, pageSize);
-        query.with(Sort.by(Sort.Order.desc("createTime")));
-        query.skip(pageable.getOffset());
-        query.limit(pageable.getPageSize());
+		List<Paper> paperList = this.mongoTemplate.find(query, Paper.class);
+		if (CollectionUtils.isEmpty(paperList)) {
+			return Page.empty();
+		}
 
-        List<Paper> paperList = this.mongoTemplate.find(query, Paper.class);
-        if (CollectionUtils.isEmpty(paperList)) {
-            return Page.empty();
-        }
+		return new PageImpl<>(paperList, pageable, total);
+	}
 
-        return new PageImpl<>(paperList, pageable, total);
-    }
-
-    /**
-     * 查询所有待审核和审核不通过的导入试卷
-     *
-     * @param paperSearchInfo
-     * @param curPage
-     * @param pageSize
-     * @return
-     */
-    public Page<Paper> getImportPapersNotSuccess(PaperSearchInfo paperSearchInfo, int curPage, int pageSize) {
-        Query query = new Query();
-        query.addCriteria(Criteria.where("orgId").is(paperSearchInfo.getOrgId()));
-        query.addCriteria(Criteria.where("paperType").is(PaperType.IMPORT));
-        query.addCriteria(Criteria.where("course.enable").is("true"));
-        if (paperSearchInfo.getPaperStatus() != null) {
-            query.addCriteria(Criteria.where("paperStatus").is(paperSearchInfo.getPaperStatus()));
-        } else {
-            query.addCriteria(Criteria.where("paperStatus").ne(PaperStatus.PASS));
-        }
-        if (StringUtil.isNotBlank(paperSearchInfo.getCourseNo())) {
-            query.addCriteria(Criteria.where("course.code").is(paperSearchInfo.getCourseNo()));
-        }
-        long total = this.mongoTemplate.count(query, Paper.class);
-        if (total == 0) {
-            return Page.empty();
-        }
+	/**
+	 * 查询所有待审核和审核不通过的导入试卷
+	 *
+	 * @param paperSearchInfo
+	 * @param curPage
+	 * @param pageSize
+	 * @return
+	 */
+	public Page<Paper> getImportPapersNotSuccess(PaperSearchInfo paperSearchInfo, int curPage, int pageSize) {
+		Query query = new Query();
+		query.addCriteria(Criteria.where("orgId").is(paperSearchInfo.getOrgId()));
+		query.addCriteria(Criteria.where("paperType").is(PaperType.IMPORT));
+		query.addCriteria(Criteria.where("course.enable").is("true"));
+		if (paperSearchInfo.getPaperStatus() != null) {
+			query.addCriteria(Criteria.where("paperStatus").is(paperSearchInfo.getPaperStatus()));
+		} else {
+			query.addCriteria(Criteria.where("paperStatus").ne(PaperStatus.PASS));
+		}
+		if (StringUtil.isNotBlank(paperSearchInfo.getCourseNo())) {
+			query.addCriteria(Criteria.where("course.code").is(paperSearchInfo.getCourseNo()));
+		}
+		long total = this.mongoTemplate.count(query, Paper.class);
+		if (total == 0) {
+			return Page.empty();
+		}
 
-        query.limit(pageSize);
-        query.skip((curPage - 1L) * pageSize);
-        List<Paper> paperList = this.mongoTemplate.find(query, Paper.class);
-        return new PageImpl<Paper>(paperList, PageRequest.of(curPage - 1, pageSize), total);
-    }
-
-    /**
-     * 根据条件查询
-     *
-     * @param paperSearchInfo
-     * @return
-     */
-    public List<Paper> getImportPapersBySearch(PaperSearchInfo paperSearchInfo) {
-        Query query = new Query();
-        query.addCriteria(Criteria.where("orgId").is(paperSearchInfo.getOrgId()));
-        query.addCriteria(Criteria.where("paperType").is(PaperType.IMPORT.name()));
-        query.addCriteria(Criteria.where("course.enable").is("true"));
-        if (StringUtils.isNotBlank(paperSearchInfo.getCourseNo())) {
-            query.addCriteria(Criteria.where("course.code").is(paperSearchInfo.getCourseNo()));
-        }
-        if (StringUtils.isNotBlank(paperSearchInfo.getLevel())) {
-            query.addCriteria(Criteria.where("course.level").is(paperSearchInfo.getLevel()));
-        }
-        List<Paper> paperList = this.mongoTemplate.find(query, Paper.class);
-        return paperList;
-    }
-
-    /**
-     * 根据条件查询
-     *
-     * @param paperSearchInfo
-     * @return
-     */
-    public List<Paper> getGenPapersBySearch(PaperSearchInfo paperSearchInfo) {
-        Query query = new Query();
-        query.addCriteria(Criteria.where("orgId").is(paperSearchInfo.getOrgId()));
-        query.addCriteria(Criteria.where("paperType").is(PaperType.GENERATE.name()));
-        query.addCriteria(Criteria.where("course.enable").is("true"));
-        query.addCriteria(Criteria.where("storage").ne(1));
-        if (StringUtils.isNotBlank(paperSearchInfo.getCourseNo())) {
-            query.addCriteria(Criteria.where("course.code").is(paperSearchInfo.getCourseNo()));
-        }
+		query.limit(pageSize);
+		query.skip((curPage - 1L) * pageSize);
+		List<Paper> paperList = this.mongoTemplate.find(query, Paper.class);
+		return new PageImpl<Paper>(paperList, PageRequest.of(curPage - 1, pageSize), total);
+	}
 
-        if (StringUtils.isNotBlank(paperSearchInfo.getLevel())) {
-            query.addCriteria(Criteria.where("course.level").is(paperSearchInfo.getLevel()));
-        }
+	/**
+	 * 根据条件查询
+	 *
+	 * @param paperSearchInfo
+	 * @return
+	 */
+	public List<Paper> getImportPapersBySearch(PaperSearchInfo paperSearchInfo) {
+		Query query = new Query();
+		query.addCriteria(Criteria.where("orgId").is(paperSearchInfo.getOrgId()));
+		query.addCriteria(Criteria.where("paperType").is(PaperType.IMPORT.name()));
+		query.addCriteria(Criteria.where("course.enable").is("true"));
+		if (StringUtils.isNotBlank(paperSearchInfo.getCourseNo())) {
+			query.addCriteria(Criteria.where("course.code").is(paperSearchInfo.getCourseNo()));
+		}
+		if (StringUtils.isNotBlank(paperSearchInfo.getLevel())) {
+			query.addCriteria(Criteria.where("course.level").is(paperSearchInfo.getLevel()));
+		}
+		List<Paper> paperList = this.mongoTemplate.find(query, Paper.class);
+		return paperList;
+	}
 
-        query.with(Sort.by(Sort.Direction.DESC, "createTime"));
-
-        List<Paper> paperList = this.mongoTemplate.find(query, Paper.class);
-        return paperList;
-    }
-
-    /**
-     * 保存试卷
-     *
-     * @param paperExp
-     * @return
-     */
-    public Map<String, Object> savePaper(PaperExp paperExp, User user) {
-        Map<String, Object> msgMap = new HashMap<>();
-
-        Paper oldPaper = Model.of(paperRepo.findById(paperExp.getId()));
-        if (oldPaper != null) {
-        	if (PaperType.GENERATE.equals(oldPaper.getPaperType())) {
-        		oldPaper.setAuditStatus(false);
-            }
-            String oldName = oldPaper.getName().trim();
-            oldPaper.setTitle(paperExp.getTitle());
-            oldPaper.setName(paperExp.getName().trim());
-            oldPaper.setLastModifyName(user.getDisplayName());
-            oldPaper.setExamRemark(paperExp.getExamRemark());
-            if (!oldName.equals(paperExp.getName().trim())) {// 假如改变了试卷名称
-                // 则要效验试卷名称唯一性
-                boolean existName = this.checkPaperName(paperExp.getName().trim(), user.getRootOrgId().toString());
-                if (existName) {
-                    msgMap.put("msg", "试卷名称重复,请重新命名!");
-                } else {
-                    formatPaper(oldPaper, user);
-                    paperRepo.save(oldPaper);
-                    msgMap.put("msg", "success");
-                }
-            } else {
-                formatPaper(oldPaper, user);
-                paperRepo.save(oldPaper);
-                msgMap.put("msg", "success");
-            }
-        }
+	/**
+	 * 根据条件查询
+	 *
+	 * @param paperSearchInfo
+	 * @return
+	 */
+	public List<Paper> getGenPapersBySearch(PaperSearchInfo paperSearchInfo) {
+		Query query = new Query();
+		query.addCriteria(Criteria.where("orgId").is(paperSearchInfo.getOrgId()));
+		query.addCriteria(Criteria.where("paperType").is(PaperType.GENERATE.name()));
+		query.addCriteria(Criteria.where("course.enable").is("true"));
+		query.addCriteria(Criteria.where("storage").ne(1));
+		if (StringUtils.isNotBlank(paperSearchInfo.getCourseNo())) {
+			query.addCriteria(Criteria.where("course.code").is(paperSearchInfo.getCourseNo()));
+		}
+
+		if (StringUtils.isNotBlank(paperSearchInfo.getLevel())) {
+			query.addCriteria(Criteria.where("course.level").is(paperSearchInfo.getLevel()));
+		}
 
-        //清除缓存
-        this.clearPaperCache(paperExp.getId());
-
-        return msgMap;
-    }
-
-    /**
-     * 查询所有已组试卷
-     *
-     * @param paperSearchInfo
-     * @param curPage
-     * @param pageSize
-     * @return
-     */
-    public Page<Paper> getGenPapers(PaperSearchInfo paperSearchInfo, int curPage, int pageSize,UserDataRule ud) {
-    	if (ud.assertEmptyQueryResult()) {
+		query.with(Sort.by(Sort.Direction.DESC, "createTime"));
+
+		List<Paper> paperList = this.mongoTemplate.find(query, Paper.class);
+		return paperList;
+	}
+
+	/**
+	 * 保存试卷
+	 *
+	 * @param paperExp
+	 * @return
+	 */
+	public Map<String, Object> savePaper(PaperExp paperExp, User user) {
+		Map<String, Object> msgMap = new HashMap<>();
+
+		Paper oldPaper = Model.of(paperRepo.findById(paperExp.getId()));
+		if (oldPaper != null) {
+			if (PaperType.GENERATE.equals(oldPaper.getPaperType())) {
+				oldPaper.setAuditStatus(false);
+			}
+			String oldName = oldPaper.getName().trim();
+			oldPaper.setTitle(paperExp.getTitle());
+			oldPaper.setName(paperExp.getName().trim());
+			oldPaper.setLastModifyName(user.getDisplayName());
+			oldPaper.setExamRemark(paperExp.getExamRemark());
+			if (!oldName.equals(paperExp.getName().trim())) {// 假如改变了试卷名称
+				// 则要效验试卷名称唯一性
+				boolean existName = this.checkPaperName(paperExp.getName().trim(), user.getRootOrgId().toString());
+				if (existName) {
+					msgMap.put("msg", "试卷名称重复,请重新命名!");
+				} else {
+					formatPaper(oldPaper, user);
+					paperRepo.save(oldPaper);
+					msgMap.put("msg", "success");
+				}
+			} else {
+				formatPaper(oldPaper, user);
+				paperRepo.save(oldPaper);
+				msgMap.put("msg", "success");
+			}
+		}
+
+		// 清除缓存
+		this.clearPaperCache(paperExp.getId());
+
+		return msgMap;
+	}
+
+	/**
+	 * 查询所有已组试卷
+	 *
+	 * @param paperSearchInfo
+	 * @param curPage
+	 * @param pageSize
+	 * @return
+	 */
+	public Page<Paper> getGenPapers(PaperSearchInfo paperSearchInfo, int curPage, int pageSize, UserDataRule ud) {
+		if (ud.assertEmptyQueryResult()) {
 			return Page.empty();
 		}
 		Query query = new Query();
@@ -408,210 +406,211 @@ public class PaperServiceImpl implements PaperService {
 		if (ud.assertNeedQueryRefIds()) {
 			query.addCriteria(Criteria.where("course.id").in(ud.stringRefIds()));
 		}
-		if(paperSearchInfo.getAuditStatus()!=null) {
-			if(paperSearchInfo.getAuditStatus()) {
+		if (paperSearchInfo.getAuditStatus() != null) {
+			if (paperSearchInfo.getAuditStatus()) {
 				query.addCriteria(Criteria.where("auditStatus").ne(false));
-			}else {
+			} else {
 				query.addCriteria(Criteria.where("auditStatus").is(false));
 			}
 		}
-        query.addCriteria(Criteria.where("paperType").is(PaperType.GENERATE.name()));
-        query.addCriteria(Criteria.where("storage").ne(1));
-        query.addCriteria(Criteria.where("course.enable").is("true"));
-        if (paperSearchInfo.getInUse()!=null) {
-        	if(paperSearchInfo.getInUse()==0) {
-        		query.addCriteria(Criteria.where("inUse").ne(1));
-        	}else if(paperSearchInfo.getInUse()==1) {
-        		query.addCriteria(Criteria.where("inUse").is(1));
-        	}
-        }
-        if (StringUtils.isNotBlank(paperSearchInfo.getCourseNo())) {
-            query.addCriteria(Criteria.where("course.code").is(paperSearchInfo.getCourseNo()));
-        }
-        if (StringUtils.isNotBlank(paperSearchInfo.getName())) {
-            String paperName = CommonUtils.escapeExprSpecialWord(paperSearchInfo.getName());
-            query.addCriteria(Criteria.where("name").regex(".*?\\.*" + paperName + ".*"));
-        }
-        if (StringUtils.isNotBlank(paperSearchInfo.getLevel())) {
-            query.addCriteria(Criteria.where("course.level").is(paperSearchInfo.getLevel()));
-        }
-        if (StringUtils.isNotBlank(paperSearchInfo.getCreator())) {
-            String creator = CommonUtils.escapeExprSpecialWord(paperSearchInfo.getCreator());
-            query.addCriteria(Criteria.where("creator").regex(".*?\\.*" + creator + ".*"));
-        }
-        if (StringUtils.isNotBlank(paperSearchInfo.getLastModifyName())) {
-            String lastModifyName = CommonUtils.escapeExprSpecialWord(paperSearchInfo.getLastModifyName());
-            query.addCriteria(Criteria.where("lastModifyName").regex(".*?\\.*" + lastModifyName + ".*"));
-        }
+		query.addCriteria(Criteria.where("paperType").is(PaperType.GENERATE.name()));
+		query.addCriteria(Criteria.where("storage").ne(1));
+		query.addCriteria(Criteria.where("course.enable").is("true"));
+		if (paperSearchInfo.getInUse() != null) {
+			if (paperSearchInfo.getInUse() == 0) {
+				query.addCriteria(Criteria.where("inUse").ne(1));
+			} else if (paperSearchInfo.getInUse() == 1) {
+				query.addCriteria(Criteria.where("inUse").is(1));
+			}
+		}
+		if (StringUtils.isNotBlank(paperSearchInfo.getCourseNo())) {
+			query.addCriteria(Criteria.where("course.code").is(paperSearchInfo.getCourseNo()));
+		}
+		if (StringUtils.isNotBlank(paperSearchInfo.getName())) {
+			String paperName = CommonUtils.escapeExprSpecialWord(paperSearchInfo.getName());
+			query.addCriteria(Criteria.where("name").regex(".*?\\.*" + paperName + ".*"));
+		}
+		if (StringUtils.isNotBlank(paperSearchInfo.getLevel())) {
+			query.addCriteria(Criteria.where("course.level").is(paperSearchInfo.getLevel()));
+		}
+		if (StringUtils.isNotBlank(paperSearchInfo.getCreator())) {
+			String creator = CommonUtils.escapeExprSpecialWord(paperSearchInfo.getCreator());
+			query.addCriteria(Criteria.where("creator").regex(".*?\\.*" + creator + ".*"));
+		}
+		if (StringUtils.isNotBlank(paperSearchInfo.getLastModifyName())) {
+			String lastModifyName = CommonUtils.escapeExprSpecialWord(paperSearchInfo.getLastModifyName());
+			query.addCriteria(Criteria.where("lastModifyName").regex(".*?\\.*" + lastModifyName + ".*"));
+		}
 
-        long total = this.mongoTemplate.count(query, Paper.class);
-        if (total == 0) {
-            return Page.empty();
-        }
+		long total = this.mongoTemplate.count(query, Paper.class);
+		if (total == 0) {
+			return Page.empty();
+		}
 
-        query.with(Sort.by(new Order(Direction.DESC, "createTime")));
-        query.limit(pageSize);
-        query.skip((curPage - 1L) * pageSize);
-        List<Paper> paperList = this.mongoTemplate.find(query, Paper.class);
-        return new PageImpl<Paper>(paperList, PageRequest.of(curPage - 1, pageSize), total);
-    }
+		query.with(Sort.by(new Order(Direction.DESC, "createTime")));
+		query.limit(pageSize);
+		query.skip((curPage - 1L) * pageSize);
+		List<Paper> paperList = this.mongoTemplate.find(query, Paper.class);
+		return new PageImpl<Paper>(paperList, PageRequest.of(curPage - 1, pageSize), total);
+	}
 
-    @Override
-    public Page<Paper> getStoragePaperPage(PaperSearchInfo paperSearchInfo, int curPage, int pageSize,UserDataRule ud) {
-    	if (ud.assertEmptyQueryResult()) {
+	@Override
+	public Page<Paper> getStoragePaperPage(PaperSearchInfo paperSearchInfo, int curPage, int pageSize,
+			UserDataRule ud) {
+		if (ud.assertEmptyQueryResult()) {
 			return Page.empty();
 		}
-    	Query query = new Query();
-        query.addCriteria(Criteria.where("orgId").is(paperSearchInfo.getOrgId()));
-        if (ud.assertNeedQueryRefIds()) {
+		Query query = new Query();
+		query.addCriteria(Criteria.where("orgId").is(paperSearchInfo.getOrgId()));
+		if (ud.assertNeedQueryRefIds()) {
 			query.addCriteria(Criteria.where("course.id").in(ud.stringRefIds()));
 		}
-        query.addCriteria(Criteria.where("paperType").is(PaperType.GENERATE.name()));
-        query.addCriteria(Criteria.where("storage").is(1));
-        query.addCriteria(Criteria.where("course.enable").is("true"));
-        if (StringUtils.isNotBlank(paperSearchInfo.getCourseNo())) {
-            query.addCriteria(Criteria.where("course.code").is(paperSearchInfo.getCourseNo()));
-        }
-        if (StringUtils.isNoneBlank(paperSearchInfo.getName())) {
-            String paperName = CommonUtils.escapeExprSpecialWord(paperSearchInfo.getName());
-            query.addCriteria(Criteria.where("name").regex(".*?\\.*" + paperName + ".*"));
-        }
-        if (StringUtils.isNotBlank(paperSearchInfo.getLevel())) {
-            query.addCriteria(Criteria.where("course.level").is(paperSearchInfo.getLevel()));
-        }
-        if (StringUtils.isNoneBlank(paperSearchInfo.getCreator())) {
-            String creator = CommonUtils.escapeExprSpecialWord(paperSearchInfo.getCreator());
-            query.addCriteria(Criteria.where("creator").regex(".*?\\.*" + creator + ".*"));
-        }
-        if (StringUtils.isNoneBlank(paperSearchInfo.getLastModifyName())) {
-            String lastModifyName = CommonUtils.escapeExprSpecialWord(paperSearchInfo.getLastModifyName());
-            query.addCriteria(Criteria.where("lastModifyName").regex(".*?\\.*" + lastModifyName + ".*"));
-        }
+		query.addCriteria(Criteria.where("paperType").is(PaperType.GENERATE.name()));
+		query.addCriteria(Criteria.where("storage").is(1));
+		query.addCriteria(Criteria.where("course.enable").is("true"));
+		if (StringUtils.isNotBlank(paperSearchInfo.getCourseNo())) {
+			query.addCriteria(Criteria.where("course.code").is(paperSearchInfo.getCourseNo()));
+		}
+		if (StringUtils.isNoneBlank(paperSearchInfo.getName())) {
+			String paperName = CommonUtils.escapeExprSpecialWord(paperSearchInfo.getName());
+			query.addCriteria(Criteria.where("name").regex(".*?\\.*" + paperName + ".*"));
+		}
+		if (StringUtils.isNotBlank(paperSearchInfo.getLevel())) {
+			query.addCriteria(Criteria.where("course.level").is(paperSearchInfo.getLevel()));
+		}
+		if (StringUtils.isNoneBlank(paperSearchInfo.getCreator())) {
+			String creator = CommonUtils.escapeExprSpecialWord(paperSearchInfo.getCreator());
+			query.addCriteria(Criteria.where("creator").regex(".*?\\.*" + creator + ".*"));
+		}
+		if (StringUtils.isNoneBlank(paperSearchInfo.getLastModifyName())) {
+			String lastModifyName = CommonUtils.escapeExprSpecialWord(paperSearchInfo.getLastModifyName());
+			query.addCriteria(Criteria.where("lastModifyName").regex(".*?\\.*" + lastModifyName + ".*"));
+		}
 
-        long total = this.mongoTemplate.count(query, Paper.class);
-        if (total == 0) {
-            return Page.empty();
-        }
+		long total = this.mongoTemplate.count(query, Paper.class);
+		if (total == 0) {
+			return Page.empty();
+		}
 
-        query.with(Sort.by(new Order(Direction.DESC, "createTime")));
-        query.limit(pageSize);
-        query.skip((curPage - 1L) * pageSize);
-        List<Paper> paperList = this.mongoTemplate.find(query, Paper.class);
-        return new PageImpl<Paper>(paperList, PageRequest.of(curPage - 1, pageSize), total);
-    }
-
-    /**
-     * 查询考试试卷
-     *
-     * @param id
-     * @param courseCode
-     * @param groupCode
-     * @return
-     */
-    public List<Paper> listExamPapers(long id, String courseCode, String groupCode) {
-        List<Paper> papers = new ArrayList<>();
-        ExamPaper examPaper = new ExamPaper();
-        examPaper.setExamId(id);
-        examPaper.setCourseCode(courseCode);
-        examPaper.setGroupCode(groupCode);
-        Example<ExamPaper> example = Example.of(examPaper);
-        List<ExamPaper> examPapers = examPaperRepo.findAll(example);
-        for (ExamPaper ePaper : examPapers) {
-            Paper paper = Model.of(paperRepo.findById(ePaper.getPaper().getId()));
-            papers.add(paper);
-        }
-        return papers;
-    }
-
-    /**
-     * 设置考试试卷
-     *
-     * @param examId
-     * @param courseCode
-     * @param groupCode
-     * @param paperId
-     * @return
-     */
-    public void joinToExamPaper(long examId, String courseCode, String groupCode, String paperId) {
-        ExamPaper examPaper = new ExamPaper();
-        examPaper.setExamId(examId);
-        examPaper.setGroupCode(groupCode);
-        examPaper.setCourseCode(courseCode);
-        // examPaper.setPaperId(paperId);
-        examPaperRepo.save(examPaper);
-    }
-
-    public void releaseExamPaper(long examId, String courseCode, String groupCode, String paperId) {
-        ExamPaper examPaper = new ExamPaper();
-        examPaper.setExamId(examId);
-        examPaper.setGroupCode(groupCode);
-        examPaper.setCourseCode(courseCode);
-        // examPaper.setPaperId(paperId);
-        examPaperRepo.delete(examPaper);
-    }
-
-    public Set<String> listGroupCodes(long examId, String courseCode) {
-        Set<String> groupSet = new HashSet<>();
-        ExamPaper examPaper = new ExamPaper();
-        examPaper.setExamId(examId);
-        examPaper.setCourseCode(courseCode);
-        List<ExamPaper> examPapers = examPaperRepo.findAll(Example.of(examPaper));
-        for (ExamPaper expaper : examPapers) {
-            groupSet.add(expaper.getGroupCode());
-        }
-        return groupSet;
-    }
-
-    public void deletGroupCode(long examId, String courseCode, String groupCode) {
-        ExamPaper examPaper = new ExamPaper();
-        examPaper.setExamId(examId);
-        examPaper.setCourseCode(courseCode);
-        examPaper.setCourseCode(courseCode);
-        examPaperRepo.delete(examPaper);
-    }
-
-    /**
-     * 根据试卷ID获取试卷下面的大题
-     *
-     * @param id
-     * @return
-     */
-    public List<PaperDetail> findPaperDetailsById(String id) {
-        return paperDetailService.getPaperDetailsByPaper(Model.of(paperRepo.findById(id)));
-    }
-
-    /**
-     * 批量删除试卷
-     *
-     * @param paperIds
-     */
-    public void deletePapers(List<String> paperIds, User user) {
-        List<Paper> papers = CommonUtils.toList(paperRepo.findByIdIn(paperIds));
-        if (papers.get(0).getPaperType() == PaperType.IMPORT) {
-            List<Question> quesList = new ArrayList<>();
-            for (Paper paper : papers) {
-                List<PaperDetailUnit> paperUnits = paperDetailUnitRepo.findByPaperOrderByNumber(paper);
-                for (PaperDetailUnit pdu : paperUnits) {
-                    if (pdu.getQuestion() != null) {
-                        quesList.add(pdu.getQuestion());
-                    }
-                }
-            }
-            List<PaperDetailUnit> allUnits = paperDetailUnitRepo.findByQuestionIn(quesList);
-            for (PaperDetailUnit pdu : allUnits) {
-                if (pdu.getPaper() != null && pdu.getPaper().getPaperType() == PaperType.GENERATE) {
+		query.with(Sort.by(new Order(Direction.DESC, "createTime")));
+		query.limit(pageSize);
+		query.skip((curPage - 1L) * pageSize);
+		List<Paper> paperList = this.mongoTemplate.find(query, Paper.class);
+		return new PageImpl<Paper>(paperList, PageRequest.of(curPage - 1, pageSize), total);
+	}
+
+	/**
+	 * 查询考试试卷
+	 *
+	 * @param id
+	 * @param courseCode
+	 * @param groupCode
+	 * @return
+	 */
+	public List<Paper> listExamPapers(long id, String courseCode, String groupCode) {
+		List<Paper> papers = new ArrayList<>();
+		ExamPaper examPaper = new ExamPaper();
+		examPaper.setExamId(id);
+		examPaper.setCourseCode(courseCode);
+		examPaper.setGroupCode(groupCode);
+		Example<ExamPaper> example = Example.of(examPaper);
+		List<ExamPaper> examPapers = examPaperRepo.findAll(example);
+		for (ExamPaper ePaper : examPapers) {
+			Paper paper = Model.of(paperRepo.findById(ePaper.getPaper().getId()));
+			papers.add(paper);
+		}
+		return papers;
+	}
+
+	/**
+	 * 设置考试试卷
+	 *
+	 * @param examId
+	 * @param courseCode
+	 * @param groupCode
+	 * @param paperId
+	 * @return
+	 */
+	public void joinToExamPaper(long examId, String courseCode, String groupCode, String paperId) {
+		ExamPaper examPaper = new ExamPaper();
+		examPaper.setExamId(examId);
+		examPaper.setGroupCode(groupCode);
+		examPaper.setCourseCode(courseCode);
+		// examPaper.setPaperId(paperId);
+		examPaperRepo.save(examPaper);
+	}
+
+	public void releaseExamPaper(long examId, String courseCode, String groupCode, String paperId) {
+		ExamPaper examPaper = new ExamPaper();
+		examPaper.setExamId(examId);
+		examPaper.setGroupCode(groupCode);
+		examPaper.setCourseCode(courseCode);
+		// examPaper.setPaperId(paperId);
+		examPaperRepo.delete(examPaper);
+	}
+
+	public Set<String> listGroupCodes(long examId, String courseCode) {
+		Set<String> groupSet = new HashSet<>();
+		ExamPaper examPaper = new ExamPaper();
+		examPaper.setExamId(examId);
+		examPaper.setCourseCode(courseCode);
+		List<ExamPaper> examPapers = examPaperRepo.findAll(Example.of(examPaper));
+		for (ExamPaper expaper : examPapers) {
+			groupSet.add(expaper.getGroupCode());
+		}
+		return groupSet;
+	}
+
+	public void deletGroupCode(long examId, String courseCode, String groupCode) {
+		ExamPaper examPaper = new ExamPaper();
+		examPaper.setExamId(examId);
+		examPaper.setCourseCode(courseCode);
+		examPaper.setCourseCode(courseCode);
+		examPaperRepo.delete(examPaper);
+	}
+
+	/**
+	 * 根据试卷ID获取试卷下面的大题
+	 *
+	 * @param id
+	 * @return
+	 */
+	public List<PaperDetail> findPaperDetailsById(String id) {
+		return paperDetailService.getPaperDetailsByPaper(Model.of(paperRepo.findById(id)));
+	}
+
+	/**
+	 * 批量删除试卷
+	 *
+	 * @param paperIds
+	 */
+	public void deletePapers(List<String> paperIds, User user) {
+		List<Paper> papers = CommonUtils.toList(paperRepo.findByIdIn(paperIds));
+		if (papers.get(0).getPaperType() == PaperType.IMPORT) {
+			List<Question> quesList = new ArrayList<>();
+			for (Paper paper : papers) {
+				List<PaperDetailUnit> paperUnits = paperDetailUnitRepo.findByPaperOrderByNumber(paper);
+				for (PaperDetailUnit pdu : paperUnits) {
+					if (pdu.getQuestion() != null) {
+						quesList.add(pdu.getQuestion());
+					}
+				}
+			}
+			List<PaperDetailUnit> allUnits = paperDetailUnitRepo.findByQuestionIn(quesList);
+			for (PaperDetailUnit pdu : allUnits) {
+				if (pdu.getPaper() != null && pdu.getPaper().getPaperType() == PaperType.GENERATE) {
 //                    msg = "待删除试卷中有试题被组卷使用,不能删除!";
 //                    msgMap.put("msg", msg);
 //                    msgMap.put("paperName", pdu.getPaper().getName());
 //                    return msgMap;
-                    throw new StatusException("试卷["+pdu.getPaper().getName()+"]中有试题被组卷使用,不能删除");
-                }
-            }
-            //删除音频
-            questionAudioService.deleteAudio(quesList);
-            quesRepo.deleteAll(quesList);
-        } else if (papers.get(0).getPaperType() == PaperType.GENERATE) {
-            for (Paper paper : papers) {
+					throw new StatusException("试卷[" + pdu.getPaper().getName() + "]中有试题被组卷使用,不能删除");
+				}
+			}
+			// 删除音频
+			questionAudioService.deleteAudio(quesList);
+			quesRepo.deleteAll(quesList);
+		} else if (papers.get(0).getPaperType() == PaperType.GENERATE) {
+			for (Paper paper : papers) {
 //                List<String> examPaperIds = extractConfigService.getExamPaperId(paper.getCourseNo(), paper.getOrgId());
 //                if (examPaperIds != null && examPaperIds.contains(paper.getId())) {
 //                    msg = "待删除试卷有被调卷规则使用,不能删除!";
@@ -619,1858 +618,1906 @@ public class PaperServiceImpl implements PaperService {
 //                    msgMap.put("paperName", paper.getName());
 //                    return msgMap;
 //                }
-                if(paper.getInUse()!=null&&paper.getInUse()==1) {
-		            throw new StatusException("试卷["+paper.getName()+"]已调用,不能删除");
-        		}
-            }
-        }
-        paperDetailService.deletePaperDetailsByPapers(papers);
-        paperRepo.deleteAll(papers);
+				if (paper.getInUse() != null && paper.getInUse() == 1) {
+					throw new StatusException("试卷[" + paper.getName() + "]已调用,不能删除");
+				}
+			}
+		}
+		paperDetailService.deletePaperDetailsByPapers(papers);
+		paperRepo.deleteAll(papers);
 
-        for (String paperId : paperIds) {
-            //清除缓存
-            this.clearPaperCache(paperId);
-        }
+		for (String paperId : paperIds) {
+			// 清除缓存
+			this.clearPaperCache(paperId);
+		}
 
-        for (Paper paper : papers) {
-            StringBuilder paperInfo = new StringBuilder();
-            paperInfo.append("课程:" + paper.getCourse().getName() + "(" + paper.getCourse().getCode() + ")");
-            paperInfo.append(" 试卷名称:" + paper.getName());
-            if (PaperType.IMPORT.equals(paper.getPaperType())) {
-                ReportsUtil.report(new AdminOperateReport(user.getRootOrgId(), user.getUserId(), AdminOperateType.TYPE46.getDesc(), paperInfo.toString()));
-            } else {
-                ReportsUtil.report(new AdminOperateReport(user.getRootOrgId(), user.getUserId(), AdminOperateType.TYPE47.getDesc(), paperInfo.toString()));
+		for (Paper paper : papers) {
+			StringBuilder paperInfo = new StringBuilder();
+			paperInfo.append("课程:" + paper.getCourse().getName() + "(" + paper.getCourse().getCode() + ")");
+			paperInfo.append(" 试卷名称:" + paper.getName());
+			if (PaperType.IMPORT.equals(paper.getPaperType())) {
+				ReportsUtil.report(new AdminOperateReport(user.getRootOrgId(), user.getUserId(),
+						AdminOperateType.TYPE46.getDesc(), paperInfo.toString()));
+			} else {
+				ReportsUtil.report(new AdminOperateReport(user.getRootOrgId(), user.getUserId(),
+						AdminOperateType.TYPE47.getDesc(), paperInfo.toString()));
 
-            }
-        }
-    }
-
-    /**
-     * 批量通过试卷
-     *
-     * @param paperIds
-     */
-    public void passPapers(List<String> paperIds) {
-        List<Paper> papers = CommonUtils.toList(paperRepo.findByIdIn(paperIds));
-        papers.stream().forEach(paper -> {
-            paper.setPaperStatus(PaperStatus.PASS);
-        });
-        paperRepo.saveAll(papers);
-    }
-
-    @Override
-    public void updatePapersStorage(List<String> paperIds, int storage, String orgId) {
-        List<Paper> papers = CommonUtils.toList(paperRepo.findByIdIn(paperIds));
-        List<Paper> papersList = papers.stream().filter(p -> orgId.equals(p.getOrgId())).collect(Collectors.toList());
-        papersList.stream().forEach(paper -> {
-            paper.setStorage(storage);
-        });
-        if (papersList.size() > 0) {
-            paperRepo.saveAll(papersList);
-        }
-    }
-
-    /**
-     * 批量不通过试卷
-     *
-     * @param paperIds
-     */
-    public void noPassPapers(List<String> paperIds) {
-        List<Paper> papers = CommonUtils.toList(paperRepo.findByIdIn(paperIds));
-        papers.stream().forEach(paper -> {
-            paper.setPaperStatus(PaperStatus.NOPASS);
-        });
-        paperRepo.saveAll(papers);
-    }
-
-    /**
-     * 批量待审核试卷
-     *
-     * @param paperIds
-     */
-    public void backPapers(List<String> paperIds) {
-        List<Paper> papers = CommonUtils.toList(paperRepo.findByIdIn(paperIds));
-        papers.stream().forEach(paper -> {
-            paper.setPaperStatus(PaperStatus.DRAFT);
-        });
-        paperRepo.saveAll(papers);
-    }
-
-    /**
-     * 初始化导出试卷DTO
-     *
-     * @param id
-     * @return
-     */
-    public PaperExp getPaperDto(String id) {
-        Paper paper = Model.of(paperRepo.findById(id));
-        // 创建paperDto
-        PaperExp paperExp = new PaperExp();
-        BeanUtils.copyProperties(paper, paperExp);
-        paperExp.setCourse(paper.getCourse());
-        // 获取大题
-        List<PaperDetail> paperDetails = paperDetailRepo.findByPaperOrderByNumber(paper);
-        List<PaperDetailExp> paperDetailExps = new ArrayList<>();
-        for (PaperDetail paperDetail : paperDetails) {
-            PaperDetailExp paperDetailExp = new PaperDetailExp();
-            BeanUtils.copyProperties(paperDetail, paperDetailExp);
-            paperDetailExps.add(paperDetailExp);
-        }
-        // 封装小题
-        for (int i = 0; i < paperDetailExps.size(); i++) {
-            List<PaperDetailUnit> paperDetailUnits = paperDetailUnitRepo.findByPaperDetailOrderByNumber(paperDetails.get(i));
-            if (paperDetailUnits != null && paperDetailUnits.size() > 0) {
-                List<PaperDetailUnitExp> paperDetailUnitExps = new ArrayList<>();
-                for (PaperDetailUnit paperDetailUnit : paperDetailUnits) {
-                    PaperDetailUnitExp paperDetailUnitExp = new PaperDetailUnitExp();
-                    BeanUtils.copyProperties(paperDetailUnit, paperDetailUnitExp);
-                    fillProperty(paperDetailUnitExp.getQuestion());
-                    if(!CollectionUtils.isEmpty(paperDetailUnitExp.getQuestion().getSubQuestions())) {
-                    	for(Question subque:paperDetailUnitExp.getQuestion().getSubQuestions()) {
-                    		fillProperty(subque);
-                    	}
-                    }
-                    paperDetailUnitExps.add(paperDetailUnitExp);
-                }
-                // 选择题,套题下选择题 选项顺序重新排列
-                reorderChoicequestionOption(paperDetailUnitExps);
-                paperDetailExps.get(i).setPaperDetailUnits(paperDetailUnitExps);
-            } else {
-                paperDetailExps.get(i).setUnitCount(0);
-            }
-        }
-        paperExp.setPaperDetails(paperDetailExps);
-        // 初始化试卷内容
-        initPaper(paperExp);
-        return paperExp;
-    }
-
-    /**
-     * 重新对选择题option进行排序(多选、单选、套题下选择题)
-     */
-    public void reorderChoicequestionOption(List<PaperDetailUnitExp> paperDetailUnitExps) {
-        for (PaperDetailUnitExp paperDetailUnitExp : paperDetailUnitExps) {
-            String optionOrder = paperDetailUnitExp.getOptionOrder();
-            if (StringUtil.isNotBlank(optionOrder)) {
-                Question question = paperDetailUnitExp.getQuestion();
-                if (question.getQuestionType() == QuesStructType.SINGLE_ANSWER_QUESTION
-                        || question.getQuestionType() == QuesStructType.MULTIPLE_ANSWER_QUESTION) {
-                    question.setQuesOptions(reorderOptionCore(question.getQuesOptions(), optionOrder));
-                }
-                if (question.getQuestionType() == QuesStructType.NESTED_ANSWER_QUESTION) {
-                    List<Question> subQuestions = question.getSubQuestions();
-                    int index = 0;
-                    for (int k = 0; k < subQuestions.size(); k++) {
-                        Question subQuestion = subQuestions.get(k);
-                        if (subQuestion.getQuestionType() == QuesStructType.SINGLE_ANSWER_QUESTION
-                                || subQuestion.getQuestionType() == QuesStructType.MULTIPLE_ANSWER_QUESTION) {
-                            subQuestion.setQuesOptions(
-                                    reorderOptionCore(subQuestion.getQuesOptions(), optionOrder.split(";")[index]));
-                            index++;
-                        }
-                    }
-                }
-            }
-        }
-    }
+			}
+		}
+	}
 
-    private List<QuesOption> reorderOptionCore(List<QuesOption> quesOptions, String optionOrder) {
-        List<QuesOption> newQuesOptions = new ArrayList<>();
-        if (StringUtil.isBlank(optionOrder) || quesOptions.isEmpty()) {
-            return null;
-        }
-        String[] optionOrderArr = optionOrder.split(",");
-        for (int j = 0; j < optionOrderArr.length; j++) {
-            for (int k = 0; k < quesOptions.size(); k++) {
-                if (optionOrderArr[j].equals(quesOptions.get(k).getNumber())) {
-                    newQuesOptions.add(quesOptions.get(k));
-                }
-            }
-        }
-        quesOptions = null;
-        return newQuesOptions;
-    }
-
-    /**
-     * 初始化试卷内容(增加序号)
-     *
-     * @param paperExp
-     */
-    public void initPaper(PaperExp paperExp) {
-        if (paperExp.getPaperDetails() == null || paperExp.getPaperDetails().size() == 0) {
-            return;
-        }
-        int mainNum = 0;
-        List<PaperDetailExp> paperDetailExpList = paperExp.getPaperDetails();
-        for (PaperDetailExp paperDetail : paperDetailExpList) {
-            // 大题序号
-            paperDetail.setNumber(++mainNum);
-            paperDetail.setCnNum(CommonUtils.toCHNum(paperDetail.getNumber()));
-            if (paperDetail != null && paperDetail.getPaperDetailUnits() != null && paperDetail.getPaperDetailUnits().size() > 0) {
-                for (PaperDetailUnitExp paperDetailUnit : paperDetail.getPaperDetailUnits()) {
-                    Question question = paperDetailUnit.getQuestion();
-                    if (question != null) {
-                        if (question.getHasAudio() != null && question.getHasAudio()) {
-                            paperExp.setHasAudio(true);    //设置试卷含有音频
-                        }
-                        quesService.formatQuesUnit(question);
-                        List<Question> subQuesList = question.getSubQuestions();
-                        // 套题序号
-                        if (subQuesList != null && subQuesList.size() > 0) {
-                            int index = 0;
-                            for (Question subQues : subQuesList) {
-                                Map<String, String> params = new HashMap<>();
-                                params.put("number", String.valueOf(++index));
-                                subQues.setQuesParams(params);
-                                quesService.formatQuesUnit(subQues);
-                            }
-                            String quesBodyHtml = CommonUtils.relaceQuestionIdx(question.getQuesBody(), 0);
-                            question.setQuesBody(quesBodyHtml);
-                        }
-                    }
-                }
-            }
-        }
-    }
-
-    /**
-     * 格式化查询条件
-     *
-     * @param paperSearchInfo
-     */
-    public void formatPaperSearchInfo(PaperSearchInfo paperSearchInfo) {
-        if (StringUtils.isEmpty(paperSearchInfo.getCourseNo())) {
-            paperSearchInfo.setCourseNo(null);
-        }
-        if (StringUtils.isEmpty(paperSearchInfo.getCreateTime())) {
-            paperSearchInfo.setCreateTime(null);
-        }
-        if (StringUtils.isEmpty(paperSearchInfo.getCreator())) {
-            paperSearchInfo.setCreator(null);
-        }
-        if (StringUtils.isEmpty(paperSearchInfo.getName())) {
-            paperSearchInfo.setName(null);
-        }
-    }
-
-    /**
-     * 1.重新设置小题number,并返回试卷总分
-     * 2.重新计算大题的总分和小题总数
-     * 3.重新保存试卷大题数量、小题数量、试卷总分等信息
-     *
-     * @param paper
-     */
-    public void formatPaper(Paper paper, User user) {
-        double paperTotalScore = reSetPaperDetailUnit(paper);
-        paper.setDifficultyDegree(reSetDifficulty(paper, paperTotalScore));
-        Map<String, Object> paperInfoMap = reSetPaperDetail(paper);
-        reSetPaper(paper, user, paperInfoMap, paperTotalScore);
-    }
-
-    /**
-     * 计算试卷难度
-     *
-     * @param paper
-     * @param paperTotalScore
-     * @return
-     */
-
-    @SuppressWarnings("unused")
-    public Double reSetDifficulty(Paper paper, double paperTotalScore) {
-        Double sum = 0.0;
-        List<PaperDetail> paperDetails = paperDetailRepo.findByPaperOrderByNumber(paper);
-        if (paperDetails != null && paperDetails.size() > 0) {
-            for (PaperDetail paperDetail : paperDetails) {
-                //获取每个大题下面的所有小题
-                List<PaperDetailUnit> paperDetailUnits = paperDetailUnitRepo.findByPaperDetailOrderByNumber(paperDetail);
-                if (paperDetailUnits != null && paperDetailUnits.size() > 0) {
-                    for (PaperDetailUnit paperDetailUnit : paperDetailUnits) {
-                        //如果为套题,重新计算难度
-                        if (paperDetailUnit.getQuestionType() == QuesStructType.NESTED_ANSWER_QUESTION) {
-                            //重新计算套题的难度,公开度
-                            boolean publicity = false;
-                            double totalSum = 0d;
-                            double totalDou = 0d;
-                            for (int i = 0; i < paperDetailUnit.getQuestion().getSubQuestions().size(); i++) {
-                                Question subQuestion = paperDetailUnit.getQuestion().getSubQuestions().get(i);
-                                //设置公开度
-                                if (subQuestion.getPublicity() == null) {
-                                    publicity = true;
-                                } else {
-                                    if (subQuestion.getPublicity()) {
-                                        publicity = true;
-                                    }
-                                }
-                                if (subQuestion.getDifficultyDegree() == null) {
-                                    subQuestion.setDifficultyDegree(0.5);
-                                }
-                                totalSum = subQuestion.getDifficultyDegree() * paperDetailUnit.getSubScoreList().get(i) + totalSum;
-                                totalDou = paperDetailUnit.getSubScoreList().get(i) + totalDou;
-                            }
-
-                            BigDecimal b;
-                            if (totalDou != 0d) {
-                                b = BigDecimal.valueOf(totalSum / totalDou);
-                            } else {
-                                b = BigDecimal.valueOf(0d);
-                            }
-
-                            Double difficulty = b.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
-                            paperDetailUnit.getQuestion().setDifficultyDegree(difficulty);
-                            paperDetailUnit.setScore(totalDou);
-                        }
-                        //旧题没有难度值,需要重新赋值
-                        if (paperDetailUnit.getQuestion().getDifficultyDegree() == null) {
-                            paperDetailUnit.getQuestion().setDifficultyDegree(0.5);
-                        }
-                        if (paperDetailUnit.getScore() == null) {
-                            paperDetailUnit.setScore(0d);
-                        }
-                        sum = paperDetailUnit.getScore() * paperDetailUnit.getQuestion().getDifficultyDegree() + sum;
-                    }
-                }
-            }
-            if (paperTotalScore < 0.1) {
-                return 0.0;
-            }
-            BigDecimal b = BigDecimal.valueOf(sum / paperTotalScore);
-            Double difficulty = b.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
-            return difficulty;
-        }
-        return 0.0;
-    }
-
-    /**
-     * 重新设置小题number,并返回试卷总分
-     *
-     * @param paper
-     * @return
-     */
-    private double reSetPaperDetailUnit(Paper paper) {
-        List<PaperDetailUnit> paperDetailUnitAll = paperDetailUnitService.findByPaperAndSort(paper);
-        double totalScore = 0;
-        for (int i = 0; i < paperDetailUnitAll.size(); i++) {
-            PaperDetailUnit unit = paperDetailUnitAll.get(i);
-            if (unit.getScore() != null) {
-                totalScore += unit.getScore();
-            }
-            unit.setNumber(i + 1);
-        }
-        paperDetailUnitRepo.saveAll(paperDetailUnitAll);
-        totalScore = CommonUtils.formatDouble(totalScore);
-        return totalScore;
-    }
-
-    /**
-     * 重新计算大题的总分和小题总数
-     *
-     * @param paper
-     */
-    private Map<String, Object> reSetPaperDetail(Paper paper) {
-        Map<String, Object> paperInfoMap = new HashMap<>();
-        int allQuesCount = 0;
-        List<PaperDetail> paperDetails = paperDetailRepo.findByPaperOrderByNumber(paper);
-        // 计算各大题总分和小题数量
-        for (PaperDetail paperDetail : paperDetails) {
-            List<PaperDetailUnit> paperDetailUnits = paperDetailUnitRepo.findByPaperDetailOrderByNumber(paperDetail);
-            if (paperDetailUnits.size() > 0) {
-                int count = 0;
-                double score = 0;
-                int nestQusNum = 0;
-                for (PaperDetailUnit unit : paperDetailUnits) {
-                    if (unit.getScore() != null) {
-                        score += unit.getScore();
-                    }
-                    if (unit.getQuestion() != null
-                            && unit.getQuestion().getSubQuestions() != null
-                            && unit.getQuestion().getSubQuestions().size() > 0) {
-                        nestQusNum += unit.getQuestion().getSubQuestions().size() - 1;
-                    }
-                }
-                count = paperDetailUnits.size() + nestQusNum;
-                score = CommonUtils.formatDouble(score);
-                paperDetail.setScore(score);
-                paperDetail.setUnitCount(count);
-                allQuesCount += count;
-            } else {
-                paperDetail.setScore(0d);
-            }
-        }
-        paperDetailRepo.saveAll(paperDetails);
-        paperInfoMap.put("allQuesCount", allQuesCount);
-        paperInfoMap.put("paperDetails", paperDetails);
-        return paperInfoMap;
-    }
-
-    /**
-     * 重新设置试卷大题数量、小题数量、试卷总分等属性
-     *
-     * @param paper
-     * @param user
-     * @param paperInfoMap
-     * @param paperTotalScore
-     */
-    @SuppressWarnings("unchecked")
-    private void reSetPaper(Paper paper, User user, Map<String, Object> paperInfoMap, double paperTotalScore) {
-        List<PaperDetail> paperDetails = (List<PaperDetail>) paperInfoMap.get("paperDetails");
-        paper.setPaperDetailCount(paperDetails.size());//设置大题数量
-        paper.setUnitCount(Integer.parseInt(paperInfoMap.get("allQuesCount") + ""));//设置小题数量
-        paper.setTotalScore(paperTotalScore);//设置试卷总分
-        if (user != null) {
-            paper.setLastModifyName(user.getDisplayName());
-        }
-        paperRepo.save(paper);
-
-        //清除缓存
-        this.clearPaperCache(paper.getId());
-    }
-
-    /**
-     * 先备份准备删掉的试题,然后再删掉
-     *
-     * @param questionId
-     * @return
-     */
-    public List<String> deleteImportQuestionById(String detailUnitId, String questionId, User user) {
-        PaperDetailUnit paperDetailUnit = null;
-        if (detailUnitId != null) {
-            paperDetailUnit = Model.of(paperDetailUnitRepo.findById(detailUnitId));
-            Paper paper=paperDetailUnit.getPaper();
-            if(paper.getInUse()!=null&&paper.getInUse()==1) {
-    			throw new StatusException("500", "试卷已调用");
-    		}
-        }
-        Question ques = Model.of(quesRepo.findById(questionId));
-
-        List<PaperDetailUnit> pdus = CommonUtils.toList(paperDetailUnitRepo.findByQuestion(ques));
-        List<String> paperNames = new ArrayList<>();
-
-        // 需要删除的小题
-        List<PaperDetailUnit> needPdus = new ArrayList<>();
-
-        List<Paper> papers = new ArrayList<>();
-        for (PaperDetailUnit pdu : pdus) {
-            if (pdu.getPaper() != null) {
-                if (!papers.contains(pdu.getPaper())) {
-                    papers.add(pdu.getPaper());
-                }
-                if (PaperType.GENERATE == pdu.getPaper().getPaperType()) {
-                    paperNames.add(pdu.getPaper().getName());
-                }
-            }
-        }
-        String changInfo = null;
-        if (paperNames.size() == 0) {
-            needPdus.addAll(pdus);// 此试题没有被组卷调用,则可以删除此试题
-            paperDetailUnitRepo.deleteAll(needPdus);
-            quesBakRepo.save(BeanCopierUtil.copyProperties(ques, QuestionBak.class));
-            quesRepo.delete(ques);
-
-            for (Paper paper : papers) {
-                if (paperDetailUnit != null && paperDetailUnit.getPaper().getId().equals(paper.getId())) {
-                    Double total = paper.getTotalScore();
-                    Integer dc = paper.getPaperDetailCount();
-                    Integer uc = paper.getUnitCount();
-                    formatPaper(paper, user);
-                    changInfo = PaperUtil.getPaperChangeInfo(total, dc, uc, paper);
-                } else {
-                    formatPaper(paper, user);
-                }
-            }
-        }
+	/**
+	 * 批量通过试卷
+	 *
+	 * @param paperIds
+	 */
+	public void passPapers(List<String> paperIds) {
+		List<Paper> papers = CommonUtils.toList(paperRepo.findByIdIn(paperIds));
+		papers.stream().forEach(paper -> {
+			paper.setPaperStatus(PaperStatus.PASS);
+		});
+		paperRepo.saveAll(papers);
+	}
 
-        if (paperDetailUnit != null) {
-            StringBuilder sb = new StringBuilder();
-            sb.append("课程:" + paperDetailUnit.getPaper().getCourse().getName() + "(" + paperDetailUnit.getPaper().getCourse().getCode() + ")");
-            sb.append(" 试卷名称:" + paperDetailUnit.getPaper().getName());
-            sb.append(" 第" + paperDetailUnit.getNumber() + "小题 ");
-            sb.append(changInfo);
-            ReportsUtil.report(new AdminOperateReport(user.getRootOrgId(), user.getUserId(), AdminOperateType.TYPE48.getDesc(), sb.toString()));
-        }
-        return paperNames;
-    }
-
-    /**
-     * 向试卷中插入一个试题
-     *
-     * @param paperId
-     * @param paperDetailId
-     * @return
-     */
-    public Paper insertQuestionToPaper(String paperId, String paperDetailId, Question question, User user) {
-        Paper paper = Model.of(paperRepo.findById(paperId));
-        question.setOrgId(user.getRootOrgId().toString());
-        question.setCourse(paper.getCourse());
-        question.setCourseNo(paper.getCourse().getCode());//必须设置,因为部分方法需要courseNo作为查询条件
-        question = quesService.saveQues(question);
-
-        PaperDetail paperDetail = Model.of(paperDetailRepo.findById(paperDetailId));
-        PaperDetailUnit paperDetailUnit = new PaperDetailUnit(paper, paperDetail, question);
-        paperDetailUnit.setPaperType(PaperType.IMPORT);
-        PaperDetailUnit paperDetailUnit2 = paperDetailUnitService.findTopOrderByNumber(paperDetail, "DESC");
-        if (paperDetailUnit2 == null) {
-            paperDetailUnit.setNumber(1);
-        } else {
-            paperDetailUnit.setNumber(paperDetailUnit2.getNumber());//设置number为大题的最大题号
-        }
-        paperDetailUnitRepo.save(paperDetailUnit);
-        formatPaper(paper, user);
-        return paper;
-    }
-
-    /**
-     * 获取试题所在的试卷名称
-     *
-     * @param questionId
-     * @return
-     */
-    public List<String> getPaperNamesByQuestionId(String questionId) {
-        List<String> paperNames = new ArrayList<>();
-        List<PaperDetailUnit> pdus = paperDetailUnitRepo.findByQuestion(Model.of(quesRepo.findById(questionId)));
-        for (PaperDetailUnit pdu : pdus) {
-            paperNames.add(pdu.getPaper().getName());
-        }
-        return paperNames;
+	@Override
+	public void updatePapersStorage(List<String> paperIds, int storage, String orgId) {
+		List<Paper> papers = CommonUtils.toList(paperRepo.findByIdIn(paperIds));
+		List<Paper> papersList = papers.stream().filter(p -> orgId.equals(p.getOrgId())).collect(Collectors.toList());
+		papersList.stream().forEach(paper -> {
+			paper.setStorage(storage);
+		});
+		if (papersList.size() > 0) {
+			paperRepo.saveAll(papersList);
+		}
+	}
 
-    }
+	/**
+	 * 批量不通过试卷
+	 *
+	 * @param paperIds
+	 */
+	public void noPassPapers(List<String> paperIds) {
+		List<Paper> papers = CommonUtils.toList(paperRepo.findByIdIn(paperIds));
+		papers.stream().forEach(paper -> {
+			paper.setPaperStatus(PaperStatus.NOPASS);
+		});
+		paperRepo.saveAll(papers);
+	}
 
-    public Page<Question> listQuestionforSelect(String paperId, int curPage, int pageSize, QuesStructType quesType, User user, String quesBody,UserDataRule ud) {
-        Set<String> selectedIds = new HashSet<>();
-        Paper paper = Model.of(paperRepo.findById(paperId));
-        List<PaperDetailUnit> pdus = paperDetailUnitRepo.findByPaperOrderByNumber(paper);
-        for (PaperDetailUnit pdu : pdus) {
-            selectedIds.add(pdu.getQuestion().getId());
-        }
-        return quesService.findByIdExclude(selectedIds, paper.getCourseNo(), quesType, curPage, pageSize, user.getRootOrgId(), quesBody,ud);
-    }
+	/**
+	 * 批量待审核试卷
+	 *
+	 * @param paperIds
+	 */
+	public void backPapers(List<String> paperIds) {
+		List<Paper> papers = CommonUtils.toList(paperRepo.findByIdIn(paperIds));
+		papers.stream().forEach(paper -> {
+			paper.setPaperStatus(PaperStatus.DRAFT);
+		});
+		paperRepo.saveAll(papers);
+	}
 
-    @SuppressWarnings("unused")
-    public Paper selectQuestionsToPaper(String paperId, String paperDetailId, List<Question> questions, User user) {
-        Paper paper = Model.of(paperRepo.findById(paperId));
-        if(paper.getInUse()!=null&&paper.getInUse()==1) {
+	/**
+	 * 初始化导出试卷DTO
+	 *
+	 * @param id
+	 * @return
+	 */
+	public PaperExp getPaperDto(String id) {
+		Paper paper = Model.of(paperRepo.findById(id));
+		// 创建paperDto
+		PaperExp paperExp = new PaperExp();
+		BeanUtils.copyProperties(paper, paperExp);
+		paperExp.setCourse(paper.getCourse());
+		// 获取大题
+		List<PaperDetail> paperDetails = paperDetailRepo.findByPaperOrderByNumber(paper);
+		List<PaperDetailExp> paperDetailExps = new ArrayList<>();
+		for (PaperDetail paperDetail : paperDetails) {
+			PaperDetailExp paperDetailExp = new PaperDetailExp();
+			BeanUtils.copyProperties(paperDetail, paperDetailExp);
+			paperDetailExps.add(paperDetailExp);
+		}
+		// 封装小题
+		for (int i = 0; i < paperDetailExps.size(); i++) {
+			List<PaperDetailUnit> paperDetailUnits = paperDetailUnitRepo
+					.findByPaperDetailOrderByNumber(paperDetails.get(i));
+			if (paperDetailUnits != null && paperDetailUnits.size() > 0) {
+				List<PaperDetailUnitExp> paperDetailUnitExps = new ArrayList<>();
+				for (PaperDetailUnit paperDetailUnit : paperDetailUnits) {
+					PaperDetailUnitExp paperDetailUnitExp = new PaperDetailUnitExp();
+					BeanUtils.copyProperties(paperDetailUnit, paperDetailUnitExp);
+					fillProperty(paperDetailUnitExp.getQuestion());
+					if (!CollectionUtils.isEmpty(paperDetailUnitExp.getQuestion().getSubQuestions())) {
+						for (Question subque : paperDetailUnitExp.getQuestion().getSubQuestions()) {
+							fillProperty(subque);
+						}
+					}
+					paperDetailUnitExps.add(paperDetailUnitExp);
+				}
+				// 选择题,套题下选择题 选项顺序重新排列
+				reorderChoicequestionOption(paperDetailUnitExps);
+				paperDetailExps.get(i).setPaperDetailUnits(paperDetailUnitExps);
+			} else {
+				paperDetailExps.get(i).setUnitCount(0);
+			}
+		}
+		paperExp.setPaperDetails(paperDetailExps);
+		// 初始化试卷内容
+		initPaper(paperExp);
+		return paperExp;
+	}
+
+	/**
+	 * 重新对选择题option进行排序(多选、单选、套题下选择题)
+	 */
+	public void reorderChoicequestionOption(List<PaperDetailUnitExp> paperDetailUnitExps) {
+		for (PaperDetailUnitExp paperDetailUnitExp : paperDetailUnitExps) {
+			String optionOrder = paperDetailUnitExp.getOptionOrder();
+			if (StringUtil.isNotBlank(optionOrder)) {
+				Question question = paperDetailUnitExp.getQuestion();
+				if (question.getQuestionType() == QuesStructType.SINGLE_ANSWER_QUESTION
+						|| question.getQuestionType() == QuesStructType.MULTIPLE_ANSWER_QUESTION) {
+					question.setQuesOptions(reorderOptionCore(question.getQuesOptions(), optionOrder));
+				}
+				if (question.getQuestionType() == QuesStructType.NESTED_ANSWER_QUESTION) {
+					List<Question> subQuestions = question.getSubQuestions();
+					int index = 0;
+					for (int k = 0; k < subQuestions.size(); k++) {
+						Question subQuestion = subQuestions.get(k);
+						if (subQuestion.getQuestionType() == QuesStructType.SINGLE_ANSWER_QUESTION
+								|| subQuestion.getQuestionType() == QuesStructType.MULTIPLE_ANSWER_QUESTION) {
+							subQuestion.setQuesOptions(
+									reorderOptionCore(subQuestion.getQuesOptions(), optionOrder.split(";")[index]));
+							index++;
+						}
+					}
+				}
+			}
+		}
+	}
+
+	private List<QuesOption> reorderOptionCore(List<QuesOption> quesOptions, String optionOrder) {
+		List<QuesOption> newQuesOptions = new ArrayList<>();
+		if (StringUtil.isBlank(optionOrder) || quesOptions.isEmpty()) {
+			return null;
+		}
+		String[] optionOrderArr = optionOrder.split(",");
+		for (int j = 0; j < optionOrderArr.length; j++) {
+			for (int k = 0; k < quesOptions.size(); k++) {
+				if (optionOrderArr[j].equals(quesOptions.get(k).getNumber())) {
+					newQuesOptions.add(quesOptions.get(k));
+				}
+			}
+		}
+		quesOptions = null;
+		return newQuesOptions;
+	}
+
+	/**
+	 * 初始化试卷内容(增加序号)
+	 *
+	 * @param paperExp
+	 */
+	public void initPaper(PaperExp paperExp) {
+		if (paperExp.getPaperDetails() == null || paperExp.getPaperDetails().size() == 0) {
+			return;
+		}
+		int mainNum = 0;
+		List<PaperDetailExp> paperDetailExpList = paperExp.getPaperDetails();
+		for (PaperDetailExp paperDetail : paperDetailExpList) {
+			// 大题序号
+			paperDetail.setNumber(++mainNum);
+			paperDetail.setCnNum(CommonUtils.toCHNum(paperDetail.getNumber()));
+			if (paperDetail != null && paperDetail.getPaperDetailUnits() != null
+					&& paperDetail.getPaperDetailUnits().size() > 0) {
+				for (PaperDetailUnitExp paperDetailUnit : paperDetail.getPaperDetailUnits()) {
+					Question question = paperDetailUnit.getQuestion();
+					if (question != null) {
+						if (question.getHasAudio() != null && question.getHasAudio()) {
+							paperExp.setHasAudio(true); // 设置试卷含有音频
+						}
+						quesService.formatQuesUnit(question);
+						List<Question> subQuesList = question.getSubQuestions();
+						// 套题序号
+						if (subQuesList != null && subQuesList.size() > 0) {
+							int index = 0;
+							for (Question subQues : subQuesList) {
+								Map<String, String> params = new HashMap<>();
+								params.put("number", String.valueOf(++index));
+								subQues.setQuesParams(params);
+								quesService.formatQuesUnit(subQues);
+							}
+							String quesBodyHtml = CommonUtils.relaceQuestionIdx(question.getQuesBody(), 0);
+							question.setQuesBody(quesBodyHtml);
+						}
+					}
+				}
+			}
+		}
+	}
+
+	/**
+	 * 格式化查询条件
+	 *
+	 * @param paperSearchInfo
+	 */
+	public void formatPaperSearchInfo(PaperSearchInfo paperSearchInfo) {
+		if (StringUtils.isEmpty(paperSearchInfo.getCourseNo())) {
+			paperSearchInfo.setCourseNo(null);
+		}
+		if (StringUtils.isEmpty(paperSearchInfo.getCreateTime())) {
+			paperSearchInfo.setCreateTime(null);
+		}
+		if (StringUtils.isEmpty(paperSearchInfo.getCreator())) {
+			paperSearchInfo.setCreator(null);
+		}
+		if (StringUtils.isEmpty(paperSearchInfo.getName())) {
+			paperSearchInfo.setName(null);
+		}
+	}
+
+	/**
+	 * 1.重新设置小题number,并返回试卷总分 2.重新计算大题的总分和小题总数 3.重新保存试卷大题数量、小题数量、试卷总分等信息
+	 *
+	 * @param paper
+	 */
+	public void formatPaper(Paper paper, User user) {
+		double paperTotalScore = reSetPaperDetailUnit(paper);
+		paper.setDifficultyDegree(reSetDifficulty(paper, paperTotalScore));
+		Map<String, Object> paperInfoMap = reSetPaperDetail(paper);
+		reSetPaper(paper, user, paperInfoMap, paperTotalScore);
+	}
+
+	/**
+	 * 计算试卷难度
+	 *
+	 * @param paper
+	 * @param paperTotalScore
+	 * @return
+	 */
+
+	@SuppressWarnings("unused")
+	public Double reSetDifficulty(Paper paper, double paperTotalScore) {
+		Double sum = 0.0;
+		List<PaperDetail> paperDetails = paperDetailRepo.findByPaperOrderByNumber(paper);
+		if (paperDetails != null && paperDetails.size() > 0) {
+			for (PaperDetail paperDetail : paperDetails) {
+				// 获取每个大题下面的所有小题
+				List<PaperDetailUnit> paperDetailUnits = paperDetailUnitRepo
+						.findByPaperDetailOrderByNumber(paperDetail);
+				if (paperDetailUnits != null && paperDetailUnits.size() > 0) {
+					for (PaperDetailUnit paperDetailUnit : paperDetailUnits) {
+						// 如果为套题,重新计算难度
+						if (paperDetailUnit.getQuestionType() == QuesStructType.NESTED_ANSWER_QUESTION) {
+							// 重新计算套题的难度,公开度
+							boolean publicity = false;
+							double totalSum = 0d;
+							double totalDou = 0d;
+							for (int i = 0; i < paperDetailUnit.getQuestion().getSubQuestions().size(); i++) {
+								Question subQuestion = paperDetailUnit.getQuestion().getSubQuestions().get(i);
+								// 设置公开度
+								if (subQuestion.getPublicity() == null) {
+									publicity = true;
+								} else {
+									if (subQuestion.getPublicity()) {
+										publicity = true;
+									}
+								}
+								if (subQuestion.getDifficultyDegree() == null) {
+									subQuestion.setDifficultyDegree(0.5);
+								}
+								totalSum = subQuestion.getDifficultyDegree() * paperDetailUnit.getSubScoreList().get(i)
+										+ totalSum;
+								totalDou = paperDetailUnit.getSubScoreList().get(i) + totalDou;
+							}
+
+							BigDecimal b;
+							if (totalDou != 0d) {
+								b = BigDecimal.valueOf(totalSum / totalDou);
+							} else {
+								b = BigDecimal.valueOf(0d);
+							}
+
+							Double difficulty = b.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
+							paperDetailUnit.getQuestion().setDifficultyDegree(difficulty);
+							paperDetailUnit.setScore(totalDou);
+						}
+						// 旧题没有难度值,需要重新赋值
+						if (paperDetailUnit.getQuestion().getDifficultyDegree() == null) {
+							paperDetailUnit.getQuestion().setDifficultyDegree(0.5);
+						}
+						if (paperDetailUnit.getScore() == null) {
+							paperDetailUnit.setScore(0d);
+						}
+						sum = paperDetailUnit.getScore() * paperDetailUnit.getQuestion().getDifficultyDegree() + sum;
+					}
+				}
+			}
+			if (paperTotalScore < 0.1) {
+				return 0.0;
+			}
+			BigDecimal b = BigDecimal.valueOf(sum / paperTotalScore);
+			Double difficulty = b.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
+			return difficulty;
+		}
+		return 0.0;
+	}
+
+	/**
+	 * 重新设置小题number,并返回试卷总分
+	 *
+	 * @param paper
+	 * @return
+	 */
+	private double reSetPaperDetailUnit(Paper paper) {
+		List<PaperDetailUnit> paperDetailUnitAll = paperDetailUnitService.findByPaperAndSort(paper);
+		double totalScore = 0;
+		for (int i = 0; i < paperDetailUnitAll.size(); i++) {
+			PaperDetailUnit unit = paperDetailUnitAll.get(i);
+			if (unit.getScore() != null) {
+				totalScore += unit.getScore();
+			}
+			unit.setNumber(i + 1);
+		}
+		paperDetailUnitRepo.saveAll(paperDetailUnitAll);
+		totalScore = CommonUtils.formatDouble(totalScore);
+		return totalScore;
+	}
+
+	/**
+	 * 重新计算大题的总分和小题总数
+	 *
+	 * @param paper
+	 */
+	private Map<String, Object> reSetPaperDetail(Paper paper) {
+		Map<String, Object> paperInfoMap = new HashMap<>();
+		int allQuesCount = 0;
+		List<PaperDetail> paperDetails = paperDetailRepo.findByPaperOrderByNumber(paper);
+		// 计算各大题总分和小题数量
+		for (PaperDetail paperDetail : paperDetails) {
+			List<PaperDetailUnit> paperDetailUnits = paperDetailUnitRepo.findByPaperDetailOrderByNumber(paperDetail);
+			if (paperDetailUnits.size() > 0) {
+				int count = 0;
+				double score = 0;
+				int nestQusNum = 0;
+				for (PaperDetailUnit unit : paperDetailUnits) {
+					if (unit.getScore() != null) {
+						score += unit.getScore();
+					}
+					if (unit.getQuestion() != null && unit.getQuestion().getSubQuestions() != null
+							&& unit.getQuestion().getSubQuestions().size() > 0) {
+						nestQusNum += unit.getQuestion().getSubQuestions().size() - 1;
+					}
+				}
+				count = paperDetailUnits.size() + nestQusNum;
+				score = CommonUtils.formatDouble(score);
+				paperDetail.setScore(score);
+				paperDetail.setUnitCount(count);
+				allQuesCount += count;
+			} else {
+				paperDetail.setScore(0d);
+			}
+		}
+		paperDetailRepo.saveAll(paperDetails);
+		paperInfoMap.put("allQuesCount", allQuesCount);
+		paperInfoMap.put("paperDetails", paperDetails);
+		return paperInfoMap;
+	}
+
+	/**
+	 * 重新设置试卷大题数量、小题数量、试卷总分等属性
+	 *
+	 * @param paper
+	 * @param user
+	 * @param paperInfoMap
+	 * @param paperTotalScore
+	 */
+	@SuppressWarnings("unchecked")
+	private void reSetPaper(Paper paper, User user, Map<String, Object> paperInfoMap, double paperTotalScore) {
+		List<PaperDetail> paperDetails = (List<PaperDetail>) paperInfoMap.get("paperDetails");
+		paper.setPaperDetailCount(paperDetails.size());// 设置大题数量
+		paper.setUnitCount(Integer.parseInt(paperInfoMap.get("allQuesCount") + ""));// 设置小题数量
+		paper.setTotalScore(paperTotalScore);// 设置试卷总分
+		if (user != null) {
+			paper.setLastModifyName(user.getDisplayName());
+		}
+		paperRepo.save(paper);
+
+		// 清除缓存
+		this.clearPaperCache(paper.getId());
+	}
+
+	/**
+	 * 先备份准备删掉的试题,然后再删掉
+	 *
+	 * @param questionId
+	 * @return
+	 */
+	public void deleteImportQuestionById(String detailUnitId, String questionId, User user) {
+		if(randomPaperQuestionService.existQuestion(questionId)) {
+        	throw new StatusException("该试题已被抽题模板使用,不能删除");
+        }
+		PaperDetailUnit paperDetailUnit = null;
+		if (detailUnitId != null) {
+			paperDetailUnit = Model.of(paperDetailUnitRepo.findById(detailUnitId));
+			Paper paper = paperDetailUnit.getPaper();
+			if (paper.getInUse() != null && paper.getInUse() == 1) {
+				throw new StatusException("500", "试卷已调用");
+			}
+		}
+		Question ques = Model.of(quesRepo.findById(questionId));
+
+		List<PaperDetailUnit> pdus = CommonUtils.toList(paperDetailUnitRepo.findByQuestion(ques));
+		List<String> paperNames = new ArrayList<>();
+
+		// 需要删除的小题
+		List<PaperDetailUnit> needPdus = new ArrayList<>();
+
+		List<Paper> papers = new ArrayList<>();
+		for (PaperDetailUnit pdu : pdus) {
+			if (pdu.getPaper() != null) {
+				if (!papers.contains(pdu.getPaper())) {
+					papers.add(pdu.getPaper());
+				}
+				if (PaperType.GENERATE == pdu.getPaper().getPaperType()) {
+					paperNames.add(pdu.getPaper().getName());
+				}
+			}
+		}
+		String changInfo = null;
+		if (paperNames.size() == 0) {
+			needPdus.addAll(pdus);// 此试题没有被组卷调用,则可以删除此试题
+			paperDetailUnitRepo.deleteAll(needPdus);
+			quesBakRepo.save(BeanCopierUtil.copyProperties(ques, QuestionBak.class));
+			quesRepo.delete(ques);
+
+			for (Paper paper : papers) {
+				if (paperDetailUnit != null && paperDetailUnit.getPaper().getId().equals(paper.getId())) {
+					Double total = paper.getTotalScore();
+					Integer dc = paper.getPaperDetailCount();
+					Integer uc = paper.getUnitCount();
+					formatPaper(paper, user);
+					changInfo = PaperUtil.getPaperChangeInfo(total, dc, uc, paper);
+				} else {
+					formatPaper(paper, user);
+				}
+			}
+		}
+
+		if (paperDetailUnit != null) {
+			StringBuilder sb = new StringBuilder();
+			sb.append("课程:" + paperDetailUnit.getPaper().getCourse().getName() + "("
+					+ paperDetailUnit.getPaper().getCourse().getCode() + ")");
+			sb.append(" 试卷名称:" + paperDetailUnit.getPaper().getName());
+			sb.append(" 第" + paperDetailUnit.getNumber() + "小题 ");
+			sb.append(changInfo);
+			ReportsUtil.report(new AdminOperateReport(user.getRootOrgId(), user.getUserId(),
+					AdminOperateType.TYPE48.getDesc(), sb.toString()));
+		}
+		if (CollectionUtils.isNotEmpty(paperNames)) {
+			throw new StatusException("该试题被试卷:" + StringUtils.join(paperNames, ",") + "使用,不能删除");
+		}
+	}
+
+	/**
+	 * 向试卷中插入一个试题
+	 *
+	 * @param paperId
+	 * @param paperDetailId
+	 * @return
+	 */
+	public Paper insertQuestionToPaper(String paperId, String paperDetailId, Question question, User user) {
+		Paper paper = Model.of(paperRepo.findById(paperId));
+		question.setOrgId(user.getRootOrgId().toString());
+		question.setCourse(paper.getCourse());
+		question.setCourseNo(paper.getCourse().getCode());// 必须设置,因为部分方法需要courseNo作为查询条件
+		question = quesService.saveQues(question);
+
+		PaperDetail paperDetail = Model.of(paperDetailRepo.findById(paperDetailId));
+		PaperDetailUnit paperDetailUnit = new PaperDetailUnit(paper, paperDetail, question);
+		paperDetailUnit.setPaperType(PaperType.IMPORT);
+		PaperDetailUnit paperDetailUnit2 = paperDetailUnitService.findTopOrderByNumber(paperDetail, "DESC");
+		if (paperDetailUnit2 == null) {
+			paperDetailUnit.setNumber(1);
+		} else {
+			paperDetailUnit.setNumber(paperDetailUnit2.getNumber());// 设置number为大题的最大题号
+		}
+		paperDetailUnitRepo.save(paperDetailUnit);
+		formatPaper(paper, user);
+		return paper;
+	}
+
+	/**
+	 * 获取试题所在的试卷名称
+	 *
+	 * @param questionId
+	 * @return
+	 */
+	public List<String> getPaperNamesByQuestionId(String questionId) {
+		List<String> paperNames = new ArrayList<>();
+		List<PaperDetailUnit> pdus = paperDetailUnitRepo.findByQuestion(Model.of(quesRepo.findById(questionId)));
+		for (PaperDetailUnit pdu : pdus) {
+			paperNames.add(pdu.getPaper().getName());
+		}
+		return paperNames;
+
+	}
+
+	public Page<Question> listQuestionforSelect(String paperId, int curPage, int pageSize, QuesStructType quesType,
+			User user, String quesBody, UserDataRule ud) {
+		Set<String> selectedIds = new HashSet<>();
+		Paper paper = Model.of(paperRepo.findById(paperId));
+		List<PaperDetailUnit> pdus = paperDetailUnitRepo.findByPaperOrderByNumber(paper);
+		for (PaperDetailUnit pdu : pdus) {
+			selectedIds.add(pdu.getQuestion().getId());
+		}
+		return quesService.findByIdExclude(selectedIds, paper.getCourseNo(), quesType, curPage, pageSize,
+				user.getRootOrgId(), quesBody, ud);
+	}
+
+	@SuppressWarnings("unused")
+	public Paper selectQuestionsToPaper(String paperId, String paperDetailId, List<Question> questions, User user) {
+		Paper paper = Model.of(paperRepo.findById(paperId));
+		if (paper.getInUse() != null && paper.getInUse() == 1) {
 			throw new StatusException("500", "试卷已调用");
 		}
-        PaperDetail paperDetail = Model.of(paperDetailRepo.findById(paperDetailId));
-        PaperDetailUnit paperDetailUnit = paperDetailUnitRepo.findTopByPaperDetailOrderByNumberDesc(paperDetail);
-
-        List<PaperDetailUnit> saveUnits = new ArrayList<>();
-        for (Question ques : questions) {
-            PaperDetailUnit pdu = new PaperDetailUnit(paper, paperDetail, ques);
-
-            //如果大题没有小题,取导入的试题分数
-            if (paperDetailUnit == null) {
-                pdu.setNumber(1);
-            } else {
-                pdu.setNumber(paperDetailUnit.getNumber());//设置为大题中最大的number
-            }
-
-            pdu.setScore(ques.getScore() == null ? 0d : ques.getScore());
-
-            //处理套题
-            if (pdu.getQuestionType() == QuesStructType.NESTED_ANSWER_QUESTION) {
-                List<Question> subQuestions = ques.getSubQuestions();
-                List<Double> subScoreList = new ArrayList<>();
-                if (subQuestions != null && subQuestions.size() > 0) {
-                    for (Question subQuestion : subQuestions) {
-                        subScoreList.add(CommonUtils.formatDouble(pdu.getScore() / subQuestions.size()));
-                    }
-                }
-                pdu.setSubScoreListNew(subScoreList);
-            }
-
-            saveUnits.add(pdu);
-        }
+		PaperDetail paperDetail = Model.of(paperDetailRepo.findById(paperDetailId));
+		PaperDetailUnit paperDetailUnit = paperDetailUnitRepo.findTopByPaperDetailOrderByNumberDesc(paperDetail);
+
+		List<PaperDetailUnit> saveUnits = new ArrayList<>();
+		for (Question ques : questions) {
+			PaperDetailUnit pdu = new PaperDetailUnit(paper, paperDetail, ques);
+
+			// 如果大题没有小题,取导入的试题分数
+			if (paperDetailUnit == null) {
+				pdu.setNumber(1);
+			} else {
+				pdu.setNumber(paperDetailUnit.getNumber());// 设置为大题中最大的number
+			}
 
-        paperDetailUnitRepo.saveAll(saveUnits);
-
-        //清除缓存
-        this.clearPaperCache(paper.getId());
-        paper.setAuditStatus(false);
-        Double total = paper.getTotalScore();
-        Integer dc = paper.getPaperDetailCount();
-        Integer uc = paper.getUnitCount();
-        formatPaper(paper, user);
-
-        StringBuilder paperInfo = new StringBuilder();
-        paperInfo.append("课程:" + paper.getCourse().getName() + "(" + paper.getCourse().getCode() + ")");
-        paperInfo.append(" 试卷名称:" + paper.getName());
-        paperInfo.append(" 第" + paperDetail.getNumber() + "大题选题题数:" + questions.size());
-        String changInfo = PaperUtil.getPaperChangeInfo(total, dc, uc, paper);
-        if (changInfo != null) {
-            paperInfo.append(changInfo);
-        }
-        ReportsUtil.report(new AdminOperateReport(user.getRootOrgId(), user.getUserId(), AdminOperateType.TYPE49.getDesc(), paperInfo.toString()));
-        return paper;
-    }
-
-    public boolean checkPaperName(String paperName, String orgId) {
-        List<Paper> paperList = paperRepo.findByNameAndOrgId(paperName, orgId);
-        if (CollectionUtils.isNotEmpty(paperList)) {
-            return true;
-        }
-        return false;
-    }
+			pdu.setScore(ques.getScore() == null ? 0d : ques.getScore());
+
+			// 处理套题
+			if (pdu.getQuestionType() == QuesStructType.NESTED_ANSWER_QUESTION) {
+				List<Question> subQuestions = ques.getSubQuestions();
+				List<Double> subScoreList = new ArrayList<>();
+				if (subQuestions != null && subQuestions.size() > 0) {
+					for (Question subQuestion : subQuestions) {
+						subScoreList.add(CommonUtils.formatDouble(pdu.getScore() / subQuestions.size()));
+					}
+				}
+				pdu.setSubScoreListNew(subScoreList);
+			}
 
-    public void checkPaperNameNew(String paperName, String orgId) throws Exception {
-        List<Paper> paperList = paperRepo.findByNameAndOrgId(paperName, orgId);
-        if (paperList != null && paperList.size() > 0) {
-            throw new PaperException("试卷名称重复,请重新命名");
-        }
-    }
+			saveUnits.add(pdu);
+		}
 
-    public Page<Paper> getPapersNotInIds(PaperSearchInfo paperSearchInfo, String[] ids, int curPage, int pageSize, PaperType paperType,UserDataRule ud) {
-        Set<String> selectedIds = new HashSet<>();
-        for (String id : ids) {
-            selectedIds.add(id);
-        }
-        if (ud.assertEmptyQueryResult()) {
+		paperDetailUnitRepo.saveAll(saveUnits);
+
+		// 清除缓存
+		this.clearPaperCache(paper.getId());
+		paper.setAuditStatus(false);
+		Double total = paper.getTotalScore();
+		Integer dc = paper.getPaperDetailCount();
+		Integer uc = paper.getUnitCount();
+		formatPaper(paper, user);
+
+		StringBuilder paperInfo = new StringBuilder();
+		paperInfo.append("课程:" + paper.getCourse().getName() + "(" + paper.getCourse().getCode() + ")");
+		paperInfo.append(" 试卷名称:" + paper.getName());
+		paperInfo.append(" 第" + paperDetail.getNumber() + "大题选题题数:" + questions.size());
+		String changInfo = PaperUtil.getPaperChangeInfo(total, dc, uc, paper);
+		if (changInfo != null) {
+			paperInfo.append(changInfo);
+		}
+		ReportsUtil.report(new AdminOperateReport(user.getRootOrgId(), user.getUserId(),
+				AdminOperateType.TYPE49.getDesc(), paperInfo.toString()));
+		return paper;
+	}
+
+	public boolean checkPaperName(String paperName, String orgId) {
+		List<Paper> paperList = paperRepo.findByNameAndOrgId(paperName, orgId);
+		if (CollectionUtils.isNotEmpty(paperList)) {
+			return true;
+		}
+		return false;
+	}
+
+	public void checkPaperNameNew(String paperName, String orgId) throws Exception {
+		List<Paper> paperList = paperRepo.findByNameAndOrgId(paperName, orgId);
+		if (paperList != null && paperList.size() > 0) {
+			throw new PaperException("试卷名称重复,请重新命名");
+		}
+	}
+
+	public Page<Paper> getPapersNotInIds(PaperSearchInfo paperSearchInfo, String[] ids, int curPage, int pageSize,
+			PaperType paperType, UserDataRule ud) {
+		Set<String> selectedIds = new HashSet<>();
+		for (String id : ids) {
+			selectedIds.add(id);
+		}
+		if (ud.assertEmptyQueryResult()) {
 			return Page.empty();
 		}
-        Query query = new Query();
-        query.addCriteria(Criteria.where("orgId").is(paperSearchInfo.getOrgId()));
-        if (ud.assertNeedQueryRefIds()) {
+		Query query = new Query();
+		query.addCriteria(Criteria.where("orgId").is(paperSearchInfo.getOrgId()));
+		if (ud.assertNeedQueryRefIds()) {
 			query.addCriteria(Criteria.where("course.id").in(ud.stringRefIds()));
 		}
-        query.addCriteria(Criteria.where("paperType").is(paperType));
-        query.addCriteria(Criteria.where("course.code").is(paperSearchInfo.getCourseNo()));
-        query.addCriteria(Criteria.where("id").nin(selectedIds));
-        if(PaperType.GENERATE.equals(paperType)) {
-        	query.addCriteria(Criteria.where("storage").ne(1));
-        }
-        long total = this.mongoTemplate.count(query, Paper.class);
-        if (total == 0) {
-            return Page.empty();
-        }
+		query.addCriteria(Criteria.where("paperType").is(paperType));
+		query.addCriteria(Criteria.where("course.code").is(paperSearchInfo.getCourseNo()));
+		query.addCriteria(Criteria.where("id").nin(selectedIds));
+		if (PaperType.GENERATE.equals(paperType)) {
+			query.addCriteria(Criteria.where("storage").ne(1));
+		}
+		long total = this.mongoTemplate.count(query, Paper.class);
+		if (total == 0) {
+			return Page.empty();
+		}
 
-        query.with(Sort.by(new Order(Direction.DESC, "createTime")));
-        query.limit(pageSize);
-        query.skip((curPage - 1L) * pageSize);
-        List<Paper> paperList = this.mongoTemplate.find(query, Paper.class);
-        Page<Paper> paperPageList = new PageImpl<Paper>(paperList, PageRequest.of(curPage - 1, pageSize), total);
-        return paperPageList;
-    }
-
-    /**
-     * 使用原卷
-     */
-    public void useBasePaper(String selectedPaperIds, String userId) {
-        Assert.hasLength(selectedPaperIds, "试卷id不能为空!");
-        String[] paperIds = selectedPaperIds.split(",");
-        for (int i = 0; i < paperIds.length; i++) {
-            Paper oldpaper = Model.of(paperRepo.findById(paperIds[i]));
-            List<PaperDetail> paperDetails = paperDetailRepo.findByPaperOrderByNumber(oldpaper);
-            for (PaperDetail paperDetail : paperDetails) {
-                List<PaperDetailUnit> paperDetailUnits = paperDetailUnitService.getUnitsByPaperDetail(paperDetail);
-                paperDetail.setPaperDetailUnits(paperDetailUnits);
-            }
-            //            PaperUtil.sortDetails(paperDetails);
-            oldpaper.setId(null);
-            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
-            String createTime = sdf.format(new Date());
-            oldpaper.setCreateTime(createTime);
-            oldpaper.setCreator(userId);
-            oldpaper.setLastModifyName(userId);
-            oldpaper.setPaperType(PaperType.GENERATE);//试卷类型 修改为组卷
-            oldpaper.setAuditStatus(false);
-            Paper newPaper = paperRepo.save(oldpaper);
-            for (int j = 0; j < paperDetails.size(); j++) {
-                PaperDetail paperDetail = paperDetails.get(j);
-                paperDetail.setNumber(j + 1);
-                List<PaperDetailUnit> paperDetailUnits = paperDetail.getPaperDetailUnits();
-                paperDetail.setPaper(newPaper);//关联新Paper
-                paperDetail.setId(null);
-                paperDetail.setCreateTime(createTime);
-                paperDetail.setCreator(userId);
-                PaperDetail newPaperDetail = paperDetailRepo.save(paperDetail);//保存新的paperDetail
-                for (int k = 0; k < paperDetailUnits.size(); k++) {
-                    //重新设置保存PaperDetailUnit
-                    PaperDetailUnit paperDetailUnit = paperDetailUnits.get(k);
-                    paperDetailUnit.setPaper(newPaper);                //关联新Paper
-                    paperDetailUnit.setPaperDetail(newPaperDetail); //关联新paperDetail
-                    paperDetailUnit.setId(null);
-                    paperDetailUnit.setCreateTime(createTime);
-                    paperDetailUnit.setCreator(userId);
-                    paperDetailUnit.setPaperType(PaperType.GENERATE);
-                    paperDetailUnitRepo.save(paperDetailUnit);//保存新的paperDetailUnit
-                }
-            }
-        }
-    }
-
-    /**
-     * 根据试卷名称、试卷类型检查名称是否存在
-     *
-     * @param paperName
-     * @param paperType
-     * @param orgId
-     * @return
-     * @throws Exception
-     */
-    public boolean checkPaperName(String paperName, PaperType paperType, String orgId) throws Exception {
-        Query query = new Query();
-        query.addCriteria(Criteria.where("orgId").is(orgId));
-        query.addCriteria(Criteria.where("name").is(paperName.trim()));
-        query.addCriteria(Criteria.where("paperType").is(paperType));
-        List<Paper> papers = this.mongoTemplate.find(query, Paper.class);
-        if (papers != null && papers.size() > 0) {
-            return false;
-        }
-        return true;
-    }
-
-    /**
-     * 上传音频文件检查
-     *
-     * @param paperId
-     * @param filesName
-     * @return
-     */
-    public Map<String, String> checkRadioFile(String paperId, List<String> filesName) {
-        Map<String, String> messageMap = new HashMap<>();
-        //判断文件名中格式是否正确
-        for (String fileName : filesName) {
-            String[] fileNames = fileName.split("\\.");
-            String fileType = fileNames[fileNames.length - 1];
-            if (sysProperty.getRadioType().indexOf(fileType) < 0) {
-                messageMap.put("errorMsg", fileName + ",文件格式不正确,当前支持格式:" + sysProperty.getRadioType());
-                return messageMap;
-            }
-
-            String pattern_01 = "\\d+_1_\\d{1,2}";                //题干正则
-            String pattern_02 = "\\d+_2_[A-Z|a-z]_\\d{1,2}";    //选项正则
-            if (!(Pattern.matches(pattern_01, fileNames[0]) || Pattern.matches(pattern_02, fileNames[0]))) {
-                messageMap.put("errorMsg", fileName + "文件名格式不正确,请检查");
-                return messageMap;
-            }
-        }
+		query.with(Sort.by(new Order(Direction.DESC, "createTime")));
+		query.limit(pageSize);
+		query.skip((curPage - 1L) * pageSize);
+		List<Paper> paperList = this.mongoTemplate.find(query, Paper.class);
+		Page<Paper> paperPageList = new PageImpl<Paper>(paperList, PageRequest.of(curPage - 1, pageSize), total);
+		return paperPageList;
+	}
 
-        //根据试卷id,查询该试卷
-        Paper paper = Model.of(paperRepo.findById(paperId));
+	/**
+	 * 使用原卷
+	 */
+	public void useBasePaper(String selectedPaperIds, String userId) {
+		Assert.hasLength(selectedPaperIds, "试卷id不能为空!");
+		String[] paperIds = selectedPaperIds.split(",");
+		for (int i = 0; i < paperIds.length; i++) {
+			Paper oldpaper = Model.of(paperRepo.findById(paperIds[i]));
+			List<PaperDetail> paperDetails = paperDetailRepo.findByPaperOrderByNumber(oldpaper);
+			for (PaperDetail paperDetail : paperDetails) {
+				List<PaperDetailUnit> paperDetailUnits = paperDetailUnitService.getUnitsByPaperDetail(paperDetail);
+				paperDetail.setPaperDetailUnits(paperDetailUnits);
+			}
+			// PaperUtil.sortDetails(paperDetails);
+			oldpaper.setId(null);
+			SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+			String createTime = sdf.format(new Date());
+			oldpaper.setCreateTime(createTime);
+			oldpaper.setCreator(userId);
+			oldpaper.setLastModifyName(userId);
+			oldpaper.setPaperType(PaperType.GENERATE);// 试卷类型 修改为组卷
+			oldpaper.setAuditStatus(false);
+			Paper newPaper = paperRepo.save(oldpaper);
+			for (int j = 0; j < paperDetails.size(); j++) {
+				PaperDetail paperDetail = paperDetails.get(j);
+				paperDetail.setNumber(j + 1);
+				List<PaperDetailUnit> paperDetailUnits = paperDetail.getPaperDetailUnits();
+				paperDetail.setPaper(newPaper);// 关联新Paper
+				paperDetail.setId(null);
+				paperDetail.setCreateTime(createTime);
+				paperDetail.setCreator(userId);
+				PaperDetail newPaperDetail = paperDetailRepo.save(paperDetail);// 保存新的paperDetail
+				for (int k = 0; k < paperDetailUnits.size(); k++) {
+					// 重新设置保存PaperDetailUnit
+					PaperDetailUnit paperDetailUnit = paperDetailUnits.get(k);
+					paperDetailUnit.setPaper(newPaper); // 关联新Paper
+					paperDetailUnit.setPaperDetail(newPaperDetail); // 关联新paperDetail
+					paperDetailUnit.setId(null);
+					paperDetailUnit.setCreateTime(createTime);
+					paperDetailUnit.setCreator(userId);
+					paperDetailUnit.setPaperType(PaperType.GENERATE);
+					paperDetailUnitRepo.save(paperDetailUnit);// 保存新的paperDetailUnit
+				}
+			}
+		}
+	}
 
-        //根据试卷查询所有的小题
-        List<PaperDetailUnit> paperDetailUnits = paperDetailUnitRepo.findByPaperOrderByNumber(paper);
+	/**
+	 * 根据试卷名称、试卷类型检查名称是否存在
+	 *
+	 * @param paperName
+	 * @param paperType
+	 * @param orgId
+	 * @return
+	 * @throws Exception
+	 */
+	public boolean checkPaperName(String paperName, PaperType paperType, String orgId) throws Exception {
+		Query query = new Query();
+		query.addCriteria(Criteria.where("orgId").is(orgId));
+		query.addCriteria(Criteria.where("name").is(paperName.trim()));
+		query.addCriteria(Criteria.where("paperType").is(paperType));
+		List<Paper> papers = this.mongoTemplate.find(query, Paper.class);
+		if (papers != null && papers.size() > 0) {
+			return false;
+		}
+		return true;
+	}
 
-        String names = "";
-        for (PaperDetailUnit paperDetailUnit : paperDetailUnits) {
-            names = names + paperDetailUnit.getNumber().toString() + ",";
-        }
+	/**
+	 * 上传音频文件检查
+	 *
+	 * @param paperId
+	 * @param filesName
+	 * @return
+	 */
+	public Map<String, String> checkRadioFile(String paperId, List<String> filesName) {
+		Map<String, String> messageMap = new HashMap<>();
+		// 判断文件名中格式是否正确
+		for (String fileName : filesName) {
+			String[] fileNames = fileName.split("\\.");
+			String fileType = fileNames[fileNames.length - 1];
+			if (sysProperty.getRadioType().indexOf(fileType) < 0) {
+				messageMap.put("errorMsg", fileName + ",文件格式不正确,当前支持格式:" + sysProperty.getRadioType());
+				return messageMap;
+			}
 
-        for (String fileName : filesName) {
-            String fileNames[] = fileName.split("_");
-
-            //先判断小题号是否正确
-            String fileNameFirst = fileNames[0];
-            if (!names.contains(fileNameFirst)) {
-                messageMap.put("errorMsg", fileName + "文件,试卷中没有对应的小题");
-                return messageMap;
-            }
-
-            //再判断题干中是否存在ABCD
-            String fileNameSecond = fileNames[1];
-            if (fileNameSecond.equals("1")) {
-                if (fileNames.length > 3) {
-                    Matcher m = Pattern.compile(".*[a-zA-Z]+.*").matcher(fileNames[2]);
-                    if (m.matches()) {
-                        messageMap.put("errorMsg", fileName + "文件名称不对,文件名为题干,但存在选项");
-                        return messageMap;
-                    }
-                }
-            }
-
-            //判断选项
-            else if (fileNameSecond.equals("2")) {
-                messageMap = checkOptions(paperDetailUnits, fileNames, fileName);
-                if (messageMap != null) {
-                    return messageMap;
-                }
-                messageMap = new HashMap<>();
-            } else {
-                messageMap.put("errorMsg", fileName + "文件名称不对,无法识别为题干或选项 ");
-                return messageMap;
-            }
-        }
+			String pattern_01 = "\\d+_1_\\d{1,2}"; // 题干正则
+			String pattern_02 = "\\d+_2_[A-Z|a-z]_\\d{1,2}"; // 选项正则
+			if (!(Pattern.matches(pattern_01, fileNames[0]) || Pattern.matches(pattern_02, fileNames[0]))) {
+				messageMap.put("errorMsg", fileName + "文件名格式不正确,请检查");
+				return messageMap;
+			}
+		}
 
-        messageMap.put("errorMsg", "OK");
-        return messageMap;
-    }
-
-    //判断选项
-    public Map<String, String> checkOptions(List<PaperDetailUnit> paperDetailUnits, String fileNames[], String fileName) {
-        Map<String, String> messageMap = new HashMap<>();
-        for (PaperDetailUnit paperDetailUnit : paperDetailUnits) {
-            if (paperDetailUnit.getNumber().toString().equals(fileNames[0])) {
-                //判断是否为选择题
-                if (paperDetailUnit.getQuestionType() != QuesStructType.SINGLE_ANSWER_QUESTION
-                        && paperDetailUnit.getQuestionType() != QuesStructType.MULTIPLE_ANSWER_QUESTION) {
-                    Matcher m = Pattern.compile(".*[a-zA-Z]+.*").matcher(fileNames[2]);
-                    if (m.matches()) {
-                        messageMap.put("errorMsg", fileName + "文件名称有误,题目不是选择题");
-                        return messageMap;
-                    }
-                    break;
-                } else {
-                    List<QuesOption> options = paperDetailUnit.getQuestion().getQuesOptions();
-                    String option = "";
-                    for (QuesOption quesOption : options) {
-                        option = option + quesOption.getNumber() + ",";
-                    }
-                    Integer integer = CommonUtils.characterToNumber(fileNames[2]);
-                    if (!option.contains(integer.toString())) {
-                        messageMap.put("errorMsg", fileName + "文件名称有误,题目中没有对应的" + fileNames[2] + "选项");
-                        return messageMap;
-                    }
-                    break;
-                }
-            }
-        }
-        return null;
-    }
-
-    /**
-     * 上传音频文件到又拍云
-     *
-     * @param files
-     * @param paperId
-     * @throws IOException
-     */
-    public void uploadRadio(List<MultipartFile> files, String paperId, User user) {
-        //根据试卷id,查询该试卷
-        Paper paper = Model.of(paperRepo.findById(paperId));
-
-        for (MultipartFile file : files) {
-            //判断文件大小
-            long fileSize = file.getSize();
-            int size = Integer.parseInt(sysProperty.getAudioMaxsize());
-            if (fileSize > (size * 1048576L)) {
-                throw new StatusException("400", "音频文件过大,限制" + size + "M内!");
-            }
-
-            //根据试卷查询所有的小题,根据文件名匹配出当前小题ID
-            String numbers[] = file.getOriginalFilename().split("_");
-            if (numbers.length < 3) {
-                throw new StatusException("400", "音频文件命名格式错误!");
-            }
-
-            PaperDetailUnit unit = paperDetailUnitRepo.findByPaperAndNumber(paper, Integer.valueOf(numbers[0]));
-            if (unit == null || unit.getQuestion() == null) {
-                throw new StatusException("400", "对应试题不存在!");
-            }
-
-            Question question = unit.getQuestion();
-            uploadAudioFile(paperId, question.getId(), file, user);
-            appendAudioTag(file.getOriginalFilename(), question.getId());
-
-            //清除缓存
-            this.clearQuestionCache(question.getId());
-        }
+		// 根据试卷id,查询该试卷
+		Paper paper = Model.of(paperRepo.findById(paperId));
 
-        //删除服务器文件夹
-        String mp3DirectoryPath = TEMP_FILE_EXP + File.separator + paperId;
-        try {
-            File mp3Directory = new File(mp3DirectoryPath);
-            FileUtils.deleteDirectory(mp3Directory);
-        } catch (IOException e) {
-            LOG.error(e.getMessage(), e);
-        }
-    }
-
-    /**
-     * 上传音频文件至又拍云
-     */
-    private void uploadAudioFile(String paperId, String questionId, MultipartFile file, User user) {
-        //文件夹不存在则新建
-        final String mp3DirectoryPath = TEMP_FILE_EXP + File.separator + paperId;
-        File mp3Directory = new File(mp3DirectoryPath);
-        if (!mp3Directory.exists()) {
-            mp3Directory.mkdirs();
-        }
+		// 根据试卷查询所有的小题
+		List<PaperDetailUnit> paperDetailUnits = paperDetailUnitRepo.findByPaperOrderByNumber(paper);
 
-        //文件名包含随机数,防止缓存
-        int randomNumber = random.nextInt(1000);
-        final String mp3FileName = questionId + "_" + randomNumber + "_" + file.getOriginalFilename();
-        File mp3File = new File(mp3DirectoryPath + File.separator + mp3FileName);
-
-        FileOutputStream outputStream;
-        try {
-            outputStream = new FileOutputStream(mp3File);
-        } catch (FileNotFoundException e) {
-            LOG.error(e.getMessage(), e);
-            throw new StatusException("500", "音频文件处理失败!");
-        }
+		String names = "";
+		for (PaperDetailUnit paperDetailUnit : paperDetailUnits) {
+			names = names + paperDetailUnit.getNumber().toString() + ",";
+		}
 
-        try (InputStream is = file.getInputStream();
-             BufferedInputStream bis = new BufferedInputStream(is, 1024 * 10);) {
-            int read;
-            byte[] bytes = new byte[1024 * 4];
-            while ((read = bis.read(bytes, 0, 1024 * 4)) != -1) {
-                outputStream.write(bytes, 0, read);
-            }
-
-            //上传到又拍云
-            //            UpYun upYun = new UpYun(sysProperty.getBucketName(), sysProperty.getUserName(), sysProperty.getPassword());
-            //            upYun.writeFile(sysProperty.getRadioUploadPath() + mp3FileName, mp3File, true);
-            //通用存储
-            FileStoragePathEnvInfo env = new FileStoragePathEnvInfo();
-            env.setRelativePath(sysProperty.getRadioUploadPath() + mp3FileName);
-            YunPathInfo pi = FileStorageUtil.saveFile("audioFile", env, mp3File, null);
-            IoUtils.removeFile(mp3File);
-
-            //保存记录
-            QuestionAudio audio = new QuestionAudio(questionId, file.getOriginalFilename(), pi.getRelativePath());
-            questionAudioService.saveQuestionAudio(audio, user);
-        } catch (Exception e) {
-            LOG.error(e.getMessage(), e);
-            throw new StatusException("500", "音频文件保存失败!");
-        } finally {
-            try {
-                if (outputStream != null) {
-                    outputStream.close();
-                }
-            } catch (IOException e) {
-                //ignore
-            }
-        }
-    }
-
-    /**
-     * 音频文件插入到标签
-     */
-    private void appendAudioTag(String fileName, String questionId) {
-        QuestionAudio questionAudio = questionAudioService.findByQuestionIdAndFileName(questionId, fileName);
-        if (questionAudio == null) {
-            return;
-        }
+		for (String fileName : filesName) {
+			String fileNames[] = fileName.split("_");
+
+			// 先判断小题号是否正确
+			String fileNameFirst = fileNames[0];
+			if (!names.contains(fileNameFirst)) {
+				messageMap.put("errorMsg", fileName + "文件,试卷中没有对应的小题");
+				return messageMap;
+			}
 
-        Question question = Model.of(quesRepo.findById(questionAudio.getQuestionId()));
+			// 再判断题干中是否存在ABCD
+			String fileNameSecond = fileNames[1];
+			if (fileNameSecond.equals("1")) {
+				if (fileNames.length > 3) {
+					Matcher m = Pattern.compile(".*[a-zA-Z]+.*").matcher(fileNames[2]);
+					if (m.matches()) {
+						messageMap.put("errorMsg", fileName + "文件名称不对,文件名为题干,但存在选项");
+						return messageMap;
+					}
+				}
+			}
+
+			// 判断选项
+			else if (fileNameSecond.equals("2")) {
+				messageMap = checkOptions(paperDetailUnits, fileNames, fileName);
+				if (messageMap != null) {
+					return messageMap;
+				}
+				messageMap = new HashMap<>();
+			} else {
+				messageMap.put("errorMsg", fileName + "文件名称不对,无法识别为题干或选项 ");
+				return messageMap;
+			}
+		}
 
-        //正则匹配音频标签
-        Pattern audioPattern = Pattern.compile(String.format("<a id=\"[\\d,\\w]+\" name=\"%s\"></a>", fileName));
+		messageMap.put("errorMsg", "OK");
+		return messageMap;
+	}
+
+	// 判断选项
+	public Map<String, String> checkOptions(List<PaperDetailUnit> paperDetailUnits, String fileNames[],
+			String fileName) {
+		Map<String, String> messageMap = new HashMap<>();
+		for (PaperDetailUnit paperDetailUnit : paperDetailUnits) {
+			if (paperDetailUnit.getNumber().toString().equals(fileNames[0])) {
+				// 判断是否为选择题
+				if (paperDetailUnit.getQuestionType() != QuesStructType.SINGLE_ANSWER_QUESTION
+						&& paperDetailUnit.getQuestionType() != QuesStructType.MULTIPLE_ANSWER_QUESTION) {
+					Matcher m = Pattern.compile(".*[a-zA-Z]+.*").matcher(fileNames[2]);
+					if (m.matches()) {
+						messageMap.put("errorMsg", fileName + "文件名称有误,题目不是选择题");
+						return messageMap;
+					}
+					break;
+				} else {
+					List<QuesOption> options = paperDetailUnit.getQuestion().getQuesOptions();
+					String option = "";
+					for (QuesOption quesOption : options) {
+						option = option + quesOption.getNumber() + ",";
+					}
+					Integer integer = CommonUtils.characterToNumber(fileNames[2]);
+					if (!option.contains(integer.toString())) {
+						messageMap.put("errorMsg", fileName + "文件名称有误,题目中没有对应的" + fileNames[2] + "选项");
+						return messageMap;
+					}
+					break;
+				}
+			}
+		}
+		return null;
+	}
+
+	/**
+	 * 上传音频文件到又拍云
+	 *
+	 * @param files
+	 * @param paperId
+	 * @throws IOException
+	 */
+	public void uploadRadio(List<MultipartFile> files, String paperId, User user) {
+		// 根据试卷id,查询该试卷
+		Paper paper = Model.of(paperRepo.findById(paperId));
+
+		for (MultipartFile file : files) {
+			// 判断文件大小
+			long fileSize = file.getSize();
+			int size = Integer.parseInt(sysProperty.getAudioMaxsize());
+			if (fileSize > (size * 1048576L)) {
+				throw new StatusException("400", "音频文件过大,限制" + size + "M内!");
+			}
+
+			// 根据试卷查询所有的小题,根据文件名匹配出当前小题ID
+			String numbers[] = file.getOriginalFilename().split("_");
+			if (numbers.length < 3) {
+				throw new StatusException("400", "音频文件命名格式错误!");
+			}
+
+			PaperDetailUnit unit = paperDetailUnitRepo.findByPaperAndNumber(paper, Integer.valueOf(numbers[0]));
+			if (unit == null || unit.getQuestion() == null) {
+				throw new StatusException("400", "对应试题不存在!");
+			}
+
+			Question question = unit.getQuestion();
+			uploadAudioFile(paperId, question.getId(), file, user);
+			appendAudioTag(file.getOriginalFilename(), question.getId());
+
+			// 清除缓存
+			this.clearQuestionCache(question.getId());
+		}
+
+		// 删除服务器文件夹
+		String mp3DirectoryPath = TEMP_FILE_EXP + File.separator + paperId;
+		try {
+			File mp3Directory = new File(mp3DirectoryPath);
+			FileUtils.deleteDirectory(mp3Directory);
+		} catch (IOException e) {
+			LOG.error(e.getMessage(), e);
+		}
+	}
+
+	/**
+	 * 上传音频文件至又拍云
+	 */
+	private void uploadAudioFile(String paperId, String questionId, MultipartFile file, User user) {
+		// 文件夹不存在则新建
+		final String mp3DirectoryPath = TEMP_FILE_EXP + File.separator + paperId;
+		File mp3Directory = new File(mp3DirectoryPath);
+		if (!mp3Directory.exists()) {
+			mp3Directory.mkdirs();
+		}
+
+		// 文件名包含随机数,防止缓存
+		int randomNumber = random.nextInt(1000);
+		final String mp3FileName = questionId + "_" + randomNumber + "_" + file.getOriginalFilename();
+		File mp3File = new File(mp3DirectoryPath + File.separator + mp3FileName);
+
+		FileOutputStream outputStream;
+		try {
+			outputStream = new FileOutputStream(mp3File);
+		} catch (FileNotFoundException e) {
+			LOG.error(e.getMessage(), e);
+			throw new StatusException("500", "音频文件处理失败!");
+		}
+
+		try (InputStream is = file.getInputStream();
+				BufferedInputStream bis = new BufferedInputStream(is, 1024 * 10);) {
+			int read;
+			byte[] bytes = new byte[1024 * 4];
+			while ((read = bis.read(bytes, 0, 1024 * 4)) != -1) {
+				outputStream.write(bytes, 0, read);
+			}
+
+			// 上传到又拍云
+			// UpYun upYun = new UpYun(sysProperty.getBucketName(),
+			// sysProperty.getUserName(), sysProperty.getPassword());
+			// upYun.writeFile(sysProperty.getRadioUploadPath() + mp3FileName, mp3File,
+			// true);
+			// 通用存储
+			FileStoragePathEnvInfo env = new FileStoragePathEnvInfo();
+			env.setRelativePath(sysProperty.getRadioUploadPath() + mp3FileName);
+			YunPathInfo pi = FileStorageUtil.saveFile("audioFile", env, mp3File, null);
+			IoUtils.removeFile(mp3File);
+
+			// 保存记录
+			QuestionAudio audio = new QuestionAudio(questionId, file.getOriginalFilename(), pi.getRelativePath());
+			questionAudioService.saveQuestionAudio(audio, user);
+		} catch (Exception e) {
+			LOG.error(e.getMessage(), e);
+			throw new StatusException("500", "音频文件保存失败!");
+		} finally {
+			try {
+				if (outputStream != null) {
+					outputStream.close();
+				}
+			} catch (IOException e) {
+				// ignore
+			}
+		}
+	}
+
+	/**
+	 * 音频文件插入到标签
+	 */
+	private void appendAudioTag(String fileName, String questionId) {
+		QuestionAudio questionAudio = questionAudioService.findByQuestionIdAndFileName(questionId, fileName);
+		if (questionAudio == null) {
+			return;
+		}
+
+		Question question = Model.of(quesRepo.findById(questionAudio.getQuestionId()));
+
+		// 正则匹配音频标签
+		Pattern audioPattern = Pattern.compile(String.format("<a id=\"[\\d,\\w]+\" name=\"%s\"></a>", fileName));
 		final String audioTag = String.format("<a id=\"%s\" name=\"%s\"></a>", questionAudio.getId(), fileName);
 
-        String numbers[] = fileName.split("_");
-        if (numbers[1].equals("1")) {
-            //处理题干
-            String quesBody = question.getQuesBody();
-            if (StringUtils.isBlank(quesBody)) {
-                question.setQuesBody("<p>" + audioTag + "</p>");
-            } else {
-                Matcher matcher = audioPattern.matcher(quesBody);
-                if (matcher.find()) {
-                    //已存在音频标签则直接替换
-                    question.setQuesBody(matcher.replaceAll(audioTag));
-                } else {
-                    //不存在音频标签则添加
-                    question.setQuesBody(quesBody + "<p>" + audioTag + "</p>");
-                }
-            }
-        } else {
-            //处理选项
-            for (QuesOption quesOption : question.getQuesOptions()) {
-                Integer optNumber = CommonUtils.characterToNumber(numbers[2]);
-                if (!quesOption.getNumber().equals(optNumber.toString())) {
-                    continue;
-                }
-
-                String optionBody = quesOption.getOptionBody();
-                if (StringUtils.isBlank(optionBody)) {
-                    quesOption.setOptionBody("<p>" + audioTag + "</p>");
-                    continue;
-                }
-
-                Matcher matcher = audioPattern.matcher(optionBody);
-                if (matcher.find()) {
-                    //已存在音频标签则直接替换
-                    quesOption.setOptionBody(matcher.replaceAll(audioTag));
-                } else {
-                    //不存在音频标签则添加
-                    quesOption.setOptionBody(optionBody + "<p>" + audioTag + "</p>");
-                }
-            }
-        }
+		String numbers[] = fileName.split("_");
+		if (numbers[1].equals("1")) {
+			// 处理题干
+			String quesBody = question.getQuesBody();
+			if (StringUtils.isBlank(quesBody)) {
+				question.setQuesBody("<p>" + audioTag + "</p>");
+			} else {
+				Matcher matcher = audioPattern.matcher(quesBody);
+				if (matcher.find()) {
+					// 已存在音频标签则直接替换
+					question.setQuesBody(matcher.replaceAll(audioTag));
+				} else {
+					// 不存在音频标签则添加
+					question.setQuesBody(quesBody + "<p>" + audioTag + "</p>");
+				}
+			}
+		} else {
+			// 处理选项
+			for (QuesOption quesOption : question.getQuesOptions()) {
+				Integer optNumber = CommonUtils.characterToNumber(numbers[2]);
+				if (!quesOption.getNumber().equals(optNumber.toString())) {
+					continue;
+				}
+
+				String optionBody = quesOption.getOptionBody();
+				if (StringUtils.isBlank(optionBody)) {
+					quesOption.setOptionBody("<p>" + audioTag + "</p>");
+					continue;
+				}
+
+				Matcher matcher = audioPattern.matcher(optionBody);
+				if (matcher.find()) {
+					// 已存在音频标签则直接替换
+					quesOption.setOptionBody(matcher.replaceAll(audioTag));
+				} else {
+					// 不存在音频标签则添加
+					quesOption.setOptionBody(optionBody + "<p>" + audioTag + "</p>");
+				}
+			}
+		}
 
-        question.setHasAudio(true);
-        quesRepo.save(question);
-    }
-
-    @Override
-    public Map<String, Object> getPaperPDF(String paperId, String type) {
-        PaperExp paperExp = getPaperDto(paperId);
-        Map<String, Object> map = new HashMap<>();
-        map.put("courseName", paperExp.getCourseName());
-        map.put("courseNo", paperExp.getCourseNo());
-        List<String> htmlList = new ArrayList<>();
-        if (paperExp.getPaperDetails() != null && paperExp.getPaperDetails().size() > 0) {
-            for (PaperDetailExp paperDetail : paperExp.getPaperDetails()) {
-                //添加大题标题
-                if (StringUtils.isBlank(paperDetail.getTitle())) {
-                    //htmlList.add(("<p>"+paperDetail.getCnNum()+"、"+paperDetail.getName()+"</p>").replaceAll("'", "&apos"));
-                    htmlList.add(("<p class='paperDetailTitle'>" + paperDetail.getCnNum() + "、" + paperDetail.getName() + "</p>").replaceAll("'", "&apos"));
-                } else {
-                    htmlList.add("<p class='paperDetailTitle'>" + paperDetail.getCnNum() + "、" + paperDetail.getName() + paperDetail.getTitle() + "</p>");
-                }
-                if (paperDetail.getPaperDetailUnits() != null && paperDetail.getPaperDetailUnits().size() > 0) {
-                    for (PaperDetailUnitExp paperDetailUnitExp : paperDetail.getPaperDetailUnits()) {
-                        Question question = paperDetailUnitExp.getQuestion();
-                        if (type.equals("paper")) {
-                            //添加题干
-                            String questionBody = CommonUtils.deleteHtmlP(paperDetailUnitExp.getNumber() + "." + question.getQuesBody() + "(" + paperDetailUnitExp.getScore() + "分)");
-                            htmlList.add("<p class='questionBody'>" + questionBody + "</p>");
-                            //判断是否为选择题
-                            if (paperDetailUnitExp.getQuestionType() == QuesStructType.SINGLE_ANSWER_QUESTION || paperDetailUnitExp.getQuestionType() == QuesStructType.MULTIPLE_ANSWER_QUESTION) {
-                                for (QuesOption quesOption : question.getQuesOptions()) {
-                                    //添加选项
-                                    String questionOption = CommonUtils.deleteHtmlP(CommonUtils.getOptionNum(Integer.parseInt(quesOption.getNumber()) - 1) + "." + quesOption.getOptionBody());
-                                    htmlList.add("<p class='selectOption'>" + questionOption + "</p>");
-                                }
-                            }
-                            //判断是否为套题
-                            if (paperDetailUnitExp.getQuestionType() == QuesStructType.NESTED_ANSWER_QUESTION) {
-                                //得到子题
-                                List<Question> subQuestions = question.getSubQuestions();
-                                for (Question subQuestion : subQuestions) {
-                                    //添加子题题干
-                                    String subQuestionBody = CommonUtils.deleteHtmlP(subQuestion.getQuesParams().get("number") + "." + subQuestion.getQuesBody() + "(" + subQuestion.getScore() + "分)");
-                                    htmlList.add("<p class='questionBody'>" + subQuestionBody + "</p>");
-                                    //判断是否为选择题
-                                    if (subQuestion.getQuestionType() == QuesStructType.SINGLE_ANSWER_QUESTION || subQuestion.getQuestionType() == QuesStructType.MULTIPLE_ANSWER_QUESTION) {
-                                        for (QuesOption quesOption : subQuestion.getQuesOptions()) {
-                                            //添加选项
-                                            String questionOption = CommonUtils.deleteHtmlP(CommonUtils.getOptionNum(Integer.parseInt(quesOption.getNumber()) - 1) + "." + quesOption.getOptionBody());
-                                            htmlList.add("<p class='selectOption'>" + questionOption + "</p>");
-                                        }
-                                    }
-                                }
-                            }
-                        } else {
-                            //判断是否为套题
-                            if (paperDetailUnitExp.getQuestionType() == QuesStructType.NESTED_ANSWER_QUESTION) {
-                                //得到子题
-                                List<Question> subQuestions = question.getSubQuestions();
-                                for (Question subQuestion : subQuestions) {
-                                    //添加答案
-                                    String questionAnswer = CommonUtils.deleteHtmlP(subQuestion.getQuesParams().get("number") + "." + subQuestion.getQuesAnswer() + "(" + subQuestion.getScore() + "分)");
-                                    htmlList.add("<p class='questionAnswer'>" + questionAnswer + "</p>");
-                                }
-                            } else {
-                                //添加答案
-                                String questionAnswer = CommonUtils.deleteHtmlP(paperDetailUnitExp.getNumber() + "." + question.getQuesAnswer() + "(" + paperDetailUnitExp.getScore() + "分)");
-                                htmlList.add("<p class='questionAnswer'>" + questionAnswer + "</p>");
-                            }
-                        }
-
-                    }
-                }
-            }
-        }
-        map.put("htmlList", htmlList);
-        return map;
-    }
-
-    @SuppressWarnings("unused")
-    @Override
-    public String sendPrint(String paperId, String orgId, String examId) {
-        //查询原paper对象
-        Paper paper = Model.of(paperRepo.findById(paperId));
-        SyncCoursePaperBean bean = new SyncCoursePaperBean();
-        bean.setOrgId(Long.valueOf(orgId));
-        bean.setExamId(Long.valueOf(examId));
-        Course course = courseService.getCourse(Long.valueOf(orgId), paper.getCourse().getCode());
-        bean.setCourseId(Long.valueOf(course.getId()));
-        bean.setCourseCode(paper.getCourse().getCode());
-        bean.setCourseName(paper.getCourse().getName());
-        bean.setPaperId(paper.getId());
-        bean.setPaperName(paper.getName());
-        SyncCoursePaperReq req = new SyncCoursePaperReq();
-        req.setBean(bean);
-        SyncCoursePaperResp resp = coursePaperCloudService.syncCoursePaper(req);
-        return "success";
-    }
-
-    @Override
-    public String findQuestionStructure(String paperId) throws Exception {
-        //根据paperId查询新的对象
-        ExportPaperAbstractService exportPaperAbstractService = (ExportPaperAbstractService) SpringContextHolder.getBean("exportPaperAbstractService");
-        DownloadPaperDto dto = new DownloadPaperDto();
-        dto.setPaperId(paperId);
-        dto.setSeqMode(PaperSeqMode.MODE3);
-        PaperExp paperExp = exportPaperAbstractService.initPaperExp(dto);
-        LOG.info("已经获取试卷");
-        //得到试卷中的客观大题
-        List<PaperDetailExp> objectiveDetails = exportPaperAbstractService.getAllObjectiveDetails(paperExp);
-        //客观题中如果有套题,要拆开
-        List<PaperDetailExp> newObjectiveDetails = buildPaperDetailExp(objectiveDetails);
-        //生成客观题数集合
-        List<ObjectiveQuestionStructure> objectiveQuestionStructureList = new ArrayList<>();
-        for (PaperDetailExp paperDetailExp : newObjectiveDetails) {
-            for (PaperDetailUnitExp unit : paperDetailExp.getPaperDetailUnits()) {
-                objectiveQuestionStructureList.add(new ObjectiveQuestionStructure(paperExp, paperDetailExp, unit, null));
-            }
-        }
-        LOG.info("生成客观题数集合");
-        //得到试卷中的主观大题
-        List<PaperDetailExp> subjectiveDetails = exportPaperAbstractService.getAllSubjectiveDetails(paperExp);
-        //生成主观题数集合
-        List<SubjectiveQuestionStructure> subjectiveQuestionStructureList = new ArrayList<>();
-        for (PaperDetailExp paperDetailExp : subjectiveDetails) {
-            for (PaperDetailUnitExp unit : paperDetailExp.getPaperDetailUnits()) {
-                subjectiveQuestionStructureList.add(new SubjectiveQuestionStructure(paperExp, paperDetailExp, unit, null));
-            }
-        }
-        LOG.info("生成主观题数集合");
-        PaperQuestionStructureInfo info = new PaperQuestionStructureInfo();
-        info.setObjectives(objectiveQuestionStructureList);
-        info.setSubjectives(subjectiveQuestionStructureList);
-        String jsonResp = JsonUtil.toJson(info);
-        LOG.info("jsonResp:" + jsonResp);
-        return jsonResp;
-    }
-
-    public List<PaperDetailExp> buildPaperDetailExp(List<PaperDetailExp> objectiveDetails) {
-        //1.得到所有客观题大题的类型
-        Set<QuesStructType> types = new HashSet<>();
-        for (PaperDetailExp paperDetailExp : objectiveDetails) {
-            types.add(QuesStructType.getQuesStructTypeById(paperDetailExp.getSortNumber()));
-        }
-        //2.生成新的大题集合
-        List<PaperDetailExp> newObjs = new ArrayList<>();
-        for (QuesStructType type : types) {
-            for (PaperDetailExp paperDetailExp : objectiveDetails) {
-                if (paperDetailExp.getSortNumber().equals(type.getId())) {
-                    //生成新的大题
-                    PaperDetailExp newPaperDetailExp = new PaperDetailExp();
-                    //生成新的小题
-                    List<PaperDetailUnitExp> newPaperDetailUnits = new ArrayList<>();
-                    //得到旧大题下的所有小题
-                    List<PaperDetailUnitExp> paperDetailUnits = paperDetailExp.getPaperDetailUnits();
-                    for (PaperDetailUnitExp paperDetailUnitExp : paperDetailUnits) {
-                        if (paperDetailUnitExp.getQuestionType() != QuesStructType.NESTED_ANSWER_QUESTION) {
-                            newPaperDetailUnits.add(paperDetailUnitExp);
-                        } else {
-                            List<Question> subQuestions = paperDetailUnitExp.getQuestion().getSubQuestions();
-                            if (subQuestions != null && subQuestions.size() > 0) {
-                                for (int i = 0; i < subQuestions.size(); i++) {
-                                    newPaperDetailUnits.add(new PaperDetailUnitExp(type, subQuestions.get(i)));
-                                }
-                            }
-                        }
-                    }
-                    //设置小题
-                    newPaperDetailExp.setPaperDetailUnits(newPaperDetailUnits);
-                    //设置大题题号
-                    newPaperDetailExp.setNumber(Integer.parseInt(type.getId() + ""));
-                    newPaperDetailExp.setSortNumber(paperDetailExp.getSortNumber());
-                    newObjs.add(newPaperDetailExp);
-                }
-            }
-        }
-        //刷一遍number
-        int num = 0;
-        for (QuesStructType type : types) {
-            for (int i = 0; i < newObjs.size(); i++) {
-                if (newObjs.get(i).getSortNumber().equals(type.getId())) {
-                    List<PaperDetailUnitExp> exps = newObjs.get(i).getPaperDetailUnits();
-                    for (int j = 0; j < exps.size(); j++) {
-                        num++;
-                        exps.get(j).setNumber(num);
-                    }
-                }
-            }
-        }
-        return newObjs;
-    }
-
-    @Override
-    public PaperExp getDownPaperExp(String paperId) {
-        Paper paper = Model.of(paperRepo.findById(paperId));
-        // 创建paperDto
-        PaperExp paperExp = BeanCopierUtil.copyProperties(paper, PaperExp.class);
-        paperExp.setCourseName(paper.getCourse().getName());
-        paperExp.setCourseNo(paper.getCourse().getCode());
-        paperExp.setCourse(paper.getCourse());
-        // 获取大题
-        List<PaperDetail> paperDetails = paperDetailRepo.findByPaperOrderByNumber(paper);
-        List<PaperDetailExp> paperDetailExps = new ArrayList<>();
-        for (PaperDetail paperDetail : paperDetails) {
-            PaperDetailExp paperDetailExp = new PaperDetailExp();
-            BeanUtils.copyProperties(paperDetail, paperDetailExp);
-            if (StringUtils.isBlank(paperDetailExp.getName())) {
-                paperDetailExp.setName("默认大题");
-            }
-            paperDetailExps.add(paperDetailExp);
-        }
-        // 封装小题
-        for (int i = 0; i < paperDetailExps.size(); i++) {
-            List<PaperDetailUnit> paperDetailUnits = paperDetailUnitRepo.findByPaperDetailOrderByNumber(paperDetails.get(i));
-            if (paperDetailUnits != null && paperDetailUnits.size() > 0) {
-                List<PaperDetailUnitExp> paperDetailUnitExps = new ArrayList<>();
-                for (PaperDetailUnit paperDetailUnit : paperDetailUnits) {
-                    PaperDetailUnitExp paperDetailUnitExp = new PaperDetailUnitExp();
-                    BeanUtils.copyProperties(paperDetailUnit, paperDetailUnitExp);
-                    paperDetailUnitExps.add(paperDetailUnitExp);
-                }
-                paperDetailExps.get(i).setPaperDetailUnits(paperDetailUnitExps);
-                paperDetailExps.get(i).setUnitCount(paperDetailUnitExps.size());
-            } else {
-                paperDetailExps.get(i).setUnitCount(0);
-            }
-        }
-        paperExp.setPaperDetails(paperDetailExps);
-        if (paperExp.getPaperDetails() == null || paperExp.getPaperDetails().size() == 0) {
-            return paperExp;
-        }
-        int mainNum = 0;
-        List<PaperDetailExp> paperDetailExpList = paperExp.getPaperDetails();
-        for (PaperDetailExp paperDetail : paperDetailExpList) {
-            // 大题序号
-            paperDetail.setNumber(++mainNum);
-            paperDetail.setCnNum(CommonUtils.toCHNum(paperDetail.getNumber()));
-            if (paperDetail.getPaperDetailUnits() == null || paperDetail.getPaperDetailUnits().size() == 0) {
-                throw new StatusException("500", "第" + mainNum + "大题没有小题");
-            }
-            if (paperDetail != null && paperDetail.getPaperDetailUnits() != null && paperDetail.getPaperDetailUnits().size() > 0) {
-                for (PaperDetailUnitExp paperDetailUnit : paperDetail.getPaperDetailUnits()) {
-                    Question question = paperDetailUnit.getQuestion();
-                    question.setDifficultyDegree(question.getDifficultyDegree() * 10);
-                    if (question.getPublicity() == null || question.getPublicity() == true) {
-                        paperDetailUnit.setPublicity("公开");
-                    } else {
-                        paperDetailUnit.setPublicity("非公开");
-                    }
-                    if (StringUtils.isBlank(paperDetail.getQuesType())) {
-                        paperDetail.setQuesType(question.getQuestionType().getName());
-                    }
-                    //设置选项
-                    List<QuesOption> optionList = paperDetailUnit.getQuestion().getQuesOptions();
-                    if (optionList != null && optionList.size() > 0) {
-                        //                        int index = 0;
-                        //                        for (QuesOption quesOption : optionList) {
-                        //                            quesOption.setOptionBodyWord(setOptionNum(quesOption.getOptionBodyWord(), getOptionNum(index)));
-                        //                            index++;
-                        //                        }
-                    }
-                    if (question.getQuestionType() != QuesStructType.NESTED_ANSWER_QUESTION) {
-                        //给小题设置序号
-                        //                        question.setQuesBodyWord(setSubQuesNum(question.getQuesBodyWord(), minNum++));
-                        //                        question.setQuesAnswerWord(setAnswerNum(question.getQuesAnswerWord()));
-                    	fillProperty(question);
-                    	if (paperDetail.getFirstScore() == null) {
-                            if (question.getScore() == null) {
-                                paperDetail.setFirstScore(0d);
-                            } else {
-                                paperDetail.setFirstScore(question.getScore());
-                            }
-                        }
-                    } else {
-                        List<Question> subQuesList = question.getSubQuestions();
-                        // 套题小题设置序号
-                        if (subQuesList != null && subQuesList.size() > 0) {
-                            for (Question subQues : subQuesList) {
-                                subQues.setDifficultyDegree(subQues.getDifficultyDegree() * 10);
-                                //                                subQues.setQuesBodyWord(setSubQuesNum(subQues.getQuesBodyWord(), index++));
-                                //                                subQues.setQuesAnswerWord(setAnswerNum(subQues.getQuesAnswerWord()));
-                                if (paperDetail.getFirstScore() == null) {
-                                    if (subQues.getScore() == null) {
-                                        paperDetail.setFirstScore(0d);
-                                    } else {
-                                        paperDetail.setFirstScore(subQues.getScore());
-                                    }
-                                }
-                                fillProperty(subQues);
-                            }
-                        }
-                    }
-                    List<QuesProperty> quesProperties = question.getQuesProperties();
-                    if (quesProperties != null && quesProperties.size() > 0) {
-                        QuesProperty quesProperty = quesProperties.get(0);
-                        if (quesProperty.getFirstProperty() != null) {
-                            paperDetailUnit.setFirstName(quesProperty.getFirstProperty().getName());
-                            paperDetailUnit.setFirstCode(quesProperty.getFirstProperty().getCode());
-                        }
-                        if (quesProperty.getSecondProperty() != null) {
-                            paperDetailUnit.setSecondName(quesProperty.getSecondProperty().getName());
-                            paperDetailUnit.setSecondCode(quesProperty.getSecondProperty().getCode());
-                        }
-                    }
-                }
-            }
-        }
-        return paperExp;
-    }
-    
-    private void fillProperty(Question question) {
-    	List<QuesProperty> ret=new ArrayList<>();
-    	List<QuesProperty> quesProperties = question.getQuesProperties();
-        if (quesProperties != null && quesProperties.size() > 0) {
-        	for(QuesProperty quesProperty:quesProperties) {
-        		if (quesProperty.getFirstProperty() != null
-						&& quesProperty.getFirstProperty().getId() != null) {
-                	Property curProperty = Model.of(propertyRepo.findById(quesProperty.getFirstProperty().getId()));
-                	if(curProperty==null) {
-                		continue;
-                	}
-                	quesProperty.setFirstProperty(curProperty);
-                }
-                if (quesProperty.getSecondProperty() != null
-						&& quesProperty.getSecondProperty().getId() != null) {
-                	Property curProperty = Model.of(propertyRepo.findById(quesProperty.getSecondProperty().getId()));
-                	if(curProperty==null) {
-                		continue;
-                	}
-                	quesProperty.setSecondProperty(curProperty);
-                }
-                ret.add(quesProperty);
-        	}
-        }
-        question.setQuesProperties(ret);
-    }
-
-    /**
-     * 设置题号
-     *
-     * @param quesBodyWordMl
-     * @param num
-     * @return
-     * @throws Exception
-     */
-    //    public String setSubQuesNum(String quesBodyWordMl, int num) throws Exception {
-    //        String tmpStr = DocxProcessUtil.BODY_HEADER + quesBodyWordMl + DocxProcessUtil.BODY_TAIL;
-    //        Body body = (Body) XmlUtils.unmarshalString(tmpStr, Context.jc, Body.class);
-    //        List<Object> pList = body.getContent();
-    //        int index = 0;
-    //        for (Object pObj : pList) {
-    //            if (index > 0) {
-    //                break;
-    //            }
-    //            P p = (P) pObj;
-    //            List<Object> pContent = p.getContent();
-    //            R run = new R();
-    //            Text text = new Text();
-    //            text.setValue(num + ". ");
-    //            run.getContent().add(text);
-    //            pContent.add(0, run);
-    //            index++;
-    //        }
-    //        StringBuffer pWordMl = new StringBuffer();
-    //        for (Object pObj : pList) {
-    //            if (pObj instanceof P) {
-    //                pWordMl.append(DocxProcessUtil.formatPWordMl(XmlUtils.marshaltoString(pObj)));
-    //            }
-    //        }
-    //        return pWordMl.toString();
-    //    }
-
-    /**
-     * 将数字1,2,3,4转化成A,B,C,D
-     *
-     * @param number
-     * @return
-     */
-    public String getOptionNum(int number) {
-        char optionNum = (char) (65 + number);
-        return String.valueOf(optionNum);
-    }
-
-    /**
-     * 设置选项号
-     *
-     * @param optionWordMl
-     * @param num
-     * @return
-     * @throws Exception
-     */
-    //    public String setOptionNum(String optionWordMl, String num) throws Exception {
-    //        String tmpStr = DocxProcessUtil.BODY_HEADER + optionWordMl + DocxProcessUtil.BODY_TAIL;
-    //        Body body = (Body) XmlUtils.unmarshalString(tmpStr, Context.jc, Body.class);
-    //        List<Object> pList = body.getContent();
-    //        int index = 0;
-    //        for (Object pObj : pList) {
-    //            if (index > 0) {
-    //                break;
-    //            }
-    //            P p = (P) pObj;
-    //            List<Object> pContent = p.getContent();
-    //            R run = new R();
-    //            Text text = new Text();
-    //            text.setValue(num + ". ");
-    //            run.getContent().add(text);
-    //            pContent.add(0, run);
-    //            index++;
-    //        }
-    //        StringBuffer pWordMl = new StringBuffer();
-    //        for (Object pObj : pList) {
-    //            if (pObj instanceof P) {
-    //                pWordMl.append(DocxProcessUtil.formatPWordMl(XmlUtils.marshaltoString(pObj)));
-    //            }
-    //        }
-    //        return pWordMl.toString();
-    //    }
-
-    //    public String setAnswerNum(String quesBodyWordMl) throws Exception {
-    //        String tmpStr = DocxProcessUtil.BODY_HEADER + quesBodyWordMl + DocxProcessUtil.BODY_TAIL;
-    //        Body body = (Body) XmlUtils.unmarshalString(tmpStr, Context.jc, Body.class);
-    //        List<Object> pList = body.getContent();
-    //        int index = 0;
-    //        for (Object pObj : pList) {
-    //            if (index > 0) {
-    //                break;
-    //            }
-    //            P p = (P) pObj;
-    //            List<Object> pContent = p.getContent();
-    //            R run = new R();
-    //            Text text = new Text();
-    //            text.setValue("[答案]:");
-    //            run.getContent().add(text);
-    //            pContent.add(0, run);
-    //            index++;
-    //        }
-    //        StringBuffer pWordMl = new StringBuffer();
-    //        for (Object pObj : pList) {
-    //            if (pObj instanceof P) {
-    //                pWordMl.append(DocxProcessUtil.formatPWordMl(XmlUtils.marshaltoString(pObj)));
-    //            }
-    //        }
-    //        return pWordMl.toString();
-    //    }
-    @Override
-    public int getQuestionTypeNumbers(String paperId, Integer publicityType, Integer difficultyType) {
-        if (publicityType == null || difficultyType == null) {
-            return 0;
-        }
-        Boolean publicity = null;
-        String difficulty = null;
-        if (publicityType == 1) {
-            publicity = true;
-        } else {
-            publicity = false;
-        }
-        if (difficultyType == 1) {
-            difficulty = "易";
-        } else if (difficultyType == 2) {
-            difficulty = "中";
-        } else {
-            difficulty = "难";
-        }
-        String needType = publicity + "-" + difficulty;
-        Paper paper = Model.of(paperRepo.findById(paperId));
-        List<PaperDetailUnit> units = paperDetailUnitRepo.findByPaperOrderByNumber(paper);
-        if (units != null && units.size() > 0) {
-            int total = 0;
-            for (PaperDetailUnit unit : units) {
-                if (unit.getQuestion().getPublicity() == null) {
-                    unit.getQuestion().setPublicity(true);
-                }
-                if (unit.getQuestion().getDifficulty() == null) {
-                    unit.getQuestion().setDifficulty("中");
-                }
-                String factType = unit.getQuestion().getPublicity() + "-" + unit.getQuestion().getDifficulty();
-                if (needType.equals(factType)) {
-                    total += 1;
-                }
-            }
-            return total;
-        }
-        return 0;
-    }
+		question.setHasAudio(true);
+		quesRepo.save(question);
+	}
 
-    @Override
-    public double getQuestionTypeScore(String paperId, Integer publicityType, Integer difficultyType) {
-        if (publicityType == null || difficultyType == null) {
-            return 0;
-        }
-        Boolean publicity = null;
-        String difficulty = null;
-        if (publicityType == 1) {
-            publicity = true;
-        } else {
-            publicity = false;
-        }
-        if (difficultyType == 1) {
-            difficulty = "易";
-        } else if (difficultyType == 2) {
-            difficulty = "中";
-        } else {
-            difficulty = "难";
-        }
-        String needType = publicity + "-" + difficulty;
-        Paper paper = Model.of(paperRepo.findById(paperId));
-        List<PaperDetailUnit> units = paperDetailUnitRepo.findByPaperOrderByNumber(paper);
-        if (units != null && units.size() > 0) {
-            double total = 0;
-            BigDecimal b1 = BigDecimal.valueOf(total);
-            for (PaperDetailUnit unit : units) {
-                if (unit.getQuestion().getPublicity() == null) {
-                    unit.getQuestion().setPublicity(true);
-                }
-                if (unit.getQuestion().getDifficulty() == null) {
-                    unit.getQuestion().setDifficulty("中");
-                }
-                String factType = unit.getQuestion().getPublicity() + "-" + unit.getQuestion().getDifficulty();
-                if (needType.equals(factType)) {
-                    BigDecimal b2 = BigDecimal.valueOf(unit.getScore());
-                    b1 = b1.add(b2);
-                }
-            }
-            return b1.doubleValue();
-        }
-        return 0;
-    }
-
-    private void clearPaperCache(String paperId) {
-        //清理与当前试卷相关的缓存
-        //        final String patternKey = CACHE_KEY_PAPER + "*" + paperId;
-        //        Set<String> keys = redisTemplate.keys(patternKey);
-        //        if (CollectionUtils.isNotEmpty(keys)) {
-        //            redisTemplate.delete(keys);
-        //        }
-        extractConfigPaperCache.remove(paperId);
-        basePaperCache.remove(paperId);
-    }
-
-    private void clearQuestionCache(String questionId) {
-        //清理与当前试题相关的缓存
-        //        final String patternKey = CACHE_KEY_QUESTION + "*" + questionId;
-        //        Set<String> keys = redisTemplate.keys(patternKey);
-        //        if (CollectionUtils.isNotEmpty(keys)) {
-        //            redisTemplate.delete(keys);
-        //        }
-        questionCache.remove(questionId);
-        questionAnswerCache.remove(questionId);
-    }
-
-    @Override
-    public List<PaperAnswerDomain> answerExport(Paper paper) {
-        List<PaperAnswerDomain> ret = new ArrayList<PaperAnswerDomain>();
-        List<PaperDetail> paperDetails = paperDetailRepo.findByPaperOrderByNumber(paper);
-        if (paperDetails != null && paperDetails.size() > 0) {
-            for (PaperDetail paperDetail : paperDetails) {
-                List<PaperDetailUnit> paperDetailUnits = paperDetailUnitRepo.findByPaperDetailOrderByNumber(paperDetail);
-                if (paperDetailUnits != null && paperDetailUnits.size() > 0) {
-                    for (PaperDetailUnit paperDetailUnit : paperDetailUnits) {
-                        Question ques = paperDetailUnit.getQuestion();
-                        if (QuesStructType.NESTED_ANSWER_QUESTION.equals(ques.getQuestionType())) {
-                            List<Question> subques = ques.getSubQuestions();
-                            if (subques != null && subques.size() > 0) {
-                                for (int i = 0; i < subques.size(); i++) {
-                                    Question subq = subques.get(i);
-                                    PaperAnswerDomain domain = new PaperAnswerDomain();
-                                    domain.setName(paperDetail.getName());
-                                    domain.setNumber(paperDetail.getNumber());
-                                    domain.setSubNumber(paperDetailUnit.getNumber());
-                                    domain.setSubType(subq.getQuestionType().getName());
-                                    domain.setChildNumber(i + 1);
-                                    domain.setAnswer(subq.getQuesAnswer());
-                                    ret.add(domain);
-                                }
-                            }
-                        } else {
-                            PaperAnswerDomain domain = new PaperAnswerDomain();
-                            domain.setName(paperDetail.getName());
-                            domain.setNumber(paperDetail.getNumber());
-                            domain.setSubNumber(paperDetailUnit.getNumber());
-                            domain.setSubType(paperDetailUnit.getQuestionType().getName());
-                            domain.setAnswer(ques.getQuesAnswer());
-                            ret.add(domain);
-                        }
-                    }
-                }
-            }
-        }
-        return ret;
-    }
-
-    @Override
-    public void answerImport(Paper paper, MultipartFile dataFile) {
-        File file = new File(systemProperties.getTempDataDir() + File.separator + UUID.randomUUID() + ".xlsx");
-        try {
-            file.createNewFile();
-            dataFile.transferTo(file);
-            List<String[]> lineList = getData(file);
-            if (lineList == null || lineList.size() == 0) {
-                throw new StatusException("500", "没有导入的数据");
-            }
-            List<PaperAnswerDomain> ret = new ArrayList<PaperAnswerDomain>();
-            for (int i = 0; i < lineList.size(); i++) {
-                String[] line = lineList.get(i);
-                PaperAnswerDomain domain = new PaperAnswerDomain();
-                domain.setNumber(getNumber(trimAndNullIfBlank(line[0])));
-                domain.setName(trimAndNullIfBlank(line[1]));
-                domain.setSubNumber(getNumber(trimAndNullIfBlank(line[2])));
-                domain.setChildNumber(getNumber(trimAndNullIfBlank(line[3])));
-                domain.setSubType(trimAndNullIfBlank(line[4]));
-                domain.setAnswer(trimAndNullIfBlank(line[5]));
-                ret.add(domain);
-            }
-            if (ret == null || ret.size() == 0) {
-                throw new StatusException("500", "没有导入的数据");
-            }
-            diposeAnswer(paper, ret);
-        } catch (StatusException e) {
-            throw e;
-        } catch (Exception e) {
-            throw new StatusException("500", "导入答案失败:" + e.getMessage(), e);
-        } finally {
-            FileUtil.deleteFile(file.getAbsolutePath());
-        }
-    }
-
-    private List<String[]> getData(File file) {
-        XSSFWorkbook wb = null;
-        try {
-            try {
-                wb = new XSSFWorkbook(file);
-            } catch (Exception e) {
-                throw new StatusException("500", "文件类型错误");
-            }
-            List<String[]> outerList = new ArrayList<String[]>();
-            XSSFSheet sheet = wb.getSheetAt(0);
-            for (int i = 1; i <= sheet.getLastRowNum(); i++) {
-                String[] innerList = new String[6];
-                XSSFRow row = sheet.getRow(i);
-                for (int j = 0; j < 6; j++) {
-                    XSSFCell cell = row.getCell(j);
-                    if (cell != null) {
-                        String cellinfo = cell.getStringCellValue();
-                        innerList[j] = cellinfo;
-                    } else {
-                        innerList[j] = "";
-                    }
-                }
-                if (!isEmpty(innerList)) {
-                    if (StringUtils.isEmpty(innerList[0])) {
-                        throw new StatusException("500", "文件类型错误" + (i + 1) + "行大题号不能为空");
-                    }
-                    if (StringUtils.isEmpty(innerList[2])) {
-                        throw new StatusException("500", "文件类型错误" + (i + 1) + "行小题号不能为空");
-                    }
-                    outerList.add(innerList);
-                }
-            }
-            return outerList;
-        } finally {
-            if (wb != null) {
-                try {
-                    wb.close();
-                } catch (IOException e) {
-                    LOG.debug("wb.close() error " + e);
-                }
-            }
-        }
+	@Override
+	public Map<String, Object> getPaperPDF(String paperId, String type) {
+		PaperExp paperExp = getPaperDto(paperId);
+		Map<String, Object> map = new HashMap<>();
+		map.put("courseName", paperExp.getCourseName());
+		map.put("courseNo", paperExp.getCourseNo());
+		List<String> htmlList = new ArrayList<>();
+		if (paperExp.getPaperDetails() != null && paperExp.getPaperDetails().size() > 0) {
+			for (PaperDetailExp paperDetail : paperExp.getPaperDetails()) {
+				// 添加大题标题
+				if (StringUtils.isBlank(paperDetail.getTitle())) {
+					// htmlList.add(("<p>"+paperDetail.getCnNum()+"、"+paperDetail.getName()+"</p>").replaceAll("'",
+					// "&apos"));
+					htmlList.add(("<p class='paperDetailTitle'>" + paperDetail.getCnNum() + "、" + paperDetail.getName()
+							+ "</p>").replaceAll("'", "&apos"));
+				} else {
+					htmlList.add("<p class='paperDetailTitle'>" + paperDetail.getCnNum() + "、" + paperDetail.getName()
+							+ paperDetail.getTitle() + "</p>");
+				}
+				if (paperDetail.getPaperDetailUnits() != null && paperDetail.getPaperDetailUnits().size() > 0) {
+					for (PaperDetailUnitExp paperDetailUnitExp : paperDetail.getPaperDetailUnits()) {
+						Question question = paperDetailUnitExp.getQuestion();
+						if (type.equals("paper")) {
+							// 添加题干
+							String questionBody = CommonUtils.deleteHtmlP(paperDetailUnitExp.getNumber() + "."
+									+ question.getQuesBody() + "(" + paperDetailUnitExp.getScore() + "分)");
+							htmlList.add("<p class='questionBody'>" + questionBody + "</p>");
+							// 判断是否为选择题
+							if (paperDetailUnitExp.getQuestionType() == QuesStructType.SINGLE_ANSWER_QUESTION
+									|| paperDetailUnitExp
+											.getQuestionType() == QuesStructType.MULTIPLE_ANSWER_QUESTION) {
+								for (QuesOption quesOption : question.getQuesOptions()) {
+									// 添加选项
+									String questionOption = CommonUtils.deleteHtmlP(
+											CommonUtils.getOptionNum(Integer.parseInt(quesOption.getNumber()) - 1) + "."
+													+ quesOption.getOptionBody());
+									htmlList.add("<p class='selectOption'>" + questionOption + "</p>");
+								}
+							}
+							// 判断是否为套题
+							if (paperDetailUnitExp.getQuestionType() == QuesStructType.NESTED_ANSWER_QUESTION) {
+								// 得到子题
+								List<Question> subQuestions = question.getSubQuestions();
+								for (Question subQuestion : subQuestions) {
+									// 添加子题题干
+									String subQuestionBody = CommonUtils
+											.deleteHtmlP(subQuestion.getQuesParams().get("number") + "."
+													+ subQuestion.getQuesBody() + "(" + subQuestion.getScore() + "分)");
+									htmlList.add("<p class='questionBody'>" + subQuestionBody + "</p>");
+									// 判断是否为选择题
+									if (subQuestion.getQuestionType() == QuesStructType.SINGLE_ANSWER_QUESTION
+											|| subQuestion
+													.getQuestionType() == QuesStructType.MULTIPLE_ANSWER_QUESTION) {
+										for (QuesOption quesOption : subQuestion.getQuesOptions()) {
+											// 添加选项
+											String questionOption = CommonUtils.deleteHtmlP(CommonUtils
+													.getOptionNum(Integer.parseInt(quesOption.getNumber()) - 1) + "."
+													+ quesOption.getOptionBody());
+											htmlList.add("<p class='selectOption'>" + questionOption + "</p>");
+										}
+									}
+								}
+							}
+						} else {
+							// 判断是否为套题
+							if (paperDetailUnitExp.getQuestionType() == QuesStructType.NESTED_ANSWER_QUESTION) {
+								// 得到子题
+								List<Question> subQuestions = question.getSubQuestions();
+								for (Question subQuestion : subQuestions) {
+									// 添加答案
+									String questionAnswer = CommonUtils
+											.deleteHtmlP(subQuestion.getQuesParams().get("number") + "."
+													+ subQuestion.getQuesAnswer() + "(" + subQuestion.getScore()
+													+ "分)");
+									htmlList.add("<p class='questionAnswer'>" + questionAnswer + "</p>");
+								}
+							} else {
+								// 添加答案
+								String questionAnswer = CommonUtils.deleteHtmlP(paperDetailUnitExp.getNumber() + "."
+										+ question.getQuesAnswer() + "(" + paperDetailUnitExp.getScore() + "分)");
+								htmlList.add("<p class='questionAnswer'>" + questionAnswer + "</p>");
+							}
+						}
+
+					}
+				}
+			}
+		}
+		map.put("htmlList", htmlList);
+		return map;
+	}
+
+	@SuppressWarnings("unused")
+	@Override
+	public String sendPrint(String paperId, String orgId, String examId) {
+		// 查询原paper对象
+		Paper paper = Model.of(paperRepo.findById(paperId));
+		SyncCoursePaperBean bean = new SyncCoursePaperBean();
+		bean.setOrgId(Long.valueOf(orgId));
+		bean.setExamId(Long.valueOf(examId));
+		Course course = courseService.getCourse(Long.valueOf(orgId), paper.getCourse().getCode());
+		bean.setCourseId(Long.valueOf(course.getId()));
+		bean.setCourseCode(paper.getCourse().getCode());
+		bean.setCourseName(paper.getCourse().getName());
+		bean.setPaperId(paper.getId());
+		bean.setPaperName(paper.getName());
+		SyncCoursePaperReq req = new SyncCoursePaperReq();
+		req.setBean(bean);
+		SyncCoursePaperResp resp = coursePaperCloudService.syncCoursePaper(req);
+		return "success";
+	}
+
+	@Override
+	public String findQuestionStructure(String paperId) throws Exception {
+		// 根据paperId查询新的对象
+		ExportPaperAbstractService exportPaperAbstractService = (ExportPaperAbstractService) SpringContextHolder
+				.getBean("exportPaperAbstractService");
+		DownloadPaperDto dto = new DownloadPaperDto();
+		dto.setPaperId(paperId);
+		dto.setSeqMode(PaperSeqMode.MODE3);
+		PaperExp paperExp = exportPaperAbstractService.initPaperExp(dto);
+		LOG.info("已经获取试卷");
+		// 得到试卷中的客观大题
+		List<PaperDetailExp> objectiveDetails = exportPaperAbstractService.getAllObjectiveDetails(paperExp);
+		// 客观题中如果有套题,要拆开
+		List<PaperDetailExp> newObjectiveDetails = buildPaperDetailExp(objectiveDetails);
+		// 生成客观题数集合
+		List<ObjectiveQuestionStructure> objectiveQuestionStructureList = new ArrayList<>();
+		for (PaperDetailExp paperDetailExp : newObjectiveDetails) {
+			for (PaperDetailUnitExp unit : paperDetailExp.getPaperDetailUnits()) {
+				objectiveQuestionStructureList
+						.add(new ObjectiveQuestionStructure(paperExp, paperDetailExp, unit, null));
+			}
+		}
+		LOG.info("生成客观题数集合");
+		// 得到试卷中的主观大题
+		List<PaperDetailExp> subjectiveDetails = exportPaperAbstractService.getAllSubjectiveDetails(paperExp);
+		// 生成主观题数集合
+		List<SubjectiveQuestionStructure> subjectiveQuestionStructureList = new ArrayList<>();
+		for (PaperDetailExp paperDetailExp : subjectiveDetails) {
+			for (PaperDetailUnitExp unit : paperDetailExp.getPaperDetailUnits()) {
+				subjectiveQuestionStructureList
+						.add(new SubjectiveQuestionStructure(paperExp, paperDetailExp, unit, null));
+			}
+		}
+		LOG.info("生成主观题数集合");
+		PaperQuestionStructureInfo info = new PaperQuestionStructureInfo();
+		info.setObjectives(objectiveQuestionStructureList);
+		info.setSubjectives(subjectiveQuestionStructureList);
+		String jsonResp = JsonUtil.toJson(info);
+		LOG.info("jsonResp:" + jsonResp);
+		return jsonResp;
+	}
 
+	public List<PaperDetailExp> buildPaperDetailExp(List<PaperDetailExp> objectiveDetails) {
+		// 1.得到所有客观题大题的类型
+		Set<QuesStructType> types = new HashSet<>();
+		for (PaperDetailExp paperDetailExp : objectiveDetails) {
+			types.add(QuesStructType.getQuesStructTypeById(paperDetailExp.getSortNumber()));
+		}
+		// 2.生成新的大题集合
+		List<PaperDetailExp> newObjs = new ArrayList<>();
+		for (QuesStructType type : types) {
+			for (PaperDetailExp paperDetailExp : objectiveDetails) {
+				if (paperDetailExp.getSortNumber().equals(type.getId())) {
+					// 生成新的大题
+					PaperDetailExp newPaperDetailExp = new PaperDetailExp();
+					// 生成新的小题
+					List<PaperDetailUnitExp> newPaperDetailUnits = new ArrayList<>();
+					// 得到旧大题下的所有小题
+					List<PaperDetailUnitExp> paperDetailUnits = paperDetailExp.getPaperDetailUnits();
+					for (PaperDetailUnitExp paperDetailUnitExp : paperDetailUnits) {
+						if (paperDetailUnitExp.getQuestionType() != QuesStructType.NESTED_ANSWER_QUESTION) {
+							newPaperDetailUnits.add(paperDetailUnitExp);
+						} else {
+							List<Question> subQuestions = paperDetailUnitExp.getQuestion().getSubQuestions();
+							if (subQuestions != null && subQuestions.size() > 0) {
+								for (int i = 0; i < subQuestions.size(); i++) {
+									newPaperDetailUnits.add(new PaperDetailUnitExp(type, subQuestions.get(i)));
+								}
+							}
+						}
+					}
+					// 设置小题
+					newPaperDetailExp.setPaperDetailUnits(newPaperDetailUnits);
+					// 设置大题题号
+					newPaperDetailExp.setNumber(Integer.parseInt(type.getId() + ""));
+					newPaperDetailExp.setSortNumber(paperDetailExp.getSortNumber());
+					newObjs.add(newPaperDetailExp);
+				}
+			}
+		}
+		// 刷一遍number
+		int num = 0;
+		for (QuesStructType type : types) {
+			for (int i = 0; i < newObjs.size(); i++) {
+				if (newObjs.get(i).getSortNumber().equals(type.getId())) {
+					List<PaperDetailUnitExp> exps = newObjs.get(i).getPaperDetailUnits();
+					for (int j = 0; j < exps.size(); j++) {
+						num++;
+						exps.get(j).setNumber(num);
+					}
+				}
+			}
+		}
+		return newObjs;
+	}
 
-    }
+	@Override
+	public PaperExp getDownPaperExp(String paperId) {
+		Paper paper = Model.of(paperRepo.findById(paperId));
+		// 创建paperDto
+		PaperExp paperExp = BeanCopierUtil.copyProperties(paper, PaperExp.class);
+		paperExp.setCourseName(paper.getCourse().getName());
+		paperExp.setCourseNo(paper.getCourse().getCode());
+		paperExp.setCourse(paper.getCourse());
+		// 获取大题
+		List<PaperDetail> paperDetails = paperDetailRepo.findByPaperOrderByNumber(paper);
+		List<PaperDetailExp> paperDetailExps = new ArrayList<>();
+		for (PaperDetail paperDetail : paperDetails) {
+			PaperDetailExp paperDetailExp = new PaperDetailExp();
+			BeanUtils.copyProperties(paperDetail, paperDetailExp);
+			if (StringUtils.isBlank(paperDetailExp.getName())) {
+				paperDetailExp.setName("默认大题");
+			}
+			paperDetailExps.add(paperDetailExp);
+		}
+		// 封装小题
+		for (int i = 0; i < paperDetailExps.size(); i++) {
+			List<PaperDetailUnit> paperDetailUnits = paperDetailUnitRepo
+					.findByPaperDetailOrderByNumber(paperDetails.get(i));
+			if (paperDetailUnits != null && paperDetailUnits.size() > 0) {
+				List<PaperDetailUnitExp> paperDetailUnitExps = new ArrayList<>();
+				for (PaperDetailUnit paperDetailUnit : paperDetailUnits) {
+					PaperDetailUnitExp paperDetailUnitExp = new PaperDetailUnitExp();
+					BeanUtils.copyProperties(paperDetailUnit, paperDetailUnitExp);
+					paperDetailUnitExps.add(paperDetailUnitExp);
+				}
+				paperDetailExps.get(i).setPaperDetailUnits(paperDetailUnitExps);
+				paperDetailExps.get(i).setUnitCount(paperDetailUnitExps.size());
+			} else {
+				paperDetailExps.get(i).setUnitCount(0);
+			}
+		}
+		paperExp.setPaperDetails(paperDetailExps);
+		if (paperExp.getPaperDetails() == null || paperExp.getPaperDetails().size() == 0) {
+			return paperExp;
+		}
+		int mainNum = 0;
+		List<PaperDetailExp> paperDetailExpList = paperExp.getPaperDetails();
+		for (PaperDetailExp paperDetail : paperDetailExpList) {
+			// 大题序号
+			paperDetail.setNumber(++mainNum);
+			paperDetail.setCnNum(CommonUtils.toCHNum(paperDetail.getNumber()));
+			if (paperDetail.getPaperDetailUnits() == null || paperDetail.getPaperDetailUnits().size() == 0) {
+				throw new StatusException("500", "第" + mainNum + "大题没有小题");
+			}
+			if (paperDetail != null && paperDetail.getPaperDetailUnits() != null
+					&& paperDetail.getPaperDetailUnits().size() > 0) {
+				for (PaperDetailUnitExp paperDetailUnit : paperDetail.getPaperDetailUnits()) {
+					Question question = paperDetailUnit.getQuestion();
+					question.setDifficultyDegree(question.getDifficultyDegree() * 10);
+					if (question.getPublicity() == null || question.getPublicity() == true) {
+						paperDetailUnit.setPublicity("公开");
+					} else {
+						paperDetailUnit.setPublicity("非公开");
+					}
+					if (StringUtils.isBlank(paperDetail.getQuesType())) {
+						paperDetail.setQuesType(question.getQuestionType().getName());
+					}
+					// 设置选项
+					List<QuesOption> optionList = paperDetailUnit.getQuestion().getQuesOptions();
+					if (optionList != null && optionList.size() > 0) {
+						// int index = 0;
+						// for (QuesOption quesOption : optionList) {
+						// quesOption.setOptionBodyWord(setOptionNum(quesOption.getOptionBodyWord(),
+						// getOptionNum(index)));
+						// index++;
+						// }
+					}
+					if (question.getQuestionType() != QuesStructType.NESTED_ANSWER_QUESTION) {
+						// 给小题设置序号
+						// question.setQuesBodyWord(setSubQuesNum(question.getQuesBodyWord(),
+						// minNum++));
+						// question.setQuesAnswerWord(setAnswerNum(question.getQuesAnswerWord()));
+						fillProperty(question);
+						if (paperDetail.getFirstScore() == null) {
+							if (question.getScore() == null) {
+								paperDetail.setFirstScore(0d);
+							} else {
+								paperDetail.setFirstScore(question.getScore());
+							}
+						}
+					} else {
+						List<Question> subQuesList = question.getSubQuestions();
+						// 套题小题设置序号
+						if (subQuesList != null && subQuesList.size() > 0) {
+							for (Question subQues : subQuesList) {
+								subQues.setDifficultyDegree(subQues.getDifficultyDegree() * 10);
+								// subQues.setQuesBodyWord(setSubQuesNum(subQues.getQuesBodyWord(), index++));
+								// subQues.setQuesAnswerWord(setAnswerNum(subQues.getQuesAnswerWord()));
+								if (paperDetail.getFirstScore() == null) {
+									if (subQues.getScore() == null) {
+										paperDetail.setFirstScore(0d);
+									} else {
+										paperDetail.setFirstScore(subQues.getScore());
+									}
+								}
+								fillProperty(subQues);
+							}
+						}
+					}
+					List<QuesProperty> quesProperties = question.getQuesProperties();
+					if (quesProperties != null && quesProperties.size() > 0) {
+						QuesProperty quesProperty = quesProperties.get(0);
+						if (quesProperty.getFirstProperty() != null) {
+							paperDetailUnit.setFirstName(quesProperty.getFirstProperty().getName());
+							paperDetailUnit.setFirstCode(quesProperty.getFirstProperty().getCode());
+						}
+						if (quesProperty.getSecondProperty() != null) {
+							paperDetailUnit.setSecondName(quesProperty.getSecondProperty().getName());
+							paperDetailUnit.setSecondCode(quesProperty.getSecondProperty().getCode());
+						}
+					}
+				}
+			}
+		}
+		return paperExp;
+	}
 
-    private boolean isEmpty(String[] ss) {
-        for (String s : ss) {
-            if (StringUtils.isNotEmpty(s)) {
-                return false;
-            }
-        }
-        return true;
-    }
-
-    private void diposeAnswer(Paper paper, List<PaperAnswerDomain> domains) {
-        Map<String, PaperAnswerDomain> answerMap = new LinkedHashMap<String, PaperAnswerDomain>();
-        for (PaperAnswerDomain domain : domains) {
-            String key = null;
-            if (domain.getChildNumber() != null) {
-                key = domain.getSubNumber() + "-" + domain.getChildNumber();
-            } else {
-                key = domain.getSubNumber().toString();
-            }
-            if (answerMap.get(key) == null) {
-                answerMap.put(key, domain);
-            } else {
-                throw new StatusException("500", "导入数据中第" + domain.getSubNumber() + "小题" + (domain.getChildNumber() != null ? "第" + domain.getChildNumber() + "子题" : "") + "重复");
-            }
-        }
+	private void fillProperty(Question question) {
+		List<QuesProperty> ret = new ArrayList<>();
+		List<QuesProperty> quesProperties = question.getQuesProperties();
+		if (quesProperties != null && quesProperties.size() > 0) {
+			for (QuesProperty quesProperty : quesProperties) {
+				if (quesProperty.getFirstProperty() != null && quesProperty.getFirstProperty().getId() != null) {
+					Property curProperty = Model.of(propertyRepo.findById(quesProperty.getFirstProperty().getId()));
+					if (curProperty == null) {
+						continue;
+					}
+					quesProperty.setFirstProperty(curProperty);
+				}
+				if (quesProperty.getSecondProperty() != null && quesProperty.getSecondProperty().getId() != null) {
+					Property curProperty = Model.of(propertyRepo.findById(quesProperty.getSecondProperty().getId()));
+					if (curProperty == null) {
+						continue;
+					}
+					quesProperty.setSecondProperty(curProperty);
+				}
+				ret.add(quesProperty);
+			}
+		}
+		question.setQuesProperties(ret);
+	}
 
-        Map<String, Question> quesMap = new LinkedHashMap<String, Question>();
-        List<PaperDetailUnit> paperDetailUnits = paperDetailUnitRepo.findByPaperIdOrderByNumber(paper.getId());
-        for (PaperDetailUnit unit : paperDetailUnits) {
-            Question qu = unit.getQuestion();
-            if (QuesStructType.NESTED_ANSWER_QUESTION.equals(qu.getQuestionType())) {
-                for (int i = 0; i < unit.getQuestion().getSubQuestions().size(); i++) {
-                    quesMap.put(unit.getNumber() + "-" + (i + 1), unit.getQuestion().getSubQuestions().get(i));
-                }
-            } else {
-                quesMap.put(unit.getNumber().toString(), qu);
-            }
-        }
+	/**
+	 * 设置题号
+	 *
+	 * @param quesBodyWordMl
+	 * @param num
+	 * @return
+	 * @throws Exception
+	 */
+	// public String setSubQuesNum(String quesBodyWordMl, int num) throws Exception
+	// {
+	// String tmpStr = DocxProcessUtil.BODY_HEADER + quesBodyWordMl +
+	// DocxProcessUtil.BODY_TAIL;
+	// Body body = (Body) XmlUtils.unmarshalString(tmpStr, Context.jc, Body.class);
+	// List<Object> pList = body.getContent();
+	// int index = 0;
+	// for (Object pObj : pList) {
+	// if (index > 0) {
+	// break;
+	// }
+	// P p = (P) pObj;
+	// List<Object> pContent = p.getContent();
+	// R run = new R();
+	// Text text = new Text();
+	// text.setValue(num + ". ");
+	// run.getContent().add(text);
+	// pContent.add(0, run);
+	// index++;
+	// }
+	// StringBuffer pWordMl = new StringBuffer();
+	// for (Object pObj : pList) {
+	// if (pObj instanceof P) {
+	// pWordMl.append(DocxProcessUtil.formatPWordMl(XmlUtils.marshaltoString(pObj)));
+	// }
+	// }
+	// return pWordMl.toString();
+	// }
+
+	/**
+	 * 将数字1,2,3,4转化成A,B,C,D
+	 *
+	 * @param number
+	 * @return
+	 */
+	public String getOptionNum(int number) {
+		char optionNum = (char) (65 + number);
+		return String.valueOf(optionNum);
+	}
 
-        Set<String> saveQuestion = new HashSet<String>();
-        for (String key : answerMap.keySet()) {
-            PaperAnswerDomain domain = answerMap.get(key);
-            Question qu = quesMap.get(key);
-            if (qu == null) {
-                answerFomatErr(domain.getSubNumber(), domain.getChildNumber(), "试题信息不存在");
-            }
-            saveQuestion.add(domain.getSubNumber().toString());
-        }
+	/**
+	 * 设置选项号
+	 *
+	 * @param optionWordMl
+	 * @param num
+	 * @return
+	 * @throws Exception
+	 */
+	// public String setOptionNum(String optionWordMl, String num) throws Exception
+	// {
+	// String tmpStr = DocxProcessUtil.BODY_HEADER + optionWordMl +
+	// DocxProcessUtil.BODY_TAIL;
+	// Body body = (Body) XmlUtils.unmarshalString(tmpStr, Context.jc, Body.class);
+	// List<Object> pList = body.getContent();
+	// int index = 0;
+	// for (Object pObj : pList) {
+	// if (index > 0) {
+	// break;
+	// }
+	// P p = (P) pObj;
+	// List<Object> pContent = p.getContent();
+	// R run = new R();
+	// Text text = new Text();
+	// text.setValue(num + ". ");
+	// run.getContent().add(text);
+	// pContent.add(0, run);
+	// index++;
+	// }
+	// StringBuffer pWordMl = new StringBuffer();
+	// for (Object pObj : pList) {
+	// if (pObj instanceof P) {
+	// pWordMl.append(DocxProcessUtil.formatPWordMl(XmlUtils.marshaltoString(pObj)));
+	// }
+	// }
+	// return pWordMl.toString();
+	// }
+
+	// public String setAnswerNum(String quesBodyWordMl) throws Exception {
+	// String tmpStr = DocxProcessUtil.BODY_HEADER + quesBodyWordMl +
+	// DocxProcessUtil.BODY_TAIL;
+	// Body body = (Body) XmlUtils.unmarshalString(tmpStr, Context.jc, Body.class);
+	// List<Object> pList = body.getContent();
+	// int index = 0;
+	// for (Object pObj : pList) {
+	// if (index > 0) {
+	// break;
+	// }
+	// P p = (P) pObj;
+	// List<Object> pContent = p.getContent();
+	// R run = new R();
+	// Text text = new Text();
+	// text.setValue("[答案]:");
+	// run.getContent().add(text);
+	// pContent.add(0, run);
+	// index++;
+	// }
+	// StringBuffer pWordMl = new StringBuffer();
+	// for (Object pObj : pList) {
+	// if (pObj instanceof P) {
+	// pWordMl.append(DocxProcessUtil.formatPWordMl(XmlUtils.marshaltoString(pObj)));
+	// }
+	// }
+	// return pWordMl.toString();
+	// }
+	@Override
+	public int getQuestionTypeNumbers(String paperId, Integer publicityType, Integer difficultyType) {
+		if (publicityType == null || difficultyType == null) {
+			return 0;
+		}
+		Boolean publicity = null;
+		String difficulty = null;
+		if (publicityType == 1) {
+			publicity = true;
+		} else {
+			publicity = false;
+		}
+		if (difficultyType == 1) {
+			difficulty = "易";
+		} else if (difficultyType == 2) {
+			difficulty = "中";
+		} else {
+			difficulty = "难";
+		}
+		String needType = publicity + "-" + difficulty;
+		Paper paper = Model.of(paperRepo.findById(paperId));
+		List<PaperDetailUnit> units = paperDetailUnitRepo.findByPaperOrderByNumber(paper);
+		if (units != null && units.size() > 0) {
+			int total = 0;
+			for (PaperDetailUnit unit : units) {
+				if (unit.getQuestion().getPublicity() == null) {
+					unit.getQuestion().setPublicity(true);
+				}
+				if (unit.getQuestion().getDifficulty() == null) {
+					unit.getQuestion().setDifficulty("中");
+				}
+				String factType = unit.getQuestion().getPublicity() + "-" + unit.getQuestion().getDifficulty();
+				if (needType.equals(factType)) {
+					total += 1;
+				}
+			}
+			return total;
+		}
+		return 0;
+	}
 
-        Set<String> updateQuesIds = new HashSet<String>();
-        List<Question> ques = new ArrayList<Question>();
-        for (PaperDetailUnit unit : paperDetailUnits) {
-            Question qu = unit.getQuestion();
-            if (saveQuestion.contains(unit.getNumber().toString())) {
-                if (QuesStructType.NESTED_ANSWER_QUESTION.equals(qu.getQuestionType())) {
-                    for (int i = 0; i < unit.getQuestion().getSubQuestions().size(); i++) {
-                        if (answerMap.get(unit.getNumber() + "-" + (i + 1)) != null) {
-                            checkAndSetAnswer(unit.getQuestion().getSubQuestions().get(i), answerMap.get(unit.getNumber() + "-" + (i + 1)).getAnswer(), unit.getNumber(), i + 1);
-                            updateQuesIds.add(qu.getId());
-                        }
-                    }
-                } else {
-                    if (answerMap.get(unit.getNumber().toString()) != null) {
-                        checkAndSetAnswer(qu, answerMap.get(unit.getNumber().toString()).getAnswer(), unit.getNumber(), null);
-                        updateQuesIds.add(qu.getId());
-                    }
-                }
-            }
-            ques.add(qu);
-        }
-        quesRepo.saveAll(ques);
-        //清除缓存
-    	for(String qid:updateQuesIds) {
-    		paperDetailUnitService.clearQuestionCache(qid);
-        }
-    }
+	@Override
+	public double getQuestionTypeScore(String paperId, Integer publicityType, Integer difficultyType) {
+		if (publicityType == null || difficultyType == null) {
+			return 0;
+		}
+		Boolean publicity = null;
+		String difficulty = null;
+		if (publicityType == 1) {
+			publicity = true;
+		} else {
+			publicity = false;
+		}
+		if (difficultyType == 1) {
+			difficulty = "易";
+		} else if (difficultyType == 2) {
+			difficulty = "中";
+		} else {
+			difficulty = "难";
+		}
+		String needType = publicity + "-" + difficulty;
+		Paper paper = Model.of(paperRepo.findById(paperId));
+		List<PaperDetailUnit> units = paperDetailUnitRepo.findByPaperOrderByNumber(paper);
+		if (units != null && units.size() > 0) {
+			double total = 0;
+			BigDecimal b1 = BigDecimal.valueOf(total);
+			for (PaperDetailUnit unit : units) {
+				if (unit.getQuestion().getPublicity() == null) {
+					unit.getQuestion().setPublicity(true);
+				}
+				if (unit.getQuestion().getDifficulty() == null) {
+					unit.getQuestion().setDifficulty("中");
+				}
+				String factType = unit.getQuestion().getPublicity() + "-" + unit.getQuestion().getDifficulty();
+				if (needType.equals(factType)) {
+					BigDecimal b2 = BigDecimal.valueOf(unit.getScore());
+					b1 = b1.add(b2);
+				}
+			}
+			return b1.doubleValue();
+		}
+		return 0;
+	}
 
-    private void checkAndSetAnswer(Question question, String answer, Integer subNum, Integer childNum) {
-        String fomatErrMsg = "答案格式错误";
-        if (answer != null) {
-            answer = answer.trim();
-        }
-        if (StringUtils.isBlank(answer)) {
-            return;
-        }
-        if (QuesStructType.SINGLE_ANSWER_QUESTION.equals(question.getQuestionType())
-                || QuesStructType.MULTIPLE_ANSWER_QUESTION.equals(question.getQuestionType())) {
-            answer = answer.replaceAll("\\s*", "");
-            if (QuesStructType.SINGLE_ANSWER_QUESTION.equals(question.getQuestionType())) {
-                if (answer.length() > 1) {
-                    answerFomatErr(subNum, childNum, fomatErrMsg);
-                }
-            }
-            String[] pAnswerArray;
-            if (answer.indexOf(",") != -1) {
-                pAnswerArray = answer.split(",");
-            } else {
-                pAnswerArray = answer.split("");
-            }
-            List<QuesOption> options = question.getQuesOptions();
-            List<String> optionNumList = new ArrayList<>();
-            for (QuesOption quesOption : options) {
-                Integer numInteger = Integer.parseInt(quesOption.getNumber());
-                char word = (char) (numInteger + 64);
-                optionNumList.add(word + "");
-            }
-            for (String option : pAnswerArray) {
-                String pattern = "[A-Z]";
-                if (!Pattern.matches(pattern, option)) {
-                    answerFomatErr(subNum, childNum, fomatErrMsg);
-                }
-                if (!optionNumList.contains(option)) {
-                    answerFomatErr(subNum, childNum, "答案选项不存在");
-                }
-            }
-            if(pAnswerArray.length>1) {
-            	question.setQuesAnswer(StringUtils.join(pAnswerArray, ","));
-            }else {
-            	question.setQuesAnswer(answer);
-            }
-            processSelectOption(question);
-        } else if (QuesStructType.BOOL_ANSWER_QUESTION.equals(question.getQuestionType())) {
-            if (!answer.equals("正确") && !answer.equals("错误")) {
-                answerFomatErr(subNum, childNum, fomatErrMsg);
-            }
-            question.setQuesAnswer(answer);
-        } else if (QuesStructType.FILL_BLANK_QUESTION.equals(question.getQuestionType())) {
-            String body = question.getQuesBody();
-            Document bodyDoc = Jsoup.parse(body);
-            String bodyText = bodyDoc.body().html();
-            Document answerDoc = null;
-            try {
-                answerDoc = Jsoup.parse(answer);
-            } catch (Exception e) {
-                answerFomatErr(subNum, childNum, "答案格式html解析错误");
-            }
-            if (answerDoc.body().childrenSize() != 0) {
-                String answerText = answerDoc.body().html();
-                if (StringUtils.isNotBlank(answerText)) {
-                    if (getSubStringCount(bodyText, "###") != answerText.split("##").length) {
-                        answerFomatErr(subNum, childNum, "题干空格数量和答案数量不一致");
-                    }
-                }
-            }
-            question.setQuesAnswer(answer);
-        } else if (QuesStructType.TEXT_ANSWER_QUESTION.equals(question.getQuestionType())) {
-            try {
-                Jsoup.parse(answer);
-            } catch (Exception e) {
-                answerFomatErr(subNum, childNum, "答案格式html解析错误");
-            }
-            question.setQuesAnswer(answer);
-        }
+	private void clearPaperCache(String paperId) {
+		// 清理与当前试卷相关的缓存
+		// final String patternKey = CACHE_KEY_PAPER + "*" + paperId;
+		// Set<String> keys = redisTemplate.keys(patternKey);
+		// if (CollectionUtils.isNotEmpty(keys)) {
+		// redisTemplate.delete(keys);
+		// }
+		extractConfigPaperCache.remove(paperId);
+		basePaperCache.remove(paperId);
+	}
 
-    }
+	private void clearQuestionCache(String questionId) {
+		// 清理与当前试题相关的缓存
+		// final String patternKey = CACHE_KEY_QUESTION + "*" + questionId;
+		// Set<String> keys = redisTemplate.keys(patternKey);
+		// if (CollectionUtils.isNotEmpty(keys)) {
+		// redisTemplate.delete(keys);
+		// }
+		questionCache.remove(questionId);
+		questionAnswerCache.remove(questionId);
+	}
 
-    private int getSubStringCount(String src, String find) {
-        int o = 0;
-        int index = -1;
-        while ((index = src.indexOf(find, index)) > -1) {
-            ++index;
-            ++o;
-        }
-        return o;
-    }
-
-    private void processSelectOption(Question question) {
-        String answer = question.getQuesAnswer();
-        if (StringUtils.isNotBlank(answer)) {
-            String[] answerArray = answer.split(",");
-            for (int i = 0; i < question.getQuesOptions().size(); i++) {
-                QuesOption quesOption = question.getQuesOptions().get(i);
-                char number = (char) (Integer.parseInt(quesOption.getNumber()) + 64);
-                if (ArrayUtils.contains(answerArray, String.valueOf(number))) {
-                    quesOption.setIsCorrect((short) 1);
-                } else {
-                    quesOption.setIsCorrect((short) 0);
-                }
-            }
-        }
-    }
+	@Override
+	public List<PaperAnswerDomain> answerExport(Paper paper) {
+		List<PaperAnswerDomain> ret = new ArrayList<PaperAnswerDomain>();
+		List<PaperDetail> paperDetails = paperDetailRepo.findByPaperOrderByNumber(paper);
+		if (paperDetails != null && paperDetails.size() > 0) {
+			for (PaperDetail paperDetail : paperDetails) {
+				List<PaperDetailUnit> paperDetailUnits = paperDetailUnitRepo
+						.findByPaperDetailOrderByNumber(paperDetail);
+				if (paperDetailUnits != null && paperDetailUnits.size() > 0) {
+					for (PaperDetailUnit paperDetailUnit : paperDetailUnits) {
+						Question ques = paperDetailUnit.getQuestion();
+						if (QuesStructType.NESTED_ANSWER_QUESTION.equals(ques.getQuestionType())) {
+							List<Question> subques = ques.getSubQuestions();
+							if (subques != null && subques.size() > 0) {
+								for (int i = 0; i < subques.size(); i++) {
+									Question subq = subques.get(i);
+									PaperAnswerDomain domain = new PaperAnswerDomain();
+									domain.setName(paperDetail.getName());
+									domain.setNumber(paperDetail.getNumber());
+									domain.setSubNumber(paperDetailUnit.getNumber());
+									domain.setSubType(subq.getQuestionType().getName());
+									domain.setChildNumber(i + 1);
+									domain.setAnswer(subq.getQuesAnswer());
+									ret.add(domain);
+								}
+							}
+						} else {
+							PaperAnswerDomain domain = new PaperAnswerDomain();
+							domain.setName(paperDetail.getName());
+							domain.setNumber(paperDetail.getNumber());
+							domain.setSubNumber(paperDetailUnit.getNumber());
+							domain.setSubType(paperDetailUnit.getQuestionType().getName());
+							domain.setAnswer(ques.getQuesAnswer());
+							ret.add(domain);
+						}
+					}
+				}
+			}
+		}
+		return ret;
+	}
 
-    private void answerFomatErr(Integer subNum, Integer childNum, String msg) {
-        throw new StatusException("500", "导入数据中第" + subNum + "小题" + (childNum != null ? "第" + childNum + "子题" : "") + msg);
-    }
+	@Override
+	public void answerImport(Paper paper, MultipartFile dataFile) {
+		File file = new File(systemProperties.getTempDataDir() + File.separator + UUID.randomUUID() + ".xlsx");
+		try {
+			file.createNewFile();
+			dataFile.transferTo(file);
+			List<String[]> lineList = getData(file);
+			if (lineList == null || lineList.size() == 0) {
+				throw new StatusException("500", "没有导入的数据");
+			}
+			List<PaperAnswerDomain> ret = new ArrayList<PaperAnswerDomain>();
+			for (int i = 0; i < lineList.size(); i++) {
+				String[] line = lineList.get(i);
+				PaperAnswerDomain domain = new PaperAnswerDomain();
+				domain.setNumber(getNumber(trimAndNullIfBlank(line[0])));
+				domain.setName(trimAndNullIfBlank(line[1]));
+				domain.setSubNumber(getNumber(trimAndNullIfBlank(line[2])));
+				domain.setChildNumber(getNumber(trimAndNullIfBlank(line[3])));
+				domain.setSubType(trimAndNullIfBlank(line[4]));
+				domain.setAnswer(trimAndNullIfBlank(line[5]));
+				ret.add(domain);
+			}
+			if (ret == null || ret.size() == 0) {
+				throw new StatusException("500", "没有导入的数据");
+			}
+			diposeAnswer(paper, ret);
+		} catch (StatusException e) {
+			throw e;
+		} catch (Exception e) {
+			throw new StatusException("500", "导入答案失败:" + e.getMessage(), e);
+		} finally {
+			FileUtil.deleteFile(file.getAbsolutePath());
+		}
+	}
 
-    private String trimAndNullIfBlank(String s) {
-        if (StringUtils.isBlank(s)) {
-            return null;
-        }
-        return s.trim();
-    }
+	private List<String[]> getData(File file) {
+		XSSFWorkbook wb = null;
+		try {
+			try {
+				wb = new XSSFWorkbook(file);
+			} catch (Exception e) {
+				throw new StatusException("500", "文件类型错误");
+			}
+			List<String[]> outerList = new ArrayList<String[]>();
+			XSSFSheet sheet = wb.getSheetAt(0);
+			for (int i = 1; i <= sheet.getLastRowNum(); i++) {
+				String[] innerList = new String[6];
+				XSSFRow row = sheet.getRow(i);
+				for (int j = 0; j < 6; j++) {
+					XSSFCell cell = row.getCell(j);
+					if (cell != null) {
+						String cellinfo = cell.getStringCellValue();
+						innerList[j] = cellinfo;
+					} else {
+						innerList[j] = "";
+					}
+				}
+				if (!isEmpty(innerList)) {
+					if (StringUtils.isEmpty(innerList[0])) {
+						throw new StatusException("500", "文件类型错误" + (i + 1) + "行大题号不能为空");
+					}
+					if (StringUtils.isEmpty(innerList[2])) {
+						throw new StatusException("500", "文件类型错误" + (i + 1) + "行小题号不能为空");
+					}
+					outerList.add(innerList);
+				}
+			}
+			return outerList;
+		} finally {
+			if (wb != null) {
+				try {
+					wb.close();
+				} catch (IOException e) {
+					LOG.debug("wb.close() error " + e);
+				}
+			}
+		}
 
-    private Integer getNumber(String s) {
-        if (StringUtils.isBlank(s)) {
-            return null;
-        }
-        return Integer.valueOf(s.trim());
-    }
+	}
+
+	private boolean isEmpty(String[] ss) {
+		for (String s : ss) {
+			if (StringUtils.isNotEmpty(s)) {
+				return false;
+			}
+		}
+		return true;
+	}
+
+	private void diposeAnswer(Paper paper, List<PaperAnswerDomain> domains) {
+		Map<String, PaperAnswerDomain> answerMap = new LinkedHashMap<String, PaperAnswerDomain>();
+		for (PaperAnswerDomain domain : domains) {
+			String key = null;
+			if (domain.getChildNumber() != null) {
+				key = domain.getSubNumber() + "-" + domain.getChildNumber();
+			} else {
+				key = domain.getSubNumber().toString();
+			}
+			if (answerMap.get(key) == null) {
+				answerMap.put(key, domain);
+			} else {
+				throw new StatusException("500", "导入数据中第" + domain.getSubNumber() + "小题"
+						+ (domain.getChildNumber() != null ? "第" + domain.getChildNumber() + "子题" : "") + "重复");
+			}
+		}
+
+		Map<String, Question> quesMap = new LinkedHashMap<String, Question>();
+		List<PaperDetailUnit> paperDetailUnits = paperDetailUnitRepo.findByPaperIdOrderByNumber(paper.getId());
+		for (PaperDetailUnit unit : paperDetailUnits) {
+			Question qu = unit.getQuestion();
+			if (QuesStructType.NESTED_ANSWER_QUESTION.equals(qu.getQuestionType())) {
+				for (int i = 0; i < unit.getQuestion().getSubQuestions().size(); i++) {
+					quesMap.put(unit.getNumber() + "-" + (i + 1), unit.getQuestion().getSubQuestions().get(i));
+				}
+			} else {
+				quesMap.put(unit.getNumber().toString(), qu);
+			}
+		}
+
+		Set<String> saveQuestion = new HashSet<String>();
+		for (String key : answerMap.keySet()) {
+			PaperAnswerDomain domain = answerMap.get(key);
+			Question qu = quesMap.get(key);
+			if (qu == null) {
+				answerFomatErr(domain.getSubNumber(), domain.getChildNumber(), "试题信息不存在");
+			}
+			saveQuestion.add(domain.getSubNumber().toString());
+		}
+
+		Set<String> updateQuesIds = new HashSet<String>();
+		List<Question> ques = new ArrayList<Question>();
+		for (PaperDetailUnit unit : paperDetailUnits) {
+			Question qu = unit.getQuestion();
+			if (saveQuestion.contains(unit.getNumber().toString())) {
+				if (QuesStructType.NESTED_ANSWER_QUESTION.equals(qu.getQuestionType())) {
+					for (int i = 0; i < unit.getQuestion().getSubQuestions().size(); i++) {
+						if (answerMap.get(unit.getNumber() + "-" + (i + 1)) != null) {
+							checkAndSetAnswer(unit.getQuestion().getSubQuestions().get(i),
+									answerMap.get(unit.getNumber() + "-" + (i + 1)).getAnswer(), unit.getNumber(),
+									i + 1);
+							updateQuesIds.add(qu.getId());
+						}
+					}
+				} else {
+					if (answerMap.get(unit.getNumber().toString()) != null) {
+						checkAndSetAnswer(qu, answerMap.get(unit.getNumber().toString()).getAnswer(), unit.getNumber(),
+								null);
+						updateQuesIds.add(qu.getId());
+					}
+				}
+			}
+			ques.add(qu);
+		}
+		quesRepo.saveAll(ques);
+		// 清除缓存
+		for (String qid : updateQuesIds) {
+			paperDetailUnitService.clearQuestionCache(qid);
+		}
+	}
+
+	private void checkAndSetAnswer(Question question, String answer, Integer subNum, Integer childNum) {
+		String fomatErrMsg = "答案格式错误";
+		if (answer != null) {
+			answer = answer.trim();
+		}
+		if (StringUtils.isBlank(answer)) {
+			return;
+		}
+		if (QuesStructType.SINGLE_ANSWER_QUESTION.equals(question.getQuestionType())
+				|| QuesStructType.MULTIPLE_ANSWER_QUESTION.equals(question.getQuestionType())) {
+			answer = answer.replaceAll("\\s*", "");
+			if (QuesStructType.SINGLE_ANSWER_QUESTION.equals(question.getQuestionType())) {
+				if (answer.length() > 1) {
+					answerFomatErr(subNum, childNum, fomatErrMsg);
+				}
+			}
+			String[] pAnswerArray;
+			if (answer.indexOf(",") != -1) {
+				pAnswerArray = answer.split(",");
+			} else {
+				pAnswerArray = answer.split("");
+			}
+			List<QuesOption> options = question.getQuesOptions();
+			List<String> optionNumList = new ArrayList<>();
+			for (QuesOption quesOption : options) {
+				Integer numInteger = Integer.parseInt(quesOption.getNumber());
+				char word = (char) (numInteger + 64);
+				optionNumList.add(word + "");
+			}
+			for (String option : pAnswerArray) {
+				String pattern = "[A-Z]";
+				if (!Pattern.matches(pattern, option)) {
+					answerFomatErr(subNum, childNum, fomatErrMsg);
+				}
+				if (!optionNumList.contains(option)) {
+					answerFomatErr(subNum, childNum, "答案选项不存在");
+				}
+			}
+			if (pAnswerArray.length > 1) {
+				question.setQuesAnswer(StringUtils.join(pAnswerArray, ","));
+			} else {
+				question.setQuesAnswer(answer);
+			}
+			processSelectOption(question);
+		} else if (QuesStructType.BOOL_ANSWER_QUESTION.equals(question.getQuestionType())) {
+			if (!answer.equals("正确") && !answer.equals("错误")) {
+				answerFomatErr(subNum, childNum, fomatErrMsg);
+			}
+			question.setQuesAnswer(answer);
+		} else if (QuesStructType.FILL_BLANK_QUESTION.equals(question.getQuestionType())) {
+			String body = question.getQuesBody();
+			Document bodyDoc = Jsoup.parse(body);
+			String bodyText = bodyDoc.body().html();
+			Document answerDoc = null;
+			try {
+				answerDoc = Jsoup.parse(answer);
+			} catch (Exception e) {
+				answerFomatErr(subNum, childNum, "答案格式html解析错误");
+			}
+			if (answerDoc.body().childrenSize() != 0) {
+				String answerText = answerDoc.body().html();
+				if (StringUtils.isNotBlank(answerText)) {
+					if (getSubStringCount(bodyText, "###") != answerText.split("##").length) {
+						answerFomatErr(subNum, childNum, "题干空格数量和答案数量不一致");
+					}
+				}
+			}
+			question.setQuesAnswer(answer);
+		} else if (QuesStructType.TEXT_ANSWER_QUESTION.equals(question.getQuestionType())) {
+			try {
+				Jsoup.parse(answer);
+			} catch (Exception e) {
+				answerFomatErr(subNum, childNum, "答案格式html解析错误");
+			}
+			question.setQuesAnswer(answer);
+		}
+
+	}
+
+	private int getSubStringCount(String src, String find) {
+		int o = 0;
+		int index = -1;
+		while ((index = src.indexOf(find, index)) > -1) {
+			++index;
+			++o;
+		}
+		return o;
+	}
+
+	private void processSelectOption(Question question) {
+		String answer = question.getQuesAnswer();
+		if (StringUtils.isNotBlank(answer)) {
+			String[] answerArray = answer.split(",");
+			for (int i = 0; i < question.getQuesOptions().size(); i++) {
+				QuesOption quesOption = question.getQuesOptions().get(i);
+				char number = (char) (Integer.parseInt(quesOption.getNumber()) + 64);
+				if (ArrayUtils.contains(answerArray, String.valueOf(number))) {
+					quesOption.setIsCorrect((short) 1);
+				} else {
+					quesOption.setIsCorrect((short) 0);
+				}
+			}
+		}
+	}
+
+	private void answerFomatErr(Integer subNum, Integer childNum, String msg) {
+		throw new StatusException("500",
+				"导入数据中第" + subNum + "小题" + (childNum != null ? "第" + childNum + "子题" : "") + msg);
+	}
+
+	private String trimAndNullIfBlank(String s) {
+		if (StringUtils.isBlank(s)) {
+			return null;
+		}
+		return s.trim();
+	}
+
+	private Integer getNumber(String s) {
+		if (StringUtils.isBlank(s)) {
+			return null;
+		}
+		return Integer.valueOf(s.trim());
+	}
 
 	@Override
 	public List<String> findPaperId(Long fromRootOrgId) {
 		Query query = new Query();
 		query.addCriteria(Criteria.where("orgId").is(fromRootOrgId.toString()));
 		query.addCriteria(Criteria.where("paperType").is(PaperType.IMPORT));
-		List<PaperId> paperList = this.mongoTemplate.find(query, PaperId.class,"paper");
-		if(CollectionUtils.isEmpty(paperList)) {
+		List<PaperId> paperList = this.mongoTemplate.find(query, PaperId.class, "paper");
+		if (CollectionUtils.isEmpty(paperList)) {
 			return null;
 		}
-		List<String> ids=paperList.stream().map(e->e.getId()).collect(Collectors.toList());
+		List<String> ids = paperList.stream().map(e -> e.getId()).collect(Collectors.toList());
 		return ids;
 	}
 
-    
-
 }

+ 14 - 4
examcloud-core-questions-service/src/main/java/cn/com/qmth/examcloud/core/questions/service/impl/RandomPaperQuestionServiceImpl.java

@@ -1,15 +1,25 @@
 package cn.com.qmth.examcloud.core.questions.service.impl;
 
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+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 cn.com.qmth.examcloud.core.questions.dao.entity.RandomPaperQuestion;
 import cn.com.qmth.examcloud.core.questions.service.RandomPaperQuestionService;
 
 @Service
 public class RandomPaperQuestionServiceImpl implements RandomPaperQuestionService {
-
-	private static final Logger log = LoggerFactory.getLogger(RandomPaperQuestionServiceImpl.class);
+	@Autowired
+	private MongoTemplate mongoTemplate;
+	@Override
+	public boolean existQuestion(String questionId) {
+		Query query = new Query();
+		query.addCriteria(Criteria.where("questionId").is(questionId));
+		RandomPaperQuestion rp=mongoTemplate.findOne(query,RandomPaperQuestion.class);
+		return rp!=null;
+	}
 	
 
 }

+ 8 - 0
examcloud-core-questions-service/src/main/java/cn/com/qmth/examcloud/core/questions/service/impl/RandomPaperServiceImpl.java

@@ -1037,4 +1037,12 @@ public class RandomPaperServiceImpl implements RandomPaperService {
 		return rp;
 	}
 
+	@Override
+	public boolean existStruct(String paperStructId) {
+		Query query = new Query();
+		query.addCriteria(Criteria.where("paperStructId").is(paperStructId));
+		RandomPaper rp=mongoTemplate.findOne(query,RandomPaper.class);
+		return rp!=null;
+	}
+
 }