基于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实现广告栏上下滚动效果
Nov 26 Vue.js
Vue如何实现验证码输入交互
Dec 07 Vue.js
vue使用exif获取图片经纬度的示例代码
Dec 11 Vue.js
vue实现两个区域滚动条同步滚动
Dec 13 Vue.js
vue+element UI实现树形表格
Dec 29 Vue.js
Vue实现图书管理案例
Jan 20 Vue.js
Vue实现todo应用的示例
Feb 20 Vue.js
vue 动态添加的路由页面刷新时失效的原因及解决方案
Feb 26 Vue.js
vue中三级导航的菜单权限控制
Mar 31 Vue.js
Vue的过滤器你真了解吗
Feb 24 Vue.js
vue的项目如何打包上线
Apr 13 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
《PHP边学边教》(02.Apache+PHP环境配置――下篇)
2006/12/13 PHP
php实现简单文件下载的方法
2015/01/30 PHP
php约瑟夫问题解决关于处死犯人的算法
2015/03/23 PHP
使用PHP编写发红包程序
2015/07/22 PHP
php计算title标题相似比的方法
2015/07/29 PHP
php实现XSS安全过滤的方法
2015/07/29 PHP
js下用层来实现select的title提示属性
2010/02/23 Javascript
微博@符号的用户名提示效果。(想@到谁?)
2010/11/05 Javascript
读jQuery之一(对象的组成)
2011/06/11 Javascript
jquery ajax 同步异步的执行 return值不能取得的解决方案
2012/01/08 Javascript
jQuery中判断对象是否存在的方法汇总
2016/02/24 Javascript
JavaScript手机振动API
2016/06/11 Javascript
Vue.js 2.0学习教程之从基础到组件详解
2017/04/24 Javascript
vue路由切换之淡入淡出的简单实现
2019/10/31 Javascript
JavaScript实现公告栏上下滚动效果
2020/03/13 Javascript
JS array数组检测方式解析
2020/05/19 Javascript
python解析xml文件实例分享
2013/12/04 Python
c++生成dll使用python调用dll的方法
2014/01/20 Python
用Python制作在地图上模拟瘟疫扩散的Gif图
2015/03/31 Python
python开启多个子进程并行运行的方法
2015/04/18 Python
python+flask实现API的方法
2018/11/21 Python
Python3搭建http服务器的实现代码
2020/02/11 Python
Python面向对象中类(class)的简单理解与用法分析
2020/02/21 Python
Scrapy模拟登录赶集网的实现代码
2020/07/07 Python
Python偏函数实现原理及应用
2020/11/20 Python
AmazeUI 评论列表的实现示例
2020/08/13 HTML / CSS
全球知名提供各类营养保健品的零售商:Vitamin Shoppe
2016/10/09 全球购物
美国校园市场:OCM
2017/06/08 全球购物
介绍一下JNDI的基本概念
2013/07/26 面试题
《蝙蝠和雷达》教学反思
2014/04/23 职场文书
电视新闻稿
2015/07/17 职场文书
描写九月优美句子(39条)
2019/09/11 职场文书
python 定义函数 返回值只取其中一个的实现
2021/05/21 Python
Python访问Redis的详细操作
2021/06/26 Python
postgresql 删除重复数据案例详解
2021/08/02 PostgreSQL
Python学习之os包使用教程详解
2022/03/21 Python