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


Posted in Vue.js onDecember 07, 2020

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

创建试卷

先放一下效果图

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

到此这篇关于基于vue与element实现创建试卷相关功能的文章就介绍到这了,更多相关vue与element创建试卷功能内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Vue.js 相关文章推荐
Vue如何循环提取对象数组中的值
Nov 18 Vue.js
Vue在H5 项目中使用融云进行实时个人单聊通讯
Dec 14 Vue.js
通过vue.extend实现消息提示弹框的方法记录
Jan 07 Vue.js
如何在 Vue 中使用 JSX
Feb 14 Vue.js
Vue和Flask通信的实现
May 19 Vue.js
vue2实现provide inject传递响应式
May 21 Vue.js
springboot+VUE实现登录注册
May 27 Vue.js
Vue中插槽slot的使用方法与应用场景详析
Jun 08 Vue.js
vue使用wavesurfer.js解决音频可视化播放问题
Apr 04 Vue.js
vue实现列表垂直无缝滚动
Apr 08 Vue.js
vue @click.native 绑定原生点击事件
Apr 22 Vue.js
vue.js 使用原生js实现轮播图
Apr 26 Vue.js
vue祖孙组件之间的数据传递案例
Dec 07 #Vue.js
在vue中动态修改css其中一个属性值操作
Dec 07 #Vue.js
在vue中使用inheritAttrs实现组件的扩展性介绍
Dec 07 #Vue.js
vue中利用three.js实现全景图的完整示例
Dec 07 #Vue.js
详解Vue中的自定义指令
Dec 07 #Vue.js
vue-router定义元信息meta操作
Dec 07 #Vue.js
Vue如何实现验证码输入交互
Dec 07 #Vue.js
You might like
frename PHP 灵活文件命名函数 frename
2009/09/09 PHP
php使用异或实现的加密解密实例
2013/09/04 PHP
javascript利用初始化数据装配模版的实现代码
2010/11/17 Javascript
将input file的选择的文件清空的两种解决方案
2013/10/21 Javascript
js控制表单不能输入空格的小例子
2013/11/20 Javascript
input:checkbox多选框实现单选效果跟radio一样
2014/06/16 Javascript
JavaScript对象属性检查、增加、删除、访问操作实例
2015/07/08 Javascript
javascript中的altKey 和 Event属性大全
2015/11/06 Javascript
BootStrap点击下拉菜单项后显示一个新的输入框实现代码
2016/05/16 Javascript
AngularJS 执行流程详细介绍
2016/08/18 Javascript
jQuery ajax的功能实现方法详解
2017/01/06 Javascript
js实现选项卡内容切换以及折叠和展开效果【推荐】
2017/01/08 Javascript
jQuery is not defined 错误原因与解决方法小结
2017/03/19 Javascript
Angular2利用组件与指令实现图片轮播组件
2017/03/27 Javascript
基于JavaScript实现移动端无限加载分页
2017/03/27 Javascript
AngularJS实现的获取焦点及失去焦点时的表单验证功能示例
2017/10/25 Javascript
JS通过ajax + 多列布局 + 自动加载实现瀑布流效果
2019/05/30 Javascript
vue项目打包后提交到git上为什么没有dist这个文件的解决方法
2020/09/16 Javascript
vue-router 按需加载 component: () =&gt; import() 报错的解决
2020/09/22 Javascript
Vue包大小优化的实现(从1.72M到94K)
2021/02/18 Vue.js
[35:34]Liquid vs Winstrike 2018国际邀请赛小组赛BO2 第一场 8.18
2018/08/19 DOTA
Python中实现两个字典(dict)合并的方法
2014/09/23 Python
Python 递归函数详解及实例
2016/12/27 Python
启动targetcli时遇到错误解决办法
2017/10/26 Python
Python3 中文文件读写方法
2018/01/23 Python
在PyCharm环境中使用Jupyter Notebook的两种方法总结
2018/05/24 Python
Python面向对象程序设计多继承和多态用法示例
2019/04/08 Python
Python 内置函数globals()和locals()对比详解
2019/12/23 Python
pytorch: Parameter 的数据结构实例
2019/12/31 Python
Python实现钉钉订阅消息功能
2020/01/14 Python
介绍一下Cookie和Session及他们之间的区别
2012/11/20 面试题
初中三年学生的学习自我评价
2013/11/13 职场文书
满月酒邀请函
2015/01/30 职场文书
2015年团队工作总结范文
2015/05/04 职场文书
Python Django ORM连表正反操作技巧
2021/06/13 Python
深入理解以DEBUG方式线程的底层运行原理
2021/06/21 Java/Android