本文实例讲述了vue+elementUI实现表单和图片上传及验证功能。分享给大家供大家参考,具体如下:

最终实现需求如下图:

form表单内容与重点人员图片同时上传且图片为必填项

vue+elementUI实现表单和图片上传及验证功能示例

分析弹框页需要解决的问题有:

1、表单内容的验证及必填项

2、新增和编辑用同一个组件如何处理数据

3、图片需要和信息一起传递(即不允许自动上传)

4、图片必填的验证问题

针对上述问题作出方案:

1、el-form的表单验证需要注意几个地方:

a:el-form-item的prop值需要和表单标签的v-model值保持一致

例如:

<el-form-item label="姓名:" prop="name">
 <el-input style="width:1rem;" v-model="addKeyPersonForm.name" placeholder="请输入姓名"></el-input>
</el-form-item>

b:验证规则有直接用element官网提供的也有自定义的

例如:其中checkNumber就是自定义的验证数字的正则

rules: { // 表单验证
 name: [
  { required: true, message: '必填项', trigger: 'blur' }
 ],
 age: [
  { required: true, message: '必填项', trigger: 'blur' },
  { validator: checkNumber, trigger: 'blur' }
 ],
 sex: [
  { required: true, message: '必填项', trigger: ['blur', 'change'] }
 ],
 nationlity: [
  { required: true, message: '必填项', trigger: ['blur', 'change'] }
 ],
 userType: [
  { required: true, message: '必填项', trigger: ['blur', 'change'] }
 ],
 idCard: [
  { required: true, message: '必填项', trigger: 'blur' },
  { validator: checkIdCard, trigger: 'blur' }
 ],
 registered: [
  { required: true, type: 'array', message: '必填项', trigger: ['blur', 'change'] }
 ],
 registeredDetails: [
  { required: true, message: '必填项', trigger: 'blur' }
 ],
 domicile: [
  { required: true, type: 'array', message: '必填项', trigger: ['blur', 'change'] }
 ],
 domicileDetails: [
  { required: true, message: '必填项', trigger: 'blur' }
 ],
 file: [
  { required: true, message: '请上传图片' }
 ],
 plateNumber: [
  { validator: checkPlateNum, trigger: 'change' }
 ]
}

2、新增和编辑问题需要我们在打开组件的时候传递两个值

props: {
 dialogType: { //是新增还是编辑,用于判断
  type: String
 },
 keypersonList: { //表单的原始值
  type: Object
 }
}

3、图片和form表单内容一起上传

首先我们需要阻止图片的自动上传让它等到我们点击保存按钮的时候再一起传给后台

我们看这段代码就是图片上传组件

<el-upload class="upload-img"
      :style="{backgroundImage:'url(' + dialogImageUrl + ')', backgroundRepeat:'no-repeat', backgroundPosition:'center center', backgroundSize: 'contain'}"
      ref="uploadxls"
      action="aaa"
      ::limit="1"
      :show-file-list="false"
      :on-change="handlePictureCardPreview"
      :before-upload="beforeupload"
      accept="image/png,image/gif,image/jpg,image/jpeg">
 <i v-show="!dialogImageUrl" class="el-icon-upload avatar-uploader-icon"></i>
 <div v-show="!dialogImageUrl" slot="tip" class="el-upload__text upload__tip">上传照片</div>
</el-upload>

action我们随便填一个就好,重点是这一句:before-upload="beforeupload"在图片上传之前执行beforeupload方法在里面return false就可以实现阻止upload自动上传

// 阻止upload的自己上传,进行再操作
beforeupload (file) {
 this.formData.append('file', file)
 return false
}

关于图片和表单文件一起上传我们选择了formData格式存储数据用于上传

选择了图片并填写必填信息之后点击保存进行上传操作,在onSubmit方法里把表单信息都append到formData里that.$refs.uploadxls.submit() // 提交时触发了before-upload函数--》完成图片的上传即执行beforeupload方法

4、图片必填的验证问题:

a、如果没有选择图片点击保存则图片提示:请上传图片

vue+elementUI实现表单和图片上传及验证功能示例

b、此时选择了图片则“请上传图片”消失

vue+elementUI实现表单和图片上传及验证功能示例

验证规则里有一条file就是做图片必填验证的

file: [
 { required: true, message: '请上传图片' }
]

c、在编辑重点人员信息时重点人员图片已存在没有进行图片上传操作此时点击保存应该不提示“请上传图片”,未解决这个问题我们在上传时添加判断:

如果是编辑信息且未进行过图片上传操作则去掉file验证

就是以下代码

that.rules.file = [{ required: true, message: '请上传图片' }]
if (that.dialogType !== 'add' && !this.doUpload) {
 that.rules.file = []
 that.$refs['uploadElement'].clearValidate()
}

整个弹框组件的代码如下:

<template>
  <div class="add-keyperson-dialog">
   <el-form :inline="true"
        ref="addKeyPersonForm"
        :model="addKeyPersonForm"
        class="demo-form-inline"
        label-width="1.4rem"
        :rules="rules">
    <el-form-item label="姓名:" prop="name">
     <el-input style="width:1rem;" v-model="addKeyPersonForm.name" placeholder="请输入姓名"></el-input>
    </el-form-item>
    <el-form-item label="性别:" label-width="0.64rem" prop="sex">
     <el-select style="width:0.65rem;" v-model="addKeyPersonForm.sex" placeholder="请选择">
      <el-option label="男" value="1"></el-option>
      <el-option label="女" value="2"></el-option>
     </el-select>
    </el-form-item>
    <el-form-item label="年龄:" label-width="0.64rem" prop="age">
     <el-input style="width:0.65rem;" v-model="addKeyPersonForm.age" placeholder="请输入"></el-input>
    </el-form-item>
    <el-form-item prop="file" class="upload-img-form" ref="uploadElement">
     <el-upload class="upload-img"
           :style="{backgroundImage:'url(' + dialogImageUrl + ')', backgroundRepeat:'no-repeat', backgroundPosition:'center center', backgroundSize: 'contain'}"
           ref="uploadxls"
           action="aaa"
           ::limit="1"
           :show-file-list="false"
           :on-change="handlePictureCardPreview"
           :before-upload="beforeupload"
           accept="image/png,image/gif,image/jpg,image/jpeg">
      <i v-show="!dialogImageUrl" class="el-icon-upload avatar-uploader-icon"></i>
      <div v-show="!dialogImageUrl" slot="tip" class="el-upload__text upload__tip">上传照片</div>
     </el-upload>
    </el-form-item>
    <!--<img :src="/UploadFiles/2021-04-02/dialogImageUrl">


<script>
import options from '../../../static/js/country-data.js'
import PersonnelControlAdd from './PersonnelControlAdd.vue'
import axiosMap from './../../api/map'
import axiosControl from './../../api/control'
import PersonnelAddPosition from './PersonnelAddPosition.vue'
export default {
 components: {
  PersonnelAddPosition,
  PersonnelControlAdd},
 name: 'add-keyperson-dialog',
 props: {
  dialogType: {
   type: String
  },
  keypersonList: {
   type: Object
  }
 },
 computed: {
  position: { // 经纬度
   // getter
   get: function () {
    let str = ''
    if (this.addKeyPersonForm.longitude !== '' && this.addKeyPersonForm.latitude !== '' && this.addKeyPersonForm.longitude !== null && this.addKeyPersonForm.latitude !== null) {
     str = this.addKeyPersonForm.longitude + ',' + this.addKeyPersonForm.latitude
    }
    return str
   },
   // setter
   set: function (newValue) {
   }
  }
 },
 /* watch: {
  keypersonList: { // 深度监听,可监听到对象、数组的变化
   handler (newQuestion, oldQuestion) {
    this.addKeyPersonForm = Object.assign({}, this.keypersonList)
    this.dialogImageUrl = Object.assign({}, this.keypersonList).iconUrl
   },
   deep: true
  }
 }, */
 data () {
  var checkNumber = (rule, value, callback) => {
   let regEn = /^[1-9]\d*$/
   if (!regEn.test(value)) {
    callback(new Error('正整数'))
   } else {
    callback()
   }
  }
  var checkIdCard = (rule, value, callback) => {
   let regEn = /(^\d{15}$)|(^\d{18}$)|(^\d{17}(\d|X|x)$)/
   if (!regEn.test(value)) {
    callback(new Error('请输入正确身份证'))
   } else {
    // 校验位按照ISO 7064:1983.MOD 11-2的规定生成,X可以认为是数字10
    // 下面分别分析出生日期和校验位
    let num = value.toUpperCase()
    let len, re
    len = num.length
    if (len === 15) {
     re = new RegExp(/^(\d{6})(\d{2})(\d{2})(\d{2})(\d{3})$/)
     let arrSplit = num.match(re) // 检查生日日期是否正确
     let dtmBirth = new Date('19' + arrSplit[2] + '/' + arrSplit[3] + '/' + arrSplit[4])
     let bGoodDay
     bGoodDay = (dtmBirth.getYear() === Number(arrSplit[2])) && ((dtmBirth.getMonth() + 1) === Number(arrSplit[3])) && (dtmBirth.getDate() === Number(arrSplit[4]))
     if (!bGoodDay) {
      callback(new Error('请输入正确身份证'))
     } else { // 将15位身份证转成18位 //校验位按照ISO 7064:1983.MOD 11-2的规定生成,X可以认为是数字10
      let arrInt = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2]
      let arrCh = ['1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2']
      var nTemp = 0, i
      num = num.substr(0, 6) + '19' + num.substr(6, num.length - 6)
      for (i = 0; i < 17; i++) {
       nTemp += num.substr(i, 1) * arrInt[i]
      }
      num += arrCh[nTemp % 11]
      callback()
     }
    }
    if (len === 18) {
     re = new RegExp(/^(\d{6})(\d{4})(\d{2})(\d{2})(\d{3})([0-9]|X)$/)
     let arrSplit = num.match(re) // 检查生日日期是否正确
     let dtmBirth = new Date(arrSplit[2] + '/' + arrSplit[3] + '/' + arrSplit[4])
     let bGoodDay
     bGoodDay = (dtmBirth.getFullYear() === Number(arrSplit[2])) && ((dtmBirth.getMonth() + 1) === Number(arrSplit[3])) && (dtmBirth.getDate() === Number(arrSplit[4]))
     if (!bGoodDay) {
      callback(new Error('请输入正确身份证'))
     } else { // 检验18位身份证的校验码是否正确。 //校验位按照ISO 7064:1983.MOD 11-2的规定生成,X可以认为是数字10
      let valnum
      let arrInt = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2]
      let arrCh = ['1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2']
      var nTemp = 0, i
      for (i = 0; i < 17; i++) {
       nTemp += num.substr(i, 1) * arrInt[i]
      }
      valnum = arrCh[nTemp % 11]
      if (!isNaN(num.substr(17, 1))) {
       callback()
      }
      if (valnum !== num.substr(17, 1)) {
       callback(new Error('请输入正确身份证'))
      }
     }
    }
   }
  }
  var checkPlateNum = (rule, value, callback) => {
   if (value && value !== '') {
    let regEn = /(^[京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领A-Z]{1}[A-Z]{1}[A-Z0-9]{4}[A-Z0-9挂学警港澳]{1}$)/
    if (!regEn.test(value)) {
     callback(new Error('请输入正确车牌号'))
    } else {
     callback()
    }
   } else {
    callback()
   }
  }
  return {
   doSubmitFlag: false,
   showPosition: false,
   doUpload: false,
   keyPersonType: [], // 重点人员类型列表
   addKeyPersonForm: Object.assign({}, this.keypersonList),
   positionForm: {
    longtitude: this.keypersonList.longitude,
    latitude: this.keypersonList.latitude
   },
   options: options, // 存放城市数据,
   innerVisible: false, // 继续添加弹框
   dialogImageUrl: Object.assign({}, this.keypersonList).iconUrl, // 图片
   formData: new FormData(),
   rules: { // 表单验证
    name: [
     { required: true, message: '必填项', trigger: 'blur' }
    ],
    age: [
     { required: true, message: '必填项', trigger: 'blur' },
     { validator: checkNumber, trigger: 'blur' }
    ],
    sex: [
     { required: true, message: '必填项', trigger: ['blur', 'change'] }
    ],
    nationlity: [
     { required: true, message: '必填项', trigger: ['blur', 'change'] }
    ],
    userType: [
     { required: true, message: '必填项', trigger: ['blur', 'change'] }
    ],
    idCard: [
     { required: true, message: '必填项', trigger: 'blur' },
     { validator: checkIdCard, trigger: 'blur' }
    ],
    registered: [
     { required: true, type: 'array', message: '必填项', trigger: ['blur', 'change'] }
    ],
    registeredDetails: [
     { required: true, message: '必填项', trigger: 'blur' }
    ],
    domicile: [
     { required: true, type: 'array', message: '必填项', trigger: ['blur', 'change'] }
    ],
    domicileDetails: [
     { required: true, message: '必填项', trigger: 'blur' }
    ],
    file: [
     { required: true, message: '请上传图片' }
    ],
    plateNumber: [
     { validator: checkPlateNum, trigger: 'change' }
    ]
   }
  }
 },
 created () {
  this.getKeyPersonType()
 },
 methods: {
  handleChange (value) {
  },
  // 获取重点人员类型
  getKeyPersonType: function () {
   let that = this
   let param = {
    typeCodes: 'userType'
   }
   axiosMap.getKeyPersonType(param)
    .then(res => {
     if (res.data.code === 200) {
      that.keyPersonType = res.data.rows['0'].userType
      that.keyPersonType.forEach(function (item) {
       if (that.addKeyPersonForm.userType === item.dataValue) {
        that.addKeyPersonForm.userType = item.dataKey
       }
      })
      // that.keyPersonType.unshift({dataValue: '全部', dataKey: ''})
     } else {
      that.$message.error({
       message: res.data.message
      })
     }
    })
  },
  // 添加控制人员
  addPerson (person) {
   this.addKeyPersonForm.controller.push(person)
  },
  // 添加经纬度
  addPosition (position) {
   this.addKeyPersonForm.longitude = position[0]
   this.addKeyPersonForm.latitude = position[1]
   this.showPosition = false
  },
  // 删除某个控制人员
  deleteRow (index) {
   this.addKeyPersonForm.controller.splice(this.addKeyPersonForm.controller[index], 1)
  },
  // 关闭新增控制人员
  closeFun () {
   this.$refs.addForm.$refs.controlForm.resetFields()
   this.innerVisible = false
  },
  // 关闭经纬度
  closePosition () {
   // this.$refs.addPosition.$refs.addPosition.resetFields()
   this.showPosition = false
  },
  // 图片预览
  handlePictureCardPreview (file) {
   this.dialogImageUrl = file.url
   this.addKeyPersonForm.file = file.url
   this.doUpload = true
   this.$refs['addKeyPersonForm'].validateField('file')
  },
  // 阻止upload的自己上传,进行再操作
  beforeupload (file) {
   this.formData.append('file', file)
   return false
  },
  // 上传重点人员信息
  onSubmit: function () {
   let that = this
   that.formData = new FormData()
   that.rules.file = [{ required: true, message: '请上传图片' }]
   if (that.dialogType !== 'add' && !this.doUpload) {
    that.rules.file = []
    that.$refs['uploadElement'].clearValidate()
   }
   that.$refs['addKeyPersonForm'].validate((valid) => {
    if (valid) {
     that.formData.append('name', that.addKeyPersonForm.name)
     if (that.addKeyPersonForm.sex === '男') {
      that.addKeyPersonForm.sex = 1
     } else if (that.addKeyPersonForm.sex === '女') {
      that.addKeyPersonForm.sex = 2
     }
     that.formData.append('sex', that.addKeyPersonForm.sex)
     that.formData.append('age', that.addKeyPersonForm.age)
     that.formData.append('idCard', that.addKeyPersonForm.idCard)
     that.formData.append('nationlity', that.addKeyPersonForm.nationlity)
     that.formData.append('plateNumber', that.addKeyPersonForm.plateNumber)
     that.formData.append('userType', that.addKeyPersonForm.userType)
     that.formData.append('longitude', that.addKeyPersonForm.longitude)
     that.formData.append('latitude', that.addKeyPersonForm.latitude)
     that.formData.append('registered', that.addKeyPersonForm.registered.join('-'))
     that.formData.append('registeredDetails', that.addKeyPersonForm.registeredDetails)
     that.formData.append('domicile', that.addKeyPersonForm.domicile.join('-'))
     that.formData.append('domicileDetails', that.addKeyPersonForm.domicileDetails)
     that.formData.append('problem', that.addKeyPersonForm.problem)
     that.formData.append('measure', that.addKeyPersonForm.measure)
     that.formData.append('controller', JSON.stringify(that.addKeyPersonForm.controller))
     that.formData.append('remark', that.addKeyPersonForm.remark)
     if (that.dialogType === 'add') {
      that.$refs.uploadxls.submit() // 提交时触发了before-upload函数
      that.doSubmitFlag = true
      axiosControl.saveNewKeyPerson(that.formData)
       .then(res => {
        that.doSubmitFlag = false
        if (res.data.code === 200) {
         that.$message({
          type: 'success',
          message: '添加成功'
         })
         that.$refs.addKeyPersonForm.dialogImageUrl = 'none'
         that.$refs.uploadxls.clearFiles()
         that.$refs.addKeyPersonForm.resetFields()
         that.fileName = ''
         that.uploadForm = new FormData()
         that.$emit('savePersonSuccess')
        } else {
         that.$message.error({
          message: res.data.message
         })
        }
       })
       /* .catch(err => {
        that.$message.error({
         message: err
        })
       }) */
     } else {
      if (!that.doUpload) {
       that.formData.append('iconUrl', that.addKeyPersonForm.iconUrl)
      }
      // 还要传id
      that.formData.append('id', that.addKeyPersonForm.id)
      that.doSubmitFlag = true
      axiosControl.saveEditKeyPerson(that.formData)
       .then(res => {
        that.doSubmitFlag = false
        if (res.data.code === 200) {
         that.$message({
          type: 'success',
          message: '添加成功'
         })
         that.$refs.addKeyPersonForm.dialogImageUrl = 'none'
         that.$refs.uploadxls.clearFiles()
         that.$refs.addKeyPersonForm.resetFields()
         that.fileName = ''
         that.uploadForm = new FormData()
         that.$emit('savePersonSuccess')
        } else {
         that.$message.error({
          message: res.data.message
         })
        }
       })
     }
    } else {
     this.$message({
      type: 'warning',
      message: '请填写正确格式'
     })
     return false
    }
   })
  }
 }
}
</script>

<style scoped>
 .add-keyperson-dialog{
  position:relative;
  height:7.2rem;
  overflow:auto;
 }
 .add-keyperson-dialog .demo-form-inline{
  font-size:0.13rem;
  color:#666;
 }
 /*上传图片样式*/
 .add-keyperson-dialog .upload-img-form{
  width: 1rem;
  height: 1.35rem;
  position: absolute;
  right:0.2rem;
  top:0rem;
  border: 1px dashed #d9d9d9;
  border-radius: 6px;
  cursor: pointer;
  text-align: center;
 }
 .add-keyperson-dialog .upload-img{
  width: 1rem;
  height: 1.35rem;
  overflow:hidden;
 }
 .add-keyperson-dialog .upload-img:hover {
  border-color: #409EFF;
  color: #409EFF;
 }
 .add-keyperson-dialog .avatar-uploader-icon {
  position:relative;
  z-index:100;
  font-size: 0.3rem;
  color: #8c939d;
  width: 0.9rem;
  height: 1.35rem;
  line-height: 1rem;
  text-align: center;
 }
 .add-keyperson-dialog .upload-img:hover .avatar-uploader-icon {
  color: #409EFF
 }
 .add-keyperson-dialog .avatar {
  width: 100%;
  height: auto;
  display: block;
 }
 .add-keyperson-dialog .upload__tip {
  font-size: 0.13rem;
  text-align: center;
  position: relative;
  z-index:10;
  top: -0.7rem;
 }
</style>

希望本文所述对大家vue.js程序设计有所帮助。

华山资源网 Design By www.eoogi.com
广告合作:本站广告合作请联系QQ:858582 申请时备注:广告合作(否则不回)
免责声明:本站资源来自互联网收集,仅供用于学习和交流,请遵循相关法律法规,本站一切资源不代表本站立场,如有侵权、后门、不妥请联系本站删除!
华山资源网 Design By www.eoogi.com

《魔兽世界》大逃杀!60人新游玩模式《强袭风暴》3月21日上线

暴雪近日发布了《魔兽世界》10.2.6 更新内容,新游玩模式《强袭风暴》即将于3月21 日在亚服上线,届时玩家将前往阿拉希高地展开一场 60 人大逃杀对战。

艾泽拉斯的冒险者已经征服了艾泽拉斯的大地及遥远的彼岸。他们在对抗世界上最致命的敌人时展现出过人的手腕,并且成功阻止终结宇宙等级的威胁。当他们在为即将于《魔兽世界》资料片《地心之战》中来袭的萨拉塔斯势力做战斗准备时,他们还需要在熟悉的阿拉希高地面对一个全新的敌人──那就是彼此。在《巨龙崛起》10.2.6 更新的《强袭风暴》中,玩家将会进入一个全新的海盗主题大逃杀式限时活动,其中包含极高的风险和史诗级的奖励。

《强袭风暴》不是普通的战场,作为一个独立于主游戏之外的活动,玩家可以用大逃杀的风格来体验《魔兽世界》,不分职业、不分装备(除了你在赛局中捡到的),光是技巧和战略的强弱之分就能决定出谁才是能坚持到最后的赢家。本次活动将会开放单人和双人模式,玩家在加入海盗主题的预赛大厅区域前,可以从强袭风暴角色画面新增好友。游玩游戏将可以累计名望轨迹,《巨龙崛起》和《魔兽世界:巫妖王之怒 经典版》的玩家都可以获得奖励。