Vue-实战篇-试题库

267 阅读1分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第11天,点击查看活动详情

开发项目实战篇,试题库出题,将试题根据题型需要的字段封装成组件,传入不同的题型,展示不同的题型,客观题的共通点就是-都有选项,选项可以增、删、改,最多20个,最少2个。话不多说,直接上代码吧

客观题-单选题、多选题、判断题

编辑器用的tinymce

题目由题干选项答案题目解析添加选项按钮,删除选项按钮,移动选项按钮组成

实现一个公共的客观题的组件,按需引入,组件如下:

<div class="selectModule">
    <div class="moduleStem">
        <p>题目:</p>
        <tinymce :placeholder="'输入题目描述'" ref="editor" v-model="data.context" :size="{ height: textHeight }"
                 :disabled="disabled" :maxlength="500"></tinymce>
                 </div>
    <ul :class="['optionList',disabled ? 'isDisabled' : '']">
        <li
            :class="['optionItem',data.isDisabled ? 'isDisabled' : '']"
            v-for="(item,index) in data.options"
            :key="item.value"
        >
            <!--单选题-->
            <template v-if="data.type == 1">
                <el-radio
                        v-model="data.answeNum"
                        :label="item.number"
                >{{item.number}}
                </el-radio>
                <tinymce placeholder="输入选项内容描述" ref="editor" v-model="item.content" :size="{ height: optionHeight }"
                         :disabled="disabled" :maxlength="500"></tinymce>
            </template>
            <!--多选题-->
            <template v-if="data.type == 2">
                <el-checkbox
                        v-model="data.answeNum"
                        :label="item.number"
                >{{item.number}}
                </el-checkbox>
                <tinymce placeholder="输入选项内容描述 " ref="editor" v-model="item.content" :size="{ height: optionHeight }"
                         :disabled="disabled" :maxlength="500"></tinymce>
            </template>
            <!--判断题-->
            <template v-if="data.type == 3">
                <el-radio
                        v-model="data.answeNum"
                        :label="item.number"
                >{{item.number | optionsName}}
                </el-radio>
            </template>
            <div v-if="data.type !== 3">
                <div class="deleteItem hoverClass" title="上移动" @click="topOption(index)" v-if="index !== 0"><i class="el-icon-top"></i></div>
                <div class="deleteItem hoverClass" title="下移动" @click="bottomOption(index)" v-if="index !== data.options.length - 1"><i class="el-icon-bottom"></i></div>
                <div class="deleteItem hoverClass" title="删除" @click="deleteOptionsFn(index)" v-if="data.options.length > 2"><i class="el-icon-close"></i></div>
            </div>
        </li>
        <div v-if="!disabled && data.type !== 3" class="addOptions hoverClass" @click="addOptionsFn">
            <i class="el-icon el-icon-plus"></i> 添加选项
        </div>
    </ul>
    <div class="moduleStem">
        <p>解析:</p>
        <tinymce :placeholder="'输入题目解析'" ref="editor" v-model="data.parse" :size="{ height: textHeight }"
                 :disabled="disabled" :maxlength="2000"></tinymce>
    </div>
</div>

增删改查的js代码

// 增加选项
addOptionsFn() {
    let length = this.data.options.length;
    if (length == 20) {
        this.$message({
            type: "error",
            message: "至多有二十项!"
        });
        return;
    }
    let optionData = {
        content: "",
        number: this.sortOptionsFn(length),
        value: length
    };
    this.data.options.push(optionData);
},
// 删除选项
deleteOptionsFn(index) {
    let remainData = this.data.options;
    if (remainData.length === 2) {
        this.$message({
            type: "error",
            message: "至少有两项!"
        });
        return;
    }
    if (this.data.answeNum.constructor == Array){
        if (this.data.answeNum.indexOf(index) > -1){
            this.data.answeNum.splice(this.data.answeNum.indexOf(index), 1);
        }
    } else {
        if (this.data.answeNum === index){
            this.data.answeNum = 0;
        }
    }
    remainData.splice(index, 1); // 删除选项
    remainData.forEach((element, index) => {
        element.number = this.sortOptionsFn(index);
        element.value = index;
    });
},
// 上移动
topOption(index) {
    let remainData = this.data.options;
    remainData[index] = remainData.splice(index - 1, 1, remainData[index])[0];
    remainData.forEach((element, index) => {
        element.number = this.sortOptionsFn(index);
        element.value = index;
    });
},
// 下移动
bottomOption(index) {
    let remainData = this.data.options;
    remainData[index] = remainData.splice(index + 1, 1, remainData[index])[0];
    remainData.forEach((element, index) => {
        element.number = this.sortOptionsFn(index);
        element.value = index;
    });
},
// 删除之后选项排序
sortOptionsFn(index) {
    let options = new Map([
        [0, "A"], [1, "B"], [2, "C"], [3, "D"], [4, "E"],
        [5, "F"], [6, "G"], [7, "H"], [8, "I"], [9, "J"],
        [10, "K"], [11, "L"], [12, "M"], [13, "N"], [14, "O"],
        [15, "P"], [16, "Q"], [17, "R"], [18, "S"], [19, "T"]
    ]);
    return options.get(index);
}