Pārlūkot izejas kodu

Merge branch 'dev_1.2.0' of http://git.qmth.com.cn/union-question/union-question-web into dev_1.2.0

xiatian 3 gadi atpakaļ
vecāks
revīzija
12ebcc5c34

+ 1 - 7
src/assets/styles/pages.scss

@@ -317,13 +317,7 @@
       }
     }
     &-action {
-      position: absolute;
-      background-color: #fff;
-      padding: 0 0 10px 20px;
-      top: 0;
-      right: 30px;
-      border-radius: 10px;
-      z-index: 9;
+      text-align: right;
     }
 
     &-body {

+ 2 - 2
src/components/vEditor/renderJSON.js

@@ -80,10 +80,10 @@ function renderBlock(block, inline) {
 
     node.src = block.value;
     node.dataset.isImage = true;
-    // 公式latex表达式
-    if (block.latex) node.dataset.latex = block.latex;
     // param
     if (block.param) {
+      // 公式latex表达式
+      if (block.param.latex) node.dataset.latex = block.param.latex;
       if (block.param.width) node.style.width = block.param.width + "px";
       if (block.param.height) node.style.height = block.param.height + "px";
     }

+ 5 - 4
src/components/vEditor/toJSON.js

@@ -120,16 +120,17 @@ function toJSONBlock(e) {
     e.dataset.isImage
   ) {
     block.type = "image";
-    // 公式latex表达式
-    if (e.dataset.dataLatex) {
-      block.latex = e.dataset.dataLatex;
-    }
+
     // change base64 image size, draw canvas
     block.value = e.src;
     block.param = {
       width: e.clientWidth,
       height: e.clientHeight,
     };
+    // 公式latex表达式
+    if (e.dataset.dataLatex) {
+      block.param.latex = e.dataset.dataLatex;
+    }
   } else if (
     e.nodeType == Node.ELEMENT_NODE &&
     e.nodeName === "IMG" &&

+ 5 - 5
src/modules/card/autoBuild/paperCard.js

@@ -159,7 +159,6 @@ function parseCommonTypeQuestions(structType, dataList) {
 }
 
 export function getFillBackClozeCount(questionBodyContent) {
-  // TODO:
   let questionBody = null;
   let num = 0;
   try {
@@ -180,9 +179,10 @@ export function buildCardElements(structList) {
   let cardElements = [];
   structList.forEach((struct) => {
     const detailChineseNumber = numberToChinese(struct.detailNo);
-    let topicName = struct.isCommon
-      ? `${detailChineseNumber}、${struct.detailName}`
-      : `${detailChineseNumber}(${struct.nestedQNo})`;
+    let topicName =
+      struct.isCommon || (!struct.isCommon && struct.isOnlyOneNested)
+        ? `${detailChineseNumber}、${struct.detailName}`
+        : `${detailChineseNumber}(${struct.nestedQNo})`;
     const modelType = structTypeToCardElementType[struct.structType];
 
     if (!struct.isCommon && struct.structType === "TEXT_ANSWER_QUESTION") {
@@ -217,7 +217,7 @@ export function buildCardElements(structList) {
 export function buildPaperCard(paperJson) {
   const structList = parsePaperStruct(paperJson);
   const cardElements = buildCardElements(structList);
-  console.log(cardElements);
+  // console.log(cardElements);
   return cardElements;
 }
 

+ 15 - 9
src/modules/card/autoBuild/simplePaperCard.js

@@ -14,21 +14,26 @@ function parseSimpleQuestion(simpleQuestion) {
   return {
     detailNo: detailNo * 1,
     questionNo: questionNo * 1,
-    subQno: subQno && subQno * 1,
+    subQno: subQno ? subQno * 1 : null,
     questionType,
     qinfo: qinfo * 1,
   };
 }
 
+function checkDetailIsOnlyOneNested(detail) {
+  const firstQuestionNo = detail.questions[0].questionNo;
+  return !detail.questions.some((q) => q.questionNo !== firstQuestionNo);
+}
+
 function parsePaperStruct(paperSimpleStruct) {
   // console.log(paperSimpleStruct);
   const dataList = paperSimpleStruct.split("#");
   const details = dataList.filter((item) => item.startsWith("detail"));
   let detailNames = {};
   details.forEach((detail) => {
-    const [detailNos, detailName] = detail.split("-");
-    const detailNo = detailNos.replace("detail:", "") * 1;
-    detailNames[detailNo] = detailName;
+    const pos = detail.indexOf("-");
+    const detailNo = detail.substring(0, pos).replace("detail:", "") * 1;
+    detailNames[detailNo] = detail.substring(pos + 1);
   });
   const questions = dataList
     .filter((item) => !item.startsWith("detail"))
@@ -50,8 +55,9 @@ function parsePaperStruct(paperSimpleStruct) {
 
   let structList = [];
   detailList.forEach((detail) => {
-    const commonQuestions = detail.questions.filter((q) =>
-      COMMON_QUESTION_TYPES.includes(q.questionType)
+    detail.isOnlyOneNested = checkDetailIsOnlyOneNested(detail);
+    const commonQuestions = detail.questions.filter(
+      (q) => COMMON_QUESTION_TYPES.includes(q.questionType) && q.subQno === null
     );
     if (commonQuestions.length) {
       const commonStructList = getCommonQuestionStructList(
@@ -63,9 +69,7 @@ function parsePaperStruct(paperSimpleStruct) {
       structList.push(...commonStructList);
     }
 
-    const nestedQuestions = detail.questions.filter(
-      (q) => !COMMON_QUESTION_TYPES.includes(q.questionType)
-    );
+    const nestedQuestions = detail.questions.filter((q) => q.subQno !== null);
     if (nestedQuestions.length) {
       const nestedStructList = getNestedQuestionStructList(
         detail,
@@ -100,6 +104,7 @@ function getCommonQuestionStructList(
     structList.push({
       detailName: detail.detailName,
       detailNo: detail.detailNo,
+      isOnlyOneNested: detail.isOnlyOneNested,
       structType,
       isCommon,
       nestedQNo,
@@ -135,6 +140,7 @@ function getNestedQuestionStructList(detail, questions) {
       false,
       question.questionNo
     );
+    // console.log(qStructList);
     structList.push(...qStructList);
   });
   return structList;

+ 2 - 2
src/modules/card/elements/fill-question/model.js

@@ -61,7 +61,7 @@ const getModel = (presetData) => {
 };
 
 const getFullModel = (modelProp, { pageSize, columnNumber }) => {
-  console.log(modelProp);
+  // console.log(modelProp);
   const parent = deepCopy(modelProp);
   const childModel = objAssign(MODEL, parent);
 
@@ -132,7 +132,7 @@ const getFullModel = (modelProp, { pageSize, columnNumber }) => {
       questionGroup,
       parent,
     });
-    console.log(questionGroup);
+    // console.log(questionGroup);
     const maxOptionCountPerGroup =
       questionGroup.length > 1
         ? childModel.questionCountPerGroup

+ 4 - 1
src/modules/card/views/CardEdit.vue

@@ -75,7 +75,6 @@ export default {
 
       const paperRes = await paperDetailApi(this.paperId);
       this.paperJson = paperRes.data;
-      const curPaperSimpleStruct = getPaperJsonSimpleStructInfo(this.paperJson);
 
       const detDataRes = await cardDetailByPaperId(this.paperId);
       if (detDataRes.data && detDataRes.data.id)
@@ -83,6 +82,10 @@ export default {
 
       if (detDataRes.data && detDataRes.data.content) {
         this.cardContent = JSON.parse(detDataRes.data.content);
+        const curPaperSimpleStruct = getPaperJsonSimpleStructInfo(
+          this.paperJson
+        );
+
         if (curPaperSimpleStruct !== this.cardContent.paperSimpleStruct) {
           this.$message.warning("试卷结构有变化,已重新生成题卡");
           this.cardContent = {

+ 65 - 53
src/modules/questions/views/EditPaper.vue

@@ -183,6 +183,10 @@
                 </span>
               </h3>
             </div>
+            <rich-text
+              class="edit-cont-body"
+              :text-json="paperDetail.description"
+            ></rich-text>
             <div
               :id="paperDetail.id"
               class="edit-cont-action"
@@ -242,10 +246,6 @@
                 @click.stop="showContent(detailIndex)"
               ></el-button>
             </div>
-            <rich-text
-              class="edit-cont-body"
-              :text-json="paperDetail.description"
-            ></rich-text>
           </div>
           <div v-show="quesTagShow" class="edit-property">
             <div class="edit-property-box">
@@ -298,6 +298,25 @@
                   ></rich-text>
                   <span> ({{ paperDetailUnit.score }}分) </span>
                 </div>
+                <div class="edit-cont-body">
+                  <div
+                    v-for="(quesOption, optionIndex) in paperDetailUnit.question
+                      .quesOptions"
+                    :key="optionIndex"
+                    class="paper-option"
+                  >
+                    <span>{{ optionIndex | optionOrderWordFilter }}. </span>
+                    <rich-text :text-json="quesOption.optionBody"></rich-text>
+                  </div>
+                  <div v-if="!isNested(paperDetailUnit.questionType)">
+                    <div v-show="quesAnswerShow" class="paper-answer">
+                      <span>答案:</span>
+                      <question-answer
+                        :data="paperDetailUnit.question"
+                      ></question-answer>
+                    </div>
+                  </div>
+                </div>
                 <div
                   :id="paperDetailUnit.id"
                   class="edit-cont-action"
@@ -379,25 +398,6 @@
                     @click.stop="showSubContent(detailIndex + '-' + unitIndex)"
                   ></el-button>
                 </div>
-                <div class="edit-cont-body">
-                  <div
-                    v-for="(quesOption, optionIndex) in paperDetailUnit.question
-                      .quesOptions"
-                    :key="optionIndex"
-                    class="paper-option"
-                  >
-                    <span>{{ optionIndex | optionOrderWordFilter }}. </span>
-                    <rich-text :text-json="quesOption.optionBody"></rich-text>
-                  </div>
-                  <div v-if="!isNested(paperDetailUnit.questionType)">
-                    <div v-show="quesAnswerShow" class="paper-answer">
-                      <span>答案:</span>
-                      <question-answer
-                        :data="paperDetailUnit.question"
-                      ></question-answer>
-                    </div>
-                  </div>
-                </div>
               </div>
               <div v-show="quesTagShow" class="edit-property">
                 <div class="edit-property-box">
@@ -442,6 +442,35 @@
                     quesMouseOut(getSubQuesEditId(paperDetailUnit, subQuestion))
                   "
                 >
+                  <div class="edit-cont-title">
+                    <span>{{ subQuestion.subNumber }}. </span>
+                    <rich-text :text-json="subQuestion.quesBody"></rich-text>
+                    <span
+                      >({{ paperDetailUnit.subScoreList[subIndex] }}分)</span
+                    >
+                  </div>
+                  <div
+                    v-if="!isMatchingQuestion(paperDetailUnit.questionType)"
+                    class="edit-cont-body"
+                  >
+                    <div
+                      v-for="(
+                        subQuesOption, subOptIndex
+                      ) in subQuestion.quesOptions"
+                      :key="subOptIndex"
+                      class="paper-option"
+                    >
+                      <span>{{ subOptIndex | optionOrderWordFilter }}. </span>
+                      <rich-text
+                        :text-json="subQuesOption.optionBody"
+                      ></rich-text>
+                    </div>
+                  </div>
+                  <div v-show="quesAnswerShow" class="paper-answer">
+                    <span>答案:</span>
+                    <question-answer :data="subQuestion"></question-answer>
+                    <!-- <rich-text :text-json="subQuestion.quesAnswer"></rich-text> -->
+                  </div>
                   <div
                     :id="getSubQuesEditId(paperDetailUnit, subQuestion)"
                     class="edit-cont-action"
@@ -483,36 +512,6 @@
                       >下移
                     </el-button>
                   </div>
-                  <div class="edit-cont-title">
-                    <span>{{ subQuestion.subNumber }}. </span>
-                    <rich-text :text-json="subQuestion.quesBody"></rich-text>
-                    <span
-                      >({{ paperDetailUnit.subScoreList[subIndex] }}分)</span
-                    >
-                  </div>
-
-                  <div
-                    v-if="!isMatchingQuestion(paperDetailUnit.questionType)"
-                    class="edit-cont-body"
-                  >
-                    <div
-                      v-for="(
-                        subQuesOption, subOptIndex
-                      ) in subQuestion.quesOptions"
-                      :key="subOptIndex"
-                      class="paper-option"
-                    >
-                      <span>{{ subOptIndex | optionOrderWordFilter }}. </span>
-                      <rich-text
-                        :text-json="subQuesOption.optionBody"
-                      ></rich-text>
-                    </div>
-                  </div>
-                  <div v-show="quesAnswerShow" class="paper-answer">
-                    <span>答案:</span>
-                    <question-answer :data="subQuestion"></question-answer>
-                    <!-- <rich-text :text-json="subQuestion.quesAnswer"></rich-text> -->
-                  </div>
                 </div>
                 <div v-show="quesTagShow" class="edit-property">
                   <div class="edit-property-box">
@@ -1180,6 +1179,7 @@ import PaperBasicComposition from "./PaperBasicComposition.vue";
 import PaperQuestionType from "./PaperQuestionType.vue";
 import PaperBlue from "./PaperBlue.vue";
 import AuditInfo from "./AuditInfo.vue";
+import { checkRichTextContentIsEmpty } from "@/plugins/utils";
 
 export default {
   name: "EditPaperApp",
@@ -2272,6 +2272,18 @@ export default {
           return;
         }
       }
+      if (
+        this.quesModel.quesOptions.length &&
+        this.quesModel.quesOptions.some((item) =>
+          checkRichTextContentIsEmpty(item.optionBody)
+        )
+      ) {
+        this.$notify({
+          message: "有选项内容为空",
+          type: "error",
+        });
+        return;
+      }
 
       if (this.paper.paperType == "GENERATE") {
         this.$confirm(

+ 67 - 53
src/modules/questions/views/EditPaperPendingTrial.vue

@@ -176,7 +176,7 @@
               >
             </div>
             <div class="edit-cont-body">
-              <div v-html="paper.examRemark"></div>
+              <rich-text :text-json="paper.examRemark"></rich-text>
             </div>
           </div>
         </div>
@@ -208,6 +208,10 @@
                 </span>
               </h3>
             </div>
+            <rich-text
+              class="edit-cont-body"
+              :text-json="paperDetail.description"
+            ></rich-text>
             <div
               :id="paperDetail.id"
               class="edit-cont-action"
@@ -273,10 +277,6 @@
                 @click.stop="showContent(detailIndex)"
               ></el-button>
             </div>
-            <rich-text
-              class="edit-cont-body"
-              :text-json="paperDetail.description"
-            ></rich-text>
           </div>
           <div v-show="quesTagShow" class="edit-property">
             <div class="edit-property-box">
@@ -329,6 +329,25 @@
                   ></rich-text>
                   <span> ({{ paperDetailUnit.score }}分) </span>
                 </div>
+                <div class="edit-cont-body">
+                  <div
+                    v-for="(quesOption, optionIndex) in paperDetailUnit.question
+                      .quesOptions"
+                    :key="optionIndex"
+                    class="paper-option"
+                  >
+                    <span>{{ optionIndex | optionOrderWordFilter }}. </span>
+                    <rich-text :text-json="quesOption.optionBody"></rich-text>
+                  </div>
+                  <div v-if="!isNested(paperDetailUnit.questionType)">
+                    <div v-show="quesAnswerShow" class="paper-answer">
+                      <span>答案:</span>
+                      <question-answer
+                        :data="paperDetailUnit.question"
+                      ></question-answer>
+                    </div>
+                  </div>
+                </div>
                 <div
                   :id="paperDetailUnit.id"
                   class="edit-cont-action"
@@ -414,25 +433,6 @@
                     @click.stop="showSubContent(detailIndex + '-' + unitIndex)"
                   ></el-button>
                 </div>
-                <div class="edit-cont-body">
-                  <div
-                    v-for="(quesOption, optionIndex) in paperDetailUnit.question
-                      .quesOptions"
-                    :key="optionIndex"
-                    class="paper-option"
-                  >
-                    <span>{{ optionIndex | optionOrderWordFilter }}. </span>
-                    <rich-text :text-json="quesOption.optionBody"></rich-text>
-                  </div>
-                  <div v-if="!isNested(paperDetailUnit.questionType)">
-                    <div v-show="quesAnswerShow" class="paper-answer">
-                      <span>答案:</span>
-                      <question-answer
-                        :data="paperDetailUnit.question"
-                      ></question-answer>
-                    </div>
-                  </div>
-                </div>
               </div>
               <div v-show="quesTagShow" class="edit-property">
                 <div class="edit-property-box">
@@ -478,6 +478,35 @@
                     quesMouseOut(getSubQuesEditId(paperDetailUnit, subQuestion))
                   "
                 >
+                  <div class="edit-cont-title">
+                    <span>{{ subQuestion.subNumber }}. </span>
+                    <rich-text :text-json="subQuestion.quesBody"></rich-text>
+                    <span
+                      >({{ paperDetailUnit.subScoreList[subIndex] }}分)</span
+                    >
+                  </div>
+
+                  <div
+                    v-if="!isMatchingQuestion(paperDetailUnit.questionType)"
+                    class="edit-cont-body"
+                  >
+                    <div
+                      v-for="(
+                        subQuesOption, subOptIndex
+                      ) in subQuestion.quesOptions"
+                      :key="subOptIndex"
+                      class="paper-option"
+                    >
+                      <span>{{ subOptIndex | optionOrderWordFilter }}. </span>
+                      <rich-text
+                        :text-json="subQuesOption.optionBody"
+                      ></rich-text>
+                    </div>
+                  </div>
+                  <div v-show="quesAnswerShow" class="paper-answer">
+                    <span>答案:</span>
+                    <question-answer :data="subQuestion"></question-answer>
+                  </div>
                   <div
                     v-show="isShowEditBtn()"
                     :id="getSubQuesEditId(paperDetailUnit, subQuestion)"
@@ -520,35 +549,6 @@
                       >下移
                     </el-button>
                   </div>
-                  <div class="edit-cont-title">
-                    <span>{{ subQuestion.subNumber }}. </span>
-                    <rich-text :text-json="subQuestion.quesBody"></rich-text>
-                    <span
-                      >({{ paperDetailUnit.subScoreList[subIndex] }}分)</span
-                    >
-                  </div>
-
-                  <div
-                    v-if="!isMatchingQuestion(paperDetailUnit.questionType)"
-                    class="edit-cont-body"
-                  >
-                    <div
-                      v-for="(
-                        subQuesOption, subOptIndex
-                      ) in subQuestion.quesOptions"
-                      :key="subOptIndex"
-                      class="paper-option"
-                    >
-                      <span>{{ subOptIndex | optionOrderWordFilter }}. </span>
-                      <rich-text
-                        :text-json="subQuesOption.optionBody"
-                      ></rich-text>
-                    </div>
-                  </div>
-                  <div v-show="quesAnswerShow" class="paper-answer">
-                    <span>答案:</span>
-                    <question-answer :data="subQuestion"></question-answer>
-                  </div>
                 </div>
                 <div v-show="quesTagShow" class="edit-property">
                   <div class="edit-property-box">
@@ -1228,6 +1228,7 @@ import PaperQuestionType from "./PaperQuestionType.vue";
 import PaperBlue from "./PaperBlue.vue";
 import AuditInfo from "./AuditInfo.vue";
 import AuditPaper from "./AuditPaper.vue";
+import { checkRichTextContentIsEmpty } from "@/plugins/utils";
 
 export default {
   name: "EditPaperApp",
@@ -2345,6 +2346,19 @@ export default {
           return;
         }
       }
+      if (
+        this.quesModel.quesOptions.length &&
+        this.quesModel.quesOptions.some((item) =>
+          checkRichTextContentIsEmpty(item.optionBody)
+        )
+      ) {
+        this.$notify({
+          message: "有选项内容为空",
+          type: "error",
+        });
+        return;
+      }
+
       if (this.paper.paperType == "GENERATE") {
         this.$confirm(
           "试题内容修改,会影响所有关联试卷,是否确定进行?",

+ 0 - 2
src/modules/questions/views/EditSelectQuestion.vue

@@ -252,11 +252,9 @@
 <script>
 import { QUESTION_API } from "@/constants/constants";
 import { isEmptyStr, QUESTION_TYPES } from "../constants/constants";
-// import ckeditor from "../component/ckeditor.vue";
 
 export default {
   name: "EditSelectApp",
-  // components: { ckeditor },
   data() {
     return {
       coursePropertyLoading: false,

+ 2 - 2
src/modules/questions/views/GenPaperDetail.vue

@@ -848,7 +848,7 @@ export default {
             // console.log("response:", response);
             this.selectPapers = response.data.content;
             this.totalSelect = response.data.totalElements;
-            this.curSelect = response.data.number + 1;
+            this.curSelect = response.data.number;
             this.loading = false;
           });
       } else if (this.paperType == "GENERATE") {
@@ -867,7 +867,7 @@ export default {
           .then((response) => {
             this.selectPapers = response.data.content;
             this.totalSelect = response.data.totalElements;
-            this.curSelect = response.data.number + 1;
+            this.curSelect = response.data.number;
             this.loading = false;
           });
       } else {

+ 22 - 0
src/plugins/utils.js

@@ -268,3 +268,25 @@ export function parseHrefParam(href, paramName = null) {
 
   return paramName ? params[paramName] : params;
 }
+
+export function checkRichTextContentIsEmpty(cont) {
+  if (!cont) return true;
+
+  if (!cont.sections || !cont.sections.length) return true;
+
+  let blocks = [];
+  cont.sections.forEach((section) => {
+    blocks = [...blocks, ...section.blocks];
+  });
+
+  if (!blocks.length) return true;
+
+  if (blocks.some((item) => item.type !== "text")) {
+    return false;
+  } else {
+    return !blocks
+      .map((item) => item.value)
+      .join("")
+      .trim();
+  }
+}