Kaynağa Gözat

武地大试卷导入接口

xiatian 5 yıl önce
ebeveyn
işleme
8be56e31e3

+ 86 - 70
examcloud-core-questions-api-provider/src/main/java/cn/com/qmth/examcloud/core/questions/api/ImportPaperController.java

@@ -6,6 +6,7 @@ import cn.com.qmth.examcloud.core.questions.base.exception.PaperException;
 import cn.com.qmth.examcloud.core.questions.dao.PaperRepo;
 import cn.com.qmth.examcloud.core.questions.dao.entity.Paper;
 import cn.com.qmth.examcloud.core.questions.service.ClonePaperService;
+import cn.com.qmth.examcloud.core.questions.service.ImportDdCollegePaperService;
 import cn.com.qmth.examcloud.core.questions.service.ImportPaperService;
 import cn.com.qmth.examcloud.core.questions.service.PaperService;
 import cn.com.qmth.examcloud.web.support.ControllerSupport;
@@ -16,12 +17,15 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.http.HttpStatus;
 import org.springframework.http.ResponseEntity;
 import org.springframework.web.bind.annotation.*;
+import org.springframework.web.multipart.MultipartFile;
 import org.springframework.web.multipart.commons.CommonsMultipartFile;
 
 import java.io.File;
 import java.util.HashMap;
 import java.util.Map;
 
+import javax.validation.constraints.NotNull;
+
 /**
  * @author weiwenhai
  * @date 2017年4月14日 下午6:05:37
@@ -32,78 +36,90 @@ import java.util.Map;
 @RestController
 @RequestMapping("${api_cqb}/")
 public class ImportPaperController extends ControllerSupport {
-    protected static final Logger LOGGER = LoggerFactory.getLogger(ImportPaperController.class);
-    @Autowired
-    private ClonePaperService clonePaperService;
-    @Autowired
-    ImportPaperService importPaperService;
-    @Autowired
-    PaperRepo paperRepo;
-    @Autowired
-    PaperService paperService;
+	protected static final Logger LOGGER = LoggerFactory.getLogger(ImportPaperController.class);
+	@Autowired
+	private ClonePaperService clonePaperService;
+	@Autowired
+	ImportPaperService importPaperService;
+	@Autowired
+	private ImportDdCollegePaperService importDdCollegePaperService;
+	@Autowired
+	PaperRepo paperRepo;
+	@Autowired
+	PaperService paperService;
+
+	/**
+	 * 导入试卷
+	 *
+	 * @param file
+	 * @return
+	 */
+	@ApiOperation(value = "导入试卷", notes = "导入试卷")
+	@PostMapping(value = "/importPaper")
+	public ResponseEntity<Object> importPaper(@ModelAttribute Paper paper,
+			@RequestParam("file") CommonsMultipartFile file) {
+		User user = getAccessUser();
+		LOGGER.info("导入开始");
+		File tempFile = null;
+		try {
+			tempFile = importPaperService.getUploadFile(file);
+			Paper newPaper = importPaperService.importPaper(paper, user, tempFile);
+			return new ResponseEntity<>(newPaper, HttpStatus.OK);
+		} catch (Exception e) {
+			LOGGER.error("导入异常:" + e.getMessage());
+			throw new StatusException("Q-090072", e.getMessage());
+		} finally {
+			LOGGER.info("导入结束");
+		}
+	}
 
-    /**
-     * 导入试卷
-     *
-     * @param file
-     * @return
-     */
-    @ApiOperation(value = "导入试卷", notes = "导入试卷")
-    @PostMapping(value = "/importPaper")
-    public ResponseEntity<Object> importPaper(@ModelAttribute Paper paper, @RequestParam("file") CommonsMultipartFile file) {
-        User user = getAccessUser();
-        LOGGER.info("导入开始");
-        File tempFile = null;
-        try {
-            tempFile = importPaperService.getUploadFile(file);
-            Paper newPaper = importPaperService.importPaper(paper, user, tempFile);
-            return new ResponseEntity<>(newPaper, HttpStatus.OK);
-        } catch (Exception e) {
-            LOGGER.error("导入异常:" + e.getMessage());
-            throw new StatusException("Q-090072", e.getMessage());
-        } finally {
-            LOGGER.info("导入结束");
-        }
-    }
+	/**
+	 * 新增试卷
+	 *
+	 * @param courseNo
+	 * @param paperName
+	 * @return
+	 */
+	@ApiOperation(value = "保存导入类型空白试卷", notes = "保存导入类型空白试卷")
+	@PostMapping(value = "/importPaper/saveBlankPaper/{courseNo}/{paperName}")
+	public ResponseEntity<Object> saveBlankPaper(@PathVariable String courseNo, @PathVariable String paperName) {
+		User user = getAccessUser();
+		Map<String, Object> returnMap = importPaperService.saveBlankPaper(courseNo, paperName, user);
+		if (returnMap.get("msg").equals("success")) {
+			return new ResponseEntity<>(returnMap, HttpStatus.OK);
+		} else {
+			return new ResponseEntity<>(returnMap, HttpStatus.INTERNAL_SERVER_ERROR);
+		}
+	}
 
-    /**
-     * 新增试卷
-     *
-     * @param courseNo
-     * @param paperName
-     * @return
-     */
-    @ApiOperation(value = "保存导入类型空白试卷", notes = "保存导入类型空白试卷")
-    @PostMapping(value = "/importPaper/saveBlankPaper/{courseNo}/{paperName}")
-    public ResponseEntity<Object> saveBlankPaper(@PathVariable String courseNo, @PathVariable String paperName) {
-        User user = getAccessUser();
-        Map<String, Object> returnMap = importPaperService.saveBlankPaper(courseNo, paperName, user);
-        if (returnMap.get("msg").equals("success")) {
-            return new ResponseEntity<>(returnMap, HttpStatus.OK);
-        } else {
-            return new ResponseEntity<>(returnMap, HttpStatus.INTERNAL_SERVER_ERROR);
-        }
-    }
+	/**
+	 * 克隆试卷
+	 *
+	 * @return
+	 */
+	@ApiOperation(value = "克隆试卷", notes = "克隆试卷")
+	@PostMapping(value = "/clonePaper/{paperId}/{paperName}/{courseNo}")
+	public ResponseEntity<Object> clonePaper(@PathVariable String paperId, @PathVariable String paperName,
+			@PathVariable String courseNo) {
+		User user = getAccessUser();
+		Map<String, Object> map = new HashMap<>();
+		try {
+			clonePaperService.clonePaper(paperId, paperName, courseNo, user);
+			map.put("msg", "success");
+			return new ResponseEntity<>(map, HttpStatus.OK);
+		} catch (PaperException e) {
+			map.put("msg", e.getMessage());
+			return new ResponseEntity<>(map, HttpStatus.INTERNAL_SERVER_ERROR);
+		}
+	}
 
-    /**
-     * 克隆试卷
-     *
-     * @return
-     */
-    @ApiOperation(value = "克隆试卷", notes = "克隆试卷")
-    @PostMapping(value = "/clonePaper/{paperId}/{paperName}/{courseNo}")
-    public ResponseEntity<Object> clonePaper(@PathVariable String paperId,
-                                             @PathVariable String paperName, @PathVariable String courseNo) {
-        User user = getAccessUser();
-        Map<String, Object> map = new HashMap<>();
-        try {
-            clonePaperService.clonePaper(paperId, paperName, courseNo, user);
-            map.put("msg", "success");
-            return new ResponseEntity<>(map, HttpStatus.OK);
-        } catch (PaperException e) {
-            map.put("msg", e.getMessage());
-            return new ResponseEntity<>(map, HttpStatus.INTERNAL_SERVER_ERROR);
-        }
-    }
+	@ApiOperation(value = "导入地大试卷", notes = "导入地大试卷")
+	@PostMapping(value = "/importDdCollegePaper")
+	public ResponseEntity<Object> importDdCollegePaper(
+			@RequestPart @NotNull(message = "上传文件不能为空!") MultipartFile dataFile,@RequestParam Long rootOrgId) {
+		User user = getAccessUser();
+		importDdCollegePaperService.importDdCollegePaper(dataFile,user, rootOrgId);
+		return new ResponseEntity<>(HttpStatus.OK);
+	}
 
 }

+ 40 - 3
examcloud-core-questions-base/src/main/java/cn/com/qmth/examcloud/core/questions/base/converter/utils/FileUtil.java

@@ -315,7 +315,6 @@ public class FileUtil {
             targetDir.mkdir();
         }
 
-        log.info("UnZip targetDir:" + targetDir.getAbsolutePath());
         List<File> result = new LinkedList<>();
 
         try (ZipFile zip = new ZipFile(zipFile, Charset.forName("UTF-8"));) {
@@ -326,7 +325,6 @@ public class FileUtil {
 
                 //Linux中需要替换掉路径的反斜杠
                 String entryName = (File.separator + entry.getName()).replaceAll("\\\\", "/");
-                log.info("UnZip:" + entryName);
 
                 String filePath = targetDir.getAbsolutePath() + entryName;
                 File target = new File(filePath);
@@ -439,5 +437,44 @@ public class FileUtil {
             zipOutStream.closeEntry();
         }
     }
-
+    public static void deleteFolder(String path) {
+
+		File file = new File(path);
+		if (file.exists()) {
+			if (file.isFile()) {
+				deleteFile(path);
+			} else {
+				deleteDirectory(path);
+			}
+		}
+	}
+
+	public static void deleteFile(String path) {
+		File file = new File(path);
+		if (file.isFile() && file.exists()) {
+			file.delete();
+		}
+	}
+
+	public static void deleteDirectory(String path) {
+		if (!path.endsWith(File.separator)) {
+			path = path + File.separator;
+		}
+		File dirFile = new File(path);
+		if (!dirFile.exists() || !dirFile.isDirectory()) {
+			return;
+		}
+		File[] files = dirFile.listFiles();
+		if (files != null) {
+			for (int i = 0; i < files.length; i++) {
+				if (files[i].isFile()) {
+					deleteFile(files[i].getAbsolutePath());
+				} else {
+					deleteDirectory(files[i].getAbsolutePath());
+				}
+			}
+		}
+
+		dirFile.delete();
+	}
 }

+ 902 - 0
examcloud-core-questions-service/src/main/java/cn/com/qmth/examcloud/core/questions/service/ImportDdCollegePaperService.java

@@ -0,0 +1,902 @@
+package cn.com.qmth.examcloud.core.questions.service;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.net.URLEncoder;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.UUID;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.poi.xssf.usermodel.XSSFRow;
+import org.apache.poi.xssf.usermodel.XSSFSheet;
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
+import org.docx4j.openpackaging.packages.WordprocessingMLPackage;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.web.multipart.MultipartFile;
+
+import cn.com.qmth.examcloud.api.commons.security.bean.User;
+import cn.com.qmth.examcloud.commons.exception.StatusException;
+import cn.com.qmth.examcloud.commons.util.JsonUtil;
+import cn.com.qmth.examcloud.core.questions.base.CommonUtils;
+import cn.com.qmth.examcloud.core.questions.base.IdUtils;
+import cn.com.qmth.examcloud.core.questions.base.converter.utils.FileUtil;
+import cn.com.qmth.examcloud.core.questions.base.enums.PaperStatus;
+import cn.com.qmth.examcloud.core.questions.base.enums.PaperType;
+import cn.com.qmth.examcloud.core.questions.base.question.enums.QuesStructType;
+import cn.com.qmth.examcloud.core.questions.base.word.DocxProcessUtil;
+import cn.com.qmth.examcloud.core.questions.dao.PaperDetailRepo;
+import cn.com.qmth.examcloud.core.questions.dao.PaperDetailUnitRepo;
+import cn.com.qmth.examcloud.core.questions.dao.PaperRepo;
+import cn.com.qmth.examcloud.core.questions.dao.QuesPkgPathRepo;
+import cn.com.qmth.examcloud.core.questions.dao.QuesRepo;
+import cn.com.qmth.examcloud.core.questions.dao.entity.Course;
+import cn.com.qmth.examcloud.core.questions.dao.entity.Paper;
+import cn.com.qmth.examcloud.core.questions.dao.entity.PaperDetail;
+import cn.com.qmth.examcloud.core.questions.dao.entity.PaperDetailUnit;
+import cn.com.qmth.examcloud.core.questions.dao.entity.QuesOption;
+import cn.com.qmth.examcloud.core.questions.dao.entity.Question;
+import cn.com.qmth.examcloud.core.questions.dao.entity.QuestionPkgPath;
+import cn.com.qmth.examcloud.core.questions.service.impl.CourseService;
+import cn.com.qmth.examcloud.core.questions.service.temp.ImgDataUtils;
+import cn.com.qmth.examcloud.core.questions.service.temp.vo.TestFillAnswer;
+import cn.com.qmth.examcloud.core.questions.service.temp.vo.TestFillContent;
+import cn.com.qmth.examcloud.core.questions.service.temp.vo.TestOption;
+import cn.com.qmth.examcloud.core.questions.service.temp.vo.TestOptionGroup;
+import cn.com.qmth.examcloud.core.questions.service.temp.vo.TestPaper;
+import cn.com.qmth.examcloud.core.questions.service.temp.vo.TestQuestion;
+import cn.com.qmth.examcloud.core.questions.service.temp.vo.TestQuestionInfo;
+import cn.com.qmth.examcloud.web.bootstrap.PropertyHolder;
+
+@Service
+public class ImportDdCollegePaperService {
+
+	protected static final Logger log = LoggerFactory.getLogger(ImportDdCollegePaperService.class);
+	@Autowired
+	private PaperRepo paperRepo;
+
+	@Autowired
+	private PaperDetailRepo paperDetailRepo;
+
+	@Autowired
+	private PaperDetailUnitRepo paperDetailUnitRepo;
+
+	@Autowired
+	private QuesRepo quesRepo;
+
+	@Autowired
+	private CourseService courseService;
+
+	@Autowired
+	private QuesPkgPathRepo quesPkgPathRepo;
+
+	public void importDdCollegePaper(MultipartFile dataFile, User user, Long rootOrgId) {
+		String tempDir = PropertyHolder.getString("examcloud.web.sys.tempDataDir");
+		String dir = tempDir + File.separator + UUID.randomUUID() + File.separator;
+		try {
+			File dfile = new File(dir);
+			dfile.mkdirs();
+			File zfile = new File(dir + dataFile.getOriginalFilename());
+			zfile.createNewFile();
+			dataFile.transferTo(zfile);
+			FileUtil.unZip(dfile, zfile);
+			resolvingImportFile(dataFile.getOriginalFilename().split("\\.")[0], dir, user, rootOrgId);
+		} catch (StatusException e) {
+			throw e;
+		} catch (Exception e) {
+			throw new StatusException("100001", "导入试卷失败:"+e.getMessage(), e);
+		} finally {
+			FileUtil.deleteFolder(dir);
+		}
+	}
+
+	private void resolvingImportFile(String courseCode, String dir, User user, Long rootOrgId) throws IOException {
+		XSSFWorkbook wb = null;
+		try {
+			wb = new XSSFWorkbook(dir + courseCode + ".xlsx");
+			XSSFSheet sheet0 = wb.getSheetAt(0);
+			Course course = courseService.getCourse(rootOrgId, courseCode);
+			if (course == null) {
+				throw new StatusException("200002", "课程信息不存在");
+			}
+			List<TestPaper> papers = new ArrayList<>();
+			for (int i = 1; i <= sheet0.getLastRowNum(); i++) {
+				XSSFRow row = sheet0.getRow(i);
+				TestPaper tp = new TestPaper();
+				tp.setId(row.getCell(0).getStringCellValue());
+				tp.setName(row.getCell(1).getStringCellValue());
+				tp.setTestPaperContentId(row.getCell(2).getStringCellValue());
+				tp.setScore(getDoubleByString(row.getCell(3).getStringCellValue()));
+				papers.add(tp);
+			}
+			if (papers == null || papers.size() == 0) {
+				throw new StatusException("200001", "试卷信息为空");
+			}
+			int quesSheetIndex = 1;
+			for (TestPaper testPaper : papers) {
+				// 查询试题详情
+				XSSFSheet quesheet = wb.getSheetAt(quesSheetIndex);
+				List<TestQuestion> questions = queryTestPaper(dir, quesheet);
+				quesSheetIndex++;
+				// 构建大题和小题对应关系
+				Map<Integer, List<TestQuestion>> map = sortPaperDetail(questions);
+				// 初始化试卷
+				Paper paper = initPaper(testPaper, rootOrgId + "", course, map, user);
+				// 定义大题集合
+				List<PaperDetail> paperDetails = new ArrayList<>();
+				// 定义小题集合
+				List<PaperDetailUnit> paperDetailUnits = new ArrayList<>();
+				// 试题---资源 对应关系
+				Map<Question, QuestionPkgPath> map2 = new HashMap<>();
+				// 定义试卷难度
+				double difficulty = 0;
+				int error = 1;
+				for (Integer key : map.keySet()) {
+					List<TestQuestion> dQuestions = map.get(key);
+					// 初始化大题对象
+					PaperDetail paperDetail = initPaperDetail(dQuestions, paper, user);
+					if (dQuestions != null && dQuestions.size() > 0) {
+						for (TestQuestion testQuestion : dQuestions) {
+							TestQuestionInfo testQuestionInfo = JsonUtil.fromJson(testQuestion.getJson(),
+									TestQuestionInfo.class);
+							// 初始化试题对象
+							Question question = null;
+							try {
+								question = initQuestion(testQuestionInfo, testQuestion, course, map2, difficulty, dir,
+										quesheet);
+							} catch (Exception e) {
+								throw new StatusException("600001", "初始化试题失败 courseCode:" + courseCode + " 试卷内容ID:"
+										+ testPaper.getTestPaperContentId() + " 错误题号:" + error +" 试题ID:"+testQuestion.getId()+ " " + e.getMessage());
+							}
+							// 初始化小题对象
+							PaperDetailUnit paperDetailUnit = initPaperDetailUnit(paper, paperDetail, question,
+									testQuestion, user);
+							paperDetailUnits.add(paperDetailUnit);
+							error++;
+						}
+					}
+					paperDetails.add(paperDetail);
+				}
+				// 保存试题资源
+				quesPkgPathRepo.saveAll(map2.values());
+				for (Map.Entry<Question, QuestionPkgPath> entry : map2.entrySet()) {
+					entry.getKey().setQuesPkgPathId(entry.getValue().getId());
+				}
+				// 计算试卷难度
+				paper.setDifficultyDegree(0.5);
+				// 重新计算试题序号
+				Map<PaperDetail, List<PaperDetailUnit>> map3 = new LinkedHashMap<>();
+				List<PaperDetailUnit> newList = null;
+				for (PaperDetail paperDetail : paperDetails) {
+					for (PaperDetailUnit paperDetailUnit : paperDetailUnits) {
+						if (paperDetail.getName().equals(paperDetailUnit.getPaperDetail().getName())) {
+							if (map3.get(paperDetail) == null) {
+								newList = new ArrayList<>();
+								newList.add(paperDetailUnit);
+							} else {
+								newList = map3.get(paperDetail);
+								newList.add(paperDetailUnit);
+							}
+							map3.put(paperDetail, newList);
+						}
+					}
+				}
+				int number = 1;
+				for (Map.Entry<PaperDetail, List<PaperDetailUnit>> entry : map3.entrySet()) {
+					for (PaperDetailUnit paperDetailUnit : entry.getValue()) {
+						paperDetailUnit.setNumber(number);
+						number++;
+					}
+				}
+				quesRepo.saveAll(map2.keySet());
+				paperRepo.save(paper);
+				paperDetailRepo.saveAll(paperDetails);
+				paperDetailUnitRepo.saveAll(paperDetailUnits);
+			}
+
+		} finally {
+			if (wb != null) {
+				wb.close();
+			}
+		}
+	}
+
+	private List<TestQuestion> queryTestPaper(String dir, XSSFSheet sheet) {
+		List<TestQuestion> questions = new ArrayList<TestQuestion>();
+		for (int i = 1; i <= sheet.getLastRowNum(); i++) {
+			XSSFRow row = sheet.getRow(i);
+			String pid = row.getCell(5).getStringCellValue();
+			if ("00000000000000000000000000000000".equals(pid)) {
+				TestQuestion tq = new TestQuestion();
+				tq.setId(row.getCell(0).getStringCellValue());
+				tq.setdNumber(getIntByString(row.getCell(1).getStringCellValue()));
+				tq.setdName(row.getCell(2).getStringCellValue());
+				tq.setNumber(getIntByString(row.getCell(3).getStringCellValue()));
+				tq.setScore(getDoubleByString(row.getCell(4).getStringCellValue()));
+				tq.setParentId(row.getCell(5).getStringCellValue());
+				tq.setType(getIntByString(row.getCell(6).getStringCellValue()));
+				File quesJson = new File(dir + tq.getId() + ".txt");
+				if (!quesJson.exists()) {
+					throw new StatusException("300002", "试题信息文件不存在");
+				}
+				tq.setJson(FileUtil.readFileContent(quesJson));
+				questions.add(tq);
+			}
+		}
+
+		if (questions.size() == 0) {
+			throw new StatusException("300001", "试题信息为空");
+		}
+		return questions;
+	}
+
+	private Integer getIntByString(String v) {
+		if (StringUtils.isEmpty(v)) {
+			return null;
+		}
+		return Integer.valueOf(v);
+	}
+
+	private Double getDoubleByString(String v) {
+		if (StringUtils.isEmpty(v)) {
+			return null;
+		}
+		return Double.valueOf(v);
+	}
+
+	// 将大题和小题分类
+	private Map<Integer, List<TestQuestion>> sortPaperDetail(List<TestQuestion> questions) {
+		Map<Integer, List<TestQuestion>> map = new HashMap<>();
+		List<TestQuestion> sortQuestions = null;
+		for (TestQuestion testQuestion : questions) {
+			if (map.get(testQuestion.getdNumber()) == null) {
+				sortQuestions = new ArrayList<TestQuestion>();
+				sortQuestions.add(testQuestion);
+			} else {
+				sortQuestions = map.get(testQuestion.getdNumber());
+				sortQuestions.add(testQuestion);
+			}
+			map.put(testQuestion.getdNumber(), sortQuestions);
+		}
+		return map;
+	}
+
+	// 初始化试卷对象
+	private Paper initPaper(TestPaper testPaper, String orgId, Course course, Map<Integer, List<TestQuestion>> map,
+			User user) {
+		int unitCount = 0;
+		Set<Integer> paperDetails = map.keySet();
+		for (Map.Entry<Integer, List<TestQuestion>> entry : map.entrySet()) {
+			unitCount = unitCount + entry.getValue().size();
+		}
+		Paper paper = new Paper();
+		paper.setName(testPaper.getName());
+		paper.setTitle(testPaper.getName());
+		paper.setPaperType(PaperType.IMPORT);
+		paper.setPaperStatus(PaperStatus.DRAFT);
+		paper.setOrgId(orgId);
+		paper.setCreator(user.getDisplayName());
+		paper.setTotalScore(testPaper.getScore());
+		paper.setCourse(course);
+		paper.setCourseName(course.getName());
+		paper.setCourseNo(course.getCode());
+		paper.setCreateTime(CommonUtils.getCurDateTime());
+		paper.setPaperDetailCount(paperDetails.size());
+		paper.setUnitCount(unitCount);
+		return paper;
+	}
+
+	// 初始化大题对象
+	private PaperDetail initPaperDetail(List<TestQuestion> dQuestions, Paper paper, User user) {
+		// 定义大题分数
+		double dTotal = 0;
+		PaperDetail paperDetail = new PaperDetail();
+		if (dQuestions != null && dQuestions.size() > 0) {
+			for (TestQuestion question : dQuestions) {
+				dTotal = dTotal + question.getScore();
+			}
+			paperDetail.setPaper(paper);
+			paperDetail.setNumber(dQuestions.get(0).getdNumber());
+			paperDetail.setName(dQuestions.get(0).getdName());
+			paperDetail.setScore(dTotal);
+			paperDetail.setUnitCount(dQuestions.size());
+			paperDetail.setCreator(user.getDisplayName());
+			paperDetail.setCreateTime(CommonUtils.getCurDateTime());
+		}
+		return paperDetail;
+	}
+
+	// 初始化试题对象
+	private Question initQuestion(TestQuestionInfo testQuestionInfo, TestQuestion testQuestion, Course course,
+			Map<Question, QuestionPkgPath> map, double difficulty, String dir, XSSFSheet sheet) throws Exception {
+		Question question = new Question();
+		question.setCreateTime(CommonUtils.getCurDateTime());
+		question.setScore(testQuestion.getScore());
+		question.setCourse(course);
+		question.setOrgId(course.getOrgId());
+		question.setHasAudio(false);
+		question.setDifficulty("中");
+		question.setDifficultyDegree(0.5);
+		question.setPublicity(true);
+		// 按试题分类初始化题干,答案,选项
+		initQuestionInfo(question, testQuestionInfo, map, testQuestion, dir, sheet);
+		difficulty = question.getScore() * 0.5 + difficulty;
+		return question;
+	}
+
+	// 初始化题干,答案,选项,资源
+	private void initQuestionInfo(Question question, TestQuestionInfo testQuestionInfo,
+			Map<Question, QuestionPkgPath> map, TestQuestion testQuestion, String dir, XSSFSheet sheet)
+			throws Exception {
+		WordprocessingMLPackage wordMLPackage = WordprocessingMLPackage.createPackage();
+		// 选词填空
+		if (testQuestionInfo.getQuestionType() == 14) {
+			String quesBody = testQuestionInfo.getQuestionHTML();
+			// 去掉<span>标签中的lang
+			quesBody = replaceLang(quesBody);
+			// 获取img标签
+			LinkedHashMap<String, String> bodyImgList = imgList(quesBody);
+			if (bodyImgList != null && bodyImgList.size() > 0) {
+				int number = 1;
+				for (Map.Entry<String, String> entry : bodyImgList.entrySet()) {
+					if (StringUtils.isBlank(entry.getValue())) {
+						quesBody = quesBody.replace(entry.getKey(), "##" + number + "##");
+						number++;
+					} else {
+						quesBody = quesBody.replace(entry.getKey(), entry.getValue());
+					}
+				}
+			}
+			question.setQuesBody("<p>" + quesBody + "</p>");
+			question.setQuesBodyWord(
+					DocxProcessUtil.html2Docx(wordMLPackage, CommonUtils.formatHtml(question.getQuesBody())));
+			question.setQuestionType(QuesStructType.NESTED_ANSWER_QUESTION);
+			List<Question> subQuestions = initSubQuestionsByOther(testQuestionInfo, wordMLPackage);
+			question.setSubQuestions(subQuestions);
+		}
+		// 阅读理解题
+		if (testQuestionInfo.getQuestionType() == 42) {
+			String quesBody = testQuestionInfo.getQuestionHTML();
+			// 去掉<span>标签中的lang
+			quesBody = replaceLang(quesBody);
+			// 获取img标签
+			LinkedHashMap<String, String> bodyImgList = imgList(quesBody);
+			// 替换、补全Img标签
+			quesBody = replaceImg(bodyImgList, quesBody);
+			question.setQuesBody("<p>" + quesBody + "</p>");
+			question.setQuesBodyWord(
+					DocxProcessUtil.html2Docx(wordMLPackage, CommonUtils.formatHtml(question.getQuesBody())));
+			question.setQuestionType(QuesStructType.NESTED_ANSWER_QUESTION);
+			List<Question> subQues = new ArrayList<Question>();
+			// 查询所有子题
+			List<TestQuestion> subQuestions = querySubQuestions(testQuestion.getId(), dir, sheet);
+			if (subQuestions != null && subQuestions.size() > 0) {
+				for (TestQuestion testQuestion2 : subQuestions) {
+					TestQuestionInfo testQuestionInfo2 = JsonUtil.fromJson(testQuestion2.getJson(),
+							TestQuestionInfo.class);
+					Question subQuestion = new Question();
+					subQuestion.setDifficulty("中");
+					subQuestion.setDifficultyDegree(0.5);
+					subQuestion.setPublicity(true);
+					// 按试题分类初始化题干,答案,选项
+					initQuestionInfo(subQuestion, testQuestionInfo2, map, testQuestion2, dir, sheet);
+					subQues.add(subQuestion);
+				}
+				question.setSubQuestions(subQues);
+			}
+		}
+		// 完形填空题
+		if (testQuestionInfo.getQuestionType() == 15) {
+			String quesBody = testQuestionInfo.getQuestionHTML();
+			// 去掉<span>标签中的lang
+			quesBody = replaceLang(quesBody);
+			// 获取img标签
+			LinkedHashMap<String, String> bodyImgList = imgList(quesBody);
+			if (bodyImgList != null && bodyImgList.size() > 0) {
+				int number = 1;
+				for (Map.Entry<String, String> entry : bodyImgList.entrySet()) {
+					if (StringUtils.isBlank(entry.getValue())) {
+						quesBody = quesBody.replace(entry.getKey(), "##" + number + "##");
+						number++;
+					} else {
+						quesBody = quesBody.replace(entry.getKey(), entry.getValue());
+					}
+				}
+			}
+			question.setQuesBody("<p>" + quesBody + "</p>");
+			question.setQuesBodyWord(
+					DocxProcessUtil.html2Docx(wordMLPackage, CommonUtils.formatHtml(question.getQuesBody())));
+			question.setQuestionType(QuesStructType.NESTED_ANSWER_QUESTION);
+			// 获取所有选项
+			List<TestFillAnswer> blanks = testQuestionInfo.getBlanks();
+			List<Question> subQuestions = initSubQuestions(blanks, wordMLPackage);
+			question.setSubQuestions(subQuestions);
+		}
+		// 问答题 、 名词解释
+		if (testQuestionInfo.getQuestionType() == 60 || testQuestionInfo.getQuestionType() == 69) {
+			String quesBody = testQuestionInfo.getQuestionHTML();
+			// 去掉<span>标签中的lang
+			quesBody = replaceLang(quesBody);
+			// 获取img标签
+			LinkedHashMap<String, String> bodyImgList = imgList(quesBody);
+			// 替换、补全Img标签
+			quesBody = replaceImg(bodyImgList, quesBody);
+			question.setQuesBody("<p>" + quesBody + "</p>");
+			question.setQuesBodyWord(
+					DocxProcessUtil.html2Docx(wordMLPackage, CommonUtils.formatHtml(question.getQuesBody())));
+			question.setQuestionType(QuesStructType.TEXT_ANSWER_QUESTION);
+			String answer = testQuestionInfo.getAnswer();
+			// 去掉<span>标签中的lang
+			answer = replaceLang(answer);
+			// 获取img标签
+			LinkedHashMap<String, String> answerImgList = imgList(answer);
+			// 替换、补全Img标签
+			answer = replaceImg(answerImgList, answer);
+			question.setQuesAnswer("<p>" + answer + "</p>");
+			question.setQuesAnswerWord(
+					DocxProcessUtil.html2Docx(wordMLPackage, CommonUtils.formatHtml(question.getQuesAnswer())));
+		}
+		// 单选题
+		if (testQuestionInfo.getQuestionType() == 11) {
+			String quesBody = testQuestionInfo.getQuestionHTML();
+			// 去掉<span>标签中的lang
+			quesBody = replaceLang(quesBody);
+			// 获取img标签
+			LinkedHashMap<String, String> bodyImgList = imgList(quesBody);
+			// 替换、补全Img标签
+			quesBody = replaceImg(bodyImgList, quesBody);
+			question.setQuesBody("<p>" + quesBody + "</p>");
+			question.setQuesBodyWord(
+					DocxProcessUtil.html2Docx(wordMLPackage, CommonUtils.formatHtml(question.getQuesBody())));
+			question.setQuestionType(QuesStructType.SINGLE_ANSWER_QUESTION);
+			List<QuesOption> quesOptions = new ArrayList<QuesOption>();
+			List<TestOption> options = testQuestionInfo.getOptions();
+			Integer answerNumber = null;
+			if (options != null && options.size() > 0) {
+				int number = 1;
+				short isCorrect = 0;
+				for (TestOption testOption : options) {
+					if (testOption.getID().equals(testQuestionInfo.getAnswerId())) {
+						isCorrect = 1;
+						answerNumber = number;
+					} else {
+						isCorrect = 0;
+					}
+					QuesOption quesOption = initQuesOption(testOption, number, isCorrect, wordMLPackage);
+					quesOptions.add(quesOption);
+					number++;
+				}
+			}
+			question.setQuesOptions(quesOptions);
+			if (answerNumber != null) {
+				char c1 = (char) (answerNumber + 64);
+				question.setQuesAnswer(String.valueOf(c1));
+				question.setQuesAnswerWord(DocxProcessUtil.html2Docx(wordMLPackage,
+						CommonUtils.formatHtml("<p>" + question.getQuesAnswer() + "</p>")));
+			}
+		}
+		// 多选题
+		if (testQuestionInfo.getQuestionType() == 12) {
+			String quesBody = testQuestionInfo.getQuestionHTML();
+			// 去掉<span>标签中的lang
+			quesBody = replaceLang(quesBody);
+			// 获取img标签
+			LinkedHashMap<String, String> bodyImgList = imgList(quesBody);
+			// 替换、补全Img标签
+			quesBody = replaceImg(bodyImgList, quesBody);
+			question.setQuesBody("<p>" + quesBody + "</p>");
+			question.setQuesBodyWord(
+					DocxProcessUtil.html2Docx(wordMLPackage, CommonUtils.formatHtml(question.getQuesBody())));
+			question.setQuestionType(QuesStructType.MULTIPLE_ANSWER_QUESTION);
+			List<QuesOption> quesOptions = new ArrayList<QuesOption>();
+			List<TestOption> options = testQuestionInfo.getOptions();
+			List<Integer> answerNumbers = new ArrayList<Integer>();
+			if (options != null && options.size() > 0) {
+				int number = 1;
+				short isCorrect = 0;
+				for (TestOption testOption : options) {
+					if (testQuestionInfo.getAnswers().contains(testOption.getID())) {
+						isCorrect = 1;
+						answerNumbers.add(number);
+					} else {
+						isCorrect = 0;
+					}
+					QuesOption quesOption = initQuesOption(testOption, number, isCorrect, wordMLPackage);
+					quesOptions.add(quesOption);
+					number++;
+				}
+			}
+			question.setQuesOptions(quesOptions);
+			if (answerNumbers != null && answerNumbers.size() > 0) {
+				String answers = "";
+				for (Integer number : answerNumbers) {
+					char c1 = (char) (number + 64);
+					if (StringUtils.isBlank(answers)) {
+						answers = String.valueOf(c1);
+					} else {
+						answers = answers + "," + String.valueOf(c1);
+					}
+				}
+				question.setQuesAnswer(answers);
+				question.setQuesAnswerWord(DocxProcessUtil.html2Docx(wordMLPackage,
+						CommonUtils.formatHtml("<p>" + question.getQuesAnswer() + "</p>")));
+			}
+		}
+		// 填空题 ###
+		if (testQuestionInfo.getQuestionType() == 13) {
+			String quesBody = testQuestionInfo.getQuestionHTML();
+			// 去掉<span>标签中的lang
+			quesBody = replaceLang(quesBody);
+			// 获取img标签
+			LinkedHashMap<String, String> imgList = imgList(quesBody);
+			if (imgList != null && imgList.size() > 0) {
+				for (Map.Entry<String, String> entry : imgList.entrySet()) {
+					if (StringUtils.isBlank(entry.getValue())) {
+						quesBody = quesBody.replace(entry.getKey(), "(###)");
+					} else {
+						quesBody = quesBody.replace(entry.getKey(), entry.getValue());
+					}
+				}
+			}
+			question.setQuesBody("<p>" + quesBody + "</p>");
+			question.setQuesBodyWord(
+					DocxProcessUtil.html2Docx(wordMLPackage, CommonUtils.formatHtml(question.getQuesBody())));
+			question.setQuestionType(QuesStructType.FILL_BLANK_QUESTION);
+			String answer = "";
+			List<TestFillAnswer> blanks = testQuestionInfo.getBlanks();
+			if (blanks != null && blanks.size() > 0) {
+				for (TestFillAnswer testFillAnswer : blanks) {
+					List<TestFillContent> answers = testFillAnswer.getAnswers();
+					if (answers != null && answers.size() > 0) {
+						for (TestFillContent testFillContent : answers) {
+							if (StringUtils.isBlank(answer)) {
+								answer = testFillContent.getContent();
+							} else {
+								answer = answer + "##" + testFillContent.getContent();
+							}
+						}
+					}
+				}
+				// 去掉<span>标签中的lang
+				answer = replaceLang(answer);
+				// 获取img标签
+				LinkedHashMap<String, String> answerImgList = imgList(answer);
+				// 替换、补全Img标签
+				answer = replaceImg(answerImgList, answer);
+				question.setQuesAnswer("<p>" + answer + "</p>");
+				question.setQuesAnswerWord(
+						DocxProcessUtil.html2Docx(wordMLPackage, CommonUtils.formatHtml(question.getQuesAnswer())));
+			}
+		}
+		// 判断题
+		if (testQuestionInfo.getQuestionType() == 20) {
+			String quesBody = testQuestionInfo.getQuestionHTML();
+			// 去掉<span>标签中的lang
+			quesBody = replaceLang(quesBody);
+			// 获取img标签
+			LinkedHashMap<String, String> bodyImgList = imgList(quesBody);
+			// 替换、补全Img标签
+			quesBody = replaceImg(bodyImgList, quesBody);
+			question.setQuesBody("<p>" + quesBody + "</p>");
+			question.setQuesBodyWord(
+					DocxProcessUtil.html2Docx(wordMLPackage, CommonUtils.formatHtml(question.getQuesBody())));
+			question.setQuestionType(QuesStructType.BOOL_ANSWER_QUESTION);
+			String answer = testQuestionInfo.getAnswer();
+			if (answer.equals("false")) {
+				answer = "错误";
+			} else {
+				answer = "正确";
+			}
+			question.setQuesAnswer(answer);
+			question.setQuesAnswerWord(DocxProcessUtil.html2Docx(wordMLPackage,
+					CommonUtils.formatHtml("<p>" + question.getQuesAnswer() + "</p>")));
+		}
+		byte[] pkgByte = DocxProcessUtil.getPkgByte(wordMLPackage);
+		QuestionPkgPath quesPkgPath = new QuestionPkgPath(pkgByte);
+		map.put(question, quesPkgPath);
+	}
+
+	// 去除<span> 标签中lang = EN - US
+	private String replaceLang(String str) {
+		if (str.contains("lang=EN-US")) {
+			str = str.replace("lang=EN-US", "");
+		}
+		if (str.contains("alt=\"\u0012\"")) {
+			str = str.replace("alt=\"\u0012\"", "alt=\"\"");
+		}
+		if (str.contains("alt=\"&#18;\"")) {
+			str = str.replace("alt=\"&#18;\"", "alt=\"\"");
+		}
+		if (str.contains("\u000b")) {
+			str = str.replaceAll("\u000b", "");
+		}
+		if (str.contains("&#0;")) {
+			str = str.replaceAll("&#0;", "");
+		}
+		if (str.contains("<img  width=\"25\" height=\"23\" src=\"/UploadFiles/Import/Image/3cf48167-932f-4ae6-be69-37520a02cd23_.png\"/>")) {
+			str = str.replaceAll("<img  width=\"25\" height=\"23\" src=\"/UploadFiles/Import/Image/3cf48167-932f-4ae6-be69-37520a02cd23_.png\"/>",
+					"图片缺失");
+		}
+		if (str.contains("<img  width=\"25\" height=\"23\" src=\"/UploadFiles/Import/Image/3cf48167-932f-4ae6-be69-37520a02cd23_.png\"/>")) {
+			str = str.replaceAll("<img  width=\"25\" height=\"23\" src=\"/UploadFiles/Import/Image/3cf48167-932f-4ae6-be69-37520a02cd23_.png\"/>", "图片缺失");
+		}
+		if (str.contains("<img  width=\"24\" height=\"24\" src=\"/UploadFiles/Import/Image/811ae8b2-4d74-4cc2-a8a3-9665e5e810c1_.png\"/>")) {
+			str = str.replaceAll("<img  width=\"24\" height=\"24\" src=\"/UploadFiles/Import/Image/811ae8b2-4d74-4cc2-a8a3-9665e5e810c1_.png\"/>", "图片缺失");
+		}
+		if (str.contains("<img width=\"12\" height=\"13\" src=\"管理会计%20专升本.files/image001.png\">")) {
+			str = str.replaceAll("<img width=\"12\" height=\"13\" src=\"管理会计%20专升本.files/image001.png\">", "图片缺失");
+		}
+		if (str.contains("<img style=\"max-width: 600px; height: auto\" alt=\"\" src=\"/UploadFiles/刘晓平/Images/OnlineExam20180709151328.png\" />")) {
+			str = str.replaceAll("<img style=\"max-width: 600px; height: auto\" alt=\"\" src=\"/UploadFiles/刘晓平/Images/OnlineExam20180709151328.png\" />", "图片缺失");
+		}
+		if (str.contains("<img width=\"52\" height=\"45\" src=\"机械制造工艺学%20专升本%20综合测试2.files/image002.png\">")) {
+			str = str.replaceAll("<img width=\"52\" height=\"45\" src=\"机械制造工艺学%20专升本%20综合测试2.files/image002.png\">", "图片缺失");
+		}
+		if (str.contains("<img  width=\"25\" height=\"23\" src=\"/UploadFiles/Import/Image/001d24f0-a007-4c13-8cb4-2a138d0545ae_.png\"/>")) {
+			str = str.replaceAll("<img  width=\"25\" height=\"23\" src=\"/UploadFiles/Import/Image/001d24f0-a007-4c13-8cb4-2a138d0545ae_.png\"/>", "图片缺失");
+		}
+		if (str.contains("<img src=\"/UploadFiles/李家林/Images/OnlineExam20140312164501.png\" alt=\"\" />")) {
+			str = str.replaceAll("<img src=\"/UploadFiles/李家林/Images/OnlineExam20140312164501.png\" alt=\"\" />", "图片缺失");
+		}
+		if (str.contains("<img  width=\"25\" height=\"23\" src=\"/UploadFiles/Import/Image/001d24f0-a007-4c13-8cb4-2a138d0545ae_.png\"/>")) {
+			str = str.replaceAll("<img  width=\"25\" height=\"23\" src=\"/UploadFiles/Import/Image/001d24f0-a007-4c13-8cb4-2a138d0545ae_.png\"/>", "图片缺失");
+		}
+		if (str.contains("<img  width=\"24\" height=\"24\" src=\"/UploadFiles/Import/Image/7828a9f0-5ec4-435d-ac78-cc400bc4cc22_.png\"/>")) {
+			str = str.replaceAll("<img  width=\"24\" height=\"24\" src=\"/UploadFiles/Import/Image/7828a9f0-5ec4-435d-ac78-cc400bc4cc22_.png\"/>", "图片缺失");
+		}
+		if (str.contains("<img alt=\"\" src=\"/UploadFiles/王建军/Images/OnlineExam20160319160348.jpg\" />")) {
+			str = str.replaceAll("<img alt=\"\" src=\"/UploadFiles/王建军/Images/OnlineExam20160319160348.jpg\" />", "图片缺失");
+		}
+		
+//		if (str.contains("&lt;")) {
+//			str = str.replace("&lt;", "<");
+//		}
+//		if (str.contains("&gt;")) {
+//			str = str.replace("&gt;", ">");
+//		}
+//		if (str.contains("&")) {
+//			str = str.replaceAll("&", "&amp;");
+//		}
+//		if (str.contains("<")) {
+//			str = str.replaceAll("<", "&lt;");
+//		}
+//		if (str.contains(">")) {
+//			str = str.replaceAll(">", "&gt;");
+//		}
+		return str;
+	}
+
+	// 替换img标签,补全图片
+	private String replaceImg(LinkedHashMap<String, String> imgList, String str) {
+		if (imgList != null && imgList.size() > 0) {
+			for (Map.Entry<String, String> entry : imgList.entrySet()) {
+				if (StringUtils.isBlank(entry.getValue())) {
+					str = str.replace(entry.getKey(), "___");
+				} else {
+					str = str.replace(entry.getKey(), entry.getValue());
+				}
+			}
+		}
+		return str;
+	}
+
+	// 將url路徑中的中文转码
+	private String regexCH(String str) throws UnsupportedEncodingException {
+		StringBuffer s = new StringBuffer();
+		Pattern pat = Pattern.compile("[\u4E00-\u9FA5]");
+		Matcher mat = pat.matcher(str);
+		while (mat.find()) {
+			s.append(mat.group());
+		}
+		String url = URLEncoder.encode(s.toString(), "utf-8");
+		return str.replace(s.toString(), url);
+	}
+
+	// 去除图片中有下划线的图片,并补全图片下载地址
+	private LinkedHashMap<String, String> imgList(String str) throws Exception {
+		LinkedHashMap<String, String> map = new LinkedHashMap<>();
+		// 获取img标签
+		List<String> srcList = ImgDataUtils.parseImages(str);
+		if (srcList != null && srcList.size() > 0) {
+			for (String img : srcList) {
+				if (img.contains("/Shared/UnderLine")) {
+					map.put(img, "");
+				} else {
+					List<String> parseImageSrc = ImgDataUtils.parseImageSrc(img);
+					if (parseImageSrc != null && parseImageSrc.size() > 0) {
+						String src = parseImageSrc.get(0);
+						String url = regexCH(src);
+						String picture=null;
+						if(url.startsWith("http://ncexam.cug.edu.cn/")) {
+							picture = url;
+						}else {
+							picture = "http://ncexam.cug.edu.cn" + url;
+						}
+						String base64 = ImgDataUtils.loadImageToBase64(picture);
+						if (base64 == null) {
+							throw new StatusException("50001", "图片下载失败" + picture);
+						} else {
+							if (src.contains("jpg")) {
+								map.put(img, img.replace(src, "data:image/jpg;base64," + base64));
+							} else if(src.contains("bmp")){
+								map.put(img, img.replace(src, "data:image/bmp;base64," + base64));
+							}else {
+								map.put(img, img.replace(src, "data:image/png;base64," + base64));
+							}
+						}
+					}
+				}
+			}
+			return map;
+		}
+		return null;
+	}
+
+	private List<Question> initSubQuestionsByOther(TestQuestionInfo testQuestionInfo,
+			WordprocessingMLPackage wordMLPackage) throws Exception {
+		List<Question> subQuestions = new ArrayList<Question>();
+		if (testQuestionInfo.getBlanks() != null && testQuestionInfo.getBlanks().size() > 0) {
+			List<TestFillAnswer> blanks = testQuestionInfo.getBlanks();
+			for (TestFillAnswer testFillAnswer : blanks) {
+				Question subQuestion = new Question();
+				subQuestion.setId(IdUtils.uuid());
+				subQuestion.setQuestionType(QuesStructType.SINGLE_ANSWER_QUESTION);
+				subQuestion.setDifficulty("中");
+				subQuestion.setDifficultyDegree(0.5);
+				subQuestion.setPublicity(true);
+				subQuestion.setQuesBody("______");
+				subQuestion.setQuesBodyWord(DocxProcessUtil.html2Docx(wordMLPackage,
+						CommonUtils.formatHtml("<p>" + subQuestion.getQuesBody() + "</p>")));
+				List<QuesOption> quesOptions = new ArrayList<QuesOption>();
+				TestOptionGroup optionGroup = testQuestionInfo.getOptionGroup();
+				List<TestOption> options = optionGroup.getOptions();
+				Integer answerNumber = null;
+				if (options != null && options.size() > 0) {
+					for (TestOption subOption : options) {
+						int subNumber = 1;
+						short isCorrect = 0;
+						if (testFillAnswer.getAnswerId().equals(subOption.getID())) {
+							isCorrect = 1;
+							answerNumber = subNumber;
+						} else {
+							isCorrect = 0;
+						}
+						QuesOption quesOption = initQuesOption(subOption, subNumber, isCorrect, wordMLPackage);
+						quesOptions.add(quesOption);
+						subNumber++;
+					}
+				}
+				subQuestion.setQuesOptions(quesOptions);
+				if (answerNumber != null) {
+					char c1 = (char) (answerNumber + 64);
+					subQuestion.setQuesAnswer(String.valueOf(c1));
+					subQuestion.setQuesAnswerWord(DocxProcessUtil.html2Docx(wordMLPackage,
+							CommonUtils.formatHtml("<p>" + subQuestion.getQuesAnswer() + "</p>")));
+				}
+				subQuestions.add(subQuestion);
+			}
+		}
+		return subQuestions;
+	}
+
+	// 初始化选项
+	private QuesOption initQuesOption(TestOption testOption, int number, short isCorrect,
+			WordprocessingMLPackage wordMLPackage) throws Exception {
+		QuesOption quesOption = new QuesOption();
+		quesOption.setNumber(String.valueOf(number));
+		quesOption.setIsCorrect(isCorrect);
+		String optionBody = testOption.getOptionHTML();
+		// 去掉<span>标签中的lang
+		optionBody = replaceLang(optionBody);
+		// 获取img标签
+		LinkedHashMap<String, String> optionBodyImgList = imgList(optionBody);
+		// 替换、补全Img标签
+		optionBody = replaceImg(optionBodyImgList, optionBody);
+		quesOption.setOptionBody("<p>" + optionBody + "</p>");
+		quesOption.setOptionBodyWord(
+				DocxProcessUtil.html2Docx(wordMLPackage, CommonUtils.formatHtml(quesOption.getOptionBody())));
+		return quesOption;
+	}
+
+	// 根据父ID查询子题
+	private List<TestQuestion> querySubQuestions(String parentId, String dir, XSSFSheet sheet) {
+		List<TestQuestion> questions = new ArrayList<TestQuestion>();
+		for (int i = 1; i <= sheet.getLastRowNum(); i++) {
+			XSSFRow row = sheet.getRow(i);
+			String pid = row.getCell(5).getStringCellValue();
+			if (parentId.equals(pid)) {
+				TestQuestion tq = new TestQuestion();
+				tq.setId(row.getCell(0).getStringCellValue());
+				tq.setdNumber(getIntByString(row.getCell(1).getStringCellValue()));
+				tq.setdName(row.getCell(2).getStringCellValue());
+				tq.setNumber(getIntByString(row.getCell(3).getStringCellValue()));
+				tq.setScore(getDoubleByString(row.getCell(4).getStringCellValue()));
+				tq.setParentId(row.getCell(5).getStringCellValue());
+				tq.setType(getIntByString(row.getCell(6).getStringCellValue()));
+				File quesJson = new File(dir + tq.getId() + ".txt");
+				if (!quesJson.exists()) {
+					throw new StatusException("400002", "试题信息文件不存在");
+				}
+				tq.setJson(FileUtil.readFileContent(quesJson));
+				questions.add(tq);
+			}
+		}
+
+		if (questions.size() == 0) {
+			throw new StatusException("400001", "试题信息为空");
+		}
+		return questions;
+	}
+
+	// 完形填空初始化所有子题
+	private List<Question> initSubQuestions(List<TestFillAnswer> blanks, WordprocessingMLPackage wordMLPackage)
+			throws Exception {
+		List<Question> subQuestions = new ArrayList<Question>();
+		if (blanks != null && blanks.size() > 0) {
+			for (TestFillAnswer testFillAnswer : blanks) {
+				Question question = new Question();
+				question.setId(IdUtils.uuid());
+				question.setQuestionType(QuesStructType.SINGLE_ANSWER_QUESTION);
+				question.setDifficulty("中");
+				question.setDifficultyDegree(0.5);
+				question.setPublicity(true);
+				question.setQuesBody("______");
+				question.setQuesBodyWord(DocxProcessUtil.html2Docx(wordMLPackage,
+						CommonUtils.formatHtml("<p>" + question.getQuesBody() + "</p>")));
+				TestOptionGroup optionGroup = testFillAnswer.getOptionGroup();
+				List<QuesOption> quesOptions = new ArrayList<QuesOption>();
+				List<TestOption> subOptions = optionGroup.getOptions();
+				Integer answerNumber = null;
+				if (subOptions != null && subOptions.size() > 0) {
+					int subNumber = 1;
+					short isCorrect = 0;
+					for (TestOption subOption : subOptions) {
+						if (testFillAnswer.getAnswerId().equals(subOption.getID())) {
+							isCorrect = 1;
+							answerNumber = subNumber;
+						} else {
+							isCorrect = 0;
+						}
+						QuesOption quesOption = initQuesOption(subOption, subNumber, isCorrect, wordMLPackage);
+						quesOptions.add(quesOption);
+						subNumber++;
+					}
+				}
+				question.setQuesOptions(quesOptions);
+				if (answerNumber != null) {
+					char c1 = (char) (answerNumber + 64);
+					question.setQuesAnswer(String.valueOf(c1));
+					question.setQuesAnswerWord(DocxProcessUtil.html2Docx(wordMLPackage,
+							CommonUtils.formatHtml("<p>" + question.getQuesAnswer() + "</p>")));
+				}
+				subQuestions.add(question);
+			}
+		}
+		return subQuestions;
+	}
+
+	// 初始化小题对象
+	private PaperDetailUnit initPaperDetailUnit(Paper paper, PaperDetail paperDetail, Question question,
+			TestQuestion testQuestion, User user) {
+		PaperDetailUnit paperDetailUnit = new PaperDetailUnit();
+		paperDetailUnit.setPaper(paper);
+		paperDetailUnit.setNumber(testQuestion.getNumber());
+		paperDetailUnit.setScore(testQuestion.getScore());
+		paperDetailUnit.setPaperDetail(paperDetail);
+		paperDetailUnit.setQuestionType(question.getQuestionType());
+		paperDetailUnit.setCreator(user.getDisplayName());
+		paperDetailUnit.setCreateTime(CommonUtils.getCurDateTime());
+		paperDetailUnit.setQuestion(question);
+		return paperDetailUnit;
+	}
+}