Răsfoiți Sursa

云阅卷接口部分代码重构

lideyin 5 ani în urmă
părinte
comite
54be9e4516

+ 37 - 326
examcloud-exchange-outer-api-provider/src/main/java/cn/com/qmth/examcloud/exchange/outer/api/provider/ExamQuestionOuterServiceProvider.java

@@ -1,7 +1,6 @@
 package cn.com.qmth.examcloud.exchange.outer.api.provider;
 
 import cn.com.qmth.examcloud.commons.exception.StatusException;
-import cn.com.qmth.examcloud.commons.util.RegExpUtil;
 import cn.com.qmth.examcloud.core.oe.admin.api.ExamRecordCloudService;
 import cn.com.qmth.examcloud.core.oe.admin.api.bean.PagedToBeMarkExamRecordBean;
 import cn.com.qmth.examcloud.core.oe.admin.api.bean.PagedToBeMarkSubjectiveAnswerBean;
@@ -22,6 +21,10 @@ import cn.com.qmth.examcloud.question.commons.core.question.AnswerType;
 import cn.com.qmth.examcloud.question.commons.core.question.QuestionType;
 import cn.com.qmth.examcloud.support.cache.CacheHelper;
 import cn.com.qmth.examcloud.support.cache.bean.QuestionAnswerCacheBean;
+import cn.com.qmth.examcloud.support.handler.richText.RichTextHandler;
+import cn.com.qmth.examcloud.support.handler.richText.RichTextHandlerFactory;
+import cn.com.qmth.examcloud.support.handler.richText.bean.SectionBean;
+import cn.com.qmth.examcloud.support.handler.richText.bean.SectionCollectionBean;
 import cn.com.qmth.examcloud.support.helper.ExamCacheTransferHelper;
 import cn.com.qmth.examcloud.web.support.ControllerSupport;
 import cn.com.qmth.examcloud.web.support.StatusResponse;
@@ -31,11 +34,6 @@ import io.swagger.annotations.ApiOperation;
 import io.swagger.annotations.ApiResponse;
 import io.swagger.annotations.ApiResponses;
 import org.apache.commons.collections.CollectionUtils;
-import org.jsoup.Jsoup;
-import org.jsoup.nodes.Document;
-import org.jsoup.nodes.Element;
-import org.jsoup.safety.Whitelist;
-import org.jsoup.select.Elements;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.PostMapping;
 import org.springframework.web.bind.annotation.RequestBody;
@@ -43,11 +41,7 @@ import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RestController;
 
 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;
 
 /**
  * @Description 考试作答服务
@@ -249,6 +243,7 @@ public class ExamQuestionOuterServiceProvider extends ControllerSupport implemen
     private List<OuterSubjectiveQuestionRecordBean> getSubjectives(Long examId,
                                                                    List<PagedToBeMarkSubjectiveAnswerBean> subjectiveAnswerList) {
         List<OuterSubjectiveQuestionRecordBean> resultList = new ArrayList<>();
+        RichTextHandler complexRichTextHandler = RichTextHandlerFactory.getHandler("complex");
 
         for (PagedToBeMarkSubjectiveAnswerBean pb : subjectiveAnswerList) {
             OuterSubjectiveQuestionRecordBean resultBean = new OuterSubjectiveQuestionRecordBean();
@@ -256,11 +251,16 @@ public class ExamQuestionOuterServiceProvider extends ControllerSupport implemen
             resultBean.setSubNumber(pb.getOrder());
             resultBean.setQuestionId(pb.getQuestionId());
 
-            resultBean.setAnswer(getFormattedAnswer(pb.getAnswer()));
-            resultBean.setStudentAnswer(
-                    getFormattedStudentAnswer(pb.getStudentAnswer(), pb.getAnswerType(), pb.getQuestionType(), examId));
-            resultBean.setBody(getFormattedBody(pb.getBody()));
-            resultBean.setParentBody(getFormattedParentBody(pb.getParentBody()));
+            resultBean.setAnswer(transferFrom(complexRichTextHandler.handle(pb.getAnswer())));
+
+            //格式化学生答案
+            String transformedAnswerType = getTransformedAnswerType(pb.getAnswerType(), pb.getQuestionType(), examId);
+            RichTextHandler richTextHandler = RichTextHandlerFactory.getHandler(transformedAnswerType);
+            SectionCollectionBean formattedStudentAnswer = richTextHandler.handle(pb.getStudentAnswer());
+            resultBean.setStudentAnswer(transferFrom(formattedStudentAnswer));
+
+            resultBean.setBody(transferFrom(complexRichTextHandler.handle(pb.getBody())));
+            resultBean.setParentBody(transferFrom(complexRichTextHandler.handle(pb.getParentBody())));
 
             resultList.add(resultBean);
         }
@@ -268,120 +268,37 @@ public class ExamQuestionOuterServiceProvider extends ControllerSupport implemen
         return resultList;
     }
 
-    /**
-     * 格式化父题干
-     *
-     * @param parentBody
-     * @return
-     */
-    private OuterSectionCollectionBean getFormattedParentBody(String parentBody) {
-        if (StringUtils.isNullOrEmpty(parentBody)) {
+    private OuterSectionCollectionBean transferFrom(SectionCollectionBean sectionCollection) {
+        List<SectionBean> sections = sectionCollection.getSections();
+        if (null == sections || sections.isEmpty()) {
             return null;
         }
 
-        return getBodyOrAnswer(parentBody);
-    }
+        OuterSectionCollectionBean result = new OuterSectionCollectionBean();
 
-    /**
-     * 格式化小题题干
-     *
-     * @param body
-     * @return
-     */
-    private OuterSectionCollectionBean getFormattedBody(String body) {
-        if (StringUtils.isNullOrEmpty(body)) {
-            return null;
-        }
+        List<OuterSectionBean> outerSections = new ArrayList<>();
+        sections.stream().forEach(sec -> {
+            OuterSectionBean outerSection = new OuterSectionBean();
+            List<OuterBlockBean> outerBlocks = new ArrayList<>();
 
-        return getBodyOrAnswer(body);
-    }
-
-    /**
-     * 格式化学生答案
-     *
-     * @param studentAnswer
-     * @return
-     */
-    private OuterSectionCollectionBean getFormattedStudentAnswer(String studentAnswer,
-                                                                 AnswerType answerType,
-                                                                 QuestionType questionType, Long examId) {
-        String transformedAnswerType = getTransformedAnswerType(answerType, questionType, examId);
-
-        List<OuterSectionBean> sectionBeanList = new ArrayList<>();
-        List<OuterBlockBean> blockBeanList = new ArrayList<>();
-
-
-        //图片文件特殊处理
-        if ("image".equals(transformedAnswerType)) {
-            //图片文本部分
-            String txtStr = getImgTxt(studentAnswer);
-            if (!StringUtils.isNullOrEmpty(txtStr)) {
-                OuterBlockBean blockBean = new OuterBlockBean();
-                blockBean.setType("text");
-                blockBean.setValue(txtStr);
-                blockBeanList.add(blockBean);
-            }
+            if (null != sec.getBlocks() && !sec.getBlocks().isEmpty()) {
+                sec.getBlocks().stream().forEach(bl -> {
+                    OuterBlockBean outerBlock = new OuterBlockBean();
+                    outerBlock.setType(bl.getType());
+                    outerBlock.setValue(bl.getValue());
+                    outerBlock.setParam(bl.getParam());
+                    outerBlock.setPlayTime(bl.getPlayTime());
 
-            //图片部分
-            if (validateImgAnswer(studentAnswer)) {
-                String imgSrc = getImgSrc(studentAnswer);
-                if (imgSrc.indexOf("|") > -1) {
-                    String[] imgAnswers = imgSrc.split("\\|");
-
-                    for (int i = 0; i < imgAnswers.length; i++) {
-                        OuterBlockBean blockBean = new OuterBlockBean();
-                        blockBean.setType(transformedAnswerType);
-                        blockBean.setValue(getSimpleTransformedAnswer(transformedAnswerType, 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);
-                        }
-
-                        blockBeanList.add(blockBean);
-                    }
-                }
-            }
-        } else if ("audio".equals(transformedAnswerType)) {
-            if (validateAudioAnswer(studentAnswer)) {
-                OuterBlockBean blockBean = new OuterBlockBean();
-                blockBean.setType(transformedAnswerType);
-                blockBean.setValue(getSimpleTransformedAnswer(transformedAnswerType, studentAnswer));
-                blockBeanList.add(blockBean);
+                    outerBlocks.add(outerBlock);
+                });
             }
 
-        } else {
-            OuterBlockBean blockBean = new OuterBlockBean();
-            blockBean.setType(transformedAnswerType);
-            blockBean.setValue(getSimpleTransformedAnswer(transformedAnswerType, studentAnswer));
-            blockBeanList.add(blockBean);
-        }
-
-        OuterSectionBean sectionBean = new OuterSectionBean();
-        sectionBean.setBlocks(blockBeanList);
-        sectionBeanList.add(sectionBean);
-
-        OuterSectionCollectionBean resultBean = new OuterSectionCollectionBean();
-        resultBean.setSections(sectionBeanList);
-        return resultBean;
-    }
-
-    /**
-     * 格式化标准答案
-     *
-     * @param answer
-     * @return
-     */
-    private OuterSectionCollectionBean getFormattedAnswer(String answer) {
-        if (StringUtils.isNullOrEmpty(answer)) {
-            return null;
-        }
+            outerSection.setBlocks(outerBlocks);
+            outerSections.add(outerSection);
+        });
 
-        return getBodyOrAnswer(answer);
+        result.setSections(outerSections);
+        return result;
     }
 
     /**
@@ -408,210 +325,4 @@ public class ExamQuestionOuterServiceProvider extends ControllerSupport implemen
         return "text";
     }
 
-    /**
-     * 获取图片作答的文本部分
-     *
-     * @param studentAnswer
-     * @return
-     */
-    private String getImgTxt(String studentAnswer) {
-        if (!StringUtils.isNullOrEmpty(studentAnswer)) {
-            return Jsoup.clean(studentAnswer, Whitelist.none());
-        }
-
-        return null;
-    }
-
-    /**
-     * 获取图片作答图片路径
-     *
-     * @param studentAnswer
-     * @return
-     */
-    private String getImgSrc(String studentAnswer) {
-        if (StringUtils.isNullOrEmpty(studentAnswer)) {
-            return studentAnswer;
-        }
-
-        //图片题特殊处理(因为图片作答题中有html标签,只需要取url即可)
-        Document doc = Jsoup.parse(studentAnswer);
-        Elements imgElements = doc.select("img[src]");
-
-        String imgSrc = "";
-
-        for (Element el : imgElements) {
-            String src = el.attr("src");
-            if (!StringUtils.isNullOrEmpty(src)) {
-                imgSrc += src + "|";
-            }
-        }
-        if (!StringUtils.isNullOrEmpty(imgSrc)) {
-            return imgSrc.substring(0, imgSrc.length() - 1);
-        }
-
-        return imgSrc;
-    }
-
-    /**
-     * 单个答案再次格式化,去除地址中的多余后缀
-     *
-     * @param answerType
-     * @param studentAnswer
-     * @return
-     */
-    private String getSimpleTransformedAnswer(String answerType, String studentAnswer) {
-        if ("image".equals(answerType)) {
-            String regExp = "(ftp|https?)\\:\\/\\/([\\w\\_\\-]+)\\.([\\w\\-]+[\\.]?)*[\\w]+\\.[a-zA-Z]{2,10}(.*)\\.(png|jpg|gif|jpeg)";
-            return RegExpUtil.find(studentAnswer, regExp);
-        }
-        return studentAnswer;
-    }
-
-    /**
-     * 获取格式化后后的题干或标准答案
-     *
-     * @param str
-     * @return
-     */
-    private OuterSectionCollectionBean getBodyOrAnswer(String str) {
-        OuterSectionCollectionBean body = new OuterSectionCollectionBean();
-        List<OuterSectionBean> sections = new ArrayList<>();
-        // 得到小题题干或者答案行数
-        if (org.apache.commons.lang3.StringUtils.isBlank(str)) {
-            return body;
-        }
-        String[] questionRowStrings = str.split("</p>");
-        for (int i = 0; i < questionRowStrings.length; i++) {
-            List<OuterBlockBean> blocks = disposeQuestionBodyOrOption(questionRowStrings[i]);
-            if (blocks != null && blocks.size() > 0) {
-                OuterSectionBean section = new OuterSectionBean();
-                // 将小题题干拆分为Block集合
-                section.setBlocks(blocks);
-                sections.add(section);
-            }
-        }
-        body.setSections(sections);
-        return body;
-    }
-
-    private List<OuterBlockBean> disposeQuestionBodyOrOption(String questionRow) {
-        List<OuterBlockBean> blocks = new ArrayList<>();
-        // 去掉每行里面的<p>,<span>,</span>标签
-        questionRow = questionRow.replaceAll("<p>", "").replaceAll("</p>", "").replaceAll("<span>", "")
-                .replaceAll("</span>", "").replaceAll("</a>", "");
-        String[] questionRowStrings = questionRow.split("<|/>|>");
-        for (int i = 0; i < questionRowStrings.length; i++) {
-            OuterBlockBean block = new OuterBlockBean();
-            String rowStr = questionRowStrings[i];
-            // 判断是否有图片
-            if (rowStr.startsWith("img")) {
-                rowStr = "<" + rowStr + ">";
-                Map<String, Object> param = new HashMap<>();
-                // 需要继续做截取,取到Parma
-                block.setType("image");
-                // 获取图片的路径
-                List<String> strSrcList = getImg(rowStr, "src");
-                if (strSrcList.size() > 0) {
-                    String strSrc = strSrcList.get(0).replaceAll("src=\"", "").replaceAll("\"", "");
-                    block.setValue(strSrc);
-                }
-                // 获取图片的高度
-                List<String> strHeightList = getImg(rowStr, "height");
-                if (strHeightList.size() > 0) {
-                    String strHeight = strHeightList.get(0).replaceAll("height=\"", "").replaceAll("\"", "");
-                    param.put("height", strHeight);
-                }
-                // 获取图片的宽度
-                List<String> strWidthList = getImg(rowStr, "width");
-                if (strHeightList.size() > 0) {
-                    String strWidth = strWidthList.get(0).replaceAll("width=\"", "").replaceAll("\"", "");
-                    param.put("width", strWidth);
-                }
-                block.setParam(param);
-                blocks.add(block);
-            } else if (rowStr.startsWith("a") && rowStr.contains("id") && rowStr.contains("name")) { // 处理音频
-                rowStr = "<" + rowStr + ">";
-                block.setPlayTime(1);
-                block.setType("audio");
-                block.setValue(this.getAttrValue(rowStr, "url"));
-                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);
-                    blocks.add(block);
-                }
-            }
-        }
-
-        return blocks;
-    }
-
-    /**
-     * 获取图片里面的路径,长度,宽度
-     */
-    private List<String> getImg(String s, String str) {
-        String regex;
-        List<String> list = new ArrayList<>();
-        regex = str + "=\"(.*?)\"";
-        Pattern pa = Pattern.compile(regex, Pattern.DOTALL);
-        Matcher ma = pa.matcher(s);
-        while (ma.find()) {
-            list.add(ma.group());
-        }
-        return list;
-    }
-
-    private String getAttrValue(String questionStr, String attrName) {
-        Pattern aPattern = Pattern.compile("a.*");
-        Matcher aMatcher = aPattern.matcher(questionStr);
-
-        if (aMatcher.find()) {
-            String idRegex = attrName + "=\".*?\"";
-            Pattern idPattern = Pattern.compile(idRegex);
-            Matcher idMatcher = idPattern.matcher(aMatcher.group());
-            if (idMatcher.find()) {
-                return idMatcher.group()
-                        .replaceAll(attrName + "=\"", "")
-                        .replaceAll("\"", "");
-            }
-        }
-
-        return "";
-    }
-
-    /**
-     * 校验图片答案格式是否正确
-     *
-     * @param studentAnswer
-     * @return
-     */
-    private boolean validateImgAnswer(String studentAnswer) {
-        if (StringUtils.isNullOrEmpty(studentAnswer)) {
-            return false;
-        }
-
-        String regExp = "[\\s\\S]*(ftp|https?)\\:\\/\\/([\\w\\_\\-]+)\\.([\\w\\-]+[\\.]?)*[\\w]+\\.[a-zA-Z]{2,10}(.*)\\.(png|jpg|gif|jpeg).*[\\s\\S]*";
-        return studentAnswer.matches(regExp);
-    }
-
-    /**
-     * 校验音频答案格式是否正确
-     *
-     * @param studentAnswer
-     * @return
-     */
-    private boolean validateAudioAnswer(String studentAnswer) {
-        if (StringUtils.isNullOrEmpty(studentAnswer)) {
-            return false;
-        }
-
-        String regExp = "^(ftp|https?)\\:\\/\\/([\\w\\_\\-]+)\\.([\\w\\-]+[\\.]?)*[\\w]+\\.[a-zA-Z]{2,10}(.*)\\.(mp3)";
-        return studentAnswer.matches(regExp);
-    }
 }