zhangjie пре 2 година
родитељ
комит
be2bd4c902

+ 2 - 0
src/assets/styles/element-ui-costom.scss

@@ -7,9 +7,11 @@
       z-index: 9;
       background-color: #fff;
       border-bottom: 1px solid $--color-border;
+      padding: 15px;
     }
     .el-dialog__body {
       padding-top: 90px;
+      top: 0;
     }
   }
 }

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

@@ -561,7 +561,7 @@
     flex-shrink: 0;
   }
   .option-delete {
-    width: 60px;
+    padding-left: 20px;
     flex-grow: 0;
     flex-shrink: 0;
     text-align: center;
@@ -849,3 +849,27 @@
     font-size: 14px;
   }
 }
+
+// question-edit-dialog
+.question-edit-dialog {
+  .el-dialog__body {
+    bottom: 0;
+    background-color: $--color-background;
+  }
+  .el-dialog__footer {
+    display: none;
+  }
+  .el-dialog__header {
+    h2 {
+      display: inline-block;
+      margin-right: 20px;
+
+      + span {
+        margin-right: 20px;
+      }
+    }
+  }
+  .el-dialog__headerbtn {
+    display: none;
+  }
+}

+ 4 - 1
src/components/selection/CourseSelect.vue

@@ -27,7 +27,7 @@ export default {
   name: "CourseSelect",
   props: {
     value: {
-      type: String,
+      type: [String, Number],
       default: "",
     },
     options: { type: Array, default: () => [] },
@@ -50,6 +50,9 @@ export default {
       },
     },
   },
+  created() {
+    this.search("");
+  },
   methods: {
     async search(query) {
       this.loading = true;

+ 4 - 1
src/components/selection/PropertySelect.vue

@@ -27,7 +27,7 @@ export default {
   name: "PropertyNameSelect",
   props: {
     value: {
-      type: String,
+      type: [String, Number],
       default: "",
     },
     options: { type: Array, default: () => [] },
@@ -61,6 +61,9 @@ export default {
       }
     },
   },
+  created() {
+    this.search("");
+  },
   methods: {
     async search(query) {
       if (!this.courseId) {

+ 1 - 1
src/components/selection/PropertySubSelect.vue

@@ -26,7 +26,7 @@ export default {
   name: "PropertyNameSelect",
   props: {
     value: {
-      type: String,
+      type: [String, Number],
       default: "",
     },
     options: { type: Array, default: () => [] },

+ 1 - 1
src/components/selection/QuestionTypeSelect.vue

@@ -22,7 +22,7 @@ export default {
   name: "QuestionTypeSelect",
   props: {
     value: {
-      type: String,
+      type: [String, Number],
       default: "",
     },
     disabled: { type: Boolean, default: false },

+ 1 - 0
src/components/vEditor/components/answerPoint.js

@@ -35,4 +35,5 @@ export async function answerPointRebuild() {
     answerPoint.dataset.order = index + 1;
     answerPoint.src = getAnswerPointImg(index + 1);
   });
+  this.$emit("answer-point-changed", answerPoints.length);
 }

+ 69 - 19
src/modules/question/components/QuestionEditDialog.vue

@@ -1,18 +1,31 @@
 <template>
   <el-dialog
-    custom-class="side-dialog"
+    custom-class="side-dialog question-edit-dialog"
     :visible.sync="modalIsShow"
-    :title="title"
     :close-on-click-modal="false"
     :close-on-press-escape="false"
     append-to-body
     fullscreen
+    destroy-on-close
     @open="visibleChange"
   >
+    <div slot="title" class="box-justify">
+      <div>
+        <h2>{{ isEdit ? "编辑试题" : "创建试题" }}</h2>
+        <span>课程代码:{{ question.courseCode }}</span>
+        <span>课程名称:{{ question.courseName }}</span>
+      </div>
+      <div>
+        <el-button type="primary" @click="confirm">确定</el-button>
+        <el-button v-if="!isEdit" type="primary" @click="initData"
+          >继续出题</el-button
+        >
+        <el-button @click="cancel">取消</el-button>
+      </div>
+    </div>
     <div class="part-box question-edit">
-      <div class="question-type">
-        <div class="question-type-list">
-          <span>题型</span>
+      <el-form label-width="100px">
+        <el-form-item label="题型">
           <el-button
             v-for="item in QUESTION_TYPES"
             :key="item.code"
@@ -20,27 +33,31 @@
             @click="switchType(item)"
             >{{ item.name }}</el-button
           >
-        </div>
-        <p class="tips-info">
-          说明:如果是综合类试题(套题)可以选择题型为阅卷理解进行录入操作。
-        </p>
-      </div>
+          <p class="tips-info">
+            说明:如果是综合类试题(套题)可以选择题型为阅卷理解进行录入操作。
+          </p>
+        </el-form-item>
+      </el-form>
       <!-- question-body -->
       <component
         :is="structTypeComp"
+        :key="questionKey"
         ref="QuestionEditDetail"
-        :question="question"
+        :question="questionModel"
       ></component>
     </div>
-    <div slot="footer">
-      <el-button type="primary" @click="confirm">确定</el-button>
-      <el-button @click="cancel">取消</el-button>
-    </div>
+    <div slot="footer"></div>
   </el-dialog>
 </template>
 
 <script>
 import { QUESTION_TYPES } from "@/constants/constants";
+import { getInitQuestionModel } from "./model/questionModel";
+import BooleanQuestion from "./edit/BooleanQuestion.vue";
+import FillBlankQuestion from "./edit/FillBlankQuestion.vue";
+import SelectQuestion from "./edit/SelectQuestion.vue";
+import TextAnswerQuestion from "./edit/TextAnswerQuestion.vue";
+import { randomCode } from "@/plugins/utils";
 
 const structTypeCompDict = {
   SINGLE_ANSWER_QUESTION: "select-question",
@@ -57,32 +74,65 @@ const structTypeCompDict = {
 
 export default {
   name: "QuestionEditDialog",
+  components: {
+    FillBlankQuestion,
+    SelectQuestion,
+    TextAnswerQuestion,
+    BooleanQuestion,
+  },
+  props: {
+    question: {
+      type: Object,
+      default() {
+        return {};
+      },
+    },
+  },
   data() {
     return {
       modalIsShow: false,
       QUESTION_TYPES,
       curQuestionType: "SINGLE_ANSWER_QUESTION",
+      questionModel: {},
+      questionKey: "",
     };
   },
   computed: {
-    title() {
-      return "11";
+    isEdit() {
+      return !!this.question.id;
     },
     structTypeComp() {
       return structTypeCompDict[this.curQuestionType];
     },
   },
   methods: {
-    visibleChange() {},
+    visibleChange() {
+      this.initData();
+    },
+    initData() {
+      this.questionKey = randomCode();
+      this.questionModel = this.$objAssign(
+        getInitQuestionModel(this.curQuestionType),
+        this.question
+      );
+    },
     cancel() {
       this.modalIsShow = false;
     },
     open() {
       this.modalIsShow = true;
     },
-    switchType(item) {
+    async switchType(item) {
+      if (this.curQuestionType === item.code) return;
+
+      const confirm = await this.$confirm("确认更改题型吗?", "提示", {
+        type: "warning",
+      }).catch(() => {});
+      if (confirm !== "confirm") return;
+
       // to warning
       this.curQuestionType = item.code;
+      this.initData();
     },
     confirm() {
       this.cancel();

+ 25 - 15
src/modules/question/components/QuestionInfoEdit.vue

@@ -2,18 +2,22 @@
   <div class="question-info-edit">
     <el-form label-width="100px">
       <el-form-item label="难度">
-        <el-select v-model="quesModel.difficulty" placeholder="请输入难度">
+        <el-select
+          v-model="modelForm.difficulty"
+          placeholder="请选择难度"
+          @change="emitChange"
+        >
           <el-option
-            v-for="item in difficultyList"
-            :key="item.value"
-            :label="item.label"
-            :value="item.value"
+            v-for="item in DIFFICULTY_LIST"
+            :key="item.code"
+            :label="item.name"
+            :value="item.code"
           >
           </el-option>
         </el-select>
       </el-form-item>
 
-      <el-form-item label="属性名">
+      <el-form-item prop="quesProperties" label="属性名">
         <div class="box-flex">
           <property-select
             v-model="properties.coursePropertyId"
@@ -63,18 +67,19 @@
 <script>
 import { DIFFICULTY_LIST } from "@/constants/constants";
 
+const initModalForm = {
+  courseId: "",
+  difficulty: "易",
+  quesProperties: [],
+};
+
 export default {
   name: "QuestionInfoEdit",
   props: {
-    data: {
+    question: {
       type: Object,
       default() {
-        return {
-          courseId: "",
-          difficulty: "易",
-          difficultyDegree: null,
-          quesProperties: [],
-        };
+        return {};
       },
     },
   },
@@ -82,8 +87,7 @@ export default {
     return {
       DIFFICULTY_LIST,
       modelForm: {
-        difficulty: "易",
-        quesProperties: [],
+        ...initModalForm,
       },
       properties: {
         coursePropertyId: "",
@@ -106,7 +110,13 @@ export default {
       );
     },
   },
+  mounted() {
+    this.initData();
+  },
   methods: {
+    initData() {
+      this.modelForm = this.$objAssign(initModalForm, this.question);
+    },
     coursePropertyChange(val) {
       this.selection.courseProperty = val || {};
     },

+ 90 - 3
src/modules/question/components/edit/BooleanQuestion.vue

@@ -1,13 +1,100 @@
 <template>
-  <div class="boolean-question">BooleanQuestion</div>
+  <div class="boolean-question">
+    <el-form
+      ref="modalFormComp"
+      :model="modelForm"
+      :rules="rules"
+      label-width="100px"
+    >
+      <el-form-item prop="quesBody" label="题干:">
+        <v-editor v-model="modalForm.quesBody"></v-editor>
+      </el-form-item>
+      <el-form-item prop="quesAnswer" label="答案">
+        <el-radio-group v-model="modalForm.quesAnswer" @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.comment"></v-editor>
+      </el-form-item>
+    </el-form>
+    <question-info-edit
+      ref="QuestionInfoEdit"
+      :question="modalForm"
+      @change="questionInfoChange"
+    ></question-info-edit>
+  </div>
 </template>
 
 <script>
+import { isAnEmptyRichText } from "@/utils/utils";
+import { getInitQuestionModel } from "../model/questionModel";
+import QuestionInfoEdit from "../QuestionInfoEdit.vue";
+
 export default {
   name: "BooleanQuestion",
+  components: { QuestionInfoEdit },
+  props: {
+    question: {
+      type: Object,
+      default() {
+        return {};
+      },
+    },
+  },
   data() {
-    return {};
+    return {
+      modalForm: {},
+      answerOptions: [
+        {
+          value: 0,
+          label: "错误",
+        },
+        {
+          value: 1,
+          label: "正确",
+        },
+      ],
+      rules: {
+        quesBody: [
+          {
+            validator: (rule, value, callback) => {
+              if (!value || isAnEmptyRichText(value)) {
+                return callback(new Error(`请输入题干`));
+              }
+              callback();
+            },
+            trigger: "change",
+          },
+        ],
+      },
+    };
+  },
+  created() {
+    this.initData();
+  },
+  methods: {
+    initData() {
+      this.modalForm = this.$objAssign(
+        getInitQuestionModel("BOOL_ANSWER_QUESTION"),
+        this.question
+      );
+    },
+    questionInfoChange(questionInfo) {
+      this.modalForm = Object.assign({}, this.modalForm, questionInfo);
+    },
+    validate() {
+      return this.$refs.modalFormComp.validate();
+    },
+    getData() {
+      return this.modalForm;
+    },
   },
-  methods: {},
 };
 </script>

+ 118 - 3
src/modules/question/components/edit/FillBlankQuestion.vue

@@ -1,10 +1,52 @@
 <template>
-  <div class="fill-blank-question">FillBlankQuestion-question</div>
+  <div class="fill-blank-question">
+    <el-form
+      ref="modalFormComp"
+      :model="modelForm"
+      :rules="rules"
+      label-width="100px"
+    >
+      <el-form-item prop="quesBody" label="题干:">
+        <v-editor
+          v-model="modalForm.quesBody"
+          enable-answer-point
+          @answer-point-changed="answerPointsChange"
+        ></v-editor>
+      </el-form-item>
+      <span>答案</span>
+      <el-form-item
+        v-for="(answer, oindex) in modalForm.quesAnswer"
+        :key="oindex"
+        :prop="`quesAnswer.${oindex}.body`"
+        :rules="answerRule"
+      >
+        <div class="option-check">
+          {{ oindex + 1 }}
+        </div>
+        <div class="option-body">
+          <v-editor v-model="answer.body"></v-editor>
+        </div>
+      </el-form-item>
+      <el-form-item label="答案解析">
+        <v-editor v-model="modalForm.comment"></v-editor>
+      </el-form-item>
+    </el-form>
+    <question-info-edit
+      ref="QuestionInfoEdit"
+      :question="modalForm"
+      @change="questionInfoChange"
+    ></question-info-edit>
+  </div>
 </template>
 
 <script>
+import { isAnEmptyRichText } from "@/utils/utils";
+import { getInitQuestionModel } from "../model/questionModel";
+import QuestionInfoEdit from "../QuestionInfoEdit.vue";
+
 export default {
   name: "FillBlankQuestion",
+  components: { QuestionInfoEdit },
   props: {
     question: {
       type: Object,
@@ -14,8 +56,81 @@ export default {
     },
   },
   data() {
-    return {};
+    return {
+      modalForm: {},
+      rules: {
+        quesBody: [
+          {
+            validator: (rule, value, callback) => {
+              if (!value || isAnEmptyRichText(value)) {
+                return callback(new Error(`请输入题干`));
+              }
+              callback();
+            },
+            trigger: "change",
+          },
+        ],
+      },
+      answerRule: {
+        validator: (rule, value, callback) => {
+          if (!value || !value.length) {
+            return callback(new Error(`请输入答案内容`));
+          }
+          callback();
+        },
+        trigger: "change",
+      },
+    };
+  },
+  created() {
+    this.initData();
+  },
+  methods: {
+    initData() {
+      this.modalForm = this.$objAssign(
+        getInitQuestionModel("FILL_BLANK_QUESTION"),
+        this.question
+      );
+      this.modalForm.quesAnswer = this.modalForm.quesAnswer.map((item) => {
+        return {
+          body: item,
+        };
+      });
+    },
+    answerPointsChange(answerPointsCount) {
+      console.log(answerPointsCount);
+      let curAnswerPointsCount = this.modalForm.quesAnswer.length;
+      if (curAnswerPointsCount === answerPointsCount) return;
+
+      if (curAnswerPointsCount > answerPointsCount) {
+        this.modalForm.quesAnswer = this.modalForm.quesAnswer.slice(
+          0,
+          answerPointsCount
+        );
+      } else {
+        for (let i = curAnswerPointsCount; i < answerPointsCount; i++) {
+          this.modalForm.quesAnswer.push({
+            body: null,
+          });
+        }
+      }
+    },
+    questionInfoChange(questionInfo) {
+      this.modalForm = Object.assign({}, this.modalForm, questionInfo);
+    },
+    validate() {
+      return this.$refs.modalFormComp.validate();
+    },
+    getData() {
+      let data = { ...this.modalForm };
+      data.quesAnswer = this.modalForm.quesAnswer.map((item, index) => {
+        return {
+          ...item.body,
+          index,
+        };
+      });
+      return data;
+    },
   },
-  methods: {},
 };
 </script>

+ 67 - 21
src/modules/question/components/edit/SelectQuestion.vue

@@ -2,11 +2,11 @@
   <div class="select-question">
     <el-form
       ref="modalFormComp"
-      :model="modelForm"
+      :model="modalForm"
       :rules="rules"
       label-width="100px"
     >
-      <el-form-item prop="quesBody" label="题干">
+      <el-form-item prop="quesBody" label="题干">
         <v-editor v-model="modalForm.quesBody"></v-editor>
       </el-form-item>
       <el-form-item
@@ -17,7 +17,21 @@
       >
         <div class="question-edit-option">
           <div class="option-check">
-            {{ (option.nmuber - 1) | optionOrderWordFilter }}
+            <el-radio
+              v-if="IS_SIMPLE"
+              v-model="quesAnswer"
+              :label="option.number"
+            >
+              {{ (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>
           <div class="option-body">
             <v-editor v-model="option.body"></v-editor>
@@ -27,7 +41,7 @@
               size="mini"
               circle
               type="primary"
-              icon="el-icon-add"
+              icon="el-icon-plus"
               title="新增"
               @click.prevent="addQuesOption(index)"
             ></el-button>
@@ -43,7 +57,8 @@
         </div>
       </el-form-item>
       <el-form-item prop="quesAnswer" label="答案">
-        <el-radio-group
+        <span>{{ answer }}</span>
+        <!-- <el-radio-group
           v-if="IS_SIMPLE"
           v-model="quesAnswer"
           @change="answerChange"
@@ -68,20 +83,28 @@
           >
             {{ (option.number - 1) | optionOrderWordFilter }}
           </el-checkbox>
-        </el-checkbox-group>
+        </el-checkbox-group> -->
       </el-form-item>
       <el-form-item label="答案解析">
         <v-editor v-model="modalForm.comment"></v-editor>
       </el-form-item>
     </el-form>
+    <question-info-edit
+      ref="QuestionInfoEdit"
+      :question="modalForm"
+      @change="questionInfoChange"
+    ></question-info-edit>
   </div>
 </template>
 
 <script>
 import { isAnEmptyRichText } from "@/utils/utils";
+import { getInitQuestionModel } from "../model/questionModel";
+import QuestionInfoEdit from "../QuestionInfoEdit.vue";
 
 export default {
   name: "SelectQuestion",
+  components: { QuestionInfoEdit },
   props: {
     question: {
       type: Object,
@@ -92,13 +115,7 @@ export default {
   },
   data() {
     return {
-      modalForm: {
-        questionType: "SINGLE_ANSWER_QUESTION",
-        quesBody: null,
-        quesOptions: [],
-        quesAnswer: [],
-        comment: null,
-      },
+      modalForm: {},
       quesAnswer: null,
       rules: {
         quesBody: [
@@ -140,10 +157,30 @@ export default {
       return this.question.questionType === "SINGLE_ANSWER_QUESTION";
     },
     answer() {
-      return "w";
+      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() {
+      console.log("11");
+      this.modalForm = this.$objAssign(
+        getInitQuestionModel("SINGLE_ANSWER_QUESTION"),
+        this.question
+      );
+      if (!this.IS_SIMPLE) {
+        const quesAnswer = this.question.quesAnswer || [];
+        this.modalForm.quesOptions.forEach((item) => {
+          item.isCorrect = quesAnswer.includes(item.number);
+        });
+      }
+    },
     addQuesOption(index) {
       if (this.modalForm.quesOptions.length >= 20) {
         this.$message.error("选项最多20个");
@@ -166,21 +203,30 @@ export default {
         }
       );
       const optionCount = this.modalForm.quesOptions.length;
-      if (this.IS_SIMPLE) {
-        if (this.quesAnswer > optionCount) this.quesAnswer = null;
-      } else {
-        this.quesAnswer = this.quesAnswer.filter((item) => item <= optionCount);
+      if (this.IS_SIMPLE && this.quesAnswer > optionCount) {
+        this.quesAnswer = null;
       }
       this.answerChange();
     },
     answerChange() {
-      this.modalForm.quesAnswer = this.IS_SIMPLE
-        ? [this.quesAnswer]
-        : this.quesAnswer;
+      if (this.IS_SIMPLE) {
+        this.modalForm.quesAnswer = this.quesAnswer ? [this.quesAnswer] : [];
+      } else {
+        this.quesAnswer = this.modalForm.quesOptions
+          .filter((item) => item.isCorrect)
+          .map((item) => item.number);
+        this.modalForm.quesAnswer = this.quesAnswer;
+      }
+    },
+    questionInfoChange(questionInfo) {
+      this.modalForm = Object.assign({}, this.modalForm, questionInfo);
     },
     validate() {
       return this.$refs.modalFormComp.validate();
     },
+    getData() {
+      return this.modalForm;
+    },
   },
 };
 </script>

+ 83 - 3
src/modules/question/components/edit/TextAnswerQuestion.vue

@@ -1,13 +1,93 @@
 <template>
-  <div class="text-answer-auestion">TextAnswerQuestion</div>
+  <div class="text-answer-question">
+    <el-form
+      ref="modalFormComp"
+      :model="modelForm"
+      :rules="rules"
+      label-width="100px"
+    >
+      <el-form-item prop="quesBody" label="题干">
+        <v-editor v-model="modalForm.quesBody"></v-editor>
+      </el-form-item>
+      <el-form-item prop="quesAnswer" label="答案">
+        <v-editor v-model="modalForm.quesAnswer"></v-editor>
+      </el-form-item>
+      <el-form-item label="答案解析">
+        <v-editor v-model="modalForm.comment"></v-editor>
+      </el-form-item>
+    </el-form>
+    <question-info-edit
+      ref="QuestionInfoEdit"
+      :question="modalForm"
+      @change="questionInfoChange"
+    ></question-info-edit>
+  </div>
 </template>
 
 <script>
+import { isAnEmptyRichText } from "@/utils/utils";
+import { getInitQuestionModel } from "../model/questionModel";
+import QuestionInfoEdit from "../QuestionInfoEdit.vue";
+
 export default {
   name: "TextAnswerQuestion",
+  components: { QuestionInfoEdit },
+  props: {
+    question: {
+      type: Object,
+      default() {
+        return {};
+      },
+    },
+  },
   data() {
-    return {};
+    return {
+      modalForm: {},
+      rules: {
+        quesBody: [
+          {
+            validator: (rule, value, callback) => {
+              if (!value || isAnEmptyRichText(value)) {
+                return callback(new Error(`请输入题干`));
+              }
+              callback();
+            },
+            trigger: "change",
+          },
+        ],
+        quesAnswer: [
+          {
+            validator: (rule, value, callback) => {
+              if (!value || isAnEmptyRichText(value)) {
+                return callback(new Error(`请输入答案`));
+              }
+              callback();
+            },
+            trigger: "change",
+          },
+        ],
+      },
+    };
+  },
+  created() {
+    this.initData();
+  },
+  methods: {
+    initData() {
+      this.modalForm = this.$objAssign(
+        getInitQuestionModel("TEXT_ANSWER_QUESTION"),
+        this.question
+      );
+    },
+    questionInfoChange(questionInfo) {
+      this.modalForm = Object.assign({}, this.modalForm, questionInfo);
+    },
+    validate() {
+      return this.$refs.modalFormComp.validate();
+    },
+    getData() {
+      return this.modalForm;
+    },
   },
-  methods: {},
 };
 </script>

+ 52 - 35
src/modules/question/components/model/questionModel.js

@@ -1,39 +1,39 @@
 import { deepCopy } from "@/plugins/utils";
 
-export const select_question = {
-  questionType: 1, // 2多选
-  quesBody: {
-    sections: [],
-  },
+export const selectQuestion = {
+  questionType: "SINGLE_ANSWER_QUESTION", // 2多选
+  quesBody: null,
   quesOptions: [
     {
       number: 1,
-      body: {
-        sections: [{ blocks: [{ type: "text", value: "黑格尔" }] }],
-      },
+      body: null,
     },
     {
       number: 2,
-      body: {
-        sections: [{ blocks: [{ type: "text", value: "苏格拉底" }] }],
-      },
+      body: null,
+    },
+    {
+      number: 3,
+      body: null,
+    },
+    {
+      number: 4,
+      body: null,
     },
   ],
-  quesAnswer: [4],
-  comment: { sections: [] },
+  quesAnswer: null,
+  comment: null,
 };
 
-export const boolean_question = {
-  questionType: 3,
-  quesBody: {
-    sections: [],
-  },
-  quesAnswer: false,
-  comment: { sections: [] },
+export const booleanQuestion = {
+  questionType: "BOOL_ANSWER_QUESTION",
+  quesBody: null,
+  quesAnswer: 0,
+  comment: null,
 };
 
-export const fill_blank_question = {
-  questionType: 4,
+export const fillBlankQuestion = {
+  questionType: "FILL_BLANK_QUESTION",
   quesBody: {
     sections: [],
   },
@@ -50,8 +50,8 @@ export const fill_blank_question = {
   comment: { sections: [] },
 };
 
-export const text_answer_question = {
-  questionType: 5,
+export const textAnswerQuestion = {
+  questionType: "TEXT_ANSWER_QUESTION",
   quesBody: {
     sections: [],
   },
@@ -65,8 +65,8 @@ export const text_answer_question = {
   comment: { sections: [] },
 };
 // 完型填空/听力/阅读理解
-export const reading_comprehension_question = {
-  questionType: 6,
+export const readingComprehensionQuestion = {
+  questionType: "READING_COMPREHENSION",
   quesBody: {
     sections: [],
   },
@@ -76,8 +76,8 @@ export const reading_comprehension_question = {
 };
 
 // 段落匹配/选词填空
-export const banked_cloze_question = {
-  questionType: 8,
+export const bankedClozeQuestion = {
+  questionType: "BANKED_CLOZE",
   quesBody: {
     sections: [],
   },
@@ -105,14 +105,31 @@ export const banked_cloze_question = {
 };
 
 const models = {
-  select_question,
-  boolean_question,
-  fill_blank_question,
-  text_answer_question,
-  reading_comprehension_question,
-  banked_cloze_question,
+  SINGLE_ANSWER_QUESTION: selectQuestion,
+  MULTIPLE_ANSWER_QUESTION: Object.assign({}, selectQuestion, {
+    questionType: "MULTIPLE_ANSWER_QUESTION",
+  }),
+  BOOL_ANSWER_QUESTION: booleanQuestion,
+  FILL_BLANK_QUESTION: fillBlankQuestion,
+  TEXT_ANSWER_QUESTION: textAnswerQuestion,
+  READING_COMPREHENSION: readingComprehensionQuestion,
+  LISTENING_QUESTION: Object.assign({}, readingComprehensionQuestion, {
+    questionType: "LISTENING_QUESTION",
+  }),
+  CLOZE: Object.assign({}, readingComprehensionQuestion, {
+    questionType: "CLOZE",
+  }),
+  PARAGRAPH_MATCHING: Object.assign({}, bankedClozeQuestion, {
+    questionType: "PARAGRAPH_MATCHING",
+  }),
+  BANKED_CLOZE: bankedClozeQuestion,
 };
 
 export const getInitQuestionModel = (qtype) => {
-  return deepCopy(models[qtype]);
+  return {
+    ...deepCopy(models[qtype]),
+    courseId: "",
+    difficulty: "易",
+    quesProperties: [],
+  };
 };

+ 26 - 2
src/modules/question/views/QuestionManage.vue

@@ -6,7 +6,8 @@
 
       <el-form class="part-filter-form" :inline="true" :model="filter">
         <el-form-item label="课程名称">
-          <course-select v-model="filter.courseId"> </course-select>
+          <course-select v-model="filter.courseId" @change="courseChange">
+          </course-select>
         </el-form-item>
         <el-form-item label="题型">
           <question-type-select v-model="filter.questionType">
@@ -194,6 +195,11 @@
       </div>
     </div>
 
+    <!-- QuestionEditDialog -->
+    <question-edit-dialog
+      ref="QuestionEditDialog"
+      :question="curQuestion"
+    ></question-edit-dialog>
     <!-- QuestionStatisticsDialog -->
     <question-statistics-dialog
       ref="QuestionStatisticsDialog"
@@ -228,6 +234,7 @@ import QuestionStatisticsDialog from "../components/QuestionStatisticsDialog.vue
 import QuestionSafetySetDialog from "../components/QuestionSafetySetDialog.vue";
 import QuestionFolderDialog from "../components/QuestionFolderDialog.vue";
 import QuestionImportDialog from "../components/QuestionImportDialog.vue";
+import QuestionEditDialog from "../components/QuestionEditDialog.vue";
 
 export default {
   name: "QuestionMamage",
@@ -236,6 +243,7 @@ export default {
     QuestionSafetySetDialog,
     QuestionFolderDialog,
     QuestionImportDialog,
+    QuestionEditDialog,
   },
   data() {
     return {
@@ -254,6 +262,8 @@ export default {
       loading: false,
       isEditFolder: true,
       curQuestionFolderId: null,
+      curQuestion: {},
+      curCourse: {},
     };
   },
   mounted() {
@@ -278,6 +288,9 @@ export default {
       this.pageSize = val;
       this.toPage(1);
     },
+    courseChange(val) {
+      this.curCourse = val || {};
+    },
     toStatistics() {
       this.$refs.QuestionStatisticsDialog.open();
     },
@@ -289,7 +302,18 @@ export default {
       this.curQuestionFolderId = null;
       this.$refs.QuestionFolderDialog.open();
     },
-    toCreateQuestion() {},
+    toCreateQuestion() {
+      if (!this.filter.courseId) {
+        this.$message.error("请先选择课程!");
+        return;
+      }
+      this.curQuestion = {
+        courseId: this.curCourse.id,
+        courseCode: this.curCourse.code,
+        courseName: this.curCourse.name,
+      };
+      this.$refs.QuestionEditDialog.open();
+    },
     toImportQuestion() {
       this.$refs.QuestionImportDialog.open();
     },

+ 2 - 2
src/modules/questions/routes/routes.js

@@ -7,8 +7,8 @@ import InsertBluePaperStructure from "../views/InsertBluePaperStructure.vue";
 import InsertBluePaperStructureInfo from "../views/InsertBluePaperStructureInfo.vue";
 import CourseProperty from "../views/CourseProperty.vue";
 import PropertyInfo from "../views/PropertyInfo.vue";
-import ImportPaper from "../views/ImportPaper.vue";
-// import ImportPaper from "../../question/views/QuestionManage";
+// import ImportPaper from "../views/ImportPaper.vue";
+import ImportPaper from "../../question/views/QuestionManage";
 import GenPaper from "../views/GenPaper.vue";
 import ImportPaperInfo from "../views/ImportPaperInfo.vue";
 import GenPaperDetail from "../views/GenPaperDetail.vue";

+ 1 - 1
src/plugins/utils.js

@@ -34,7 +34,7 @@ export function deepCopy(data) {
  * @param {Object} sources 源对象
  */
 export function objAssign(target, sources) {
-  let targ = { ...target };
+  let targ = deepCopy(target);
   for (let k in targ) {
     targ[k] = Object.prototype.hasOwnProperty.call(sources, k)
       ? sources[k]