sculp-js 1.5.1 → 1.7.0
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/README.md +10 -1
- package/lib/cjs/array.js +2 -21
- package/lib/cjs/async.js +2 -2
- package/lib/cjs/base64.js +62 -0
- package/lib/cjs/clipboard.js +2 -2
- package/lib/cjs/cookie.js +2 -2
- package/lib/cjs/date.js +2 -3
- package/lib/cjs/dom.js +2 -2
- package/lib/cjs/download.js +2 -2
- package/lib/cjs/easing.js +2 -2
- package/lib/cjs/file.js +2 -2
- package/lib/cjs/func.js +3 -3
- package/lib/cjs/index.js +37 -4
- package/lib/cjs/math.js +88 -0
- package/lib/cjs/number.js +2 -2
- package/lib/cjs/object.js +10 -20
- package/lib/cjs/path.js +2 -2
- package/lib/cjs/qs.js +2 -2
- package/lib/cjs/random.js +2 -2
- package/lib/cjs/string.js +3 -3
- package/lib/cjs/tooltip.js +2 -2
- package/lib/cjs/tree.js +4 -4
- package/lib/cjs/type.js +69 -3
- package/lib/cjs/unique.js +2 -2
- package/lib/cjs/url.js +2 -2
- package/lib/cjs/validator.js +147 -0
- package/lib/cjs/variable.js +118 -0
- package/lib/cjs/watermark.js +2 -2
- package/lib/cjs/we-decode.js +4 -4
- package/lib/es/array.js +3 -21
- package/lib/es/async.js +2 -2
- package/lib/es/base64.js +59 -0
- package/lib/es/clipboard.js +2 -2
- package/lib/es/cookie.js +2 -2
- package/lib/es/date.js +2 -3
- package/lib/es/dom.js +2 -2
- package/lib/es/download.js +2 -2
- package/lib/es/easing.js +2 -2
- package/lib/es/file.js +2 -2
- package/lib/es/func.js +3 -3
- package/lib/es/index.js +9 -5
- package/lib/es/math.js +82 -0
- package/lib/es/number.js +2 -2
- package/lib/es/object.js +9 -18
- package/lib/es/path.js +2 -2
- package/lib/es/qs.js +2 -2
- package/lib/es/random.js +2 -2
- package/lib/es/string.js +3 -3
- package/lib/es/tooltip.js +2 -2
- package/lib/es/tree.js +4 -4
- package/lib/es/type.js +67 -4
- package/lib/es/unique.js +2 -2
- package/lib/es/url.js +2 -2
- package/lib/es/validator.js +130 -0
- package/lib/es/variable.js +112 -0
- package/lib/es/watermark.js +2 -2
- package/lib/es/we-decode.js +4 -4
- package/lib/index.d.ts +236 -21
- package/lib/tsdoc-metadata.json +11 -0
- package/lib/umd/index.js +571 -155
- package/package.json +2 -2
package/lib/umd/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* sculp-js v1.
|
|
3
|
-
* (c) 2023-
|
|
2
|
+
* sculp-js v1.7.0
|
|
3
|
+
* (c) 2023-present chandq
|
|
4
4
|
* Released under the MIT License.
|
|
5
5
|
*/
|
|
6
6
|
|
|
@@ -10,6 +10,117 @@
|
|
|
10
10
|
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.sculpJs = {}, global.bezier));
|
|
11
11
|
})(this, (function (exports, bezier) { 'use strict';
|
|
12
12
|
|
|
13
|
+
/**
|
|
14
|
+
* 遍历数组,返回 false 中断遍历(支持continue和break操作)
|
|
15
|
+
*
|
|
16
|
+
* @param {ArrayLike<V>} array
|
|
17
|
+
* @param {(val: V, idx: number) => any} iterator 迭代函数, 返回值为true时continue, 返回值为false时break
|
|
18
|
+
* @param {boolean} reverse 是否倒序
|
|
19
|
+
* @returns {*}
|
|
20
|
+
*/
|
|
21
|
+
function arrayEach(array, iterator, reverse = false) {
|
|
22
|
+
if (reverse) {
|
|
23
|
+
for (let idx = array.length - 1; idx >= 0; idx--) {
|
|
24
|
+
const val = array[idx];
|
|
25
|
+
const re = iterator(val, idx, array);
|
|
26
|
+
if (re === false)
|
|
27
|
+
break;
|
|
28
|
+
else if (re === true)
|
|
29
|
+
continue;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
else {
|
|
33
|
+
for (let idx = 0; idx < array.length; idx++) {
|
|
34
|
+
const val = array[idx];
|
|
35
|
+
const re = iterator(val, idx, array);
|
|
36
|
+
if (re === false)
|
|
37
|
+
break;
|
|
38
|
+
else if (re === true)
|
|
39
|
+
continue;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* 异步遍历数组,返回 false 中断遍历
|
|
45
|
+
* @param {ArrayLike<V>} array 数组
|
|
46
|
+
* @param {(val: V, idx: number) => Promise<any>} iterator 支持Promise类型的回调函数
|
|
47
|
+
* @param {boolean} reverse 是否反向遍历
|
|
48
|
+
*/
|
|
49
|
+
async function arrayEachAsync(array, iterator, reverse = false) {
|
|
50
|
+
if (reverse) {
|
|
51
|
+
for (let idx = array.length - 1; idx >= 0; idx--) {
|
|
52
|
+
const val = array[idx];
|
|
53
|
+
if ((await iterator(val, idx)) === false)
|
|
54
|
+
break;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
else {
|
|
58
|
+
for (let idx = 0; idx < array.length; idx++) {
|
|
59
|
+
const val = array[idx];
|
|
60
|
+
if ((await iterator(val, idx)) === false)
|
|
61
|
+
break;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* 插入到目标位置之前
|
|
67
|
+
* @param {AnyArray} array
|
|
68
|
+
* @param {number} start
|
|
69
|
+
* @param {number} to
|
|
70
|
+
* @returns {*}
|
|
71
|
+
*/
|
|
72
|
+
function arrayInsertBefore(array, start, to) {
|
|
73
|
+
if (start === to || start + 1 === to)
|
|
74
|
+
return;
|
|
75
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
76
|
+
const [source] = array.splice(start, 1);
|
|
77
|
+
const insertIndex = to < start ? to : to - 1;
|
|
78
|
+
array.splice(insertIndex, 0, source);
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* 数组删除指定项目
|
|
82
|
+
* @param {V[]} array
|
|
83
|
+
* @param {(val: V, idx: number) => boolean} expect
|
|
84
|
+
* @returns {V[]}
|
|
85
|
+
*/
|
|
86
|
+
function arrayRemove(array, expect) {
|
|
87
|
+
const indexes = [];
|
|
88
|
+
// 这里重命名一下:是为了杜绝 jest 里的 expect 与之产生检查错误
|
|
89
|
+
// eslint 的 jest 语法检查是遇到 expect 函数就以为是单元测试
|
|
90
|
+
const _expect = expect;
|
|
91
|
+
arrayEach(array, (val, idx) => {
|
|
92
|
+
if (_expect(val, idx))
|
|
93
|
+
indexes.push(idx);
|
|
94
|
+
});
|
|
95
|
+
indexes.forEach((val, idx) => array.splice(val - idx, 1));
|
|
96
|
+
return array;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// 常用类型定义
|
|
100
|
+
/**
|
|
101
|
+
* 判断对象内是否有该静态属性
|
|
102
|
+
* @param {object} obj
|
|
103
|
+
* @param {string} key
|
|
104
|
+
* @returns {boolean}
|
|
105
|
+
*/
|
|
106
|
+
function objectHas(obj, key) {
|
|
107
|
+
return Object.prototype.hasOwnProperty.call(obj, key);
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* 判断一个对象是否为类数组
|
|
111
|
+
*
|
|
112
|
+
* @param any
|
|
113
|
+
* @returns {boolean}
|
|
114
|
+
*/
|
|
115
|
+
function arrayLike(any) {
|
|
116
|
+
if (isArray(any))
|
|
117
|
+
return true;
|
|
118
|
+
if (isString(any))
|
|
119
|
+
return true;
|
|
120
|
+
if (!isObject(any))
|
|
121
|
+
return false;
|
|
122
|
+
return objectHas(any, 'length');
|
|
123
|
+
}
|
|
13
124
|
/**
|
|
14
125
|
* 判断任意值的数据类型
|
|
15
126
|
* @param {unknown} any
|
|
@@ -45,7 +156,7 @@
|
|
|
45
156
|
/**
|
|
46
157
|
* 判断一个字符串是否为有效的 JSON, 若有效则返回有效的JSON对象,否则false
|
|
47
158
|
* @param {string} str
|
|
48
|
-
* @
|
|
159
|
+
* @returns {Object | boolean}
|
|
49
160
|
*/
|
|
50
161
|
function isJsonString(str) {
|
|
51
162
|
try {
|
|
@@ -56,6 +167,72 @@
|
|
|
56
167
|
return false;
|
|
57
168
|
}
|
|
58
169
|
}
|
|
170
|
+
/**
|
|
171
|
+
* Checks if `value` is an empty object, collection, map, or set.
|
|
172
|
+
*
|
|
173
|
+
* Objects are considered empty if they have no own enumerable string keyed
|
|
174
|
+
* properties.
|
|
175
|
+
*
|
|
176
|
+
* Array-like values such as `arguments` objects, arrays, buffers, strings, or
|
|
177
|
+
* jQuery-like collections are considered empty if they have a `length` of `0`.
|
|
178
|
+
* Similarly, maps and sets are considered empty if they have a `size` of `0`.
|
|
179
|
+
*
|
|
180
|
+
* @param {*} value The value to check.
|
|
181
|
+
* @returns {boolean} Returns `true` if `value` is empty, else `false`.
|
|
182
|
+
* @example
|
|
183
|
+
*
|
|
184
|
+
* isEmpty(null);
|
|
185
|
+
* // => true
|
|
186
|
+
*
|
|
187
|
+
* isEmpty(true);
|
|
188
|
+
* // => true
|
|
189
|
+
*
|
|
190
|
+
* isEmpty(1);
|
|
191
|
+
* // => true
|
|
192
|
+
*
|
|
193
|
+
* isEmpty([1, 2, 3]);
|
|
194
|
+
* // => false
|
|
195
|
+
*
|
|
196
|
+
* isEmpty({ 'a': 1 });
|
|
197
|
+
* // => false
|
|
198
|
+
*/
|
|
199
|
+
function isEmpty(value) {
|
|
200
|
+
if (isNullOrUnDef(value) || Number.isNaN(value)) {
|
|
201
|
+
return true;
|
|
202
|
+
}
|
|
203
|
+
if (arrayLike(value) && (isArray(value) || isString(value) || isFunction(value.splice))) {
|
|
204
|
+
return !value.length;
|
|
205
|
+
}
|
|
206
|
+
return !Object.keys(value).length;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
// @ref https://cubic-bezier.com/
|
|
210
|
+
const easingDefines = {
|
|
211
|
+
linear: [0, 0, 1, 1],
|
|
212
|
+
ease: [0.25, 0.1, 0.25, 1],
|
|
213
|
+
'ease-in': [0.42, 0, 1, 1],
|
|
214
|
+
'ease-out': [0, 0, 0.58, 1],
|
|
215
|
+
'ease-in-out': [0.42, 0, 0.58, 1]
|
|
216
|
+
};
|
|
217
|
+
/**
|
|
218
|
+
* 缓冲函数化,用于 js 计算缓冲进度
|
|
219
|
+
* @param {EasingNameOrDefine} [name=linear]
|
|
220
|
+
* @returns {EasingFunction}
|
|
221
|
+
*/
|
|
222
|
+
function easingFunctional(name) {
|
|
223
|
+
let fn;
|
|
224
|
+
if (isArray(name)) {
|
|
225
|
+
fn = bezier(...name);
|
|
226
|
+
}
|
|
227
|
+
else {
|
|
228
|
+
const define = easingDefines[name];
|
|
229
|
+
if (!define) {
|
|
230
|
+
throw new Error(`${name} 缓冲函数未定义`);
|
|
231
|
+
}
|
|
232
|
+
fn = bezier(...define);
|
|
233
|
+
}
|
|
234
|
+
return (input) => fn(Math.max(0, Math.min(input, 1)));
|
|
235
|
+
}
|
|
59
236
|
|
|
60
237
|
/**
|
|
61
238
|
* 判断对象是否为纯对象
|
|
@@ -72,15 +249,6 @@
|
|
|
72
249
|
// 是否对象直接实例
|
|
73
250
|
return proto === Object.prototype;
|
|
74
251
|
};
|
|
75
|
-
/**
|
|
76
|
-
* 判断对象内是否有该静态属性
|
|
77
|
-
* @param {object} obj
|
|
78
|
-
* @param {string} key
|
|
79
|
-
* @returns {boolean}
|
|
80
|
-
*/
|
|
81
|
-
function objectHas(obj, key) {
|
|
82
|
-
return Object.prototype.hasOwnProperty.call(obj, key);
|
|
83
|
-
}
|
|
84
252
|
/**
|
|
85
253
|
* 遍历对象,返回 false 中断遍历
|
|
86
254
|
* @param {O} obj
|
|
@@ -234,23 +402,23 @@
|
|
|
234
402
|
let i = 0;
|
|
235
403
|
for (let len = keyArr.length; i < len - 1; ++i) {
|
|
236
404
|
const key = keyArr[i];
|
|
237
|
-
if (key
|
|
238
|
-
|
|
405
|
+
if (isNumber(Number(key)) && Array.isArray(tempObj)) {
|
|
406
|
+
tempObj = tempObj[key];
|
|
407
|
+
}
|
|
408
|
+
else if (isObject(tempObj) && objectHas(tempObj, key)) {
|
|
239
409
|
tempObj = tempObj[key];
|
|
240
410
|
}
|
|
241
411
|
else {
|
|
242
412
|
tempObj = undefined;
|
|
243
413
|
if (strict) {
|
|
244
|
-
throw new Error('[
|
|
414
|
+
throw new Error('[Object] objectGet path 路径不正确');
|
|
245
415
|
}
|
|
246
416
|
break;
|
|
247
417
|
}
|
|
248
418
|
}
|
|
249
419
|
return {
|
|
250
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
251
420
|
p: tempObj,
|
|
252
421
|
k: tempObj ? keyArr[i] : undefined,
|
|
253
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access,@typescript-eslint/no-unsafe-assignment
|
|
254
422
|
v: tempObj ? tempObj[keyArr[i]] : undefined
|
|
255
423
|
};
|
|
256
424
|
}
|
|
@@ -278,135 +446,6 @@
|
|
|
278
446
|
return cloneObj;
|
|
279
447
|
}
|
|
280
448
|
|
|
281
|
-
/**
|
|
282
|
-
* 判断一个对象是否为类数组
|
|
283
|
-
*
|
|
284
|
-
* @param any
|
|
285
|
-
* @returns {boolean}
|
|
286
|
-
*/
|
|
287
|
-
function arrayLike(any) {
|
|
288
|
-
if (isArray(any))
|
|
289
|
-
return true;
|
|
290
|
-
if (isString(any))
|
|
291
|
-
return true;
|
|
292
|
-
if (!isObject(any))
|
|
293
|
-
return false;
|
|
294
|
-
return objectHas(any, 'length');
|
|
295
|
-
}
|
|
296
|
-
/**
|
|
297
|
-
* 遍历数组,返回 false 中断遍历(支持continue和break操作)
|
|
298
|
-
*
|
|
299
|
-
* @param {ArrayLike<V>} array
|
|
300
|
-
* @param {(val: V, idx: number) => any} iterator 迭代函数, 返回值为true时continue, 返回值为false时break
|
|
301
|
-
* @param {boolean} reverse 是否倒序
|
|
302
|
-
* @returns {*}
|
|
303
|
-
*/
|
|
304
|
-
function arrayEach(array, iterator, reverse = false) {
|
|
305
|
-
if (reverse) {
|
|
306
|
-
for (let idx = array.length - 1; idx >= 0; idx--) {
|
|
307
|
-
const val = array[idx];
|
|
308
|
-
const re = iterator(val, idx, array);
|
|
309
|
-
if (re === false)
|
|
310
|
-
break;
|
|
311
|
-
else if (re === true)
|
|
312
|
-
continue;
|
|
313
|
-
}
|
|
314
|
-
}
|
|
315
|
-
else {
|
|
316
|
-
for (let idx = 0; idx < array.length; idx++) {
|
|
317
|
-
const val = array[idx];
|
|
318
|
-
const re = iterator(val, idx, array);
|
|
319
|
-
if (re === false)
|
|
320
|
-
break;
|
|
321
|
-
else if (re === true)
|
|
322
|
-
continue;
|
|
323
|
-
}
|
|
324
|
-
}
|
|
325
|
-
}
|
|
326
|
-
/**
|
|
327
|
-
* 异步遍历数组,返回 false 中断遍历
|
|
328
|
-
* @param {ArrayLike<V>} array 数组
|
|
329
|
-
* @param {(val: V, idx: number) => Promise<any>} iterator 支持Promise类型的回调函数
|
|
330
|
-
* @param {boolean} reverse 是否反向遍历
|
|
331
|
-
*/
|
|
332
|
-
async function arrayEachAsync(array, iterator, reverse = false) {
|
|
333
|
-
if (reverse) {
|
|
334
|
-
for (let idx = array.length - 1; idx >= 0; idx--) {
|
|
335
|
-
const val = array[idx];
|
|
336
|
-
if ((await iterator(val, idx)) === false)
|
|
337
|
-
break;
|
|
338
|
-
}
|
|
339
|
-
}
|
|
340
|
-
else {
|
|
341
|
-
for (let idx = 0; idx < array.length; idx++) {
|
|
342
|
-
const val = array[idx];
|
|
343
|
-
if ((await iterator(val, idx)) === false)
|
|
344
|
-
break;
|
|
345
|
-
}
|
|
346
|
-
}
|
|
347
|
-
}
|
|
348
|
-
/**
|
|
349
|
-
* 插入到目标位置之前
|
|
350
|
-
* @param {AnyArray} array
|
|
351
|
-
* @param {number} start
|
|
352
|
-
* @param {number} to
|
|
353
|
-
* @returns {*}
|
|
354
|
-
*/
|
|
355
|
-
function arrayInsertBefore(array, start, to) {
|
|
356
|
-
if (start === to || start + 1 === to)
|
|
357
|
-
return;
|
|
358
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
359
|
-
const [source] = array.splice(start, 1);
|
|
360
|
-
const insertIndex = to < start ? to : to - 1;
|
|
361
|
-
array.splice(insertIndex, 0, source);
|
|
362
|
-
}
|
|
363
|
-
/**
|
|
364
|
-
* 数组删除指定项目
|
|
365
|
-
* @param {V[]} array
|
|
366
|
-
* @param {(val: V, idx: number) => boolean} expect
|
|
367
|
-
* @returns {V[]}
|
|
368
|
-
*/
|
|
369
|
-
function arrayRemove(array, expect) {
|
|
370
|
-
const indexes = [];
|
|
371
|
-
// 这里重命名一下:是为了杜绝 jest 里的 expect 与之产生检查错误
|
|
372
|
-
// eslint 的 jest 语法检查是遇到 expect 函数就以为是单元测试
|
|
373
|
-
const _expect = expect;
|
|
374
|
-
arrayEach(array, (val, idx) => {
|
|
375
|
-
if (_expect(val, idx))
|
|
376
|
-
indexes.push(idx);
|
|
377
|
-
});
|
|
378
|
-
indexes.forEach((val, idx) => array.splice(val - idx, 1));
|
|
379
|
-
return array;
|
|
380
|
-
}
|
|
381
|
-
|
|
382
|
-
// @ref https://cubic-bezier.com/
|
|
383
|
-
const easingDefines = {
|
|
384
|
-
linear: [0, 0, 1, 1],
|
|
385
|
-
ease: [0.25, 0.1, 0.25, 1],
|
|
386
|
-
'ease-in': [0.42, 0, 1, 1],
|
|
387
|
-
'ease-out': [0, 0, 0.58, 1],
|
|
388
|
-
'ease-in-out': [0.42, 0, 0.58, 1]
|
|
389
|
-
};
|
|
390
|
-
/**
|
|
391
|
-
* 缓冲函数化,用于 js 计算缓冲进度
|
|
392
|
-
* @param {EasingNameOrDefine} [name=linear]
|
|
393
|
-
* @returns {EasingFunction}
|
|
394
|
-
*/
|
|
395
|
-
function easingFunctional(name) {
|
|
396
|
-
let fn;
|
|
397
|
-
if (isArray(name)) {
|
|
398
|
-
fn = bezier(...name);
|
|
399
|
-
}
|
|
400
|
-
else {
|
|
401
|
-
const define = easingDefines[name];
|
|
402
|
-
if (!define) {
|
|
403
|
-
throw new Error(`${name} 缓冲函数未定义`);
|
|
404
|
-
}
|
|
405
|
-
fn = bezier(...define);
|
|
406
|
-
}
|
|
407
|
-
return (input) => fn(Math.max(0, Math.min(input, 1)));
|
|
408
|
-
}
|
|
409
|
-
|
|
410
449
|
/**
|
|
411
450
|
* 将字符串转换为驼峰格式
|
|
412
451
|
* @param {string} string
|
|
@@ -526,7 +565,7 @@
|
|
|
526
565
|
/**
|
|
527
566
|
* 解析URL查询参数
|
|
528
567
|
* @param {string} searchStr
|
|
529
|
-
* @
|
|
568
|
+
* @returns {Record<string, string | string[]>}
|
|
530
569
|
*/
|
|
531
570
|
function parseQueryParams(searchStr = location.search) {
|
|
532
571
|
const queryObj = {};
|
|
@@ -913,7 +952,6 @@
|
|
|
913
952
|
* - DD:日
|
|
914
953
|
* - dd: 日
|
|
915
954
|
* - HH:时(24 小时制)
|
|
916
|
-
* - hh:时(12 小时制)
|
|
917
955
|
* - mm:分
|
|
918
956
|
* - ss:秒
|
|
919
957
|
* - SSS:毫秒
|
|
@@ -1331,7 +1369,7 @@
|
|
|
1331
1369
|
/**
|
|
1332
1370
|
* 字符串编码成Base64 (适用于任何环境,包括小程序)
|
|
1333
1371
|
* @param {string} string
|
|
1334
|
-
* @
|
|
1372
|
+
* @returns {string}
|
|
1335
1373
|
*/
|
|
1336
1374
|
function weBtoa(string) {
|
|
1337
1375
|
// 同window.btoa: 字符串编码成Base64
|
|
@@ -1353,7 +1391,7 @@
|
|
|
1353
1391
|
/**
|
|
1354
1392
|
* Base64解码为原始字符串(适用于任何环境,包括小程序)
|
|
1355
1393
|
* @param {string} string
|
|
1356
|
-
* @
|
|
1394
|
+
* @returns {string}
|
|
1357
1395
|
*/
|
|
1358
1396
|
function weAtob(string) {
|
|
1359
1397
|
// 同window.atob: Base64解码为原始字符串
|
|
@@ -1764,7 +1802,7 @@
|
|
|
1764
1802
|
throw new SyntaxError('当前环境下无法设置全局属性');
|
|
1765
1803
|
}
|
|
1766
1804
|
/**
|
|
1767
|
-
*
|
|
1805
|
+
* 获取全局变量
|
|
1768
1806
|
* @param {string | number | symbol} key
|
|
1769
1807
|
* @param val
|
|
1770
1808
|
*/
|
|
@@ -1852,7 +1890,7 @@
|
|
|
1852
1890
|
const supportBigInt = typeof BigInt !== 'undefined';
|
|
1853
1891
|
const jsbi = () => getGlobal('JSBI');
|
|
1854
1892
|
const toBigInt = (n) => (supportBigInt ? BigInt(n) : jsbi().BigInt(n));
|
|
1855
|
-
const divide = (x, y) => (supportBigInt ? x / y : jsbi().divide(x, y));
|
|
1893
|
+
const divide$1 = (x, y) => (supportBigInt ? x / y : jsbi().divide(x, y));
|
|
1856
1894
|
const remainder = (x, y) => (supportBigInt ? x % y : jsbi().remainder(x, y));
|
|
1857
1895
|
/**
|
|
1858
1896
|
* 将十进制转换成任意进制
|
|
@@ -1874,7 +1912,7 @@
|
|
|
1874
1912
|
const bigLength = toBigInt(length);
|
|
1875
1913
|
const execute = () => {
|
|
1876
1914
|
const y = Number(remainder(bigInt, bigLength));
|
|
1877
|
-
bigInt = divide(bigInt, bigLength);
|
|
1915
|
+
bigInt = divide$1(bigInt, bigLength);
|
|
1878
1916
|
ret.unshift(hexPool[y]);
|
|
1879
1917
|
if (bigInt > 0) {
|
|
1880
1918
|
execute();
|
|
@@ -2364,7 +2402,7 @@
|
|
|
2364
2402
|
* 树形结构转扁平化
|
|
2365
2403
|
* @param {any} treeList
|
|
2366
2404
|
* @param {IFieldOptions} options
|
|
2367
|
-
* @
|
|
2405
|
+
* @returns {*}
|
|
2368
2406
|
*/
|
|
2369
2407
|
function flatTree(treeList, options = defaultFieldOptions) {
|
|
2370
2408
|
const { childField, keyField, pidField } = options;
|
|
@@ -2390,7 +2428,7 @@
|
|
|
2390
2428
|
* @param {any[]} nodes
|
|
2391
2429
|
* @param {string} query
|
|
2392
2430
|
* @param {ISearchTreeOpts} options
|
|
2393
|
-
* @
|
|
2431
|
+
* @returns {any[]}
|
|
2394
2432
|
*/
|
|
2395
2433
|
function fuzzySearchTree(nodes, query, options = defaultSearchTreeOptions) {
|
|
2396
2434
|
const result = [];
|
|
@@ -2433,12 +2471,368 @@
|
|
|
2433
2471
|
return result;
|
|
2434
2472
|
}
|
|
2435
2473
|
|
|
2474
|
+
/**
|
|
2475
|
+
* 数值安全乘法
|
|
2476
|
+
* @param arg1 数值1
|
|
2477
|
+
* @param arg2 数值2
|
|
2478
|
+
*/
|
|
2479
|
+
const multiply = (arg1, arg2) => {
|
|
2480
|
+
let m = 0;
|
|
2481
|
+
const s1 = arg1.toString();
|
|
2482
|
+
const s2 = arg2.toString();
|
|
2483
|
+
if (s1.split('.')[1] !== undefined)
|
|
2484
|
+
m += s1.split('.')[1].length;
|
|
2485
|
+
if (s2.split('.')[1] !== undefined)
|
|
2486
|
+
m += s2.split('.')[1].length;
|
|
2487
|
+
return (Number(s1.replace('.', '')) * Number(s2.replace('.', ''))) / Math.pow(10, m);
|
|
2488
|
+
};
|
|
2489
|
+
/**
|
|
2490
|
+
* 数值安全加法
|
|
2491
|
+
* @param arg1 数值1
|
|
2492
|
+
* @param arg2 数值2
|
|
2493
|
+
*/
|
|
2494
|
+
const add = (arg1, arg2) => {
|
|
2495
|
+
let r1 = 0;
|
|
2496
|
+
let r2 = 0;
|
|
2497
|
+
let m = 0;
|
|
2498
|
+
try {
|
|
2499
|
+
r1 = arg1.toString().split('.')[1].length;
|
|
2500
|
+
}
|
|
2501
|
+
catch (e) {
|
|
2502
|
+
r1 = 0;
|
|
2503
|
+
}
|
|
2504
|
+
try {
|
|
2505
|
+
r2 = arg2.toString().split('.')[1].length;
|
|
2506
|
+
}
|
|
2507
|
+
catch (e) {
|
|
2508
|
+
r2 = 0;
|
|
2509
|
+
}
|
|
2510
|
+
m = 10 ** Math.max(r1, r2);
|
|
2511
|
+
return (multiply(arg1, m) + multiply(arg2, m)) / m;
|
|
2512
|
+
};
|
|
2513
|
+
/**
|
|
2514
|
+
* 数值安全减法
|
|
2515
|
+
* @param arg1 数值1
|
|
2516
|
+
* @param arg2 数值2
|
|
2517
|
+
*/
|
|
2518
|
+
const subtract = (arg1, arg2) => add(arg1, -arg2);
|
|
2519
|
+
/**
|
|
2520
|
+
* 数值安全除法
|
|
2521
|
+
* @param arg1 数值1
|
|
2522
|
+
* @param arg2 数值2
|
|
2523
|
+
*/
|
|
2524
|
+
const divide = (arg1, arg2) => {
|
|
2525
|
+
let t1 = 0;
|
|
2526
|
+
let t2 = 0;
|
|
2527
|
+
let r1 = 0;
|
|
2528
|
+
let r2 = 0;
|
|
2529
|
+
if (arg1.toString().split('.')[1] !== undefined)
|
|
2530
|
+
t1 = arg1.toString().split('.')[1].length;
|
|
2531
|
+
if (arg2.toString().split('.')[1] !== undefined)
|
|
2532
|
+
t2 = arg2.toString().split('.')[1].length;
|
|
2533
|
+
r1 = Number(arg1.toString().replace('.', ''));
|
|
2534
|
+
r2 = Number(arg2.toString().replace('.', ''));
|
|
2535
|
+
return (r1 / r2) * Math.pow(10, t2 - t1);
|
|
2536
|
+
};
|
|
2537
|
+
/**
|
|
2538
|
+
* Correct the given number to specifying significant digits.
|
|
2539
|
+
*
|
|
2540
|
+
* @param num The input number
|
|
2541
|
+
* @param precision An integer specifying the number of significant digits
|
|
2542
|
+
*
|
|
2543
|
+
* @example strip(0.09999999999999998) === 0.1 // true
|
|
2544
|
+
*/
|
|
2545
|
+
function strip(num, precision = 15) {
|
|
2546
|
+
return +parseFloat(Number(num).toPrecision(precision));
|
|
2547
|
+
}
|
|
2548
|
+
|
|
2549
|
+
function stringToUint8Array(str) {
|
|
2550
|
+
const utf8 = encodeURIComponent(str); // 将字符串转换为 UTF-8 编码
|
|
2551
|
+
const uint8Array = new Uint8Array(utf8.length); // 创建 Uint8Array
|
|
2552
|
+
for (let i = 0; i < utf8.length; i++) {
|
|
2553
|
+
uint8Array[i] = utf8.charCodeAt(i); // 填充 Uint8Array
|
|
2554
|
+
}
|
|
2555
|
+
return uint8Array;
|
|
2556
|
+
}
|
|
2557
|
+
function uint8ArrayToString(uint8Array) {
|
|
2558
|
+
const utf8 = String.fromCharCode.apply(null, uint8Array); // 将 Uint8Array 转为字符串
|
|
2559
|
+
return decodeURIComponent(utf8); // 将 UTF-8 字符串解码回正常字符串
|
|
2560
|
+
}
|
|
2561
|
+
/**
|
|
2562
|
+
* 将base64编码的字符串转换为原始字符串,包括对中文内容的处理(高性能,且支持Web、Node、小程序等任意平台)
|
|
2563
|
+
* @param base64 base64编码的字符串
|
|
2564
|
+
* @returns 原始字符串,包括中文内容
|
|
2565
|
+
*/
|
|
2566
|
+
function decodeFromBase64(base64) {
|
|
2567
|
+
const binaryString = !isNullOrUnDef(getGlobal('atob')) ? getGlobal('atob')(base64) : weAtob(base64);
|
|
2568
|
+
const len = binaryString.length;
|
|
2569
|
+
const bytes = new Uint8Array(len);
|
|
2570
|
+
for (let i = 0; i < len; i++) {
|
|
2571
|
+
bytes[i] = binaryString.charCodeAt(i);
|
|
2572
|
+
}
|
|
2573
|
+
// 使用TextDecoder将Uint8Array转换为原始字符串,包括中文内容
|
|
2574
|
+
return !isNullOrUnDef(getGlobal('TextDecoder'))
|
|
2575
|
+
? new (getGlobal('TextDecoder'))('utf-8').decode(bytes)
|
|
2576
|
+
: uint8ArrayToString(bytes);
|
|
2577
|
+
}
|
|
2578
|
+
/**
|
|
2579
|
+
* 将原始字符串,包括中文内容,转换为base64编码的字符串(高性能,且支持Web、Node、小程序等任意平台)
|
|
2580
|
+
* @param rawStr 原始字符串,包括中文内容
|
|
2581
|
+
* @returns base64编码的字符串
|
|
2582
|
+
*/
|
|
2583
|
+
function encodeToBase64(rawStr) {
|
|
2584
|
+
const utf8Array = !isNullOrUnDef(getGlobal('TextEncoder'))
|
|
2585
|
+
? new (getGlobal('TextEncoder'))().encode(rawStr)
|
|
2586
|
+
: stringToUint8Array(rawStr);
|
|
2587
|
+
// 将 Uint8Array 转换为二进制字符串
|
|
2588
|
+
let binaryString = '';
|
|
2589
|
+
const len = utf8Array.length;
|
|
2590
|
+
for (let i = 0; i < len; i++) {
|
|
2591
|
+
binaryString += String.fromCharCode(utf8Array[i]);
|
|
2592
|
+
}
|
|
2593
|
+
// 将二进制字符串转换为base64编码的字符串
|
|
2594
|
+
return !isNullOrUnDef(getGlobal('btoa')) ? getGlobal('btoa')(binaryString) : weBtoa(binaryString);
|
|
2595
|
+
}
|
|
2596
|
+
|
|
2597
|
+
// 邮箱
|
|
2598
|
+
const EMAIL_REGEX = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/;
|
|
2599
|
+
/**
|
|
2600
|
+
* 判断字符串是否为邮箱格式,不对邮箱真实性做验证,如域名是否正确等
|
|
2601
|
+
* @param {string} value
|
|
2602
|
+
* @returns {boolean}
|
|
2603
|
+
*/
|
|
2604
|
+
const isEmail = (value) => EMAIL_REGEX.test(value);
|
|
2605
|
+
// 手机号码 (中国大陆)
|
|
2606
|
+
// reference: https://www.runoob.com/regexp/regexp-syntax.html (?: 是非捕获元之一)
|
|
2607
|
+
const PHONE_REGEX = /^(?:(?:\+|00)86)?1\d{10}$/;
|
|
2608
|
+
/**
|
|
2609
|
+
* 判断字符串是否为宽松手机格式,即首位为 1 的 11 位数字都属于手机号
|
|
2610
|
+
* @param {string} value
|
|
2611
|
+
* @returns {boolean}
|
|
2612
|
+
*/
|
|
2613
|
+
const isPhone = (value) => PHONE_REGEX.test(value);
|
|
2614
|
+
// 身份证号码
|
|
2615
|
+
// http://www.stats.gov.cn/tjsj/tjbz/xzqhdm/
|
|
2616
|
+
// ["北京市", "天津市", "河北省", "山西省", "内蒙古自治区",
|
|
2617
|
+
// "辽宁省", "吉林省", "黑龙江省",
|
|
2618
|
+
// "上海市", "江苏省", "浙江省", "安徽省", "福建省", "江西省", "山东省",
|
|
2619
|
+
// "河南省", "湖北省", "湖南省", "广东省", "广西壮族自治区", "海南省",
|
|
2620
|
+
// "重庆市", "四川省", "贵州省", "云南省", "西藏自治区",
|
|
2621
|
+
// "陕西省", "甘肃省", "青海省","宁夏回族自治区", "新疆维吾尔自治区",
|
|
2622
|
+
// "台湾省",
|
|
2623
|
+
// "香港特别行政区", "澳门特别行政区"]
|
|
2624
|
+
// ["11", "12", "13", "14", "15",
|
|
2625
|
+
// "21", "22", "23",
|
|
2626
|
+
// "31", "32", "33", "34", "35", "36", "37",
|
|
2627
|
+
// "41", "42", "43", "44", "45", "46",
|
|
2628
|
+
// "50", "51", "52", "53", "54",
|
|
2629
|
+
// "61", "62", "63", "64", "65",
|
|
2630
|
+
// "71",
|
|
2631
|
+
// "81", "82"]
|
|
2632
|
+
// 91 国外
|
|
2633
|
+
const IDNO_RE = /^(1[1-5]|2[1-3]|3[1-7]|4[1-6]|5[0-4]|6[1-5]|7[1]|8[1-2]|9[1])\d{4}(18|19|20)\d{2}[01]\d[0123]\d{4}[\dxX]$/;
|
|
2634
|
+
/**
|
|
2635
|
+
* 判断字符串是否为身份证号码格式
|
|
2636
|
+
* @param {string} value
|
|
2637
|
+
* @returns {boolean}
|
|
2638
|
+
*/
|
|
2639
|
+
const isIdNo = (value) => {
|
|
2640
|
+
const isSameFormat = IDNO_RE.test(value);
|
|
2641
|
+
if (!isSameFormat)
|
|
2642
|
+
return false;
|
|
2643
|
+
const year = Number(value.slice(6, 10));
|
|
2644
|
+
const month = Number(value.slice(10, 12));
|
|
2645
|
+
const date = Number(value.slice(12, 14));
|
|
2646
|
+
const d = new Date(year, month - 1, date);
|
|
2647
|
+
const isSameDate = d.getFullYear() === year && d.getMonth() + 1 === month && d.getDate() === date;
|
|
2648
|
+
if (!isSameDate)
|
|
2649
|
+
return false;
|
|
2650
|
+
// 将身份证号码前面的17位数分别乘以不同的系数;
|
|
2651
|
+
// 从第一位到第十七位的系数分别为:7-9-10-5-8-4-2-1-6-3-7-9-10-5-8-4-2
|
|
2652
|
+
// 将这17位数字和系数相乘的结果相加;
|
|
2653
|
+
// 用加出来和除以11,看余数是多少;
|
|
2654
|
+
// 余数只可能有0-1-2-3-4-5-6-7-8-9-10这11个数字;
|
|
2655
|
+
// 其分别对应的最后一位身份证的号码为1-0-X-9-8-7-6-5-4-3-2
|
|
2656
|
+
// 通过上面得知如果余数是2,就会在身份证的第18位数字上出现罗马数字的Ⅹ。如果余数是10,身份证的最后一位号码就是2。
|
|
2657
|
+
const coefficientList = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2];
|
|
2658
|
+
const residueList = ['1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2'];
|
|
2659
|
+
let sum = 0;
|
|
2660
|
+
for (let start = 0; start < 17; start++) {
|
|
2661
|
+
sum += Number(value.slice(start, start + 1)) * coefficientList[start];
|
|
2662
|
+
}
|
|
2663
|
+
return residueList[sum % 11] === value.slice(-1);
|
|
2664
|
+
};
|
|
2665
|
+
const URL_REGEX = /^(https?|ftp):\/\/([^\s/$.?#].[^\s]*)$/i;
|
|
2666
|
+
const HTTP_URL_REGEX = /^https?:\/\/([^\s/$.?#].[^\s]*)$/i;
|
|
2667
|
+
/**
|
|
2668
|
+
* 判断字符串是否为 url 格式,支持 http、https、ftp 协议,支持域名或者 ipV4
|
|
2669
|
+
* @param {string} value
|
|
2670
|
+
* @returns {boolean}
|
|
2671
|
+
*/
|
|
2672
|
+
const isUrl = (url, includeFtp = false) => {
|
|
2673
|
+
const regex = includeFtp ? URL_REGEX : HTTP_URL_REGEX;
|
|
2674
|
+
return regex.test(url);
|
|
2675
|
+
};
|
|
2676
|
+
// ipv4
|
|
2677
|
+
const IPV4_REGEX = /^(?:(?:\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.){3}(?:\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])$/;
|
|
2678
|
+
// ipv6
|
|
2679
|
+
const IPV6_REGEX = /^(([\da-fA-F]{1,4}:){7}[\da-fA-F]{1,4}|([\da-fA-F]{1,4}:){1,7}:|([\da-fA-F]{1,4}:){1,6}:[\da-fA-F]{1,4}|([\da-fA-F]{1,4}:){1,5}(:[\da-fA-F]{1,4}){1,2}|([\da-fA-F]{1,4}:){1,4}(:[\da-fA-F]{1,4}){1,3}|([\da-fA-F]{1,4}:){1,3}(:[\da-fA-F]{1,4}){1,4}|([\da-fA-F]{1,4}:){1,2}(:[\da-fA-F]{1,4}){1,5}|[\da-fA-F]{1,4}:((:[\da-fA-F]{1,4}){1,6})|:((:[\da-fA-F]{1,4}){1,7}|:)|fe80:(:[\da-fA-F]{0,4}){0,4}%[\da-zA-Z]+|::(ffff(:0{1,4})?:)?((25[0-5]|(2[0-4]|1?\d)?\d)\.){3}(25[0-5]|(2[0-4]|1?\d)?\d)|([\da-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1?\d)?\d)\.){3}(25[0-5]|(2[0-4]|1?\d)?\d))$/i;
|
|
2680
|
+
/**
|
|
2681
|
+
* 判断字符串是否为 IPV4 格式,不对 ip 真实性做验证
|
|
2682
|
+
* @param {string} value
|
|
2683
|
+
* @returns {boolean}
|
|
2684
|
+
*/
|
|
2685
|
+
const isIpV4 = (value) => IPV4_REGEX.test(value);
|
|
2686
|
+
/**
|
|
2687
|
+
* 判断字符串是否为 IPV6 格式,不对 ip 真实性做验证
|
|
2688
|
+
* @param {string} value
|
|
2689
|
+
* @returns {boolean}
|
|
2690
|
+
*/
|
|
2691
|
+
const isIpV6 = (value) => IPV6_REGEX.test(value);
|
|
2692
|
+
const INTEGER_RE = /^(-?[1-9]\d*|0)$/;
|
|
2693
|
+
/**
|
|
2694
|
+
* 判断字符串是否为整数(自然数),即 ...,-3,-2,-1,0,1,2,3,...
|
|
2695
|
+
* @param {string} value
|
|
2696
|
+
* @returns {boolean}
|
|
2697
|
+
*/
|
|
2698
|
+
const isInteger = (value) => INTEGER_RE.test(value);
|
|
2699
|
+
const FLOAT_RE = /^-?([1-9]\d*|0)\.\d*[1-9]$/;
|
|
2700
|
+
/**
|
|
2701
|
+
* 判断字符串是否为浮点数,即必须有小数点的有理数
|
|
2702
|
+
* @param {string} value
|
|
2703
|
+
* @returns {boolean}
|
|
2704
|
+
*/
|
|
2705
|
+
const isFloat = (value) => FLOAT_RE.test(value);
|
|
2706
|
+
/**
|
|
2707
|
+
* 判断字符串是否为正确数值,包括整数和浮点数
|
|
2708
|
+
* @param {string} value
|
|
2709
|
+
* @returns {boolean}
|
|
2710
|
+
*/
|
|
2711
|
+
const isNumerical = (value) => isInteger(value) || isFloat(value);
|
|
2712
|
+
const DIGIT_RE = /^\d+$/;
|
|
2713
|
+
/**
|
|
2714
|
+
* 判断字符串是否为数字,例如六位数字短信验证码(093031)
|
|
2715
|
+
* @param {string} value
|
|
2716
|
+
* @returns {boolean}
|
|
2717
|
+
*/
|
|
2718
|
+
const isDigit = (value) => DIGIT_RE.test(value);
|
|
2719
|
+
|
|
2720
|
+
/**
|
|
2721
|
+
* 去除字符串中重复字符
|
|
2722
|
+
* @param {string} str
|
|
2723
|
+
* @returns string
|
|
2724
|
+
* @example
|
|
2725
|
+
*
|
|
2726
|
+
* uniqueSymbol('1a1bac');
|
|
2727
|
+
* // => '1abc'
|
|
2728
|
+
*/
|
|
2729
|
+
function uniqueSymbol(str) {
|
|
2730
|
+
return [...new Set(str.trim().split(''))].join('');
|
|
2731
|
+
}
|
|
2732
|
+
/**
|
|
2733
|
+
* 转义所有特殊字符
|
|
2734
|
+
* @param {string} str 原字符串
|
|
2735
|
+
* reference: https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Guide/Regular_expressions
|
|
2736
|
+
* @returns string
|
|
2737
|
+
*/
|
|
2738
|
+
function escapeRegExp(str) {
|
|
2739
|
+
return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); //$&表示整个被匹配的字符串
|
|
2740
|
+
}
|
|
2741
|
+
/**
|
|
2742
|
+
* 根据左右匹配符号生产解析变量(自动删除变量内的空白)
|
|
2743
|
+
* @param {string} leftMatchSymbol
|
|
2744
|
+
* @param {string} rightMatchSymbol
|
|
2745
|
+
* @returns RegExp
|
|
2746
|
+
*/
|
|
2747
|
+
function parseVariableRegExp(leftMatchSymbol, rightMatchSymbol) {
|
|
2748
|
+
return new RegExp(`${escapeRegExp(leftMatchSymbol.trim())}\\s*([^${escapeRegExp(uniqueSymbol(leftMatchSymbol))}${escapeRegExp(uniqueSymbol(rightMatchSymbol))}\\s]*)\\s*${rightMatchSymbol.trim()}`, 'g');
|
|
2749
|
+
}
|
|
2750
|
+
/**
|
|
2751
|
+
* 解析字符串的插值变量
|
|
2752
|
+
* @param {string} str 字符串
|
|
2753
|
+
* @param {string} leftMatchSymbol 变量左侧匹配符号,默认:{
|
|
2754
|
+
* @param {string} rightMatchSymbol 变量右侧匹配符号,默认:}
|
|
2755
|
+
* @returns string[]
|
|
2756
|
+
* @example
|
|
2757
|
+
*
|
|
2758
|
+
* default match symbol {} same as /{\s*([^{}\s]*)\s*}/g
|
|
2759
|
+
*/
|
|
2760
|
+
function parseVarFromString(str, leftMatchSymbol = '{', rightMatchSymbol = '}') {
|
|
2761
|
+
return Array.from(str.matchAll(parseVariableRegExp(leftMatchSymbol, rightMatchSymbol))).map(el => el?.[1]);
|
|
2762
|
+
}
|
|
2763
|
+
/**
|
|
2764
|
+
* 替换字符串中的插值变量
|
|
2765
|
+
* @param {string} sourceStr
|
|
2766
|
+
* @param {Record<string, any>} targetObj
|
|
2767
|
+
* @param {string} leftMatchSymbol 变量左侧匹配符号,默认:{
|
|
2768
|
+
* @param {string} rightMatchSymbol 变量右侧匹配符号,默认:}
|
|
2769
|
+
* @returns string
|
|
2770
|
+
*/
|
|
2771
|
+
function replaceVarFromString(sourceStr, targetObj, leftMatchSymbol = '{', rightMatchSymbol = '}') {
|
|
2772
|
+
return sourceStr.replace(new RegExp(parseVariableRegExp(leftMatchSymbol, rightMatchSymbol)), function (m, p1) {
|
|
2773
|
+
return objectHas(targetObj, p1) ? targetObj[p1] : m;
|
|
2774
|
+
});
|
|
2775
|
+
}
|
|
2776
|
+
/**
|
|
2777
|
+
* 在指定作用域中执行代码
|
|
2778
|
+
* @param {string} code 要执行的代码(需包含 return 语句或表达式)
|
|
2779
|
+
* @param {Object} scope 作用域对象(键值对形式的变量环境)
|
|
2780
|
+
* @returns 代码执行结果
|
|
2781
|
+
*
|
|
2782
|
+
* @example
|
|
2783
|
+
* // 测试用例 1: 基本变量访问
|
|
2784
|
+
* executeInScope("return a + b;", { a: 1, b: 2 });
|
|
2785
|
+
* // 3
|
|
2786
|
+
*
|
|
2787
|
+
* // 测试用例 2: 支持复杂表达式和运算
|
|
2788
|
+
* executeInScope(
|
|
2789
|
+
* "return Array.from({ length: 3 }, (_, i) => base + i);",
|
|
2790
|
+
* { base: 100 }
|
|
2791
|
+
* );
|
|
2792
|
+
* // [100, 101, 102]
|
|
2793
|
+
*
|
|
2794
|
+
* // 支持外传函数作用域执行
|
|
2795
|
+
* const scope = {
|
|
2796
|
+
* $: {
|
|
2797
|
+
* fun: {
|
|
2798
|
+
* time: {
|
|
2799
|
+
* now: function () {
|
|
2800
|
+
* return new Date();
|
|
2801
|
+
* },
|
|
2802
|
+
* },
|
|
2803
|
+
* },
|
|
2804
|
+
* },
|
|
2805
|
+
* };
|
|
2806
|
+
* executeInScope("return $.fun.time.now()", scope)
|
|
2807
|
+
*/
|
|
2808
|
+
function executeInScope(code, scope = {}) {
|
|
2809
|
+
// 提取作用域对象的键和值
|
|
2810
|
+
const keys = Object.keys(scope);
|
|
2811
|
+
const values = keys.map(key => scope[key]);
|
|
2812
|
+
try {
|
|
2813
|
+
// 动态创建函数,将作用域的键作为参数,代码作为函数体
|
|
2814
|
+
const func = new Function(...keys, `return (() => { ${code} })()`);
|
|
2815
|
+
// 调用函数并传入作用域的值
|
|
2816
|
+
return func(...values);
|
|
2817
|
+
}
|
|
2818
|
+
catch (error) {
|
|
2819
|
+
throw new Error(`代码执行失败: ${error.message}`);
|
|
2820
|
+
}
|
|
2821
|
+
}
|
|
2822
|
+
|
|
2823
|
+
exports.EMAIL_REGEX = EMAIL_REGEX;
|
|
2436
2824
|
exports.HEX_POOL = HEX_POOL;
|
|
2825
|
+
exports.HTTP_URL_REGEX = HTTP_URL_REGEX;
|
|
2826
|
+
exports.IPV4_REGEX = IPV4_REGEX;
|
|
2827
|
+
exports.IPV6_REGEX = IPV6_REGEX;
|
|
2828
|
+
exports.PHONE_REGEX = PHONE_REGEX;
|
|
2437
2829
|
exports.STRING_ARABIC_NUMERALS = STRING_ARABIC_NUMERALS;
|
|
2438
2830
|
exports.STRING_LOWERCASE_ALPHA = STRING_LOWERCASE_ALPHA;
|
|
2439
2831
|
exports.STRING_POOL = STRING_POOL;
|
|
2440
2832
|
exports.STRING_UPPERCASE_ALPHA = STRING_UPPERCASE_ALPHA;
|
|
2441
2833
|
exports.UNIQUE_NUMBER_SAFE_LENGTH = UNIQUE_NUMBER_SAFE_LENGTH;
|
|
2834
|
+
exports.URL_REGEX = URL_REGEX;
|
|
2835
|
+
exports.add = add;
|
|
2442
2836
|
exports.addClass = addClass;
|
|
2443
2837
|
exports.arrayEach = arrayEach;
|
|
2444
2838
|
exports.arrayEachAsync = arrayEachAsync;
|
|
@@ -2461,10 +2855,15 @@
|
|
|
2461
2855
|
exports.dateToEnd = dateToEnd;
|
|
2462
2856
|
exports.dateToStart = dateToStart;
|
|
2463
2857
|
exports.debounce = debounce;
|
|
2858
|
+
exports.decodeFromBase64 = decodeFromBase64;
|
|
2859
|
+
exports.divide = divide;
|
|
2464
2860
|
exports.downloadBlob = downloadBlob;
|
|
2465
2861
|
exports.downloadData = downloadData;
|
|
2466
2862
|
exports.downloadHref = downloadHref;
|
|
2467
2863
|
exports.downloadURL = downloadURL;
|
|
2864
|
+
exports.encodeToBase64 = encodeToBase64;
|
|
2865
|
+
exports.escapeRegExp = escapeRegExp;
|
|
2866
|
+
exports.executeInScope = executeInScope;
|
|
2468
2867
|
exports.flatTree = flatTree;
|
|
2469
2868
|
exports.forEachDeep = forEachDeep;
|
|
2470
2869
|
exports.forEachMap = forEachMap;
|
|
@@ -2482,22 +2881,34 @@
|
|
|
2482
2881
|
exports.isBigInt = isBigInt;
|
|
2483
2882
|
exports.isBoolean = isBoolean;
|
|
2484
2883
|
exports.isDate = isDate;
|
|
2884
|
+
exports.isDigit = isDigit;
|
|
2485
2885
|
exports.isDomReady = isDomReady;
|
|
2886
|
+
exports.isEmail = isEmail;
|
|
2887
|
+
exports.isEmpty = isEmpty;
|
|
2486
2888
|
exports.isError = isError;
|
|
2889
|
+
exports.isFloat = isFloat;
|
|
2487
2890
|
exports.isFunction = isFunction;
|
|
2891
|
+
exports.isIdNo = isIdNo;
|
|
2892
|
+
exports.isInteger = isInteger;
|
|
2893
|
+
exports.isIpV4 = isIpV4;
|
|
2894
|
+
exports.isIpV6 = isIpV6;
|
|
2488
2895
|
exports.isJsonString = isJsonString;
|
|
2489
2896
|
exports.isNaN = isNaN;
|
|
2490
2897
|
exports.isNull = isNull;
|
|
2491
2898
|
exports.isNullOrUnDef = isNullOrUnDef;
|
|
2492
2899
|
exports.isNumber = isNumber;
|
|
2900
|
+
exports.isNumerical = isNumerical;
|
|
2493
2901
|
exports.isObject = isObject;
|
|
2902
|
+
exports.isPhone = isPhone;
|
|
2494
2903
|
exports.isPlainObject = isPlainObject;
|
|
2495
2904
|
exports.isPrimitive = isPrimitive;
|
|
2496
2905
|
exports.isRegExp = isRegExp;
|
|
2497
2906
|
exports.isString = isString;
|
|
2498
2907
|
exports.isSymbol = isSymbol;
|
|
2499
2908
|
exports.isUndefined = isUndefined;
|
|
2909
|
+
exports.isUrl = isUrl;
|
|
2500
2910
|
exports.isValidDate = isValidDate;
|
|
2911
|
+
exports.multiply = multiply;
|
|
2501
2912
|
exports.numberAbbr = numberAbbr;
|
|
2502
2913
|
exports.numberToHex = numberToHex;
|
|
2503
2914
|
exports.objectAssign = objectAssign;
|
|
@@ -2513,6 +2924,7 @@
|
|
|
2513
2924
|
exports.onDomReady = onDomReady;
|
|
2514
2925
|
exports.once = once;
|
|
2515
2926
|
exports.parseQueryParams = parseQueryParams;
|
|
2927
|
+
exports.parseVarFromString = parseVarFromString;
|
|
2516
2928
|
exports.pathJoin = pathJoin;
|
|
2517
2929
|
exports.pathNormalize = pathNormalize;
|
|
2518
2930
|
exports.qsParse = qsParse;
|
|
@@ -2521,6 +2933,7 @@
|
|
|
2521
2933
|
exports.randomString = randomString;
|
|
2522
2934
|
exports.randomUuid = randomUuid;
|
|
2523
2935
|
exports.removeClass = removeClass;
|
|
2936
|
+
exports.replaceVarFromString = replaceVarFromString;
|
|
2524
2937
|
exports.searchTreeById = searchTreeById;
|
|
2525
2938
|
exports.setGlobal = setGlobal;
|
|
2526
2939
|
exports.setStyle = setStyle;
|
|
@@ -2531,12 +2944,15 @@
|
|
|
2531
2944
|
exports.stringFill = stringFill;
|
|
2532
2945
|
exports.stringFormat = stringFormat;
|
|
2533
2946
|
exports.stringKebabCase = stringKebabCase;
|
|
2947
|
+
exports.strip = strip;
|
|
2948
|
+
exports.subtract = subtract;
|
|
2534
2949
|
exports.supportCanvas = supportCanvas;
|
|
2535
2950
|
exports.throttle = throttle;
|
|
2536
2951
|
exports.tooltipEvent = tooltipEvent;
|
|
2537
2952
|
exports.typeIs = typeIs;
|
|
2538
2953
|
exports.uniqueNumber = uniqueNumber;
|
|
2539
2954
|
exports.uniqueString = uniqueString;
|
|
2955
|
+
exports.uniqueSymbol = uniqueSymbol;
|
|
2540
2956
|
exports.urlDelParams = urlDelParams;
|
|
2541
2957
|
exports.urlParse = urlParse;
|
|
2542
2958
|
exports.urlSetParams = urlSetParams;
|