leisure-core 0.6.62 → 0.6.63

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.
@@ -30,57 +30,46 @@ export default {
30
30
  inheritAttrs: false,
31
31
 
32
32
  props: {
33
- // 数值类型
34
33
  number: {
35
34
  type: Boolean,
36
35
  default: false,
37
36
  },
38
- // 手机号类型
39
37
  mobile: {
40
38
  type: Boolean,
41
39
  default: false,
42
40
  },
43
- // 邮箱类型
44
41
  email: {
45
42
  type: Boolean,
46
43
  default: false,
47
44
  },
48
- // 金额类型
49
45
  amount: {
50
46
  type: Boolean,
51
47
  default: false,
52
48
  },
53
- // 最大长度
54
49
  maxlength: {
55
50
  type: [Number, String],
56
51
  default: null,
57
52
  },
58
- // 是否显示字数统计
59
53
  showCount: {
60
54
  type: Boolean,
61
55
  default: false,
62
56
  },
63
- // 自定义验证函数
64
57
  validator: {
65
58
  type: Function,
66
59
  default: null,
67
60
  },
68
- // 值
69
61
  value: {
70
62
  type: [String, Number],
71
63
  default: "",
72
64
  },
73
- // 是否允许小数
74
65
  allowDecimal: {
75
66
  type: Boolean,
76
67
  default: true,
77
68
  },
78
- // 小数位数限制
79
69
  decimalLimit: {
80
70
  type: Number,
81
71
  default: 2,
82
72
  },
83
- // 新增:是否允许负数(仅对 number 和 amount 类型生效)
84
73
  allowNegative: {
85
74
  type: Boolean,
86
75
  default: false,
@@ -101,11 +90,8 @@ export default {
101
90
  mergedAttrs() {
102
91
  const attrs = { ...this.$attrs };
103
92
 
104
- // 移除已单独处理的属性
105
93
  delete attrs.class;
106
94
  delete attrs.style;
107
-
108
- // 移除props中定义的属性,避免重复
109
95
  delete attrs.number;
110
96
  delete attrs.mobile;
111
97
  delete attrs.email;
@@ -116,9 +102,8 @@ export default {
116
102
  delete attrs.value;
117
103
  delete attrs.allowDecimal;
118
104
  delete attrs.decimalLimit;
119
- delete attrs.allowNegative; // 新增
105
+ delete attrs.allowNegative;
120
106
 
121
- // 合并值,确保我们的 value 逻辑优先
122
107
  return {
123
108
  ...attrs,
124
109
  value: this.displayValue,
@@ -130,7 +115,6 @@ export default {
130
115
  if (this.maxlength) {
131
116
  return Number(this.maxlength);
132
117
  }
133
- // 手机号默认11位
134
118
  if (this.mobile) {
135
119
  return 11;
136
120
  }
@@ -148,7 +132,6 @@ export default {
148
132
  },
149
133
 
150
134
  displayValue() {
151
- // 金额类型在非聚焦状态下显示格式化后的值
152
135
  if (
153
136
  this.amount &&
154
137
  !this.isFocused &&
@@ -168,7 +151,6 @@ export default {
168
151
 
169
152
  internalValue(newVal) {
170
153
  this.validateInput(newVal);
171
- // 触发外部监听的事件
172
154
  this.$listeners.change && this.$listeners.change(newVal);
173
155
  },
174
156
  },
@@ -177,22 +159,18 @@ export default {
177
159
  handleInput(value) {
178
160
  let processedValue = value;
179
161
 
180
- // 数值类型处理
181
162
  if (this.number) {
182
163
  processedValue = this.formatNumber(value);
183
164
  }
184
165
 
185
- // 手机号类型处理
186
166
  if (this.mobile) {
187
167
  processedValue = this.formatMobile(value);
188
168
  }
189
169
 
190
- // 金额类型处理
191
170
  if (this.amount) {
192
171
  processedValue = this.formatAmountInput(value);
193
172
  }
194
173
 
195
- // 长度限制
196
174
  if (
197
175
  this.computedMaxlength &&
198
176
  processedValue.length > this.computedMaxlength
@@ -202,8 +180,6 @@ export default {
202
180
 
203
181
  this.internalValue = processedValue;
204
182
  this.$emit("input", processedValue);
205
-
206
- // 触发外部监听的事件
207
183
  this.$listeners.input && this.$listeners.input(processedValue);
208
184
  },
209
185
 
@@ -212,16 +188,12 @@ export default {
212
188
  this.isFocused = false;
213
189
  this.validateInput(this.internalValue, true);
214
190
  this.$emit("blur", event);
215
-
216
- // 触发外部监听的事件
217
191
  this.$listeners.blur && this.$listeners.blur(event);
218
192
  },
219
193
 
220
194
  handleFocus(event) {
221
195
  this.isFocused = true;
222
196
  this.$emit("focus", event);
223
-
224
- // 触发外部监听的事件
225
197
  this.$listeners.focus && this.$listeners.focus(event);
226
198
  },
227
199
 
@@ -229,37 +201,29 @@ export default {
229
201
  this.hasError = false;
230
202
  this.errorMessage = "";
231
203
  this.$emit("clear");
232
-
233
- // 触发外部监听的事件
234
204
  this.$listeners.clear && this.$listeners.clear();
235
205
  },
236
206
 
237
207
  formatNumber(value) {
238
- // 根据 allowNegative 决定是否保留负号
239
208
  let filtered = value;
240
209
  if (this.allowNegative) {
241
- // 允许负数:保留数字、小数点、负号,但负号只能出现在开头,多个负号只保留第一个
210
+ // 允许负数:保留数字、小数点、负号,负号只能出现在开头
242
211
  filtered = value.replace(/[^\d.-]/g, "");
243
- // 处理多个负号的情况:只保留第一个负号,并确保负号在开头
244
212
  const hasNegative = filtered.startsWith("-");
245
213
  filtered = filtered.replace(/-/g, "");
246
214
  if (hasNegative) {
247
215
  filtered = "-" + filtered;
248
216
  }
249
- // 处理小数点后多余的小数点
250
217
  filtered = filtered.replace(/(\..*)\./g, "$1");
251
218
  } else {
252
- // 不允许负数:直接过滤掉负号
253
219
  filtered = value.replace(/[^\d.]/g, "");
254
220
  filtered = filtered.replace(/(\..*)\./g, "$1");
255
221
  }
256
222
 
257
- // 如果不允许小数,移除小数点
258
223
  if (this.number && !this.allowDecimal) {
259
224
  filtered = filtered.replace(/\./g, "");
260
225
  }
261
226
 
262
- // 如果允许小数,限制小数位数
263
227
  if (this.number && this.allowDecimal && this.decimalLimit > 0) {
264
228
  const parts = filtered.split(".");
265
229
  if (parts.length === 2 && parts[1].length > this.decimalLimit) {
@@ -271,69 +235,62 @@ export default {
271
235
  },
272
236
 
273
237
  formatMobile(value) {
274
- // 只允许数字
275
238
  return value.replace(/\D/g, "");
276
239
  },
277
240
 
278
241
  formatAmountInput(value) {
279
- // 金额输入过滤
280
242
  let filteredValue = value;
281
243
 
282
244
  if (this.allowNegative) {
283
- // 允许负数:保留数字、小数点、负号,负号只能出现在开头
284
245
  filteredValue = value.replace(/[^\d.-]/g, "");
285
246
  const hasNegative = filteredValue.startsWith("-");
286
247
  filteredValue = filteredValue.replace(/-/g, "");
287
248
  if (hasNegative) {
288
249
  filteredValue = "-" + filteredValue;
289
250
  }
251
+ // 修复:允许临时输入 '-' 或 '-.',不清空,以便用户继续输入小数部分
252
+ if (filteredValue === "-" || filteredValue === "-.") {
253
+ return filteredValue;
254
+ }
290
255
  } else {
291
- // 不允许负数:只保留数字和小数点
292
256
  filteredValue = value.replace(/[^\d.]/g, "");
293
257
  }
294
258
 
295
- // 如果禁止小数,则删除所有小数点
296
259
  if (!this.allowDecimal) {
297
260
  return filteredValue.replace(/\./g, "");
298
261
  }
299
262
 
300
- // 处理多个小数点的情况
301
263
  const parts = filteredValue.split(".");
302
264
  if (parts.length > 2) {
303
265
  filteredValue = parts[0] + "." + parts.slice(1).join("");
304
266
  }
305
267
 
306
- // 限制小数位数
307
268
  if (parts.length === 2 && parts[1].length > this.decimalLimit) {
308
269
  filteredValue =
309
270
  parts[0] + "." + parts[1].substring(0, this.decimalLimit);
310
271
  }
311
272
 
312
- // 特殊情况:单独的负号或负号+小数点不允许,清除无效输入
313
- if (filteredValue === "-" || filteredValue === "-.") {
314
- filteredValue = "";
315
- }
316
-
317
273
  return filteredValue;
318
274
  },
319
275
 
320
276
  formatAmount(value) {
321
277
  if (value === undefined || value === null || value === "") return "";
322
278
 
323
- // 将值转换为字符串,处理负数
324
279
  const strValue = String(value);
325
280
  const isNegative = strValue.startsWith("-");
326
281
  let absValue = isNegative ? strValue.slice(1) : strValue;
327
282
 
328
- // 分割整数和小数部分
283
+ // 修复:处理无效的中间状态,如 '-' 或 '-.'
284
+ if (absValue === "" || absValue === ".") {
285
+ return strValue;
286
+ }
287
+
329
288
  const parts = absValue.split(".");
330
289
  let integerPart = parts[0];
331
290
  let decimalPart = parts.length > 1 ? parts[1] : "";
332
291
 
333
- // 对整数部分添加千分位分隔符
334
292
  integerPart = integerPart.replace(/\B(?=(\d{3})+(?!\d))/g, ",");
335
293
 
336
- // 组合整数和小数部分
337
294
  let formatted = "";
338
295
  if (decimalPart && this.allowDecimal) {
339
296
  formatted = `${integerPart}.${decimalPart}`;
@@ -341,7 +298,6 @@ export default {
341
298
  formatted = integerPart;
342
299
  }
343
300
 
344
- // 添加负号
345
301
  if (isNegative && formatted !== "") {
346
302
  formatted = "-" + formatted;
347
303
  }
@@ -354,15 +310,12 @@ export default {
354
310
 
355
311
  let isValid = true;
356
312
  let message = "";
357
-
358
313
  const strValue = String(value || "");
359
314
 
360
- // 数值验证
361
315
  if (this.number && strValue) {
362
316
  let numberPattern;
363
317
  if (this.allowNegative) {
364
- // 允许负数:可选负号,整数或小数
365
- numberPattern = new RegExp(`^-?\\d*\\.?\\d*$`);
318
+ numberPattern = /^-?\d*\.?\d*$/;
366
319
  } else {
367
320
  numberPattern = /^\d*\.?\d*$/;
368
321
  }
@@ -372,7 +325,6 @@ export default {
372
325
  }
373
326
  }
374
327
 
375
- // 手机号验证
376
328
  if (this.mobile && strValue) {
377
329
  if (!/^1[3-9]\d{9}$/.test(strValue)) {
378
330
  isValid = false;
@@ -380,7 +332,6 @@ export default {
380
332
  }
381
333
  }
382
334
 
383
- // 邮箱验证
384
335
  if (this.email && strValue) {
385
336
  if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(strValue)) {
386
337
  isValid = false;
@@ -388,40 +339,56 @@ export default {
388
339
  }
389
340
  }
390
341
 
391
- // 金额验证
392
342
  if (this.amount && strValue) {
393
- // 去除千分位分隔符后再验证
394
343
  const cleanValue = strValue.replace(/,/g, "");
395
344
  let amountPattern;
396
345
  if (this.allowNegative) {
397
- amountPattern = this.allowDecimal
398
- ? new RegExp(`^-?\\d+(\\.\\d{0,${this.decimalLimit}})?$`)
399
- : /^-?\d+$/;
346
+ // 更严格的金额正则:不允许单独的负号、小数点、负号+小数点
347
+ if (this.allowDecimal) {
348
+ amountPattern = /^-?(?:[1-9]\d*|0)(?:\.\d{0,2})?$|^-?0\.\d{0,2}$/;
349
+ } else {
350
+ amountPattern = /^-?(?:[1-9]\d*|0)$/;
351
+ }
352
+ // 临时允许用户输入过程中的不完整状态,但最终提交时需完整
353
+ // 这里先检查完整格式,如果是不完整状态(如 '-'、'-.'、'.')也认为无效
354
+ if (
355
+ cleanValue === "-" ||
356
+ cleanValue === "-." ||
357
+ cleanValue === "." ||
358
+ cleanValue === ""
359
+ ) {
360
+ isValid = false;
361
+ message = this.allowDecimal
362
+ ? "请输入有效的金额"
363
+ : "请输入有效的整数金额";
364
+ } else if (!amountPattern.test(cleanValue)) {
365
+ isValid = false;
366
+ message = this.allowDecimal
367
+ ? `请输入有效的金额(最多${this.decimalLimit}位小数)`
368
+ : "请输入有效的金额(整数)";
369
+ }
400
370
  } else {
401
371
  amountPattern = this.allowDecimal
402
- ? new RegExp(`^\\d+(\\.\\d{0,${this.decimalLimit}})?$`)
403
- : /^\d+$/;
404
- }
405
- if (!amountPattern.test(cleanValue)) {
406
- isValid = false;
407
- message = this.allowDecimal
408
- ? `请输入有效的金额(最多${this.decimalLimit}位小数)`
409
- : "请输入有效的金额(整数)";
372
+ ? /^(?:[1-9]\d*|0)(?:\.\d{0,2})?$|^0\.\d{0,2}$/
373
+ : /^(?:[1-9]\d*|0)$/;
374
+ if (!amountPattern.test(cleanValue)) {
375
+ isValid = false;
376
+ message = this.allowDecimal
377
+ ? `请输入有效的金额(最多${this.decimalLimit}位小数)`
378
+ : "请输入有效的金额(整数)";
379
+ }
410
380
  }
411
- // 额外检查负数是否允许
412
381
  if (!this.allowNegative && cleanValue.startsWith("-")) {
413
382
  isValid = false;
414
383
  message = "不允许输入负数";
415
384
  }
416
385
  }
417
386
 
418
- // 最大长度验证
419
387
  if (this.computedMaxlength && strValue.length > this.computedMaxlength) {
420
388
  isValid = false;
421
389
  message = `输入内容不能超过${this.computedMaxlength}个字符`;
422
390
  }
423
391
 
424
- // 自定义验证
425
392
  if (this.validator && typeof this.validator === "function") {
426
393
  const customResult = this.validator(value);
427
394
  if (customResult !== true) {
@@ -436,25 +403,21 @@ export default {
436
403
  return isValid;
437
404
  },
438
405
 
439
- // 公开方法:手动验证
440
406
  validate() {
441
407
  this.isTouched = true;
442
408
  return this.validateInput(this.internalValue, true);
443
409
  },
444
410
 
445
- // 公开方法:清除验证状态
446
411
  clearValidate() {
447
412
  this.hasError = false;
448
413
  this.errorMessage = "";
449
414
  this.isTouched = false;
450
415
  },
451
416
 
452
- // 公开方法:聚焦输入框
453
417
  focus() {
454
418
  this.$refs.inputRef?.focus();
455
419
  },
456
420
 
457
- // 公开方法:失焦输入框
458
421
  blur() {
459
422
  this.$refs.inputRef?.blur();
460
423
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "leisure-core",
3
- "version": "0.6.62",
3
+ "version": "0.6.63",
4
4
  "description": "leisure-core是京心数据基于vue2.x开发的一套后台管理系统桌面端组件库,封装了大量实用的UI控件模板,非常方便开发者快速搭建前端应用",
5
5
  "private": false,
6
6
  "author": "北方乐逍遥(zcx7878)",