核心思想

A.利用失去焦点事件on-focus替换千分位符号

this.formInfoData[name] = this.formInfoData[name].replace(/\,/g, '')

B.利用 验证绑定的事件处理数字

(处理数字 功能有待完善,因不支持负数, 精度不够,js toFixed方法   对于数字精度处理有问题)  

呵呵呵哒  主要是思想和应用 ,具体数字处理网上有很多实例。这里不做赘述。

//验证处理对象的绑定
rules: {
        contractName: [{ validator: this.contractNameValid, trigger: 'blur' }],
        endDate: [{ validator: this.endDateValid, type: 'date', trigger: 'change' }],
        money: [ // 合同金额需要特殊处理
          { validator: this.moneyValidChange, trigger: 'change' },
          { validator: this.moneyValidBlur, trigger: 'blur' }
        ]
      },
// 验证的处理方法 

moneyValidChange (rule, val, cb) {
      val = val.replace(/\,/g, '').replace('-', '')
      if (this._isEmpty(val)) {
        cb(new Error('请填写合同金额'))
      } else if (this.isNumberInt(val)) {
        cb(new Error('请输入正确数字'))
      }
      cb()
    },
    moneyValidBlur (rule, val, cb) {
      val = val.replace(/\,/g, '').replace('-', '')
      if (this._isEmpty(val)) {
        cb(new Error('请填写合同金额'))
      } else if (this.isNumberInt(val)) {
        cb(new Error('请输入正确数字'))
      } else {
        this.signInfoData[rule.field] = parseFloat(val).toFixed(2).replace(/(\d)(?=(\d{3})+\.)/g, '$1,')
      }
      cb()
    },
//数字判断  具体什么要求,可以根据自己的业务自行拓展。  
isNumberInt (val) {
      let regPos = /^\d+(\.\d+)?$/ // 非负浮点数
      if (regPos.test(val)) {
        return false
      } else {
        return true
      }
    }

实战核心代码

A 如下 focus事件的绑定,

<Input v-if="item.type==='number2'" v-model="formModel[item.model]" :maxlength="16" placeholder="" type="text" @on-focus="inputFocus(item.model)" />
     

事件处理代码因为封装通用, 所以用emit 抛出去。

 inputFocus (name) {
      this.$emit('inputFocus', name)
    }

实战代码如下。 


 

实例应用


form.vue  表单。

<template>
  <Form ref="signInfoForm" :rules="rules" :show-message="true" :model="signInfoData" :label-width="262">
    <cus-form :datas="datas" :formModel="signInfoData" @inputFocus="inputFocus" />
  </Form>
</template>

<script>
import { formatDate } from '@util/tool'
import { addProjectForms } from './singinfoOption'
import CusForm from './CusForm'
const arrayModelType = ['checkbox']
export default {
  name: 'SignInfo',

  components: {
    CusForm
  },
  props: {
    signType: {
      default: '1',
      type: String
    },
    tempName: {
      default: '',
      type: String
    }
  },
  data () {
    return {
      checkboxSelect: false,
      endDateType: '1',
      rules: {
        contractName: [{ validator: this.contractNameValid, trigger: 'blur' }],
        endDate: [{ validator: this.endDateValid, type: 'date', trigger: 'change' }],
        money: [ // 合同金额需要特殊处理
          { validator: this.moneyValidChange, trigger: 'change' },
          { validator: this.moneyValidBlur, trigger: 'blur' }
        ]
      },
      signInfoData: {
        contractName: '',
        endDate: ''
      },
      datas: [],
      options: {
        disabledDate (date) {
          return date && date.valueOf() < Date.now() - 86400000
        }
      }
    }
  },

  computed: {
    // ...mapGetters({
    //   _user: '_user'
    // })
  },

  watch: {
   .........
  },

  mounted () {
    this.datas = addProjectForms().filter((item) => {
      if (item.showItem && item.showItem === '1') {
        return false
      } else {
        return true
      }
    })
  },

  beforeDestroy () {

  },

  methods: {
    inputFocus (name) {
      this.signInfoData[name] = this.signInfoData[name].replace(/\,/g, '')
    },
    isNumberInt (val) {
      let regPos = /^\d+(\.\d+)?$/ // 非负浮点数
      if (regPos.test(val)) {
        return false
      } else {
        return true
      }
    },
    setupForm () {
      let forms = {}
      // 此处千万不要this.data 作为循环, 因为 addProjectForms 包含默认值会丢失
      this._forEach(addProjectForms(), item => {
        let arr = []
        if (item.type === 'checkbox') {
          this._forEach(item.children, o => {
            o.value && arr.push(o.value)
          })
        }
        if (!this._isNil(item.model) && item.type !== 'text') {
          // 取默认值
          forms[item.model] = !this._isNil(item.value) ? item.value : arrayModelType.includes(item.type) ? arr : ''
        }
      })
      console.log('------1', this.signInfoData)
      return Object.assign({}, forms, this.signInfoData)
    },
    contractNameValid (rule, val, cb) {
      if (this._isEmpty(val)) {
        cb(new Error('请输入签署名称'))
      } else if (val.length > 60) {
        cb(new Error('超出最长字数限制,请重新输入'))
      }
      cb()
    },
    moneyValidChange (rule, val, cb) {
      val = val.replace(/\,/g, '').replace('-', '')
      if (this._isEmpty(val)) {
        cb(new Error('请填写合同金额'))
      } else if (this.isNumberInt(val)) {
        cb(new Error('请输入正确数字'))
      }
      cb()
    },
    moneyValidBlur (rule, val, cb) {
      val = val.replace(/\,/g, '').replace('-', '')
      if (this._isEmpty(val)) {
        cb(new Error('请填写合同金额'))
      } else if (this.isNumberInt(val)) {
        cb(new Error('请输入正确数字'))
      } else {
        this.signInfoData[rule.field] = parseFloat(val).toFixed(2).replace(/(\d)(?=(\d{3})+\.)/g, '$1,')
      }
      cb()
    },
    endDateValid (rule, val, cb) {
      // 指定截止日期 时做空验证
      if (this.endDateType === '2' && val === '') {
        cb(new Error('请填写签署截止日'))
      }
      cb()
    },
    // 提交
    singInfoSubmit (status) {
      if (this.checkboxSelect) {
        this.$refs['signInfoForm'].validate((valid) => {
          if (valid) {
            this.$emit('handleSubmit', this.getData(), status)
          }
        })
      } else {
        if (this.signInfoData.isContract === '1') {
          this.$Message.info('请勾选说明内容')
        } else {
          this.$refs['signInfoForm'].validate((valid) => {
            if (valid) {
              this.$emit('handleSubmit', this.getData(), status)
            }
          })
        }
      }
    },
    setData (signInfo) {
      if (signInfo.endDate) {
        this.endDateType = '2'
        signInfo.endDate = formatDate(new Date(signInfo.endDate), 'yyyy-MM-dd')
      } else {
        this.endDateType = '1'
      }
      // if (signInfo.requestTime) {
      //   signInfo.requestTime = formatDate(new Date(signInfo.requestTime), 'yyyy-MM-dd')
      // }
      if (signInfo.money) { // 合同金额格式化
        signInfo.money = parseFloat(signInfo.money).toFixed(2).replace(/(\d)(?=(\d{3})+\.)/g, '$1,')
      }
      Object.assign(this.signInfoData, signInfo)
      console.log('------2', this.signInfoData)
    },
    getData () {
      let obj = {}
      if (this.signType === '02') {
        obj = Object.assign({}, obj, this.signInfoData)
        obj.money = obj.money.replace(/\,/g, '').replace('-', '')
        // obj.requestTime = obj.requestTime ? formatDate(new Date(this.signInfoData.requestTime), 'yyyy-MM-dd') : ''
      } else {
        obj = {
          contractName: this.signInfoData.contractName,
          endDate: this.endDateType === '2' && this.signInfoData.endDate ? formatDate(new Date(this.signInfoData.endDate), 'yyyy-MM-dd') : '',
          endDateType: this.endDateType
        }
      }
      return obj
    }
  }
}
</script>

 Cusform.vue    在另一篇实战也有一个类似,那个更高级。

<template>
  <div class="formPanel">
    <FormItem v-for="(item, index) in datas" :key="index" :label="item.label" :rules="item.rules" :prop="item.prop" :class="item.class">
      <i-input v-if="item.type === 'input'" v-model.trim="formModel[item.model]" :type="item.inputType" :disabled="item.disabled" :placeholder="item.placeholder" :size="item.size" @on-enter="search" />
      <RadioGroup v-if="item.type === 'radio'" v-model="formModel[item.model]">
        <Radio v-for="(e, i) in item.children" :key="i" :label="e.label">
          {{ e.text }}
        </Radio>
        <slot v-if="item.slot" :name="item.slot" />
      </RadioGroup>
      <CheckboxGroup v-if="item.type === 'checkbox'" v-model="formModel[item.model]" class="mycheck-group">
        <Checkbox v-for="(e, i) in item.children" :key="i" :label="e.label" :disabled="e.disabled">
          {{ e.text }}
        </Checkbox>
      </CheckboxGroup>
      <Checkbox v-if="item.type === 'check'" v-model="formModel[item.model]" :label="item.checklabel" :disabled="e.disabled">
        {{ e.text }}
        <slot v-if="item.slot" :name="item.slot" />
      </Checkbox>
      <DatePicker v-if="item.type === 'datePicker'" v-model="formModel[item.model]" style="width:100%;" :value="formModel[item.model]" :type="item.pickertype ? item.pickertype : 'date'" :options="item.options" :size="item.size" :placeholder="item.placeholder" />
      <i-input v-if="item.type === 'textarea'" v-model="formModel[item.model]" :autosize="item.autosize" type="textarea" :size="item.size" />
      <Select v-if="item.type === 'select'" v-model="formModel[item.model]" :disabled="item.disabled" :filterable="item.filterable" :size="item.size" :placeholder="item.placeholder" @on-change="selectChange">
        <Option v-for="(e, i) in item.children" :key="i" :value="e.label">
          {{ e.text }}
        </Option>
      </Select>
      <label v-if="item.type === 'text'" :size="item.size">
        {{ item.text }} <slot v-if="item.slot" :name="item.slot" :params="item.params" />
      </label>
      <Select v-if="item.type === 'filterSelect'" v-model="formModel[item.model]" :disabled="item.disabled" :label-in-value="true" :size="item.size">
        <Option v-for="(e, i) in item.children" :key="i" :value="e.code">
          {{ e.name }}
        </Option>
      </Select>

      <InputNumber
        v-if="item.type==='number'"
        v-model="formModel[item.model]"
        style="width:100%;"
        :formatter="value => `${value}`.replace(/(?=(?!\b)(\d{3})+\.)/g,',')"
        :parser="value => value.replace(/$s?|(,*)/g, '')" :precision="item.precision" :min="item.min"
        :max="item.max"
        :disabled="item.disabled"
        :placeholder="item.placeholder"
        :size="item.size" />
      <Input v-if="item.type==='number2'" v-model="formModel[item.model]" :maxlength="16" placeholder="" type="text" @on-focus="inputFocus(item.model)" />
      <div v-if="item.type === 'inputSlot'" style="postion:relative;">
        <i-input v-model="formModel[item.model]" :type="item.inputType" :disabled="item.disabled" :placeholder="item.placeholder" :size="item.size" />
        <slot v-if="item.slot" :name="item.slot" :params="item.params" />
      </div>
    </FormItem>
  </div>
</template>
<script>

export default {
  name: 'CusForm',
  props: {
    datas: {
      type: Array,
      required: true
    },
    formModel: {
      type: Object,
      required: true
    }
  },
  data () {
    return {
      left: ''
    }
  },
  computed: {
  },
  watch: {
  },
  mounted () {
    // this.left = this.toLeft !== '1' ? this.toLeft : (this.inline ? '0' : '200')
  },
  methods: {
    inputFocus (name) {
      this.$emit('inputFocus', name)
    }
  }
}
</script>
<style lang="scss">
.form-wrap {

  .ivu-cascader-rel {
    width: 18.75rem;
  }

  .phone-wrap {

    .phone-zone {
      width: 3.75rem;

      .ivu-input {
        width: 3.75rem !important;
      }
    }

    .phone-num {
      width: 14.062rem;

      .ivu-input {
        width: 14.062rem !important;
      }
    }
  }
}

.mycheck-group {
  overflow: hidden;

  .ivu-checkbox-wrapper {
    display: flex;
    float: left;
    align-items: center;
    margin-right: 0;
    min-width: 20%;
    font-size: 14px;

    > span {
      margin-right: 9px;
    }
  }
}
</style>
<style lang="scss" scoped>
.form-wrap {

  &.formvertical {

    .btn-wrap {
      margin-left: 8.125rem;
    }
  }
  margin-top: 12px;

  .btn-wrap {
    display: inline-block;
    margin-top: 4px;
  }

  .btncenter {
    display: flex;
    justify-content: center;
    margin-top: 1.875rem;
  }
}

</style>

配置文件   number2的配置。

   {
      type: 'number2',
      label: '合同金额:',
      model: 'money',
      showItem: '1',
      max: 999999999999999999,
      min: 0,
      precision: 2,
      // rules: signRules.money,
      prop: 'money'
    },
Logo

前往低代码交流专区

更多推荐