Преглед на файлове

试题导入编辑成卷

zhangjie преди 2 години
родител
ревизия
6c51dde63f

BIN
src/assets/images/icon-export-answer.png


BIN
src/assets/images/icon-export-prop.png


BIN
src/assets/images/icon-tips.png


+ 12 - 0
src/assets/styles/icons.scss

@@ -185,4 +185,16 @@
     width: 14px;
     height: 12px;
   }
+  &-tips {
+    background-image: url(../images/icon-tips.png);
+    @include icon-12;
+  }
+  &-export-answer {
+    background-image: url(../images/icon-export-answer.png);
+    @include icon-12;
+  }
+  &-export-prop {
+    background-image: url(../images/icon-export-prop.png);
+    @include icon-12;
+  }
 }

+ 90 - 0
src/assets/styles/pages.scss

@@ -1183,3 +1183,93 @@
     }
   }
 }
+
+// question-export-edit-dialog
+.question-export-edit-dialog {
+  .el-dialog__body {
+    height: 100%;
+    overflow: auto;
+    min-width: 1200px;
+  }
+  .qe-body {
+    height: 100%;
+    position: relative;
+    font-size: 0;
+  }
+  .qe-part {
+    display: inline-block;
+    vertical-align: top;
+    width: 50%;
+    height: 100%;
+    font-size: 14px;
+
+    &-edit {
+      padding-right: 52px;
+
+      .v-editor {
+        height: 100%;
+        padding-top: 20px;
+      }
+      .v-editor-head {
+        display: none;
+      }
+      .v-editor-container {
+        padding: 0;
+        max-height: 100%;
+        height: 100%;
+      }
+    }
+    &-view {
+      padding-left: 52px;
+    }
+
+    &-main {
+      background-color: #fff;
+      padding: 20px;
+      box-shadow: 0px 20px 20px 0px rgba(212, 220, 243, 0.2);
+      border-radius: 16px;
+      height: 100%;
+
+      display: flex;
+      flex-direction: column;
+      justify-content: space-between;
+    }
+
+    &-head {
+      display: flex;
+      justify-content: space-between;
+      align-items: center;
+      height: 64px;
+      margin-top: -20px;
+      border-bottom: 1px solid #f0f2f6;
+
+      flex-grow: 0;
+      flex-shrink: 0;
+
+      > h3 {
+        font-size: 16px;
+        font-weight: bold;
+      }
+
+      &:nth-of-type(1) {
+        > div {
+          color: #9a9dab;
+        }
+      }
+    }
+    &-body {
+      flex-grow: 2;
+      overflow-x: hidden;
+      overflow-y: auto;
+    }
+  }
+  .qe-middle {
+    position: absolute;
+    top: 50%;
+    left: 50%;
+    transform: translate(-50%, -50%);
+    width: 80px;
+    text-align: center;
+    z-index: 99;
+  }
+}

+ 14 - 2
src/components/ImportFileDialog.vue

@@ -53,7 +53,7 @@
         清空文件
       </el-button>
       <el-button
-        v-if="templateUrl"
+        v-if="templateUrl || templateDownloadHandle"
         size="small"
         type="primary"
         icon="icon icon-export-white"
@@ -114,6 +114,10 @@ export default {
       type: String,
       default: "",
     },
+    templateDownloadHandle: {
+      type: Function,
+      default: null,
+    },
   },
   data() {
     return {
@@ -242,7 +246,15 @@ export default {
       this.$refs.UploadComp.clearFiles();
     },
     exportFile() {
-      window.open(this.templateUrl);
+      if (this.templateUrl) {
+        window.open(this.templateUrl);
+        return;
+      }
+
+      if (this.templateDownloadHandle) {
+        this.templateDownloadHandle();
+        return;
+      }
     },
   },
 };

+ 8 - 1
src/components/vEditor/VEditor.vue

@@ -1,7 +1,10 @@
 <template>
   <div class="v-editor">
     <VMenu class="v-editor-head" />
-    <div :class="['v-editor-container', { 'is-focus': isFocus }]">
+    <div
+      :class="['v-editor-container', { 'is-focus': isFocus }]"
+      @click="containerClick"
+    >
       <div ref="editorMain" class="v-editor-main">
         <div
           :id="'ved' + _uid"
@@ -142,6 +145,10 @@ export default {
       this.$emit("input", json);
       this.$emit("change", json);
     },
+    containerClick() {
+      this.$refs.editor.focus();
+      this.isFocus = true;
+    },
     // image resize
     clickEventHandle(e) {
       const el = e.target;

+ 4 - 0
src/filters/filters.js

@@ -8,6 +8,7 @@ import {
   QUESTION_MAIN_TYPE,
   QUESTION_TYPES,
 } from "@/constants/constants";
+import { numberToChinese } from "@/plugins/utils";
 
 // 课程层次过滤器
 Vue.filter("levelTypeFilter", function (val) {
@@ -50,3 +51,6 @@ Vue.filter("questionTypeFilter", function (val) {
     }
   }
 });
+Vue.filter("numberToChaineseFilter", function (val) {
+  return val ? numberToChinese(val) : "";
+});

+ 10 - 0
src/modules/question/api.js

@@ -270,3 +270,13 @@ export function updateSourceDetailApi(data) {
     { params: data }
   );
 }
+
+// question-import-edit
+export function questionImportParseRichText(richText) {
+  return $httpWithMsg.post(`${QUESTION_API}/question/import/parse`, {
+    richText,
+  });
+}
+export function questionImportPaperSave(paperData) {
+  return $httpWithMsg.post(`${QUESTION_API}/question/import/paper`, paperData);
+}

+ 274 - 0
src/modules/question/components/QuestionImportEdit.vue

@@ -0,0 +1,274 @@
+<template>
+  <div class="question-export-edit">
+    <el-dialog
+      custom-class="question-export-edit-dialog"
+      :visible.sync="modalIsShow"
+      :close-on-click-modal="false"
+      :close-on-press-escape="false"
+      append-to-body
+      fullscreen
+      destroy-on-close
+      :show-close="false"
+      @open="visibleChange"
+    >
+      <div slot="title" class="box-justify">
+        <div>
+          <h2>文件上传</h2>
+        </div>
+        <div>
+          <el-button
+            size="small"
+            type="danger"
+            plain
+            icon="icon icon-back"
+            @click="cancel"
+            >返回</el-button
+          >
+        </div>
+      </div>
+      <div class="qe-body">
+        <div class="qe-part qe-part-edit">
+          <div class="qe-part-main">
+            <div class="qe-part-head">
+              <h3>题目编辑</h3>
+              <div>
+                <i class="icon icon-tips"></i>
+                提示:若识别有误,可点击左侧题目按格式进行修改后重新识别
+              </div>
+            </div>
+            <div class="qe-part-body">
+              <v-editor v-model="paperRichJson"></v-editor>
+            </div>
+          </div>
+        </div>
+        <div class="qe-part qe-part-view">
+          <div class="qe-part-main">
+            <div class="qe-part-head">
+              <h3>题目阅览</h3>
+              <div>
+                <el-button
+                  size="small"
+                  type="primary"
+                  plain
+                  icon="icon icon-export-answer"
+                  @click="toImportAnswer"
+                  >导入答案</el-button
+                >
+                <el-button
+                  size="small"
+                  type="primary"
+                  plain
+                  icon="icon icon-export-prop"
+                  @click="toImportProp"
+                  >导入属性</el-button
+                >
+                <el-button
+                  size="small"
+                  type="primary"
+                  icon="icon icon-save-white"
+                  @click="confirm"
+                  >识别无误,加入题库</el-button
+                >
+              </div>
+            </div>
+            <div class="qe-part-body">
+              <question-import-paper-edit
+                ref="QuestionImportPaperEdit"
+                :key="questionKey"
+                :paper="paperData"
+                :course-id="data.courseId"
+              ></question-import-paper-edit>
+            </div>
+          </div>
+        </div>
+        <div class="qe-middle">
+          <el-button
+            size="small"
+            type="primary"
+            :loading="loading"
+            @click="toParse"
+            >识别</el-button
+          >
+        </div>
+      </div>
+    </el-dialog>
+
+    <!-- 上传答案文件 -->
+    <import-file-dialog
+      ref="ImportAnswerDialog"
+      dialog-title="导入答案"
+      :template-download-handle="answerTemplateDownload"
+      :upload-url="uploadAnswerUrl"
+      add-file-param="dataFile"
+      @uploaded="answerUploaded"
+    ></import-file-dialog>
+    <!-- 上传属性文件 -->
+    <import-file-dialog
+      ref="ImportPropDialog"
+      dialog-title="导入属性"
+      :template-download-handle="propTemplateDownload"
+      :upload-url="uploadPropUrl"
+      add-file-param="dataFile"
+      @uploaded="propUploaded"
+    ></import-file-dialog>
+  </div>
+</template>
+
+<script>
+import { deepCopy, randomCode } from "@/plugins/utils";
+import paperRichTextJson from "../datas/paperRichText.json";
+import QuestionImportPaperEdit from "./QuestionImportPaperEdit.vue";
+import { isAnEmptyRichText } from "@/utils/utils";
+import { questionImportPaperSave, questionImportParseRichText } from "../api";
+import ImportFileDialog from "@/components/ImportFileDialog.vue";
+import { QUESTION_API } from "@/constants/constants";
+
+const questionInfoField = [
+  "courseId",
+  "difficulty",
+  "quesProperties",
+  "score",
+  "publicity",
+  "control",
+  "quesAnswer",
+];
+
+export default {
+  name: "QuestionExportEdit",
+  components: { QuestionImportPaperEdit, ImportFileDialog },
+  props: {
+    data: {
+      type: Object,
+      default() {
+        return {
+          paperRichText: { sections: [] },
+          paperData: [],
+          courseId: "",
+        };
+      },
+    },
+  },
+  data() {
+    return {
+      modalIsShow: true,
+      loading: false,
+      paperData: [],
+      paperRichJson: paperRichTextJson,
+      // paperRichJson: { sections: [] },
+      // upload answer
+      uploadAnswerUrl: `${QUESTION_API}/paper/answer/import/`,
+      // upload prop
+      uploadPropUrl: `${QUESTION_API}/paper/answer/import/`,
+    };
+  },
+  methods: {
+    visibleChange() {
+      this.paperRichJson = deepCopy(this.data.paperRichText);
+      this.paperData = deepCopy(this.data.paperData);
+      this.questionKey = randomCode();
+    },
+    cancel() {
+      this.modalIsShow = false;
+    },
+    open() {
+      this.modalIsShow = true;
+    },
+    async toParse() {
+      if (isAnEmptyRichText(this.paperRichJson)) {
+        this.$message.error("请输入试卷内容!");
+        return;
+      }
+
+      if (this.loading) return;
+      this.loading = true;
+
+      const res = questionImportParseRichText(this.paperRichJson).catch(
+        () => {}
+      );
+      this.loading = false;
+      if (!res) return;
+
+      const cacheData = this.getCachePaperInfo(
+        this.paperData,
+        questionInfoField
+      );
+      this.paperData = this.assignCachePaperData(res.data, cacheData);
+      this.questionKey = randomCode();
+    },
+    getCachePaperInfo(paperData, cacheFields = []) {
+      let cachePaperInfo = {};
+      paperData.forEach((detail) => {
+        detail.questions.forEach((question) => {
+          let info = {};
+          let k = `${detail.number}_${question.number}`;
+          if (cacheFields.length) {
+            cacheFields.forEach((field) => {
+              info[field] = question[field];
+            });
+          } else {
+            info = { ...question };
+          }
+
+          cachePaperInfo[k] = info;
+        });
+      });
+      return cachePaperInfo;
+    },
+    assignCachePaperData(paperData, cacheData) {
+      paperData.forEach((detail) => {
+        detail.questions.forEach((question) => {
+          Object.assign(
+            question,
+            cacheData[`${detail.number}_${question.number}`] || {}
+          );
+        });
+      });
+      return paperData;
+    },
+    async confirm() {
+      const confirm = await this.$confirm("确认加入题库吗?", "提示", {
+        type: "warning",
+      }).catch(() => {});
+      if (confirm !== "confirm") return;
+
+      if (this.loading) return;
+      this.loading = true;
+
+      const paperData = this.$refs.QuestionImportPaperEdit.getData();
+      console.log(paperData);
+
+      const res = await questionImportPaperSave({
+        courseId: this.courseId,
+        paperData,
+      }).catch(() => {});
+
+      this.loading = false;
+      if (!res) return;
+
+      this.$message.success("提交成功!");
+      this.$emit("modified");
+      this.cancel();
+    },
+    // 导入答案
+    toImportAnswer() {
+      this.$refs.ImportAnswerDialog.open();
+    },
+    answerTemplateDownload() {},
+    answerUploaded(answerData) {
+      const cacheData = this.getCachePaperInfo(answerData, ["quesAnswer"]);
+      this.paperData = this.assignCachePaperData(this.paperData, cacheData);
+      this.questionKey = randomCode();
+    },
+    // 导入属性
+    toImportProp() {
+      this.$refs.ImportPropDialog.open();
+    },
+    propTemplateDownload() {},
+    propUploaded(propData) {
+      const cacheData = this.getCachePaperInfo(propData, ["quesProperties"]);
+      this.paperData = this.assignCachePaperData(this.paperData, cacheData);
+      this.questionKey = randomCode();
+    },
+  },
+};
+</script>

+ 97 - 0
src/modules/question/components/QuestionImportPaperEdit.vue

@@ -0,0 +1,97 @@
+<template>
+  <div class="question-export-paper-edit">
+    <div v-for="detail in paperData" :key="detail.number" class="ep-detail">
+      <div class="ep-detail-head">
+        <h3 class="ep-detail-title">
+          {{ detail.number | numberToChaineseFilter }}、{{ detail.name }}
+        </h3>
+        <!-- <p class="ep-detail-desc"></p> -->
+      </div>
+      <div class="ep-detail-body">
+        <div
+          v-for="question in detail"
+          :key="question.number"
+          class="ep-question"
+        >
+          <div class="ep-question-type">
+            [题型:{{ question.questionType | questionTypeFilter }}]
+          </div>
+          <component
+            :is="structTypeComp(question.questionType)"
+            :ref="`QuestionEditDetail${detail.number}-${question.number}`"
+            :question="question"
+          ></component>
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+import { deepCopy } from "@/plugins/utils";
+import paperParseData from "../datas/paperParseData.json";
+import { structTypeToQuestionType } from "./import-edit/model";
+import BooleanQuestion from "./import-edit/BooleanQuestion.vue";
+import FillBlankQuestion from "./import-edit/FillBlankQuestion.vue";
+import SelectQuestion from "./import-edit/SelectQuestion.vue";
+import TextAnswerQuestion from "./import-edit/TextAnswerQuestion.vue";
+import NestedQuestion from "./import-edit/NestedQuestion.vue";
+import BankedClozeQuestion from "./import-edit/BankedClozeQuestion.vue";
+import { STRUCT_TYPE_COMP_DICT } from "./model/questionModel";
+
+export default {
+  name: "QuestionExportPaperEdit",
+  components: {
+    FillBlankQuestion,
+    SelectQuestion,
+    TextAnswerQuestion,
+    BooleanQuestion,
+    NestedQuestion,
+    BankedClozeQuestion,
+  },
+  props: {
+    paper: {
+      type: Array,
+      default() {
+        return [];
+      },
+    },
+    courseId: {
+      type: [String, Number],
+      default: "",
+    },
+  },
+  data() {
+    return {
+      paperData: paperParseData,
+      // paperData: [],
+    };
+  },
+  methods: {
+    structTypeComp(questionType) {
+      return STRUCT_TYPE_COMP_DICT[questionType];
+    },
+    transformPaperData() {
+      let paperData = deepCopy(this.paper);
+      paperData.forEach((detail) => {
+        detail.questions.forEach((question) => {
+          question.questionType = structTypeToQuestionType(question.type);
+          question.courseId = this.courseId;
+        });
+      });
+      this.paperData = paperData;
+    },
+    checkData() {},
+    getData() {
+      this.paperData.forEach((detail) => {
+        detail.questions.forEach((question) => {
+          const refName = `QuestionEditDetail${detail.number}-${question.number}`;
+          const questionData = this.$refs[refName].getData();
+          Object.assign(question, questionData);
+        });
+      });
+      return this.paperData;
+    },
+  },
+};
+</script>

+ 115 - 0
src/modules/question/components/import-edit/BankedClozeQuestion.vue

@@ -0,0 +1,115 @@
+<template>
+  <div class="banked-cloze-question nested-question">
+    <div class="ep-question-title">
+      <rich-text :text-json="question.body"></rich-text>
+    </div>
+    <div class="ep-question-body">
+      <div
+        v-for="(option, optionIndex) in question.options"
+        :key="optionIndex"
+        class="ep-question-option"
+      >
+        <div class="ep-question-option-check">
+          {{ (option.number - 1) | optionOrderWordFilter }}
+        </div>
+        <rich-text :text-json="option.body"></rich-text>
+      </div>
+    </div>
+
+    <el-form ref="modalFormComp" :model="modalForm" label-width="100px">
+      <el-form-item label="答题模式">
+        <el-select v-model="matchingMode">
+          <el-option
+            v-for="item in matchingModes"
+            :key="item.value"
+            :label="item.label"
+            :value="item.value"
+          >
+          </el-option>
+        </el-select>
+      </el-form-item>
+    </el-form>
+
+    <el-collapse v-model="activeNames">
+      <el-collapse-item
+        v-for="(subq, index) in question.subQuestions"
+        :key="subq.questionKey"
+        :name="subq.questionKey"
+      >
+        <div slot="title" class="subq-header">
+          <h3>第{{ index + 1 }}小题</h3>
+        </div>
+
+        <match-question
+          ref="MatchQuestion"
+          :question="subq"
+          :parent-question="question"
+        ></match-question>
+      </el-collapse-item>
+    </el-collapse>
+  </div>
+</template>
+
+<script>
+import MatchQuestion from "./MatchQuestion.vue";
+
+export default {
+  name: "BankedClozeQuestion",
+  components: { MatchQuestion },
+  props: {
+    question: {
+      type: Object,
+      default() {
+        return {};
+      },
+    },
+  },
+  data() {
+    return {
+      matchingMode: 1,
+      activeNames: [],
+      matchingModes: [
+        { label: "单用", value: 1 },
+        { label: "复用", value: 2 },
+      ],
+    };
+  },
+  computed: {
+    IS_BANKED_CLOZE() {
+      return this.modalForm.questionType === "BANKED_CLOZE";
+    },
+  },
+  created() {},
+  methods: {
+    async validate() {
+      let errorQuestionIndexs = [];
+      for (let i = 0; i < this.$refs.MatchQuestion.length; i++) {
+        const compInst = this.$refs.MatchQuestion[i];
+        const res = await compInst.validate().catch(() => {});
+        if (!res) {
+          errorQuestionIndexs.push(i + 1);
+        }
+      }
+      if (errorQuestionIndexs.length) {
+        this.$message.error(
+          `请完成第${errorQuestionIndexs.join()}小题的编辑!`
+        );
+        return Promise.reject();
+      }
+
+      return true;
+    },
+    getData() {
+      let data = {
+        ...this.question,
+        quesParam: { matchingMode: this.matchingMode },
+      };
+
+      data.subQuestions = this.$refs.MatchQuestion.map((compInst) =>
+        compInst.getData()
+      );
+      return data;
+    },
+  },
+};
+</script>

+ 101 - 0
src/modules/question/components/import-edit/BooleanQuestion.vue

@@ -0,0 +1,101 @@
+<template>
+  <div class="boolean-question">
+    <div class="ep-question-title">
+      <rich-text :text-json="question.body"></rich-text>
+    </div>
+    <div class="ep-question-props">
+      <el-form
+        ref="modalFormComp"
+        :model="modalForm"
+        :rules="rules"
+        label-width="100px"
+      >
+        <el-form-item prop="answer" label="答案">
+          <el-radio-group v-model="modalForm.answer" @change="answerChange">
+            <el-radio
+              v-for="option in answerOptions"
+              :key="option.value"
+              :label="option.value"
+            >
+              {{ option.label }}
+            </el-radio>
+          </el-radio-group>
+        </el-form-item>
+        <el-form-item label="答案解析">
+          <v-editor
+            v-model="modalForm.answerAnalysis"
+            :enable-audio="false"
+          ></v-editor>
+        </el-form-item>
+      </el-form>
+      <question-info-edit
+        ref="QuestionInfoEdit"
+        :question="modalForm"
+        @change="questionInfoChange"
+      ></question-info-edit>
+    </div>
+  </div>
+</template>
+
+<script>
+import { getInitQuestionModel } from "./model";
+import QuestionInfoEdit from "../QuestionInfoEdit.vue";
+
+export default {
+  name: "BooleanQuestion",
+  components: { QuestionInfoEdit },
+  props: {
+    question: {
+      type: Object,
+      default() {
+        return {};
+      },
+    },
+  },
+  data() {
+    return {
+      modalForm: {},
+      answerOptions: [
+        {
+          value: "false",
+          label: "错误",
+        },
+        {
+          value: "true",
+          label: "正确",
+        },
+      ],
+      rules: {
+        answer: [
+          {
+            required: true,
+            message: "请设置答案",
+            trigger: "change",
+          },
+        ],
+      },
+    };
+  },
+  created() {
+    this.initData();
+  },
+  methods: {
+    initData() {
+      this.modalForm = this.$objAssign(getInitQuestionModel(), this.question);
+    },
+    answerChange() {
+      this.$refs.modalFormComp.validateField(`answer`, () => {});
+    },
+    questionInfoChange(questionInfo) {
+      this.modalForm = Object.assign({}, this.modalForm, questionInfo);
+    },
+    validate() {
+      return this.$refs.modalFormComp.validate();
+    },
+    getData() {
+      let data = Object.assign({}, this.question, this.modalForm);
+      return data;
+    },
+  },
+};
+</script>

+ 94 - 0
src/modules/question/components/import-edit/FillBlankQuestion.vue

@@ -0,0 +1,94 @@
+<template>
+  <div class="fill-blank-question">
+    <div class="ep-question-title">
+      <rich-text :text-json="question.body"></rich-text>
+    </div>
+    <div class="ep-question-props">
+      <el-form ref="modalFormComp" :model="modalForm" label-width="100px">
+        <el-form-item label="答案"></el-form-item>
+        <el-form-item
+          v-for="(answer, oindex) in modalForm.answer"
+          :key="oindex"
+        >
+          <div class="question-edit-option">
+            <div class="option-check">({{ oindex + 1 }})</div>
+            <div class="option-body">
+              <v-editor
+                v-model="answer.body"
+                :enable-audio="false"
+                @change="() => answerBodyChange(oindex)"
+              ></v-editor>
+            </div>
+          </div>
+        </el-form-item>
+        <el-form-item label="答案解析">
+          <v-editor
+            v-model="modalForm.answerAnalysis"
+            :enable-audio="false"
+          ></v-editor>
+        </el-form-item>
+      </el-form>
+      <question-info-edit
+        ref="QuestionInfoEdit"
+        :question="modalForm"
+        @change="questionInfoChange"
+      ></question-info-edit>
+    </div>
+  </div>
+</template>
+
+<script>
+import { getInitQuestionModel } from "../model/questionModel";
+import QuestionInfoEdit from "../QuestionInfoEdit.vue";
+
+export default {
+  name: "FillBlankQuestion",
+  components: { QuestionInfoEdit },
+  props: {
+    question: {
+      type: Object,
+      default() {
+        return {};
+      },
+    },
+  },
+  data() {
+    return {
+      modalForm: {},
+    };
+  },
+  created() {
+    this.initData();
+  },
+  methods: {
+    initData() {
+      this.modalForm = this.$objAssign(getInitQuestionModel(), this.question);
+      this.modalForm.answer = [];
+      if (!this.question.body || !this.question.body.sections) return;
+      this.question.body.sections.forEach((section) => {
+        section.blocks.forEach((block) => {
+          if (block.type === "cloze")
+            this.modalForm.answer.push({ body: { sections: [] } });
+        });
+      });
+    },
+    questionInfoChange(questionInfo) {
+      this.modalForm = Object.assign({}, this.modalForm, questionInfo);
+    },
+    validate() {
+      return Promise.resolve(true);
+    },
+    getData() {
+      let data = Object.assign({}, this.question, this.modalForm);
+      data.answer = data.answer.map((item, index) => {
+        return {
+          ...item.body,
+          index,
+        };
+      });
+      data.answer = JSON.stringify(data.answer);
+      return data;
+    },
+  },
+};
+</script>

+ 116 - 0
src/modules/question/components/import-edit/MatchQuestion.vue

@@ -0,0 +1,116 @@
+<template>
+  <div class="match-question">
+    <div v-if="showQuesBody" class="ep-question-title">
+      <rich-text :text-json="question.body"></rich-text>
+    </div>
+    <div class="ep-question-props">
+      <el-form
+        ref="modalFormComp"
+        :model="modalForm"
+        :rules="rules"
+        label-width="100px"
+      >
+        <el-form-item prop="answer" label="答案">
+          <el-radio-group v-model="quesAnswer" @change="answerChange">
+            <el-radio-button
+              v-for="option in parentQuestion.options"
+              :key="option.number"
+              :label="option.number"
+            >
+              {{ (option.number - 1) | optionOrderWordFilter }}
+            </el-radio-button>
+          </el-radio-group>
+        </el-form-item>
+        <el-form-item label="答案解析">
+          <v-editor
+            v-model="modalForm.answerAnalysis"
+            :enable-audio="false"
+          ></v-editor>
+        </el-form-item>
+      </el-form>
+      <question-info-edit
+        ref="QuestionInfoEdit"
+        :question="modalForm"
+        @change="questionInfoChange"
+      ></question-info-edit>
+    </div>
+  </div>
+</template>
+
+<script>
+import QuestionInfoEdit from "../QuestionInfoEdit.vue";
+import { getMatchQuestionModel } from "../model/questionModel";
+
+export default {
+  name: "MatchQuestion",
+  components: { QuestionInfoEdit },
+  props: {
+    question: {
+      type: Object,
+      default() {
+        return {};
+      },
+    },
+    parentQuestion: {
+      type: Object,
+      default() {
+        return {
+          options: [],
+          questionType: "",
+        };
+      },
+    },
+  },
+  data() {
+    return {
+      modalForm: {},
+      quesAnswer: null,
+      rules: {
+        answer: [
+          {
+            validator: (rule, value, callback) => {
+              if (!value || !value.length) {
+                return callback(new Error(`请设置答案`));
+              }
+              callback();
+            },
+            trigger: "change",
+          },
+        ],
+      },
+    };
+  },
+  computed: {
+    IS_PARAGRAPH_MATCHING() {
+      return this.parentQuestion.questionType === "PARAGRAPH_MATCHING";
+    },
+  },
+  created() {
+    this.initData();
+  },
+  methods: {
+    initData() {
+      this.modalForm = this.$objAssign(getMatchQuestionModel(), this.question);
+      this.modalForm.courseId = this.parentQuestion.courseId;
+      this.modalForm.answer = [];
+      this.quesAnswer = this.modalForm.answer[0] || null;
+    },
+    answerChange() {
+      this.modalForm.answer =
+        this.quesAnswer || this.quesAnswer === 0 ? [this.quesAnswer] : [];
+      this.$refs.modalFormComp.validateField(`answer`, () => {});
+    },
+    questionInfoChange(questionInfo) {
+      this.modalForm = Object.assign({}, this.modalForm, questionInfo);
+    },
+    validate() {
+      return this.$refs.modalFormComp.validate();
+    },
+    getData() {
+      let data = { ...this.modalForm };
+      data.answer = JSON.stringify(data.answer);
+      return data;
+    },
+  },
+};
+</script>

+ 100 - 0
src/modules/question/components/import-edit/NestedQuestion.vue

@@ -0,0 +1,100 @@
+<template>
+  <div class="nested-question">
+    <div class="ep-question-title">
+      <rich-text :text-json="question.body"></rich-text>
+    </div>
+    <el-collapse v-model="activeNames" style="margin-top: 10px">
+      <el-collapse-item
+        v-for="(subq, index) in question.subQuestions"
+        :key="subq.questionKey"
+        :name="index"
+      >
+        <h3 slot="title">
+          第{{ index + 1 }}小题({{ subq.questionType | questionType }})
+        </h3>
+
+        <component
+          :is="getStructTypeComp(subq.questionType)"
+          ref="QuestionEditDetail"
+          :question="subq"
+          :show-ques-body="!IS_CLOZE"
+        ></component>
+      </el-collapse-item>
+    </el-collapse>
+  </div>
+</template>
+
+<script>
+import { STRUCT_TYPE_COMP_DICT } from "../model/questionModel";
+import BooleanQuestion from "./BooleanQuestion.vue";
+import FillBlankQuestion from "./FillBlankQuestion.vue";
+import SelectQuestion from "./SelectQuestion.vue";
+import TextAnswerQuestion from "./TextAnswerQuestion.vue";
+import { BASE_QUESTION_TYPES } from "@/constants/constants";
+
+export default {
+  name: "NestedQuestion",
+  components: {
+    FillBlankQuestion,
+    SelectQuestion,
+    TextAnswerQuestion,
+    BooleanQuestion,
+  },
+  props: {
+    question: {
+      type: Object,
+      default() {
+        return {};
+      },
+    },
+  },
+  data() {
+    return {
+      modalForm: {},
+      BASE_QUESTION_TYPES,
+      activeNames: [],
+    };
+  },
+  computed: {
+    IS_CLOZE() {
+      return this.question.questionType === "CLOZE";
+    },
+    IS_LISTENING_QUESTION() {
+      return this.question.questionType === "LISTENING_QUESTION";
+    },
+  },
+  created() {
+    this.initData();
+  },
+  methods: {
+    getStructTypeComp(questionType) {
+      return STRUCT_TYPE_COMP_DICT[questionType];
+    },
+    async validate() {
+      let errorQuestionIndexs = [];
+      for (let i = 0; i < this.$refs.QuestionEditDetail.length; i++) {
+        const compInst = this.$refs.QuestionEditDetail[i];
+        const res = await compInst.validate().catch(() => {});
+        if (!res) {
+          errorQuestionIndexs.push(i + 1);
+        }
+      }
+      if (errorQuestionIndexs.length) {
+        this.$message.error(
+          `请完成第${errorQuestionIndexs.join()}小题的编辑!`
+        );
+        return Promise.reject();
+      }
+
+      return true;
+    },
+    getData() {
+      let data = { ...this.question };
+      data.subQuestions = this.$refs.QuestionEditDetail.map((compInst) =>
+        compInst.getData()
+      );
+      return data;
+    },
+  },
+};
+</script>

+ 148 - 0
src/modules/question/components/import-edit/SelectQuestion.vue

@@ -0,0 +1,148 @@
+<template>
+  <div class="select-question">
+    <div v-if="showQuesBody" class="ep-question-title">
+      <rich-text :text-json="question.body"></rich-text>
+    </div>
+    <div class="ep-question-body">
+      <div
+        v-for="(option, optionIndex) in options"
+        :key="optionIndex"
+        class="ep-question-option"
+      >
+        <div class="ep-question-option-check">
+          <el-radio
+            v-if="IS_SIMPLE"
+            v-model="quesAnswer"
+            :label="option.number"
+            @change="answerChange"
+          >
+            {{ (option.number - 1) | optionOrderWordFilter }}
+          </el-radio>
+          <el-checkbox
+            v-else
+            v-model="option.isCorrect"
+            :label="option.number"
+            @change="answerChange"
+          >
+            {{ (option.number - 1) | optionOrderWordFilter }}
+          </el-checkbox>
+        </div>
+        <rich-text :text-json="option.body"></rich-text>
+      </div>
+    </div>
+    <div class="ep-question-props">
+      <el-form
+        ref="modalFormComp"
+        :model="modalForm"
+        :rules="rules"
+        label-width="100px"
+      >
+        <el-form-item prop="answer" label="答案">
+          <span>{{ answer }}</span>
+        </el-form-item>
+        <el-form-item label="答案解析">
+          <v-editor
+            v-model="modalForm.answerAnalysis"
+            :enable-audio="false"
+          ></v-editor>
+        </el-form-item>
+      </el-form>
+      <question-info-edit
+        ref="QuestionInfoEdit"
+        :question="modalForm"
+        @change="questionInfoChange"
+      ></question-info-edit>
+    </div>
+  </div>
+</template>
+
+<script>
+import QuestionInfoEdit from "../QuestionInfoEdit.vue";
+import { getInitQuestionModel } from "./model";
+
+export default {
+  name: "SelectQuestion",
+  components: { QuestionInfoEdit },
+  props: {
+    question: {
+      type: Object,
+      default() {
+        return {};
+      },
+    },
+    showQuesBody: {
+      type: Boolean,
+      default: true,
+    },
+  },
+  data() {
+    return {
+      modalForm: {},
+      quesAnswer: null,
+      options: [],
+      rules: {
+        answer: [
+          {
+            validator: (rule, value, callback) => {
+              if (!value || !value.length) {
+                return callback(new Error(`请设置答案`));
+              }
+              callback();
+            },
+            trigger: "change",
+          },
+        ],
+      },
+    };
+  },
+  computed: {
+    IS_SIMPLE() {
+      return this.question.questionType === "SINGLE_ANSWER_QUESTION";
+    },
+    answer() {
+      if (!this.quesAnswer) return "";
+      const quesAnswer = this.IS_SIMPLE ? [this.quesAnswer] : this.quesAnswer;
+      return quesAnswer
+        .map((value) => String.fromCharCode(64 + value))
+        .join("");
+    },
+  },
+  created() {
+    this.initData();
+  },
+  methods: {
+    initData() {
+      this.modalForm = this.$objAssign(getInitQuestionModel(), this.question);
+      this.quesAnswer = this.IS_SIMPLE ? null : [];
+      this.options = this.question.options.map((item) => {
+        let nitem = { ...item };
+        if (!this.IS_SIMPLE) nitem.isCorrect = false;
+        return nitem;
+      });
+    },
+    answerChange() {
+      if (this.IS_SIMPLE) {
+        this.modalForm.answer =
+          this.quesAnswer || this.quesAnswer === 0 ? [this.quesAnswer] : [];
+      } else {
+        this.quesAnswer = this.options
+          .filter((item) => item.isCorrect)
+          .map((item) => item.number);
+        this.modalForm.answer = this.quesAnswer;
+      }
+      this.$refs.modalFormComp.validateField(`answer`, () => {});
+    },
+    questionInfoChange(questionInfo) {
+      this.modalForm = Object.assign({}, this.modalForm, questionInfo);
+    },
+    validate() {
+      return this.$refs.modalFormComp.validate();
+    },
+    getData() {
+      let data = Object.assign({}, this.question, this.modalForm);
+      data.answer = JSON.stringify(this.modalForm.answer);
+      return data;
+    },
+  },
+};
+</script>

+ 81 - 0
src/modules/question/components/import-edit/TextAnswerQuestion.vue

@@ -0,0 +1,81 @@
+<template>
+  <div class="text-answer-question">
+    <div class="ep-question-title">
+      <rich-text :text-json="question.body"></rich-text>
+    </div>
+    <div class="ep-question-props">
+      <el-form ref="modalFormComp" :model="modalForm" label-width="100px">
+        <el-form-item label="答案">
+          <v-editor
+            v-model="quesAnswer"
+            :enable-audio="false"
+            @change="answerChange"
+          ></v-editor>
+        </el-form-item>
+        <el-form-item label="答案解析">
+          <v-editor
+            v-model="modalForm.answerAnalysis"
+            :enable-audio="false"
+          ></v-editor>
+        </el-form-item>
+      </el-form>
+      <question-info-edit
+        ref="QuestionInfoEdit"
+        :question="modalForm"
+        @change="questionInfoChange"
+      ></question-info-edit>
+    </div>
+  </div>
+</template>
+
+<script>
+import { getInitQuestionModel } from "../model/questionModel";
+import QuestionInfoEdit from "../QuestionInfoEdit.vue";
+
+export default {
+  name: "TextAnswerQuestion",
+  components: { QuestionInfoEdit },
+  props: {
+    question: {
+      type: Object,
+      default() {
+        return {};
+      },
+    },
+  },
+  data() {
+    return {
+      modalForm: {},
+      quesAnswer: null,
+    };
+  },
+  created() {
+    this.initData();
+  },
+  methods: {
+    initData() {
+      this.modalForm = this.$objAssign(getInitQuestionModel(), this.question);
+      this.modalForm.answer = this.modalForm.answer || [];
+    },
+    answerChange() {
+      this.modalForm.answer = [
+        {
+          index: 1,
+          ...this.quesAnswer,
+        },
+      ];
+    },
+    questionInfoChange(questionInfo) {
+      this.modalForm = Object.assign({}, this.modalForm, questionInfo);
+    },
+    validate() {
+      return Promise.resolve(true);
+    },
+    getData() {
+      let data = Object.assign({}, this.question, this.modalForm);
+      data.answer = JSON.stringify(data.answer);
+      return data;
+    },
+  },
+};
+</script>

+ 34 - 0
src/modules/question/components/import-edit/model.js

@@ -0,0 +1,34 @@
+export const getInitQuestionModel = () => {
+  return {
+    id: null,
+    editMode: "paper",
+    sourceDetailId: "",
+    courseId: "",
+    difficulty: "易",
+    quesProperties: [],
+    score: 0,
+    publicity: true,
+    control: { maxAnswerTime: 0 },
+    quesAnswer: null,
+  };
+};
+
+// 新的题型编码,全局通用
+// 1-单选,2-多选,3-判断,4-填空,5-问答
+// 100-阅读理解,101-完形填空,102-段落匹配,103-选词填空
+// Doc: https://doc.qmth.com.cn/pages/viewpage.action?pageId=23334762
+const typeQuestionTypes = {
+  1: "SINGLE_ANSWER_QUESTION",
+  2: "MULTIPLE_ANSWER_QUESTION",
+  3: "BOOL_ANSWER_QUESTION",
+  4: "FILL_BLANK_QUESTION",
+  5: "TEXT_ANSWER_QUESTION",
+  100: "READING_COMPREHENSION",
+  101: "CLOZE",
+  102: "PARAGRAPH_MATCHING",
+  103: "BANKED_CLOZE",
+};
+
+export function structTypeToQuestionType(type) {
+  return typeQuestionTypes[type];
+}

+ 2026 - 0
src/modules/question/datas/paperParseData.json

@@ -0,0 +1,2026 @@
+[
+  {
+    "number": 1,
+    "name": "A型题",
+    "questions": [
+      {
+        "number": 1,
+        "type": 1,
+        "body": {
+          "sections": [
+            {
+              "blocks": [
+                {
+                  "type": "text",
+                  "value": "已知核糖核酸酶分子由一条多肽链组成,那么它的最高级结构是:",
+                  "param": {}
+                }
+              ]
+            }
+          ]
+        },
+        "options": [
+          {
+            "number": 1,
+            "body": {
+              "sections": [
+                {
+                  "blocks": [
+                    {
+                      "type": "text",
+                      "value": "一级结构    ",
+                      "param": {}
+                    }
+                  ]
+                }
+              ]
+            }
+          },
+          {
+            "number": 2,
+            "body": {
+              "sections": [
+                {
+                  "blocks": [
+                    {
+                      "type": "text",
+                      "value": "二级结构   ",
+                      "param": {}
+                    }
+                  ]
+                }
+              ]
+            }
+          },
+          {
+            "number": 3,
+            "body": {
+              "sections": [
+                {
+                  "blocks": [
+                    {
+                      "type": "text",
+                      "value": "三级结构   ",
+                      "param": {}
+                    }
+                  ]
+                }
+              ]
+            }
+          },
+          {
+            "number": 4,
+            "body": {
+              "sections": [
+                {
+                  "blocks": [
+                    {
+                      "type": "text",
+                      "value": "四级结构",
+                      "param": {}
+                    }
+                  ]
+                }
+              ]
+            }
+          }
+        ],
+        "subQuestions": [],
+        "answer": {
+          "sections": []
+        },
+        "structType": 1
+      },
+      {
+        "number": 2,
+        "type": 1,
+        "body": {
+          "sections": [
+            {
+              "blocks": [
+                {
+                  "type": "text",
+                  "value": "Tm是指DNA双链解开多少时的环境温度?",
+                  "param": {}
+                }
+              ]
+            }
+          ]
+        },
+        "options": [
+          {
+            "number": 1,
+            "body": {
+              "sections": [
+                {
+                  "blocks": [
+                    {
+                      "type": "text",
+                      "value": "20%    ",
+                      "param": {}
+                    }
+                  ]
+                }
+              ]
+            }
+          },
+          {
+            "number": 2,
+            "body": {
+              "sections": [
+                {
+                  "blocks": [
+                    {
+                      "type": "text",
+                      "value": "30%    ",
+                      "param": {}
+                    }
+                  ]
+                }
+              ]
+            }
+          },
+          {
+            "number": 3,
+            "body": {
+              "sections": [
+                {
+                  "blocks": [
+                    {
+                      "type": "text",
+                      "value": "50%    ",
+                      "param": {}
+                    }
+                  ]
+                }
+              ]
+            }
+          },
+          {
+            "number": 4,
+            "body": {
+              "sections": [
+                {
+                  "blocks": [
+                    {
+                      "type": "text",
+                      "value": "80%",
+                      "param": {}
+                    }
+                  ]
+                }
+              ]
+            }
+          }
+        ],
+        "subQuestions": [],
+        "answer": {
+          "sections": []
+        },
+        "structType": 1
+      },
+      {
+        "number": 3,
+        "type": 1,
+        "body": {
+          "sections": [
+            {
+              "blocks": [
+                {
+                  "type": "text",
+                  "value": "LDH是由2条不同多肽链组成的四聚体,请问该酶有几种同工酶?",
+                  "param": {}
+                }
+              ]
+            }
+          ]
+        },
+        "options": [
+          {
+            "number": 1,
+            "body": {
+              "sections": [
+                {
+                  "blocks": [
+                    {
+                      "type": "text",
+                      "value": "2种   ",
+                      "param": {}
+                    }
+                  ]
+                }
+              ]
+            }
+          },
+          {
+            "number": 2,
+            "body": {
+              "sections": [
+                {
+                  "blocks": [
+                    {
+                      "type": "text",
+                      "value": "3种   ",
+                      "param": {}
+                    }
+                  ]
+                }
+              ]
+            }
+          },
+          {
+            "number": 3,
+            "body": {
+              "sections": [
+                {
+                  "blocks": [
+                    {
+                      "type": "text",
+                      "value": "4种   ",
+                      "param": {}
+                    }
+                  ]
+                }
+              ]
+            }
+          },
+          {
+            "number": 4,
+            "body": {
+              "sections": [
+                {
+                  "blocks": [
+                    {
+                      "type": "text",
+                      "value": "5种",
+                      "param": {}
+                    }
+                  ]
+                }
+              ]
+            }
+          }
+        ],
+        "subQuestions": [],
+        "answer": {
+          "sections": []
+        },
+        "structType": 1
+      },
+      {
+        "number": 4,
+        "type": 1,
+        "body": {
+          "sections": [
+            {
+              "blocks": [
+                {
+                  "type": "text",
+                  "value": "糖在体内的储存形式是",
+                  "param": {}
+                }
+              ]
+            }
+          ]
+        },
+        "options": [
+          {
+            "number": 1,
+            "body": {
+              "sections": [
+                {
+                  "blocks": [
+                    {
+                      "type": "text",
+                      "value": "葡萄糖   ",
+                      "param": {}
+                    }
+                  ]
+                }
+              ]
+            }
+          },
+          {
+            "number": 2,
+            "body": {
+              "sections": [
+                {
+                  "blocks": [
+                    {
+                      "type": "text",
+                      "value": "核糖  ",
+                      "param": {}
+                    }
+                  ]
+                }
+              ]
+            }
+          },
+          {
+            "number": 3,
+            "body": {
+              "sections": [
+                {
+                  "blocks": [
+                    {
+                      "type": "text",
+                      "value": "磷酸丙糖   ",
+                      "param": {}
+                    }
+                  ]
+                }
+              ]
+            }
+          },
+          {
+            "number": 4,
+            "body": {
+              "sections": [
+                {
+                  "blocks": [
+                    {
+                      "type": "text",
+                      "value": "糖原 ",
+                      "param": {}
+                    }
+                  ]
+                }
+              ]
+            }
+          }
+        ],
+        "subQuestions": [],
+        "answer": {
+          "sections": []
+        },
+        "structType": 1
+      },
+      {
+        "number": 5,
+        "type": 1,
+        "body": {
+          "sections": [
+            {
+              "blocks": [
+                {
+                  "type": "text",
+                  "value": "体内CO2来自:",
+                  "param": {}
+                }
+              ]
+            }
+          ]
+        },
+        "options": [
+          {
+            "number": 1,
+            "body": {
+              "sections": [
+                {
+                  "blocks": [
+                    {
+                      "type": "text",
+                      "value": "碳原子被氧原子氧 ",
+                      "param": {}
+                    }
+                  ]
+                }
+              ]
+            }
+          },
+          {
+            "number": 2,
+            "body": {
+              "sections": [
+                {
+                  "blocks": [
+                    {
+                      "type": "text",
+                      "value": "呼吸链的氧化还原过程 ",
+                      "param": {}
+                    }
+                  ]
+                }
+              ]
+            }
+          },
+          {
+            "number": 3,
+            "body": {
+              "sections": [
+                {
+                  "blocks": [
+                    {
+                      "type": "text",
+                      "value": "有机酸的脱羧 ",
+                      "param": {}
+                    }
+                  ]
+                }
+              ]
+            }
+          },
+          {
+            "number": 4,
+            "body": {
+              "sections": [
+                {
+                  "blocks": [
+                    {
+                      "type": "text",
+                      "value": "糖原的分解",
+                      "param": {}
+                    }
+                  ]
+                }
+              ]
+            }
+          }
+        ],
+        "subQuestions": [],
+        "answer": {
+          "sections": []
+        },
+        "structType": 1
+      },
+      {
+        "number": 6,
+        "type": 1,
+        "body": {
+          "sections": [
+            {
+              "blocks": [
+                {
+                  "type": "text",
+                  "value": "治疗痛风症有效的别嘌呤醇可抑制:",
+                  "param": {}
+                }
+              ]
+            }
+          ]
+        },
+        "options": [
+          {
+            "number": 1,
+            "body": {
+              "sections": [
+                {
+                  "blocks": [
+                    {
+                      "type": "text",
+                      "value": "黄嘌呤氧化酶  ",
+                      "param": {}
+                    }
+                  ]
+                }
+              ]
+            }
+          },
+          {
+            "number": 2,
+            "body": {
+              "sections": [
+                {
+                  "blocks": [
+                    {
+                      "type": "text",
+                      "value": "腺苷脱氨酶   ",
+                      "param": {}
+                    }
+                  ]
+                }
+              ]
+            }
+          },
+          {
+            "number": 3,
+            "body": {
+              "sections": [
+                {
+                  "blocks": [
+                    {
+                      "type": "text",
+                      "value": "尿酸氧化酶   ",
+                      "param": {}
+                    }
+                  ]
+                }
+              ]
+            }
+          },
+          {
+            "number": 4,
+            "body": {
+              "sections": [
+                {
+                  "blocks": [
+                    {
+                      "type": "text",
+                      "value": "鸟嘌呤脱氨酶",
+                      "param": {}
+                    }
+                  ]
+                }
+              ]
+            }
+          }
+        ],
+        "subQuestions": [],
+        "answer": {
+          "sections": []
+        },
+        "structType": 1
+      },
+      {
+        "number": 7,
+        "type": 1,
+        "body": {
+          "sections": [
+            {
+              "blocks": [
+                {
+                  "type": "text",
+                  "value": "DNA复制过程中,不需要下列哪一种酶?",
+                  "param": {}
+                }
+              ]
+            }
+          ]
+        },
+        "options": [
+          {
+            "number": 1,
+            "body": {
+              "sections": [
+                {
+                  "blocks": [
+                    {
+                      "type": "text",
+                      "value": "引物酶    ",
+                      "param": {}
+                    }
+                  ]
+                }
+              ]
+            }
+          },
+          {
+            "number": 2,
+            "body": {
+              "sections": [
+                {
+                  "blocks": [
+                    {
+                      "type": "text",
+                      "value": "解旋酶    ",
+                      "param": {}
+                    }
+                  ]
+                }
+              ]
+            }
+          },
+          {
+            "number": 3,
+            "body": {
+              "sections": [
+                {
+                  "blocks": [
+                    {
+                      "type": "text",
+                      "value": "核酶   ",
+                      "param": {}
+                    }
+                  ]
+                }
+              ]
+            }
+          },
+          {
+            "number": 4,
+            "body": {
+              "sections": [
+                {
+                  "blocks": [
+                    {
+                      "type": "text",
+                      "value": "DNA聚合酶",
+                      "param": {}
+                    }
+                  ]
+                }
+              ]
+            }
+          }
+        ],
+        "subQuestions": [],
+        "answer": {
+          "sections": []
+        },
+        "structType": 1
+      },
+      {
+        "number": 8,
+        "type": 1,
+        "body": {
+          "sections": [
+            {
+              "blocks": [
+                {
+                  "type": "text",
+                  "value": "DNA上某段碱基顺序为5'-ACTAGTCAG-3',转录后的mRNA上相应的碱基顺序为:",
+                  "param": {}
+                }
+              ]
+            }
+          ]
+        },
+        "options": [
+          {
+            "number": 1,
+            "body": {
+              "sections": [
+                {
+                  "blocks": [
+                    {
+                      "type": "text",
+                      "value": "5'-TGATCAGTC-3'      ",
+                      "param": {}
+                    }
+                  ]
+                }
+              ]
+            }
+          },
+          {
+            "number": 2,
+            "body": {
+              "sections": [
+                {
+                  "blocks": [
+                    {
+                      "type": "text",
+                      "value": "5'-UGAUCAGUC-3' ",
+                      "param": {}
+                    }
+                  ]
+                }
+              ]
+            }
+          },
+          {
+            "number": 3,
+            "body": {
+              "sections": [
+                {
+                  "blocks": [
+                    {
+                      "type": "text",
+                      "value": "5'-CUGACUAGU-3'     ",
+                      "param": {}
+                    }
+                  ]
+                }
+              ]
+            }
+          },
+          {
+            "number": 4,
+            "body": {
+              "sections": [
+                {
+                  "blocks": [
+                    {
+                      "type": "text",
+                      "value": "5'-CTAGACTAG-3'",
+                      "param": {}
+                    }
+                  ]
+                }
+              ]
+            }
+          }
+        ],
+        "subQuestions": [],
+        "answer": {
+          "sections": []
+        },
+        "structType": 1
+      },
+      {
+        "number": 9,
+        "type": 1,
+        "body": {
+          "sections": [
+            {
+              "blocks": [
+                {
+                  "type": "text",
+                  "value": "作为蛋白质生物合成的模板是哪个物质?",
+                  "param": {}
+                }
+              ]
+            }
+          ]
+        },
+        "options": [
+          {
+            "number": 1,
+            "body": {
+              "sections": [
+                {
+                  "blocks": [
+                    {
+                      "type": "text",
+                      "value": "DNA    ",
+                      "param": {}
+                    }
+                  ]
+                }
+              ]
+            }
+          },
+          {
+            "number": 2,
+            "body": {
+              "sections": [
+                {
+                  "blocks": [
+                    {
+                      "type": "text",
+                      "value": "tRNA    ",
+                      "param": {}
+                    }
+                  ]
+                }
+              ]
+            }
+          },
+          {
+            "number": 3,
+            "body": {
+              "sections": [
+                {
+                  "blocks": [
+                    {
+                      "type": "text",
+                      "value": "rRNA    ",
+                      "param": {}
+                    }
+                  ]
+                }
+              ]
+            }
+          },
+          {
+            "number": 4,
+            "body": {
+              "sections": [
+                {
+                  "blocks": [
+                    {
+                      "type": "text",
+                      "value": "mRNA ",
+                      "param": {}
+                    }
+                  ]
+                }
+              ]
+            }
+          }
+        ],
+        "subQuestions": [],
+        "answer": {
+          "sections": []
+        },
+        "structType": 1
+      },
+      {
+        "number": 10,
+        "type": 1,
+        "body": {
+          "sections": [
+            {
+              "blocks": [
+                {
+                  "type": "text",
+                  "value": "不属于胆色素的物质:",
+                  "param": {}
+                }
+              ]
+            }
+          ]
+        },
+        "options": [
+          {
+            "number": 1,
+            "body": {
+              "sections": [
+                {
+                  "blocks": [
+                    {
+                      "type": "text",
+                      "value": "胆红素    ",
+                      "param": {}
+                    }
+                  ]
+                }
+              ]
+            }
+          },
+          {
+            "number": 2,
+            "body": {
+              "sections": [
+                {
+                  "blocks": [
+                    {
+                      "type": "text",
+                      "value": "血红素    ",
+                      "param": {}
+                    }
+                  ]
+                }
+              ]
+            }
+          },
+          {
+            "number": 3,
+            "body": {
+              "sections": [
+                {
+                  "blocks": [
+                    {
+                      "type": "text",
+                      "value": "胆绿素    ",
+                      "param": {}
+                    }
+                  ]
+                }
+              ]
+            }
+          },
+          {
+            "number": 4,
+            "body": {
+              "sections": [
+                {
+                  "blocks": [
+                    {
+                      "type": "text",
+                      "value": "胆素原",
+                      "param": {}
+                    }
+                  ]
+                }
+              ]
+            }
+          }
+        ],
+        "subQuestions": [],
+        "answer": {
+          "sections": []
+        },
+        "structType": 1
+      }
+    ]
+  },
+  {
+    "number": 2,
+    "name": "B型题",
+    "questions": [
+      {
+        "number": 11,
+        "type": 1,
+        "body": {
+          "sections": [
+            {
+              "blocks": [
+                {
+                  "type": "text",
+                  "value": "苹果酸脱氢酶的辅酶是:",
+                  "param": {}
+                }
+              ]
+            }
+          ]
+        },
+        "options": [],
+        "subQuestions": [],
+        "answer": {
+          "sections": []
+        },
+        "structType": 1
+      },
+      {
+        "number": 12,
+        "type": 1,
+        "body": {
+          "sections": [
+            {
+              "blocks": [
+                {
+                  "type": "text",
+                  "value": "6-磷酸葡萄糖脱氢酶的辅酶是:",
+                  "param": {}
+                }
+              ]
+            }
+          ]
+        },
+        "options": [
+          {
+            "number": 1,
+            "body": {
+              "sections": [
+                {
+                  "blocks": [
+                    {
+                      "type": "text",
+                      "value": "琥珀酰CoA→琥珀酸    ",
+                      "param": {}
+                    }
+                  ]
+                }
+              ]
+            }
+          },
+          {
+            "number": 2,
+            "body": {
+              "sections": [
+                {
+                  "blocks": [
+                    {
+                      "type": "text",
+                      "value": "α-酮戊二酸→琥珀酰CoA",
+                      "param": {}
+                    }
+                  ]
+                }
+              ]
+            }
+          },
+          {
+            "number": 3,
+            "body": {
+              "sections": [
+                {
+                  "blocks": [
+                    {
+                      "type": "text",
+                      "value": "琥珀酸→延胡索酸       ",
+                      "param": {}
+                    }
+                  ]
+                }
+              ]
+            }
+          },
+          {
+            "number": 4,
+            "body": {
+              "sections": [
+                {
+                  "blocks": [
+                    {
+                      "type": "text",
+                      "value": "草酰乙酸+乙酰辅酶A→柠檬酸",
+                      "param": {}
+                    }
+                  ]
+                }
+              ]
+            }
+          }
+        ],
+        "subQuestions": [],
+        "answer": {
+          "sections": []
+        },
+        "structType": 1
+      },
+      {
+        "number": 13,
+        "type": 1,
+        "body": {
+          "sections": [
+            {
+              "blocks": [
+                {
+                  "type": "text",
+                  "value": "三羧酸循环中第一步反应是:",
+                  "param": {}
+                }
+              ]
+            }
+          ]
+        },
+        "options": [],
+        "subQuestions": [],
+        "answer": {
+          "sections": []
+        },
+        "structType": 1
+      },
+      {
+        "number": 14,
+        "type": 1,
+        "body": {
+          "sections": [
+            {
+              "blocks": [
+                {
+                  "type": "text",
+                  "value": "上述哪个反应以FAD为受氢体?",
+                  "param": {}
+                }
+              ]
+            }
+          ]
+        },
+        "options": [],
+        "subQuestions": [],
+        "answer": {
+          "sections": []
+        },
+        "structType": 1
+      },
+      {
+        "number": 15,
+        "type": 1,
+        "body": {
+          "sections": [
+            {
+              "blocks": [
+                {
+                  "type": "text",
+                  "value": "催化上述哪个反应的酶是多酶复合体?",
+                  "param": {}
+                }
+              ]
+            }
+          ]
+        },
+        "options": [],
+        "subQuestions": [],
+        "answer": {
+          "sections": []
+        },
+        "structType": 1
+      }
+    ]
+  },
+  {
+    "number": 3,
+    "name": "X型题",
+    "questions": [
+      {
+        "number": 16,
+        "type": 2,
+        "body": {
+          "sections": [
+            {
+              "blocks": [
+                {
+                  "type": "text",
+                  "value": "蛋白质的二级结构包括:",
+                  "param": {}
+                }
+              ]
+            },
+            {
+              "blocks": [
+                {
+                  "type": "text",
+                  "value": "A、α-螺旋   B、β-折叠   C、β-转角   D、不规则卷曲",
+                  "param": {}
+                }
+              ]
+            }
+          ]
+        },
+        "options": [],
+        "subQuestions": [],
+        "answer": {
+          "sections": []
+        },
+        "structType": 2
+      },
+      {
+        "number": 17,
+        "type": 2,
+        "body": {
+          "sections": [
+            {
+              "blocks": [
+                {
+                  "type": "text",
+                  "value": "关于三羧酸循环的叙述正确的是:",
+                  "param": {}
+                }
+              ]
+            },
+            {
+              "blocks": [
+                {
+                  "type": "text",
+                  "value": "A、循环一周有2次底物水平磷酸化    B、循环一周可产生10个ATP",
+                  "param": {}
+                }
+              ]
+            },
+            {
+              "blocks": [
+                {
+                  "type": "text",
+                  "value": "C、三羧酸循环过程是可逆的          D、循环一周可产生2个CO2",
+                  "param": {}
+                }
+              ]
+            }
+          ]
+        },
+        "options": [],
+        "subQuestions": [],
+        "answer": {
+          "sections": []
+        },
+        "structType": 2
+      },
+      {
+        "number": 18,
+        "type": 2,
+        "body": {
+          "sections": [
+            {
+              "blocks": [
+                {
+                  "type": "text",
+                  "value": "胆固醇在体内除构成膜的组分外的主要代谢去路包括:",
+                  "param": {}
+                }
+              ]
+            },
+            {
+              "blocks": [
+                {
+                  "type": "text",
+                  "value": "A、转变为胆汁酸           B、转变为VD3    ",
+                  "param": {}
+                }
+              ]
+            },
+            {
+              "blocks": [
+                {
+                  "type": "text",
+                  "value": "C、转变为类固醇激素       D、转变为胆红素 ",
+                  "param": {}
+                }
+              ]
+            }
+          ]
+        },
+        "options": [],
+        "subQuestions": [],
+        "answer": {
+          "sections": []
+        },
+        "structType": 2
+      },
+      {
+        "number": 19,
+        "type": 2,
+        "body": {
+          "sections": [
+            {
+              "blocks": [
+                {
+                  "type": "text",
+                  "value": "生成一碳单位的氨基酸有:",
+                  "param": {}
+                }
+              ]
+            },
+            {
+              "blocks": [
+                {
+                  "type": "text",
+                  "value": "A、甘氨酸   B、丝氨酸   C、组氨酸   D、色氨酸",
+                  "param": {}
+                }
+              ]
+            }
+          ]
+        },
+        "options": [],
+        "subQuestions": [],
+        "answer": {
+          "sections": []
+        },
+        "structType": 2
+      },
+      {
+        "number": 20,
+        "type": 2,
+        "body": {
+          "sections": [
+            {
+              "blocks": [
+                {
+                  "type": "text",
+                  "value": "关于DNA复制的说法正确的是:",
+                  "param": {}
+                }
+              ]
+            },
+            {
+              "blocks": [
+                {
+                  "type": "text",
+                  "value": "A、它是半保留复制        B、它是半不连续复制   ",
+                  "param": {}
+                }
+              ]
+            },
+            {
+              "blocks": [
+                {
+                  "type": "text",
+                  "value": "C、复制有特定的起始位点  D、是双向复制",
+                  "param": {}
+                }
+              ]
+            },
+            {
+              "blocks": []
+            }
+          ]
+        },
+        "options": [],
+        "subQuestions": [],
+        "answer": {
+          "sections": []
+        },
+        "structType": 2
+      }
+    ]
+  },
+  {
+    "number": 2,
+    "name": "填空题(每空2分,共20分)",
+    "questions": [
+      {
+        "number": 1,
+        "type": 4,
+        "body": {
+          "sections": [
+            {
+              "blocks": [
+                {
+                  "type": "cloze",
+                  "value": 1
+                },
+                {
+                  "type": "cloze",
+                  "value": 2
+                }
+              ]
+            }
+          ]
+        },
+        "options": [],
+        "subQuestions": [],
+        "answer": {
+          "sections": []
+        },
+        "structType": 4
+      },
+      {
+        "number": 2,
+        "type": 4,
+        "body": {
+          "sections": [
+            {
+              "blocks": [
+                {
+                  "type": "cloze",
+                  "value": 1
+                },
+                {
+                  "type": "cloze",
+                  "value": 2
+                }
+              ]
+            }
+          ]
+        },
+        "options": [],
+        "subQuestions": [],
+        "answer": {
+          "sections": []
+        },
+        "structType": 4
+      },
+      {
+        "number": 3,
+        "type": 4,
+        "body": {
+          "sections": [
+            {
+              "blocks": [
+                {
+                  "type": "cloze",
+                  "value": 1
+                }
+              ]
+            }
+          ]
+        },
+        "options": [],
+        "subQuestions": [],
+        "answer": {
+          "sections": []
+        },
+        "structType": 4
+      },
+      {
+        "number": 4,
+        "type": 4,
+        "body": {
+          "sections": [
+            {
+              "blocks": [
+                {
+                  "type": "cloze",
+                  "value": 1
+                }
+              ]
+            }
+          ]
+        },
+        "options": [],
+        "subQuestions": [],
+        "answer": {
+          "sections": []
+        },
+        "structType": 4
+      },
+      {
+        "number": 5,
+        "type": 4,
+        "body": {
+          "sections": [
+            {
+              "blocks": [
+                {
+                  "type": "cloze",
+                  "value": 1
+                }
+              ]
+            }
+          ]
+        },
+        "options": [],
+        "subQuestions": [],
+        "answer": {
+          "sections": []
+        },
+        "structType": 4
+      },
+      {
+        "number": 6,
+        "type": 4,
+        "body": {
+          "sections": [
+            {
+              "blocks": [
+                {
+                  "type": "cloze",
+                  "value": 1
+                }
+              ]
+            }
+          ]
+        },
+        "options": [],
+        "subQuestions": [],
+        "answer": {
+          "sections": []
+        },
+        "structType": 4
+      },
+      {
+        "number": 7,
+        "type": 4,
+        "body": {
+          "sections": [
+            {
+              "blocks": [
+                {
+                  "type": "cloze",
+                  "value": 1
+                }
+              ]
+            }
+          ]
+        },
+        "options": [],
+        "subQuestions": [],
+        "answer": {
+          "sections": []
+        },
+        "structType": 4
+      },
+      {
+        "number": 8,
+        "type": 4,
+        "body": {
+          "sections": [
+            {
+              "blocks": [
+                {
+                  "type": "cloze",
+                  "value": 1
+                }
+              ]
+            },
+            {
+              "blocks": []
+            }
+          ]
+        },
+        "options": [],
+        "subQuestions": [],
+        "answer": {
+          "sections": []
+        },
+        "structType": 4
+      }
+    ]
+  },
+  {
+    "number": 3,
+    "name": "判断题(每小题",
+    "questions": [
+      {
+        "number": 1,
+        "type": 3,
+        "body": {
+          "sections": [
+            {
+              "blocks": [
+                {
+                  "type": "text",
+                  "value": "有功能的血红蛋白是具有三级结构的蛋白。(       )",
+                  "param": {}
+                }
+              ]
+            }
+          ]
+        },
+        "options": [],
+        "subQuestions": [],
+        "answer": {
+          "sections": []
+        },
+        "structType": 3
+      },
+      {
+        "number": 2,
+        "type": 3,
+        "body": {
+          "sections": [
+            {
+              "blocks": [
+                {
+                  "type": "text",
+                  "value": "基因的化学本质是蛋白质。(       )",
+                  "param": {}
+                }
+              ]
+            }
+          ]
+        },
+        "options": [],
+        "subQuestions": [],
+        "answer": {
+          "sections": []
+        },
+        "structType": 3
+      },
+      {
+        "number": 3,
+        "type": 3,
+        "body": {
+          "sections": [
+            {
+              "blocks": [
+                {
+                  "type": "text",
+                  "value": "一种酶作用于多种底物时,其天然底物的Km值应该最大。(       )",
+                  "param": {}
+                }
+              ]
+            }
+          ]
+        },
+        "options": [],
+        "subQuestions": [],
+        "answer": {
+          "sections": []
+        },
+        "structType": 3
+      },
+      {
+        "number": 4,
+        "type": 3,
+        "body": {
+          "sections": [
+            {
+              "blocks": [
+                {
+                  "type": "text",
+                  "value": "磺胺药的抑菌作用机制是直接干扰人体核酸代谢。(       )",
+                  "param": {}
+                }
+              ]
+            }
+          ]
+        },
+        "options": [],
+        "subQuestions": [],
+        "answer": {
+          "sections": []
+        },
+        "structType": 3
+      },
+      {
+        "number": 5,
+        "type": 3,
+        "body": {
+          "sections": [
+            {
+              "blocks": [
+                {
+                  "type": "text",
+                  "value": "酶的必需基团都位于活性中心。(       )",
+                  "param": {}
+                }
+              ]
+            }
+          ]
+        },
+        "options": [],
+        "subQuestions": [],
+        "answer": {
+          "sections": []
+        },
+        "structType": 3
+      },
+      {
+        "number": 6,
+        "type": 3,
+        "body": {
+          "sections": [
+            {
+              "blocks": [
+                {
+                  "type": "text",
+                  "value": "三羧酸循环能将草酰乙酸彻底氧化。(       )",
+                  "param": {}
+                }
+              ]
+            }
+          ]
+        },
+        "options": [],
+        "subQuestions": [],
+        "answer": {
+          "sections": []
+        },
+        "structType": 3
+      },
+      {
+        "number": 7,
+        "type": 3,
+        "body": {
+          "sections": [
+            {
+              "blocks": [
+                {
+                  "type": "text",
+                  "value": "三羧酸循环是体内营养物质彻底氧化分解的共同通路。(       )",
+                  "param": {}
+                }
+              ]
+            }
+          ]
+        },
+        "options": [],
+        "subQuestions": [],
+        "answer": {
+          "sections": []
+        },
+        "structType": 3
+      },
+      {
+        "number": 8,
+        "type": 3,
+        "body": {
+          "sections": [
+            {
+              "blocks": [
+                {
+                  "type": "text",
+                  "value": "肝是糖原合成的唯一器官。(       )",
+                  "param": {}
+                }
+              ]
+            }
+          ]
+        },
+        "options": [],
+        "subQuestions": [],
+        "answer": {
+          "sections": []
+        },
+        "structType": 3
+      },
+      {
+        "number": 9,
+        "type": 3,
+        "body": {
+          "sections": [
+            {
+              "blocks": [
+                {
+                  "type": "text",
+                  "value": "嘌呤核苷酸从头合成途径最先合成的核苷酸是IMP。(       )",
+                  "param": {}
+                }
+              ]
+            }
+          ]
+        },
+        "options": [],
+        "subQuestions": [],
+        "answer": {
+          "sections": []
+        },
+        "structType": 3
+      },
+      {
+        "number": 10,
+        "type": 3,
+        "body": {
+          "sections": [
+            {
+              "blocks": [
+                {
+                  "type": "text",
+                  "value": "有毒物质经过肝脏的生物转化后溶解度均有所降低。(       )",
+                  "param": {}
+                }
+              ]
+            }
+          ]
+        },
+        "options": [],
+        "subQuestions": [],
+        "answer": {
+          "sections": []
+        },
+        "structType": 3
+      }
+    ]
+  },
+  {
+    "number": 4,
+    "name": "名词解释(每小题3分,共15分)",
+    "questions": [
+      {
+        "number": 1,
+        "type": 5,
+        "body": {
+          "sections": [
+            {
+              "blocks": [
+                {
+                  "type": "text",
+                  "value": "盐析 ",
+                  "param": {}
+                }
+              ]
+            },
+            {
+              "blocks": []
+            }
+          ]
+        },
+        "options": [],
+        "subQuestions": [],
+        "answer": {
+          "sections": []
+        },
+        "structType": 5
+      },
+      {
+        "number": 2,
+        "type": 5,
+        "body": {
+          "sections": [
+            {
+              "blocks": [
+                {
+                  "type": "text",
+                  "value": "呼吸链 ",
+                  "param": {}
+                }
+              ]
+            },
+            {
+              "blocks": []
+            }
+          ]
+        },
+        "options": [],
+        "subQuestions": [],
+        "answer": {
+          "sections": []
+        },
+        "structType": 5
+      },
+      {
+        "number": 3,
+        "type": 5,
+        "body": {
+          "sections": [
+            {
+              "blocks": [
+                {
+                  "type": "text",
+                  "value": "必需氨基酸",
+                  "param": {}
+                }
+              ]
+            },
+            {
+              "blocks": []
+            }
+          ]
+        },
+        "options": [],
+        "subQuestions": [],
+        "answer": {
+          "sections": []
+        },
+        "structType": 5
+      },
+      {
+        "number": 4,
+        "type": 5,
+        "body": {
+          "sections": [
+            {
+              "blocks": [
+                {
+                  "type": "text",
+                  "value": "半保留复制  ",
+                  "param": {}
+                }
+              ]
+            },
+            {
+              "blocks": []
+            },
+            {
+              "blocks": []
+            }
+          ]
+        },
+        "options": [],
+        "subQuestions": [],
+        "answer": {
+          "sections": []
+        },
+        "structType": 5
+      },
+      {
+        "number": 5,
+        "type": 5,
+        "body": {
+          "sections": [
+            {
+              "blocks": [
+                {
+                  "type": "text",
+                  "value": "模板链",
+                  "param": {}
+                }
+              ]
+            },
+            {
+              "blocks": [
+                {
+                  "type": "text",
+                  "value": " ",
+                  "param": {}
+                }
+              ]
+            },
+            {
+              "blocks": []
+            }
+          ]
+        },
+        "options": [],
+        "subQuestions": [],
+        "answer": {
+          "sections": []
+        },
+        "structType": 5
+      }
+    ]
+  },
+  {
+    "number": 5,
+    "name": "简答题(共30分)",
+    "questions": [
+      {
+        "number": 1,
+        "type": 5,
+        "body": {
+          "sections": [
+            {
+              "blocks": [
+                {
+                  "type": "text",
+                  "value": "与一般催化剂相比,酶催化作用的个性特征有哪些?(6分)",
+                  "param": {}
+                }
+              ]
+            },
+            {
+              "blocks": []
+            },
+            {
+              "blocks": []
+            },
+            {
+              "blocks": []
+            },
+            {
+              "blocks": []
+            },
+            {
+              "blocks": []
+            },
+            {
+              "blocks": []
+            },
+            {
+              "blocks": []
+            }
+          ]
+        },
+        "options": [],
+        "subQuestions": [],
+        "answer": {
+          "sections": []
+        },
+        "structType": 5
+      },
+      {
+        "number": 2,
+        "type": 5,
+        "body": {
+          "sections": [
+            {
+              "blocks": [
+                {
+                  "type": "text",
+                  "value": "写出糖无氧氧化的生理意义。(9分)",
+                  "param": {}
+                }
+              ]
+            },
+            {
+              "blocks": []
+            },
+            {
+              "blocks": []
+            },
+            {
+              "blocks": []
+            },
+            {
+              "blocks": []
+            },
+            {
+              "blocks": []
+            },
+            {
+              "blocks": []
+            },
+            {
+              "blocks": []
+            }
+          ]
+        },
+        "options": [],
+        "subQuestions": [],
+        "answer": {
+          "sections": []
+        },
+        "structType": 5
+      },
+      {
+        "number": 3,
+        "type": 5,
+        "body": {
+          "sections": [
+            {
+              "blocks": [
+                {
+                  "type": "text",
+                  "value": "写出酮体生成的部位、关键酶、原料及生理意义。(10分)",
+                  "param": {}
+                }
+              ]
+            },
+            {
+              "blocks": []
+            },
+            {
+              "blocks": []
+            },
+            {
+              "blocks": []
+            },
+            {
+              "blocks": []
+            },
+            {
+              "blocks": []
+            },
+            {
+              "blocks": []
+            },
+            {
+              "blocks": []
+            },
+            {
+              "blocks": []
+            },
+            {
+              "blocks": []
+            },
+            {
+              "blocks": []
+            }
+          ]
+        },
+        "options": [],
+        "subQuestions": [],
+        "answer": {
+          "sections": []
+        },
+        "structType": 5
+      },
+      {
+        "number": 4,
+        "type": 5,
+        "body": {
+          "sections": [
+            {
+              "blocks": [
+                {
+                  "type": "text",
+                  "value": "遗传密码的特点有哪些?(5分)",
+                  "param": {}
+                }
+              ]
+            },
+            {
+              "blocks": []
+            },
+            {
+              "blocks": []
+            },
+            {
+              "blocks": []
+            }
+          ]
+        },
+        "options": [],
+        "subQuestions": [],
+        "answer": {
+          "sections": []
+        },
+        "structType": 5
+      }
+    ]
+  }
+]

Файловите разлики са ограничени, защото са твърде много
+ 710 - 0
src/modules/question/datas/paperRichText.json


+ 4 - 0
src/modules/question/views/QuestionManage.vue

@@ -214,6 +214,8 @@
     <folder-question-manage-dialog
       ref="FolderQuestionManageDialog"
     ></folder-question-manage-dialog>
+    <!-- QuestionImportEdit -->
+    <question-import-edit ref="QuestionImportEdit"></question-import-edit>
   </div>
 </template>
 
@@ -232,6 +234,7 @@ import QuestionEditDialog from "../components/QuestionEditDialog.vue";
 import QuestionPreviewDialog from "../components/QuestionPreviewDialog.vue";
 import FolderQuestionManageDialog from "../components/FolderQuestionManageDialog.vue";
 import PropertyTreeSelect from "../components/PropertyTreeSelect.vue";
+import QuestionImportEdit from "../components/QuestionImportEdit.vue";
 
 export default {
   name: "QuestionMamage",
@@ -244,6 +247,7 @@ export default {
     QuestionPreviewDialog,
     FolderQuestionManageDialog,
     PropertyTreeSelect,
+    QuestionImportEdit,
   },
   data() {
     return {

+ 18 - 0
src/plugins/utils.js

@@ -290,3 +290,21 @@ export function checkRichTextContentIsEmpty(cont) {
       .trim();
   }
 }
+
+export function numberToChinese(num) {
+  if (num >= 100 || num <= 0) return num + "";
+  const cnNums = "一二三四五六七八九十".split("");
+  if (num <= 10) return cnNums[num - 1];
+
+  return (num + "")
+    .split("")
+    .map((item) => item * 1)
+    .map((item, index) => {
+      if (index) {
+        return !item ? "" : cnNums[item - 1];
+      } else {
+        return item === 1 ? "" : cnNums[item - 1];
+      }
+    })
+    .join("十");
+}

Някои файлове не бяха показани, защото твърде много файлове са промени