From e83fc0a8a9ae88449bbdbb914dc65b0ca2049b90 Mon Sep 17 00:00:00 2001 From: novlan1 <1576271227@qq.com> Date: Tue, 10 Mar 2026 14:26:43 +0800 Subject: [PATCH 1/2] fix(stepper): fix integer error --- packages/components/stepper/stepper.ts | 18 ++++++---- .../uniapp-components/stepper/stepper.vue | 33 ++++++++++++++----- 2 files changed, 37 insertions(+), 14 deletions(-) diff --git a/packages/components/stepper/stepper.ts b/packages/components/stepper/stepper.ts index 711cdebaf..c8332fc0b 100644 --- a/packages/components/stepper/stepper.ts +++ b/packages/components/stepper/stepper.ts @@ -62,20 +62,25 @@ export default class Stepper extends SuperComponent { add(a: number, b: number) { const maxLen = Math.max(this.getLen(a), this.getLen(b)); const base = 10 ** maxLen; - return Math.round(a * base + b * base) / base; + const result = Math.round(a * base + b * base) / base; + // 保留运算涉及的最大小数位数,避免精度信息丢失 + return maxLen > 0 ? result.toFixed(maxLen) : result; }, format(value) { const { min, max, step } = this.properties as any; - const len = Math.max(this.getLen(step), this.getLen(value)); + // 使用字符串形式计算小数位数,避免数字隐式转换导致末尾0丢失 + const len = Math.max(this.getLen(step), this.getLen(String(value))); // 超过边界取边界值 return Math.max(Math.min(max, value, Number.MAX_SAFE_INTEGER), min, Number.MIN_SAFE_INTEGER).toFixed(len); }, setValue(value) { - const newValue = Number(this.format(value)); + const formattedStr = this.format(value); + const newValue = Number(formattedStr); - this.updateCurrentValue(newValue); + // 使用 format 返回的字符串更新显示值,避免 Number() 转换丢失末尾0 + this.updateCurrentValue(formattedStr); if (this.preValue === newValue) return; @@ -139,14 +144,15 @@ export default class Stepper extends SuperComponent { this.updateCurrentValue(this.data.integer ? newValue : formatted); - if (this.data.integer || /\.\d+/.test(formatted)) { + if (this.data.integer || /\.\d*[1-9]/.test(formatted)) { this.setValue(formatted); } }, handleBlur(e) { const { value: rawValue } = e.detail; - const value = this.format(rawValue); + const formatted = this.filterIllegalChar(rawValue); + const value = this.format(formatted); this.setValue(value); this.triggerEvent('blur', { value }); diff --git a/packages/uniapp-components/stepper/stepper.vue b/packages/uniapp-components/stepper/stepper.vue index 2ef00df70..08ca9df2b 100644 --- a/packages/uniapp-components/stepper/stepper.vue +++ b/packages/uniapp-components/stepper/stepper.vue @@ -51,7 +51,7 @@ import TIcon from '../icon/icon'; import { uniComponent } from '../common/src/index'; import { prefix } from '../common/config'; -import { coalesce } from '../common/utils'; +import { coalesce, nextTick } from '../common/utils'; import props from './props'; import tools from '../common/utils.wxs'; @@ -128,20 +128,27 @@ export default uniComponent({ add(a, b) { const maxLen = Math.max(this.getLen(a), this.getLen(b)); const base = 10 ** maxLen; - return Math.round(a * base + b * base) / base; + const result = Math.round(a * base + b * base) / base; + // 保留运算涉及的最大小数位数,避免精度信息丢失 + return maxLen > 0 ? result.toFixed(maxLen) : result; }, format(value) { const { min, max, step } = this; - const len = Math.max(this.getLen(step), this.getLen(value)); + // 使用字符串形式计算小数位数,避免数字隐式转换导致末尾0丢失 + const len = Math.max(this.getLen(step), this.getLen(String(value))); // 超过边界取边界值 return Math.max(Math.min(max, value, Number.MAX_SAFE_INTEGER), min, Number.MIN_SAFE_INTEGER).toFixed(len); }, setValue(value) { - const newValue = Number(this.format(value)); + const formattedStr = this.format(value); + const newValue = Number(formattedStr); - this.updateCurrentValue(newValue); + nextTick().then(() => { + // 使用 format 返回的字符串更新显示值,避免 Number() 转换丢失末尾0 + this.updateCurrentValue(formattedStr); + }); if (this.preValue === newValue) return; @@ -201,16 +208,26 @@ export default uniComponent({ const formatted = this.filterIllegalChar(value); const newValue = this.format(formatted); - this.updateCurrentValue(this.integer ? newValue : formatted); + const displayValue = this.integer ? newValue : formatted; + // 当过滤后的值与当前值相同时,需要先清空再回填,强制触发视图更新 + if (String(this.currentValue) === String(displayValue)) { + this.updateCurrentValue(''); + nextTick().then(() => { + this.updateCurrentValue(displayValue); + }); + } else { + this.updateCurrentValue(displayValue); + } - if (this.integer || /\.\d+/.test(formatted)) { + if (this.integer || /\.\d*[1-9]/.test(formatted)) { this.setValue(formatted); } }, handleBlur(e) { const { value: rawValue } = e.detail; - const value = this.format(rawValue); + const formatted = this.filterIllegalChar(rawValue); + const value = this.format(formatted); this.setValue(value); this.$emit('blur', { value }); From 2fa9a60b8c90a3290712714d2dcadb814e14896c Mon Sep 17 00:00:00 2001 From: novlan1 <1576271227@qq.com> Date: Tue, 10 Mar 2026 14:42:31 +0800 Subject: [PATCH 2/2] fix: fix unit test error --- packages/components/stepper/stepper.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/packages/components/stepper/stepper.ts b/packages/components/stepper/stepper.ts index c8332fc0b..a16c0b6d4 100644 --- a/packages/components/stepper/stepper.ts +++ b/packages/components/stepper/stepper.ts @@ -121,8 +121,11 @@ export default class Stepper extends SuperComponent { }, updateCurrentValue(value) { + // 当字符串转数字不丢失信息时(如 "88" → 88),用数字类型,保持模板渲染一致性 + // 当会丢失信息时(如 "1.0" → 1),保留字符串以维持小数末尾0 + const numValue = Number(value); this.setData({ - currentValue: value, + currentValue: String(numValue) === String(value) ? numValue : value, }); },