基于vue与element实现创建试卷相关功能(实例代码)

由于最近在一个项目中需要实现创建试卷与预览试卷的功能,所以就自己动手写了一个,效果还不错,目前项目已经交付使用,今天就先和大家分享一下创建试卷。

创建试卷

先放一下效果图

基于vue与element实现创建试卷相关功能(实例代码)

首先是试卷的相关设置

考试对象是通过接口返回的数据

基于vue与element实现创建试卷相关功能(实例代码)

<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时间日期选择器

基于vue与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>

 

然后是添加试题
试题类型的相关数据也是通过接口返回的

基于vue与element实现创建试卷相关功能(实例代码)
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
喜欢就支持一下吧
点赞0 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容