由于最近在一个项目中需要实现创建试卷与预览试卷的功能,所以就自己动手写了一个,效果还不错,目前项目已经交付使用,今天就先和大家分享一下创建试卷。
创建试卷
先放一下效果图
首先是试卷的相关设置
考试对象是通过接口返回的数据
<span class=\"content-label\">选择考试对象</span> <el-form-item prop=\"roleList\"> <el-select v-model=\"form.roleList\" multiple filterable allow-create default-first-option placeholder=\"请选择考试对象\" > <el-option v-for=\"item in roles\" :key=\"item.value\" :label=\"item.label\" :value=\"item.value\" /> </el-select> </el-form-item>
需要定义的data
数据
roles: [], //考试对象选择列表(接口返回) form: { title: \'\', roleList: [], // 考试对象 deadline: \'\', // 截止时间 questions: [] },
获取考试对象列表
getRoles() { crudRoles.getAll().then(res => { res.map((obj) => { const role = { value: obj.id, label: obj.name } this.roles.push(role) }) }) },
截至时间使用的是element时间日期选择器
<span class=\"content-label\">截止时间</span> <el-form-item prop=\"deadline\"> <el-date-picker v-model=\"form.deadline\" type=\"datetime\" placeholder=\"选择日期时间\" value-format=\"yyyy-MM-dd HH:mm:ss\" /> </el-form-item>
然后是添加试题
试题类型的相关数据也是通过接口返回的
data
数据
questionType: [],
获取试题类型
getQuestionType() { crudExam.getQuestionType().then(res => { this.questionType = res }) },
<div class=\"question-type\"> <el-button v-for=\"item in questionType\" :key=\"item.typeId\" style=\"border-color: #2A82E4; color: #2A82E4\" @click=\"addQuestion(item.typeId)\" > <svg-icon :icon-class=\"item.icon\" /> {{ item.typeName }} </el-button> </div>
addQuestion(typeId) { const question = { id: this.questionId, quesTypeId: typeId, title: \'\', score: 0, answer: [], content: [] } this.form.questions.push(question) this.questionId++ },
对于添加的试题模板则是单独创建了一个question.vue
这里由于其他布局方法一直不太理想,所以采用了栅格布局,效果还算可以
<template> <el-card class=\"box-card\"> <div slot=\"header\" class=\"clearfix\" style=\"margin-bottom: -10px\"> <span class=\"type-name\" v-text=\"question.quesTypeId < 3 ? question.quesTypeId === 1 ? \'单选题\' : \'多选题\' : question.quesTypeId < 5 ? question.quesTypeId === 3 ? \'填空题\' : \'简答题\' : \'判断题\'\" >卡片名称</span> <el-input v-model=\"question.score\" style=\"width: 55px\" /> <span>分</span> <el-button style=\"float: right; border: none; font-size: 20px\" icon=\"el-icon-close\" @click=\"removeQuestion\" /> </div> <el-form-item> <el-input v-model=\"question.title\" type=\"textarea\" placeholder=\"请输入题干内容...\" /> </el-form-item> <!--单选、多选--> <el-form-item v-if=\"question.quesTypeId === 1 || question.quesTypeId === 2\" style=\"margin-bottom: 0px\"> <el-checkbox-group v-model=\"question.answer\" :min=\"0\" :max=\"question.quesTypeId === 1 ? 1 : 4\" > <el-row v-for=\"(item, index) in [\'A\', \'B\', \'C\', \'D\']\" :key=\"item\" > <el-col :span=\"1\"> <el-checkbox-button v-model=\"question.answer\" :label=\"question.content[index]\" border > {{ item }} </el-checkbox-button> </el-col> <el-col :span=\"23\"> <el-input v-model=\"question.content[index]\" placeholder=\"请输入选项...\" @input=\"contentChange(question)\" /> </el-col> </el-row> </el-checkbox-group> </el-form-item> <!--简答、填空--> <el-form-item v-if=\"question.quesTypeId === 3 || question.quesTypeId === 4\" style=\"margin-bottom: 0px\"> <el-input v-model=\"question.answer[0]\" type=\"textarea\" placeholder=\"请输入参考答案\" /> </el-form-item> <!--判断--> <el-form-item v-if=\"question.quesTypeId === 5\" style=\"margin-bottom: 0px\"> <el-checkbox-group v-model=\"question.answer\" :min=\"0\" :max=\"1\" > <el-checkbox v-model=\"question.answer\" label=\"对\" border /> <el-checkbox v-model=\"question.answer\" label=\"错\" border /> </el-checkbox-group> </el-form-item> </el-card> </template> <script> export default { props: { question: { type: Object, required: true } }, methods: { removeQuestion() { this.$emit(\'removeQuestion\', this.question.id) }, contentChange(question) { question.answer.splice(0) } } } </script> <style scoped> .type-name { color: #505050; margin-right: 20px; } </style>
然后是删除试题
<question v-for=\"item in form.questions\" :key=\"item.id\" :question=\"item\" class=\"question-content\" @removeQuestion=\"removeQuestion\" />
removeQuestion(id) { for (let i = 0; i < this.form.questions.length; i++) { if (this.form.questions[i].id === id) { this.form.questions.splice(i, 1) } } },
最后提交方法中进行数据验证
这个在之前一篇博客中简单介绍过,感兴趣的朋友可以自行前去了解
Vue关于Element对表单的校验
最最后把create.vue
的源码分享给大家方便大家进行参考,如有更好的建议也请大家不吝赐教
<template> <div class=\"app-container\"> <div> <el-form ref=\"form\" :model=\"form\" :rules=\"rules\" class=\"form\" > <h4 class=\"card-label\">设置任务</h4> <div class=\"card-panel\"> <div class=\"settings-wrap\" style=\"width: 18%\"> <span class=\"content-label\">选择考试对象</span> <el-form-item prop=\"roleList\"> <el-select v-model=\"form.roleList\" multiple filterable allow-create default-first-option placeholder=\"请选择考试对象\" > <el-option v-for=\"item in roles\" :key=\"item.value\" :label=\"item.label\" :value=\"item.value\" /> </el-select> </el-form-item> </div> <div class=\"settings-wrap\" style=\"width: 18%\"> <span class=\"content-label\">截止时间</span> <el-form-item prop=\"deadline\"> <el-date-picker v-model=\"form.deadline\" type=\"datetime\" placeholder=\"选择日期时间\" value-format=\"yyyy-MM-dd HH:mm:ss\" /> </el-form-item> </div> </div> <h4 class=\"card-label\">试卷标题</h4> <div class=\"card-panel\"> <div class=\"settings-wrap\" style=\"width: 40%\"> <el-form-item prop=\"title\"> <el-input v-model=\"form.title\" type=\"text\" placeholder=\"请输入试卷标题(1-20个字)\" maxlength=\"20\" show-word-limit /> </el-form-item> </div> </div> <question v-for=\"item in form.questions\" :key=\"item.id\" :question=\"item\" class=\"question-content\" @removeQuestion=\"removeQuestion\" /> <div class=\"question-type\"> <el-button v-for=\"item in questionType\" :key=\"item.typeId\" style=\"border-color: #2A82E4; color: #2A82E4\" @click=\"addQuestion(item.typeId)\" > <svg-icon :icon-class=\"item.icon\" /> {{ item.typeName }} </el-button> </div> <el-button type=\"primary\" class=\"submit\" :loading=\"loading\" style=\"margin-top: 20px\" @click=\"submit\" > 提交试卷 </el-button> </el-form> </div> </div> </template> <script> import crudRoles from \'@/api/system/role\' import crudExam from \'@/api/exam/exam\' import question from \'@/views/exam/module/question\' import crudList from \'@/api/exam/list\' export default { name: \'Create\', components: { question }, data() { return { roles: [], dialogVisible: false, loading: false, questionId: 0, form: { title: \'\', roleList: [], // 考试对象 deadline: \'\', // 截止时间 questions: [] }, questionType: [], rules: { roleList: [{ required: true, message: \'请选择考试对象\', trigger: \'blur\' }], deadline: [{ required: true, message: \'请选择截止时间\', trigger: \'blur\' }], title: [{ required: true, message: \'请输入试卷标题(1-20个字)\', trigger: \'blur\' }] } } }, created() { this.getRoles() this.getQuestionType() }, methods: { getRoles() { crudRoles.getAll().then(res => { res.map((obj) => { const role = { value: obj.id, label: obj.name } this.roles.push(role) }) }) }, getQuestionType() { crudExam.getQuestionType().then(res => { this.questionType = res }) }, addQuestion(typeId) { const question = { id: this.questionId, quesTypeId: typeId, title: \'\', score: 0, answer: [], content: [] } this.form.questions.push(question) this.questionId++ }, removeQuestion(id) { for (let i = 0; i < this.form.questions.length; i++) { if (this.form.questions[i].id === id) { this.form.questions.splice(i, 1) } } }, submit() { if (this.form.questions.length === 0) { this.$notify({ title: \'警告\', message: \'请添加试题\', type: \'warning\' }) return } const form = JSON.parse(JSON.stringify(this.form)) let isSubmit = true let message = \'\' this.loading = true this.$refs[\'form\'].validate(res => { if (!res) { this.loading = false return } for (let i = 0; i < form.questions.length; i++) { const question = form.questions[i] if (question.title === \'\') { isSubmit = false message = \'请设置题目题干\' break } if ((question.quesTypeId === 1 || question.quesTypeId === 2) && question.content.length === 0) { isSubmit = false message = \'请设置选择题题答案\' break } if ((question.quesTypeId === 1 || question.quesTypeId === 2 || question.quesTypeId === 5) && question.answer.length === 0) { isSubmit = false message = \'请设置客观题选项\' break } } if (!isSubmit) { this.$notify({ title: \'警告\', message: message, type: \'warning\' }) this.loading = false return } form.questions.forEach(function(question) { question.answer = JSON.stringify(question.answer) question.content = JSON.stringify(question.content) }) crudExam.add(form).then((res) => { this.loading = false const params = { type: 2, typeId: res, url: this.$frontUrl + \'/answerOnline\' } crudList.remind(params).then(() => { this.$message.success(\'提醒成功~\') }) this.$router.push(\'/exam/index\') }).catch(() => { this.loading = false }) }) } } } </script> <style rel=\"stylesheet/scss\" lang=\"scss\" scoped> .card-label { margin: 30px 0 15px; } .card-panel { display: flex; flex-direction: row; padding: 17px 15px 0; color: #666; box-shadow: 0 0 3px 1px #e7e7e7; border-color: #e7e7e7; .settings-wrap { margin-right: 4%; } } .content-label { display: block; padding-bottom: 5px; } .question-type { margin-top: 20px; } .question-content { margin-top: 20px; color: #666; box-shadow: 0 0 4px 2px rgba(0, 0, 0, .05); border-color: rgba(0, 0, 0, .05); } </style>
© 版权声明
THE END
暂无评论内容