基于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 24 Vue.js
vue表单验证之禁止input输入框输入空格
Dec 03 Vue.js
Vue中computed和watch有哪些区别
Dec 19 Vue.js
vue3.0自定义指令(drectives)知识点总结
Dec 27 Vue.js
Vue中使用wangeditor富文本编辑的问题
Feb 07 Vue.js
vue-router路由懒加载及实现的3种方式
Feb 28 Vue.js
vite2.0+vue3移动端项目实战详解
Mar 03 Vue.js
手写Vue2.0 数据劫持的示例
Mar 04 Vue.js
开发一个封装iframe的vue组件
Mar 29 Vue.js
详解Vue的sync修饰符
May 15 Vue.js
Vue h函数的使用详解
Feb 18 Vue.js
ant design vue的form表单取值方法
Jun 01 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
Sorting Array Values in PHP(数组排序)
2011/09/15 PHP
php中计算未知长度的字符串哪个字符出现的次数最多的代码
2012/08/14 PHP
PHP加Nginx实现动态裁剪图片方案
2014/03/10 PHP
PHP_NETWORK_GETADDRESSES: GETADDRINFO FAILED问题解决办法
2014/05/04 PHP
PHP通过插入mysql数据来实现多机互锁实例
2014/11/05 PHP
利用jQuery 实现GridView异步排序、分页的代码
2010/02/06 Javascript
JavaScript 判断指定字符串是否为有效数字
2010/05/11 Javascript
深入理解JavaScript系列(11) 执行上下文(Execution Contexts)
2012/01/15 Javascript
javascript 兼容所有浏览器的DOM扩展功能
2012/08/01 Javascript
后台获取ZTREE选中节点的方法
2015/02/12 Javascript
HTML页面,测试JS对C函数的调用简单实例
2016/08/09 Javascript
JS数组搜索之折半搜索实现方法分析
2017/03/27 Javascript
Angular2里获取(input file)上传文件的内容的方法
2017/09/05 Javascript
微信小程序报错:this.setData is not a function的解决办法
2017/09/27 Javascript
微信小程序radio组件使用详解
2018/01/31 Javascript
vue项目中跳转到外部链接的实例讲解
2018/09/20 Javascript
浅谈VueJS SSR 后端绘制内存泄漏的相关解决经验
2018/12/20 Javascript
在layui中select更改后生效的方法
2019/09/05 Javascript
jQuery实现弹幕特效
2019/11/29 jQuery
vue中路由跳转不计入history的操作
2020/09/21 Javascript
python逐行读写txt文件的实例讲解
2018/04/03 Python
Python实现字典(dict)的迭代操作示例
2018/06/05 Python
Appium+python自动化之连接模拟器并启动淘宝APP(超详解)
2019/06/17 Python
win10安装tesserocr配置 Python使用tesserocr识别字母数字验证码
2020/01/16 Python
美国最大的香水连锁店官网:Perfumania
2016/08/15 全球购物
Hotels.com日本:国外和海外住宿,酒店预订
2019/12/13 全球购物
文职个人求职信范文
2013/09/23 职场文书
口腔工艺技术专业毕业生自荐信
2013/09/27 职场文书
酒店总经理欢迎词
2014/01/08 职场文书
大学生志愿者活动总结
2014/06/27 职场文书
党员剖析材料范文
2014/09/30 职场文书
防火标语大全
2014/10/06 职场文书
医院保洁员岗位职责
2015/02/13 职场文书
同事打架检讨书
2015/05/06 职场文书
golang中的空slice案例
2021/04/27 Golang
用Python实现一个打字速度测试工具来测试你的手速
2021/05/28 Python