|
@@ -0,0 +1,723 @@
|
|
|
+package cn.com.qmth.examcloud.core.questions.service.util;
|
|
|
+
|
|
|
+import java.io.File;
|
|
|
+import java.io.IOException;
|
|
|
+import java.io.StringWriter;
|
|
|
+import java.util.ArrayList;
|
|
|
+import java.util.HashMap;
|
|
|
+import java.util.List;
|
|
|
+import java.util.Map;
|
|
|
+import java.util.regex.Matcher;
|
|
|
+import java.util.regex.Pattern;
|
|
|
+
|
|
|
+import org.apache.commons.io.FileUtils;
|
|
|
+import org.apache.commons.lang.StringEscapeUtils;
|
|
|
+import org.apache.commons.lang3.StringUtils;
|
|
|
+import org.jsoup.Jsoup;
|
|
|
+import org.jsoup.nodes.Document;
|
|
|
+import org.jsoup.nodes.Element;
|
|
|
+import org.jsoup.nodes.Node;
|
|
|
+import org.jsoup.nodes.TextNode;
|
|
|
+import org.slf4j.Logger;
|
|
|
+import org.slf4j.LoggerFactory;
|
|
|
+
|
|
|
+import cn.com.qmth.examcloud.commons.exception.ExamCloudRuntimeException;
|
|
|
+import cn.com.qmth.examcloud.core.questions.base.FileDisposeUtil;
|
|
|
+import cn.com.qmth.examcloud.core.questions.base.dto.ExportTempDataDto;
|
|
|
+import cn.com.qmth.examcloud.core.questions.base.enums.ExamFileType;
|
|
|
+import cn.com.qmth.examcloud.core.questions.base.enums.ExportTemplateType;
|
|
|
+import cn.com.qmth.examcloud.core.questions.base.json.JOption;
|
|
|
+import cn.com.qmth.examcloud.core.questions.base.json.JOptionDto;
|
|
|
+import cn.com.qmth.examcloud.core.questions.base.json.JSection;
|
|
|
+import cn.com.qmth.examcloud.core.questions.base.json.JsonImportUtil;
|
|
|
+import cn.com.qmth.examcloud.core.questions.base.json.SectionElement;
|
|
|
+import cn.com.qmth.examcloud.core.questions.base.json.SectionElementParams;
|
|
|
+import cn.com.qmth.examcloud.core.questions.base.question.enums.QuesStructType;
|
|
|
+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.service.bean.dto.PaperDetailExp;
|
|
|
+import cn.com.qmth.examcloud.core.questions.service.bean.dto.PaperDetailUnitExp;
|
|
|
+import cn.com.qmth.examcloud.core.questions.service.bean.dto.PaperExp;
|
|
|
+import freemarker.template.Configuration;
|
|
|
+import freemarker.template.Template;
|
|
|
+import sun.misc.BASE64Decoder;
|
|
|
+
|
|
|
+public class ExportPaperUtil {
|
|
|
+
|
|
|
+ private static final Logger log = LoggerFactory.getLogger(ExportPaperUtil.class);
|
|
|
+
|
|
|
+ private static final int docImageSzie=12700;
|
|
|
+
|
|
|
+ private static final String DOCX_SUFFIX = ".docx";
|
|
|
+
|
|
|
+ private static final String ZIP_SUFFIX = ".zip";
|
|
|
+
|
|
|
+ public static final String QUESOPS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
|
|
+
|
|
|
+ public static final String ELEMENT_TYPE_RID = "imageId";
|
|
|
+
|
|
|
+ public static final String ELEMENT_TYPE_TEXT = "text";
|
|
|
+
|
|
|
+ public static final String ELEMENT_TYPE_IMG = "image";
|
|
|
+
|
|
|
+ private static final String ENCODING = "UTF-8";
|
|
|
+
|
|
|
+ private static Configuration config;
|
|
|
+
|
|
|
+ private static Template docSection;
|
|
|
+
|
|
|
+ private static Template examReamarkDocument;
|
|
|
+
|
|
|
+ private static Template questionSection;
|
|
|
+
|
|
|
+ private static Template paperQuesOps;
|
|
|
+
|
|
|
+ private static Template contentTypes;
|
|
|
+
|
|
|
+ private static Template document;
|
|
|
+
|
|
|
+ private static Template documentRel;
|
|
|
+
|
|
|
+ private static Pattern heightRex = Pattern.compile("height:([\\s\\S]*?)px");
|
|
|
+
|
|
|
+ private static Pattern widthRex = Pattern.compile("width:([\\s\\S]*?)px");
|
|
|
+ static {
|
|
|
+
|
|
|
+ config = new Configuration(Configuration.VERSION_2_3_25);
|
|
|
+ // 设置编码
|
|
|
+ config.setDefaultEncoding(ENCODING);
|
|
|
+ // 设置ftl模板路径
|
|
|
+ config.setClassForTemplateLoading(JsonImportUtil.class, "/export_template/origin_paper/");
|
|
|
+
|
|
|
+ try {
|
|
|
+ questionSection = config.getTemplate("question_section.ftl", ENCODING);
|
|
|
+ contentTypes = config.getTemplate("content_types.ftl", ENCODING);
|
|
|
+ document = config.getTemplate("document.ftl", ENCODING);
|
|
|
+ documentRel = config.getTemplate("document_rel.ftl", ENCODING);
|
|
|
+ paperQuesOps = config.getTemplate("question_options.ftl", ENCODING);
|
|
|
+ docSection=config.getTemplate("doc_section.ftl", ENCODING);
|
|
|
+ examReamarkDocument=config.getTemplate("exam_reamark_document.ftl", ENCODING);
|
|
|
+ } catch (IOException e) {
|
|
|
+ log.error(e.getMessage(), e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ //考试说明word文件
|
|
|
+ public static File createExamRemarkDocFile(File directory,String fileName,String html) throws IOException {
|
|
|
+ // doc固定源文件目录
|
|
|
+ File docxDir = new File(getDocxBasePath());
|
|
|
+ // 将要生成的doc源文件目录
|
|
|
+ File docxTargetDir = new File(directory.getAbsolutePath() + "/docx/");
|
|
|
+ docxTargetDir.mkdir();
|
|
|
+ // 复制docx基础文件
|
|
|
+ FileUtils.copyDirectory(docxDir, docxTargetDir);
|
|
|
+ // 处理并生成doc源文件
|
|
|
+ disposeExamRemark(docxTargetDir, html);
|
|
|
+ // 压缩docx源文件
|
|
|
+ File zipfile = new File(
|
|
|
+ docxTargetDir.getParentFile().getAbsolutePath() + File.separator + fileName + ZIP_SUFFIX);
|
|
|
+ FileDisposeUtil.createZip(docxTargetDir.getAbsolutePath(), zipfile.getAbsolutePath());
|
|
|
+ File docfile = new File(
|
|
|
+ docxTargetDir.getParentFile().getAbsolutePath() + File.separator + fileName + DOCX_SUFFIX);
|
|
|
+ // 修改压缩包为doc文件
|
|
|
+ zipfile.renameTo(docfile);
|
|
|
+ FileUtils.deleteDirectory(docxTargetDir);
|
|
|
+ return docfile;
|
|
|
+ }
|
|
|
+ private static void disposeExamRemark(File docxTargetDir, String html) throws IOException {
|
|
|
+ ExportTempDataDto dto = new ExportTempDataDto();
|
|
|
+ List<JSection> slist=null;
|
|
|
+ if (StringUtils.isNotBlank(html)) {
|
|
|
+ slist = getSections(html);
|
|
|
+ if (slist != null && slist.size() > 0) {
|
|
|
+ htmlToDoc(slist, dto);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ // content-type
|
|
|
+ writeContentType(docxTargetDir, dto);
|
|
|
+ // document
|
|
|
+ writeExamRemarkDocument(docxTargetDir, slist);
|
|
|
+ // document-rel
|
|
|
+ writeDocumentRel(docxTargetDir, dto);
|
|
|
+ // image file
|
|
|
+ writeImage(docxTargetDir, dto);
|
|
|
+ }
|
|
|
+ private static void writeExamRemarkDocument(File docxTargetDir, List<JSection> slist) throws IOException {
|
|
|
+ StringWriter result = null;
|
|
|
+ try {
|
|
|
+ result = new StringWriter();
|
|
|
+ Map<String, Object> map = new HashMap<String, Object>();
|
|
|
+ map.put("sections", slist);
|
|
|
+ examReamarkDocument.process(map, result);
|
|
|
+ } catch (Exception e) {
|
|
|
+ throw new ExamCloudRuntimeException(e);
|
|
|
+ }
|
|
|
+ File file = new File(docxTargetDir.getAbsolutePath() + "/word/document.xml");
|
|
|
+ FileUtils.writeStringToFile(file, result.toString(), "utf-8");
|
|
|
+ }
|
|
|
+ // 考试试卷
|
|
|
+ public static File createPaperDocFile(Long rootOrgId, PaperExp paperExp, File directory, String paperfileName,
|
|
|
+ ExportTemplateType templateType) throws Exception {
|
|
|
+ DocxTemplateBean docxTemplate = ExportTemplateUtil.getDocxTemplateBean(rootOrgId, templateType);
|
|
|
+ // doc固定源文件目录
|
|
|
+ File docxDir = new File(docxTemplate.getDocxPath());
|
|
|
+ // 将要生成的doc源文件目录
|
|
|
+ File docxTargetDir = new File(directory.getAbsolutePath() + File.separator + "docx" + File.separator);
|
|
|
+ docxTargetDir.mkdir();
|
|
|
+ // 复制docx基础文件
|
|
|
+ FileUtils.copyDirectory(docxDir, docxTargetDir);
|
|
|
+ // 处理并生成doc源文件
|
|
|
+ disposePaperDoc(docxTargetDir, paperExp, docxTemplate);
|
|
|
+ // 压缩docx源文件
|
|
|
+ File zipfile = new File(docxTargetDir.getParentFile().getAbsolutePath() + File.separator
|
|
|
+ + paperfileName.substring(0, paperfileName.lastIndexOf(".")) + ZIP_SUFFIX);
|
|
|
+ FileDisposeUtil.createZip(docxTargetDir.getAbsolutePath(), zipfile.getAbsolutePath());
|
|
|
+ File docfile = new File(docxTargetDir.getParentFile().getAbsolutePath() + File.separator + paperfileName);
|
|
|
+ // 修改压缩包为doc文件
|
|
|
+ zipfile.renameTo(docfile);
|
|
|
+ FileUtils.deleteDirectory(docxTargetDir);
|
|
|
+ return docfile;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ private static void disposePaperDoc(File docxTargetDir, PaperExp paperExp, DocxTemplateBean docxTemplate)
|
|
|
+ throws IOException {
|
|
|
+ ExportTempDataDto dto = new ExportTempDataDto();
|
|
|
+ disposePaperExamRemark(paperExp, dto);
|
|
|
+ if (paperExp.getPaperDetails() != null && paperExp.getPaperDetails().size() > 0) {
|
|
|
+ for (PaperDetailExp pde : paperExp.getPaperDetails()) {
|
|
|
+ dto.setSubNum(0);
|
|
|
+ dto.setAnswerNum(0);
|
|
|
+ if (pde.getPaperDetailUnits() != null && pde.getPaperDetailUnits().size() > 0) {
|
|
|
+ for (PaperDetailUnitExp pdue : pde.getPaperDetailUnits()) {
|
|
|
+ Question qes = pdue.getQuestion();
|
|
|
+ disposePaperQuestion(qes, dto);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ // content-type
|
|
|
+ writePaperContentType(docxTargetDir, dto, docxTemplate);
|
|
|
+ // document
|
|
|
+ writePaperDocument(docxTargetDir, paperExp, docxTemplate);
|
|
|
+ // document-rel
|
|
|
+ writePaperDocumentRel(docxTargetDir, dto, docxTemplate);
|
|
|
+ // image file
|
|
|
+ writeImage(docxTargetDir, dto);
|
|
|
+ }
|
|
|
+
|
|
|
+ private static void writePaperDocument(File docxTargetDir, PaperExp paperExp, DocxTemplateBean docxTemplate)
|
|
|
+ throws IOException {
|
|
|
+ String doc = getPaperDocumentDoc(paperExp, docxTemplate);
|
|
|
+ File file = new File(docxTargetDir.getAbsolutePath() + "/word/document.xml");
|
|
|
+ FileUtils.writeStringToFile(file, doc, "utf-8");
|
|
|
+ }
|
|
|
+
|
|
|
+ private static String getPaperDocumentDoc(Object paperExp, DocxTemplateBean docxTemplate) {
|
|
|
+ StringWriter result = null;
|
|
|
+ try {
|
|
|
+ result = new StringWriter();
|
|
|
+ docxTemplate.getDocument().process(paperExp, result);
|
|
|
+ return result.toString();
|
|
|
+ } catch (Exception e) {
|
|
|
+ throw new ExamCloudRuntimeException(e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private static void writePaperContentType(File docxTargetDir, ExportTempDataDto dto, DocxTemplateBean docxTemplate)
|
|
|
+ throws IOException {
|
|
|
+ Map<String, Object> map = new HashMap<String, Object>();
|
|
|
+ map.put("images", dto.getTypes());
|
|
|
+ String doc = getPaperContentTypesDoc(map, docxTemplate);
|
|
|
+ File file = new File(docxTargetDir.getAbsolutePath() + "/[Content_Types].xml");
|
|
|
+ FileUtils.writeStringToFile(file, doc, "utf-8");
|
|
|
+ }
|
|
|
+
|
|
|
+ private static String getPaperContentTypesDoc(Map<String, Object> map, DocxTemplateBean docxTemplate) {
|
|
|
+ StringWriter result = null;
|
|
|
+ try {
|
|
|
+ result = new StringWriter();
|
|
|
+ docxTemplate.getContentTypes().process(map, result);
|
|
|
+ return result.toString();
|
|
|
+ } catch (Exception e) {
|
|
|
+ throw new ExamCloudRuntimeException(e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private static void writePaperDocumentRel(File docxTargetDir, ExportTempDataDto dto, DocxTemplateBean docxTemplate)
|
|
|
+ throws IOException {
|
|
|
+ Map<String, Object> map = new HashMap<String, Object>();
|
|
|
+ map.put("images", dto.getImages());
|
|
|
+ String doc = getPaperDocumentRelDoc(map, docxTemplate);
|
|
|
+ File file = new File(docxTargetDir.getAbsolutePath() + "/word/_rels/document.xml.rels");
|
|
|
+ FileUtils.writeStringToFile(file, doc, "utf-8");
|
|
|
+ }
|
|
|
+
|
|
|
+ private static String getPaperDocumentRelDoc(Map<String, Object> map, DocxTemplateBean docxTemplate) {
|
|
|
+ StringWriter result = null;
|
|
|
+ try {
|
|
|
+ result = new StringWriter();
|
|
|
+ docxTemplate.getDocumentRels().process(map, result);
|
|
|
+ return result.toString();
|
|
|
+ } catch (Exception e) {
|
|
|
+ throw new ExamCloudRuntimeException(e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 原始试卷
|
|
|
+ public static File createOriginPaperDocFile(PaperExp paperExp, File directory) throws Exception {
|
|
|
+ // doc固定源文件目录
|
|
|
+ File docxDir = new File(getDocxBasePath());
|
|
|
+ // 将要生成的doc源文件目录
|
|
|
+ File docxTargetDir = new File(directory.getAbsolutePath() + "/docx/");
|
|
|
+ docxTargetDir.mkdir();
|
|
|
+ // 复制docx基础文件
|
|
|
+ FileUtils.copyDirectory(docxDir, docxTargetDir);
|
|
|
+ // 处理并生成doc源文件
|
|
|
+ dispose(docxTargetDir, paperExp);
|
|
|
+ // 压缩docx源文件
|
|
|
+ String paperfileName = paperExp.getName() + "_" + paperExp.getCourseNo() + "_" + ExamFileType.PAPER.getName();
|
|
|
+ File zipfile = new File(
|
|
|
+ docxTargetDir.getParentFile().getAbsolutePath() + File.separator + paperfileName + ZIP_SUFFIX);
|
|
|
+ FileDisposeUtil.createZip(docxTargetDir.getAbsolutePath(), zipfile.getAbsolutePath());
|
|
|
+ File docfile = new File(
|
|
|
+ docxTargetDir.getParentFile().getAbsolutePath() + File.separator + paperfileName + DOCX_SUFFIX);
|
|
|
+ // 修改压缩包为doc文件
|
|
|
+ zipfile.renameTo(docfile);
|
|
|
+ FileUtils.deleteDirectory(docxTargetDir);
|
|
|
+ return docfile;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ private static String getDocxBasePath() {
|
|
|
+ return JsonImportUtil.class.getProtectionDomain().getCodeSource().getLocation().getPath()
|
|
|
+ + "export_template/docx";
|
|
|
+ }
|
|
|
+
|
|
|
+ private static List<JSection> getSections(String html) {
|
|
|
+ return getSections(html, false);
|
|
|
+ }
|
|
|
+
|
|
|
+ private static List<JSection> getSections(String html, boolean diposeFillBlank) {
|
|
|
+ if (StringUtils.isBlank(html)) {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ html = html.trim();
|
|
|
+ if (!html.startsWith("<p>")) {
|
|
|
+ html = "<p>" + html + "</p>";
|
|
|
+ }
|
|
|
+ List<JSection> ss = new ArrayList<JSection>();
|
|
|
+ Document doc = Jsoup.parse(html);
|
|
|
+ Element b = doc.body();
|
|
|
+ for (Node e : b.childNodes()) {
|
|
|
+ if ("p".equals(e.nodeName()) && e.childNodeSize() > 0) {
|
|
|
+ JSection s = new JSection();
|
|
|
+ List<SectionElement> ses = new ArrayList<SectionElement>();
|
|
|
+ s.setElements(ses);
|
|
|
+ for (Node ce : e.childNodes()) {
|
|
|
+ getSectionElement(ce, ses, diposeFillBlank);
|
|
|
+ }
|
|
|
+ ss.add(s);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return ss;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ private static void getSectionElement(Node ce, List<SectionElement> ses, boolean diposeFillBlank) {
|
|
|
+ if ("span".equals(ce.nodeName()) && ce.childNodeSize() > 0) {
|
|
|
+ for (Node e : ce.childNodes()) {
|
|
|
+ getSectionElement(e, ses, diposeFillBlank);
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ SectionElement se = new SectionElement();
|
|
|
+ if (ce instanceof TextNode) {
|
|
|
+ TextNode tn = (TextNode) ce;
|
|
|
+ se.setType(ELEMENT_TYPE_TEXT);
|
|
|
+ String text = tn.text();
|
|
|
+ if (diposeFillBlank) {
|
|
|
+ text = text.replaceAll("###", "______").replaceAll("##", "______");
|
|
|
+ }
|
|
|
+ text = text.replaceAll("<", "<").replaceAll(">", ">").replaceAll("\u0000", " ");
|
|
|
+ se.setValue(text);
|
|
|
+ } else if (ce instanceof Element) {
|
|
|
+ if ("img".equals(ce.nodeName())) {
|
|
|
+ se.setType(ELEMENT_TYPE_IMG);
|
|
|
+ se.setValue(ce.attr("src"));
|
|
|
+ SectionElementParams sep = se.getParams();
|
|
|
+ sep.setHeight(getHeight(ce));
|
|
|
+ sep.setWidth(getWidth(ce));
|
|
|
+ } else {
|
|
|
+ Element el = (Element) ce;
|
|
|
+ se.setType(ELEMENT_TYPE_TEXT);
|
|
|
+ se.setValue(el.text());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ ses.add(se);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private static int getWidth(Node ce) {
|
|
|
+ int n = 50;
|
|
|
+ String str = ce.attr("width");
|
|
|
+ if (StringUtils.isNoneBlank(str)) {
|
|
|
+ return getWordImgSize(str);
|
|
|
+ }
|
|
|
+ String style = ce.attr("style");
|
|
|
+ if (StringUtils.isNoneBlank(style)) {
|
|
|
+ Matcher m = widthRex.matcher(style);
|
|
|
+ if (m.find()) {
|
|
|
+ return Integer.valueOf(m.group(1)) * docImageSzie;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return n;
|
|
|
+ }
|
|
|
+
|
|
|
+ private static int getHeight(Node ce) {
|
|
|
+ int n = 50;
|
|
|
+ String str = ce.attr("height");
|
|
|
+ if (StringUtils.isNoneBlank(str)) {
|
|
|
+ return getWordImgSize(str);
|
|
|
+ }
|
|
|
+ String style = ce.attr("style");
|
|
|
+ if (StringUtils.isNoneBlank(style)) {
|
|
|
+ Matcher m = heightRex.matcher(style);
|
|
|
+ if (m.find()) {
|
|
|
+ return Integer.valueOf(m.group(1)) * docImageSzie;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return n;
|
|
|
+ }
|
|
|
+
|
|
|
+ private static Integer getWordImgSize(String px) {
|
|
|
+ if (StringUtils.isBlank(px)) {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ String sizeStr = px.replace("px", "");
|
|
|
+ Integer size = Integer.valueOf(sizeStr) * docImageSzie;
|
|
|
+ return size;
|
|
|
+ }
|
|
|
+
|
|
|
+ private static void dispose(File docxTargetDir, PaperExp paperExp) throws IOException {
|
|
|
+ ExportTempDataDto dto = new ExportTempDataDto();
|
|
|
+ if (paperExp.getPaperDetails() != null && paperExp.getPaperDetails().size() > 0) {
|
|
|
+ for (PaperDetailExp pde : paperExp.getPaperDetails()) {
|
|
|
+ dto.setMainNum(dto.getMainNum() + 1);
|
|
|
+ dto.setSubNum(0);
|
|
|
+ if (pde.getPaperDetailUnits() != null && pde.getPaperDetailUnits().size() > 0) {
|
|
|
+ for (PaperDetailUnitExp pdue : pde.getPaperDetailUnits()) {
|
|
|
+ Question qes = pdue.getQuestion();
|
|
|
+ disposeQuestion(qes, dto);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ // content-type
|
|
|
+ writeContentType(docxTargetDir, dto);
|
|
|
+ // document
|
|
|
+ writeDocument(docxTargetDir, paperExp);
|
|
|
+ // document-rel
|
|
|
+ writeDocumentRel(docxTargetDir, dto);
|
|
|
+ // image file
|
|
|
+ writeImage(docxTargetDir, dto);
|
|
|
+ }
|
|
|
+
|
|
|
+ private static void writeImage(File docxTargetDir, ExportTempDataDto dto) throws IOException {
|
|
|
+ for (SectionElement se : dto.getImages()) {
|
|
|
+ File file = new File(docxTargetDir.getAbsolutePath() + "/word/media/image" + se.getParams().getIndex() + "."
|
|
|
+ + se.getParams().getType());
|
|
|
+ String base64 = se.getValue();
|
|
|
+ if (base64.contains("data:image")) {
|
|
|
+ base64 = base64.substring(base64.indexOf(",") + 1);
|
|
|
+ }
|
|
|
+ BASE64Decoder decoder = new BASE64Decoder();
|
|
|
+ byte[] bytes = decoder.decodeBuffer(base64);
|
|
|
+ FileUtils.writeByteArrayToFile(file, bytes);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private static void writeDocumentRel(File docxTargetDir, ExportTempDataDto dto) throws IOException {
|
|
|
+ Map<String, Object> map = new HashMap<String, Object>();
|
|
|
+ map.put("images", dto.getImages());
|
|
|
+ StringWriter result = null;
|
|
|
+ try {
|
|
|
+ result = new StringWriter();
|
|
|
+ documentRel.process(map, result);
|
|
|
+ } catch (Exception e) {
|
|
|
+ throw new ExamCloudRuntimeException(e);
|
|
|
+ }
|
|
|
+ File file = new File(docxTargetDir.getAbsolutePath() + "/word/_rels/document.xml.rels");
|
|
|
+ FileUtils.writeStringToFile(file, result.toString(), "utf-8");
|
|
|
+ }
|
|
|
+
|
|
|
+ private static void writeContentType(File docxTargetDir, ExportTempDataDto dto) throws IOException {
|
|
|
+ Map<String, Object> map = new HashMap<String, Object>();
|
|
|
+ map.put("images", dto.getTypes());
|
|
|
+ StringWriter result = null;
|
|
|
+ try {
|
|
|
+ result = new StringWriter();
|
|
|
+ contentTypes.process(map, result);
|
|
|
+ } catch (Exception e) {
|
|
|
+ throw new ExamCloudRuntimeException(e);
|
|
|
+ }
|
|
|
+ File file = new File(docxTargetDir.getAbsolutePath() + "/[Content_Types].xml");
|
|
|
+ FileUtils.writeStringToFile(file, result.toString(), "utf-8");
|
|
|
+ }
|
|
|
+
|
|
|
+ private static void writeDocument(File docxTargetDir, PaperExp paperExp) throws IOException {
|
|
|
+ StringWriter result = null;
|
|
|
+ try {
|
|
|
+ result = new StringWriter();
|
|
|
+ document.process(paperExp, result);
|
|
|
+ } catch (Exception e) {
|
|
|
+ throw new ExamCloudRuntimeException(e);
|
|
|
+ }
|
|
|
+ File file = new File(docxTargetDir.getAbsolutePath() + "/word/document.xml");
|
|
|
+ FileUtils.writeStringToFile(file, result.toString(), "utf-8");
|
|
|
+ }
|
|
|
+
|
|
|
+ private static void disposeQuestion(Question qes, ExportTempDataDto dto) {
|
|
|
+ if (qes != null) {
|
|
|
+ List<JSection> slist1 = getSections(qes.getQuesBody(),
|
|
|
+ QuesStructType.FILL_BLANK_QUESTION.equals(qes.getQuestionType()));
|
|
|
+ if (slist1 != null && slist1.size() > 0) {
|
|
|
+ if (qes.getSubQuestions() == null || qes.getSubQuestions().size() == 0) {// 套题题干不加题号
|
|
|
+ dto.setSubNum(dto.getSubNum() + 1);
|
|
|
+ SectionElement se = new SectionElement();
|
|
|
+ se.setType(ELEMENT_TYPE_TEXT);
|
|
|
+ se.setValue(dto.getSubNum() + ".");
|
|
|
+ slist1.get(0).getElements().add(0, se);
|
|
|
+ }
|
|
|
+
|
|
|
+ htmlToDoc(slist1, dto);
|
|
|
+ qes.setQuesBodyWord(getQuestionDoc(slist1));
|
|
|
+ }
|
|
|
+
|
|
|
+ if (qes.getQuesOptions() != null && qes.getQuesOptions().size() > 0) {
|
|
|
+ int index = 0;
|
|
|
+ for (QuesOption qo : qes.getQuesOptions()) {
|
|
|
+ List<JSection> slist2 = getSections(qo.getOptionBody());
|
|
|
+ if (slist2 != null && slist2.size() > 0) {
|
|
|
+ SectionElement se = new SectionElement();
|
|
|
+ se.setType(ELEMENT_TYPE_TEXT);
|
|
|
+ se.setValue(QUESOPS.charAt(index) + ".");
|
|
|
+ index++;
|
|
|
+ slist2.get(0).getElements().add(0, se);
|
|
|
+ htmlToDoc(slist2, dto);
|
|
|
+ qo.setOptionBodyWord(getQuestionDoc(slist2));
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+ }
|
|
|
+ List<JSection> slist3 = getSections(qes.getQuesAnswer());
|
|
|
+ if (slist3 != null && slist3.size() > 0) {
|
|
|
+ SectionElement se = new SectionElement();
|
|
|
+ se.setType(ELEMENT_TYPE_TEXT);
|
|
|
+ se.setValue("[答案]:");
|
|
|
+ slist3.get(0).getElements().add(0, se);
|
|
|
+
|
|
|
+ htmlToDoc(slist3, dto);
|
|
|
+ qes.setQuesAnswerWord(getQuestionDoc(slist3));
|
|
|
+ }
|
|
|
+
|
|
|
+ if (qes.getSubQuestions() != null && qes.getSubQuestions().size() > 0) {
|
|
|
+ dto.setSubNum(0);
|
|
|
+ for (Question sunqes : qes.getSubQuestions()) {
|
|
|
+ disposeQuestion(sunqes, dto);// 递归处理套题
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private static void disposePaperExamRemark(PaperExp paperExp, ExportTempDataDto dto) {
|
|
|
+ if (StringUtils.isNotBlank(paperExp.getExamRemark())) {
|
|
|
+ List<JSection> slist = getSections(paperExp.getExamRemark());
|
|
|
+ if (slist != null && slist.size() > 0) {
|
|
|
+ htmlToDoc(slist, dto);
|
|
|
+ paperExp.setExamRemarkWord(getSectionDoc(slist));
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if(paperExp.getExamRemarkWord()==null) {
|
|
|
+ paperExp.setExamRemarkWord("");
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private static void disposePaperQuestion(Question qes, ExportTempDataDto dto) {
|
|
|
+ if (qes != null) {
|
|
|
+ if (qes.getSubQuestions() == null || qes.getSubQuestions().size() == 0) {// 套题题干不加题号
|
|
|
+ dto.setSubNum(dto.getSubNum() + 1);
|
|
|
+ }
|
|
|
+ List<JSection> slist1 = getSections(qes.getQuesBody(),true);
|
|
|
+ if (slist1 != null && slist1.size() > 0) {
|
|
|
+ if (qes.getSubQuestions() == null || qes.getSubQuestions().size() == 0) {// 套题题干不加题号
|
|
|
+ SectionElement se = new SectionElement();
|
|
|
+ se.setType(ELEMENT_TYPE_TEXT);
|
|
|
+ se.setValue(dto.getSubNum() + ".");
|
|
|
+ slist1.get(0).getElements().add(0, se);
|
|
|
+ }
|
|
|
+
|
|
|
+ htmlToDoc(slist1, dto);
|
|
|
+ qes.setQuesBodyWord(getQuestionDoc(slist1));
|
|
|
+ }
|
|
|
+
|
|
|
+ if (qes.getQuesOptions() != null && qes.getQuesOptions().size() > 0) {
|
|
|
+ int index = 0;
|
|
|
+ JOptionDto joDto = new JOptionDto();
|
|
|
+ List<JOption> ops = new ArrayList<JOption>();
|
|
|
+ joDto.setOptions(ops);
|
|
|
+ for (QuesOption qo : qes.getQuesOptions()) {
|
|
|
+ List<JSection> slist2 = getSections(qo.getOptionBody());
|
|
|
+ if (slist2 != null && slist2.size() > 0) {
|
|
|
+ SectionElement se = new SectionElement();
|
|
|
+ se.setType(ELEMENT_TYPE_TEXT);
|
|
|
+ se.setValue(QUESOPS.charAt(index) + ".");
|
|
|
+ index++;
|
|
|
+ slist2.get(0).getElements().add(0, se);
|
|
|
+ htmlToDoc(slist2, dto);
|
|
|
+ JOption jo = new JOption();
|
|
|
+ jo.setJsections(slist2);
|
|
|
+ ops.add(jo);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ disposeQuesOptions(joDto);// 处理选项列数
|
|
|
+ qes.setQuesOptionsWord(getPaperQuestionDoc(joDto.getOptions()));
|
|
|
+ }
|
|
|
+ if (qes.getSubQuestions() == null || qes.getSubQuestions().size() == 0) {// 套题不加答案序号
|
|
|
+ dto.setAnswerNum(dto.getAnswerNum() + 1);
|
|
|
+ }
|
|
|
+ List<JSection> slist3 = getSections(qes.getQuesAnswer());
|
|
|
+ if (slist3 != null && slist3.size() > 0) {
|
|
|
+ SectionElement se = new SectionElement();
|
|
|
+ se.setType(ELEMENT_TYPE_TEXT);
|
|
|
+ se.setValue(dto.getAnswerNum() + ".");
|
|
|
+ slist3.get(0).getElements().add(0, se);
|
|
|
+
|
|
|
+ htmlToDoc(slist3, dto);
|
|
|
+ qes.setQuesAnswerWord(getQuestionDoc(slist3));
|
|
|
+ }
|
|
|
+
|
|
|
+ if (qes.getSubQuestions() != null && qes.getSubQuestions().size() > 0) {
|
|
|
+ dto.setSubNum(0);
|
|
|
+ dto.setAnswerNum(0);
|
|
|
+ for (Question sunqes : qes.getSubQuestions()) {
|
|
|
+ disposePaperQuestion(sunqes, dto);// 递归处理套题
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private static void disposeQuesOptions(JOptionDto joDto) {
|
|
|
+ for (JOption jo : joDto.getOptions()) {
|
|
|
+ if (jo.getJsections().size() > 1) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ for (JSection js : jo.getJsections()) {
|
|
|
+ for (SectionElement se : js.getElements()) {
|
|
|
+ if (ELEMENT_TYPE_IMG.equals(se.getType())) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ int columns = 4;
|
|
|
+ for (JOption jo : joDto.getOptions()) {
|
|
|
+ JSection js = jo.getJsections().get(0);
|
|
|
+ for (SectionElement se : js.getElements()) {
|
|
|
+ String text = StringEscapeUtils.unescapeXml(se.getValue());
|
|
|
+ if (text.length() > 20) {
|
|
|
+ return;
|
|
|
+ } else if (text.length() > 9) {
|
|
|
+ columns = 2;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+ formatList(joDto, columns);
|
|
|
+ }
|
|
|
+
|
|
|
+ private static void formatList(JOptionDto joDto, int size) {
|
|
|
+ List<JOption> ret = new ArrayList<JOption>();
|
|
|
+ int count = 0;
|
|
|
+ for (int i = 0; i < joDto.getOptions().size(); i++) {
|
|
|
+ if (count == 0) {
|
|
|
+ JOption jo = new JOption();
|
|
|
+ jo.setCols(size);
|
|
|
+ List<JSection> temlist = new ArrayList<JSection>();
|
|
|
+ jo.setJsections(temlist);
|
|
|
+ JSection js = new JSection();
|
|
|
+ List<SectionElement> ses = new ArrayList<SectionElement>();
|
|
|
+ js.setElements(ses);
|
|
|
+ temlist.add(js);
|
|
|
+ ret.add(jo);
|
|
|
+ }
|
|
|
+ if (count != 0) {
|
|
|
+ joDto.getOptions().get(i).getJsections().get(0).getElements().get(0).getParams().setTab(true);
|
|
|
+ }
|
|
|
+ for (SectionElement se : joDto.getOptions().get(i).getJsections().get(0).getElements()) {
|
|
|
+ ret.get(ret.size() - 1).getJsections().get(0).getElements().add(se);
|
|
|
+ }
|
|
|
+ count++;
|
|
|
+ if (count == size) {
|
|
|
+ count = 0;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ joDto.setOptions(ret);
|
|
|
+ }
|
|
|
+
|
|
|
+ private static void htmlToDoc(List<JSection> slist, ExportTempDataDto dto) {
|
|
|
+ for (JSection js : slist) {
|
|
|
+ for (SectionElement se : js.getElements()) {
|
|
|
+ if (ELEMENT_TYPE_IMG.equals(se.getType())) {
|
|
|
+ dto.setIndex(dto.getIndex() + 1);
|
|
|
+ se.getParams().setIndex(dto.getIndex());
|
|
|
+ se.getParams().setRid(ELEMENT_TYPE_RID + dto.getIndex());
|
|
|
+ se.getParams().setType(getImageType(se.getValue()));
|
|
|
+ dto.getTypes().add(se.getParams().getType());
|
|
|
+ dto.getImages().add(se);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private static String getImageType(String base64) {
|
|
|
+ return base64.substring(11, base64.indexOf(";"));
|
|
|
+ }
|
|
|
+ private static String getSectionDoc(List<JSection> sections) {
|
|
|
+ Map<String, Object> map = new HashMap<String, Object>();
|
|
|
+ map.put("sections", sections);
|
|
|
+ StringWriter result = null;
|
|
|
+ try {
|
|
|
+ result = new StringWriter();
|
|
|
+ docSection.process(map, result);
|
|
|
+ return result.toString();
|
|
|
+ } catch (Exception e) {
|
|
|
+ throw new ExamCloudRuntimeException(e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private static String getQuestionDoc(List<JSection> sections) {
|
|
|
+ Map<String, Object> map = new HashMap<String, Object>();
|
|
|
+ map.put("sections", sections);
|
|
|
+ StringWriter result = null;
|
|
|
+ try {
|
|
|
+ result = new StringWriter();
|
|
|
+ questionSection.process(map, result);
|
|
|
+ return result.toString();
|
|
|
+ } catch (Exception e) {
|
|
|
+ throw new ExamCloudRuntimeException(e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private static String getPaperQuestionDoc(List<JOption> options) {
|
|
|
+ Map<String, Object> map = new HashMap<String, Object>();
|
|
|
+ map.put("options", options);
|
|
|
+ StringWriter result = null;
|
|
|
+ try {
|
|
|
+ result = new StringWriter();
|
|
|
+ paperQuesOps.process(map, result);
|
|
|
+ return result.toString();
|
|
|
+ } catch (Exception e) {
|
|
|
+ throw new ExamCloudRuntimeException(e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+}
|