@aspire-ui/element-component-pro 1.0.8 → 1.0.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -2594,6 +2594,10 @@ declare const _default: {
2594
2594
  type: import('vue').PropType<import('.').FormattedNumberRounding>;
2595
2595
  default: string;
2596
2596
  };
2597
+ inputLimit: {
2598
+ type: import('vue').PropType<boolean>;
2599
+ default: boolean;
2600
+ };
2597
2601
  }, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {
2598
2602
  input: (value: unknown) => void;
2599
2603
  }, string, Readonly<import('vue').ExtractPropTypes<{
@@ -2618,10 +2622,15 @@ declare const _default: {
2618
2622
  type: import('vue').PropType<import('.').FormattedNumberRounding>;
2619
2623
  default: string;
2620
2624
  };
2625
+ inputLimit: {
2626
+ type: import('vue').PropType<boolean>;
2627
+ default: boolean;
2628
+ };
2621
2629
  }>>, {
2622
2630
  integerDigits: number;
2623
2631
  decimalPlaces: number;
2624
2632
  rounding: import('.').FormattedNumberRounding;
2633
+ inputLimit: boolean;
2625
2634
  }>;
2626
2635
  };
2627
2636
  export default _default;
@@ -3,6 +3,11 @@ export type FormattedNumberRounding = 'floor' | 'ceil' | 'round';
3
3
  /** 仅保留数字、至多一个小数点、可选前导负号 */
4
4
  export declare function sanitizeNumericInput(raw: string): string;
5
5
  export declare function stripNumberGrouping(s: string): string;
6
+ /**
7
+ * 对已清洗的数字串按整数位、小数位截断输入长度(inputLimit 为 true 时使用)。
8
+ * 整数部分至多 integerDigits 位,小数部分至多 decimalPlaces 位;保留末尾仅小数点(如 `12.`)以便继续输入。
9
+ */
10
+ export declare function applyNumericInputDigitLimits(sanitized: string, integerDigits: number, decimalPlaces: number): string;
6
11
  /** 按整数位数上限约束绝对值 */
7
12
  export declare function clampByIntegerDigits(value: number, integerDigits: number, decimalPlaces: number): number;
8
13
  export declare function roundToDecimals(value: number, decimalPlaces: number, rounding: FormattedNumberRounding): number;
@@ -10,6 +15,10 @@ export declare function roundToDecimals(value: number, decimalPlaces: number, ro
10
15
  * 解析 → 按整数位夹紧 → 按小数位与进位方式舍入 → 再夹紧(防止舍入后越界)
11
16
  */
12
17
  export declare function normalizeNumericValue(value: number, integerDigits: number, decimalPlaces: number, rounding: FormattedNumberRounding): number;
18
+ /**
19
+ * 固定小数位数字符串(无千分位),用于表单存值以保留配置的小数位数(number 无法保留尾随 0)。
20
+ */
21
+ export declare function toFixedDecimalString(value: number, decimalPlaces: number): string;
13
22
  /** 千分位格式化展示(整数部分),小数部分固定 m 位 */
14
23
  export declare function formatWithThousands(value: number, decimalPlaces: number): string;
15
24
  /** 编辑态:无千分位,去掉多余尾部 0(在 m 位精度内) */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aspire-ui/element-component-pro",
3
- "version": "1.0.08",
3
+ "version": "1.0.10",
4
4
  "description": "Element UI 二次封装组件库,基于 Vue 2.7 + TypeScript + setup 语法糖,实现 VbenAdmin 风格的 Pro 组件",
5
5
  "type": "module",
6
6
  "main": "./dist/element-component-pro.umd.js",
@@ -14,11 +14,13 @@
14
14
  import { ref, watch } from 'vue'
15
15
  import type { FormattedNumberRounding } from '../utils/formattedNumber'
16
16
  import {
17
+ applyNumericInputDigitLimits,
17
18
  formatWithThousands,
18
19
  normalizeNumericValue,
19
20
  numberToEditString,
20
21
  sanitizeNumericInput,
21
22
  stripNumberGrouping,
23
+ toFixedDecimalString,
22
24
  } from '../utils/formattedNumber'
23
25
 
24
26
  const props = withDefaults(
@@ -32,11 +34,17 @@ const props = withDefaults(
32
34
  decimalPlaces?: number
33
35
  /** 进位方式,默认四舍五入 */
34
36
  rounding?: FormattedNumberRounding
37
+ /**
38
+ * 为 true 时在输入过程中按 integerDigits / decimalPlaces 限制可输入位数;
39
+ * 为 false 时仅失焦后规范化,输入阶段不截断长度。
40
+ */
41
+ inputLimit?: boolean
35
42
  }>(),
36
43
  {
37
44
  integerDigits: 5,
38
45
  decimalPlaces: 6,
39
46
  rounding: 'round',
47
+ inputLimit: true,
40
48
  }
41
49
  )
42
50
 
@@ -78,13 +86,21 @@ watch(
78
86
  { immediate: true, deep: true }
79
87
  )
80
88
 
89
+ function emitStoredValue(normalized: number) {
90
+ emit('input', toFixedDecimalString(normalized, decM()))
91
+ }
92
+
81
93
  function onInput(val: string) {
82
- const clean = sanitizeNumericInput(val)
94
+ let clean = sanitizeNumericInput(val)
95
+ if (props.inputLimit !== false) {
96
+ clean = applyNumericInputDigitLimits(clean, intN(), decM())
97
+ }
83
98
  displayText.value = clean
84
99
  if (clean === '' || clean === '-') return
85
100
  const num = Number(clean)
86
101
  if (!Number.isFinite(num)) return
87
- emit('input', num)
102
+ const normalized = normalizeNumericValue(num, intN(), decM(), props.rounding)
103
+ emitStoredValue(normalized)
88
104
  }
89
105
 
90
106
  function onFocus() {
@@ -117,6 +133,6 @@ function onBlur() {
117
133
  }
118
134
  const final = normalizeNumericValue(parsed, intN(), decM(), props.rounding)
119
135
  displayText.value = formatWithThousands(final, decM())
120
- emit('input', final)
136
+ emitStoredValue(final)
121
137
  }
122
138
  </script>
@@ -31,6 +31,40 @@ export function stripNumberGrouping(s: string): string {
31
31
  return s.replace(/,/g, '').trim()
32
32
  }
33
33
 
34
+ /**
35
+ * 对已清洗的数字串按整数位、小数位截断输入长度(inputLimit 为 true 时使用)。
36
+ * 整数部分至多 integerDigits 位,小数部分至多 decimalPlaces 位;保留末尾仅小数点(如 `12.`)以便继续输入。
37
+ */
38
+ export function applyNumericInputDigitLimits(
39
+ sanitized: string,
40
+ integerDigits: number,
41
+ decimalPlaces: number
42
+ ): string {
43
+ if (!sanitized || sanitized === '-') return sanitized
44
+ const neg = sanitized[0] === '-'
45
+ let body = neg ? sanitized.slice(1) : sanitized
46
+ const dotIdx = body.indexOf('.')
47
+ if (dotIdx === -1) {
48
+ const maxInt = Math.max(0, integerDigits)
49
+ body = maxInt > 0 ? body.slice(0, maxInt) : body
50
+ return neg ? '-' + body : body
51
+ }
52
+ let intPart = body.slice(0, dotIdx)
53
+ if (integerDigits > 0) {
54
+ intPart = intPart.slice(0, integerDigits)
55
+ }
56
+ const afterDot = body.slice(dotIdx + 1)
57
+ const endsWithDot = afterDot === '' && body.endsWith('.')
58
+ if (decimalPlaces <= 0) {
59
+ return neg ? '-' + intPart : intPart
60
+ }
61
+ if (endsWithDot) {
62
+ return (neg ? '-' : '') + intPart + '.'
63
+ }
64
+ const decPart = afterDot.slice(0, decimalPlaces)
65
+ return (neg ? '-' : '') + intPart + '.' + decPart
66
+ }
67
+
34
68
  function maxAbsValue(integerDigits: number, decimalPlaces: number): number {
35
69
  const maxInt = Math.pow(10, integerDigits) - 1
36
70
  if (decimalPlaces <= 0) return maxInt
@@ -96,6 +130,14 @@ export function normalizeNumericValue(
96
130
  return v
97
131
  }
98
132
 
133
+ /**
134
+ * 固定小数位数字符串(无千分位),用于表单存值以保留配置的小数位数(number 无法保留尾随 0)。
135
+ */
136
+ export function toFixedDecimalString(value: number, decimalPlaces: number): string {
137
+ if (Number.isNaN(value) || !Number.isFinite(value)) return ''
138
+ return value.toFixed(Math.max(0, decimalPlaces))
139
+ }
140
+
99
141
  /** 千分位格式化展示(整数部分),小数部分固定 m 位 */
100
142
  export function formatWithThousands(value: number, decimalPlaces: number): string {
101
143
  if (Number.isNaN(value) || !Number.isFinite(value)) return ''