浏览代码

代码优化及bug修复

lideyin 5 年之前
父节点
当前提交
f4d024f8d4

+ 6 - 0
src/main/java/cn/com/qmth/examcloud/support/enums/BlockType.java

@@ -0,0 +1,6 @@
+package cn.com.qmth.examcloud.support.enums;
+
+public enum BlockType {
+
+    text, image, audio;
+}

+ 7 - 6
src/main/java/cn/com/qmth/examcloud/support/enums/ExamProperties.java

@@ -1,7 +1,7 @@
 package cn.com.qmth.examcloud.support.enums;
 
 /**
- * 
+ *
  * @author  	chenken
  * @date    	2018年11月15日 下午5:37:35
  * @company 	QMTH
@@ -49,12 +49,13 @@ public enum ExamProperties {
 	MAX_INTERRUPT_NUM("最大断点续考次数"),
 	IS_STRANGER_ENABLE("是否启用陌生人检测"),
 	LIMITED_IF_NO_SPECIAL_SETTINGS("无特殊设置时禁止考试"),
-	WEIXIN_ANSWER_ENABLED("是否开放微信小程序作答");
-	
+	WEIXIN_ANSWER_ENABLED("是否开放微信小程序作答"),
+	APP_EXAM_ENABLED("是否开放app考试");
+
 	private ExamProperties(String desc){
 		this.desc = desc;
 	}
-	
+
 	private String desc;
 
 	public String getDesc() {
@@ -64,5 +65,5 @@ public enum ExamProperties {
 	public void setDesc(String desc) {
 		this.desc = desc;
 	}
-	
-}
+
+}

+ 2 - 2
src/main/java/cn/com/qmth/examcloud/support/handler/richText/AudioTextHandler.java

@@ -1,5 +1,6 @@
 package cn.com.qmth.examcloud.support.handler.richText;
 
+import cn.com.qmth.examcloud.support.enums.BlockType;
 import cn.com.qmth.examcloud.support.handler.richText.bean.BlockBean;
 import cn.com.qmth.examcloud.support.handler.richText.bean.SectionBean;
 import cn.com.qmth.examcloud.support.handler.richText.bean.SectionCollectionBean;
@@ -35,8 +36,7 @@ public class AudioTextHandler implements RichTextHandler{
         List<BlockBean> blockList = new ArrayList<>();
 
         if (validateAudioAnswer(richText)) {
-            BlockBean blockBean = new BlockBean();
-            blockBean.setType("audio");
+            BlockBean blockBean = new BlockBean(BlockType.audio.name());
             blockBean.setValue(richText);
             blockList.add(blockBean);
         }

+ 4 - 7
src/main/java/cn/com/qmth/examcloud/support/handler/richText/ComplexTextHandler.java

@@ -1,9 +1,11 @@
 package cn.com.qmth.examcloud.support.handler.richText;
 
+import cn.com.qmth.examcloud.support.enums.BlockType;
 import cn.com.qmth.examcloud.support.handler.richText.bean.BlockBean;
 import cn.com.qmth.examcloud.support.handler.richText.bean.SectionBean;
 import cn.com.qmth.examcloud.support.handler.richText.bean.SectionCollectionBean;
 import com.mysql.cj.util.StringUtils;
+import org.apache.commons.lang.StringEscapeUtils;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 
@@ -62,7 +64,7 @@ public class ComplexTextHandler implements RichTextHandler {
                 .replaceAll("</span>", "").replaceAll("</a>", "");
         String[] questionRowStrings = questionRow.split("<|/>|>");
         for (int i = 0; i < questionRowStrings.length; i++) {
-            BlockBean block = new BlockBean();
+            BlockBean block = new BlockBean(BlockType.text.name());
             String rowStr = questionRowStrings[i];
             // 判断是否有图片
             if (rowStr.startsWith("img")) {
@@ -98,13 +100,8 @@ public class ComplexTextHandler implements RichTextHandler {
                 blocks.add(block);
             } else {
                 block.setType("text");
-                rowStr = rowStr.replace("&nbsp;", "");// 消除空格
-                rowStr = rowStr.replace("&quot;", "\"");// 将&quot;转换成\"
-                rowStr = rowStr.replace("&lt;", "<");// 将&lt;转换成<
-                rowStr = rowStr.replace("&gt;", ">");// 将&gt;转换成>
-                rowStr = rowStr.replace("&amp;", "&");// 将&amp;转换成&
                 if (org.apache.commons.lang3.StringUtils.isNotBlank(rowStr)) {
-                    block.setValue(rowStr);
+                    block.setValue(StringEscapeUtils.unescapeHtml(rowStr));
                     blocks.add(block);
                 }
             }

+ 7 - 5
src/main/java/cn/com/qmth/examcloud/support/handler/richText/HtmlTextHandler.java

@@ -1,7 +1,7 @@
 package cn.com.qmth.examcloud.support.handler.richText;
 
-import cn.com.qmth.examcloud.commons.util.JsonUtil;
 import cn.com.qmth.examcloud.commons.util.RegExpUtil;
+import cn.com.qmth.examcloud.support.enums.BlockType;
 import cn.com.qmth.examcloud.support.handler.richText.bean.BlockBean;
 import cn.com.qmth.examcloud.support.handler.richText.bean.SectionBean;
 import cn.com.qmth.examcloud.support.handler.richText.bean.SectionCollectionBean;
@@ -144,8 +144,7 @@ public class HtmlTextHandler implements RichTextHandler {
 
     //构建普通的文本作答
     private static BlockBean buildNormalTextAnswer(String value) {
-        BlockBean obb = new BlockBean();
-        obb.setType("text");
+        BlockBean obb = new BlockBean(BlockType.text.name());
         obb.setValue(StringEscapeUtils.unescapeHtml(value));
 
         return obb;
@@ -153,7 +152,7 @@ public class HtmlTextHandler implements RichTextHandler {
 
     //构建带特殊标签的文本作答
     private static BlockBean buildSpecialTextAnswer(String value, String tag) {
-        BlockBean obb = new BlockBean();
+        BlockBean obb = new BlockBean(BlockType.text.name());
         obb.setType("text");
         obb.setValue(StringEscapeUtils.unescapeHtml(value));
 
@@ -179,12 +178,15 @@ public class HtmlTextHandler implements RichTextHandler {
     }
 
 //    public static void main(String[] args) {
-//        String testStr = "1111111<div>222&lt;div&gt;&lt;/div&gt;21000<sup>2</sup></div><div>3333399<sub>3</sub>5555555</div><div><br></div><div>444444</div>";
+////        String testStr = "1111111<div>222&lt;div&gt;&lt;/div&gt;21000<sup>2</sup></div><div>3333399<sub>3</sub>5555555</div><div><br></div><div>444444</div>";
+////        String testStr="{\"mainNumber\":2,\"order\":23,\"questionId\":\"5ebdf1cbcad4db1aee85e907\",\"studentAnswer\":\"发发呆<div>ななぅぅぉてふっふてふ</div><div class='photo-answers-block'><a href='https://ecs-test-static.qmth.com.cn/oe-answer-file/21083/19288/23/21083_19288_23_15895106360336244.jpeg' target='_blank' ><img class='photo-answer' src='https://ecs-test-static.qmth.com.cn/oe-answer-file/21083/19288/23/21083_19288_23_15895106360336244.jpeg?x-oss-process=image/resize,m_lfit,h_200,w_200' /></a></div>\",\"answerType\":null,\"answer\":\"<p><span> えいが</span></p>\",\"body\":\"<p>映画</p>\",\"parentBody\":null,\"questionType\":\"ESSAY\"}";
+//            String testStr="{\"mainNumber\":5,\"order\":19,\"questionId\":\"5e942585cad4db278def3df5\",\"studentAnswer\":\"范德萨范德萨飞<sup>电风扇的</sup><div>范德萨范德萨</div><div>范德萨范德萨范<sub>德萨发的</sub></div><div class='photo-answers-block'><a href='https://ecs-test-static.qmth.com.cn/oe-answer-file/20820/19336/19/20820_19336_19_15899464519267961.jpeg' target='_blank' ><img class='photo-answer' src='https://ecs-test-static.qmth.com.cn/oe-answer-file/20820/19336/19/20820_19336_19_15899464519267961.jpeg?x-oss-process=image/resize,m_lfit,h_200,w_200' /></a><a href='https://ecs-test-static.qmth.com.cn/oe-answer-file/20820/19336/19/20820_19336_19_15899464518985666.jpeg' target='_blank' ><img class='photo-answer' src='https://ecs-test-static.qmth.com.cn/oe-answer-file/20820/19336/19/20820_19336_19_15899464518985666.jpeg?x-oss-process=image/resize,m_lfit,h_200,w_200' /></a><a href='https://ecs-test-static.qmth.com.cn/oe-answer-file/20820/19336/19/20820_19336_19_15899464519221951.jpeg' target='_blank' ><img class='photo-answer' src='https://ecs-test-static.qmth.com.cn/oe-answer-file/20820/19336/19/20820_19336_19_15899464519221951.jpeg?x-oss-process=image/resize,m_lfit,h_200,w_200' /></a></div>\",\"answerType\":\"DIVERSIFIED_TEXT\",\"answer\":\"<p>1).杆件变形的基本形式有轴向拉伸和压缩,剪切,扭转和弯曲。</p>\\n\\n<p>2).强度&mdash;&mdash;构建抵抗破坏的能力。刚度&mdash;&mdash;构件抵抗变形的能力。</p>\\n\\n<p>3).稳定性&mdash;&mdash;构件保持原型状的能力。</p>\",\"body\":\"<p>杆件变形的<em><strong><u>基本形式</u></strong></em>有哪几种?何谓构件的强度,刚度和稳定性?</p><p><a id=\\\"5eba5fadcad4db05908c8d13\\\" name=\\\"19_1_2.mp3\\\" question-audio url=\\\"https://ecs-test-static.qmth.com.cn/comm-ques-bank/prod/audio/5e942585cad4db278def3df5_514_19_1_2.mp3\\\"></a></p>\",\"parentBody\":null,\"questionType\":\"ESSAY\"}";
 //
 //        HtmlTextHandler o = new HtmlTextHandler();
 //
 //
 //        SectionCollectionBean sfds = o.handle(testStr);
+//
 //        System.out.println(JsonUtil.toJson(sfds));
 //    }
 

+ 33 - 21
src/main/java/cn/com/qmth/examcloud/support/handler/richText/ImageTextHandler.java

@@ -1,10 +1,13 @@
 package cn.com.qmth.examcloud.support.handler.richText;
 
+import cn.com.qmth.examcloud.commons.util.JsonUtil;
 import cn.com.qmth.examcloud.commons.util.RegExpUtil;
+import cn.com.qmth.examcloud.support.enums.BlockType;
 import cn.com.qmth.examcloud.support.handler.richText.bean.BlockBean;
 import cn.com.qmth.examcloud.support.handler.richText.bean.SectionBean;
 import cn.com.qmth.examcloud.support.handler.richText.bean.SectionCollectionBean;
 import com.mysql.cj.util.StringUtils;
+import org.apache.commons.lang.StringEscapeUtils;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.jsoup.Jsoup;
@@ -45,34 +48,31 @@ public class ImageTextHandler implements RichTextHandler {
         //图片文本部分
         String txtStr = getImgTxt(richText);
         if (!StringUtils.isNullOrEmpty(txtStr)) {
-            BlockBean blockBean = new BlockBean();
-            blockBean.setType("text");
-            blockBean.setValue(txtStr);
+            BlockBean blockBean = new BlockBean(BlockType.text.name());
+            blockBean.setValue(StringEscapeUtils.unescapeHtml(txtStr));
             blockList.add(blockBean);
         }
 
         //图片部分
         if (validateImgAnswer(richText)) {
             String imgSrc = getImgSrc(richText);
-            if (imgSrc.indexOf("|") > -1) {
-                String[] imgAnswers = imgSrc.split("\\|");
-
-                for (int i = 0; i < imgAnswers.length; i++) {
-                    BlockBean blockBean = new BlockBean();
-                    blockBean.setType("text");
-                    blockBean.setValue(getPureUrl(imgAnswers[i]));
-
-                    //又拍云图片的宽*高
-                    String imgWH = RegExpUtil.find(imgAnswers[i], "(\\d+)x(\\d+)");
-                    if (!StringUtils.isNullOrEmpty(imgWH)) {
-                        Map<String, Object> paramMap = new HashMap<>();
-                        paramMap.put("width", Integer.valueOf(imgWH.split("x")[0]));
-                        paramMap.put("height", Integer.valueOf(imgWH.split("x")[1]));
-                        blockBean.setParam(paramMap);
-                    }
-
-                    blockList.add(blockBean);
+            String[] imgAnswers = imgSrc.split("\\|");
+
+            for (int i = 0; i < imgAnswers.length; i++) {
+                BlockBean blockBean = new BlockBean(BlockType.image.name());
+                blockBean.setValue(getPureUrl(imgAnswers[i]));
+
+                //又拍云图片的宽*高
+                String width=RegExpUtil.find(imgAnswers[i], "w_(\\d+)");
+                String height=RegExpUtil.find(imgAnswers[i], "h_(\\d+)");
+                Map<String, Object> paramMap = new HashMap<>();
+                if (!StringUtils.isNullOrEmpty(width) && !StringUtils.isNullOrEmpty(height)) {
+                    paramMap.put("width", Integer.valueOf(width.replaceAll("w_","")));
+                    paramMap.put("height", Integer.valueOf(height.replaceAll("h_","")));
+                    blockBean.setParam(paramMap);
                 }
+
+                blockList.add(blockBean);
             }
         }
 
@@ -157,4 +157,16 @@ public class ImageTextHandler implements RichTextHandler {
         String regExp = "(ftp|https?)\\:\\/\\/([\\w\\_\\-]+)\\.([\\w\\-]+[\\.]?)*[\\w]+\\.[a-zA-Z]{2,10}(.*)\\.(png|jpg|gif|jpeg)";
         return RegExpUtil.find(imgUrl, regExp);
     }
+
+//    public static void main(String[] args) {
+////        String testStr = "1111111<div>222&lt;div&gt;&lt;/div&gt;21000<sup>2</sup></div><div>3333399<sub>3</sub>5555555</div><div><br></div><div>444444</div>";
+//        String testStr = "{\"mainNumber\":2,\"order\":23,\"questionId\":\"5ebdf1cbcad4db1aee85e907\",\"studentAnswer\":\"发发呆<div>ななぅぅぉてふっふてふ</div><div class='photo-answers-block'><a href='https://ecs-test-static.qmth.com.cn/oe-answer-file/21083/19288/23/21083_19288_23_15895106360336244.jpeg' target='_blank' ><img class='photo-answer' src='https://ecs-test-static.qmth.com.cn/oe-answer-file/21083/19288/23/21083_19288_23_15895106360336244.jpeg?x-oss-process=image/resize,m_lfit,h_200,w_200' /></a></div>\",\"answerType\":null,\"answer\":\"<p><span> えいが</span></p>\",\"body\":\"<p>映画</p>\",\"parentBody\":null,\"questionType\":\"ESSAY\"}";
+//
+//        ImageTextHandler o = new ImageTextHandler();
+//
+//
+//        SectionCollectionBean sfds = o.handle(testStr);
+//
+//        System.out.println(JsonUtil.toJson(sfds));
+//    }
 }

+ 7 - 0
src/main/java/cn/com/qmth/examcloud/support/handler/richText/bean/BlockBean.java

@@ -1,5 +1,6 @@
 package cn.com.qmth.examcloud.support.handler.richText.bean;
 
+import java.util.HashMap;
 import java.util.Map;
 
 /**
@@ -9,6 +10,12 @@ import java.util.Map;
  * @Version 1.0
  */
 public class BlockBean {
+    public BlockBean(String type) {
+        this.type = type;
+        this.param = new HashMap<>();
+        this.value = "";
+    }
+
     /**
      * text:文字
      * image:图片

+ 6 - 0
src/main/java/cn/com/qmth/examcloud/support/handler/richText/bean/SectionBean.java

@@ -1,5 +1,6 @@
 package cn.com.qmth.examcloud.support.handler.richText.bean;
 
+import java.util.ArrayList;
 import java.util.List;
 
 /**
@@ -10,6 +11,10 @@ import java.util.List;
  */
 public class SectionBean {
 
+    public SectionBean() {
+        this.blocks=new ArrayList<>();
+    }
+
     private List<BlockBean> blocks;
 
     public List<BlockBean> getBlocks() {
@@ -21,5 +26,6 @@ public class SectionBean {
     }
 
 
+
 }
 

+ 49 - 0
src/test/java/cn/com/qmth/examcloud/support/test/Block.java

@@ -0,0 +1,49 @@
+package cn.com.qmth.examcloud.support.test;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class Block {
+
+    private String type;
+
+    private String value;
+
+    /**
+     * 播放次数
+     */
+    private Integer playTime;
+
+    public Integer getPlayTime() {
+        return playTime;
+    }
+
+    public void setPlayTime(Integer playTime) {
+        this.playTime = playTime;
+    }
+
+    private Map<String, Object> param;
+
+    public Block(BlockType type) {
+        this.type = type.name().toLowerCase();
+        this.param = new HashMap<>();
+        this.value = "";
+    }
+
+    public String getType() {
+        return type;
+    }
+
+    public String getValue() {
+        return value;
+    }
+
+    public void setValue(String value) {
+        this.value = value;
+    }
+
+    public Map<String, Object> getParam() {
+        return param;
+    }
+
+}

+ 6 - 0
src/test/java/cn/com/qmth/examcloud/support/test/BlockType.java

@@ -0,0 +1,6 @@
+package cn.com.qmth.examcloud.support.test;
+
+public enum BlockType {
+
+    TEXT, IMAGE, AUDIO;
+}

+ 162 - 0
src/test/java/cn/com/qmth/examcloud/support/test/Context.java

@@ -0,0 +1,162 @@
+package cn.com.qmth.examcloud.support.test;
+
+import org.apache.commons.lang.StringEscapeUtils;
+import org.apache.commons.lang.StringUtils;
+import org.jsoup.Jsoup;
+import org.jsoup.nodes.Element;
+import org.jsoup.nodes.Node;
+import org.jsoup.nodes.TextNode;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class Context {
+
+    private static final Map<String, String> TEXT_PARAM_MAP = new HashMap<>();
+
+    static {
+        TEXT_PARAM_MAP.put("b", "bold");
+        TEXT_PARAM_MAP.put("i", "italic");
+        TEXT_PARAM_MAP.put("strong", "bold");
+        TEXT_PARAM_MAP.put("em", "italic");
+        TEXT_PARAM_MAP.put("u", "underline");
+        TEXT_PARAM_MAP.put("sup", "sup");
+        TEXT_PARAM_MAP.put("sub", "sub");
+    }
+
+    private List<Section> sections;
+
+    private Section currentSection;
+
+    private Map<String, Object> currentTextParam;
+
+    public Context() {
+        this.sections = new ArrayList<>();
+        this.currentTextParam = new HashMap<>();
+    }
+
+    public List<Section> process(String input) {
+        Element body = Jsoup.parseBodyFragment(StringUtils.trimToEmpty(input)).body();
+        switchSection();
+        for (Node child : body.childNodes()) {
+            parseNode(child);
+        }
+        return sections;
+    }
+
+    private void parseNode(Node node) {
+        if (node instanceof TextNode) {
+            TextNode textNode = (TextNode) node;
+            parseText(textNode.text());
+        } else if (node instanceof Element) {
+            Element element = (Element) node;
+            onElementStart(element);
+            for (Node child : element.childNodes()) {
+                parseNode(child);
+            }
+            onElementEnd(element);
+        }
+    }
+
+    private void parseText(String text) {
+        Block block = new Block(BlockType.TEXT);
+        block.setValue(StringEscapeUtils.unescapeHtml(text));
+        block.getParam().putAll(currentTextParam);
+        addBlock(block);
+    }
+
+    private void parseImage(Element element) {
+        Block block = new Block(BlockType.IMAGE);
+
+        String src = element.attr("src");
+        block.setValue(src);
+
+        Map<String, Object> param = new HashMap<>();
+        String height = element.attr("height");
+        String width = element.attr("width");
+        param.put("width", height);
+        param.put("height", width);
+        block.getParam().putAll(param);
+
+        addBlock(block);
+    }
+
+    private void parseAudio(Element element) {
+        //todo 此处为题库特殊处理,待确认
+        String id = element.attr("id");
+        String name = element.attr("name");
+        if (StringUtils.isNotEmpty(id) && StringUtils.isNotEmpty(name)) {
+            Block block = new Block(BlockType.AUDIO);
+            block.setPlayTime(1);
+            block.setValue(element.attr("url"));
+            addBlock(block);
+        }
+    }
+
+    private void onElementStart(Element element) {
+        String name = element.nodeName().toLowerCase();
+        switch (name) {
+            case "div":
+            case "p":
+                switchSection();
+                break;
+            case "br":
+                finishSection();
+                break;
+            case "img":
+                parseImage(element);
+                break;
+            case "audio":// TODO
+            case "a":// TODO
+                parseAudio(element);
+                break;
+            default:
+                String style = TEXT_PARAM_MAP.get(name);
+                if (style != null) {
+                    currentTextParam.put(style, true);
+                }
+        }
+    }
+
+    private void onElementEnd(Element element) {
+        String name = element.nodeName().toLowerCase();
+        switch (name) {
+            case "div":
+            case "p":
+            case "span":
+                finishSection();
+                break;
+            case "img":// TODO
+            case "audio":// TODO
+            case "a":// TODO
+//                finishSection();
+                break;
+            default:
+                String style = TEXT_PARAM_MAP.get(name);
+                if (style != null) {
+                    currentTextParam.remove(style);
+                }
+        }
+    }
+
+    private void addBlock(Block block) {
+        if (currentSection == null) {
+            switchSection();
+        }
+        currentSection.addBlock(block);
+    }
+
+    private void finishSection() {
+        currentSection = null;
+    }
+
+    private void switchSection() {
+        Section section = new Section();
+        sections.add(section);
+        currentSection = section;
+        currentTextParam.clear();
+    }
+
+}

+ 21 - 0
src/test/java/cn/com/qmth/examcloud/support/test/Section.java

@@ -0,0 +1,21 @@
+package cn.com.qmth.examcloud.support.test;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class Section {
+
+    private List<Block> blocks;
+
+    public Section() {
+        this.blocks = new ArrayList<>();
+    }
+
+    public void addBlock(Block block) {
+        this.blocks.add(block);
+    }
+
+    public List<Block> getBlocks() {
+        return blocks;
+    }
+}

+ 19 - 0
src/test/java/cn/com/qmth/examcloud/support/test/Test.java

@@ -0,0 +1,19 @@
+package cn.com.qmth.examcloud.support.test;
+
+import net.sf.json.JSONArray;
+import org.apache.commons.lang.StringUtils;
+
+public class Test {
+
+    public static void main(String[] args) {
+        String input = "<br>普通文本<br><div>这个被div包裹着</div><p>这个被p包裹 着</p><div><b>加粗<i>加粗且斜体<u>加粗且斜体且有下划线</u><b>加粗且斜体且有重复加粗标签</b></i>100<sup>2</sup></b></div>普通文本log<sub>3</sub>";
+//        String t2="<p><strong><em>杆件变形</em></strong><a id='a' name='1' url='http://1.mp3'></a>的基本形式有哪几种?<img src='http://www.baidu.com'/>何谓构件的强度,刚度和稳定性?</p>";
+//        String t2="<p><strong><em>杆件变形</em></strong>的基本形式有哪几种?何谓构件的强度,刚度和稳定性?</p>";
+        Context context = new Context();
+
+        System.out.println(JSONArray.fromObject(context.process(input)));
+
+//        System.out.println(JSONArray.fromObject(context.process(t2)));
+    }
+
+}