|
@@ -1,17 +1,29 @@
|
|
|
-<!-- 只能输入纯数字的input框 -->
|
|
|
+<!-- 数字input框 -->
|
|
|
<template>
|
|
|
- <el-input v-model="inputVal" :maxlength="maxLen" :disabled="disabled" type="text" :placeholder="placeholder" @input="handleInput">
|
|
|
- <template v-if="!isPositive">
|
|
|
- <i slot="prefix" class="el-icon-minus" />
|
|
|
- </template>
|
|
|
- </el-input>
|
|
|
+ <el-input
|
|
|
+ v-if="decimalOptions.needy"
|
|
|
+ v-model="inputVal"
|
|
|
+ :placeholder="placeholder"
|
|
|
+ :disabled="disabled"
|
|
|
+ :maxlength="maxLen"
|
|
|
+ @change="handleChange"
|
|
|
+ />
|
|
|
+ <el-input
|
|
|
+ v-else
|
|
|
+ v-model="inputVal"
|
|
|
+ :disabled="disabled"
|
|
|
+ :placeholder="placeholder"
|
|
|
+ :controls="false"
|
|
|
+ :maxlength="maxLen"
|
|
|
+ @change="handleInput"
|
|
|
+ />
|
|
|
</template>
|
|
|
|
|
|
<script>
|
|
|
/**
|
|
|
- * 如果数字是负数必须在组件声明处标志isPositive此prop
|
|
|
- * eg: <cy-number-input v-model="testVal" :is-positive="false" />
|
|
|
- * <cy-number-input v-model="testVal" />
|
|
|
+ * eg: <cy-number-input v-model="testVal" />
|
|
|
+ * 支持小数需要配置decimalOptions选项, 如果小数不保留任何位数请直接使用整数配置
|
|
|
+ * <cy-number-input v-model="testVal" :decimalOptions="{ needy:true, digitsNo: 2 }" />
|
|
|
*/
|
|
|
export default {
|
|
|
props: {
|
|
@@ -23,11 +35,6 @@ export default {
|
|
|
type: String,
|
|
|
default: '请输入数字'
|
|
|
},
|
|
|
- // 是否为正数
|
|
|
- isPositive: {
|
|
|
- type: Boolean,
|
|
|
- default: true
|
|
|
- },
|
|
|
value: {
|
|
|
type: [String, Number],
|
|
|
default: ''
|
|
@@ -35,6 +42,15 @@ export default {
|
|
|
disabled: {
|
|
|
type: Boolean,
|
|
|
default: false
|
|
|
+ },
|
|
|
+ decimalOptions: {
|
|
|
+ type: Object,
|
|
|
+ default: () => {
|
|
|
+ return {
|
|
|
+ needy: false, // true开启小数认证
|
|
|
+ digitsNo: 2 // 保留位数
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
},
|
|
|
data() {
|
|
@@ -46,26 +62,72 @@ export default {
|
|
|
value: {
|
|
|
handler(val) {
|
|
|
if (val === undefined) return
|
|
|
- this.handleInput(String(val))
|
|
|
+ if (!this.decimalOptions.needy) {
|
|
|
+ this.handleInput(val)
|
|
|
+ } else {
|
|
|
+ this.handleChange(val)
|
|
|
+ }
|
|
|
},
|
|
|
immediate: true
|
|
|
},
|
|
|
inputVal(val) {
|
|
|
- this.handleInput(val)
|
|
|
+ if (!this.decimalOptions.needy) {
|
|
|
+ this.handleInput(val)
|
|
|
+ }
|
|
|
}
|
|
|
},
|
|
|
methods: {
|
|
|
handleInput(val) {
|
|
|
- // 移除非数字字符
|
|
|
- this.inputVal = val.replace(/[^\d]/g, '')
|
|
|
- if (!this.isPositive) {
|
|
|
- this.$emit('input', Number('-' + this.inputVal))
|
|
|
+ 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 = ''
|
|
|
+ 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 {
|
|
|
- this.$emit('input', Number(this.inputVal))
|
|
|
+ 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]}`
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
</script>
|
|
|
|
|
|
-<style lang="scss" scoped></style>
|
|
|
+<style lang="scss" scoped>
|
|
|
+::v-deep .el-input__inner {
|
|
|
+ text-align: left;
|
|
|
+}
|
|
|
+</style>
|