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