@@ -42,21 +42,25 @@ export default {
4242import wdIcon from ' ../wd-icon/wd-icon.vue'
4343import { computed , nextTick , ref , watch } from ' vue'
4444import { isDef , isEqual } from ' ../common/util'
45- import { inputNumberProps } from ' ./types'
45+ import { inputNumberProps , InputNumberEventType } from ' ./types'
4646import { callInterceptor } from ' ../common/interceptor'
4747
4848const props = defineProps (inputNumberProps )
4949const emit = defineEmits ([' focus' , ' blur' , ' change' , ' update:modelValue' ])
5050const inputValue = ref <string | number >(getInitValue ()) // 输入框的值
5151
52- // 减号是否禁用
52+ /**
53+ * 判断数字是否达到最小值限制
54+ */
5355const minDisabled = computed (() => {
5456 const value = formatValue (inputValue .value )
5557 const { disabled, min, step } = props
5658 return disabled || Number (value ) <= min || changeStep (value , - step ) < min
5759})
5860
59- // 加号是否禁用
61+ /**
62+ * 判断数字是否达到最大值限制
63+ */
6064const maxDisabled = computed (() => {
6165 const value = formatValue (inputValue .value )
6266 const { disabled, max, step } = props
@@ -67,17 +71,22 @@ const maxDisabled = computed(() => {
6771watch (
6872 () => props .modelValue ,
6973 (value ) => {
70- updateValue (value )
74+ updateValue (value , InputNumberEventType . Watch )
7175 }
7276)
7377
7478// 监听 max, min, precision 变化
7579watch ([() => props .max , () => props .min , () => props .precision ], () => {
7680 const value = formatValue (inputValue .value )
77- updateValue (value )
81+ updateValue (value , InputNumberEventType . Watch )
7882})
7983
80- // 判断两个值是否相等
84+ /**
85+ * 对比两个值是否相等
86+ * @param value1 第一个值
87+ * @param value2 第二个值
88+ * @returns 是否相等
89+ */
8190function isValueEqual(value1 : number | string , value2 : number | string ) {
8291 return isEqual (String (value1 ), String (value2 ))
8392}
@@ -97,7 +106,11 @@ function toPrecision(value: number) {
97106 return Number (parseFloat (` ${Math .round (value * Math .pow (10 , precision )) / Math .pow (10 , precision )} ` ).toFixed (precision ))
98107}
99108
100- // 获取值的精度
109+ /**
110+ * 获取数字的小数位数
111+ * @param value 需要计算精度的数字
112+ * @returns 小数位数
113+ */
101114function getPrecision(value ? : number ) {
102115 if (! isDef (value )) return 0
103116 const valueString = value .toString ()
@@ -109,28 +122,75 @@ function getPrecision(value?: number) {
109122 return precision
110123}
111124
112- // 严格按照步进值递增或递减
125+ /**
126+ * 按步进值严格递增或递减
127+ * @param value 当前值
128+ * @returns 按步进值调整后的值
129+ */
113130function toStrictlyStep(value : number | string ) {
114131 const stepPrecision = getPrecision (props .step )
115132 const precisionFactory = Math .pow (10 , stepPrecision )
116133 return (Math .round (Number (value ) / props .step ) * precisionFactory * props .step ) / precisionFactory
117134}
118135
119- // 更新值
120- function updateValue(value : string | number , fromUser : boolean = false ) {
121- if (isValueEqual (value , inputValue .value )) {
122- return
136+ // 内部更新处理函数
137+ function doUpdate(value : string | number ) {
138+ inputValue .value = value
139+ const formatted = formatValue (value )
140+ nextTick (() => {
141+ inputValue .value = formatted
142+ emit (' update:modelValue' , inputValue .value )
143+ emit (' change' , { value: inputValue .value })
144+ })
145+ }
146+
147+ /**
148+ * 清理输入字符串中多余的小数点
149+ * @param value 输入的字符串
150+ * @returns 清理后的字符串
151+ */
152+ function cleanExtraDecimal(value : string ): string {
153+ const precisionAllowed = Number (props .precision ) > 0
154+ if (precisionAllowed ) {
155+ const dotIndex = value .indexOf (' .' )
156+ if (dotIndex === - 1 ) {
157+ return value
158+ } else {
159+ const integerPart = value .substring (0 , dotIndex + 1 )
160+ // 去除后续出现的'.'
161+ const decimalPart = value .substring (dotIndex + 1 ).replace (/ \. / g , ' ' )
162+ return integerPart + decimalPart
163+ }
164+ } else {
165+ // 不允许小数:保留整数部分
166+ const dotIndex = value .indexOf (' .' )
167+ return dotIndex !== - 1 ? value .substring (0 , dotIndex ) : value
123168 }
169+ }
124170
125- const update = () => {
171+ /**
172+ * 更新输入框的值
173+ * @param value 新的值
174+ * @param eventType 触发更新的事件类型
175+ */
176+ function updateValue(value : string | number , eventType : InputNumberEventType = InputNumberEventType .Input ) {
177+ const fromUser = eventType !== InputNumberEventType .Watch // watch时不认为是用户直接输入
178+ const forceFormat = eventType === InputNumberEventType .Blur || eventType === InputNumberEventType .Button
179+ // 对于 Input 和 Watch 类型,如果值以'.'结尾,则直接更新,不进行格式化
180+ if ((eventType === InputNumberEventType .Input || eventType === InputNumberEventType .Watch ) && String (value ).endsWith (' .' ) && props .precision ) {
126181 inputValue .value = value
127- const formatted = formatValue (value )
128182 nextTick (() => {
129- inputValue .value = formatted
183+ inputValue .value = cleanExtraDecimal ( String ( value ))
130184 emit (' update:modelValue' , inputValue .value )
131185 emit (' change' , { value: inputValue .value })
132186 })
187+ return
133188 }
189+ if (! forceFormat && isValueEqual (value , inputValue .value )) {
190+ return
191+ }
192+
193+ const update = () => doUpdate (value )
134194
135195 if (fromUser ) {
136196 callInterceptor (props .beforeChange , {
@@ -153,11 +213,10 @@ function changeStep(val: string | number, step: number) {
153213 return toPrecision ((val * precisionFactor + step * precisionFactor ) / precisionFactor )
154214}
155215
156- // 改变值
157216function changeValue(step : number ) {
158217 if ((step < 0 && (minDisabled .value || props .disableMinus )) || (step > 0 && (maxDisabled .value || props .disablePlus ))) return
159218 const value = changeStep (inputValue .value , step )
160- updateValue (value , true )
219+ updateValue (value , InputNumberEventType . Button )
161220}
162221
163222// 减少值
@@ -170,26 +229,22 @@ function add() {
170229 changeValue (props .step )
171230}
172231
173- // 处理输入事件
174232function handleInput(event : any ) {
175- let value = event .detail .value || ' '
176- updateValue (value , true )
233+ const rawValue = event .detail .value || ' '
234+ updateValue (rawValue , InputNumberEventType .Input )
235+ }
236+
237+ function handleBlur(event : any ) {
238+ const value = event .detail .value || ' '
239+ updateValue (value , InputNumberEventType .Blur )
240+ emit (' blur' , { value })
177241}
178242
179243// 处理聚焦事件
180244function handleFocus(event : any ) {
181245 emit (' focus' , event .detail )
182246}
183247
184- // 处理失焦事件
185- function handleBlur(event : any ) {
186- const value = event .detail .value || ' '
187- updateValue (value , true )
188- emit (' blur' , {
189- value
190- })
191- }
192-
193248// 格式化值
194249function formatValue(value : string | number ) {
195250 if (props .allowNull && (! isDef (value ) || value === ' ' )) {
0 commit comments