BMT兑换接入DecimalInput组件,限制整数输入

This commit is contained in:
yankang 2026-07-29 18:32:43 +08:00
parent 10d491d5ad
commit b91481ce9d
7 changed files with 161 additions and 10 deletions

View File

@ -0,0 +1,97 @@
<template>
<input ref="InputRef" class="DecimalInput UI-FLEX-1 UI-P-L24 UI-FS28" type="text" inputmode="decimal"
:value="InnerValue" :placeholder="placeholder" :placeholder-style="placeholderStyle"
@input="HandleInput" />
</template>
<script>
import { limitDecimal } from '@/utils/index.js'
export default {
name: 'DecimalInput',
props: {
value: { type: [String, Number], default: '' },
digit: { type: Number, default: 2 },
allowNegative: { type: Boolean, default: false },
max: { type: [String, Number], default: null },
placeholder: { type: String, default: '' },
placeholderStyle: { type: String, default: '' }
},
data() {
return {
//
InnerValue: String(this.value === null || this.value === undefined ? '' : this.value)
}
},
watch: {
value(Val) {
const Str = String(Val === null || Val === undefined ? '' : Val)
if (Str !== this.InnerValue) {
this.InnerValue = Str
}
}
},
methods: {
/** 获取 uni-app input 组件内部的原生 input 节点 */
GetNativeInput(Target) {
if (Target && Target.tagName === 'INPUT') return Target
const ShadowInput = Target && Target.shadowRoot && typeof Target.shadowRoot.querySelector === 'function'
? Target.shadowRoot.querySelector('input')
: null
if (ShadowInput) return ShadowInput
const ChildInput = Target && typeof Target.querySelector === 'function'
? Target.querySelector('input')
: null
if (ChildInput) return ChildInput
const RootEl = this.$refs.InputRef && this.$refs.InputRef.$el
const RootInput = RootEl && typeof RootEl.querySelector === 'function'
? RootEl.querySelector('input')
: null
if (RootInput) return RootInput
// H5 input
const ActiveInput = typeof document !== 'undefined' ? document.activeElement : null
if (ActiveInput && ActiveInput.tagName === 'INPUT') return ActiveInput
return null
},
/** 输入时实时限制小数位数与最大值 */
HandleInput(e) {
const NativeInput = this.GetNativeInput(e && e.target)
const DetailValue = e && e.detail ? e.detail.value : undefined
let Value = String(
DetailValue !== undefined && DetailValue !== null
? DetailValue
: (NativeInput ? NativeInput.value : '')
)
//
Value = limitDecimal(Value, this.digit, this.allowNegative)
//
const Max = Number(this.max)
if (Value !== '' && this.max !== null && !isNaN(Number(Value)) && !isNaN(Max) && Number(Value) > Max) {
Value = String(Max)
}
this.InnerValue = Value
this.$emit('input', Value)
// uni-app H5 input uni-input valueSync
// Vue input
// patch nextTick input
this.$nextTick(() => {
const Target = this.GetNativeInput(e && e.target)
if (Target && Target.value !== Value) {
Target.value = Value
}
})
}
}
}
</script>
<style lang="scss" scoped>
.DecimalInput {
height: 100%;
}
</style>

View File

@ -78,12 +78,12 @@
</view> </view>
<view class="form-input"> <view class="form-input">
<input <decimal-input
v-model="form.points" v-model="form.points"
class="form-input__field asset-number-font" class="form-input__field asset-number-font"
type="number" :digit="0"
placeholder="请输入积分数量" placeholder="请输入积分数量"
placeholder-class="form-input__placeholder" placeholder-style="color: rgba(177, 187, 214, 0.42);"
/> />
<text class="form-input__suffix">可用积分</text> <text class="form-input__suffix">可用积分</text>
</view> </view>
@ -156,6 +156,7 @@
<script> <script>
import AssetConfirmPopup from "../../components/asset-confirm-popup.vue"; import AssetConfirmPopup from "../../components/asset-confirm-popup.vue";
import AssetPageShell from "../../components/asset-page-shell.vue"; import AssetPageShell from "../../components/asset-page-shell.vue";
import DecimalInput from "../../components/DecimalInput/DecimalInput.vue";
import { import {
fetchBmtExchangeDetail, fetchBmtExchangeDetail,
submitAssetBmtExchange, submitAssetBmtExchange,
@ -165,6 +166,7 @@ export default {
components: { components: {
AssetConfirmPopup, AssetConfirmPopup,
AssetPageShell, AssetPageShell,
DecimalInput,
}, },
data() { data() {
return { return {
@ -573,10 +575,6 @@ export default {
color: #ffffff; color: #ffffff;
} }
.form-input__placeholder {
color: rgba(177, 187, 214, 0.42);
}
.form-input__suffix { .form-input__suffix {
margin-left: 16rpx; margin-left: 16rpx;
font-size: 22rpx; font-size: 22rpx;

View File

@ -1,2 +1,2 @@
<!DOCTYPE html><html lang=zh-CN><head><meta charset=utf-8><meta http-equiv=X-UA-Compatible content="IE=edge"><title>白马交易所</title><script>var coverSupport = 'CSS' in window && typeof CSS.supports === 'function' && (CSS.supports('top: env(a)') || CSS.supports('top: constant(a)')) <!DOCTYPE html><html lang=zh-CN><head><meta charset=utf-8><meta http-equiv=X-UA-Compatible content="IE=edge"><title>白马交易所</title><script>var coverSupport = 'CSS' in window && typeof CSS.supports === 'function' && (CSS.supports('top: env(a)') || CSS.supports('top: constant(a)'))
document.write('<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0' + (coverSupport ? ', viewport-fit=cover' : '') + '" />')</script><link rel=stylesheet href=/bmt/static/index.149e085d.css></head><body><noscript><strong>Please enable JavaScript to continue.</strong></noscript><div id=app></div><script src=/bmt/static/js/chunk-vendors.e13b4a2c.js></script><script src=/bmt/static/js/index.4e3c3222.js></script></body></html> document.write('<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0' + (coverSupport ? ', viewport-fit=cover' : '') + '" />')</script><link rel=stylesheet href=/bmt/static/index.149e085d.css></head><body><noscript><strong>Please enable JavaScript to continue.</strong></noscript><div id=app></div><script src=/bmt/static/js/chunk-vendors.e13b4a2c.js></script><script src=/bmt/static/js/index.68f4d562.js></script></body></html>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

56
utils/index.js Normal file
View File

@ -0,0 +1,56 @@
/**
* 限制输入框中的小数位数
* @param {string} val - 输入值
* @param {number} digit - 小数位位数默认 2
* @param {boolean} allowNegative - 是否允许负数默认 false
* @returns {string}
*
* 示例
* limitDecimal('12.345', 2) // '12.34'
* limitDecimal('12..34', 2) // '12.34'
* limitDecimal('abc123.45', 2) // '123.45'
* limitDecimal('-12.34', 2, true) // '-12.34'
* limitDecimal('007.00', 2) // '7.00'
* limitDecimal('12.5', 0) // '12'digit 为 0 时小数点一并去除,仅保留整数)
*/
export function limitDecimal(val, digit = 2, allowNegative = false) {
if (!val && val !== "0") return "";
// 1. 过滤非法字符
let result = allowNegative
? String(val).replace(/[^\d.-]/g, "")
: String(val).replace(/[^\d.]/g, "");
// 2. 负号只能出现在开头
if (allowNegative) {
const hasMinus = result.indexOf("-") > -1;
result = result.replace(/-/g, "");
if (hasMinus && result) result = "-" + result;
}
// 3. 多个小数点只保留第一个
const parts = result.split(".");
if (parts.length > 2) {
result = parts[0] + "." + parts.slice(1).join("");
}
// 4. 限制小数位数digit 为 0 时去除小数点,仅保留整数)
if (result.includes(".") && digit >= 0) {
const [intPart, decPart] = result.split(".");
result = digit === 0 ? intPart : intPart + "." + decPart.slice(0, digit);
}
// 5. 处理前导零00、01 等
if (
result &&
!result.startsWith("-") &&
result.startsWith("0") &&
result.length > 1 &&
result[1] !== "."
) {
result = result.replace(/^0+/, "");
if (result === "") result = "0";
}
return result;
}