|
@@ -1,13 +1,265 @@
|
|
|
<template>
|
|
|
- <div class="banked-cloze-question">BankedClozeQuestion</div>
|
|
|
+ <div class="banked-cloze-question nested-question">
|
|
|
+ <el-form
|
|
|
+ ref="modalFormComp"
|
|
|
+ :model="modalForm"
|
|
|
+ :rules="rules"
|
|
|
+ label-width="100px"
|
|
|
+ >
|
|
|
+ <el-form-item prop="quesBody" label="大题题干">
|
|
|
+ <v-editor
|
|
|
+ v-model="modalForm.quesBody"
|
|
|
+ :enable-answer-point="IS_BANKED_CLOZE"
|
|
|
+ @answer-point-changed="answerPointsChange"
|
|
|
+ @change="quesBodyChange"
|
|
|
+ ></v-editor>
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item
|
|
|
+ v-for="(option, oindex) in modalForm.quesOptions"
|
|
|
+ :key="option.nmuber"
|
|
|
+ :prop="`quesOptions.${oindex}.body`"
|
|
|
+ :rules="optionRule"
|
|
|
+ >
|
|
|
+ <div class="question-edit-option">
|
|
|
+ <div class="option-check">
|
|
|
+ {{ (option.number - 1) | optionOrderWordFilter }}
|
|
|
+ </div>
|
|
|
+ <div class="option-body">
|
|
|
+ <v-editor
|
|
|
+ v-model="option.body"
|
|
|
+ @change="() => optionBodyChange(oindex)"
|
|
|
+ ></v-editor>
|
|
|
+ </div>
|
|
|
+ <div class="option-delete">
|
|
|
+ <el-button
|
|
|
+ size="mini"
|
|
|
+ circle
|
|
|
+ type="primary"
|
|
|
+ icon="el-icon-plus"
|
|
|
+ title="新增"
|
|
|
+ @click.prevent="addQuesOption(oindex)"
|
|
|
+ ></el-button>
|
|
|
+ <el-button
|
|
|
+ size="mini"
|
|
|
+ circle
|
|
|
+ type="danger"
|
|
|
+ icon="el-icon-delete"
|
|
|
+ title="删除"
|
|
|
+ :disabled="deleleOptionDisabled"
|
|
|
+ @click.prevent="removeQuesOption(oindex)"
|
|
|
+ ></el-button>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </el-form-item>
|
|
|
+ </el-form>
|
|
|
+
|
|
|
+ <el-collapse v-model="activeNames">
|
|
|
+ <el-collapse-item
|
|
|
+ v-for="(subq, index) in modalForm.subQuestions"
|
|
|
+ :key="subq.questionKey"
|
|
|
+ :name="subq.questionKey"
|
|
|
+ >
|
|
|
+ <div slot="title" class="subq-header">
|
|
|
+ <h3>第{{ index + 1 }}小题</h3>
|
|
|
+ <div>
|
|
|
+ <el-button
|
|
|
+ v-if="!IS_BANKED_CLOZE"
|
|
|
+ size="mini"
|
|
|
+ type="text"
|
|
|
+ icon="el-icon-delete"
|
|
|
+ title="删除"
|
|
|
+ @click.stop="removeSubQuestion(index)"
|
|
|
+ ></el-button>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <match-question
|
|
|
+ ref="MatchQuestion"
|
|
|
+ :question="subq"
|
|
|
+ :parent-question="modalForm"
|
|
|
+ ></match-question>
|
|
|
+ </el-collapse-item>
|
|
|
+ </el-collapse>
|
|
|
+
|
|
|
+ <el-button
|
|
|
+ v-if="!IS_BANKED_CLOZE"
|
|
|
+ type="primary"
|
|
|
+ size="small"
|
|
|
+ icon="el-icon-circle-plus-outline"
|
|
|
+ @click="addSubQuestion()"
|
|
|
+ >新增小题</el-button
|
|
|
+ >
|
|
|
+ </div>
|
|
|
</template>
|
|
|
|
|
|
<script>
|
|
|
+import { isAnEmptyRichText } from "@/utils/utils";
|
|
|
+import { randomCode } from "@/plugins/utils";
|
|
|
+import {
|
|
|
+ getInitQuestionModel,
|
|
|
+ getMatchQuestionModel,
|
|
|
+} from "../model/questionModel";
|
|
|
+import MatchQuestion from "./MatchQuestion.vue";
|
|
|
+
|
|
|
export default {
|
|
|
name: "BankedClozeQuestion",
|
|
|
+ components: { MatchQuestion },
|
|
|
+ props: {
|
|
|
+ question: {
|
|
|
+ type: Object,
|
|
|
+ default() {
|
|
|
+ return {};
|
|
|
+ },
|
|
|
+ },
|
|
|
+ },
|
|
|
data() {
|
|
|
- return {};
|
|
|
+ return {
|
|
|
+ modalForm: {},
|
|
|
+ activeNames: [],
|
|
|
+ rules: {
|
|
|
+ quesBody: [
|
|
|
+ {
|
|
|
+ validator: (rule, value, callback) => {
|
|
|
+ if (!this.IS_BANKED_CLOZE) return callback();
|
|
|
+
|
|
|
+ if (!value || isAnEmptyRichText(value)) {
|
|
|
+ return callback(new Error(`请输入题干`));
|
|
|
+ }
|
|
|
+ callback();
|
|
|
+ },
|
|
|
+ trigger: "change",
|
|
|
+ },
|
|
|
+ ],
|
|
|
+ },
|
|
|
+ optionRule: {
|
|
|
+ validator: (rule, value, callback) => {
|
|
|
+ if (!value || isAnEmptyRichText(value)) {
|
|
|
+ return callback(new Error(`请输入选项内容`));
|
|
|
+ }
|
|
|
+ callback();
|
|
|
+ },
|
|
|
+ trigger: "change",
|
|
|
+ },
|
|
|
+ };
|
|
|
+ },
|
|
|
+ computed: {
|
|
|
+ IS_BANKED_CLOZE() {
|
|
|
+ return this.modalForm.questionType === "BANKED_CLOZE";
|
|
|
+ },
|
|
|
+ deleleOptionDisabled() {
|
|
|
+ return this.modalForm.quesOptions.length === 1;
|
|
|
+ },
|
|
|
+ },
|
|
|
+ created() {
|
|
|
+ this.initData();
|
|
|
+ },
|
|
|
+ methods: {
|
|
|
+ initData() {
|
|
|
+ this.modalForm = this.$objAssign(
|
|
|
+ getInitQuestionModel("PARAGRAPH_MATCHING"),
|
|
|
+ this.question
|
|
|
+ );
|
|
|
+ },
|
|
|
+ optionBodyChange(oindex) {
|
|
|
+ this.$refs.modalFormComp.validateField(
|
|
|
+ `quesOptions.${oindex}.body`,
|
|
|
+ () => {}
|
|
|
+ );
|
|
|
+ },
|
|
|
+ addQuesOption(index) {
|
|
|
+ if (this.modalForm.quesOptions.length >= 20) {
|
|
|
+ this.$message.error("选项最多20个");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ this.modalForm.quesOptions.splice(index + 1, 0, {
|
|
|
+ number: 0,
|
|
|
+ body: { sections: [] },
|
|
|
+ });
|
|
|
+ this.resetNumberAndSaveOptions();
|
|
|
+ },
|
|
|
+ removeQuesOption(index) {
|
|
|
+ if (this.deleleOptionDisabled) return;
|
|
|
+ this.modalForm.quesOptions.splice(index, 1);
|
|
|
+ this.resetNumberAndSaveOptions();
|
|
|
+
|
|
|
+ this.$nextTick(() => {
|
|
|
+ for (let i = 0; i < this.$refs.MatchQuestion.length; i++) {
|
|
|
+ this.$refs.MatchQuestion[i].optionChange();
|
|
|
+ }
|
|
|
+ });
|
|
|
+ },
|
|
|
+ resetNumberAndSaveOptions() {
|
|
|
+ this.modalForm.quesOptions.forEach((option, index) => {
|
|
|
+ option.number = index + 1;
|
|
|
+ });
|
|
|
+ },
|
|
|
+ addSubQuestion(index = null) {
|
|
|
+ let newQuestion = getMatchQuestionModel();
|
|
|
+ newQuestion.questionKey = randomCode();
|
|
|
+ const nindex =
|
|
|
+ index === null ? this.modalForm.subQuestions.length : index + 1;
|
|
|
+ this.modalForm.subQuestions.splice(nindex, 0, newQuestion);
|
|
|
+ if (!this.activeNames.includes(newQuestion.questionKey))
|
|
|
+ this.activeNames.push(newQuestion.questionKey);
|
|
|
+ },
|
|
|
+ async removeSubQuestion(index) {
|
|
|
+ if (this.IS_BANKED_CLOZE) return;
|
|
|
+
|
|
|
+ const res = await this.$confirm("确定要删除该小题吗?", "提示", {
|
|
|
+ type: "warning",
|
|
|
+ }).catch(() => {});
|
|
|
+ if (res !== "confirm") return;
|
|
|
+
|
|
|
+ this.modalForm.subQuestions.splice(index, 1);
|
|
|
+ const delQuestionKey =
|
|
|
+ this.modalForm.subQuestions[index].newQuestion.questionKey;
|
|
|
+ this.activeNames = this.activeNames.filter((k) => k !== delQuestionKey);
|
|
|
+ },
|
|
|
+ answerPointsChange(answerPointsCount) {
|
|
|
+ let curSubQuestionCount = this.modalForm.subQuestions.length;
|
|
|
+ if (curSubQuestionCount === answerPointsCount) return;
|
|
|
+
|
|
|
+ if (curSubQuestionCount > answerPointsCount) {
|
|
|
+ this.modalForm.subQuestions = this.modalForm.subQuestions.slice(
|
|
|
+ 0,
|
|
|
+ answerPointsCount
|
|
|
+ );
|
|
|
+ } else {
|
|
|
+ for (let i = curSubQuestionCount; i < answerPointsCount; i++) {
|
|
|
+ this.addSubQuestion();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ },
|
|
|
+ quesBodyChange() {
|
|
|
+ this.$refs.modalFormComp.validateField(`quesBody`, () => {});
|
|
|
+ },
|
|
|
+ async validate() {
|
|
|
+ const valid = await this.$refs.modalFormComp.validate().catch(() => {});
|
|
|
+ if (!valid) return;
|
|
|
+
|
|
|
+ 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() {
|
|
|
+ this.modalForm.subQuestions = this.$refs.MatchQuestion.map((compInst) =>
|
|
|
+ compInst.getData()
|
|
|
+ );
|
|
|
+ return this.modalForm;
|
|
|
+ },
|
|
|
},
|
|
|
- methods: {},
|
|
|
};
|
|
|
</script>
|