Files
hht-tongbo-two/components/NumberInput.vue
2025-06-10 15:10:06 +08:00

123 lines
2.8 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<input
type="text"
:value="displayValue"
@input="handleInput"
@blur="handleBlur"
:placeholder="placeholder"
:class="inputClass"
:style="inputStyle"
/>
</template>
<script>
export default {
name: "NumberInput",
props: {
value: {
type: [Number, String],
default: ''
},
min: {
type: Number,
default: 0.001
},
max: {
type: Number,
default: 100000
},
placeholder: {
type: String,
default: '请输入大于0的数字'
},
inputClass: {
type: String,
default: ''
},
inputStyle: {
type: String,
default: ''
}
},
data() {
return {
displayValue: this.value.toString()
};
},
watch: {
value(newVal) {
// 当外部value变化时更新显示值
this.displayValue = newVal.toString();
}
},
methods: {
handleInput(e) {
const rawValue = e.detail.value;
let filtered = rawValue
// 移除非数字和小数点的字符
.replace(/[^\d.]/g, '')
// 只保留第一个小数点
.replace(/(\.+)/g, '.')
.replace(/(\..*)\./g, '$1')
// 避免以0开头0后面没有小数点的情况
.replace(/^0+(\d)/, '$1');
// 处理开头是小数点的情况添加0前缀
if (filtered.startsWith('.')) {
filtered = '0' + filtered;
}
this.displayValue = filtered;
this.$emit('input', filtered);
},
handleBlur() {
let finalValue = this.displayValue;
// 空值处理
if (!finalValue) {
finalValue = this.min.toString();
}
// 处理以小数点结尾的情况
if (finalValue.endsWith('.')) {
finalValue = finalValue.slice(0, -1);
}
// 转换为数字
let numValue = parseFloat(finalValue);
// 验证数字有效性
if (isNaN(numValue)) {
numValue = this.min;
}
// 边界校验
if (numValue <= 0) {
numValue = this.min;
} else if (numValue > this.max) {
numValue = this.max;
} else if (numValue < this.min) {
numValue = this.min;
}
// 小数位处理最多3位
const numStr = numValue.toString();
const decimalIndex = numStr.indexOf('.');
if (decimalIndex !== -1) {
const decimalPart = numStr.slice(decimalIndex + 1);
if (decimalPart.length > 3) {
// 直接截断而非四舍五入
numValue = parseFloat(numStr.substring(0, decimalIndex + 4));
}
}
// 更新显示值并通知父组件
this.displayValue = numValue.toString();
this.$emit('input', numValue);
this.$emit('change', numValue);
}
}
}
</script>