微信小程序实现仿钉钉报销页面新增报销明细功能

先上一个效果图,要实现的效果就是报销明细的组别里,填写相应的字段,点击新增一条报销,可以在组别里增加一组。提交时计算出报销的总金额,确认无误后提交。
在这里插入图片描述

UI组件我这边使用的是vant weapp组件库

第一步是基础的组件json配置

{
  "usingComponents": {
    "van-field": "@vant/weapp/field/index",
    "van-button": "@vant/weapp/button/index"
  }
}

首先,我们先对初始的页面进行布局,本来我是想将所有的可见项都放进一个form表单中一起提交,但是碍于接口采用了报销明细条目特殊符号拼接的传参方式,如果全部放进去,遍历表单数据的时候会不方便,所以,我只把明细组别里的数据放进表单中。

wxml:

<view class="container">

<view class="form-group-title-box">
    <text class="form-group-title">
      审核单号
    </text>
  </view>
  <view class="background">
    <van-field label='审核单号' value="{{orderNumText}}" bind:change = onOrderNumChange/>
  </view>

  <view class="form-group-title-box">
    <text class="form-group-title">
      申请人姓名
    </text>
  </view>
  <view class="background">
    <van-field name="username" label='用户名' value="{{nameText}}" bind:change = onUserNameChange/>
  </view>

  <view class="form-group-title-box">
    <text class="form-group-title">
      申请人所属部门
    </text>
  </view>
  <view class="background">
    <van-field name="department" label='部门' value="{{depText}}" bind:change = onDepNameChange/>
  </view>

<form class="form" catchsubmit="formSubmit">
  <view class="form-group-title-box">
    <text class="form-group-title">
      报销明细
    </text>
  </view>
  <view class="detail-container{{index}}" wx:for="{{subs}}">
    <picker bindchange="bindPickerChange" value="{{pickerIndex}}" range="{{array}}" data-index="{{index}}">
      <view class="picker" id='type-input-{{index}}'>
        <!-- <van-field name="typeText-{{index}}" id='type-input-{{index}}' label='类别' value="{{subs[index].typename}}" bind:change = onTypenNameChange/> -->
        <view class="picker-inner-title">类别</view>
        <text class="picker-inner-text">{{subs[index].typename}}</text>
      </view>
    </picker>
    <van-field name="use-{{index}}" label='用途' value="{{subs[index].memo}}" bind:change = "onUseChange" data-index="{{index}}"/>
    <van-field name="amount-{{index}}" label='金额(元)' value="{{subs[index].fee}}" bind:change = "onAmountChange" data-index="{{index}}" type="number"/>
    <van-field name="appendix-{{index}}" label='附件上传' value="{{subs[index].imgurl}}" bind:change = "onAppendixChange" bindtap="choosePic" data-index="{{index}}"/>
    <view class="group-separator"></view>
  </view>
  <view class="add-new-button" bindtap="handleAddNew" data-index="{{subs}}">+ 新增一条报销</view>


  <button style="margin: 30rpx 0" type="primary" formType="submit">提交</button>
</form>
</view>

wxss:

.form-group-title-box  {
  padding-left: 8px;
  padding-bottom: 8px;
}

.form-group-title {
  color: rgb(132, 145, 151);
  font-size: 12px;
}

.group-separator {
  background-color: rgb(245, 246, 249);
  height: 8px;
}

.add-new-button {
  height: 44px;
  text-align: center;
}

.add-new-button {
  font-size: 16px;
  color: rgb(24, 113, 248);
}


.submit-button {
  display: flex;
  flex-direction: row;
  justify-content: center;
  align-items: center;
  background-color: rgb(24, 113, 248);
  height: 50px;
}
.picker {
  display: flex;
  flex-direction: row;
  align-items: center;
  height: 40px; 
  background-color: white
}

.picker-inner-title {
  width: 100px;
  padding-left: 16px;
  font-size: 14px;
  color: rgb(100, 101, 102);
}

.picker-inner-text {
  font-size: 14px;
}

.submit-button-inner-text {
  font-size: 14px;
  color: white;
  text-align: center;
}

page {
  height: 100%;
  background-color: rgb(245, 246, 249)
}

写js之前想到一个问题,需求是报销的申请是可以回来查看的,所以,只能使用map+数组的形式来构建列表,这样问题就来了,我填写完一组后,新增一组,我该如何把之前已经填写的那一组放进列表数组里去呢。。。,不解决这个问题,填写完一组新增就白写了。。。

本来我一开始的做法是,声明一个文件内的全局对象,每次监听到input值变化的时候,我就更新那个对象,新增时,将这个对象push进数组,不过事实证明,我想多了,这样push进来了,但是数组是倒着的。。。,只能另想一个解决方案。

我为啥不直接修改数组里面每一个对象的属性呢,但是,setData可以修改属性对象里面的值吗,最后,我找到了方法

js

Page({
  data: {
    array: ['差旅费', '误餐费', '招待费', '燃料费', '过桥过路费', '办公费', '电话费', '房租', '水电', '运费', '取暖费', '修理费', '其他'],
    orderNumText: '10000922222',
    nameText: wx.getStorageSync('userinfo').opername,
    depText: wx.getStorageSync('userinfo').depname,
    namePlaceholder: '请输入姓名',
    depPlaceholder: '请输入部门',
    orderText: '单据号',
    pickerIndex: 0,
    dic: {
      typename: '',
      memo: '',
      fee: '',
      imgurl: '',
    },
    subs: [{
      typename: '',
      memo: '',
      fee: '',
      imgurl: '',
    }],
    imgurl: ''
  },

  handleAddNew: function (e) {
    // console.log(this.data.dic)
    // this.data.subs.push(this.data.dic)
    console.log(this.data.subs)
    var newDic = {
      typename: '',
      memo: '',
      fee: '',
      imgurl: '',
    }
    this.data.subs.push(newDic)
    this.setData({
      subs: this.data.subs
    })
    console.log(this.data.subs)
  },
  onOrderNumChange: function(e) {
    this.setData({
      orderNumText: e.detail
    })
  },
  onUserNameChange: function(e) {
    this.setData({
      nameText: e.detail
    })
  },
  onDepNameChange: function(e) {
    this.setData({
      depText: e.detail
    })
  },
  onTypenNameChage: function (e) {
    console.log('onTypenNameChage')
    var val = e.detail
    let index = e.currentTarget.dataset.index
    let typename = 'subs['+ index +'].typename'
    this.setData({
      [typename]: val
    })
  },
  onUseChange: function (e) {
    var val = e.detail
    let index = e.currentTarget.dataset.index
    let memo = 'subs['+ index +'].memo'
    this.setData({
      [memo]: val
    })
  },
  onAmountChange: function (e) {
    var val = e.detail
    let index = e.currentTarget.dataset.index
    let fee = 'subs['+ index +'].fee'
    this.setData({
      [fee]: val
    })
  },
  onAppendixChange: function (e) {
  },
  bindPickerChange: function (e) {
    // console.log('bindPickerChange')
    // this.setData({
    //   pickerIndex: e.detail.value
    // })
    var obj = e.detail
    var val = this.data.array[obj.value]
    console.log(this.data.array)
    let index = e.currentTarget.dataset.index
    let typename = 'subs['+ index +'].typename'
    this.setData({
      [typename]: val
    })
  },

  formSubmit: function (e) {
    let obj = e.detail.value
    if (JSON.stringify(obj) === '{}') {
      wx.showToast({
        title: '请填写至少一条报销申请后再提交',
        icon: 'none',
        duration: 2000
      })
      return
    }
    var dataArr = ''
    var totalamount = 0
    for (let key in obj) {
      if (key.indexOf("amount") != -1) {
        totalamount += parseInt(obj[key])
      }
      let ele = obj[key]
      dataArr = dataArr + '$' + `${ele}`
    }
    console.log(totalamount)
  },
})

好了,到这里问题就解决了,还有一个小问题,就是,如果将input和 picker绑定在一起的时候,可能会出现两种情况

第一、弹出的键盘遮挡住picker
第二、弹出picker选中其中一项,选中的值不会填充进input

所以,咱们尽量不要将input和picker一起使用,我的处理是,自定义了一个组件,view里面包含了一个用作前缀的view,还有中心用于文本展示的text

wxml

    <picker bindchange="bindPickerChange" value="{{pickerIndex}}" range="{{array}}" data-index="{{index}}">
      <view class="picker" id='type-input-{{index}}'>
        <!-- <van-field name="typeText-{{index}}" id='type-input-{{index}}' label='类别' value="{{subs[index].typename}}" bind:change = onTypenNameChange/> -->
        <view class="picker-inner-title">类别</view>
        <text class="picker-inner-text">{{subs[index].typename}}</text>
      </view>
    </picker>

wxss

.picker {
  display: flex;
  flex-direction: row;
  align-items: center;
  height: 40px; 
  background-color: white
}

.picker-inner-title {
  width: 100px;
  padding-left: 16px;
  font-size: 14px;
  color: rgb(100, 101, 102);
}

.picker-inner-text {
  font-size: 14px;
}

效果几乎和vant的input组件一样

嘿嘿

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
微信小程序仿豆瓣电影源码微信小程序仿豆瓣电影源码微信小程序仿豆瓣电影源码微信小程序仿豆瓣电影源码微信小程序仿豆瓣电影源码微信小程序仿豆瓣电影源码微信小程序仿豆瓣电影源码微信小程序仿豆瓣电影源码微信小程序仿豆瓣电影源码微信小程序仿豆瓣电影源码微信小程序仿豆瓣电影源码微信小程序仿豆瓣电影源码微信小程序仿豆瓣电影源码微信小程序仿豆瓣电影源码微信小程序仿豆瓣电影源码微信小程序仿豆瓣电影源码微信小程序仿豆瓣电影源码微信小程序仿豆瓣电影源码微信小程序仿豆瓣电影源码微信小程序仿豆瓣电影源码微信小程序仿豆瓣电影源码微信小程序仿豆瓣电影源码微信小程序仿豆瓣电影源码微信小程序仿豆瓣电影源码微信小程序仿豆瓣电影源码微信小程序仿豆瓣电影源码微信小程序仿豆瓣电影源码微信小程序仿豆瓣电影源码微信小程序仿豆瓣电影源码微信小程序仿豆瓣电影源码微信小程序仿豆瓣电影源码微信小程序仿豆瓣电影源码微信小程序仿豆瓣电影源码微信小程序仿豆瓣电影源码微信小程序仿豆瓣电影源码微信小程序仿豆瓣电影源码微信小程序仿豆瓣电影源码微信小程序仿豆瓣电影源码微信小程序仿豆瓣电影源码微信小程序仿豆瓣电影源码微信小程序仿豆瓣电影源码微信小程序仿豆瓣

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值