首页 > 其他分享 >vue+vant移动端制作一个可添加的form提交表单

vue+vant移动端制作一个可添加的form提交表单

时间:2022-12-14 11:46:25浏览次数:42  
标签:vue false vant form 表单 item Notify return mus

<template>
  <van-nav-bar
    title="填写参会人员信息"
    left-text="返回"
    left-arrow
    @click-left="onClickLeft"
  />
  
  <!-- 添加参会人员信息 -->
  <div class="content">
    <div class="array" v-for="item,index in mus" :key="index">
      <p class="form-title">参会人员表单</p>
      <van-form>
        <van-cell-group inset>
          <van-button class="del-btn" size="small" icon="delete-o" type="danger" @click="deleteItem"></van-button>
          <!-- 姓名 -->
          <van-field
            required
            v-model="item.name"          
            label="姓名"
            placeholder="姓名"
            :rules="[{ required: true, message: '请填写姓名' }]"
          />
          <!-- 职务 -->
          <van-field
            required
            v-model="item.post"
            label="职务"
            placeholder="职务"
            :rules="[{ required: true, message: '请填写职务' }]"
          />
          <!-- 性别 -->
          <van-field required name="radio" label="性别">
            <template #input>
              <van-radio-group v-model="item.sex" direction="horizontal">
                <van-radio name="1">男</van-radio>
                <van-radio name="0">女</van-radio>
              </van-radio-group>
            </template>
          </van-field>
          <!-- 联系电话 -->
          <van-field
            required
            v-model="item.phone"
            label="联系电话"
            placeholder="联系电话"
            type="tel"
            :rules="[{ required: true, message: '请填写联系电话' }]"
          />
          <!-- 现居地址 -->
          <van-field
            required
            v-model="item.liveCounty"
            is-link
            readonly
            label="现居地址"
            placeholder="点击选择省市区"
            @click="item.showArea = true"
          />
          <van-popup v-model:show="item.showArea" position="bottom">
            <van-area
              :area-list="areaList"
              @confirm="onConfirmArea($event,index)"
              @cancel="item.showArea = false"
            />
          </van-popup>
          <van-field  required name="radio" label="居住要求">
            <template #input>
              <van-radio-group v-model="item.stay" direction="horizontal">
                <van-radio name="0">不住宿</van-radio>
                <van-radio name="1">单间</van-radio>
                <van-radio name="2">两人合住</van-radio>
              </van-radio-group>
            </template>
          </van-field>
          <!-- 交通信息 -->
          <van-field required name="radio" label="交通信息">
            <template #input>
              <van-radio-group v-model="item.travel" direction="horizontal">
                <van-radio name="0">自驾</van-radio>
                <van-radio name="1">高铁</van-radio>
                <van-radio name="2">飞机</van-radio>
              </van-radio-group>
            </template>
          </van-field>
          <!-- 预计到达时间 -->
          <van-field
            required
            v-model="item.arriveTime"
            is-link
            readonly
            name="datetimePicker"
            label="预计到达时间"
            placeholder="点击选择时间"
            @click="item.showArriveTime = true"
          />
          <van-popup v-model:show="item.showArriveTime" position="bottom">
            <van-datetime-picker
              type="datetime"
              :min-date="minDate"
              :max-date="maxDate"
              @confirm="onConfirmArriveTime($event,index)"
              @cancel="item.showArriveTime = false"
            />
          </van-popup>
          <!-- 是否接站 -->
          <van-field required name="radio" label="是否接站">
            <template #input>
              <van-radio-group v-model="item.isReceive" direction="horizontal">
                <van-radio name="1">是</van-radio>
                <van-radio name="0">否</van-radio>
              </van-radio-group>
            </template>
          </van-field>
          <!-- 预计返程时间 -->
          <van-field
            required
            v-model="item.leaveTime"
            is-link
            readonly
            name="datetimePicker"
            label="预计返程时间"
            placeholder="点击选择时间"
            @click="item.showLeaveTime = true"
          />
          <van-popup v-model:show="item.showLeaveTime" position="bottom">
            <van-datetime-picker
              type="datetime"
              :min-date="minDate"
              :max-date="maxDate"
              @confirm="onConfirmLeaveTime($event,index)"
              @cancel="item.showLeaveTime = false"
            />
          </van-popup>
          <!-- 是否送站 -->
          <van-field required name="radio" label="是否送站">
            <template #input>
              <van-radio-group v-model="item.isSend" direction="horizontal">
                <van-radio name="1">是</van-radio>
                <van-radio name="0">否</van-radio>
              </van-radio-group>
            </template>
          </van-field>
          <!-- 发票抬头名称 -->
          <van-field
            required
            v-model="item.invoiceTitle"          
            label="发票抬头名称"
            placeholder="发票抬头名称"
            :rules="[{ required: true, message: '请填写发票抬头名称' }]"
          />
           <!-- 发票类型 -->
           <van-field required name="radio" label="发票类型">
            <template #input>
              <van-radio-group v-model="item.invoiceType" direction="horizontal">
                <van-radio name="1">增值税普通发票</van-radio>
                <van-radio name="0">增值税专用发票</van-radio>
              </van-radio-group>
            </template>
          </van-field>
          <!-- 税号 -->
          <van-field
            required
            v-model="item.tin"          
            label="税号"
            placeholder="税号"
            :rules="[{ required: true, message: '请填写税号' }]"
          />
          <!-- 开户行及账号 -->
          <van-field
            required
            v-model="item.bank"          
            label="开户行及账号"
            placeholder="开户行及账号"
            :rules="[{ required: true, message: '请填写开户行及账号' }]"
          />
          <!-- 地址及电话 -->
          <van-field
            required
            v-model="item.addressPhone"          
            label="地址及电话"
            placeholder="地址及电话"
            :rules="[{ required: true, message: '请填写地址及电话' }]"
          />
          <!-- 备注 -->
          <van-field
            v-model="item.remark"          
            label="备注"
            placeholder="备注"
            :rules="[{ required: false, message: '请填写备注' }]"
          />
        </van-cell-group>     
      </van-form>
    </div>
      <div class="btn">
        <van-button type="primary" block icon="plus" plain @click="addItem">点击这里添加更多</van-button>
      </div>
  </div>
  <div class="btn">
    <van-button type="primary" block  :disabled="disabled" @click="saveOrUpdate">提交</van-button>
  </div>
</template>
<script>
  import { saveOrUpdate,getExistMu,getHotel} from 'network/mu'
  import { NavBar,Form, Field, CellGroup,Button,Icon,Toast,Radio,RadioGroup,Popup,Area,DatetimePicker,Notify } from 'vant';
  import { areaList } from '@vant/area-data';
  import {formatDate,isEmpty,mobileValidate} from 'common/utils'

  export default {
    name:'Person',

    components: {
        [NavBar.name]: NavBar,
        [Form.name]: Form,
        [Field.name]: Field,
        [CellGroup.name]: CellGroup,
        [Button.name]: Button,
        [Radio.name]: Radio,
        [RadioGroup.name]: RadioGroup,
        [Popup.name]: Popup,
        [Area.name]: Area,
        [DatetimePicker.name]: DatetimePicker,
        [Notify.name]: Notify,
        [Toast.name]: Toast
    },

    data(){
      return{
        person: JSON.parse(decodeURIComponent(this.$route.query.person)),
        mus: [],
        result: '',
        areaList,
        showArea: false,
        minDate: new Date(2022, 11, 1),
        maxDate: new Date(2050, 1, 1),
        currentDate: new Date(),
        showArriveTime: false,
        showLeaveTime: false,
        hotel: {},
        showHotel: false,
        disabled: false
      }
    },

    computed: {
    },

    methods: {
      /**
       * 返回
       */
      onClickLeft(){
        this.$router.back()
      },

      //添加表单
      addItem(e){
        if(this.mus.length === 2){
          Notify({ type: 'danger', message: '最多只能添加两个人员' })
          return
        }
        this.mus.push(
          {showArea:false,showArriveTime:false,showLeaveTime:false}
        )
      },

      //删除行
      deleteItem(index){
        this.mus.splice(index,1)
      },

      //地区选择
      onConfirmArea(areaValues,index){
        this.mus[index].showArea = false
        this.mus[index].liveCounty = areaValues.filter(item => !!item).map(item => item.name).join('/')
      },

      //打开到达时间选择
      onConfirmArriveTime(value,index){
        this.mus[index].arriveTime = formatDate(value)
        this.mus[index].showArriveTime = false
      },

      //打开到达时间选择
      onConfirmLeaveTime(value,index){
        this.mus[index].leaveTime = formatDate(value)
        this.mus[index].showLeaveTime = false
      },

      /**
       * 新增或修改
       */
      saveOrUpdate(){
        if(!this.checkData()){
          return
        }
        Toast.loading({
          duration: 0,
          message: '提交中...',
          forbidClick: true,
        });
        this.disabled = true
        //构建提交form
        const data = {
          meetId: this.person.meetId,
          erp: this.person.erp,
          supplierName: this.person.supplierName,
          mus: this.mus
        }
        saveOrUpdate(data).then(res => {
          if(res.code === 200){
            //关闭提醒
            Toast.clear()
            //设置按钮为常量
            this.disabled = false
            //跳转到成功页面
            this.$router.push('/success')
          }else{
            Toast.fail(res.msg)
            this.disabled = false
          }
        },err => {
          Toast.fail('系统错误')
          this.disabled = false
        })
      },

      /**
       * 校验数据的合法性
       */
      checkData(){
        const mus = this.mus
        if(mus.length === 0){
          Notify({type: 'danger',message:'请创建表单填写参会人员'})
          return false
        }

        for(let i = 0; i< mus.length; i++){
          let num = i+1
          if(isEmpty(mus[i].name)){
            Notify({type: 'danger',message:'表单'+num+'的姓名不能为空'})
            return false
          }
          if(isEmpty(mus[i].post)){
            Notify({type: 'danger',message: '表单'+num+'的职务不能为空'})
            return false
          }
          if(isEmpty(mus[i].sex)){
            Notify({type: 'danger',message: '表单'+num+'的性别不能为空'})
            return false
          }
          if(isEmpty(mus[i].phone)){
            Notify({type: 'danger',message: '表单'+num+'的联系电话不能为空'})
            return false
          }
          if(!mobileValidate(mus[i].phone)){
            Notify({type: 'danger',message: '表单'+num+'的联系电话格式不正确'})
            return false
          }
          if(isEmpty(mus[i].liveCounty)){
            Notify({type: 'danger',message: '表单'+num+'的现居地址不能为空'})
            return false
          }
          if(isEmpty(mus[i].stay)){
            Notify({type: 'danger',message: '表单'+num+'的居住要求不能为空'})
            return false
          }
          if(isEmpty(mus[i].travel)){
            Notify({type: 'danger',message: '表单'+num+'的交通信息不能为空'})
            return false
          }
          if(isEmpty(mus[i].arriveTime)){
            Notify({type: 'danger',message: '表单'+num+'的预计到达时间不能为空'})
            return false
          }
          if(isEmpty(mus[i].isReceive)){
            Notify({type: 'danger',message: '表单'+num+'的是否接站不能为空'})
            return false
          }
          if(isEmpty(mus[i].leaveTime)){
            Notify({type: 'danger',message: '表单'+num+'的预计返程时间不能为空'})
            return false
          }
          if(isEmpty(mus[i].isSend)){
            Notify({type: 'danger',message: '表单'+num+'的是否送站不能为空'})
            return false
          }
          if(isEmpty(mus[i].invoiceTitle)){
            Notify({type: 'danger',message: '表单'+num+'的发票抬头名称不能为空'})
            return false
          }
          if(isEmpty(mus[i].invoiceType)){
            Notify({type: 'danger',message: '表单'+num+'的发票类型不能为空'})
            return false
          }
          if(isEmpty(mus[i].tin)){
            Notify({type: 'danger',message: '表单'+num+'的税号不能为空'})
            return false
          }
          if(isEmpty(mus[i].bank)){
            Notify({type: 'danger',message: '表单'+num+'的开户行及账号不能为空'})
            return false
          }
          if(isEmpty(mus[i].addressPhone)){
            Notify({type: 'danger',message: '表单'+num+'的地址及电话不能为空'})
            return false
          }
        }
        return true
      },

      /**
       * 获取已存在的参会人员信息
       */
      getExistMu(){
         Toast.loading({
          duration: 0,
          message: '加载中...',
          forbidClick: true,
        });
        //封装请求参数
        const me = {
          meetId: this.person.meetId,
          erp: this.person.erp
        }
        getExistMu(me).then(res => {
          if(res.code === 200){
            res.mus.forEach(item =>{
              this.mus.push({
                id: item.id,
                name: item.name,
                post: item.post,
                sex: item.sex.toString(),
                phone: item.phone,
                liveCounty: item.liveCounty,
                stay: item.stay.toString(),
                travel: item.travel.toString(),
                arriveTime: item.arriveTime,
                isReceive: item.isReceive.toString(),
                leaveTime: item.leaveTime,
                isSend: item.isSend.toString(),
                invoiceTitle: item.invoiceTitle,
                invoiceType: item.invoiceType.toString(),
                tin: item.tin,
                bank: item.bank,
                addressPhone: item.addressPhone,
                remark: item.remark,
                showArea:false,
                showArriveTime:false,
                showLeaveTime:false
              })
            })
            Toast.clear()
          }else{
            Toast.fail(res.msg)
          }
        },err =>{
          Toast.fail('系统错误')
        })
      },

      /**
       * 获取酒店详情
       */
      getHotel(){
        getHotel().then(res => {
          if(res.code === 200){
            if(res.hotel != null){
              this.hotel = res.hotel
              this.showHotel = true
            }
          }else{
            Toast.fail(res.msg)
          }
        },err => {
          Toast.fail('系统错误')
        })
      }

    },

    //生命周期函数
    mounted(){
      this.getExistMu()
      this.getHotel()
    }

  };
</script>
<style scoped>
  .form-title{
    color: rgba(69,90,100,.6);
    font-size: 14px;
    margin: 20px 16px 5px 16px;
  }
  .del-btn{
    float: right;
    border-radius: 0 0 0 8px; 
  }
  .btn{
    margin: 16px 16px;
  }
  .delete{
    background-color: red;
    color: #fff;
  }
  .hotel-notify{
    color: #9fa4a4;
    font-size: 13px;
    line-height: 22px;
    padding: 16px 16px 0 16px;
  }
  .hotel-info{
    color: #000;
  }
</style>

效果:

 

标签:vue,false,vant,form,表单,item,Notify,return,mus
From: https://www.cnblogs.com/chen-guo-liang/p/16981637.html

相关文章

  • Vuex极速入门
    01、什么是Vuex?1.1、为什么需要状态管理?在复杂的系统中,我们会把系统按照业务逻辑拆分为多个层次、多个模块,采用组件式的开发方式。而此时不同模块、父子模块之间的通信......
  • 在vue的v-for中,key为什么不能用index?
    写在前面在前端中,主要涉及的基本上就是DOM的相关操作和JS,我们都知道DOM操作是比较耗时的,那么在我们写前端相关代码的时候,如何减少不必要的DOM操作便成了前端优化的......
  • 写过vue自定义指令吗,原理是什么?.m
    背景看了一些自定义指令的文章,但是探究其原理的文章却不多见,所以我决定水一篇。如何自定义指令?其实关于这个问题官方文档上已经有了很好的示例的,我们先来温故一下。除......
  • 常见经典vue面试题(面试必问)
    MVVM的优缺点?优点:分离视图(View)和模型(Model),降低代码耦合,提⾼视图或者逻辑的重⽤性:⽐如视图(View)可以独⽴于Model变化和修改,⼀个ViewModel可以绑定不同的"View"上,当Vie......
  • 常考vue面试题(附答案)
    Vue生命周期钩子是如何实现的vue的生命周期钩子就是回调函数而已,当创建组件实例的过程中会调用对应的钩子方法内部会对钩子函数进行处理,将钩子函数维护成数组的形式V......
  • Vue笔记4--组件和插槽
    1、组件基础Vue的特点:组件开发。页面将为是一颗嵌套的组件树src目录下有个components,组件都放在其中。组件首字母一般为大写。组件是带有名称可复用的实例。1.1vue2做......
  • 搞清webpack、vite、vue-cli、create-vue的区别
    1.要区分脚手架、构建项目、打包代码的概念1.1脚手架:创建项目,选择性安装需要的插件,指定统一的风格,生成demo。(vue-cli和create-vue是由vue提供的脚手架,创建项目时......
  • 基于Vision Transformers的文档理解简介
    文档理解是从pdf、图像和Word文档中提取关键信息的技术。这篇文章的目标是提供一个文档理解模型的概述。文档理解算法使用编码器-解码器结构分析文档内容,该管道结合了计算......
  • 用 TFormatSettings 日期格式处理
    有小伙伴想把日期转换为Excel那样的格式,如下图,比如:2022年3月9日显示为:9-Mar-22代码如下:varFS:=TFormatSettings.Create('en-US');varStr:=FormatDateTime('......
  • 开源的vue优秀的UI组件库主要用于后台管理系统和移动端的制作
    vue作为一款深受广大群众以及尤大崇拜者的喜欢,特此列出在github上开源的vue优秀的UI组件库供大家参考这几套框架主要用于后台管理系统和移动端的制作,方便开发者快速开发E......