Newer
Older
xc-business-system / src / components / precisionInputNumber / index.vue
liyaguang on 18 Mar 6 KB 科学计数法需求修改
<!-- 数字输入框 -->
<script lang="ts" setup name="precisionInputNumber">
import BigNumber from 'bignumber.js'
// ------------------定义props、 emit-------------------
const props = defineProps({
  // 数据绑定
  modelValue: {
    type: [Number, String],
    default: '',
  }, // 输入
  // 是否禁用
  disabled: {
    type: Boolean,
    default: false,
  },
  // 清空按钮
  clearable: {
    type: Boolean,
    default: false,
  },
  // 输入框最大长度
  maxlength: {
    type: [Number, String],
    default: '',
  },
  // 输入框最小长度
  minlength: {
    type: [Number, String],
    default: '',
  },
  // 是否显示统计字数
  showWordLimit: {
    type: Boolean,
    default: false,
  },
  placeholder: {
    type: String,
    default: '请输入',
  },
  // 保留小数位数
  precision: {
    type: Number,
    default: 0,
  },
  max: {
    type: Number,
    default: 99999999,
  },
  min: {
    type: Number,
    default: -99999999,
  },
  valueOnClear: {
    type: Number,
    default: 0,
  },
  // 失焦执行的方法(可传可不传)
  blur: {
    type: Function,
    default: () => { },
  },
  // 获取焦点执行的方法(可传可不传)
  focus: {
    type: Function,
    default: () => { },
  },
  // 输入框值变化执行的方法(可传可不传)
  change: {
    type: Function,
    default: () => { },
  },
  // 清空按钮时执行的方法(可传可不传)
  clear: {
    type: Function,
    default: () => { },
  },
})
const emit = defineEmits(['update:modelValue', 'blur', 'change', 'focus'])
const isFirst = ref(true)
// -------------------------定义数据--------------------
const value = computed({
  get() {
    return props.modelValue
  },
  set(value) {
    emit('update:modelValue', value)
  },
})
// 输入框失焦
const handler = () => {
  // console.log(props.precision, 'props.precision')
  const inputValue = value.value
  console.log(inputValue, '输入框的值')
  if (value.value === '' || value.value === null || value.value === undefined || isNaN(value.value)) {
    console.log(inputValue, '无效')
    if (props.valueOnClear) {
      if (Number(props.precision)) {
        value.value = Number(props.valueOnClear).toFixed(props.precision)
      }
      else {
        value.value = props.valueOnClear
      }
    }
    else {
      value.value = ''
    }
    return
  }
  if (Number(props.precision)) {
    value.value = Number(value.value || 0).toFixed(props.precision)
  }
  // else {
  //   console.log(33333333333)
  //   let digits = 0
  //   if(step.value.toString().includes('.')) {
  //     digits = step.value.toString().split('.')[1].length
  //   }
  //   else {
  //     digits = 0
  //   }
  //   value.value = Number(value.value || 0).toFixed(digits)
  // }
  emit('blur', value.value)
}
const blur = () => {
  console.log('输入框失焦')
  handler()
}
// 输入框获取焦点
const focus = () => {
  console.log('输入框获取焦点')
  isFirst.value = false
  emit('focus', value.value)
}
// 输入框值变化
const step = ref(1)
const change = () => {
  console.log('输入框值变化')
  emit('change', value.value)
  step.value = stepCalc.value
}
const stepCalc = computed(() => {
  if (props.precision && props.precision) {
    console.log('步长', 0.1 * 10 ** -(props.precision - 1))
    return 0.1 * 10 ** -(props.precision - 1)
  }
  else {
    // 先判断是否科学计数法
    if (String(value.value).includes('e') || String(value.value).includes('E')) {
      const a = String(value.value)
      let [coefficient, exponent] = a.split('e') || a.split('E')
      const data = new BigNumber(coefficient).times(`1e${exponent}`).toString()
      const number = data.split('.')[1].length - 1
      let str = ''
      for (let i = 0; i < number; i++) {
        str += '0'
      }
      return data.split('.')[0].includes('-') ? Number(`-0.${str}1`) : Number(`0.${str}1`)
    }
    else {
      if (String(value.value).includes('.')) {
        const number = String(value.value).split('.')[1].length - 1
        let str = ''
        for (let i = 0; i < number; i++) {
          str += '0'
        }
        return Number(`0.${str}1`)
      }
      else {
        return 1
      }
    }
  }
})
// -------------------------钩子--------------------
const inputRef = ref()
const clickInput = () => {
  inputRef.value.focus()
}
const handlerInput = (type: 'add' | 'minus') => {
  step.value = stepCalc.value
  let digits = 0
  if(props.precision && Number(props.precision)) {
    digits = props.precision
  }
  else {
    if(step.value.toString().includes('.')) {
      digits = step.value.toString().split('.')[1].length
    }
    else {
      digits = 0
    }
  }
  if (type === 'add') {
    console.log(digits, 'digits')
    value.value = Number(new BigNumber(value.value).plus(new BigNumber(step.value))).toFixed(digits)
  }
  else {
    value.value = Number(new BigNumber(value.value).minus(new BigNumber(step.value))).toFixed(digits)
  }
  change()
}

</script>

<template>
  <div class="input-container">
    <el-input ref="inputRef" v-model.trim="value" type="number" resize="none" :disabled="props.disabled"
      :placeholder="props.placeholder" :clearable="props.clearable" :maxlength="props.maxlength"
      :minlength="props.minlength" :show-word-limit="props.showWordLimit" :max="props.max" :min="props.min"
      style="width: 100%;" @blur="blur" @change="change" @focus="focus" @clear="props.clear" @mousewheel.prevent
      controls-position="right">
    </el-input>
    <div class="input-mask">
      <div class="input-1" @click="clickInput"></div>
      <div class="input-2" style="width: 32px;height: 32px;">
        <span class="span" @click="handlerInput('add')">+</span>
        <span class="span" @click="handlerInput('minus')">-</span>
      </div>
    </div>
  </div>
</template>

<style lang="scss" scoped>
.input-container {
  width: 100%;
  position: relative;

  .input-mask {
    width: 100%;
    height: 32px;
    position: absolute;
    top: 0px;
    left: 0px;
    z-index: 9;
    display: flex;

    .input-1 {
      flex: 1;
    }

    .input-2 {
      &:hover {
        cursor: pointer;
      }

      display: flex;
      justify-content: center;
      flex-direction: column;

      span {
        display: inline-block;
        width: 31px;
        height: 15px;
        line-height: 15px;
        text-align: center;
        background-color: #F5F7FA;

        &:hover {
          cursor: pointer;
        }
      }
    }
  }
}
</style>