<!-- 数字input框 -->
<template>
  <el-input
    v-if="decimalOptions.needy"
    v-model="inputVal"
    :placeholder="placeholder"
    :disabled="disabled"
    :maxlength="maxLen"
    @change="handleChange"
    @blur="handleBlur"
  >
    <template v-if="forntUnitName" slot="prepend">{{ forntUnitName }}</template>
    <template v-if="isUnit" slot="append">{{ unitName }}</template>
  </el-input>
  <el-input
    v-else
    v-model="inputVal"
    :disabled="disabled"
    :placeholder="placeholder"
    :controls="false"
    :maxlength="maxLen"
    @change="handleInput"
    @blur="handleBlur"
  >
    <template v-if="forntUnitName" slot="prepend">{{ forntUnitName }}</template>
    <template v-if="isUnit" slot="append">{{ unitName }}</template>
  </el-input>
</template>

<script>
/**
 * eg: <cy-number-input v-model="testVal" />
 * 支持小数需要配置decimalOptions选项, 如果小数不保留任何位数请直接使用整数配置
 * <cy-number-input v-model="testVal" :decimalOptions="{ needy:true, digitsNo: 2 }" />
 */
export default {
  props: {
    maxLen: {
      type: Number,
      default: 255
    },
    placeholder: {
      type: String,
      default: '请输入数字'
    },
    value: {
      type: [String, Number],
      default: ''
    },
    disabled: {
      type: Boolean,
      default: false
    },
    unitName: {
      type: String,
      default: '元'
    },
    isUnit: {
      type: Boolean,
      required: false,
      default: false
    },
    forntUnitName: {
      type: String,
      default: ''
    },
    decimalOptions: {
      type: Object,
      default: () => {
        return {
          needy: false, // true开启小数认证
          digitsNo: 2 // 保留位数
        }
      }
    }
  },
  data() {
    return {
      inputVal: ''
    }
  },
  watch: {
    value: {
      handler(val) {
        if (val === undefined) return
        if (!this.decimalOptions.needy) {
          this.handleInput(String(val))
        } else {
          this.handleChange(String(val))
        }
      },
      immediate: true
    },
    inputVal(val) {
      if (!this.decimalOptions.needy) {
        this.handleInput(String(val))
      }
    }
  },
  methods: {
    handleInput(val) {
      if (val === '' || val.replace(/\s/g, '') === '') {
        this.inputVal = ''
        return
      }
      const newVal = String(val).replace(/[^\d | \-]/g, '').replace(/\s/g, '')
      if (newVal === undefined || newVal === '-') return
      this.inputVal = newVal
      this.$emit('input', this.inputVal)
    },
    handleChange(val) {
      if (val === '' || val.replace(/\s/g, '') === '') {
        this.inputVal = ''
        return
      }
      if (val.indexOf('.') === -1) {
        this.inputVal = val
        this.$emit('input', val)
        return
      }
      let newVal = val.replace(/[^d+] | [\-] | [\.]/g, '').replace(/\s/g, '')
      const fixedPosition = this.decimalOptions.digitsNo ? this.decimalOptions.digitsNo : 2
      newVal = this.toPrecision(val, fixedPosition)
      this.inputVal = newVal
      this.$emit('input', this.inputVal)
    },
    toPrecision(num, precision) {
      // 处理精度
      const res = parseFloat(Math.round(num * Math.pow(10, precision)) / Math.pow(10, precision))
      if (res.toString().includes('e')) {
        const resArr = num.split('.')
        return `${resArr[0]}.${resArr[1].slice(0, precision)}`
      } else {
        const splitArr = res.toString().split('.')
        if (splitArr[1].length < precision) {
          // 缺位补0
          while (splitArr[1].length < precision) {
            splitArr[1] = splitArr[1] + '0'
          }
        } else {
          // 多余截取
          splitArr[1] = splitArr[1].slice(0, precision)
        }
        return `${splitArr[0]}.${splitArr[1]}`
      }
    },
    handleBlur(val) {
      this.$emit('blur', val)
    }
  }
}
</script>

<style lang="scss" scoped>
::v-deep .el-input__inner {
  text-align: left;
}
</style>
