xiatian 4 жил өмнө
parent
commit
7b1e579031

+ 10 - 0
examcloud-core-questions-base/pom.xml

@@ -68,6 +68,16 @@
             <artifactId>examcloud-reports-commons</artifactId>
             <artifactId>examcloud-reports-commons</artifactId>
             <version>${project.version}</version>
             <version>${project.version}</version>
         </dependency>
         </dependency>
+        <dependency>
+            <groupId>cn.com.qmth.examcloud.rpc</groupId>
+            <artifactId>examcloud-core-oe-admin-api-client</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>cn.com.qmth.examcloud.rpc</groupId>
+            <artifactId>examcloud-core-oe-student-api-client</artifactId>
+            <version>${project.version}</version>
+        </dependency>
         <dependency>
         <dependency>
             <groupId>com.upyun</groupId>
             <groupId>com.upyun</groupId>
             <artifactId>java-sdk</artifactId>
             <artifactId>java-sdk</artifactId>

+ 14 - 0
examcloud-core-questions-dao/src/main/java/cn/com/qmth/examcloud/core/questions/dao/entity/Paper.java

@@ -84,6 +84,11 @@ public class Paper extends MongoBaseEntity {
      * 是否在仓库:1-在 ,空或者0不在
      * 是否在仓库:1-在 ,空或者0不在
      */
      */
     private Integer storage;
     private Integer storage;
+    
+    /**
+     * 是否已调用:1-已调用,空或者0未调用
+     */
+    private Integer inUse;
 
 
     public String getName() {
     public String getName() {
         return name;
         return name;
@@ -290,5 +295,14 @@ public class Paper extends MongoBaseEntity {
 		this.storage = storage;
 		this.storage = storage;
 	}
 	}
 
 
+	public Integer getInUse() {
+		return inUse;
+	}
+
+	public void setInUse(Integer inUse) {
+		this.inUse = inUse;
+	}
+
+	
 	
 	
 }
 }

+ 11 - 0
examcloud-core-questions-dao/src/main/java/cn/com/qmth/examcloud/core/questions/dao/entity/PaperSearchInfo.java

@@ -27,6 +27,8 @@ public class PaperSearchInfo implements Serializable {
     private PaperStatus paperStatus; // 试卷审核状态
     private PaperStatus paperStatus; // 试卷审核状态
 
 
     private String[] paperIds;
     private String[] paperIds;
+    
+    private Integer inUse;
 
 
     public String getName() {
     public String getName() {
         return name;
         return name;
@@ -108,4 +110,13 @@ public class PaperSearchInfo implements Serializable {
 		this.lastModifyName = lastModifyName;
 		this.lastModifyName = lastModifyName;
 	}
 	}
 
 
+	public Integer getInUse() {
+		return inUse;
+	}
+
+	public void setInUse(Integer inUse) {
+		this.inUse = inUse;
+	}
+
+	
 }
 }

+ 477 - 477
examcloud-core-questions-service/src/main/java/cn/com/qmth/examcloud/core/questions/service/impl/ExtractConfigFileServiceImpl.java

@@ -18,6 +18,7 @@ import org.apache.commons.lang3.StringUtils;
 import org.slf4j.Logger;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.mongodb.core.MongoTemplate;
 import org.springframework.stereotype.Service;
 import org.springframework.stereotype.Service;
 
 
 import cn.com.qmth.examcloud.api.commons.security.bean.User;
 import cn.com.qmth.examcloud.api.commons.security.bean.User;
@@ -73,500 +74,499 @@ import cn.com.qmth.examcloud.support.filestorage.FileStorageUtil;
 @Service("extractConfigFileService")
 @Service("extractConfigFileService")
 public class ExtractConfigFileServiceImpl implements ExtractConfigFileService {
 public class ExtractConfigFileServiceImpl implements ExtractConfigFileService {
 
 
-    private static final Logger LOG = LoggerFactory.getLogger(ExtractConfigFileServiceImpl.class);
-
-    public static final String TEMP_FILE_EXP = "docxExport/";
-
-    public static final String TEMP_FILE_NAME = "_考试说明";
-
-    @Autowired
-    private ExportStructureService exportStructureService;
-
-    @Autowired
-    private ExtractConfigService extractConfigService;
-
-    @Autowired
-    private ExamFileService examFileService;
-
-    @Autowired
-    private QuestionAudioService questionAudioService;
-
-    @Autowired
-    private InitPaperExpService initPaperExpService;
-
-    @Autowired
-    private PrintExamPaperService printExamPaperService;
-
-
-    @Autowired
-    private ExamCloudService examCloudService;
-
-    @Autowired
-    private SysProperty sysProperty;
-
-    @Override
-    public void saveExtractConfigAndBuildPaperFile(ExtractConfig extractConfig, Integer isbuildFile, User user,PaperSeqMode seqMode) {
-        //新增,id为空
-        if (StringUtils.isBlank(extractConfig.getId())) {
-            //先查询
-            ExtractConfig tempConfig = extractConfigService.findConfig(extractConfig);
-            if (tempConfig != null) {
-                extractConfig.setId(tempConfig.getId());
-            }
-        }
-        //查询试卷导出设置
-        ExportStructure exportStructure = null;
-        if (isbuildFile == 1) {
-            exportStructure = exportStructureService.findStructureByExamId(extractConfig.getExamId() + "");
-        }
-        //生成试卷
-        List<ExamPaper> examPaperList = extractConfigService.saveExtractConfig(extractConfig, user);
-        if (isbuildFile == 1) {
-            //删除原有试卷文件
-            ExamFile examFile = new ExamFile();
-            examFile.setExamId(extractConfig.getExamId() + "");
-            examFile.setCourseId(extractConfig.getCourseCode());
-            examFile.setOrgId(extractConfig.getOrgId());
-            examFileService.deleteExamFile(examFile);
-            //上传抽取试卷对象集合
-            for (ExamPaper examPaper : examPaperList) {
-                String paperId = examPaper.getPaper().getId();
-                uploadPaperFile(extractConfig, paperId, exportStructure, user, examPaper,seqMode);
-            }
-        }
-        /*if (isbuildFile == 1) {
-            //删除原有试卷文件
-            ExamFile examFile = new ExamFile();
-            examFile.setExamId(extractConfig.getExamId() + "");
-            examFile.setCourseId(extractConfig.getCourseCode());
-            examFile.setOrgId(extractConfig.getOrgId());
-            examFileService.deleteExamFile(examFile);
-            //生成并上传新的试卷文件
-            Set<Entry<String, String>> entrySet = finishedPaperIdMap.entrySet();
-            Iterator<Entry<String, String>> iterator = entrySet.iterator();
-            while (iterator.hasNext()) {
-                Entry<String, String> entry = iterator.next();
-                String paperId = entry.getValue();
-                uploadPaperFile(extractConfig, paperId, exportStructure, user);
-            }
-        }*/
-    }
-
-    /**
-     * 生成并上传试卷文件
-     *
-     * @param extractConfig
-     * @param paperId
-     * @param exportStructure
-     * @param user
-     * @throws Exception
-     */
-    private void uploadPaperFile(ExtractConfig extractConfig, String paperId, ExportStructure exportStructure, User user, ExamPaper examPaper,PaperSeqMode seqMode) {
-        ExportPaperAbstractService exportPaperAbstractService = PaperUtil.getByRootOrgId(String.valueOf(user.getRootOrgId()));
-        exportPaperAbstractService.uploadFile(extractConfig, paperId, exportStructure, user, examPaper,seqMode);
-    }
-
-    @Override
-    public void exportExamPaperInfoCheck(ExportPaperInfoModel exportModel, HttpServletResponse response) throws Exception {
-        ExportStructure exportStructure = exportStructureService.findStructureByExamId(exportModel.getExamId() + "");
-        //如果是批量导出
-        if (exportModel.getExportWay() == ExportWay.BATCH) {
-            if (exportStructure == null) {
-                exportStructure = new ExportStructure();
-                exportStructure.setExportType(ExportType.NORMAL);
-            }
-            //查询该考试下是否所有课程都制定了调卷规则和考试文件
-            checkAllCourseByExamId(exportModel.getExamId(), exportStructure.getExportType());
-        }
-    }
-
-    @Override
-    public void exportExamPaperInfo(ExportPaperInfoModel exportModel, HttpServletResponse response, String loginName, String orgId, String psw) throws Exception {
-        String tempDir = loginName + System.currentTimeMillis();
-        String downloadDir = sysProperty.getDownloadDirectory() + "/" + tempDir;
-        String downZipDir = sysProperty.getZipDirectory() + "/" + tempDir;
-        //创建试卷和压缩文件 文件夹
-        FileDisposeUtil.createDirectory(downloadDir);
-        //创建压缩文件的文件夹
-        FileDisposeUtil.createDirectory(downZipDir);
-        ExportStructure exportStructure = exportStructureService.findStructureByExamId(exportModel.getExamId() + "");
-        if (exportStructure == null) {
-            exportStructure = new ExportStructure();
-            exportStructure.setExportType(ExportType.NORMAL);
-        }
-
-        //导出分布式印刷的数据包
-        if (exportModel.getExportContentList().contains(ExamFileType.PRINT_EXAM_PACKAGE.name())) {
-            ExtractConfig condition = new ExtractConfig();
-            condition.setExamId(Long.valueOf(exportModel.getExamId()));
-            condition.setCourseCode(exportModel.getCourseId());
-            //获取调卷规则
-            ExtractConfig extractConfig = extractConfigService.findConfig(condition);
-            if (extractConfig != null) {
-                List<Paper> papers = new ArrayList<>();
-                List<ExamPaper> examPapers = extractConfig.getExamPaperList();
-                if (examPapers != null && examPapers.size() > 0) {
-                    for (ExamPaper examPaper : examPapers) {
-                        papers.add(examPaper.getPaper());
-                    }
-                }
-                printExamPaperService.downloadPaper(papers, downloadDir, psw);
-            } else {
-                LOG.info("exportPrintExamPaper fail, extractConfig is not exist!");
-            }
-        }
-
-        //如果是普通类型的批量导出  导出试卷结构
-        if (exportModel.getExportWay() == ExportWay.BATCH) {
-            Map<String, String> paperIds = checkAllCourseByExamId(exportModel.getExamId(), exportStructure.getExportType());
-            if (exportStructure.getExportType() == ExportType.NORMAL) {
-                if (paperIds.size() > 0 && exportModel.getExportContentList().contains(ExamFileType.PAPER_STRUCTURE_OBJECTIVE.name())) {
-                    makePaperStructure(downloadDir, exportStructure.getExamName(), paperIds, exportStructure);//for export test
-                }
-            }
-        }
-        //根据条件获取到文件下载路径,下载文件到服务器的downloadDirectory文件夹
-        List<ExamFile> examFiles = examFileService.findExamFileListByExportPaperInfoModel(exportModel);
-        if (examFiles != null && examFiles.size() > 0) {
-            for (int i = 0; i < examFiles.size(); i++) {
-                ExamFile examFile = examFiles.get(i);
+	private static final Logger LOG = LoggerFactory.getLogger(ExtractConfigFileServiceImpl.class);
+
+	public static final String TEMP_FILE_EXP = "docxExport/";
+
+	public static final String TEMP_FILE_NAME = "_考试说明";
+
+	@Autowired
+	private ExportStructureService exportStructureService;
+
+	@Autowired
+	private ExtractConfigService extractConfigService;
+
+	@Autowired
+	private ExamFileService examFileService;
+
+	@Autowired
+	private QuestionAudioService questionAudioService;
+
+	@Autowired
+	private InitPaperExpService initPaperExpService;
+
+	@Autowired
+	private PrintExamPaperService printExamPaperService;
+
+	@Autowired
+	private ExamCloudService examCloudService;
+
+	@Autowired
+	private SysProperty sysProperty;
+
+	@Autowired
+	MongoTemplate mongoTemplate;
+
+	@Override
+	public void saveExtractConfigAndBuildPaperFile(ExtractConfig extractConfig, Integer isbuildFile, User user,
+			PaperSeqMode seqMode) {
+		// 新增,id为空
+		if (StringUtils.isBlank(extractConfig.getId())) {
+			// 先查询
+			ExtractConfig tempConfig = extractConfigService.findConfig(extractConfig);
+			if (tempConfig != null) {
+				extractConfig.setId(tempConfig.getId());
+			}
+		}
+		// 查询试卷导出设置
+		ExportStructure exportStructure = null;
+		if (isbuildFile == 1) {
+			exportStructure = exportStructureService.findStructureByExamId(extractConfig.getExamId() + "");
+		}
+
+		// 生成试卷
+		List<ExamPaper> examPaperList = extractConfigService.saveExtractConfig(extractConfig, user);
+		if (isbuildFile == 1) {
+			// 删除原有试卷文件
+			ExamFile examFile = new ExamFile();
+			examFile.setExamId(extractConfig.getExamId() + "");
+			examFile.setCourseId(extractConfig.getCourseCode());
+			examFile.setOrgId(extractConfig.getOrgId());
+			examFileService.deleteExamFile(examFile);
+			// 上传抽取试卷对象集合
+			for (ExamPaper examPaper : examPaperList) {
+				String paperId = examPaper.getPaper().getId();
+				uploadPaperFile(extractConfig, paperId, exportStructure, user, examPaper, seqMode);
+			}
+		}
+	}
+	
+	/**
+	 * 生成并上传试卷文件
+	 *
+	 * @param extractConfig
+	 * @param paperId
+	 * @param exportStructure
+	 * @param user
+	 * @throws Exception
+	 */
+	private void uploadPaperFile(ExtractConfig extractConfig, String paperId, ExportStructure exportStructure,
+			User user, ExamPaper examPaper, PaperSeqMode seqMode) {
+		ExportPaperAbstractService exportPaperAbstractService = PaperUtil
+				.getByRootOrgId(String.valueOf(user.getRootOrgId()));
+		exportPaperAbstractService.uploadFile(extractConfig, paperId, exportStructure, user, examPaper, seqMode);
+	}
+
+	@Override
+	public void exportExamPaperInfoCheck(ExportPaperInfoModel exportModel, HttpServletResponse response)
+			throws Exception {
+		ExportStructure exportStructure = exportStructureService.findStructureByExamId(exportModel.getExamId() + "");
+		// 如果是批量导出
+		if (exportModel.getExportWay() == ExportWay.BATCH) {
+			if (exportStructure == null) {
+				exportStructure = new ExportStructure();
+				exportStructure.setExportType(ExportType.NORMAL);
+			}
+			// 查询该考试下是否所有课程都制定了调卷规则和考试文件
+			checkAllCourseByExamId(exportModel.getExamId(), exportStructure.getExportType());
+		}
+	}
+
+	@Override
+	public void exportExamPaperInfo(ExportPaperInfoModel exportModel, HttpServletResponse response, String loginName,
+			String orgId, String psw) throws Exception {
+		String tempDir = loginName + System.currentTimeMillis();
+		String downloadDir = sysProperty.getDownloadDirectory() + "/" + tempDir;
+		String downZipDir = sysProperty.getZipDirectory() + "/" + tempDir;
+		// 创建试卷和压缩文件 文件夹
+		FileDisposeUtil.createDirectory(downloadDir);
+		// 创建压缩文件的文件夹
+		FileDisposeUtil.createDirectory(downZipDir);
+		ExportStructure exportStructure = exportStructureService.findStructureByExamId(exportModel.getExamId() + "");
+		if (exportStructure == null) {
+			exportStructure = new ExportStructure();
+			exportStructure.setExportType(ExportType.NORMAL);
+		}
+
+		// 导出分布式印刷的数据包
+		if (exportModel.getExportContentList().contains(ExamFileType.PRINT_EXAM_PACKAGE.name())) {
+			ExtractConfig condition = new ExtractConfig();
+			condition.setExamId(Long.valueOf(exportModel.getExamId()));
+			condition.setCourseCode(exportModel.getCourseId());
+			// 获取调卷规则
+			ExtractConfig extractConfig = extractConfigService.findConfig(condition);
+			if (extractConfig != null) {
+				List<Paper> papers = new ArrayList<>();
+				List<ExamPaper> examPapers = extractConfig.getExamPaperList();
+				if (examPapers != null && examPapers.size() > 0) {
+					for (ExamPaper examPaper : examPapers) {
+						papers.add(examPaper.getPaper());
+					}
+				}
+				printExamPaperService.downloadPaper(papers, downloadDir, psw);
+			} else {
+				LOG.info("exportPrintExamPaper fail, extractConfig is not exist!");
+			}
+		}
+
+		// 如果是普通类型的批量导出 导出试卷结构
+		if (exportModel.getExportWay() == ExportWay.BATCH) {
+			Map<String, String> paperIds = checkAllCourseByExamId(exportModel.getExamId(),
+					exportStructure.getExportType());
+			if (exportStructure.getExportType() == ExportType.NORMAL) {
+				if (paperIds.size() > 0
+						&& exportModel.getExportContentList().contains(ExamFileType.PAPER_STRUCTURE_OBJECTIVE.name())) {
+					makePaperStructure(downloadDir, exportStructure.getExamName(), paperIds, exportStructure);// for
+																												// export
+																												// test
+				}
+			}
+		}
+		// 根据条件获取到文件下载路径,下载文件到服务器的downloadDirectory文件夹
+		List<ExamFile> examFiles = examFileService.findExamFileListByExportPaperInfoModel(exportModel);
+		if (examFiles != null && examFiles.size() > 0) {
+			for (int i = 0; i < examFiles.size(); i++) {
+				ExamFile examFile = examFiles.get(i);
 //                UpYun upyun = new UpYun(sysProperty.getBucketName(), sysProperty.getUserName(), sysProperty.getPassword());
 //                UpYun upyun = new UpYun(sysProperty.getBucketName(), sysProperty.getUserName(), sysProperty.getPassword());
-                File file = new File(downloadDir + File.separator + examFile.getFileName());
+				File file = new File(downloadDir + File.separator + examFile.getFileName());
 //                upyun.readFile(examFile.getFilePath(), file);
 //                upyun.readFile(examFile.getFilePath(), file);
-                //通用存储
+				// 通用存储
 				FileStorageUtil.saveUrlAs(FileStorageUtil.realPath(examFile.getFilePath()), file);
 				FileStorageUtil.saveUrlAs(FileStorageUtil.realPath(examFile.getFilePath()), file);
 
 
-                if (examFile.getExamFileType() == ExamFileType.PAPER) {
-                    Long examId = Long.parseLong(exportModel.getExamId());
-                    ExtractConfig extractConfig = extractConfigService.findConfig(new ExtractConfig(examId, examFile.getCourseId()));
-                    List<ExamPaper> list = extractConfig.getExamPaperList();
-                    if (list != null && list.size() > 0) {
-                        for (ExamPaper examPaper : list) {
-                            String groupCode = examPaper.getGroupCode();
-                            String paperId = examPaper.getPaper().getId();
-                            if (groupCode.equals(examFile.getGroupCode())) {
-                                downloadAudio(paperId, examFile, downloadDir, orgId);
-                            }
-
-                        }
-                    }
-                   /* Map<String, String> finishedPaperIdMap = extractConfig.getFinishedPaperIdMap();
-                    Set<Entry<String, String>> entrySet = finishedPaperIdMap.entrySet();
-                    Iterator<Entry<String, String>> iterator = entrySet.iterator();
-                    while (iterator.hasNext()) {
-                        Entry<String, String> entry = iterator.next();
-                        String groupCode = entry.getKey();
-                        String paperId = entry.getValue();
-                        if (groupCode.equals(examFile.getGroupCode())) {
-                            downloadAudio(paperId, examFile, downloadDir, orgName);
-                        }
-                    }*/
-                }
-            }
-        }
-        //创建压缩文件名称
-        String zipFileName = exportModel.getExamId();
-        //将downloadDirectory文件夹压缩成zip文件,存放到zipDirectory文件夹中
-        FileDisposeUtil.fileToZip(downloadDir, downZipDir, zipFileName);
-        //下载zip文件到客户端
-        FileDisposeUtil.downloadFile(zipFileName + ".zip", downZipDir + File.separator + zipFileName + ".zip", response);
-        //删除文件夹
-        FileUtils.deleteQuietly(new File(downloadDir));
-        FileUtils.deleteQuietly(new File(downZipDir));
-    }
-
-    /**
-     * 下载试卷音频文件
-     *
-     * @throws Exception
-     */
-    private void downloadAudio(String paperId, ExamFile examFile, String downloadDir, String orgId) throws Exception {
-        ExportPaperAbstractService exportPaperAbstractService = PaperUtil.getByRootOrgId(orgId);
-        DownloadPaperDto dto=new DownloadPaperDto();
-    	dto.setPaperId(paperId);
-    	dto.setSeqMode(PaperSeqMode.MODE3);
-        PaperExp paperExp = exportPaperAbstractService.initPaperExp(dto);
-        //下载考试说明
-        if (StringUtils.isNotBlank(paperExp.getExamRemark())) {
-            downExamRemark(paperExp, downloadDir, examFile);
-        }
-        //取到所有大题
-        List<PaperDetailExp> paperDetailExps = paperExp.getPaperDetails();
-        if (paperDetailExps != null && paperDetailExps.size() > 0) {
-            for (PaperDetailExp paperDetailExp : paperDetailExps) {
-                //取到所有小题
-                List<PaperDetailUnitExp> paperDetailUnitExps = paperDetailExp.getPaperDetailUnits();
-                if (paperDetailUnitExps != null && paperDetailUnitExps.size() > 0) {
-                    for (PaperDetailUnitExp unit : paperDetailUnitExps) {
-                        if (unit.getQuestion().getHasAudio() != null && unit.getQuestion().getHasAudio()) {
-                            List<QuestionAudio> questionAudios = questionAudioService.findQuestionAudiosByQuestionId(unit.getQuestion().getId());
-                            for (QuestionAudio audio : questionAudios) {
-                                String audioFileName = audio.getId() +
-                                        "_" + exportPaperAbstractService.getAudioFileName(audio, unit, paperDetailExp);
+				if (examFile.getExamFileType() == ExamFileType.PAPER) {
+					Long examId = Long.parseLong(exportModel.getExamId());
+					ExtractConfig extractConfig = extractConfigService
+							.findConfig(new ExtractConfig(examId, examFile.getCourseId()));
+					List<ExamPaper> list = extractConfig.getExamPaperList();
+					if (list != null && list.size() > 0) {
+						for (ExamPaper examPaper : list) {
+							String groupCode = examPaper.getGroupCode();
+							String paperId = examPaper.getPaper().getId();
+							if (groupCode.equals(examFile.getGroupCode())) {
+								downloadAudio(paperId, examFile, downloadDir, orgId);
+							}
+
+						}
+					}
+					/*
+					 * Map<String, String> finishedPaperIdMap =
+					 * extractConfig.getFinishedPaperIdMap(); Set<Entry<String, String>> entrySet =
+					 * finishedPaperIdMap.entrySet(); Iterator<Entry<String, String>> iterator =
+					 * entrySet.iterator(); while (iterator.hasNext()) { Entry<String, String> entry
+					 * = iterator.next(); String groupCode = entry.getKey(); String paperId =
+					 * entry.getValue(); if (groupCode.equals(examFile.getGroupCode())) {
+					 * downloadAudio(paperId, examFile, downloadDir, orgName); } }
+					 */
+				}
+			}
+		}
+		// 创建压缩文件名称
+		String zipFileName = exportModel.getExamId();
+		// 将downloadDirectory文件夹压缩成zip文件,存放到zipDirectory文件夹中
+		FileDisposeUtil.fileToZip(downloadDir, downZipDir, zipFileName);
+		// 下载zip文件到客户端
+		FileDisposeUtil.downloadFile(zipFileName + ".zip", downZipDir + File.separator + zipFileName + ".zip",
+				response);
+		// 删除文件夹
+		FileUtils.deleteQuietly(new File(downloadDir));
+		FileUtils.deleteQuietly(new File(downZipDir));
+	}
+
+	/**
+	 * 下载试卷音频文件
+	 *
+	 * @throws Exception
+	 */
+	private void downloadAudio(String paperId, ExamFile examFile, String downloadDir, String orgId) throws Exception {
+		ExportPaperAbstractService exportPaperAbstractService = PaperUtil.getByRootOrgId(orgId);
+		DownloadPaperDto dto = new DownloadPaperDto();
+		dto.setPaperId(paperId);
+		dto.setSeqMode(PaperSeqMode.MODE3);
+		PaperExp paperExp = exportPaperAbstractService.initPaperExp(dto);
+		// 下载考试说明
+		if (StringUtils.isNotBlank(paperExp.getExamRemark())) {
+			downExamRemark(paperExp, downloadDir, examFile);
+		}
+		// 取到所有大题
+		List<PaperDetailExp> paperDetailExps = paperExp.getPaperDetails();
+		if (paperDetailExps != null && paperDetailExps.size() > 0) {
+			for (PaperDetailExp paperDetailExp : paperDetailExps) {
+				// 取到所有小题
+				List<PaperDetailUnitExp> paperDetailUnitExps = paperDetailExp.getPaperDetailUnits();
+				if (paperDetailUnitExps != null && paperDetailUnitExps.size() > 0) {
+					for (PaperDetailUnitExp unit : paperDetailUnitExps) {
+						if (unit.getQuestion().getHasAudio() != null && unit.getQuestion().getHasAudio()) {
+							List<QuestionAudio> questionAudios = questionAudioService
+									.findQuestionAudiosByQuestionId(unit.getQuestion().getId());
+							for (QuestionAudio audio : questionAudios) {
+								String audioFileName = audio.getId() + "_"
+										+ exportPaperAbstractService.getAudioFileName(audio, unit, paperDetailExp);
 //                                UpYun upyun = new UpYun(sysProperty.getBucketName(), sysProperty.getUserName(), sysProperty.getPassword());
 //                                UpYun upyun = new UpYun(sysProperty.getBucketName(), sysProperty.getUserName(), sysProperty.getPassword());
-                                File file = new File(downloadDir + File.separator + audioFileName);
+								File file = new File(downloadDir + File.separator + audioFileName);
 //                                upyun.readFile(audio.getFileUrl(), file);
 //                                upyun.readFile(audio.getFileUrl(), file);
-                                //通用存储
-                				FileStorageUtil.saveUrlAs(FileStorageUtil.realPath(audio.getFileUrl()), file);
-                            }
-                        }
-                    }
-                }
-            }
-        }
-    }
-
-    /**
-     * 下载考试说明
-     *
-     * @param zipFileName
-     * @throws Exception
-     */
-    public void downExamRemark(PaperExp paperExp, String zipFileName, ExamFile examFile) throws Exception {
+								// 通用存储
+								FileStorageUtil.saveUrlAs(FileStorageUtil.realPath(audio.getFileUrl()), file);
+							}
+						}
+					}
+				}
+			}
+		}
+	}
+
+	/**
+	 * 下载考试说明
+	 *
+	 * @param zipFileName
+	 * @throws Exception
+	 */
+	public void downExamRemark(PaperExp paperExp, String zipFileName, ExamFile examFile) throws Exception {
 //        //1.考试说明html转成word
 //        //1.考试说明html转成word
 //        String title = "<p style=\"text-align:center\"><span style=\"font-size:26px\"><span style=\"font-family:宋体\">考&nbsp;试&nbsp;说&nbsp;明</span></span></p>";
 //        String title = "<p style=\"text-align:center\"><span style=\"font-size:26px\"><span style=\"font-family:宋体\">考&nbsp;试&nbsp;说&nbsp;明</span></span></p>";
 //        WordprocessingMLPackage wordMLPackage = WordprocessingMLPackage.createPackage();
 //        WordprocessingMLPackage wordMLPackage = WordprocessingMLPackage.createPackage();
 //        String html = title + ImageUtils.reSizeImg(paperExp.getExamRemark());
 //        String html = title + ImageUtils.reSizeImg(paperExp.getExamRemark());
 //        DocxProcessUtil.html2Docx(wordMLPackage, CommonUtils.formatHtml(html));
 //        DocxProcessUtil.html2Docx(wordMLPackage, CommonUtils.formatHtml(html));
 //        //2.导出考试说明word
 //        //2.导出考试说明word
-        File directory = new File(zipFileName + File.separator);
-        String fileName=paperExp.getName() + "_" + paperExp.getCourse().getName() + "_" + paperExp.getCourse().getCode() + "_" + examFile.getGroupCode() + TEMP_FILE_NAME;
+		File directory = new File(zipFileName + File.separator);
+		String fileName = paperExp.getName() + "_" + paperExp.getCourse().getName() + "_"
+				+ paperExp.getCourse().getCode() + "_" + examFile.getGroupCode() + TEMP_FILE_NAME;
 //        Docx4J.save(wordMLPackage, file);
 //        Docx4J.save(wordMLPackage, file);
-        ExportPaperUtil.createExamRemarkDocFile(directory, fileName, paperExp.getExamRemark());
-    }
-
-    /**
-     * 计算取得音频文件名称
-     *
-     * @param audio
-     * @param unit
-     * @return
-     */
-    @SuppressWarnings("unused")
-    private String getAudioFileName(QuestionAudio audio, PaperDetailUnit unit) {
-        String questionAudioId = audio.getId();
-        StringBuffer audioFileName = new StringBuffer(unit.getPaperDetail().getNumber() + "_" + unit.getNumber() + "_");
-        Question question = unit.getQuestion();
-        List<String> idvaluesBody = CommonUtils.getTagANames(question.getQuesBody());
-        if (idvaluesBody.contains(questionAudioId)) {
-            audioFileName.append("1");//题干
-            audioFileName.append("_");
-            int index = idvaluesBody.indexOf(questionAudioId);
-            audioFileName.append(index + 1);
-        } else {
-            List<QuesOption> options = question.getQuesOptions();
-            if (options != null && options.size() > 0) {
-                for (QuesOption option : options) {
-                    List<String> idvaluesOption = CommonUtils.getTagANames(option.getOptionBody());
-                    if (idvaluesOption.contains(questionAudioId)) {
-                        audioFileName.append("2");//选项
-                        audioFileName.append("_");
-                        audioFileName.append(CommonUtils.getOptionNum(Integer.parseInt(option.getNumber()) - 1));
-                        audioFileName.append("_");
-                        int index = idvaluesOption.indexOf(questionAudioId);
-                        audioFileName.append(index + 1);
-                        break;
-                    }
-                }
-            }
-        }
-        audioFileName.append(".");
-        audioFileName.append(audio.getFileSuffixes());
-        return audioFileName.toString();
-    }
-
-    /**
-     * 查询该考试下是否所有课程都制定了调卷规则
-     *
-     * @param examId
-     */
-    private Map<String, String> checkAllCourseByExamId(String examId, ExportType exportType) {
-        Map<String, String> paperIdMap = new HashMap<>();
-        List<ExamCourseRelationBean> examCourseDtoList = new ArrayList<>();
-        GetExamCourseListReq req = new GetExamCourseListReq();
-        req.setExamId(Long.valueOf(examId));
-        //req.setExamId(299L);//for export test
-        req.setCourseEnable(true);
-        Long start = 1l;
-        int count = 0;
-        while (true) {
-            req.setStart(start);
-            GetExamCourseListResp resp = examCloudService.getExamCourseList(req);
-            examCourseDtoList.addAll(resp.getRelationList());
-            if (start.equals(resp.getNext())) {
-                break;
-            } else {
-                start = resp.getNext();
-            }
-            count++;
-            if (count > 1000) {
-                throw new StatusException("Q-", "考试下课程的数据量过大");
-            }
-        }
-
-        for (ExamCourseRelationBean examCourseDto : examCourseDtoList) {
-            ExtractConfig condition = new ExtractConfig();
-            condition.setExamId(examCourseDto.getExamId());
-            //condition.setExamId(606L);//for export online
-            condition.setCourseCode(examCourseDto.getCourseCode());
-
-            ExtractConfig extractConfig = extractConfigService.findConfig(condition);
+		ExportPaperUtil.createExamRemarkDocFile(directory, fileName, paperExp.getExamRemark());
+	}
+
+	/**
+	 * 计算取得音频文件名称
+	 *
+	 * @param audio
+	 * @param unit
+	 * @return
+	 */
+	@SuppressWarnings("unused")
+	private String getAudioFileName(QuestionAudio audio, PaperDetailUnit unit) {
+		String questionAudioId = audio.getId();
+		StringBuffer audioFileName = new StringBuffer(unit.getPaperDetail().getNumber() + "_" + unit.getNumber() + "_");
+		Question question = unit.getQuestion();
+		List<String> idvaluesBody = CommonUtils.getTagANames(question.getQuesBody());
+		if (idvaluesBody.contains(questionAudioId)) {
+			audioFileName.append("1");// 题干
+			audioFileName.append("_");
+			int index = idvaluesBody.indexOf(questionAudioId);
+			audioFileName.append(index + 1);
+		} else {
+			List<QuesOption> options = question.getQuesOptions();
+			if (options != null && options.size() > 0) {
+				for (QuesOption option : options) {
+					List<String> idvaluesOption = CommonUtils.getTagANames(option.getOptionBody());
+					if (idvaluesOption.contains(questionAudioId)) {
+						audioFileName.append("2");// 选项
+						audioFileName.append("_");
+						audioFileName.append(CommonUtils.getOptionNum(Integer.parseInt(option.getNumber()) - 1));
+						audioFileName.append("_");
+						int index = idvaluesOption.indexOf(questionAudioId);
+						audioFileName.append(index + 1);
+						break;
+					}
+				}
+			}
+		}
+		audioFileName.append(".");
+		audioFileName.append(audio.getFileSuffixes());
+		return audioFileName.toString();
+	}
+
+	/**
+	 * 查询该考试下是否所有课程都制定了调卷规则
+	 *
+	 * @param examId
+	 */
+	private Map<String, String> checkAllCourseByExamId(String examId, ExportType exportType) {
+		Map<String, String> paperIdMap = new HashMap<>();
+		List<ExamCourseRelationBean> examCourseDtoList = new ArrayList<>();
+		GetExamCourseListReq req = new GetExamCourseListReq();
+		req.setExamId(Long.valueOf(examId));
+		// req.setExamId(299L);//for export test
+		req.setCourseEnable(true);
+		Long start = 1l;
+		int count = 0;
+		while (true) {
+			req.setStart(start);
+			GetExamCourseListResp resp = examCloudService.getExamCourseList(req);
+			examCourseDtoList.addAll(resp.getRelationList());
+			if (start.equals(resp.getNext())) {
+				break;
+			} else {
+				start = resp.getNext();
+			}
+			count++;
+			if (count > 1000) {
+				throw new StatusException("Q-", "考试下课程的数据量过大");
+			}
+		}
+
+		for (ExamCourseRelationBean examCourseDto : examCourseDtoList) {
+			ExtractConfig condition = new ExtractConfig();
+			condition.setExamId(examCourseDto.getExamId());
+			// condition.setExamId(606L);//for export online
+			condition.setCourseCode(examCourseDto.getCourseCode());
+
+			ExtractConfig extractConfig = extractConfigService.findConfig(condition);
 //            if (extractConfig == null) {
 //            if (extractConfig == null) {
 //                logger.warn("examId:" + examId + " courseCode:" + examCourseDto.getCourseCode());
 //                logger.warn("examId:" + examId + " courseCode:" + examCourseDto.getCourseCode());
 //                continue;
 //                continue;
 //            }
 //            }
 
 
-            if (extractConfig == null) {
-                throw new RuntimeException("该考试下的课程“" + examCourseDto.getCourseName() + "”没有制定调卷规则,不能批量导出,请保存调卷规则生成文件");
-            }
-            if (extractConfig.getIfFinish() == null || extractConfig.getIfFinish() == 0) {
-                throw new RuntimeException("该考试下的课程“" + examCourseDto.getCourseName() + "”考试文件没有生成,不能批量导出,请保存调卷规则生成文件");
-            }
-            checkExamFileExists(examId, examCourseDto.getCourseCode(), exportType, examCourseDto.getCourseName());
-
-            List<ExamPaper> examPapers = extractConfig.getExamPaperList();
-            if (examPapers == null || examPapers.size() < 1) {
-                throw new RuntimeException("该考试下的课程“" + examCourseDto.getCourseName() + "”没有绑定试卷。");
-            }
-            for (ExamPaper examPaper : examPapers) {
-                String paperId = examPaper.getPaper().getId();
-                paperIdMap.put(paperId, examPaper.getGroupCode());
-            }
-            
-            /*Map<String, String> finishedPaperIdMap = extractConfig.getFinishedPaperIdMap();
-            Set<Entry<String, String>> entry = finishedPaperIdMap.entrySet();
-            Iterator<Entry<String, String>> iterator = entry.iterator();
-            while (iterator.hasNext()) {
-                Entry<String, String> next = iterator.next();
-                //paperId为key,paperType为value
-                paperIdMap.put(next.getValue(), next.getKey());
-            }*/
-        }
-        return paperIdMap;
-    }
-
-    /**
-     * 检查试卷文件是否存在
-     *
-     * @param examId
-     */
-    private void checkExamFileExists(String examId, String code, ExportType exportType, String name) {
-        ExamFile examFileCondition = new ExamFile();
-        examFileCondition.setExamId(examId);
-        examFileCondition.setCourseId(code);
-
-        List<ExamFile> examfiles = examFileService.findExamFileListByExamFile(examFileCondition);
-
-        //检查是否都生成了试卷文件
-        boolean paperFlag = false;
-        if (exportType == ExportType.NORMAL) {
-            for (ExamFile examFile : examfiles) {
-                if (examFile.getExamFileType() == ExamFileType.PAPER) {
-                    paperFlag = true;
-                }
-            }
-        } else {
-            for (ExamFile examFile : examfiles) {
-                if (examFile.getExamFileType() == ExamFileType.COMPUTERTEST_PACKAGE) {
-                    paperFlag = true;
-                }
-            }
-        }
-
-        if (!paperFlag) {
-            String message = exportType == ExportType.NORMAL ? "考试文件" : "机考数据包";
-            throw new RuntimeException("该考试下的课程“" + name + "”" + message + "没有生成,不能批量导出,请重新保存调卷规则生成");
-        }
-    }
-
-    /**
-     * 将该考试下的所有课程试卷的结构生成到一张Excel表中
-     *
-     * @param examName
-     * @param paperIds
-     * @param exportStructure
-     * @throws Exception
-     */
-    private void makePaperStructure(String downloadDir, String examName, Map<String, String> paperIds, ExportStructure exportStructure) throws Exception {
-        LOG.info("正在批量生成试卷结构...");
-        List<QuestionTypeNum> questionTypeNums = exportStructure.getQuestionTypeNums();
-        //客观题集合
-        List<ObjectiveQuestionStructure> objectiveQuestionStructureList = new ArrayList<>();
-        //主观题集合
-        List<SubjectiveQuestionStructure> subjectiveQuestionStructureList = new ArrayList<>();
-
-        ExportPaperAbstractService exportPaperAbstractService = PaperUtil.getByRootOrgId(exportStructure.getOrgId());
-        Set<Entry<String, String>> entrySet = paperIds.entrySet();
-        Iterator<Entry<String, String>> iterator = entrySet.iterator();
-
-        int index = 1;
-        while (iterator.hasNext()) {
-            Entry<String, String> entry = iterator.next();
-            String paperId = entry.getKey();
-            String paperType = entry.getValue();
-            LOG.info(index + " - 处理试卷:" + paperId);
-            
-            DownloadPaperDto dto=new DownloadPaperDto();
-            dto.setPaperId(paperId);
-        	dto.setSeqMode(PaperSeqMode.MODE3);
-            PaperExp paperExp = initPaperExpService.initPaperExp(dto);//for export test
-            LOG.info("处理客观题...");
-            //添加客观题
-            List<PaperDetailExp> objectiveDetails = exportPaperAbstractService.getAllObjectiveDetails(paperExp);
-            //得到补齐后的客观题大题
-            List<PaperDetailExp> paperDetailExps = exportPaperAbstractService.fillObjectiveQuestions(objectiveDetails, questionTypeNums);
-            List<ObjectiveQuestionStructure> objectiveList = new ArrayList<>();
-            for (PaperDetailExp paperDetailExp : paperDetailExps) {
-                for (PaperDetailUnitExp unit : paperDetailExp.getPaperDetailUnits()) {
-                    objectiveList.add(new ObjectiveQuestionStructure(paperExp, paperDetailExp, unit, paperType));
-                }
-            }
-            objectiveQuestionStructureList.addAll(objectiveList);
-            LOG.info("处理客观题完成");
-            //添加主观题
-            LOG.info("处理主观题...");
-            List<PaperDetailExp> subjectiveDetails = exportPaperAbstractService.getAllSubjectiveDetails(paperExp);
-            List<SubjectiveQuestionStructure> subjectiveList = new ArrayList<>();
-            for (PaperDetailExp paperDetailExp : subjectiveDetails) {
-                for (PaperDetailUnitExp unit : paperDetailExp.getPaperDetailUnits()) {
-                    subjectiveList.add(new SubjectiveQuestionStructure(paperExp, paperDetailExp, unit, paperType));
-                }
-            }
-            subjectiveQuestionStructureList.addAll(subjectiveList);
-            LOG.info("处理主观题完成");
-            index++;
-        }
-
-
-        ExcelWriter objectiveExcelExporter = new ExcelWriter(ObjectiveQuestionStructure.class);
-        String keguanFileName = examName + "_客观题.xlsx";
-        try (FileOutputStream out1 = getFileOutputStream(downloadDir, keguanFileName);) {
-            objectiveExcelExporter.write(keguanFileName, objectiveQuestionStructureList, out1);
-        } catch (IOException e) {
-            LOG.error(e.getMessage(), e);
-        }
-
-        ExcelWriter subjectiveExcelExporter = new ExcelWriter(SubjectiveQuestionStructure.class);
-        String zhuguanFileName = examName + "_主观题.xlsx";
-        try (FileOutputStream out2 = getFileOutputStream(downloadDir, zhuguanFileName);) {
-            subjectiveExcelExporter.write(zhuguanFileName, subjectiveQuestionStructureList, out2);
-        } catch (IOException e) {
-            LOG.error(e.getMessage(), e);
-        }
-
-        LOG.info("批量生成试卷结构完成");
-    }
-
-    private FileOutputStream getFileOutputStream(String downloadDir, String fileName) throws IOException {
-        File directory = new File(downloadDir);
-        if (!directory.exists()) {
-            directory.mkdirs();
-        }
-        File file = new File(downloadDir + File.separator + fileName);
-        if (!file.exists()) {
-            IoUtils.createFile(file);
-        }
-        return new FileOutputStream(file);
-    }
+			if (extractConfig == null) {
+				throw new RuntimeException("该考试下的课程“" + examCourseDto.getCourseName() + "”没有制定调卷规则,不能批量导出,请保存调卷规则生成文件");
+			}
+			if (extractConfig.getIfFinish() == null || extractConfig.getIfFinish() == 0) {
+				throw new RuntimeException("该考试下的课程“" + examCourseDto.getCourseName() + "”考试文件没有生成,不能批量导出,请保存调卷规则生成文件");
+			}
+			checkExamFileExists(examId, examCourseDto.getCourseCode(), exportType, examCourseDto.getCourseName());
+
+			List<ExamPaper> examPapers = extractConfig.getExamPaperList();
+			if (examPapers == null || examPapers.size() < 1) {
+				throw new RuntimeException("该考试下的课程“" + examCourseDto.getCourseName() + "”没有绑定试卷。");
+			}
+			for (ExamPaper examPaper : examPapers) {
+				String paperId = examPaper.getPaper().getId();
+				paperIdMap.put(paperId, examPaper.getGroupCode());
+			}
+
+			/*
+			 * Map<String, String> finishedPaperIdMap =
+			 * extractConfig.getFinishedPaperIdMap(); Set<Entry<String, String>> entry =
+			 * finishedPaperIdMap.entrySet(); Iterator<Entry<String, String>> iterator =
+			 * entry.iterator(); while (iterator.hasNext()) { Entry<String, String> next =
+			 * iterator.next(); //paperId为key,paperType为value
+			 * paperIdMap.put(next.getValue(), next.getKey()); }
+			 */
+		}
+		return paperIdMap;
+	}
+
+	/**
+	 * 检查试卷文件是否存在
+	 *
+	 * @param examId
+	 */
+	private void checkExamFileExists(String examId, String code, ExportType exportType, String name) {
+		ExamFile examFileCondition = new ExamFile();
+		examFileCondition.setExamId(examId);
+		examFileCondition.setCourseId(code);
+
+		List<ExamFile> examfiles = examFileService.findExamFileListByExamFile(examFileCondition);
+
+		// 检查是否都生成了试卷文件
+		boolean paperFlag = false;
+		if (exportType == ExportType.NORMAL) {
+			for (ExamFile examFile : examfiles) {
+				if (examFile.getExamFileType() == ExamFileType.PAPER) {
+					paperFlag = true;
+				}
+			}
+		} else {
+			for (ExamFile examFile : examfiles) {
+				if (examFile.getExamFileType() == ExamFileType.COMPUTERTEST_PACKAGE) {
+					paperFlag = true;
+				}
+			}
+		}
+
+		if (!paperFlag) {
+			String message = exportType == ExportType.NORMAL ? "考试文件" : "机考数据包";
+			throw new RuntimeException("该考试下的课程“" + name + "”" + message + "没有生成,不能批量导出,请重新保存调卷规则生成");
+		}
+	}
+
+	/**
+	 * 将该考试下的所有课程试卷的结构生成到一张Excel表中
+	 *
+	 * @param examName
+	 * @param paperIds
+	 * @param exportStructure
+	 * @throws Exception
+	 */
+	private void makePaperStructure(String downloadDir, String examName, Map<String, String> paperIds,
+			ExportStructure exportStructure) throws Exception {
+		LOG.info("正在批量生成试卷结构...");
+		List<QuestionTypeNum> questionTypeNums = exportStructure.getQuestionTypeNums();
+		// 客观题集合
+		List<ObjectiveQuestionStructure> objectiveQuestionStructureList = new ArrayList<>();
+		// 主观题集合
+		List<SubjectiveQuestionStructure> subjectiveQuestionStructureList = new ArrayList<>();
+
+		ExportPaperAbstractService exportPaperAbstractService = PaperUtil.getByRootOrgId(exportStructure.getOrgId());
+		Set<Entry<String, String>> entrySet = paperIds.entrySet();
+		Iterator<Entry<String, String>> iterator = entrySet.iterator();
+
+		int index = 1;
+		while (iterator.hasNext()) {
+			Entry<String, String> entry = iterator.next();
+			String paperId = entry.getKey();
+			String paperType = entry.getValue();
+			LOG.info(index + " - 处理试卷:" + paperId);
+
+			DownloadPaperDto dto = new DownloadPaperDto();
+			dto.setPaperId(paperId);
+			dto.setSeqMode(PaperSeqMode.MODE3);
+			PaperExp paperExp = initPaperExpService.initPaperExp(dto);// for export test
+			LOG.info("处理客观题...");
+			// 添加客观题
+			List<PaperDetailExp> objectiveDetails = exportPaperAbstractService.getAllObjectiveDetails(paperExp);
+			// 得到补齐后的客观题大题
+			List<PaperDetailExp> paperDetailExps = exportPaperAbstractService.fillObjectiveQuestions(objectiveDetails,
+					questionTypeNums);
+			List<ObjectiveQuestionStructure> objectiveList = new ArrayList<>();
+			for (PaperDetailExp paperDetailExp : paperDetailExps) {
+				for (PaperDetailUnitExp unit : paperDetailExp.getPaperDetailUnits()) {
+					objectiveList.add(new ObjectiveQuestionStructure(paperExp, paperDetailExp, unit, paperType));
+				}
+			}
+			objectiveQuestionStructureList.addAll(objectiveList);
+			LOG.info("处理客观题完成");
+			// 添加主观题
+			LOG.info("处理主观题...");
+			List<PaperDetailExp> subjectiveDetails = exportPaperAbstractService.getAllSubjectiveDetails(paperExp);
+			List<SubjectiveQuestionStructure> subjectiveList = new ArrayList<>();
+			for (PaperDetailExp paperDetailExp : subjectiveDetails) {
+				for (PaperDetailUnitExp unit : paperDetailExp.getPaperDetailUnits()) {
+					subjectiveList.add(new SubjectiveQuestionStructure(paperExp, paperDetailExp, unit, paperType));
+				}
+			}
+			subjectiveQuestionStructureList.addAll(subjectiveList);
+			LOG.info("处理主观题完成");
+			index++;
+		}
+
+		ExcelWriter objectiveExcelExporter = new ExcelWriter(ObjectiveQuestionStructure.class);
+		String keguanFileName = examName + "_客观题.xlsx";
+		try (FileOutputStream out1 = getFileOutputStream(downloadDir, keguanFileName);) {
+			objectiveExcelExporter.write(keguanFileName, objectiveQuestionStructureList, out1);
+		} catch (IOException e) {
+			LOG.error(e.getMessage(), e);
+		}
+
+		ExcelWriter subjectiveExcelExporter = new ExcelWriter(SubjectiveQuestionStructure.class);
+		String zhuguanFileName = examName + "_主观题.xlsx";
+		try (FileOutputStream out2 = getFileOutputStream(downloadDir, zhuguanFileName);) {
+			subjectiveExcelExporter.write(zhuguanFileName, subjectiveQuestionStructureList, out2);
+		} catch (IOException e) {
+			LOG.error(e.getMessage(), e);
+		}
+
+		LOG.info("批量生成试卷结构完成");
+	}
+
+	private FileOutputStream getFileOutputStream(String downloadDir, String fileName) throws IOException {
+		File directory = new File(downloadDir);
+		if (!directory.exists()) {
+			directory.mkdirs();
+		}
+		File file = new File(downloadDir + File.separator + fileName);
+		if (!file.exists()) {
+			IoUtils.createFile(file);
+		}
+		return new FileOutputStream(file);
+	}
 
 
 }
 }

+ 1227 - 1136
examcloud-core-questions-service/src/main/java/cn/com/qmth/examcloud/core/questions/service/impl/ExtractConfigServiceImpl.java

@@ -1,6 +1,5 @@
 package cn.com.qmth.examcloud.core.questions.service.impl;
 package cn.com.qmth.examcloud.core.questions.service.impl;
 
 
-
 import static cn.com.qmth.examcloud.core.questions.service.cache.Constants.CACHE_KEY_PAPER_FOR_DTO;
 import static cn.com.qmth.examcloud.core.questions.service.cache.Constants.CACHE_KEY_PAPER_FOR_DTO;
 import static cn.com.qmth.examcloud.core.questions.service.cache.Constants.DEFAULT_TIME_OUT;
 import static cn.com.qmth.examcloud.core.questions.service.cache.Constants.DEFAULT_TIME_OUT;
 
 
@@ -17,6 +16,7 @@ import java.util.regex.Pattern;
 import java.util.stream.Collectors;
 import java.util.stream.Collectors;
 
 
 import org.apache.commons.lang3.StringUtils;
 import org.apache.commons.lang3.StringUtils;
+import org.bson.types.ObjectId;
 import org.nlpcn.commons.lang.util.StringUtil;
 import org.nlpcn.commons.lang.util.StringUtil;
 import org.slf4j.Logger;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.slf4j.LoggerFactory;
@@ -29,6 +29,7 @@ import org.springframework.data.domain.PageRequest;
 import org.springframework.data.mongodb.core.MongoTemplate;
 import org.springframework.data.mongodb.core.MongoTemplate;
 import org.springframework.data.mongodb.core.query.Criteria;
 import org.springframework.data.mongodb.core.query.Criteria;
 import org.springframework.data.mongodb.core.query.Query;
 import org.springframework.data.mongodb.core.query.Query;
+import org.springframework.data.mongodb.core.query.Update;
 import org.springframework.stereotype.Service;
 import org.springframework.stereotype.Service;
 import org.springframework.util.Assert;
 import org.springframework.util.Assert;
 import org.springframework.util.CollectionUtils;
 import org.springframework.util.CollectionUtils;
@@ -36,6 +37,10 @@ import org.springframework.util.CollectionUtils;
 import cn.com.qmth.examcloud.api.commons.security.bean.User;
 import cn.com.qmth.examcloud.api.commons.security.bean.User;
 import cn.com.qmth.examcloud.api.commons.security.bean.UserDataRule;
 import cn.com.qmth.examcloud.api.commons.security.bean.UserDataRule;
 import cn.com.qmth.examcloud.commons.exception.StatusException;
 import cn.com.qmth.examcloud.commons.exception.StatusException;
+import cn.com.qmth.examcloud.core.oe.admin.api.ExamRecordCloudService;
+import cn.com.qmth.examcloud.core.oe.admin.api.request.CheckPaperInExamReq;
+import cn.com.qmth.examcloud.core.oe.admin.api.response.CheckPaperInExamResp;
+import cn.com.qmth.examcloud.core.oe.student.api.ExamRecordDataCloudService;
 import cn.com.qmth.examcloud.core.questions.base.BeanCopierUtil;
 import cn.com.qmth.examcloud.core.questions.base.BeanCopierUtil;
 import cn.com.qmth.examcloud.core.questions.base.CommonUtils;
 import cn.com.qmth.examcloud.core.questions.base.CommonUtils;
 import cn.com.qmth.examcloud.core.questions.base.Model;
 import cn.com.qmth.examcloud.core.questions.base.Model;
@@ -89,1156 +94,1242 @@ import cn.com.qmth.examcloud.web.redis.RedisClient;
  */
  */
 @Service("extractConfigService")
 @Service("extractConfigService")
 public class ExtractConfigServiceImpl implements ExtractConfigService {
 public class ExtractConfigServiceImpl implements ExtractConfigService {
-    private static final Logger LOG = LoggerFactory.getLogger(ExtractConfigServiceImpl.class);
+	private static final Logger LOG = LoggerFactory.getLogger(ExtractConfigServiceImpl.class);
 
 
-    @Autowired
-    private ExtractConfigRepo extractConfigRepo;
+	@Autowired
+	private ExtractConfigRepo extractConfigRepo;
 
 
-    @Autowired
-    private PaperDetailRepo paperDetailRepo;
+	@Autowired
+	private PaperDetailRepo paperDetailRepo;
 
 
-    @Autowired
-    private PaperDetailUnitRepo paperDetailUnitRepo;
+	@Autowired
+	private PaperDetailUnitRepo paperDetailUnitRepo;
 
 
-    @Autowired
-    private AudioTimeConfigRepo audioTimeConfigRepo;
+	@Autowired
+	private AudioTimeConfigRepo audioTimeConfigRepo;
 
 
-    @Autowired
-    private PaperRepo paperRepo;
+	@Autowired
+	private PaperRepo paperRepo;
 
 
-    @Autowired
-    private QuesService quesService;
+	@Autowired
+	private QuesService quesService;
 
 
-    @Autowired
-    private QuestionAudioService questionAudioService;
+	@Autowired
+	private QuestionAudioService questionAudioService;
 
 
-    @Autowired
-    private MongoTemplate mongoTemplate;
+	@Autowired
+	private MongoTemplate mongoTemplate;
 
 
-    @Autowired
-    private CourseService courseService;
+	@Autowired
+	private CourseService courseService;
 //
 //
 //    @Autowired
 //    @Autowired
 //    private SysProperty sysProperty;
 //    private SysProperty sysProperty;
 
 
-    @Autowired
-    private PaperDtoAssembler paperDtoAssembler;
-
-    @Autowired
-    private PaperDetailDtoAssembler paperDetailDtoAssembler;
-
-    @Autowired
-    private PaperDetailUnitDtoAssembler paperDetailUnitDtoAssembler;
-
-    @Autowired
-    private SubQuestionDtoAssembler subQuestionDtoAssembler;
-
-    @Autowired
-    private RedisClient redisClient;
-
-    /*@Autowired
-    private PaperDetailUnitNativeRepo detailUnitNativeRepo;*/
-
-    @Autowired
-    private ExamCloudService examCloudService;
-
-    @Override
-    public ExtractConfig findConfig(ExtractConfig condition) {
-        if (condition.getExamId() == null) {
-            return null;
-        }
-        if (StringUtils.isBlank(condition.getCourseCode())) {
-            return null;
-        }
-        Query query = new Query();
-        if (!StringUtils.isBlank(condition.getOrgId())) {
-            query.addCriteria(Criteria.where("orgId").is(condition.getOrgId()));
-        }
-        query.addCriteria(Criteria.where("examId").is(condition.getExamId()));
-        query.addCriteria(Criteria.where("courseCode").is(condition.getCourseCode()));
-        ExtractConfig tempConfig = this.mongoTemplate.findOne(query, ExtractConfig.class);
-        return tempConfig;
-    }
-
-    @Override
-    public Map<String, String> saveExtractConfig2(ExtractConfig extractConfig, User user) throws Exception {
-        List<ExamPaper> examPapers = extractConfig.getExamPaperList();
-        for (int i = 0; i < examPapers.size(); i++) {
-            ExamPaper examPaper = examPapers.get(i);
-            Paper paper = examPaper.getPaper();
-            paper = Model.of(paperRepo.findById(paper.getId()));
-            examPaper.setPaper(paper);
-        }
-        Course course = courseService.getCourse(Long.valueOf(extractConfig.getOrgId()), extractConfig.getCourseCode());
-        extractConfig.setCourse(course);
-        extractConfig.setCourseName(course.getName());
-        Map<String, String> newFinishedPaperIdMap = makePaperByConfig(extractConfig);
-        extractConfig.setFinishedPaperIdMap(newFinishedPaperIdMap);
-        extractConfig.setIfFinish((short) 1);
-        extractConfigRepo.save(extractConfig);
-        return newFinishedPaperIdMap;
-    }
-
-    @Override
-    public List<ExamPaper> saveExtractConfig(ExtractConfig extractConfig, User user) {
-        List<ExamPaper> examPapers = extractConfig.getExamPaperList();
-        for (int i = 0; i < examPapers.size(); i++) {
-            ExamPaper examPaper = examPapers.get(i);
-            Paper paper = examPaper.getPaper();
-            paper = Model.of(paperRepo.findById(paper.getId()));
-            examPaper.setPaper(paper);
-            if(ExamType.OFFLINE.name().equals(extractConfig.getExamType())) {
-            	checkOfflinePaper(paper);
-            }
-        }
-        Course course = courseService.getCourse(Long.valueOf(extractConfig.getOrgId()), extractConfig.getCourseCode());
-        extractConfig.setCourse(course);
-        extractConfig.setCourseName(course.getName());
-        extractConfig.setIfFinish((short) 1);
-        extractConfigRepo.save(extractConfig);
-        return examPapers;
-    }
-    
-    private void checkOfflinePaper(Paper paper) {
-    	List<PaperDetailUnit> pdus=paperDetailUnitRepo.findByPaper(paper);
-    	if(pdus==null||pdus.size()==0) {
-    		return;
-    	}
-    	for(PaperDetailUnit pdu:pdus) {
-    		if (pdu.getQuestionType() == QuesStructType.SINGLE_ANSWER_QUESTION
-                    || pdu.getQuestionType() == QuesStructType.MULTIPLE_ANSWER_QUESTION
-                    || pdu.getQuestionType() == QuesStructType.BOOL_ANSWER_QUESTION){
-    			throw new StatusException("500", "试卷包含客观题,无法保存规则");
-    		}else if(pdu.getQuestionType() == QuesStructType.NESTED_ANSWER_QUESTION&&!CollectionUtils.isEmpty(pdu.getQuestion().getSubQuestions())) {
-    			for(Question q:pdu.getQuestion().getSubQuestions()) {
-    				if (q.getQuestionType() == QuesStructType.SINGLE_ANSWER_QUESTION
-    	                    || q.getQuestionType() == QuesStructType.MULTIPLE_ANSWER_QUESTION
-    	                    || q.getQuestionType() == QuesStructType.BOOL_ANSWER_QUESTION){
-    	    			throw new StatusException("500", "试卷包含客观题,无法保存规则");
-    	    		}
-    			}
-    		}
-    	}
-    }
-
-
-    @Override
-    public ExtractConfig findConfigById(String id) {
-        if (StringUtils.isBlank(id)) {
-            return null;
-        }
-        return Model.of(extractConfigRepo.findById(id));
-    }
-
-    @Override
-    public Map<String, Object> extractExamPaper(Long exam_id, String course_code, String group_code) {
-        Map<String, Object> returnMap = new HashMap<>();
-        LOG.info("调卷开始...");
-        long beginTime = System.currentTimeMillis();
-        LOG.info("开始根据examId:" + exam_id + "和courseCode:" + course_code + "获取调卷规则");
-        ExtractConfig extractConfig = this.findConfig(new ExtractConfig(exam_id, course_code));
-        if (extractConfig == null) {
-            LOG.error("该考试和课程下调卷规则未制定,请先制定调卷规则,调卷程序退出");
-            returnMap.put("errorMsg", "该考试和课程下调卷规则未制定,请先制定调卷规则");
-            return returnMap;
-        }
-        long configFinishTime = System.currentTimeMillis();
-        LOG.info("获取调卷规则共耗时:" + (configFinishTime - beginTime) + "ms");
-        LOG.info("根据调卷规则中设置的概率获取类型为" + group_code + "的试卷");
-        Map<String, Paper> paperMap = this.getExamPaperByProbability(extractConfig.getExamPaperList());
-        if (paperMap.isEmpty()) {
-            LOG.error("该考试和课程下调卷规则中试卷不存在,请检查调卷规则,调卷程序退出");
-            returnMap.put("errorMsg", "该考试和课程下调卷规则中试卷不存在,请重新制定调卷规则");
-            return returnMap;
-        }
-
-        long paperMapFinishTime = System.currentTimeMillis();
-        LOG.info("获取类型为" + group_code + "的试卷共耗时:" + (paperMapFinishTime - configFinishTime) + "ms");
-
-        Paper basePaper = paperMap.get(group_code);
-        if (basePaper == null) {
-            LOG.error("该考试和课程下调卷规则中该类型试卷不存在,请检查调卷规则,调卷程序退出");
-            returnMap.put("errorMsg", "该考试和课程下调卷规则中该类型试卷不存在,请重新制定调卷规则");
-            return returnMap;
-        }
-        String basePaperId = basePaper.getId();
-        LOG.info("将原始试卷:" + basePaperId + "根据规则重新组卷");
-        int upSetQuestionOrder = extractConfig.getScrambling_the_question_order();
-        int upSetOptionOrder = extractConfig.getScrambling_the_option_order();
-        //不乱序直接调卷
-        if (upSetQuestionOrder == 0 && upSetOptionOrder == 0) {
-            PaperDto paperDto = getPaperDtoByPaper(basePaper, basePaperId);
-            long paperDtoFinishTime = System.currentTimeMillis();
-            LOG.info("获取试卷Dto共耗时:" + (paperDtoFinishTime - paperMapFinishTime) + "ms");
-            returnMap.put("paperDto", paperDto);
-            LOG.info("调卷完成");
-            LOG.info("总共耗时:" + (System.currentTimeMillis() - beginTime) + "ms");
-        } else {
-            //乱序重新生成试卷
-            Paper newPaper = this.recombinationPaper(basePaper, PaperType.STUDENT_EXAM, upSetQuestionOrder, upSetOptionOrder);
-            LOG.info("根据新试卷 paperId:" + newPaper.getId() + "组装PaperDto后返回");
-
-            long genPaperFinishTime = System.currentTimeMillis();
-            LOG.info("组卷共耗时:" + (genPaperFinishTime - paperMapFinishTime) + "ms");
-            PaperDto paperDto = getPaperDtoByPaper(newPaper, basePaperId);
-
-            long paperDtoFinishTime = System.currentTimeMillis();
-            LOG.info("获取试卷Dto共耗时:" + (paperDtoFinishTime - genPaperFinishTime) + "ms");
-
-            returnMap.put("paperDto", paperDto);
-            LOG.info("调卷完成");
-            LOG.info("总共耗时:" + (System.currentTimeMillis() - beginTime) + "ms");
-        }
-        return returnMap;
-    }
-
-    @Override
-    public boolean checkIsAllQbjectiveQuestion(String paperId) {
-        //优先从redis中获取缓存dto
-        PaperDto cachePaperDto = redisClient.get(CACHE_KEY_PAPER_FOR_DTO + paperId, PaperDto.class, DEFAULT_TIME_OUT);
-        if (cachePaperDto != null) {
-            return cachePaperDto.isAllQbjectiveQuestion();
-        }
-
-        Paper paper = Model.of(paperRepo.findById(paperId));
-        List<PaperDetailUnit> paperDetailUnits = paperDetailUnitRepo.findByPaperOrderByNumber(paper);
-        for (PaperDetailUnit paperDetailUnit : paperDetailUnits) {
-            Question question = paperDetailUnit.getQuestion();
-            //填空或问答
-            if (question.getQuestionType() == QuesStructType.FILL_BLANK_QUESTION
-                    || question.getQuestionType() == QuesStructType.TEXT_ANSWER_QUESTION) {
-                return false;
-            }
-            if (question.getQuestionType() == QuesStructType.NESTED_ANSWER_QUESTION) {
-                List<Question> subQuestions = question.getSubQuestions();
-                for (Question subQuestion : subQuestions) {
-                    if (subQuestion.getQuestionType() == QuesStructType.FILL_BLANK_QUESTION
-                            || subQuestion.getQuestionType() == QuesStructType.TEXT_ANSWER_QUESTION) {
-                        return false;
-                    }
-                }
-            }
-        }
-        return true;
-    }
-
-    public boolean checkIsAllQbjectiveByPdu(List<PaperDetailUnit> paperDetailUnits) {
-        for (PaperDetailUnit paperDetailUnit : paperDetailUnits) {
-            Question question = paperDetailUnit.getQuestion();
-            //填空或问答
-            if (question.getQuestionType() == QuesStructType.FILL_BLANK_QUESTION
-                    || question.getQuestionType() == QuesStructType.TEXT_ANSWER_QUESTION) {
-                return false;
-            }
-            if (question.getQuestionType() == QuesStructType.NESTED_ANSWER_QUESTION) {
-                List<Question> subQuestions = question.getSubQuestions();
-                for (Question subQuestion : subQuestions) {
-                    if (subQuestion.getQuestionType() == QuesStructType.FILL_BLANK_QUESTION
-                            || subQuestion.getQuestionType() == QuesStructType.TEXT_ANSWER_QUESTION) {
-                        return false;
-                    }
-                }
-            }
-        }
-        return true;
-    }
-
-    @Override
-    public Map<String, String> makePaperByConfig(ExtractConfig extractConfig) {
-        Map<String, String> finishedPaperIdMap = new HashMap<>();
-        if (extractConfig == null) {
-            throw new RuntimeException("调卷规则不存在");
-        }
-        //获得规则中设置的试卷
-        Map<String, Paper> paperMap = this.getExamPaperByProbability(extractConfig.getExamPaperList());
-        if (paperMap.isEmpty()) {
-            throw new RuntimeException("抽取试卷失败");
-        }
-        for (Map.Entry<String, Paper> entry : paperMap.entrySet()) {
-            String key = entry.getKey();
-            //根据原有试卷重新组卷得到新试卷
-        	/*Paper newPaper = this.recombinationPaper(entry.getValue(), 
-             PaperType.PREVIEW,
-             extractConfig.getScrambling_the_question_order(),
-             extractConfig.getScrambling_the_option_order());*/
-            finishedPaperIdMap.put(key, entry.getValue().getId());
-        }
-        return finishedPaperIdMap;
-    }
-
-    /**
-     * 重组试卷,生成新的试卷
-     *
-     * @param paper              选中的试卷
-     * @param upSetQuestionOrder 客观题小题乱序		1:乱序  0:不乱序
-     * @param upSetOptionOrder   客观题选项乱序		1:乱序  0:不乱序
-     * @return
-     */
-    public Paper recombinationPaper(Paper paper, PaperType paperType, int upSetQuestionOrder, int upSetOptionOrder) {
-
-        //将小题全部取出来,只取一次
-        List<PaperDetailUnit> allPaperDetailUnits = paperDetailUnitRepo.findByPaperOrderByNumber(paper);
-        //获取大题
-        List<PaperDetail> paperDetails = paperDetailRepo.findByPaperOrderByNumber(paper);
-
-        //抽取大题号对应的小题
-        Map<String, List<PaperDetailUnit>> pduMap = allPaperDetailUnits.stream()
-                .collect(Collectors.groupingBy(PaperDetailUnit::getDetailId));
-        //最终保存的所有小题
-        List<PaperDetailUnit> savePaperDetailUnits = new ArrayList<>();
-        //保存试卷信息
-        paper.setId(null);
-        paper.setPaperType(paperType);
-        Paper newPaper = paperRepo.insert(paper);
-
-        for (int i = 0; i < paperDetails.size(); i++) {
-            PaperDetail paperDetail = paperDetails.get(i);
-
-            List<PaperDetailUnit> paperDetailUnits = pduMap.get(paperDetail.getId());
-            if (paperDetailUnits == null || paperDetailUnits.size() == 0) {
-                continue;
-            }
-            Collections.sort(paperDetailUnits);
-
-            //将大题中最小的number取出
-            PaperDetailUnit topDetailUnit = paperDetailUnits.get(0);
-            int minNumber = topDetailUnit.getNumber();
-
-            //小题乱序
-            if (paperDetailUnits != null && paperDetailUnits.size() > 0) {
-                if ((topDetailUnit.getQuestionType() == QuesStructType.SINGLE_ANSWER_QUESTION
-                        || topDetailUnit.getQuestionType() == QuesStructType.MULTIPLE_ANSWER_QUESTION
-                        || topDetailUnit.getQuestionType() == QuesStructType.BOOL_ANSWER_QUESTION)
-                        && upSetQuestionOrder == 1) {
-                    Collections.shuffle(paperDetailUnits);//打乱小题List
-                }
-            }
-            //设置大题信息
-            paperDetail.setId(null);
-            paperDetail.setPaper(newPaper);
-
-            for (int j = 0; j < paperDetailUnits.size(); j++) {
-                //重新设置保存PaperDetailUnit
-                PaperDetailUnit paperDetailUnit = paperDetailUnits.get(j);
-                paperDetailUnit.setPaperType(paperType);
-                paperDetailUnit.setPaper(newPaper);
-                paperDetailUnit.setPaperDetail(paperDetail);
-                paperDetailUnit.setNumber(minNumber + j);            //重新设置序号
-                reSavePaperDetailUtilAndQuestion(paperDetailUnit, upSetOptionOrder);
-                savePaperDetailUnits.add(paperDetailUnit);
-            }
-
-        }
-        //保存大题信息
-        paperDetailRepo.insert(paperDetails);
-        //保存小题信息
-        paperDetailUnitRepo.insert(savePaperDetailUnits);
-
-
-        //清空所有list
-        allPaperDetailUnits.clear();
-        savePaperDetailUnits.clear();
-        paperDetails.clear();
-
-        return newPaper;
-    }
-
-    /**
-     * 每个试卷类型取出一套试卷
-     * {
-     * A:Paper,
-     * B:Paper
-     * }
-     * A是试卷类型   Paper是A类型下选定的试卷
-     *
-     * @param examPaperList
-     * @return
-     */
-    private Map<String, Paper> getExamPaperByProbability(List<ExamPaper> examPaperList) {
-        Map<String, Paper> paperByTypeMap = new HashMap<>();
-        if (examPaperList == null || examPaperList.size() == 0) {
-            throw new RuntimeException("可供抽取的试卷集合为空,无法抽取试卷");
-        }
-
-        Map<String, List<ExamPaper>> examPaperMap = new HashMap<>();
-        for (int i = 0; i < examPaperList.size(); i++) {
-            ExamPaper examPaper = examPaperList.get(i);
-            if (!examPaperMap.containsKey(examPaper.getGroupCode())) {
-                if (examPaper.getPaper() != null) {
-                    List<ExamPaper> epList = new ArrayList<>();
-                    epList.add(examPaper);
-                    examPaperMap.put(examPaper.getGroupCode(), epList);
-                }
-            } else {
-                if (examPaper.getPaper() != null) {
-                    List<ExamPaper> epList = examPaperMap.get(examPaper.getGroupCode());
-                    epList.add(examPaper);
-                }
-            }
-        }
-
-        if (examPaperMap != null) {
-            Set<String> keys = examPaperMap.keySet();
-            Iterator<String> it = keys.iterator();
-            while (it.hasNext()) {
-                String key = it.next();
-                Paper paper = this.getPaperByProbability(examPaperMap.get(key));
-
-                if (paper == null) {
-                    continue;
-                }
-
-                //不能用原来的paper对象,否则examPaperList中的paper对象会被覆盖
-                Paper newPaper = Model.of(paperRepo.findById(paper.getId()));
-                paperByTypeMap.put(key, newPaper);
-            }
-        }
-
-        return paperByTypeMap;
-    }
-
-    /**
-     * 根据设定几率取出一套试卷
-     *
-     * @param examPaperList
-     * @return
-     */
-    private Paper getPaperByProbability(List<ExamPaper> examPaperList) {
-        int sum = 0;
-        for (int i = 0; i < examPaperList.size(); i++) {
-            sum += examPaperList.get(i).getWeight();
-        }
-
-        // 从1开始  
-        Integer rand = new Random().nextInt(sum) + 1;
-        for (int i = 0; i < examPaperList.size(); i++) {
-            rand -= examPaperList.get(i).getWeight();
-            // 选中
-            if (rand <= 0) {
-                return examPaperList.get(i).getPaper();
-            }
-        }
-
-        return null;
-    }
-
-    /**
-     * 重新设置并保存paperDetailUnit和question
-     *
-     * @param paperDetailUnit
-     * @param upSetOptionOrder
-     */
-    private void reSavePaperDetailUtilAndQuestion(PaperDetailUnit paperDetailUnit, Integer upSetOptionOrder) {
-        Question question = paperDetailUnit.getQuestion();
-        //选项乱序
-        if (upSetOptionOrder == 1) {
-            //单选或多选
-            if (question.getQuestionType() == QuesStructType.SINGLE_ANSWER_QUESTION ||
-                    question.getQuestionType() == QuesStructType.MULTIPLE_ANSWER_QUESTION) {
-                List<String> numberList = new ArrayList<>();
-                List<QuesOption> options = question.getQuesOptions();
-                for (int k = 0; k < options.size(); k++) {
-                    QuesOption quesOption = options.get(k);
-                    numberList.add(quesOption.getNumber());
-                }
-                Collections.shuffle(numberList);                      //打乱number顺序
-                paperDetailUnit.setOptionOrder(StringUtils.join(numberList.toArray(), ","));//设置option顺序
-            }
-            //套题,套题下小题不乱序,选择题选项乱序
-            if (question.getQuestionType() == QuesStructType.NESTED_ANSWER_QUESTION) {
-                List<Question> subQuestions = question.getSubQuestions();
-                StringBuffer optionOrder = new StringBuffer();
-                for (int m = 0; m < subQuestions.size(); m++) {
-                    Question subQuestion = subQuestions.get(m);
-                    if (subQuestion.getQuestionType() == QuesStructType.SINGLE_ANSWER_QUESTION ||
-                            subQuestion.getQuestionType() == QuesStructType.MULTIPLE_ANSWER_QUESTION) {
-                        List<String> numberList = new ArrayList<>();
-                        List<QuesOption> options = subQuestion.getQuesOptions();
-                        for (int n = 0; n < options.size(); n++) {
-                            QuesOption quesOption = options.get(n);
-                            numberList.add(quesOption.getNumber());
-                        }
-                        Collections.shuffle(numberList);                      //打乱number顺序
-                        optionOrder.append(StringUtils.join(numberList.toArray(), ",")).append(";");
-                    }
-                }
-                paperDetailUnit.setOptionOrder(optionOrder.toString());         //设置option顺序
-            }
-        }
-        paperDetailUnit.setId(null);
-    }
-
-    @Override
-    public List<String> getExamPaperId(String courseCode, String orgId) {
-        Assert.hasLength(courseCode, "courseCode不能为空");
-        Assert.hasLength(orgId, "orgId不能为空");
-        List<String> paperIdList = new ArrayList<>();
-        Query query = new Query();
-        query.addCriteria(Criteria.where("courseCode").is(courseCode));
-        query.addCriteria(Criteria.where("orgId").is(orgId));
-        List<ExtractConfig> extractConfigList = this.mongoTemplate.find(query, ExtractConfig.class);
-        for (ExtractConfig extractConfig : extractConfigList) {
-            List<ExamPaper> examPaperList = extractConfig.getExamPaperList();
-            if (examPaperList != null && examPaperList.size() > 0) {
-                for (ExamPaper examPaper : examPaperList) {
-                    paperIdList.add(examPaper.getPaper().getId());
-                }
-            }
-        }
-        return paperIdList;
-    }
-
-    /**
-     * 根据paper得到PaperDto
-     *
-     * @param paper
-     * @return
-     */
-    @SuppressWarnings("unchecked")
-    private PaperDto getPaperDtoByPaper(Paper paper, String basePaperId) {
-        long beginTime = System.currentTimeMillis();
-        //没有则重新组装
-        PaperDto paperDto = paperDtoAssembler.toDto(paper);
-        paperDto.setBasePaperId(basePaperId);
-        paperDto.setAllQbjectiveQuestion(checkIsAllQbjectiveQuestion(basePaperId));
-
-        long paperDtoEndTime = System.currentTimeMillis();
-        LOG.info("单独组装paperDto耗时:" + (paperDtoEndTime - beginTime) + "ms");
-
-        //将小题全部取出来,只取一次
-        List<PaperDetailUnit> allPaperDetailUnits = paperDetailUnitRepo.findByPaper(paper);
-        long pduEndTime = System.currentTimeMillis();
-        LOG.info("数据库取小题耗时:" + (pduEndTime - paperDtoEndTime) + "ms");
-        Collections.sort(allPaperDetailUnits);
-        long pduSortEndTime = System.currentTimeMillis();
-        LOG.info("排序小题耗时:" + (pduSortEndTime - pduEndTime) + "ms");
-
-        //获取大题
-        List<PaperDetail> paperDetails = paperDetailRepo.findByPaper(paper);
-        long pdEndTime = System.currentTimeMillis();
-        LOG.info("数据库取大题耗时:" + (pdEndTime - pduSortEndTime) + "ms");
-        Collections.sort(paperDetails);
-        long pdSortEndTime = System.currentTimeMillis();
-        LOG.info("排序大题耗时:" + (pdSortEndTime - pdEndTime) + "ms");
-
-        //抽取大题Id对应的小题
-        Map<String, List<PaperDetailUnit>> pduMap = allPaperDetailUnits.stream()
-                .collect(Collectors.groupingBy(PaperDetailUnit::getDetailId));
-        long pduMapEndTime = System.currentTimeMillis();
-        LOG.info("获取大题与小题对应关系耗时:" + (pduMapEndTime - pdSortEndTime) + "ms");
-
-        // 获取大题Dto
-        List<PaperDetailDto> paperDetailDtos = paperDetailDtoAssembler.toDtoList(paperDetails);
-        paperDto.setPaperDetails(paperDetailDtos);
-        long paperDetailDtoEndTime = System.currentTimeMillis();
-        LOG.info("单独组装paperDetailDto耗时:" + (paperDetailDtoEndTime - pduMapEndTime) + "ms");
-
-        // 封装小题
-        for (int i = 0; i < paperDetailDtos.size(); i++) {
-            //根据大题查出大题下面的小题
-            PaperDetail paperDetail = paperDetails.get(i);
-
-            List<PaperDetailUnit> paperDetailUnits = pduMap.get(paperDetail.getId());
-
-            List<PaperDetailUnitDto> paperDetailUnitDtos = new ArrayList<>();
-            for (int j = 0; j < paperDetailUnits.size(); j++) {
-                PaperDetailUnit paperDetailUnit = paperDetailUnits.get(j);
-                if (paperDetailUnit == null || paperDetailUnit.getQuestion() == null) {
-                    break;
-                }
-                //设置答案
-                setSelectQuestionAnswerUnit(paperDetailUnit);
-
-                PaperDetailUnitDto unitDto = paperDetailUnitDtoAssembler.toDto(paperDetailUnit);
-                /**
-                 * 此处不能传questionId,需要传paperDetailUnitId
-                 * 因为选项乱序在paperDetailUnit里
-                 * unitDto.setQuesId(paperDetailUnit.getQuestion().getId());
-                 */
-                unitDto.setQuesId(paperDetailUnit.getId());
-                String answer = paperDetailUnit.getQuestion().getQuesAnswer();
-                if (StringUtils.isNotEmpty(answer)) {
-                    unitDto.setAnswer(answer);
-                }
-                if (unitDto.getQuestionType() == QuesStructType.NESTED_ANSWER_QUESTION) {// 假如是套题
-                    List<Question> subQuesList = paperDetailUnit.getQuestion().getSubQuestions();
-                    List<SubQuestionDto> subQuesDtos = subQuestionDtoAssembler.toDtoList(subQuesList);
-                    for (int m = 0; m < subQuesList.size(); m++) {
-                        List<QuesOptionDto> quesOptionDtos = subQuestionDtoAssembler.toOptionDtoList(subQuesList.get(m).getQuesOptions());
-                        subQuesDtos.get(m).setQuesOptions(quesOptionDtos);
-                        if (StringUtils.isNotEmpty(subQuesList.get(m).getQuesAnswer())) {
-                            subQuesDtos.get(m).setQuesAnswer(subQuesList.get(m).getQuesAnswer());
-                        }
-                        subQuesDtos.get(m).setNumber(m + 1);
-                        //套题分数从小题类中取值
-                        subQuesDtos.get(m).setScore(paperDetailUnit.getSubScoreList().get(m));
-                    }
-                    unitDto.setSubQuestions(subQuesDtos);
-                }
-                paperDetailUnitDtos.add(unitDto);
-            }
-            paperDetailDtos.get(i).setPaperDetailUnits(paperDetailUnitDtos);
-            paperDetailDtos.get(i).setCnNum(CommonUtils.toCHNum(paperDetailDtos.get(i).getNumber()));
-        }
-        long paperDetailUnitDtoEndTime = System.currentTimeMillis();
-        LOG.info("单独组装paperDetailUnitDto耗时:" + (paperDetailUnitDtoEndTime - paperDetailDtoEndTime) + "ms");
-
-        //将重新组装的dto放进缓存
-        redisClient.set(CACHE_KEY_PAPER_FOR_DTO + paperDto.getId(), paperDto, DEFAULT_TIME_OUT);
-        return paperDto;
-    }
-
-    /**
-     * 测试获取paperDto
-     *
-     * @param basePaperId
-     * @return
-     */
-    @Deprecated
-    public PaperDto getPaperDtoByPaperNew(String basePaperId) {
-
-        long beginTime = System.currentTimeMillis();
-        //没有则重新组装
-        Paper paper = Model.of(paperRepo.findById(basePaperId));
-        PaperDto paperDto = paperDtoAssembler.toDto(paper);
-        paperDto.setBasePaperId(basePaperId);
-
-        long paperDtoEndTime = System.currentTimeMillis();
-        LOG.info("单独组装paperDto耗时:" + (paperDtoEndTime - beginTime) + "ms");
-
-        //将小题全部取出来,只取一次
-        // List<PaperDetailUnit> allPaperDetailUnits = detailUnitNativeRepo.findByPaperId(paper.getId());
-        List<PaperDetailUnit> allPaperDetailUnits = new ArrayList<>();
-
-        long pduEndTime = System.currentTimeMillis();
-        LOG.info("数据库取小题耗时:" + (pduEndTime - paperDtoEndTime) + "ms");
-        Collections.sort(allPaperDetailUnits);
-        long pduSortEndTime = System.currentTimeMillis();
-        LOG.info("排序小题耗时:" + (pduSortEndTime - pduEndTime) + "ms");
-
-
-        paperDto.setAllQbjectiveQuestion(checkIsAllQbjectiveByPdu(allPaperDetailUnits));
-        long isAllObjEndtime = System.currentTimeMillis();
-        LOG.info("设置客观题耗时:" + (isAllObjEndtime - pduSortEndTime) + "ms");
-
-
-        //获取大题
-        List<PaperDetail> paperDetails = paperDetailRepo.findByPaper(paper);
-        long pdEndTime = System.currentTimeMillis();
-        LOG.info("数据库取大题耗时:" + (pdEndTime - isAllObjEndtime) + "ms");
-        Collections.sort(paperDetails);
-        long pdSortEndTime = System.currentTimeMillis();
-        LOG.info("排序大题耗时:" + (pdSortEndTime - pdEndTime) + "ms");
-
-        //抽取大题Id对应的小题
-        Map<String, List<PaperDetailUnit>> pduMap = allPaperDetailUnits.stream()
-                .collect(Collectors.groupingBy(PaperDetailUnit::getDetailId));
-        long pduMapEndTime = System.currentTimeMillis();
-        LOG.info("获取大题与小题对应关系耗时:" + (pduMapEndTime - pdSortEndTime) + "ms");
-
-        // 获取大题Dto
-        List<PaperDetailDto> paperDetailDtos = paperDetailDtoAssembler.toDtoList(paperDetails);
-        paperDto.setPaperDetails(paperDetailDtos);
-        long paperDetailDtoEndTime = System.currentTimeMillis();
-        LOG.info("单独组装paperDetailDto耗时:" + (paperDetailDtoEndTime - pduMapEndTime) + "ms");
-
-        // 封装小题
-        for (int i = 0; i < paperDetailDtos.size(); i++) {
-            //根据大题查出大题下面的小题
-            PaperDetail paperDetail = paperDetails.get(i);
-
-            List<PaperDetailUnit> paperDetailUnits = pduMap.get(paperDetail.getId());
-
-            List<PaperDetailUnitDto> paperDetailUnitDtos = new ArrayList<>();
-            for (int j = 0; j < paperDetailUnits.size(); j++) {
-                PaperDetailUnit paperDetailUnit = paperDetailUnits.get(j);
-                if (paperDetailUnit == null || paperDetailUnit.getQuestion() == null) {
-                    break;
-                }
-                //设置答案
-                setSelectQuestionAnswerUnit(paperDetailUnit);
-
-                PaperDetailUnitDto unitDto = paperDetailUnitDtoAssembler.toDto(paperDetailUnit);
-                /**
-                 * 此处不能传questionId,需要传paperDetailUnitId
-                 * 因为选项乱序在paperDetailUnit里
-                 * unitDto.setQuesId(paperDetailUnit.getQuestion().getId());
-                 */
-                unitDto.setQuesId(paperDetailUnit.getId());
-                String answer = paperDetailUnit.getQuestion().getQuesAnswer();
-                if (StringUtils.isNotEmpty(answer)) {
-                    unitDto.setAnswer(answer);
-                }
-                if (unitDto.getQuestionType() == QuesStructType.NESTED_ANSWER_QUESTION) {// 假如是套题
-                    List<Question> subQuesList = paperDetailUnit.getQuestion().getSubQuestions();
-                    List<SubQuestionDto> subQuesDtos = subQuestionDtoAssembler.toDtoList(subQuesList);
-                    for (int m = 0; m < subQuesList.size(); m++) {
-                        List<QuesOptionDto> quesOptionDtos = subQuestionDtoAssembler.toOptionDtoList(subQuesList.get(m).getQuesOptions());
-                        subQuesDtos.get(m).setQuesOptions(quesOptionDtos);
-                        if (StringUtils.isNotEmpty(subQuesList.get(m).getQuesAnswer())) {
-                            subQuesDtos.get(m).setQuesAnswer(subQuesList.get(m).getQuesAnswer());
-                        }
-                        subQuesDtos.get(m).setNumber(m + 1);
-                        //套题分数从小题类中取值
-                        subQuesDtos.get(m).setScore(paperDetailUnit.getSubScoreList().get(m));
-                    }
-                    unitDto.setSubQuestions(subQuesDtos);
-                }
-                paperDetailUnitDtos.add(unitDto);
-            }
-            paperDetailDtos.get(i).setPaperDetailUnits(paperDetailUnitDtos);
-            paperDetailDtos.get(i).setCnNum(CommonUtils.toCHNum(paperDetailDtos.get(i).getNumber()));
-        }
-        long paperDetailUnitDtoEndTime = System.currentTimeMillis();
-        LOG.info("单独组装paperDetailUnitDto耗时:" + (paperDetailUnitDtoEndTime - paperDetailDtoEndTime) + "ms");
-        return paperDto;
-    }
-
-    private void setSelectQuestoionAnswer(List<PaperDetailUnit> paperDetailUnits) {
-        for (PaperDetailUnit paperDetailUnit : paperDetailUnits) {
-            if (paperDetailUnit == null || paperDetailUnit.getQuestion() == null) {
-                break;
-            }
-            String optionOrder = paperDetailUnit.getOptionOrder();
-            Question question = paperDetailUnit.getQuestion();
-            quesService.setSelectQuestionAnswer(question, optionOrder);
-        }
-    }
-
-    private void setSelectQuestionAnswerUnit(PaperDetailUnit paperDetailUnit) {
-        Question question = paperDetailUnit.getQuestion();
-        if (paperDetailUnit == null || question == null) {
-            return;
-        }
-        String optionOrder = paperDetailUnit.getOptionOrder();
-        quesService.setSelectQuestionAnswer(question, optionOrder);
-    }
-
-
-    /**
-     * 根据paperDetailUnitId抽取单个试题
-     * 根据paperDetailUnitId中设置的option顺序对option排序
-     */
-    @Override
-    public QuestionDto extractExamQuestion(String examId, String courseCode, String groupCode, String paperDetailUnitId) {
-        PaperDetailUnit paperDetailUnit = Model.of(paperDetailUnitRepo.findById(paperDetailUnitId));
-        List<PaperDetailUnit> paperDetailUnits = new ArrayList<>();
-        paperDetailUnits.add(paperDetailUnit);
-        //设置答案
-        setSelectQuestoionAnswer(paperDetailUnits);
-        //重新对选择题option进行排序(多选、单选、套题下选择题)
-        reorderChoicequestionOption(paperDetailUnit);
-        Question ques = paperDetailUnit.getQuestion();
-        quesService.formatQues(ques);
-        QuestionDto dto = BeanCopierUtil.copyProperties(ques, QuestionDto.class);
-        dto.setScore(paperDetailUnit.getScore());
-        dto.setQuesOptions(buildQuestionOptionDto(ques.getQuesOptions()));
-        if (ques.getQuestionType() == QuesStructType.NESTED_ANSWER_QUESTION) {
-            List<Question> subQuesList = ques.getSubQuestions();
-            List<SubQuestionDto> subQuesDtos = new ArrayList<>();
-            for (Question question : subQuesList) {
-                SubQuestionDto subQuestionDto = new SubQuestionDto();
-                BeanUtils.copyProperties(question, subQuestionDto);
-                subQuesDtos.add(subQuestionDto);
-            }
-            for (int m = 0; m < subQuesList.size(); m++) {
-                List<QuesOptionDto> quesOptionDtos = BeanCopierUtil
-                        .copyPropertiesOfList(subQuesList.get(m).getQuesOptions(), QuesOptionDto.class);
-                subQuesDtos.get(m).setQuesOptions(quesOptionDtos);
-                subQuesDtos.get(m).setQuesAnswer(subQuesList.get(m).getQuesAnswer());
-                subQuesDtos.get(m).setNumber(m + 1);
-                //套题分数从小题类中取值
-                subQuesDtos.get(m).setScore(paperDetailUnit.getSubScoreList().get(m));
-                dto.setSubQuestions(subQuesDtos);
-            }
-        }
-        if (ques.getQuestionType() == QuesStructType.SINGLE_ANSWER_QUESTION
-                || ques.getQuestionType() == QuesStructType.MULTIPLE_ANSWER_QUESTION) {
-            dto.setQuesAnswer(ques.getQuesAnswer());
-        }
-        appendAudioFlag(dto, examId, courseCode, groupCode);
-        return dto;
-    }
-
-    private List<QuesOptionDto> buildQuestionOptionDto(List<QuesOption> quesOptions) {
-        if (quesOptions == null) {
-            return null;
-        }
-        List<QuesOptionDto> optionDtos = new ArrayList<>();
-        for (QuesOption option : quesOptions) {
-            QuesOptionDto optionDto = new QuesOptionDto();
-            optionDto.setNumber(option.getNumber());
-            optionDto.setOptionBody(option.getOptionBody());
-            optionDtos.add(optionDto);
-        }
-        return optionDtos;
-    }
-
-    /**
-     * 1.给QuestionDto添加音频播放次数
-     * 2.给试题音频中有a标签添加url
-     *
-     * @param questionDto
-     */
-    private void appendAudioFlag(QuestionDto questionDto, String examId, String courseCode, String groupCode) {
-        if (questionDto.getHasAudio() != null && questionDto.getHasAudio() == true) {
-            //1.判断questionDto是否含有音频,如果有添加音频播放次数
-            AudioTimeConfig audioTimeConfig = Model.of(audioTimeConfigRepo.findOne(Example.of(new AudioTimeConfig(examId, courseCode, groupCode, questionDto.getId()))));
-            questionDto.setPlayTime(audioTimeConfig != null ? audioTimeConfig.getPlayTime() : null);
-            //2.1 取到题干,给a标签添加url
-            String quesBody = questionDto.getQuesBody();
-            questionDto.setQuesBody(buildBody(quesBody, questionDto));
-            //2.2取到选项,给a标签添加url
-            List<QuesOptionDto> quesOptionDtoList = questionDto.getQuesOptions();
-            if (quesOptionDtoList != null && quesOptionDtoList.size() > 0) {
-                for (QuesOptionDto quesOptionDto : quesOptionDtoList) {
-                    quesOptionDto.setOptionBody(buildBody(quesOptionDto.getOptionBody(), questionDto));
-                }
-            }
-        } else {
-            questionDto.setPlayTime(null);
-        }
-    }
-
-    //给题目和选项添加url
-    public String buildBody(String body, QuestionDto questionDto) {
-        String[] bodyStrings = body.split("></a>");
-        if (bodyStrings.length > 1) {
-            String resultBody = "";
-            for (int i = 0; i < bodyStrings.length; i++) {
-                String containAStr = bodyStrings[i];
-                if (containAStr.indexOf("<a") > -1) {
-                    String questionAudioId = matchAudioName(containAStr, "a", "id");
-                    QuestionAudio questionAudio = questionAudioService.findAudioById(questionAudioId);
-                    if (questionAudio != null) {
+	@Autowired
+	private PaperDtoAssembler paperDtoAssembler;
+
+	@Autowired
+	private PaperDetailDtoAssembler paperDetailDtoAssembler;
+
+	@Autowired
+	private PaperDetailUnitDtoAssembler paperDetailUnitDtoAssembler;
+
+	@Autowired
+	private SubQuestionDtoAssembler subQuestionDtoAssembler;
+
+	@Autowired
+	private RedisClient redisClient;
+
+	/*
+	 * @Autowired private PaperDetailUnitNativeRepo detailUnitNativeRepo;
+	 */
+
+	@Autowired
+	private ExamCloudService examCloudService;
+	@Autowired
+	private ExamRecordCloudService adminExamRecordCloudService;
+	@Autowired
+	private ExamRecordDataCloudService studentExamRecordCloudService;
+
+	@Override
+	public ExtractConfig findConfig(ExtractConfig condition) {
+		if (condition.getExamId() == null) {
+			return null;
+		}
+		if (StringUtils.isBlank(condition.getCourseCode())) {
+			return null;
+		}
+		Query query = new Query();
+		if (!StringUtils.isBlank(condition.getOrgId())) {
+			query.addCriteria(Criteria.where("orgId").is(condition.getOrgId()));
+		}
+		query.addCriteria(Criteria.where("examId").is(condition.getExamId()));
+		query.addCriteria(Criteria.where("courseCode").is(condition.getCourseCode()));
+		ExtractConfig tempConfig = this.mongoTemplate.findOne(query, ExtractConfig.class);
+		return tempConfig;
+	}
+
+	@Override
+	public Map<String, String> saveExtractConfig2(ExtractConfig extractConfig, User user) throws Exception {
+		List<ExamPaper> examPapers = extractConfig.getExamPaperList();
+		for (int i = 0; i < examPapers.size(); i++) {
+			ExamPaper examPaper = examPapers.get(i);
+			Paper paper = examPaper.getPaper();
+			paper = Model.of(paperRepo.findById(paper.getId()));
+			examPaper.setPaper(paper);
+		}
+		Course course = courseService.getCourse(Long.valueOf(extractConfig.getOrgId()), extractConfig.getCourseCode());
+		extractConfig.setCourse(course);
+		extractConfig.setCourseName(course.getName());
+		Map<String, String> newFinishedPaperIdMap = makePaperByConfig(extractConfig);
+		extractConfig.setFinishedPaperIdMap(newFinishedPaperIdMap);
+		extractConfig.setIfFinish((short) 1);
+		extractConfigRepo.save(extractConfig);
+		return newFinishedPaperIdMap;
+	}
+
+	@Override
+	public List<ExamPaper> saveExtractConfig(ExtractConfig extractConfig, User user) {
+		List<ExamPaper> examPapers = extractConfig.getExamPaperList();
+		for (int i = 0; i < examPapers.size(); i++) {
+			ExamPaper examPaper = examPapers.get(i);
+			Paper paper = examPaper.getPaper();
+			paper = Model.of(paperRepo.findById(paper.getId()));
+			examPaper.setPaper(paper);
+			if (ExamType.OFFLINE.name().equals(extractConfig.getExamType())) {
+				checkOfflinePaper(paper);
+			}
+		}
+		if(StringUtils.isNotBlank(extractConfig.getId())) {
+			disposeOldPaper(extractConfig.getId());
+		}
+		Course course = courseService.getCourse(Long.valueOf(extractConfig.getOrgId()), extractConfig.getCourseCode());
+		extractConfig.setCourse(course);
+		extractConfig.setCourseName(course.getName());
+		extractConfig.setIfFinish((short) 1);
+		extractConfigRepo.save(extractConfig);
+		disposeNowPaper(extractConfig.getId());
+		return examPapers;
+	}
+
+	/**先处理原来绑定的试卷
+	 * @param extractConfigId
+	 */
+	private void disposeOldPaper(String extractConfigId) {
+		ExtractConfig ec = Model.of(extractConfigRepo.findById(extractConfigId));
+		for (ExamPaper paper : ec.getExamPaperList()) {
+			if(inExam(paper.getPaper().getId())) {//如果有考试记录
+				updatePaperInUse(paper.getPaper().getId(), 1);
+			}else {
+				if(!inOtherExtractConfig(extractConfigId, paper.getPaper().getId())) {//没有考试记录且不被其他调卷规则引用
+					updatePaperInUse(paper.getPaper().getId(), 0);
+				}
+			}
+		}
+	}
+	/**处理当前绑定试卷
+	 * @param extractConfigId
+	 */
+	private void disposeNowPaper(String extractConfigId) {
+		ExtractConfig ec = Model.of(extractConfigRepo.findById(extractConfigId));
+		for (ExamPaper paper : ec.getExamPaperList()) {
+			updatePaperInUse(paper.getPaper().getId(), 1);
+		}
+	}
+
+	private void updatePaperInUse(String paperId, int inUse) {
+		Query query = null;
+		if(paperId.length()==24) {
+			query = Query.query(Criteria.where("_id").is(new ObjectId(paperId)));
+		}else {
+			query = Query.query(Criteria.where("_id").is(paperId));
+		}
+		Update update = new Update();
+		update.set("inUse", inUse);
+		mongoTemplate.updateFirst(query, update, "paper");
+	}
+
+	private boolean inExam(String paperId) {
+		CheckPaperInExamReq req1 = new CheckPaperInExamReq();
+		req1.setBasePaperId(paperId);
+		CheckPaperInExamResp res1 = adminExamRecordCloudService.checkPaperInExam(req1);
+		if (res1.getInExam()) {
+			return res1.getInExam();
+		}
+		cn.com.qmth.examcloud.core.oe.student.api.request.CheckPaperInExamReq req2 = new cn.com.qmth.examcloud.core.oe.student.api.request.CheckPaperInExamReq();
+		req2.setBasePaperId(paperId);
+		cn.com.qmth.examcloud.core.oe.student.api.response.CheckPaperInExamResp res2 = studentExamRecordCloudService
+				.checkPaperInExam(req2);
+		return res2.getInExam();
+	}
+
+	private boolean inOtherExtractConfig(String extractConfigId, String paperId) {
+		Criteria criteria = new Criteria();
+		criteria.and("examPaperList").elemMatch(Criteria.where("paper.$id").is(new ObjectId(paperId)));
+		Query query = Query.query(criteria);
+		List<ExtractConfig> list = mongoTemplate.find(query, ExtractConfig.class, "extractConfig");
+		if (list == null || list.size() == 0) {
+			return false;
+		}
+		if (list.size() == 1 && list.get(0).getId().equals(extractConfigId)) {
+			return false;
+		}
+		return true;
+	}
+
+	private void checkOfflinePaper(Paper paper) {
+		List<PaperDetailUnit> pdus = paperDetailUnitRepo.findByPaper(paper);
+		if (pdus == null || pdus.size() == 0) {
+			return;
+		}
+		for (PaperDetailUnit pdu : pdus) {
+			if (pdu.getQuestionType() == QuesStructType.SINGLE_ANSWER_QUESTION
+					|| pdu.getQuestionType() == QuesStructType.MULTIPLE_ANSWER_QUESTION
+					|| pdu.getQuestionType() == QuesStructType.BOOL_ANSWER_QUESTION) {
+				throw new StatusException("500", "试卷包含客观题,无法保存规则");
+			} else if (pdu.getQuestionType() == QuesStructType.NESTED_ANSWER_QUESTION
+					&& !CollectionUtils.isEmpty(pdu.getQuestion().getSubQuestions())) {
+				for (Question q : pdu.getQuestion().getSubQuestions()) {
+					if (q.getQuestionType() == QuesStructType.SINGLE_ANSWER_QUESTION
+							|| q.getQuestionType() == QuesStructType.MULTIPLE_ANSWER_QUESTION
+							|| q.getQuestionType() == QuesStructType.BOOL_ANSWER_QUESTION) {
+						throw new StatusException("500", "试卷包含客观题,无法保存规则");
+					}
+				}
+			}
+		}
+	}
+
+	@Override
+	public ExtractConfig findConfigById(String id) {
+		if (StringUtils.isBlank(id)) {
+			return null;
+		}
+		return Model.of(extractConfigRepo.findById(id));
+	}
+
+	@Override
+	public Map<String, Object> extractExamPaper(Long exam_id, String course_code, String group_code) {
+		Map<String, Object> returnMap = new HashMap<>();
+		LOG.info("调卷开始...");
+		long beginTime = System.currentTimeMillis();
+		LOG.info("开始根据examId:" + exam_id + "和courseCode:" + course_code + "获取调卷规则");
+		ExtractConfig extractConfig = this.findConfig(new ExtractConfig(exam_id, course_code));
+		if (extractConfig == null) {
+			LOG.error("该考试和课程下调卷规则未制定,请先制定调卷规则,调卷程序退出");
+			returnMap.put("errorMsg", "该考试和课程下调卷规则未制定,请先制定调卷规则");
+			return returnMap;
+		}
+		long configFinishTime = System.currentTimeMillis();
+		LOG.info("获取调卷规则共耗时:" + (configFinishTime - beginTime) + "ms");
+		LOG.info("根据调卷规则中设置的概率获取类型为" + group_code + "的试卷");
+		Map<String, Paper> paperMap = this.getExamPaperByProbability(extractConfig.getExamPaperList());
+		if (paperMap.isEmpty()) {
+			LOG.error("该考试和课程下调卷规则中试卷不存在,请检查调卷规则,调卷程序退出");
+			returnMap.put("errorMsg", "该考试和课程下调卷规则中试卷不存在,请重新制定调卷规则");
+			return returnMap;
+		}
+
+		long paperMapFinishTime = System.currentTimeMillis();
+		LOG.info("获取类型为" + group_code + "的试卷共耗时:" + (paperMapFinishTime - configFinishTime) + "ms");
+
+		Paper basePaper = paperMap.get(group_code);
+		if (basePaper == null) {
+			LOG.error("该考试和课程下调卷规则中该类型试卷不存在,请检查调卷规则,调卷程序退出");
+			returnMap.put("errorMsg", "该考试和课程下调卷规则中该类型试卷不存在,请重新制定调卷规则");
+			return returnMap;
+		}
+		String basePaperId = basePaper.getId();
+		LOG.info("将原始试卷:" + basePaperId + "根据规则重新组卷");
+		int upSetQuestionOrder = extractConfig.getScrambling_the_question_order();
+		int upSetOptionOrder = extractConfig.getScrambling_the_option_order();
+		// 不乱序直接调卷
+		if (upSetQuestionOrder == 0 && upSetOptionOrder == 0) {
+			PaperDto paperDto = getPaperDtoByPaper(basePaper, basePaperId);
+			long paperDtoFinishTime = System.currentTimeMillis();
+			LOG.info("获取试卷Dto共耗时:" + (paperDtoFinishTime - paperMapFinishTime) + "ms");
+			returnMap.put("paperDto", paperDto);
+			LOG.info("调卷完成");
+			LOG.info("总共耗时:" + (System.currentTimeMillis() - beginTime) + "ms");
+		} else {
+			// 乱序重新生成试卷
+			Paper newPaper = this.recombinationPaper(basePaper, PaperType.STUDENT_EXAM, upSetQuestionOrder,
+					upSetOptionOrder);
+			LOG.info("根据新试卷 paperId:" + newPaper.getId() + "组装PaperDto后返回");
+
+			long genPaperFinishTime = System.currentTimeMillis();
+			LOG.info("组卷共耗时:" + (genPaperFinishTime - paperMapFinishTime) + "ms");
+			PaperDto paperDto = getPaperDtoByPaper(newPaper, basePaperId);
+
+			long paperDtoFinishTime = System.currentTimeMillis();
+			LOG.info("获取试卷Dto共耗时:" + (paperDtoFinishTime - genPaperFinishTime) + "ms");
+
+			returnMap.put("paperDto", paperDto);
+			LOG.info("调卷完成");
+			LOG.info("总共耗时:" + (System.currentTimeMillis() - beginTime) + "ms");
+		}
+		return returnMap;
+	}
+
+	@Override
+	public boolean checkIsAllQbjectiveQuestion(String paperId) {
+		// 优先从redis中获取缓存dto
+		PaperDto cachePaperDto = redisClient.get(CACHE_KEY_PAPER_FOR_DTO + paperId, PaperDto.class, DEFAULT_TIME_OUT);
+		if (cachePaperDto != null) {
+			return cachePaperDto.isAllQbjectiveQuestion();
+		}
+
+		Paper paper = Model.of(paperRepo.findById(paperId));
+		List<PaperDetailUnit> paperDetailUnits = paperDetailUnitRepo.findByPaperOrderByNumber(paper);
+		for (PaperDetailUnit paperDetailUnit : paperDetailUnits) {
+			Question question = paperDetailUnit.getQuestion();
+			// 填空或问答
+			if (question.getQuestionType() == QuesStructType.FILL_BLANK_QUESTION
+					|| question.getQuestionType() == QuesStructType.TEXT_ANSWER_QUESTION) {
+				return false;
+			}
+			if (question.getQuestionType() == QuesStructType.NESTED_ANSWER_QUESTION) {
+				List<Question> subQuestions = question.getSubQuestions();
+				for (Question subQuestion : subQuestions) {
+					if (subQuestion.getQuestionType() == QuesStructType.FILL_BLANK_QUESTION
+							|| subQuestion.getQuestionType() == QuesStructType.TEXT_ANSWER_QUESTION) {
+						return false;
+					}
+				}
+			}
+		}
+		return true;
+	}
+
+	public boolean checkIsAllQbjectiveByPdu(List<PaperDetailUnit> paperDetailUnits) {
+		for (PaperDetailUnit paperDetailUnit : paperDetailUnits) {
+			Question question = paperDetailUnit.getQuestion();
+			// 填空或问答
+			if (question.getQuestionType() == QuesStructType.FILL_BLANK_QUESTION
+					|| question.getQuestionType() == QuesStructType.TEXT_ANSWER_QUESTION) {
+				return false;
+			}
+			if (question.getQuestionType() == QuesStructType.NESTED_ANSWER_QUESTION) {
+				List<Question> subQuestions = question.getSubQuestions();
+				for (Question subQuestion : subQuestions) {
+					if (subQuestion.getQuestionType() == QuesStructType.FILL_BLANK_QUESTION
+							|| subQuestion.getQuestionType() == QuesStructType.TEXT_ANSWER_QUESTION) {
+						return false;
+					}
+				}
+			}
+		}
+		return true;
+	}
+
+	@Override
+	public Map<String, String> makePaperByConfig(ExtractConfig extractConfig) {
+		Map<String, String> finishedPaperIdMap = new HashMap<>();
+		if (extractConfig == null) {
+			throw new RuntimeException("调卷规则不存在");
+		}
+		// 获得规则中设置的试卷
+		Map<String, Paper> paperMap = this.getExamPaperByProbability(extractConfig.getExamPaperList());
+		if (paperMap.isEmpty()) {
+			throw new RuntimeException("抽取试卷失败");
+		}
+		for (Map.Entry<String, Paper> entry : paperMap.entrySet()) {
+			String key = entry.getKey();
+			// 根据原有试卷重新组卷得到新试卷
+			/*
+			 * Paper newPaper = this.recombinationPaper(entry.getValue(), PaperType.PREVIEW,
+			 * extractConfig.getScrambling_the_question_order(),
+			 * extractConfig.getScrambling_the_option_order());
+			 */
+			finishedPaperIdMap.put(key, entry.getValue().getId());
+		}
+		return finishedPaperIdMap;
+	}
+
+	/**
+	 * 重组试卷,生成新的试卷
+	 *
+	 * @param paper              选中的试卷
+	 * @param upSetQuestionOrder 客观题小题乱序 1:乱序 0:不乱序
+	 * @param upSetOptionOrder   客观题选项乱序 1:乱序 0:不乱序
+	 * @return
+	 */
+	public Paper recombinationPaper(Paper paper, PaperType paperType, int upSetQuestionOrder, int upSetOptionOrder) {
+
+		// 将小题全部取出来,只取一次
+		List<PaperDetailUnit> allPaperDetailUnits = paperDetailUnitRepo.findByPaperOrderByNumber(paper);
+		// 获取大题
+		List<PaperDetail> paperDetails = paperDetailRepo.findByPaperOrderByNumber(paper);
+
+		// 抽取大题号对应的小题
+		Map<String, List<PaperDetailUnit>> pduMap = allPaperDetailUnits.stream()
+				.collect(Collectors.groupingBy(PaperDetailUnit::getDetailId));
+		// 最终保存的所有小题
+		List<PaperDetailUnit> savePaperDetailUnits = new ArrayList<>();
+		// 保存试卷信息
+		paper.setId(null);
+		paper.setPaperType(paperType);
+		Paper newPaper = paperRepo.insert(paper);
+
+		for (int i = 0; i < paperDetails.size(); i++) {
+			PaperDetail paperDetail = paperDetails.get(i);
+
+			List<PaperDetailUnit> paperDetailUnits = pduMap.get(paperDetail.getId());
+			if (paperDetailUnits == null || paperDetailUnits.size() == 0) {
+				continue;
+			}
+			Collections.sort(paperDetailUnits);
+
+			// 将大题中最小的number取出
+			PaperDetailUnit topDetailUnit = paperDetailUnits.get(0);
+			int minNumber = topDetailUnit.getNumber();
+
+			// 小题乱序
+			if (paperDetailUnits != null && paperDetailUnits.size() > 0) {
+				if ((topDetailUnit.getQuestionType() == QuesStructType.SINGLE_ANSWER_QUESTION
+						|| topDetailUnit.getQuestionType() == QuesStructType.MULTIPLE_ANSWER_QUESTION
+						|| topDetailUnit.getQuestionType() == QuesStructType.BOOL_ANSWER_QUESTION)
+						&& upSetQuestionOrder == 1) {
+					Collections.shuffle(paperDetailUnits);// 打乱小题List
+				}
+			}
+			// 设置大题信息
+			paperDetail.setId(null);
+			paperDetail.setPaper(newPaper);
+
+			for (int j = 0; j < paperDetailUnits.size(); j++) {
+				// 重新设置保存PaperDetailUnit
+				PaperDetailUnit paperDetailUnit = paperDetailUnits.get(j);
+				paperDetailUnit.setPaperType(paperType);
+				paperDetailUnit.setPaper(newPaper);
+				paperDetailUnit.setPaperDetail(paperDetail);
+				paperDetailUnit.setNumber(minNumber + j); // 重新设置序号
+				reSavePaperDetailUtilAndQuestion(paperDetailUnit, upSetOptionOrder);
+				savePaperDetailUnits.add(paperDetailUnit);
+			}
+
+		}
+		// 保存大题信息
+		paperDetailRepo.insert(paperDetails);
+		// 保存小题信息
+		paperDetailUnitRepo.insert(savePaperDetailUnits);
+
+		// 清空所有list
+		allPaperDetailUnits.clear();
+		savePaperDetailUnits.clear();
+		paperDetails.clear();
+
+		return newPaper;
+	}
+
+	/**
+	 * 每个试卷类型取出一套试卷 { A:Paper, B:Paper } A是试卷类型 Paper是A类型下选定的试卷
+	 *
+	 * @param examPaperList
+	 * @return
+	 */
+	private Map<String, Paper> getExamPaperByProbability(List<ExamPaper> examPaperList) {
+		Map<String, Paper> paperByTypeMap = new HashMap<>();
+		if (examPaperList == null || examPaperList.size() == 0) {
+			throw new RuntimeException("可供抽取的试卷集合为空,无法抽取试卷");
+		}
+
+		Map<String, List<ExamPaper>> examPaperMap = new HashMap<>();
+		for (int i = 0; i < examPaperList.size(); i++) {
+			ExamPaper examPaper = examPaperList.get(i);
+			if (!examPaperMap.containsKey(examPaper.getGroupCode())) {
+				if (examPaper.getPaper() != null) {
+					List<ExamPaper> epList = new ArrayList<>();
+					epList.add(examPaper);
+					examPaperMap.put(examPaper.getGroupCode(), epList);
+				}
+			} else {
+				if (examPaper.getPaper() != null) {
+					List<ExamPaper> epList = examPaperMap.get(examPaper.getGroupCode());
+					epList.add(examPaper);
+				}
+			}
+		}
+
+		if (examPaperMap != null) {
+			Set<String> keys = examPaperMap.keySet();
+			Iterator<String> it = keys.iterator();
+			while (it.hasNext()) {
+				String key = it.next();
+				Paper paper = this.getPaperByProbability(examPaperMap.get(key));
+
+				if (paper == null) {
+					continue;
+				}
+
+				// 不能用原来的paper对象,否则examPaperList中的paper对象会被覆盖
+				Paper newPaper = Model.of(paperRepo.findById(paper.getId()));
+				paperByTypeMap.put(key, newPaper);
+			}
+		}
+
+		return paperByTypeMap;
+	}
+
+	/**
+	 * 根据设定几率取出一套试卷
+	 *
+	 * @param examPaperList
+	 * @return
+	 */
+	private Paper getPaperByProbability(List<ExamPaper> examPaperList) {
+		int sum = 0;
+		for (int i = 0; i < examPaperList.size(); i++) {
+			sum += examPaperList.get(i).getWeight();
+		}
+
+		// 从1开始
+		Integer rand = new Random().nextInt(sum) + 1;
+		for (int i = 0; i < examPaperList.size(); i++) {
+			rand -= examPaperList.get(i).getWeight();
+			// 选中
+			if (rand <= 0) {
+				return examPaperList.get(i).getPaper();
+			}
+		}
+
+		return null;
+	}
+
+	/**
+	 * 重新设置并保存paperDetailUnit和question
+	 *
+	 * @param paperDetailUnit
+	 * @param upSetOptionOrder
+	 */
+	private void reSavePaperDetailUtilAndQuestion(PaperDetailUnit paperDetailUnit, Integer upSetOptionOrder) {
+		Question question = paperDetailUnit.getQuestion();
+		// 选项乱序
+		if (upSetOptionOrder == 1) {
+			// 单选或多选
+			if (question.getQuestionType() == QuesStructType.SINGLE_ANSWER_QUESTION
+					|| question.getQuestionType() == QuesStructType.MULTIPLE_ANSWER_QUESTION) {
+				List<String> numberList = new ArrayList<>();
+				List<QuesOption> options = question.getQuesOptions();
+				for (int k = 0; k < options.size(); k++) {
+					QuesOption quesOption = options.get(k);
+					numberList.add(quesOption.getNumber());
+				}
+				Collections.shuffle(numberList); // 打乱number顺序
+				paperDetailUnit.setOptionOrder(StringUtils.join(numberList.toArray(), ","));// 设置option顺序
+			}
+			// 套题,套题下小题不乱序,选择题选项乱序
+			if (question.getQuestionType() == QuesStructType.NESTED_ANSWER_QUESTION) {
+				List<Question> subQuestions = question.getSubQuestions();
+				StringBuffer optionOrder = new StringBuffer();
+				for (int m = 0; m < subQuestions.size(); m++) {
+					Question subQuestion = subQuestions.get(m);
+					if (subQuestion.getQuestionType() == QuesStructType.SINGLE_ANSWER_QUESTION
+							|| subQuestion.getQuestionType() == QuesStructType.MULTIPLE_ANSWER_QUESTION) {
+						List<String> numberList = new ArrayList<>();
+						List<QuesOption> options = subQuestion.getQuesOptions();
+						for (int n = 0; n < options.size(); n++) {
+							QuesOption quesOption = options.get(n);
+							numberList.add(quesOption.getNumber());
+						}
+						Collections.shuffle(numberList); // 打乱number顺序
+						optionOrder.append(StringUtils.join(numberList.toArray(), ",")).append(";");
+					}
+				}
+				paperDetailUnit.setOptionOrder(optionOrder.toString()); // 设置option顺序
+			}
+		}
+		paperDetailUnit.setId(null);
+	}
+
+	@Override
+	public List<String> getExamPaperId(String courseCode, String orgId) {
+		Assert.hasLength(courseCode, "courseCode不能为空");
+		Assert.hasLength(orgId, "orgId不能为空");
+		List<String> paperIdList = new ArrayList<>();
+		Query query = new Query();
+		query.addCriteria(Criteria.where("courseCode").is(courseCode));
+		query.addCriteria(Criteria.where("orgId").is(orgId));
+		List<ExtractConfig> extractConfigList = this.mongoTemplate.find(query, ExtractConfig.class);
+		for (ExtractConfig extractConfig : extractConfigList) {
+			List<ExamPaper> examPaperList = extractConfig.getExamPaperList();
+			if (examPaperList != null && examPaperList.size() > 0) {
+				for (ExamPaper examPaper : examPaperList) {
+					paperIdList.add(examPaper.getPaper().getId());
+				}
+			}
+		}
+		return paperIdList;
+	}
+
+	/**
+	 * 根据paper得到PaperDto
+	 *
+	 * @param paper
+	 * @return
+	 */
+	@SuppressWarnings("unchecked")
+	private PaperDto getPaperDtoByPaper(Paper paper, String basePaperId) {
+		long beginTime = System.currentTimeMillis();
+		// 没有则重新组装
+		PaperDto paperDto = paperDtoAssembler.toDto(paper);
+		paperDto.setBasePaperId(basePaperId);
+		paperDto.setAllQbjectiveQuestion(checkIsAllQbjectiveQuestion(basePaperId));
+
+		long paperDtoEndTime = System.currentTimeMillis();
+		LOG.info("单独组装paperDto耗时:" + (paperDtoEndTime - beginTime) + "ms");
+
+		// 将小题全部取出来,只取一次
+		List<PaperDetailUnit> allPaperDetailUnits = paperDetailUnitRepo.findByPaper(paper);
+		long pduEndTime = System.currentTimeMillis();
+		LOG.info("数据库取小题耗时:" + (pduEndTime - paperDtoEndTime) + "ms");
+		Collections.sort(allPaperDetailUnits);
+		long pduSortEndTime = System.currentTimeMillis();
+		LOG.info("排序小题耗时:" + (pduSortEndTime - pduEndTime) + "ms");
+
+		// 获取大题
+		List<PaperDetail> paperDetails = paperDetailRepo.findByPaper(paper);
+		long pdEndTime = System.currentTimeMillis();
+		LOG.info("数据库取大题耗时:" + (pdEndTime - pduSortEndTime) + "ms");
+		Collections.sort(paperDetails);
+		long pdSortEndTime = System.currentTimeMillis();
+		LOG.info("排序大题耗时:" + (pdSortEndTime - pdEndTime) + "ms");
+
+		// 抽取大题Id对应的小题
+		Map<String, List<PaperDetailUnit>> pduMap = allPaperDetailUnits.stream()
+				.collect(Collectors.groupingBy(PaperDetailUnit::getDetailId));
+		long pduMapEndTime = System.currentTimeMillis();
+		LOG.info("获取大题与小题对应关系耗时:" + (pduMapEndTime - pdSortEndTime) + "ms");
+
+		// 获取大题Dto
+		List<PaperDetailDto> paperDetailDtos = paperDetailDtoAssembler.toDtoList(paperDetails);
+		paperDto.setPaperDetails(paperDetailDtos);
+		long paperDetailDtoEndTime = System.currentTimeMillis();
+		LOG.info("单独组装paperDetailDto耗时:" + (paperDetailDtoEndTime - pduMapEndTime) + "ms");
+
+		// 封装小题
+		for (int i = 0; i < paperDetailDtos.size(); i++) {
+			// 根据大题查出大题下面的小题
+			PaperDetail paperDetail = paperDetails.get(i);
+
+			List<PaperDetailUnit> paperDetailUnits = pduMap.get(paperDetail.getId());
+
+			List<PaperDetailUnitDto> paperDetailUnitDtos = new ArrayList<>();
+			for (int j = 0; j < paperDetailUnits.size(); j++) {
+				PaperDetailUnit paperDetailUnit = paperDetailUnits.get(j);
+				if (paperDetailUnit == null || paperDetailUnit.getQuestion() == null) {
+					break;
+				}
+				// 设置答案
+				setSelectQuestionAnswerUnit(paperDetailUnit);
+
+				PaperDetailUnitDto unitDto = paperDetailUnitDtoAssembler.toDto(paperDetailUnit);
+				/**
+				 * 此处不能传questionId,需要传paperDetailUnitId 因为选项乱序在paperDetailUnit里
+				 * unitDto.setQuesId(paperDetailUnit.getQuestion().getId());
+				 */
+				unitDto.setQuesId(paperDetailUnit.getId());
+				String answer = paperDetailUnit.getQuestion().getQuesAnswer();
+				if (StringUtils.isNotEmpty(answer)) {
+					unitDto.setAnswer(answer);
+				}
+				if (unitDto.getQuestionType() == QuesStructType.NESTED_ANSWER_QUESTION) {// 假如是套题
+					List<Question> subQuesList = paperDetailUnit.getQuestion().getSubQuestions();
+					List<SubQuestionDto> subQuesDtos = subQuestionDtoAssembler.toDtoList(subQuesList);
+					for (int m = 0; m < subQuesList.size(); m++) {
+						List<QuesOptionDto> quesOptionDtos = subQuestionDtoAssembler
+								.toOptionDtoList(subQuesList.get(m).getQuesOptions());
+						subQuesDtos.get(m).setQuesOptions(quesOptionDtos);
+						if (StringUtils.isNotEmpty(subQuesList.get(m).getQuesAnswer())) {
+							subQuesDtos.get(m).setQuesAnswer(subQuesList.get(m).getQuesAnswer());
+						}
+						subQuesDtos.get(m).setNumber(m + 1);
+						// 套题分数从小题类中取值
+						subQuesDtos.get(m).setScore(paperDetailUnit.getSubScoreList().get(m));
+					}
+					unitDto.setSubQuestions(subQuesDtos);
+				}
+				paperDetailUnitDtos.add(unitDto);
+			}
+			paperDetailDtos.get(i).setPaperDetailUnits(paperDetailUnitDtos);
+			paperDetailDtos.get(i).setCnNum(CommonUtils.toCHNum(paperDetailDtos.get(i).getNumber()));
+		}
+		long paperDetailUnitDtoEndTime = System.currentTimeMillis();
+		LOG.info("单独组装paperDetailUnitDto耗时:" + (paperDetailUnitDtoEndTime - paperDetailDtoEndTime) + "ms");
+
+		// 将重新组装的dto放进缓存
+		redisClient.set(CACHE_KEY_PAPER_FOR_DTO + paperDto.getId(), paperDto, DEFAULT_TIME_OUT);
+		return paperDto;
+	}
+
+	/**
+	 * 测试获取paperDto
+	 *
+	 * @param basePaperId
+	 * @return
+	 */
+	@Deprecated
+	public PaperDto getPaperDtoByPaperNew(String basePaperId) {
+
+		long beginTime = System.currentTimeMillis();
+		// 没有则重新组装
+		Paper paper = Model.of(paperRepo.findById(basePaperId));
+		PaperDto paperDto = paperDtoAssembler.toDto(paper);
+		paperDto.setBasePaperId(basePaperId);
+
+		long paperDtoEndTime = System.currentTimeMillis();
+		LOG.info("单独组装paperDto耗时:" + (paperDtoEndTime - beginTime) + "ms");
+
+		// 将小题全部取出来,只取一次
+		// List<PaperDetailUnit> allPaperDetailUnits =
+		// detailUnitNativeRepo.findByPaperId(paper.getId());
+		List<PaperDetailUnit> allPaperDetailUnits = new ArrayList<>();
+
+		long pduEndTime = System.currentTimeMillis();
+		LOG.info("数据库取小题耗时:" + (pduEndTime - paperDtoEndTime) + "ms");
+		Collections.sort(allPaperDetailUnits);
+		long pduSortEndTime = System.currentTimeMillis();
+		LOG.info("排序小题耗时:" + (pduSortEndTime - pduEndTime) + "ms");
+
+		paperDto.setAllQbjectiveQuestion(checkIsAllQbjectiveByPdu(allPaperDetailUnits));
+		long isAllObjEndtime = System.currentTimeMillis();
+		LOG.info("设置客观题耗时:" + (isAllObjEndtime - pduSortEndTime) + "ms");
+
+		// 获取大题
+		List<PaperDetail> paperDetails = paperDetailRepo.findByPaper(paper);
+		long pdEndTime = System.currentTimeMillis();
+		LOG.info("数据库取大题耗时:" + (pdEndTime - isAllObjEndtime) + "ms");
+		Collections.sort(paperDetails);
+		long pdSortEndTime = System.currentTimeMillis();
+		LOG.info("排序大题耗时:" + (pdSortEndTime - pdEndTime) + "ms");
+
+		// 抽取大题Id对应的小题
+		Map<String, List<PaperDetailUnit>> pduMap = allPaperDetailUnits.stream()
+				.collect(Collectors.groupingBy(PaperDetailUnit::getDetailId));
+		long pduMapEndTime = System.currentTimeMillis();
+		LOG.info("获取大题与小题对应关系耗时:" + (pduMapEndTime - pdSortEndTime) + "ms");
+
+		// 获取大题Dto
+		List<PaperDetailDto> paperDetailDtos = paperDetailDtoAssembler.toDtoList(paperDetails);
+		paperDto.setPaperDetails(paperDetailDtos);
+		long paperDetailDtoEndTime = System.currentTimeMillis();
+		LOG.info("单独组装paperDetailDto耗时:" + (paperDetailDtoEndTime - pduMapEndTime) + "ms");
+
+		// 封装小题
+		for (int i = 0; i < paperDetailDtos.size(); i++) {
+			// 根据大题查出大题下面的小题
+			PaperDetail paperDetail = paperDetails.get(i);
+
+			List<PaperDetailUnit> paperDetailUnits = pduMap.get(paperDetail.getId());
+
+			List<PaperDetailUnitDto> paperDetailUnitDtos = new ArrayList<>();
+			for (int j = 0; j < paperDetailUnits.size(); j++) {
+				PaperDetailUnit paperDetailUnit = paperDetailUnits.get(j);
+				if (paperDetailUnit == null || paperDetailUnit.getQuestion() == null) {
+					break;
+				}
+				// 设置答案
+				setSelectQuestionAnswerUnit(paperDetailUnit);
+
+				PaperDetailUnitDto unitDto = paperDetailUnitDtoAssembler.toDto(paperDetailUnit);
+				/**
+				 * 此处不能传questionId,需要传paperDetailUnitId 因为选项乱序在paperDetailUnit里
+				 * unitDto.setQuesId(paperDetailUnit.getQuestion().getId());
+				 */
+				unitDto.setQuesId(paperDetailUnit.getId());
+				String answer = paperDetailUnit.getQuestion().getQuesAnswer();
+				if (StringUtils.isNotEmpty(answer)) {
+					unitDto.setAnswer(answer);
+				}
+				if (unitDto.getQuestionType() == QuesStructType.NESTED_ANSWER_QUESTION) {// 假如是套题
+					List<Question> subQuesList = paperDetailUnit.getQuestion().getSubQuestions();
+					List<SubQuestionDto> subQuesDtos = subQuestionDtoAssembler.toDtoList(subQuesList);
+					for (int m = 0; m < subQuesList.size(); m++) {
+						List<QuesOptionDto> quesOptionDtos = subQuestionDtoAssembler
+								.toOptionDtoList(subQuesList.get(m).getQuesOptions());
+						subQuesDtos.get(m).setQuesOptions(quesOptionDtos);
+						if (StringUtils.isNotEmpty(subQuesList.get(m).getQuesAnswer())) {
+							subQuesDtos.get(m).setQuesAnswer(subQuesList.get(m).getQuesAnswer());
+						}
+						subQuesDtos.get(m).setNumber(m + 1);
+						// 套题分数从小题类中取值
+						subQuesDtos.get(m).setScore(paperDetailUnit.getSubScoreList().get(m));
+					}
+					unitDto.setSubQuestions(subQuesDtos);
+				}
+				paperDetailUnitDtos.add(unitDto);
+			}
+			paperDetailDtos.get(i).setPaperDetailUnits(paperDetailUnitDtos);
+			paperDetailDtos.get(i).setCnNum(CommonUtils.toCHNum(paperDetailDtos.get(i).getNumber()));
+		}
+		long paperDetailUnitDtoEndTime = System.currentTimeMillis();
+		LOG.info("单独组装paperDetailUnitDto耗时:" + (paperDetailUnitDtoEndTime - paperDetailDtoEndTime) + "ms");
+		return paperDto;
+	}
+
+	private void setSelectQuestoionAnswer(List<PaperDetailUnit> paperDetailUnits) {
+		for (PaperDetailUnit paperDetailUnit : paperDetailUnits) {
+			if (paperDetailUnit == null || paperDetailUnit.getQuestion() == null) {
+				break;
+			}
+			String optionOrder = paperDetailUnit.getOptionOrder();
+			Question question = paperDetailUnit.getQuestion();
+			quesService.setSelectQuestionAnswer(question, optionOrder);
+		}
+	}
+
+	private void setSelectQuestionAnswerUnit(PaperDetailUnit paperDetailUnit) {
+		Question question = paperDetailUnit.getQuestion();
+		if (paperDetailUnit == null || question == null) {
+			return;
+		}
+		String optionOrder = paperDetailUnit.getOptionOrder();
+		quesService.setSelectQuestionAnswer(question, optionOrder);
+	}
+
+	/**
+	 * 根据paperDetailUnitId抽取单个试题 根据paperDetailUnitId中设置的option顺序对option排序
+	 */
+	@Override
+	public QuestionDto extractExamQuestion(String examId, String courseCode, String groupCode,
+			String paperDetailUnitId) {
+		PaperDetailUnit paperDetailUnit = Model.of(paperDetailUnitRepo.findById(paperDetailUnitId));
+		List<PaperDetailUnit> paperDetailUnits = new ArrayList<>();
+		paperDetailUnits.add(paperDetailUnit);
+		// 设置答案
+		setSelectQuestoionAnswer(paperDetailUnits);
+		// 重新对选择题option进行排序(多选、单选、套题下选择题)
+		reorderChoicequestionOption(paperDetailUnit);
+		Question ques = paperDetailUnit.getQuestion();
+		quesService.formatQues(ques);
+		QuestionDto dto = BeanCopierUtil.copyProperties(ques, QuestionDto.class);
+		dto.setScore(paperDetailUnit.getScore());
+		dto.setQuesOptions(buildQuestionOptionDto(ques.getQuesOptions()));
+		if (ques.getQuestionType() == QuesStructType.NESTED_ANSWER_QUESTION) {
+			List<Question> subQuesList = ques.getSubQuestions();
+			List<SubQuestionDto> subQuesDtos = new ArrayList<>();
+			for (Question question : subQuesList) {
+				SubQuestionDto subQuestionDto = new SubQuestionDto();
+				BeanUtils.copyProperties(question, subQuestionDto);
+				subQuesDtos.add(subQuestionDto);
+			}
+			for (int m = 0; m < subQuesList.size(); m++) {
+				List<QuesOptionDto> quesOptionDtos = BeanCopierUtil
+						.copyPropertiesOfList(subQuesList.get(m).getQuesOptions(), QuesOptionDto.class);
+				subQuesDtos.get(m).setQuesOptions(quesOptionDtos);
+				subQuesDtos.get(m).setQuesAnswer(subQuesList.get(m).getQuesAnswer());
+				subQuesDtos.get(m).setNumber(m + 1);
+				// 套题分数从小题类中取值
+				subQuesDtos.get(m).setScore(paperDetailUnit.getSubScoreList().get(m));
+				dto.setSubQuestions(subQuesDtos);
+			}
+		}
+		if (ques.getQuestionType() == QuesStructType.SINGLE_ANSWER_QUESTION
+				|| ques.getQuestionType() == QuesStructType.MULTIPLE_ANSWER_QUESTION) {
+			dto.setQuesAnswer(ques.getQuesAnswer());
+		}
+		appendAudioFlag(dto, examId, courseCode, groupCode);
+		return dto;
+	}
+
+	private List<QuesOptionDto> buildQuestionOptionDto(List<QuesOption> quesOptions) {
+		if (quesOptions == null) {
+			return null;
+		}
+		List<QuesOptionDto> optionDtos = new ArrayList<>();
+		for (QuesOption option : quesOptions) {
+			QuesOptionDto optionDto = new QuesOptionDto();
+			optionDto.setNumber(option.getNumber());
+			optionDto.setOptionBody(option.getOptionBody());
+			optionDtos.add(optionDto);
+		}
+		return optionDtos;
+	}
+
+	/**
+	 * 1.给QuestionDto添加音频播放次数 2.给试题音频中有a标签添加url
+	 *
+	 * @param questionDto
+	 */
+	private void appendAudioFlag(QuestionDto questionDto, String examId, String courseCode, String groupCode) {
+		if (questionDto.getHasAudio() != null && questionDto.getHasAudio() == true) {
+			// 1.判断questionDto是否含有音频,如果有添加音频播放次数
+			AudioTimeConfig audioTimeConfig = Model.of(audioTimeConfigRepo
+					.findOne(Example.of(new AudioTimeConfig(examId, courseCode, groupCode, questionDto.getId()))));
+			questionDto.setPlayTime(audioTimeConfig != null ? audioTimeConfig.getPlayTime() : null);
+			// 2.1 取到题干,给a标签添加url
+			String quesBody = questionDto.getQuesBody();
+			questionDto.setQuesBody(buildBody(quesBody, questionDto));
+			// 2.2取到选项,给a标签添加url
+			List<QuesOptionDto> quesOptionDtoList = questionDto.getQuesOptions();
+			if (quesOptionDtoList != null && quesOptionDtoList.size() > 0) {
+				for (QuesOptionDto quesOptionDto : quesOptionDtoList) {
+					quesOptionDto.setOptionBody(buildBody(quesOptionDto.getOptionBody(), questionDto));
+				}
+			}
+		} else {
+			questionDto.setPlayTime(null);
+		}
+	}
+
+	// 给题目和选项添加url
+	public String buildBody(String body, QuestionDto questionDto) {
+		String[] bodyStrings = body.split("></a>");
+		if (bodyStrings.length > 1) {
+			String resultBody = "";
+			for (int i = 0; i < bodyStrings.length; i++) {
+				String containAStr = bodyStrings[i];
+				if (containAStr.indexOf("<a") > -1) {
+					String questionAudioId = matchAudioName(containAStr, "a", "id");
+					QuestionAudio questionAudio = questionAudioService.findAudioById(questionAudioId);
+					if (questionAudio != null) {
 //                        String url = sysProperty.getDomain() + questionAudio.getFileUrl();
 //                        String url = sysProperty.getDomain() + questionAudio.getFileUrl();
-                        //通用存储
-                        String url = FileStorageUtil.realPath(questionAudio.getFileUrl());
-                        if (questionDto.getPlayTime() != null) {
-                            containAStr += " question-audio url=\"" + url + "\" playTime=\"" + questionDto.getPlayTime() + "\"" + "></a>";
-                        } else {
-                            containAStr += " question-audio url=\"" + url + "\"" + "></a>";
-                        }
-                    }
-                }
-                resultBody += containAStr;
-            }
-            return resultBody;
-        } else {
-            return body;
-        }
-    }
-
-    private String matchAudioName(String source, String element, String attr) {
-        String reg = "<" + element + "[^<>]*?\\s" + attr + "=['\"]?(.*?)['\"]?(\\s.*?)";
-        Matcher m = Pattern.compile(reg).matcher(source);
-        if (m.find()) {
-            return m.group(1);
-        }
-        return "";
-    }
-
-    /**
-     * 重新对选择题option进行排序(多选、单选、套题下选择题)
-     */
-    private void reorderChoicequestionOption(PaperDetailUnit paperDetailUnit) {
-        String optionOrder = paperDetailUnit.getOptionOrder();
-        if (StringUtil.isNotBlank(optionOrder)) {
-            Question question = paperDetailUnit.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++;
-                    }
-                }
-            }
-        }
-    }
-
-    /**
-     * 对option排序
-     *
-     * @param quesOptions
-     * @param optionOrder
-     * @return
-     */
-    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;
-    }
-
-    @Override
-    public Page<ExtractConfig> findPageExtractConfig(int currentPage, int pageSize, Long examId, String courseCode, String orgId,UserDataRule ud ) {
-    	if (ud.assertEmptyQueryResult()) {
+						// 通用存储
+						String url = FileStorageUtil.realPath(questionAudio.getFileUrl());
+						if (questionDto.getPlayTime() != null) {
+							containAStr += " question-audio url=\"" + url + "\" playTime=\"" + questionDto.getPlayTime()
+									+ "\"" + "></a>";
+						} else {
+							containAStr += " question-audio url=\"" + url + "\"" + "></a>";
+						}
+					}
+				}
+				resultBody += containAStr;
+			}
+			return resultBody;
+		} else {
+			return body;
+		}
+	}
+
+	private String matchAudioName(String source, String element, String attr) {
+		String reg = "<" + element + "[^<>]*?\\s" + attr + "=['\"]?(.*?)['\"]?(\\s.*?)";
+		Matcher m = Pattern.compile(reg).matcher(source);
+		if (m.find()) {
+			return m.group(1);
+		}
+		return "";
+	}
+
+	/**
+	 * 重新对选择题option进行排序(多选、单选、套题下选择题)
+	 */
+	private void reorderChoicequestionOption(PaperDetailUnit paperDetailUnit) {
+		String optionOrder = paperDetailUnit.getOptionOrder();
+		if (StringUtil.isNotBlank(optionOrder)) {
+			Question question = paperDetailUnit.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++;
+					}
+				}
+			}
+		}
+	}
+
+	/**
+	 * 对option排序
+	 *
+	 * @param quesOptions
+	 * @param optionOrder
+	 * @return
+	 */
+	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;
+	}
+
+	@Override
+	public Page<ExtractConfig> findPageExtractConfig(int currentPage, int pageSize, Long examId, String courseCode,
+			String orgId, UserDataRule ud) {
+		if (ud.assertEmptyQueryResult()) {
 			return Page.empty();
 			return Page.empty();
 		}
 		}
-    	if (examId == null) {
-            throw new StatusException("Q-", "examId is null");
-        }
-        Query query = new Query();
-        query.addCriteria(Criteria.where("orgId").is(orgId));
-        if (ud.assertNeedQueryRefIds()) {
-            query.addCriteria(Criteria.where("course.id").in(ud.stringRefIds()));
-        }
-        query.addCriteria(Criteria.where("examId").is(examId));
-        query.addCriteria(Criteria.where("course.enable").is("true"));
-        if (!StringUtils.isBlank(courseCode)) {
-            query.addCriteria(Criteria.where("course.code").is(courseCode));
-        }
-
-        long count = this.mongoTemplate.count(query, ExtractConfig.class);
-        query.limit(pageSize);
-        query.skip((currentPage - 1L) * pageSize);
-
-        List<ExtractConfig> extractConfigList = this.mongoTemplate.find(query, ExtractConfig.class);
-        if (extractConfigList != null && extractConfigList.size() > 0) {
-            //调用考务rmi,获取考试信息
-            GetExamReq req = new GetExamReq();
-            req.setId(examId);
-            req.setRootOrgId(Long.valueOf(orgId));
-            GetExamResp resp = examCloudService.getExam(req);
-            ExamBean bean = resp.getExamBean();
-            for (ExtractConfig extractConfig : extractConfigList) {
-                extractConfig.setExamType(bean.getExamType());
-            }
-        }
-
-        return new PageImpl<>(extractConfigList, PageRequest.of(currentPage - 1, pageSize), count);
-    }
-
-    @Override
-    public Map<String, Object> extractPaper(String paperId) {
-        Map<String, Object> returnMap = new HashMap<>();
-        Paper paper = Model.of(paperRepo.findById(paperId));
-        if (paper == null) {
-            returnMap.put("errorMsg", "该试卷不存在");
-            return returnMap;
-        }
-        PaperDto paperDto = getPaperDtoByPaper(paper, paperId);
-        returnMap.put("paperDto", paperDto);
-        return returnMap;
-    }
-
-    @Override
-    public String getAnswerHtml(String paperId) {
-        //1.根据id查询试卷
-        Paper paper = Model.of(paperRepo.findById(paperId));
-        //2.定义html字符串
-        StringBuffer answerHtml = new StringBuffer("<p style=\"text-align:center;font-size:20px;font-weight:bold\">" + paper.getCourse().getName() + "(" + paper.getCourse().getCode() + ")" + "</p>");
-        //添加考试说明
-        if (paper.getExamRemark() == null) {
-            answerHtml.append("<p>考试说明:</p>");
-        } else {
-            answerHtml.append("<p>考试说明:</p>" + paper.getExamRemark());
-        }
-        //3.通过试卷获取考试端试卷结构
-        PaperDto paperDto = getPaperDtoByPaper(paper, paper.getId());
-        //4.获取试卷所有大题,并且循环
-        List<PaperDetailDto> paperDetailDtos = paperDto.getPaperDetails();
-        for (PaperDetailDto paperDetailDto : paperDetailDtos) {
-            String title = "<p>" + paperDetailDto.getCnNum() + "、" + paperDetailDto.getName() + "(共" + paperDetailDto.getScore() + "分)" + "</p>";
-            answerHtml.append(title);
-            //5.获取大题下面的小题,并循环
-            List<PaperDetailUnitDto> paperDetailUnitDtos = paperDetailDto.getPaperDetailUnits();
-            for (PaperDetailUnitDto paperDetailUnitDto : paperDetailUnitDtos) {
-                //定义题干
-                String body = paperDetailUnitDto.getQuesBody().replaceAll("<span>", "").replaceAll("</span>", "").replaceAll("###", "___");
-                ;
-                //定义选项
-                String option = "";
-                //定义答案
-                String answer = "";
-                //6.如果为单选和多选
-                if (paperDetailUnitDto.getQuestionType() == QuesStructType.SINGLE_ANSWER_QUESTION || paperDetailUnitDto.getQuestionType() == QuesStructType.MULTIPLE_ANSWER_QUESTION) {
-                    //获取选项
-                    List<QuesOptionDto> quesOptionDtos = paperDetailUnitDto.getQuesOptions();
-                    //添加题干
-                    body = startWithP(body, paperDetailUnitDto.getNumber(), false);
-                    answerHtml.append(body);
-                    //添加选项
-                    for (QuesOptionDto quesOptionDto : quesOptionDtos) {
-                        option = startWithP(quesOptionDto.getOptionBody(), Integer.parseInt(quesOptionDto.getNumber()), true);
-                        answerHtml.append(option);
-                    }
-                    answer = startWithP(paperDetailUnitDto.getAnswer(), -1, false);
-                    answerHtml.append(answer);
-                }
-                //7.如果为套题
-                else if (paperDetailUnitDto.getSubQuestions() != null && paperDetailUnitDto.getSubQuestions().size() > 0) {
-                    //添加主题干
-                    String bigBody = CommonUtils.relaceQuestionIdx(paperDetailUnitDto.getQuesBody(), 0);
-                    bigBody = bigBody.replaceAll("<span>", "").replaceAll("</span>", "").replaceAll("###", "___");
-                    bigBody = startWithP(bigBody, -2, false);
-                    answerHtml.append(bigBody);
-                    List<SubQuestionDto> subQuestionDtos = paperDetailUnitDto.getSubQuestions();
-                    for (SubQuestionDto subQuestionDto : subQuestionDtos) {
-                        body = subQuestionDto.getQuesBody().replaceAll("<span>", "").replaceAll("</span>", "").replaceAll("###", "___");
-                        //如果子题为单选或者多选
-                        if (subQuestionDto.getQuestionType() == QuesStructType.SINGLE_ANSWER_QUESTION || subQuestionDto.getQuestionType() == QuesStructType.MULTIPLE_ANSWER_QUESTION) {
-                            //获取选项
-                            List<QuesOptionDto> quesOptionDtos = subQuestionDto.getQuesOptions();
-                            //添加题干
-                            body = startWithP(body, subQuestionDto.getNumber(), false);
-                            answerHtml.append(body);
-                            //添加选项
-                            for (QuesOptionDto quesOptionDto : quesOptionDtos) {
-                                option = startWithP(quesOptionDto.getOptionBody(), Integer.parseInt(quesOptionDto.getNumber()), true);
-                                answerHtml.append(option);
-                            }
-                            answer = startWithP(subQuestionDto.getQuesAnswer(), -1, false);
-                            answerHtml.append(answer);
-                        } else {
-                            //添加题干
-                            body = startWithP(body, subQuestionDto.getNumber(), false);
-                            answerHtml.append(body);
-                            //添加答案
-                            answer = startWithP(subQuestionDto.getQuesAnswer(), -1, false);
-                            answerHtml.append(answer);
-                        }
-                    }
-                } else {
-                    //添加题干
-                    body = startWithP(body, paperDetailUnitDto.getNumber(), false);
-                    answerHtml.append(body);
-                    //添加答案
-                    answer = startWithP(paperDetailUnitDto.getAnswer(), -1, false);
-                    answerHtml.append(answer);
-                }
-            }
-        }
-        return answerHtml.toString();
-    }
-
-    public String startWithP(String s, Integer number, boolean option) {
-        if (s == null) {
-            s = "<p></p>";
-        }
-        if (number == -2) {
-            if (s.startsWith("<p>")) {
-                s = s.replaceAll("<p>", "<p style=\"margin-left:40px;\">").replaceAll("<p style=\"margin-left:40px;\">", "<p style=\"margin-left:20px;\">");
-            } else {
-                s = "<p style=\"margin-left:20px;color:red;\">" + s + "</p>";
-            }
-        } else if (number == -1) {
-            if (s.startsWith("<p>")) {
-                s = s.replaceAll("<p>", "<p style=\"margin-left:65px;\">").replaceFirst("<p style=\"margin-left:65px;\">", "<p style=\"margin-left:20px;color:red;\">" + "答案:").replace("<p style=\"margin-left:65px;\">", "<p style=\"margin-left:65px;color:red;\">");
-            } else {
-                s = "<p style=\"margin-left:20px;color:red;\">" + "答案:" + s + "</p>";
-            }
-        } else {
-            if (option) {
-                if (s.startsWith("<p>")) {
-                    s = s.replaceAll("<p>", "<p style=\"margin-left:40px;\">").replaceFirst("<p style=\"margin-left:40px;\">", "<p style=\"margin-left:20px;\">" + CommonUtils.getOptionNum(number - 1) + ".");
-                } else {
-                    s = "<p style=\"margin-left:20px;\">" + CommonUtils.getOptionNum(number - 1) + "." + s + "</p>";
-                }
-            } else {
-                if (s.startsWith("<p>")) {
-                    s = s.replaceAll("<p>", "<p style=\"margin-left:40px;\">").replaceFirst("<p style=\"margin-left:40px;\">", "<p style=\"margin-left:20px;\">" + number + ".");
-                } else {
-                    s = "<p style=\"margin-left:20px;\">" + number + "." + s + "</p>";
-                }
-            }
-        }
-        return s;
-    }
-
-
-    @Override
-    public List<CouresInfo> findCourseByExtractConfig(Long examId, String orgId,UserDataRule ud) {
-    	if(ud.assertEmptyQueryResult()) {
-    		return new ArrayList<>();
-    	}
-        if (examId == null) {
-            throw new StatusException("500", "examId is null");
-        }
-        //从考务查询改考试下的所有开启课程
-        List<CouresInfo> courseInfoList = new ArrayList<>();
-        GetExamCourseListReq req = new GetExamCourseListReq();
-        req.setExamId(examId);
-        req.setCourseEnable(true);
-        Long start = 1l;
-        int count = 0;
-        while (true) {
-            req.setStart(start);
-            GetExamCourseListResp resp = examCloudService.getExamCourseList(req);
-            for (ExamCourseRelationBean bean : resp.getRelationList()) {
-                CouresInfo info = new CouresInfo(bean);
-                courseInfoList.add(info);
-            }
-            if (start.equals(resp.getNext())) {
-                break;
-            } else {
-                start = resp.getNext();
-            }
-            count++;
-            if (count > 1000) {
-                throw new StatusException("Q-", "考试下课程的数据量过大");
-            }
-        }
-        if (CollectionUtils.isEmpty(courseInfoList)) {
-            return null;
-        }
-        //查询已经改考试下已经制定的课程的调卷规则
-        Query query = new Query();
-        query.addCriteria(Criteria.where("orgId").is(orgId));
-        query.addCriteria(Criteria.where("examId").is(examId));
-        List<ExtractConfig> extractConfigList = this.mongoTemplate.find(query, ExtractConfig.class);
-        if (extractConfigList != null && extractConfigList.size() > 0) {
-            for (ExtractConfig extractConfig : extractConfigList) {
-                CouresInfo info = new CouresInfo();
-                info.setCourseCode(extractConfig.getCourseCode());
-                if (courseInfoList.contains(info)) {
-                    courseInfoList.remove(info);
-                }
-            }
-            return courseInfoList;
-        }
-        if(ud.assertNeedQueryRefIds()&&courseInfoList.size()>0) {
-        	List<CouresInfo> ret = new ArrayList<>();
-        	for(CouresInfo info:courseInfoList) {
-        		if(ud.getRefIds().contains(info.getCourseId())) {
-        			ret.add(info);
-        		}
-        	}
-        	return ret;
-        }
-        return courseInfoList;
-    }
-    
-    @Override
-    public List<ExtractConfig> findExtractConfig(Long examId) {
-        if (examId == null) {
-            throw new StatusException("1001", "examId is null");
-        }
-        Query query = new Query();
-        query.addCriteria(Criteria.where("examId").is(examId));
-        query.addCriteria(Criteria.where("course.enable").is("true"));
-
-        List<ExtractConfig> extractConfigList = this.mongoTemplate.find(query, ExtractConfig.class);
-
-        return extractConfigList;
-    }
+		if (examId == null) {
+			throw new StatusException("Q-", "examId is null");
+		}
+		Query query = new Query();
+		query.addCriteria(Criteria.where("orgId").is(orgId));
+		if (ud.assertNeedQueryRefIds()) {
+			query.addCriteria(Criteria.where("course.id").in(ud.stringRefIds()));
+		}
+		query.addCriteria(Criteria.where("examId").is(examId));
+		query.addCriteria(Criteria.where("course.enable").is("true"));
+		if (!StringUtils.isBlank(courseCode)) {
+			query.addCriteria(Criteria.where("course.code").is(courseCode));
+		}
+
+		long count = this.mongoTemplate.count(query, ExtractConfig.class);
+		query.limit(pageSize);
+		query.skip((currentPage - 1L) * pageSize);
+
+		List<ExtractConfig> extractConfigList = this.mongoTemplate.find(query, ExtractConfig.class);
+		if (extractConfigList != null && extractConfigList.size() > 0) {
+			// 调用考务rmi,获取考试信息
+			GetExamReq req = new GetExamReq();
+			req.setId(examId);
+			req.setRootOrgId(Long.valueOf(orgId));
+			GetExamResp resp = examCloudService.getExam(req);
+			ExamBean bean = resp.getExamBean();
+			for (ExtractConfig extractConfig : extractConfigList) {
+				extractConfig.setExamType(bean.getExamType());
+			}
+		}
+
+		return new PageImpl<>(extractConfigList, PageRequest.of(currentPage - 1, pageSize), count);
+	}
+
+	@Override
+	public Map<String, Object> extractPaper(String paperId) {
+		Map<String, Object> returnMap = new HashMap<>();
+		Paper paper = Model.of(paperRepo.findById(paperId));
+		if (paper == null) {
+			returnMap.put("errorMsg", "该试卷不存在");
+			return returnMap;
+		}
+		PaperDto paperDto = getPaperDtoByPaper(paper, paperId);
+		returnMap.put("paperDto", paperDto);
+		return returnMap;
+	}
+
+	@Override
+	public String getAnswerHtml(String paperId) {
+		// 1.根据id查询试卷
+		Paper paper = Model.of(paperRepo.findById(paperId));
+		// 2.定义html字符串
+		StringBuffer answerHtml = new StringBuffer("<p style=\"text-align:center;font-size:20px;font-weight:bold\">"
+				+ paper.getCourse().getName() + "(" + paper.getCourse().getCode() + ")" + "</p>");
+		// 添加考试说明
+		if (paper.getExamRemark() == null) {
+			answerHtml.append("<p>考试说明:</p>");
+		} else {
+			answerHtml.append("<p>考试说明:</p>" + paper.getExamRemark());
+		}
+		// 3.通过试卷获取考试端试卷结构
+		PaperDto paperDto = getPaperDtoByPaper(paper, paper.getId());
+		// 4.获取试卷所有大题,并且循环
+		List<PaperDetailDto> paperDetailDtos = paperDto.getPaperDetails();
+		for (PaperDetailDto paperDetailDto : paperDetailDtos) {
+			String title = "<p>" + paperDetailDto.getCnNum() + "、" + paperDetailDto.getName() + "(共"
+					+ paperDetailDto.getScore() + "分)" + "</p>";
+			answerHtml.append(title);
+			// 5.获取大题下面的小题,并循环
+			List<PaperDetailUnitDto> paperDetailUnitDtos = paperDetailDto.getPaperDetailUnits();
+			for (PaperDetailUnitDto paperDetailUnitDto : paperDetailUnitDtos) {
+				// 定义题干
+				String body = paperDetailUnitDto.getQuesBody().replaceAll("<span>", "").replaceAll("</span>", "")
+						.replaceAll("###", "___");
+				;
+				// 定义选项
+				String option = "";
+				// 定义答案
+				String answer = "";
+				// 6.如果为单选和多选
+				if (paperDetailUnitDto.getQuestionType() == QuesStructType.SINGLE_ANSWER_QUESTION
+						|| paperDetailUnitDto.getQuestionType() == QuesStructType.MULTIPLE_ANSWER_QUESTION) {
+					// 获取选项
+					List<QuesOptionDto> quesOptionDtos = paperDetailUnitDto.getQuesOptions();
+					// 添加题干
+					body = startWithP(body, paperDetailUnitDto.getNumber(), false);
+					answerHtml.append(body);
+					// 添加选项
+					for (QuesOptionDto quesOptionDto : quesOptionDtos) {
+						option = startWithP(quesOptionDto.getOptionBody(), Integer.parseInt(quesOptionDto.getNumber()),
+								true);
+						answerHtml.append(option);
+					}
+					answer = startWithP(paperDetailUnitDto.getAnswer(), -1, false);
+					answerHtml.append(answer);
+				}
+				// 7.如果为套题
+				else if (paperDetailUnitDto.getSubQuestions() != null
+						&& paperDetailUnitDto.getSubQuestions().size() > 0) {
+					// 添加主题干
+					String bigBody = CommonUtils.relaceQuestionIdx(paperDetailUnitDto.getQuesBody(), 0);
+					bigBody = bigBody.replaceAll("<span>", "").replaceAll("</span>", "").replaceAll("###", "___");
+					bigBody = startWithP(bigBody, -2, false);
+					answerHtml.append(bigBody);
+					List<SubQuestionDto> subQuestionDtos = paperDetailUnitDto.getSubQuestions();
+					for (SubQuestionDto subQuestionDto : subQuestionDtos) {
+						body = subQuestionDto.getQuesBody().replaceAll("<span>", "").replaceAll("</span>", "")
+								.replaceAll("###", "___");
+						// 如果子题为单选或者多选
+						if (subQuestionDto.getQuestionType() == QuesStructType.SINGLE_ANSWER_QUESTION
+								|| subQuestionDto.getQuestionType() == QuesStructType.MULTIPLE_ANSWER_QUESTION) {
+							// 获取选项
+							List<QuesOptionDto> quesOptionDtos = subQuestionDto.getQuesOptions();
+							// 添加题干
+							body = startWithP(body, subQuestionDto.getNumber(), false);
+							answerHtml.append(body);
+							// 添加选项
+							for (QuesOptionDto quesOptionDto : quesOptionDtos) {
+								option = startWithP(quesOptionDto.getOptionBody(),
+										Integer.parseInt(quesOptionDto.getNumber()), true);
+								answerHtml.append(option);
+							}
+							answer = startWithP(subQuestionDto.getQuesAnswer(), -1, false);
+							answerHtml.append(answer);
+						} else {
+							// 添加题干
+							body = startWithP(body, subQuestionDto.getNumber(), false);
+							answerHtml.append(body);
+							// 添加答案
+							answer = startWithP(subQuestionDto.getQuesAnswer(), -1, false);
+							answerHtml.append(answer);
+						}
+					}
+				} else {
+					// 添加题干
+					body = startWithP(body, paperDetailUnitDto.getNumber(), false);
+					answerHtml.append(body);
+					// 添加答案
+					answer = startWithP(paperDetailUnitDto.getAnswer(), -1, false);
+					answerHtml.append(answer);
+				}
+			}
+		}
+		return answerHtml.toString();
+	}
+
+	public String startWithP(String s, Integer number, boolean option) {
+		if (s == null) {
+			s = "<p></p>";
+		}
+		if (number == -2) {
+			if (s.startsWith("<p>")) {
+				s = s.replaceAll("<p>", "<p style=\"margin-left:40px;\">").replaceAll("<p style=\"margin-left:40px;\">",
+						"<p style=\"margin-left:20px;\">");
+			} else {
+				s = "<p style=\"margin-left:20px;color:red;\">" + s + "</p>";
+			}
+		} else if (number == -1) {
+			if (s.startsWith("<p>")) {
+				s = s.replaceAll("<p>", "<p style=\"margin-left:65px;\">")
+						.replaceFirst("<p style=\"margin-left:65px;\">",
+								"<p style=\"margin-left:20px;color:red;\">" + "答案:")
+						.replace("<p style=\"margin-left:65px;\">", "<p style=\"margin-left:65px;color:red;\">");
+			} else {
+				s = "<p style=\"margin-left:20px;color:red;\">" + "答案:" + s + "</p>";
+			}
+		} else {
+			if (option) {
+				if (s.startsWith("<p>")) {
+					s = s.replaceAll("<p>", "<p style=\"margin-left:40px;\">").replaceFirst(
+							"<p style=\"margin-left:40px;\">",
+							"<p style=\"margin-left:20px;\">" + CommonUtils.getOptionNum(number - 1) + ".");
+				} else {
+					s = "<p style=\"margin-left:20px;\">" + CommonUtils.getOptionNum(number - 1) + "." + s + "</p>";
+				}
+			} else {
+				if (s.startsWith("<p>")) {
+					s = s.replaceAll("<p>", "<p style=\"margin-left:40px;\">").replaceFirst(
+							"<p style=\"margin-left:40px;\">", "<p style=\"margin-left:20px;\">" + number + ".");
+				} else {
+					s = "<p style=\"margin-left:20px;\">" + number + "." + s + "</p>";
+				}
+			}
+		}
+		return s;
+	}
+
+	@Override
+	public List<CouresInfo> findCourseByExtractConfig(Long examId, String orgId, UserDataRule ud) {
+		if (ud.assertEmptyQueryResult()) {
+			return new ArrayList<>();
+		}
+		if (examId == null) {
+			throw new StatusException("500", "examId is null");
+		}
+		// 从考务查询改考试下的所有开启课程
+		List<CouresInfo> courseInfoList = new ArrayList<>();
+		GetExamCourseListReq req = new GetExamCourseListReq();
+		req.setExamId(examId);
+		req.setCourseEnable(true);
+		Long start = 1l;
+		int count = 0;
+		while (true) {
+			req.setStart(start);
+			GetExamCourseListResp resp = examCloudService.getExamCourseList(req);
+			for (ExamCourseRelationBean bean : resp.getRelationList()) {
+				CouresInfo info = new CouresInfo(bean);
+				courseInfoList.add(info);
+			}
+			if (start.equals(resp.getNext())) {
+				break;
+			} else {
+				start = resp.getNext();
+			}
+			count++;
+			if (count > 1000) {
+				throw new StatusException("Q-", "考试下课程的数据量过大");
+			}
+		}
+		if (CollectionUtils.isEmpty(courseInfoList)) {
+			return null;
+		}
+		// 查询已经改考试下已经制定的课程的调卷规则
+		Query query = new Query();
+		query.addCriteria(Criteria.where("orgId").is(orgId));
+		query.addCriteria(Criteria.where("examId").is(examId));
+		List<ExtractConfig> extractConfigList = this.mongoTemplate.find(query, ExtractConfig.class);
+		if (extractConfigList != null && extractConfigList.size() > 0) {
+			for (ExtractConfig extractConfig : extractConfigList) {
+				CouresInfo info = new CouresInfo();
+				info.setCourseCode(extractConfig.getCourseCode());
+				if (courseInfoList.contains(info)) {
+					courseInfoList.remove(info);
+				}
+			}
+			return courseInfoList;
+		}
+		if (ud.assertNeedQueryRefIds() && courseInfoList.size() > 0) {
+			List<CouresInfo> ret = new ArrayList<>();
+			for (CouresInfo info : courseInfoList) {
+				if (ud.getRefIds().contains(info.getCourseId())) {
+					ret.add(info);
+				}
+			}
+			return ret;
+		}
+		return courseInfoList;
+	}
+
+	@Override
+	public List<ExtractConfig> findExtractConfig(Long examId) {
+		if (examId == null) {
+			throw new StatusException("1001", "examId is null");
+		}
+		Query query = new Query();
+		query.addCriteria(Criteria.where("examId").is(examId));
+		query.addCriteria(Criteria.where("course.enable").is("true"));
+
+		List<ExtractConfig> extractConfigList = this.mongoTemplate.find(query, ExtractConfig.class);
+
+		return extractConfigList;
+	}
 
 
 }
 }

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

@@ -114,6 +114,9 @@ public class PaperDetailServiceImpl implements PaperDetailService {
      */
      */
     public void deletePaperDetail(String paperId,String id,User user) {
     public void deletePaperDetail(String paperId,String id,User user) {
     	Paper paper = Model.of(paperRepo.findById(paperId));
     	Paper paper = Model.of(paperRepo.findById(paperId));
+    	if(paper.getInUse()!=null&&paper.getInUse()==1) {
+			throw new StatusException("500", "试卷已调用");
+		}
     	PaperDetail oldpaperDetail = Model.of(paperDetailRepo.findById(id));
     	PaperDetail oldpaperDetail = Model.of(paperDetailRepo.findById(id));
         paperDetailRepo.deleteById(id);
         paperDetailRepo.deleteById(id);
         StringBuilder paperInfo=new StringBuilder();
         StringBuilder paperInfo=new StringBuilder();
@@ -165,6 +168,9 @@ public class PaperDetailServiceImpl implements PaperDetailService {
 	@Override
 	@Override
 	public void movePaperDetail(String paperId, String detailId, String vc, User user) {
 	public void movePaperDetail(String paperId, String detailId, String vc, User user) {
 		Paper paper = Model.of(paperRepo.findById(paperId));
 		Paper paper = Model.of(paperRepo.findById(paperId));
+		if(paper.getInUse()!=null&&paper.getInUse()==1) {
+			throw new StatusException("500", "试卷已调用");
+		}
 		List<PaperDetail> pds=getPaperDetailsByPaper(paper);
 		List<PaperDetail> pds=getPaperDetailsByPaper(paper);
 		if(pds==null||pds.size()<=1) {
 		if(pds==null||pds.size()<=1) {
 			throw new StatusException("500", "大题数量未达到两题,无法移动");
 			throw new StatusException("500", "大题数量未达到两题,无法移动");

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

@@ -135,6 +135,10 @@ public class PaperDetailUnitServiceImpl implements PaperDetailUnitService {
     public PaperDetailUnit savePaperDetailUnit(PaperDetailUnitExp updateUnit, User user) {
     public PaperDetailUnit savePaperDetailUnit(PaperDetailUnitExp updateUnit, User user) {
     	StringBuilder sb=new StringBuilder();
     	StringBuilder sb=new StringBuilder();
         PaperDetailUnit baseUnit = Model.of(paperDetailUnitRepo.findById(updateUnit.getId()));
         PaperDetailUnit baseUnit = Model.of(paperDetailUnitRepo.findById(updateUnit.getId()));
+        Paper cpaper=baseUnit.getPaper();
+        if(cpaper.getInUse()!=null&&cpaper.getInUse()==1) {
+        	checkUpdate(updateUnit, baseUnit);
+        }
         Question baseQuestion = baseUnit.getQuestion();
         Question baseQuestion = baseUnit.getQuestion();
         Question updateQuestion = updateUnit.getQuestion();
         Question updateQuestion = updateUnit.getQuestion();
         checkFillBlankQuestion(updateQuestion);
         checkFillBlankQuestion(updateQuestion);
@@ -252,6 +256,46 @@ public class PaperDetailUnitServiceImpl implements PaperDetailUnitService {
         return baseUnit;
         return baseUnit;
     }
     }
     
     
+    private void checkUpdate(PaperDetailUnitExp updateUnit,PaperDetailUnit baseUnit) {
+    	Question baseQuestion = baseUnit.getQuestion();
+        Question updateQuestion = updateUnit.getQuestion();
+    	if (baseUnit.getQuestionType() == QuesStructType.NESTED_ANSWER_QUESTION) {
+            if (updateQuestion.getId().equals(baseQuestion.getId())) {
+            	return;
+            } else {
+                int size = baseQuestion.getSubQuestions().size();
+                // 判断更新的对象是哪个子题
+                for (int index = 1; index <= size; index++) {
+
+                    Question sub = baseQuestion.getSubQuestions().get(index - 1);
+                    if (updateQuestion.getId().equals(sub.getId())) {
+                        checkUpdate(updateQuestion, sub);
+
+                    }
+                }
+            }
+        } else {
+        	checkUpdate(updateQuestion, baseQuestion);
+        }
+    }
+    private void checkUpdate(Question update,Question base) {
+    	if(update.getScore().doubleValue()!=base.getScore().doubleValue()) {
+    		throw new StatusException("500", "试卷已调用,不能修改分数");
+    	}
+    	if(QuesStructType.SINGLE_ANSWER_QUESTION.equals(base.getQuestionType())
+    			||QuesStructType.MULTIPLE_ANSWER_QUESTION.equals(base.getQuestionType())){
+	    	if(update.getQuesOptions().size()!=base.getQuesOptions().size()) {
+	    		throw new StatusException("500", "试卷已调用,不能修改选项数量");
+	    	}
+    	}
+    	if(QuesStructType.SINGLE_ANSWER_QUESTION.equals(base.getQuestionType())
+    			||QuesStructType.MULTIPLE_ANSWER_QUESTION.equals(base.getQuestionType())
+    			||QuesStructType.BOOL_ANSWER_QUESTION.equals(base.getQuestionType())){
+	    	if(!update.getQuesAnswer().equals(base.getQuesAnswer())) {
+	    		throw new StatusException("500", "试卷已调用,不能修改客观题答案");
+	    	}
+    	}
+    }
     
     
     private String getQuestionChangeInfo(Question old,Question now) {
     private String getQuestionChangeInfo(Question old,Question now) {
     	StringBuilder sb=new StringBuilder();
     	StringBuilder sb=new StringBuilder();
@@ -297,6 +341,9 @@ public class PaperDetailUnitServiceImpl implements PaperDetailUnitService {
     	String changInfo=null;
     	String changInfo=null;
         PaperDetailUnit detailUnit = Model.of(paperDetailUnitRepo.findById(id));
         PaperDetailUnit detailUnit = Model.of(paperDetailUnitRepo.findById(id));
         Paper paper = detailUnit.getPaper();
         Paper paper = detailUnit.getPaper();
+        if(paper.getInUse()!=null&&paper.getInUse()==1) {
+			throw new StatusException("500", "试卷已调用");
+		}
         paperDetailUnitRepo.deleteById(id);
         paperDetailUnitRepo.deleteById(id);
 
 
         if (detailUnit.getQuestion() != null) {
         if (detailUnit.getQuestion() != null) {

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

@@ -359,21 +359,28 @@ public class PaperServiceImpl implements PaperService {
         query.addCriteria(Criteria.where("paperType").is(PaperType.GENERATE.name()));
         query.addCriteria(Criteria.where("paperType").is(PaperType.GENERATE.name()));
         query.addCriteria(Criteria.where("storage").ne(1));
         query.addCriteria(Criteria.where("storage").ne(1));
         query.addCriteria(Criteria.where("course.enable").is("true"));
         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())) {
         if (StringUtils.isNotBlank(paperSearchInfo.getCourseNo())) {
             query.addCriteria(Criteria.where("course.code").is(paperSearchInfo.getCourseNo()));
             query.addCriteria(Criteria.where("course.code").is(paperSearchInfo.getCourseNo()));
         }
         }
-        if (StringUtils.isNoneBlank(paperSearchInfo.getName())) {
+        if (StringUtils.isNotBlank(paperSearchInfo.getName())) {
             String paperName = CommonUtils.escapeExprSpecialWord(paperSearchInfo.getName());
             String paperName = CommonUtils.escapeExprSpecialWord(paperSearchInfo.getName());
             query.addCriteria(Criteria.where("name").regex(".*?\\.*" + paperName + ".*"));
             query.addCriteria(Criteria.where("name").regex(".*?\\.*" + paperName + ".*"));
         }
         }
         if (StringUtils.isNotBlank(paperSearchInfo.getLevel())) {
         if (StringUtils.isNotBlank(paperSearchInfo.getLevel())) {
             query.addCriteria(Criteria.where("course.level").is(paperSearchInfo.getLevel()));
             query.addCriteria(Criteria.where("course.level").is(paperSearchInfo.getLevel()));
         }
         }
-        if (StringUtils.isNoneBlank(paperSearchInfo.getCreator())) {
+        if (StringUtils.isNotBlank(paperSearchInfo.getCreator())) {
             String creator = CommonUtils.escapeExprSpecialWord(paperSearchInfo.getCreator());
             String creator = CommonUtils.escapeExprSpecialWord(paperSearchInfo.getCreator());
             query.addCriteria(Criteria.where("creator").regex(".*?\\.*" + creator + ".*"));
             query.addCriteria(Criteria.where("creator").regex(".*?\\.*" + creator + ".*"));
         }
         }
-        if (StringUtils.isNoneBlank(paperSearchInfo.getLastModifyName())) {
+        if (StringUtils.isNotBlank(paperSearchInfo.getLastModifyName())) {
             String lastModifyName = CommonUtils.escapeExprSpecialWord(paperSearchInfo.getLastModifyName());
             String lastModifyName = CommonUtils.escapeExprSpecialWord(paperSearchInfo.getLastModifyName());
             query.addCriteria(Criteria.where("lastModifyName").regex(".*?\\.*" + lastModifyName + ".*"));
             query.addCriteria(Criteria.where("lastModifyName").regex(".*?\\.*" + lastModifyName + ".*"));
         }
         }
@@ -965,6 +972,10 @@ public class PaperServiceImpl implements PaperService {
         PaperDetailUnit paperDetailUnit = null;
         PaperDetailUnit paperDetailUnit = null;
         if (detailUnitId != null) {
         if (detailUnitId != null) {
             paperDetailUnit = Model.of(paperDetailUnitRepo.findById(detailUnitId));
             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));
         Question ques = Model.of(quesRepo.findById(questionId));
 
 
@@ -1073,6 +1084,9 @@ public class PaperServiceImpl implements PaperService {
     @SuppressWarnings("unused")
     @SuppressWarnings("unused")
     public Paper selectQuestionsToPaper(String paperId, String paperDetailId, List<Question> questions, User user) {
     public Paper selectQuestionsToPaper(String paperId, String paperDetailId, List<Question> questions, User user) {
         Paper paper = Model.of(paperRepo.findById(paperId));
         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));
         PaperDetail paperDetail = Model.of(paperDetailRepo.findById(paperDetailId));
         PaperDetailUnit paperDetailUnit = paperDetailUnitRepo.findTopByPaperDetailOrderByNumberDesc(paperDetail);
         PaperDetailUnit paperDetailUnit = paperDetailUnitRepo.findTopByPaperDetailOrderByNumberDesc(paperDetail);