<!-- 数字输入框 --> <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>