BMT兑换接入DecimalInput组件,限制整数输入
This commit is contained in:
parent
10d491d5ad
commit
b91481ce9d
|
|
@ -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>
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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
File diff suppressed because one or more lines are too long
|
|
@ -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;
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue