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