Selaa lähdekoodia

feat: word导入调整

zhangjie 1 kuukausi sitten
vanhempi
commit
946a1d3ad9

+ 61 - 4
src/assets/styles/pages.scss

@@ -1451,10 +1451,12 @@
 
       &-menu {
         margin-top: 8px;
-
-        .el-tabs__header {
-          margin: 0;
+        .el-tabs__nav-next,
+        .el-tabs__nav-prev {
+          line-height: 32px;
+          font-size: 14px;
         }
+
         .el-tabs__item {
           font-size: 14px;
           height: 32px;
@@ -1469,7 +1471,20 @@
       overflow-y: auto;
     }
     &-richtext {
-      margin: 10px;
+      margin: 10px 6px;
+      padding: 6px;
+      border: 1px solid #e4e7ed;
+      border-radius: 5px;
+      &.is-error {
+        border-color: #fe5d4e;
+      }
+
+      &-error {
+        padding: 0 8px;
+      }
+      .v-editor-container {
+        border-color: transparent;
+      }
       .tips-info {
         line-height: 20px;
         min-height: auto;
@@ -1511,6 +1526,48 @@
   div.section-error {
     color: #fe5d4e;
   }
+
+  // ep-question
+  .ep-question {
+    padding: 0;
+    border: 1px solid #e4e7ed;
+    border-radius: 5px;
+    overflow: hidden;
+    margin: 10px 0;
+
+    &-type {
+      padding: 15px;
+      font-size: 14px;
+      background-color: #f6f6f6;
+      margin: 0;
+      border-bottom: 1px solid #e4e7ed;
+    }
+
+    &.is-error {
+      border-color: #fe5d4e;
+
+      .ep-question-type {
+        background-color: #fff2f0;
+        border-color: #fe5d4e;
+      }
+    }
+
+    &-main {
+      padding: 10px;
+    }
+
+    &-content {
+      margin: 0;
+      padding: 10px;
+
+      &:not(.is-active) {
+        cursor: pointer;
+        &:hover {
+          background-color: transparent;
+        }
+      }
+    }
+  }
 }
 
 // question-info-edit

+ 129 - 26
src/modules/question/components/QuestionImportEdit.vue

@@ -114,9 +114,12 @@
             <div class="qe-part-body">
               <div id="qe-part-richtext-list">
                 <div
-                  class="qe-part-richtext"
                   v-for="(richJsonItem, rindex) in paperRichJsonGroup"
                   :key="rindex"
+                  :class="[
+                    'qe-part-richtext',
+                    { 'is-error': richJsonItem.exceptions.length },
+                  ]"
                 >
                   <v-editor
                     ref="RichTextEditor"
@@ -175,11 +178,11 @@
                 <p class="desc-qcout">
                   <span>共识别 </span>
                   <span class="color-success">
-                    {{ parseQuestionData.successCount }}
+                    {{ questionStatData.successCount }}
                   </span>
                   <span> 题,其中识别有误 </span>
                   <span class="color-danger">
-                    {{ parseQuestionData.errorCount }}
+                    {{ questionStatData.errorCount }}
                   </span>
                   <span> 题</span>
                 </p>
@@ -188,11 +191,14 @@
               <div class="qe-part-head-menu">
                 <el-tabs
                   v-model="filterQuestionType"
-                  @tab-click="filterQuestionTypeClick"
+                  @tab-click="filterQuestionTypeChange"
                 >
-                  <el-tab-pane label="全部" name=""></el-tab-pane>
                   <el-tab-pane
-                    v-for="item in parseQuestionData.qtypes"
+                    :label="`全部(${questionStatData.total})`"
+                    name="all"
+                  ></el-tab-pane>
+                  <el-tab-pane
+                    v-for="item in questionStatData.qtypes"
                     :key="item.questionType"
                     :label="`${item.questionTypeName}(${item.questionCount})`"
                     :name="item.questionType"
@@ -202,10 +208,10 @@
             </div>
             <div id="qe-part-paper" class="qe-part-body">
               <question-import-paper-edit
-                v-if="paperData.length"
+                v-if="filterPaperData.length"
                 ref="QuestionImportPaperEdit"
                 :key="questionKey"
-                :paper="paperData"
+                :paper="filterPaperData"
                 :course-id="data.importData.courseId"
               ></question-import-paper-edit>
             </div>
@@ -272,7 +278,7 @@ import {
   questionWordImportTemplate,
 } from "../api";
 import ImportFileDialog from "@/components/ImportFileDialog.vue";
-import { QUESTION_API } from "@/constants/constants";
+import { QUESTION_API, QUESTION_TYPES } from "@/constants/constants";
 import { downloadByApi } from "@/plugins/download";
 import { richTextToJSON, renderRichText } from "./import-edit/richText";
 import scrollMixins from "./import-edit/scrollMixins";
@@ -346,21 +352,6 @@ export default {
         });
       });
     },
-    parseQuestionData() {
-      // TODO:
-      return {
-        total: 0,
-        successCount: 0,
-        errorCount: 0,
-        qtypes: [
-          {
-            questionType: "1",
-            questionTypeName: "单选题",
-            questionCount: 0,
-          },
-        ],
-      };
-    },
   },
   data() {
     return {
@@ -368,6 +359,7 @@ export default {
       modalIsShow: false,
       loading: false,
       questionKey: "",
+      filterPaperData: [],
       paperData: [],
       paperRichJson: { sections: [] },
       paperRichJsonGroup: [],
@@ -387,13 +379,51 @@ export default {
       uploadUrl: `${QUESTION_API}/word/parse/struct`,
       showIframeDialog: false,
       // question types
-      filterQuestionType: "",
+      questionStatData: {
+        total: 0,
+        successCount: 0,
+        errorCount: 0,
+        qtypes: [],
+      },
+      filterQuestionType: "all",
       modalForm: this.getInitForm(),
+      rules: {
+        courseId: [
+          {
+            required: true,
+            message: "请选择课程",
+            trigger: "change",
+          },
+        ],
+        name: [
+          {
+            required: true,
+            message: "请输入试卷名称",
+            trigger: "change",
+          },
+        ],
+        totalScore: [
+          {
+            required: true,
+            message: "请输入试卷总分",
+            trigger: "change",
+          },
+        ],
+      },
     };
   },
   created() {
     this.$bus.on("markIgnoreRepeatQuestion", this.markIgnoreRepeat);
   },
+  watch: {
+    paperData: {
+      handler() {
+        this.parseQuestionStatData();
+        this.filterQuestionTypeChange({ name: this.filterQuestionType });
+        this.questionKey = randomCode();
+      },
+    },
+  },
   methods: {
     getInitForm() {
       return {
@@ -409,6 +439,51 @@ export default {
     courseChange(val) {
       this.modalForm.courseName = val ? val.name : "";
       this.getCourseProperty();
+      this.uploadData = { courseId: this.modalForm.courseId };
+    },
+    parseQuestionStatData() {
+      const total = calcSum(
+        this.paperData.map((item) => item.questions.length)
+      );
+      const successCount = calcSum(
+        this.paperData.map(
+          (item) =>
+            item.questions.filter((v) => !v.questionExceptions.length).length
+        )
+      );
+      const errorCount = calcSum(
+        this.paperData.map(
+          (item) =>
+            item.questions.filter((v) => v.questionExceptions.length).length
+        )
+      );
+      const questionTypeStat = {};
+      this.paperData.forEach((detail) => {
+        detail.questions.forEach((question) => {
+          const { questionType } = question;
+          if (questionTypeStat[questionType]) {
+            questionTypeStat[questionType]++;
+          } else {
+            questionTypeStat[questionType] = 1;
+          }
+        });
+      });
+      const qtMap = {};
+      QUESTION_TYPES.forEach((item) => {
+        qtMap[item.code] = item.name;
+      });
+      const qtypes = Object.keys(questionTypeStat).map((key) => ({
+        questionType: key,
+        questionTypeName: qtMap[key],
+        questionCount: questionTypeStat[key],
+      }));
+
+      this.questionStatData = {
+        total,
+        successCount,
+        errorCount,
+        qtypes,
+      };
     },
     inHasIgnore(indexes) {
       return this.ignoreRepeatExceptionIndexArr.includes(indexes.toString());
@@ -494,8 +569,31 @@ export default {
         this.getRichTextIndexList();
       });
     },
-    filterQuestionTypeClick(val) {
+    filterQuestionTypeChange(val) {
+      console.log(val);
       this.filterQuestionType = val.name;
+
+      const filterQuestionType =
+        this.filterQuestionType === "all" ? "" : this.filterQuestionType;
+      if (!filterQuestionType) {
+        this.filterPaperData = this.paperData;
+        return;
+      }
+
+      this.filterPaperData = this.paperData
+        .filter((detail) => {
+          return detail.questions.some(
+            (question) => question.questionType == filterQuestionType
+          );
+        })
+        .map((detail) => {
+          return {
+            ...detail,
+            questions: detail.questions.filter(
+              (question) => question.questionType == filterQuestionType
+            ),
+          };
+        });
     },
     getRichTextIndexList() {
       const richTextListDom = document.getElementById("qe-part-richtext-list");
@@ -707,6 +805,8 @@ export default {
       }, 5000);
     },
     initData() {
+      this.filterPaperData = [];
+      this.filterQuestionType = "all";
       this.paperData = [];
       this.paperRichJson = { sections: [] };
       window.sessionStorage.removeItem("coursePropertys");
@@ -1146,6 +1246,9 @@ export default {
       return true;
     },
     async confirm() {
+      const valid = await this.$refs.modalFormComp.validate().catch(() => {});
+      if (!valid) return;
+
       const confirm = await this.$confirm("确认加入题库吗?", "提示", {
         type: "warning",
       }).catch(() => {});

+ 25 - 18
src/modules/question/components/QuestionImportPaperEdit.vue

@@ -16,12 +16,15 @@
         <div
           v-for="(question, qindex) in detail.questions"
           :key="qindex"
-          class="ep-question"
+          :class="[
+            'ep-question',
+            { 'is-error': question.exceptions?.length > 0 },
+          ]"
         >
           <div class="ep-question-type">
             [题型:{{ question.sourceDetailName }}]
           </div>
-          <div :id="`question-${question.id}`">
+          <div :id="`question-${question.id}`" class="ep-question-main">
             <component
               :is="structTypeComp(question.questionType)"
               :ref="`QuestionEditDetail-${dIndex}-${qindex}-${question.id}`"
@@ -100,22 +103,26 @@ export default {
       return STRUCT_TYPE_COMP_DICT[questionType];
     },
     getQuestionInfo(question) {
-      const exceptionField = ["bodyIndex", "optionIndex"];
-      let exceptionIndexs = [];
-      exceptionField.forEach((item) => {
-        if (question.questionIndex[item])
-          exceptionIndexs.push(...question.questionIndex[item]);
-      });
-      let exceptions = [];
-      if (question.questionExceptions) {
-        question.questionExceptions.forEach((item) => {
-          if (
-            item.exceptionIndex.some((key) => exceptionIndexs.includes(key))
-          ) {
-            exceptions.push(item.cause);
-          }
-        });
-      }
+      // const exceptionField = ["bodyIndex", "optionIndex"];
+      // let exceptionIndexs = [];
+      // exceptionField.forEach((item) => {
+      //   if (question.questionIndex[item])
+      //     exceptionIndexs.push(...question.questionIndex[item]);
+      // });
+      // let exceptions = [];
+      // if (question.questionExceptions) {
+      //   question.questionExceptions.forEach((item) => {
+      //     if (
+      //       item.exceptionIndex.some((key) => exceptionIndexs.includes(key))
+      //     ) {
+      //       exceptions.push(item.cause);
+      //     }
+      //   });
+      // }
+
+      const exceptions = (question.questionExceptions || []).map(
+        (item) => item.cause
+      );
 
       return {
         sourceDetailId: question.customizeQuestionType?.id,