numberinput

This commit is contained in:
2025-05-30 17:36:59 +08:00
parent c768b659f9
commit 0b888ad75e
6 changed files with 552 additions and 274 deletions

85
components/LimitInput.vue Normal file
View File

@@ -0,0 +1,85 @@
<template>
<div class="fxcol">
<input
class="filter-input i-border"
:disabled="disabled"
:type="type"
ref="input"
:value="numberValue"
:placeholder="placeholder"
oninput="value=value.replace(/[^\d.]/g,'')"
@input="handleChange"
/>
</div>
</template>
<script>
export default {
name: 'limitInput',
props: {
disabled: Boolean,
type: String,
placeholder: String,
value: '', // 传过来的值
max: Number,
min: Number,
defaultValue: '' // 默认值
},
data () {
return {
numberValue: this.value
}
},
watch: {
value (val) { // 监听传来的value值并传递给新定义的值
// debugger
this.numberValue = Number(val)
},
max (val) { // 因为最大值是根据上个值输入而变化的,所以要监听相应变化
this.max = val
},
min (val) { // 因为最小值是根据上个值输入而变化的,所以要监听相应变化
this.min = val
},
numberValue (val) { // emit input事件,可令父组件进行v-model绑定
this.$emit('input', val)
},
disabled (val) {
this.disabled = val
},
defaultValue (val) { // 要根据上面的值变化而相应变化,所以要监听
this.numberValue = val
}
},
methods: {
handleChange (event) {
let val = event.target.value.trim()
if (val < 0 || isNaN(val)) {
this.numberValue = 0
return
}
if (val) {
val = Number(val)
this.numberValue = val
if (val > Number(this.max)) this.numberValue = this.max
if (val < Number(this.min)) this.numberValue = this.min
} else {
this.numberValue = 0
}
}
},
mounted () {
if (this.defaultValue) {
this.numberValue = this.defaultValue
}
}
}
</script>
<style lang="stylus" scoped>
// input
// width 100%
.i-border
border 1px solid #a1a1a1
border-radius 3px
text-align center
</style>

123
components/NumberInput.vue Normal file
View File

@@ -0,0 +1,123 @@
<!-- components/number-input.vue -->
<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>