@yh-kit/utils 1.15.1 → 1.17.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/dist/utils.js +401 -145
- package/dist/utils.umd.cjs +1 -1
- package/package.json +1 -1
- package/types/array/fisher-yates.d.ts +38 -0
- package/types/array/index.d.ts +11 -2
- package/types/array/orderby.d.ts +0 -12
- package/types/array/unique.d.ts +82 -2
- package/types/common/clone.d.ts +29 -0
- package/types/common/index.d.ts +4 -6
- package/types/common/type.d.ts +9 -0
package/dist/utils.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const
|
|
1
|
+
const b = {
|
|
2
2
|
/**
|
|
3
3
|
* 统计数组中某元素出现的次数:对于大型数组,手动循环的性能略优于 filter 和 reduce。
|
|
4
4
|
* @param arr 数组
|
|
@@ -25,7 +25,7 @@ const w = {
|
|
|
25
25
|
while (t !== -1);
|
|
26
26
|
return r;
|
|
27
27
|
}
|
|
28
|
-
},
|
|
28
|
+
}, A = {
|
|
29
29
|
// toEnumObj: handleArrTansferEnumObj,
|
|
30
30
|
/**
|
|
31
31
|
* 数组转枚举对象
|
|
@@ -41,7 +41,7 @@ const w = {
|
|
|
41
41
|
t[r[n]] = o;
|
|
42
42
|
}), t;
|
|
43
43
|
}
|
|
44
|
-
},
|
|
44
|
+
}, M = {
|
|
45
45
|
/**
|
|
46
46
|
* 判断某元素是否在存在于数组中(indexOf方法)
|
|
47
47
|
* @param arr 数组
|
|
@@ -107,60 +107,236 @@ const w = {
|
|
|
107
107
|
{ value: e[0], index: 0 }
|
|
108
108
|
);
|
|
109
109
|
}
|
|
110
|
-
},
|
|
110
|
+
}, E = {
|
|
111
111
|
/**
|
|
112
|
-
*
|
|
112
|
+
* 数组随机打乱-Fisher-Yates算法
|
|
113
|
+
* 要点:
|
|
114
|
+
* 1、倒叙遍历数组;
|
|
115
|
+
* 2、获取随机位置,并交换当前位置和随机位置的元素;
|
|
116
|
+
* 3、返回洗牌后的数组;
|
|
113
117
|
* @param arr 数组
|
|
114
|
-
* @
|
|
115
|
-
*
|
|
118
|
+
* @returns 随机打乱后的数组
|
|
119
|
+
*
|
|
120
|
+
* 注意,这个算法会改变原数组。如果不想改变原数组,可以先复制一份再进行操作。
|
|
121
|
+
* 时间复杂度:O(n)
|
|
122
|
+
* 空间复杂度:O(1)
|
|
116
123
|
*/
|
|
117
|
-
|
|
118
|
-
|
|
124
|
+
shuffle(e) {
|
|
125
|
+
if (!e)
|
|
126
|
+
return [];
|
|
127
|
+
const n = [...e];
|
|
128
|
+
for (let t = n.length - 1; t > 0; t--) {
|
|
129
|
+
const r = Math.floor(Math.random() * (t + 1));
|
|
130
|
+
[n[t], n[r]] = [n[r], n[t]];
|
|
131
|
+
}
|
|
132
|
+
return n;
|
|
119
133
|
},
|
|
120
134
|
/**
|
|
121
|
-
*
|
|
122
|
-
* 1. 从数组的最后一个元素开始,将其与随机位置的元素交换位置。
|
|
123
|
-
* 2. 然后,从倒数第二个元素开始,将其与随机位置的元素交换位置。
|
|
124
|
-
* 3. 以此类推,直到第一个元素。
|
|
125
|
-
* 4. 这样,数组中的元素就会被随机打乱顺序。
|
|
126
|
-
* 5. 注意,这个算法会改变原数组。如果不想改变原数组,可以先复制一份再进行操作。
|
|
127
|
-
* 6. 时间复杂度:O(n)
|
|
135
|
+
* 数组随机抽样-Fisher-Yates算法前k次迭代,再取前k个元素【洗牌开头,返回开头(更常见)】
|
|
128
136
|
* @param arr 数组
|
|
129
|
-
* @
|
|
137
|
+
* @param k 抽样次数
|
|
138
|
+
* @returns 抽样后的数组
|
|
130
139
|
*/
|
|
131
|
-
|
|
140
|
+
sample(e, n) {
|
|
141
|
+
if (!e)
|
|
142
|
+
return [];
|
|
143
|
+
if (n <= 0 || n > e.length)
|
|
144
|
+
throw new Error("抽样次数必须在1次到数组长度之间");
|
|
145
|
+
const t = [...e];
|
|
146
|
+
for (let r = 0; r < n; r++) {
|
|
147
|
+
const o = Math.floor(Math.random() * (e.length - r)) + r;
|
|
148
|
+
[t[r], t[o]] = [t[o], t[r]];
|
|
149
|
+
}
|
|
150
|
+
return t.slice(0, n);
|
|
151
|
+
},
|
|
152
|
+
/**
|
|
153
|
+
* 数组随机抽样-Fisher-Yates算法【洗牌开头,返回开头(更常见)】
|
|
154
|
+
* @param arr 数组
|
|
155
|
+
* @param k 抽样次数
|
|
156
|
+
* @returns 抽样后的数组
|
|
157
|
+
*/
|
|
158
|
+
sampleByStart(e, n) {
|
|
132
159
|
if (!e)
|
|
133
160
|
return [];
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
161
|
+
if (n <= 0 || n > e.length)
|
|
162
|
+
throw new Error("抽样次数必须在1次到数组长度之间");
|
|
163
|
+
const t = [...e];
|
|
164
|
+
for (let r = n - 1; r >= 0; r--) {
|
|
165
|
+
const o = Math.floor(Math.random() * (e.length - r)) + r;
|
|
166
|
+
[t[r], t[o]] = [t[o], t[r]];
|
|
137
167
|
}
|
|
138
|
-
return
|
|
168
|
+
return t.slice(0, n);
|
|
169
|
+
},
|
|
170
|
+
/**
|
|
171
|
+
* 数组随机抽样-Fisher-Yates算法【洗牌结尾,返回结尾(不常见)】
|
|
172
|
+
* @param arr 数组
|
|
173
|
+
* @param k 抽样次数
|
|
174
|
+
* @returns 抽样后的数组
|
|
175
|
+
*/
|
|
176
|
+
sampleByEnd(e, n) {
|
|
177
|
+
if (!e)
|
|
178
|
+
return [];
|
|
179
|
+
if (n <= 0 || n > e.length)
|
|
180
|
+
throw new Error("抽样次数必须在1次到数组长度之间");
|
|
181
|
+
const t = [...e];
|
|
182
|
+
for (let r = e.length - 1; r >= e.length - n; r--) {
|
|
183
|
+
const o = Math.floor(Math.random() * (r + 1));
|
|
184
|
+
[t[r], t[o]] = [t[o], t[r]];
|
|
185
|
+
}
|
|
186
|
+
return t.slice(e.length - n);
|
|
139
187
|
}
|
|
140
188
|
}, x = {
|
|
141
189
|
/**
|
|
142
|
-
*
|
|
190
|
+
* 数组排序-默认升序
|
|
191
|
+
* @param arr 数组
|
|
192
|
+
* @param order 排序方式:asc 升序;desc 降序
|
|
193
|
+
* @returns 排序后的数组
|
|
194
|
+
*/
|
|
195
|
+
sort(e, n = "asc") {
|
|
196
|
+
return e ? e.sort((t, r) => n === "asc" ? t > r ? 1 : -1 : t < r ? 1 : -1) : [];
|
|
197
|
+
}
|
|
198
|
+
}, B = {
|
|
199
|
+
/**
|
|
200
|
+
* 数组去重:针对简单类型数据s
|
|
201
|
+
* 性能 O(n)
|
|
143
202
|
* @param arr 数组
|
|
144
203
|
* @returns 去重后的数组
|
|
145
204
|
*/
|
|
146
205
|
uniqueBySet(e) {
|
|
147
|
-
|
|
206
|
+
if (!e)
|
|
207
|
+
throw new Error("数组不能为空");
|
|
208
|
+
const n = e;
|
|
209
|
+
return Array.from(new Set(n));
|
|
210
|
+
},
|
|
211
|
+
/**
|
|
212
|
+
* 双重循环之 filter + indexOf 数组去重:
|
|
213
|
+
* 此方法不能去重 NaN 值,也不能去重对象类型数据。
|
|
214
|
+
* 性能 O(n²),每次 indexOf 都是 O(n) 操作
|
|
215
|
+
* @param arr 数组
|
|
216
|
+
* @returns 去重后的数组
|
|
217
|
+
*/
|
|
218
|
+
uniqueByFilter(e) {
|
|
219
|
+
if (!e)
|
|
220
|
+
throw new Error("数组不能为空");
|
|
221
|
+
return e.filter((t, r, o) => r === o.indexOf(t));
|
|
222
|
+
},
|
|
223
|
+
/**
|
|
224
|
+
* 双重循环之 reduce + includes 数组去重:
|
|
225
|
+
* 适用于基本类型数据(string、number、boolean),能去重 NaN 值,但不能去重对象类型数据。
|
|
226
|
+
* 性能 O(n²),每次 includes 都是 O(n) 操作
|
|
227
|
+
* @param arr 数组
|
|
228
|
+
* @returns 去重后的数组
|
|
229
|
+
*/
|
|
230
|
+
uniqueByReduce(e) {
|
|
231
|
+
if (!e)
|
|
232
|
+
throw new Error("数组不能为空");
|
|
233
|
+
return e.reduce((t, r) => (t.includes(r) || t.push(r), t), []);
|
|
234
|
+
},
|
|
235
|
+
/**
|
|
236
|
+
* 双重循环之 forEach + includes 数组去重:
|
|
237
|
+
* 适用于基本类型数据(string、number、boolean),能去重 NaN 值,但不能去重对象类型数据。
|
|
238
|
+
* 性能 O(n²),每次 includes 都是 O(n) 操作
|
|
239
|
+
* @param arr 数组
|
|
240
|
+
* @returns 去重后的数组
|
|
241
|
+
*/
|
|
242
|
+
uniqueByIncludes(e) {
|
|
243
|
+
if (!e)
|
|
244
|
+
throw new Error("数组不能为空");
|
|
245
|
+
const n = e, t = [];
|
|
246
|
+
return n.forEach((r) => {
|
|
247
|
+
t.includes(r) || t.push(r);
|
|
248
|
+
}), t;
|
|
249
|
+
},
|
|
250
|
+
/**
|
|
251
|
+
* 双重循环之 for + includes 数组去重:
|
|
252
|
+
* 适用于基本类型数据(string、number、boolean),能去重 NaN 值,但不能去重对象类型数据。
|
|
253
|
+
* 性能 O(n²),每次 includes 都是 O(n) 操作
|
|
254
|
+
* @param arr 数组
|
|
255
|
+
* @returns 去重后的数组
|
|
256
|
+
*/
|
|
257
|
+
uniqueByFor(e) {
|
|
258
|
+
if (!e)
|
|
259
|
+
throw new Error("数组不能为空");
|
|
260
|
+
const n = e, t = [];
|
|
261
|
+
for (let r = 0; r < n.length; r++)
|
|
262
|
+
t.includes(n[r]) || t.push(n[r]);
|
|
263
|
+
return t;
|
|
264
|
+
},
|
|
265
|
+
/**
|
|
266
|
+
* Map + 根据指定键去重
|
|
267
|
+
* 适用类型 对象数组(通过指定键进行去重)
|
|
268
|
+
* 键值类型 支持 string、number、boolean、Symbol
|
|
269
|
+
* NaN 处理 ✅ 支持(Map 支持 NaN 作为键)
|
|
270
|
+
* 性能 O(n),Map 的 has 和 set 操作都是 O(1)
|
|
271
|
+
* @param arr 数组
|
|
272
|
+
* @param key 对象的键名
|
|
273
|
+
* @returns 去重后的数组
|
|
274
|
+
*/
|
|
275
|
+
uniqueByKey(e, n) {
|
|
276
|
+
if (!e || !n)
|
|
277
|
+
throw new Error("数组不能为空或键名不能为空");
|
|
278
|
+
const t = e, r = /* @__PURE__ */ new Map();
|
|
279
|
+
return t.filter((o) => r.has(o[n]) ? !1 : (r.set(o[n], !0), !0));
|
|
280
|
+
},
|
|
281
|
+
/**
|
|
282
|
+
* 通用数组去重函数 - 根据选项自动选择去重策略
|
|
283
|
+
*
|
|
284
|
+
* @template T - 数组元素类型
|
|
285
|
+
* @param {T[]} _arr - 待去重的数组
|
|
286
|
+
* @param {TUniqueOptions<T>} [options={}] - 去重选项
|
|
287
|
+
* @param {(keyof T)[]} [options.keys] - 按指定键组合去重(适用于对象数组)
|
|
288
|
+
* @param {(a: T, b: T) => boolean} [options.compareFn] - 自定义比较函数
|
|
289
|
+
* @returns {T[]} 去重后的数组
|
|
290
|
+
*
|
|
291
|
+
* @example
|
|
292
|
+
* // 基本类型数组(默认使用 Set 去重)
|
|
293
|
+
* unique([1, 2, 2, 3, 1]); // [1, 2, 3]
|
|
294
|
+
*
|
|
295
|
+
* @example
|
|
296
|
+
* // 对象数组按多个键去重
|
|
297
|
+
* const users = [{ id: 1, name: 'Alice' }, { id: 2, name: 'Bob' }, { id: 1, name: 'Alice' }];
|
|
298
|
+
* unique(users, { keys: ['id', 'name'] }); // [{ id: 1, name: 'Alice' }, { id: 2, name: 'Bob' }]
|
|
299
|
+
*
|
|
300
|
+
* @example
|
|
301
|
+
* // 使用自定义比较函数
|
|
302
|
+
* unique(arr, { compareFn: (a, b) => a.x === b.x && a.y === b.y });
|
|
303
|
+
*
|
|
304
|
+
* @throws {Error} 当输入数组为空时抛出错误
|
|
305
|
+
*/
|
|
306
|
+
unique(e, n = {}) {
|
|
307
|
+
const { keys: t, compareFn: r } = n;
|
|
308
|
+
if (!e)
|
|
309
|
+
throw new Error("数组不能为空");
|
|
310
|
+
const o = e;
|
|
311
|
+
if (!t && !r)
|
|
312
|
+
return this.uniqueBySet(o);
|
|
313
|
+
if (t) {
|
|
314
|
+
const s = /* @__PURE__ */ new Map();
|
|
315
|
+
return o.filter((c) => {
|
|
316
|
+
const l = t.map((i) => c[i]).join("|");
|
|
317
|
+
return s.has(l) ? !1 : (s.set(l, !0), !0);
|
|
318
|
+
});
|
|
319
|
+
}
|
|
320
|
+
if (r)
|
|
321
|
+
return o.filter((s, c, l) => c === l.findIndex((i) => r(s, i)));
|
|
148
322
|
}
|
|
149
|
-
},
|
|
323
|
+
}, C = {
|
|
150
324
|
// 数组转对象
|
|
151
|
-
...
|
|
325
|
+
...A,
|
|
152
326
|
// 数组去重
|
|
153
|
-
...
|
|
327
|
+
...B,
|
|
154
328
|
// 判断元素是否存在
|
|
155
|
-
...A,
|
|
156
|
-
// 数组排序
|
|
157
329
|
...M,
|
|
330
|
+
// 数组排序
|
|
331
|
+
...x,
|
|
158
332
|
// 获取极值
|
|
159
333
|
...S,
|
|
160
334
|
// 统计出现次数
|
|
161
|
-
...
|
|
335
|
+
...b,
|
|
336
|
+
// 数组随机打乱-Fisher-Yates算法
|
|
337
|
+
...E
|
|
162
338
|
};
|
|
163
|
-
class
|
|
339
|
+
class N {
|
|
164
340
|
/** Base64 编码表 */
|
|
165
341
|
static BASE64_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
|
166
342
|
/**
|
|
@@ -177,10 +353,10 @@ class I {
|
|
|
177
353
|
try {
|
|
178
354
|
const i = atob(l), h = [];
|
|
179
355
|
for (let a = 0; a < i.length; a += r) {
|
|
180
|
-
const u = i.slice(a, a + r),
|
|
181
|
-
for (let
|
|
182
|
-
d
|
|
183
|
-
const p = new Uint8Array(
|
|
356
|
+
const u = i.slice(a, a + r), f = new Array(u.length);
|
|
357
|
+
for (let d = 0; d < u.length; d++)
|
|
358
|
+
f[d] = u.charCodeAt(d);
|
|
359
|
+
const p = new Uint8Array(f);
|
|
184
360
|
h.push(p);
|
|
185
361
|
}
|
|
186
362
|
return new Blob(h, { type: t });
|
|
@@ -201,9 +377,9 @@ class I {
|
|
|
201
377
|
static toFile(n, t = "file.txt", r = "text/plain") {
|
|
202
378
|
const s = n.replace(/^data:.+;base64,/, "").replace(/-/g, "+").replace(/_/g, "/"), c = "=".repeat((4 - s.length % 4) % 4), l = s + c, i = atob(l), h = [];
|
|
203
379
|
for (let u = 0; u < i.length; u += 512) {
|
|
204
|
-
const
|
|
205
|
-
for (let
|
|
206
|
-
p[
|
|
380
|
+
const f = i.slice(u, u + 512), p = new Array(f.length);
|
|
381
|
+
for (let d = 0; d < f.length; d++)
|
|
382
|
+
p[d] = f.charCodeAt(d);
|
|
207
383
|
h.push(new Uint8Array(p));
|
|
208
384
|
}
|
|
209
385
|
const a = new Blob(h, { type: r });
|
|
@@ -282,8 +458,8 @@ class I {
|
|
|
282
458
|
static _bytesToBase64(n) {
|
|
283
459
|
let t = "", r = 0;
|
|
284
460
|
for (; r < n.length; ) {
|
|
285
|
-
const o = n[r++], s = r < n.length, c = s ? n[r++] : 0, l = r < n.length, i = l ? n[r++] : 0, h = o >> 2, a = (o & 3) << 4 | c >> 4, u = (c & 15) << 2 | i >> 6,
|
|
286
|
-
s ? l ? t += this.BASE64_CHARS.charAt(h) + this.BASE64_CHARS.charAt(a) + this.BASE64_CHARS.charAt(u) + this.BASE64_CHARS.charAt(
|
|
461
|
+
const o = n[r++], s = r < n.length, c = s ? n[r++] : 0, l = r < n.length, i = l ? n[r++] : 0, h = o >> 2, a = (o & 3) << 4 | c >> 4, u = (c & 15) << 2 | i >> 6, f = i & 63;
|
|
462
|
+
s ? l ? t += this.BASE64_CHARS.charAt(h) + this.BASE64_CHARS.charAt(a) + this.BASE64_CHARS.charAt(u) + this.BASE64_CHARS.charAt(f) : t += this.BASE64_CHARS.charAt(h) + this.BASE64_CHARS.charAt(a) + this.BASE64_CHARS.charAt(u) + "=" : t += this.BASE64_CHARS.charAt(h) + this.BASE64_CHARS.charAt(a) + "==";
|
|
287
463
|
}
|
|
288
464
|
return t;
|
|
289
465
|
}
|
|
@@ -299,14 +475,14 @@ class I {
|
|
|
299
475
|
c[this.BASE64_CHARS.charCodeAt(h)] = h;
|
|
300
476
|
let l = 0, i = 0;
|
|
301
477
|
for (; i < t; ) {
|
|
302
|
-
const h = c[n.charCodeAt(i++)], a = c[n.charCodeAt(i++)], u = i < t ? c[n.charCodeAt(i++)] : -1,
|
|
478
|
+
const h = c[n.charCodeAt(i++)], a = c[n.charCodeAt(i++)], u = i < t ? c[n.charCodeAt(i++)] : -1, f = i < t ? c[n.charCodeAt(i++)] : -1;
|
|
303
479
|
if (h === -1 || a === -1)
|
|
304
480
|
throw new Error("无效的 Base64 字符");
|
|
305
481
|
const p = h << 2 | a >> 4;
|
|
306
482
|
if (s[l++] = p, u !== -1) {
|
|
307
|
-
const
|
|
308
|
-
if (s[l++] =
|
|
309
|
-
const g = (u & 3) << 6 |
|
|
483
|
+
const d = (a & 15) << 4 | u >> 2;
|
|
484
|
+
if (s[l++] = d, f !== -1) {
|
|
485
|
+
const g = (u & 3) << 6 | f;
|
|
310
486
|
s[l++] = g;
|
|
311
487
|
}
|
|
312
488
|
}
|
|
@@ -314,7 +490,7 @@ class I {
|
|
|
314
490
|
return s;
|
|
315
491
|
}
|
|
316
492
|
}
|
|
317
|
-
const
|
|
493
|
+
const R = {
|
|
318
494
|
/**
|
|
319
495
|
* 检查是否为空字符串
|
|
320
496
|
* @param str 要检查的字符串
|
|
@@ -458,7 +634,115 @@ const C = {
|
|
|
458
634
|
isMobile() {
|
|
459
635
|
return /Mobi|Android|iPhone/i.test(navigator.userAgent);
|
|
460
636
|
}
|
|
461
|
-
},
|
|
637
|
+
}, m = {
|
|
638
|
+
/**
|
|
639
|
+
* 判断对象是否为空
|
|
640
|
+
* @param obj 对象
|
|
641
|
+
* @returns 是否为空。true 为空;false 不为空
|
|
642
|
+
*/
|
|
643
|
+
isEmptyObject(e) {
|
|
644
|
+
return e ? Object.keys(e).length === 0 && e.constructor === Object : !0;
|
|
645
|
+
},
|
|
646
|
+
/**
|
|
647
|
+
* 复制对象【对象的浅拷贝 把obj1的成员,复制给obj2】
|
|
648
|
+
* @param obj1 源对象
|
|
649
|
+
* @param obj2 目标对象
|
|
650
|
+
*/
|
|
651
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
652
|
+
copy(e, n) {
|
|
653
|
+
for (const t in e)
|
|
654
|
+
n[t] = e[t];
|
|
655
|
+
},
|
|
656
|
+
/**
|
|
657
|
+
* 对象的深拷贝 把o1 的成员,复制给o2
|
|
658
|
+
* @param o1
|
|
659
|
+
* @param o2
|
|
660
|
+
*/
|
|
661
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
662
|
+
deepCopy(e, n) {
|
|
663
|
+
for (const t in e) {
|
|
664
|
+
const r = e[t];
|
|
665
|
+
r instanceof Object ? (n[t] = {}, this.deepCopy(r, n[t])) : r instanceof Array ? (n[t] = [], this.deepCopy(r, n[t])) : n[t] = e[t];
|
|
666
|
+
}
|
|
667
|
+
}
|
|
668
|
+
}, D = {
|
|
669
|
+
/**
|
|
670
|
+
* 浅拷贝
|
|
671
|
+
* @param source 需要处理的源对象
|
|
672
|
+
* @returns 浅拷贝后的新对象
|
|
673
|
+
*/
|
|
674
|
+
shallowClone(e) {
|
|
675
|
+
if (e === null || typeof e != "object")
|
|
676
|
+
return e;
|
|
677
|
+
if (m.isEmptyObject(e))
|
|
678
|
+
return {};
|
|
679
|
+
const n = {};
|
|
680
|
+
for (const t in e)
|
|
681
|
+
n[t] = e[t];
|
|
682
|
+
return n;
|
|
683
|
+
},
|
|
684
|
+
/**
|
|
685
|
+
* 最便捷实现深克隆/拷贝
|
|
686
|
+
* 存在的问题:
|
|
687
|
+
* (1)序列化会自动忽略 undefined、Symbol、函数等特殊类型
|
|
688
|
+
* (2)序列化会将 NaN、Infinity、-Infinity 转换为 null
|
|
689
|
+
* (3)无法解决循环引用的问题。报错:TypeError: Converting circular structure to JSON
|
|
690
|
+
* @param source 任意对象
|
|
691
|
+
* @returns 深克隆/拷贝后的对象
|
|
692
|
+
*/
|
|
693
|
+
deepCloneByJSON(e) {
|
|
694
|
+
return e === null || typeof e != "object" ? e : m.isEmptyObject(e) ? {} : JSON.parse(JSON.stringify(e));
|
|
695
|
+
},
|
|
696
|
+
/**
|
|
697
|
+
* 深拷贝函数
|
|
698
|
+
* (1)处理对象和数组
|
|
699
|
+
* (2)支持循环引用
|
|
700
|
+
* (3)还支持更多类型的对象,如 Date、RegExp、Error、Map、Set、Symbol、Function、Node 等
|
|
701
|
+
* @param source 任意对象
|
|
702
|
+
* @param map 用于存储已经拷贝过的对象,避免循环引用
|
|
703
|
+
* @returns 深拷贝/拷贝后的对象
|
|
704
|
+
*/
|
|
705
|
+
deepCloneByMap(e, n = /* @__PURE__ */ new WeakMap()) {
|
|
706
|
+
if (e === null || typeof e != "object")
|
|
707
|
+
return e;
|
|
708
|
+
if (m.isEmptyObject(e))
|
|
709
|
+
throw new Error("空对象不能进行深拷贝");
|
|
710
|
+
if (n.has(e))
|
|
711
|
+
return n.get(e);
|
|
712
|
+
const t = U.getType(e);
|
|
713
|
+
let r;
|
|
714
|
+
switch (t) {
|
|
715
|
+
case "object":
|
|
716
|
+
case "array":
|
|
717
|
+
r = Array.isArray(e) ? [] : {};
|
|
718
|
+
break;
|
|
719
|
+
case "Date":
|
|
720
|
+
r = new Date(e);
|
|
721
|
+
break;
|
|
722
|
+
case "RegExp":
|
|
723
|
+
r = new RegExp(e);
|
|
724
|
+
break;
|
|
725
|
+
case "Map":
|
|
726
|
+
r = new Map(e);
|
|
727
|
+
break;
|
|
728
|
+
case "Set":
|
|
729
|
+
r = new Set(e);
|
|
730
|
+
break;
|
|
731
|
+
default:
|
|
732
|
+
return e;
|
|
733
|
+
}
|
|
734
|
+
return n.set(e, r), t === "Map" ? (e.forEach((o, s) => {
|
|
735
|
+
r.set(this.deepCloneByMap(s, n), this.deepCloneByMap(o, n));
|
|
736
|
+
}), r) : t === "Set" ? (e.forEach((o) => {
|
|
737
|
+
r.add(this.deepCloneByMap(o, n));
|
|
738
|
+
}), r) : (Reflect.ownKeys(e).forEach((o) => {
|
|
739
|
+
r[o] = this.deepCloneByMap(
|
|
740
|
+
e[o],
|
|
741
|
+
n
|
|
742
|
+
);
|
|
743
|
+
}), r);
|
|
744
|
+
}
|
|
745
|
+
}, O = {
|
|
462
746
|
/**
|
|
463
747
|
* 获取变量的类型
|
|
464
748
|
* @param val 任意变量
|
|
@@ -467,7 +751,10 @@ const C = {
|
|
|
467
751
|
getType(e) {
|
|
468
752
|
return Object.prototype.toString.call(e).replace(/\[object\s(\w+)\]/, "$1");
|
|
469
753
|
}
|
|
470
|
-
},
|
|
754
|
+
}, U = {
|
|
755
|
+
...O,
|
|
756
|
+
...D
|
|
757
|
+
}, F = {
|
|
471
758
|
/**
|
|
472
759
|
* 通过传入的name获取cookie的值
|
|
473
760
|
* @param name cookie的name
|
|
@@ -497,7 +784,7 @@ const C = {
|
|
|
497
784
|
deleteCookie(e) {
|
|
498
785
|
this.setCookie(e, "", -1);
|
|
499
786
|
}
|
|
500
|
-
},
|
|
787
|
+
}, P = {
|
|
501
788
|
/**
|
|
502
789
|
* 获取当前时间字符串
|
|
503
790
|
* @param locales 区域设置。如:'zh-CN','en-US',"chinese"。默认'zh-CN'。
|
|
@@ -545,7 +832,7 @@ const C = {
|
|
|
545
832
|
r += 31;
|
|
546
833
|
break;
|
|
547
834
|
case 2:
|
|
548
|
-
|
|
835
|
+
R.isLeapYear(e) ? r += 29 : r += 28;
|
|
549
836
|
break;
|
|
550
837
|
default:
|
|
551
838
|
r += 30;
|
|
@@ -564,18 +851,18 @@ const C = {
|
|
|
564
851
|
let a = "";
|
|
565
852
|
const u = n ? " " + this.formatDate(r, "hh:mm") : "";
|
|
566
853
|
if (o === l) {
|
|
567
|
-
const
|
|
854
|
+
const d = t.getTime() - e;
|
|
568
855
|
if (s === i && c === h)
|
|
569
|
-
|
|
856
|
+
d < 60 * 1e3 ? a = "刚刚" : a = this.formatDate(r, "hh:mm");
|
|
570
857
|
else {
|
|
571
858
|
const g = /* @__PURE__ */ new Date();
|
|
572
859
|
g.setDate(g.getDate() - 1);
|
|
573
|
-
const
|
|
574
|
-
if (
|
|
860
|
+
const w = /* @__PURE__ */ new Date();
|
|
861
|
+
if (w.setDate(w.getDate() - 2), i === g.getMonth() + 1 && h === g.getDate())
|
|
575
862
|
a = "昨天" + u;
|
|
576
|
-
else if (i ===
|
|
863
|
+
else if (i === w.getMonth() + 1 && h === w.getDate())
|
|
577
864
|
a = "前天" + u;
|
|
578
|
-
else if (
|
|
865
|
+
else if (d / 36e5 <= 7 * 24) {
|
|
579
866
|
const y = new Array(7);
|
|
580
867
|
y[0] = "星期日", y[1] = "星期一", y[2] = "星期二", y[3] = "星期三", y[4] = "星期四", y[5] = "星期五", y[6] = "星期六", a = y[r.getDay()] + u;
|
|
581
868
|
} else a = this.formatDate(r, "yyyy/M/d") + u;
|
|
@@ -612,7 +899,7 @@ const C = {
|
|
|
612
899
|
new RegExp("(" + r + ")").test(n) && (n = n.replace(RegExp.$1, RegExp.$1.length === 1 ? t[r] : ("00" + t[r]).substr(("" + t[r]).length)));
|
|
613
900
|
return n;
|
|
614
901
|
}
|
|
615
|
-
},
|
|
902
|
+
}, q = {
|
|
616
903
|
/**
|
|
617
904
|
* 获取元素相对于文档顶部的偏移量(距离)
|
|
618
905
|
* 处理了SVG元素的特殊情况。
|
|
@@ -683,7 +970,7 @@ const C = {
|
|
|
683
970
|
getViewportHeight() {
|
|
684
971
|
return window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight;
|
|
685
972
|
}
|
|
686
|
-
},
|
|
973
|
+
}, V = {
|
|
687
974
|
/**
|
|
688
975
|
* 将blob对象转化成文件并导出到本地
|
|
689
976
|
* @param blob blob对象
|
|
@@ -702,7 +989,7 @@ const C = {
|
|
|
702
989
|
const t = document.createElement("a");
|
|
703
990
|
t.href = e, t.download = n, document.body.appendChild(t), t.click(), URL.revokeObjectURL(e), document.body.removeChild(t);
|
|
704
991
|
}
|
|
705
|
-
},
|
|
992
|
+
}, W = {
|
|
706
993
|
/**
|
|
707
994
|
* echarts动画函数
|
|
708
995
|
* @param option echarts配置
|
|
@@ -734,7 +1021,7 @@ const C = {
|
|
|
734
1021
|
});
|
|
735
1022
|
});
|
|
736
1023
|
}
|
|
737
|
-
},
|
|
1024
|
+
}, Y = {
|
|
738
1025
|
/**
|
|
739
1026
|
* 将选中的字母数组从A-Z排序:用于试题选择答案的排序实例
|
|
740
1027
|
* @param arr 字母数组
|
|
@@ -746,7 +1033,7 @@ const C = {
|
|
|
746
1033
|
return o < s ? -1 : o > s ? 1 : 0;
|
|
747
1034
|
}) : void 0;
|
|
748
1035
|
}
|
|
749
|
-
},
|
|
1036
|
+
}, z = {
|
|
750
1037
|
/**
|
|
751
1038
|
* 角度(度数)转弧度
|
|
752
1039
|
* 在数学和编程里,角度有两种常用单位,分别是度(°)和弧度(rad)。
|
|
@@ -794,7 +1081,7 @@ const C = {
|
|
|
794
1081
|
const r = this, o = e.longitude ?? e.lng, s = e.latitude ?? e.lat, c = n.longitude ?? n.lng, l = n.latitude ?? n.lat;
|
|
795
1082
|
if (o === void 0 || s === void 0 || c === void 0 || l === void 0)
|
|
796
1083
|
throw new Error("无效的坐标格式,缺少经纬度信息");
|
|
797
|
-
const i = 6371, h = r.degrees2Radians(s), a = r.degrees2Radians(l), u = r.degrees2Radians(l - s),
|
|
1084
|
+
const i = 6371, h = r.degrees2Radians(s), a = r.degrees2Radians(l), u = r.degrees2Radians(l - s), f = r.degrees2Radians(c - o), p = Math.sin(u / 2) * Math.sin(u / 2) + Math.cos(h) * Math.cos(a) * Math.sin(f / 2) * Math.sin(f / 2), d = 2 * Math.atan2(Math.sqrt(p), Math.sqrt(1 - p)), g = i * d;
|
|
798
1085
|
switch (t) {
|
|
799
1086
|
case "m":
|
|
800
1087
|
return g * 1e3;
|
|
@@ -832,7 +1119,7 @@ const C = {
|
|
|
832
1119
|
return { segments: r, total: o };
|
|
833
1120
|
}
|
|
834
1121
|
};
|
|
835
|
-
class
|
|
1122
|
+
class J {
|
|
836
1123
|
/**
|
|
837
1124
|
* 转换为标准金额格式(带千分位和两位小数)
|
|
838
1125
|
* @param num 要转换的数字
|
|
@@ -867,27 +1154,27 @@ class W {
|
|
|
867
1154
|
if (u === 0)
|
|
868
1155
|
a = l[0];
|
|
869
1156
|
else {
|
|
870
|
-
let
|
|
1157
|
+
let d = 0;
|
|
871
1158
|
for (; u > 0; ) {
|
|
872
1159
|
const g = u % 10;
|
|
873
|
-
g !== 0 ? a = l[g] + i[
|
|
1160
|
+
g !== 0 ? a = l[g] + i[d] + a : a.charAt(0) !== l[0] && (a = l[g] + a), u = Math.floor(u / 10), d++;
|
|
874
1161
|
}
|
|
875
1162
|
a = a.replace(/零+/g, "零"), a = a.replace(/零+$/, "");
|
|
876
1163
|
}
|
|
877
|
-
let
|
|
1164
|
+
let f = "";
|
|
878
1165
|
if (c > 0) {
|
|
879
|
-
const
|
|
880
|
-
|
|
1166
|
+
const d = Math.floor(c / 10), g = c % 10;
|
|
1167
|
+
d > 0 && (f += l[d] + h[0]), g > 0 && (f += l[g] + h[1]);
|
|
881
1168
|
} else
|
|
882
|
-
|
|
883
|
-
let p = (r ? "负" : "") + a + "圆" +
|
|
1169
|
+
f = "整";
|
|
1170
|
+
let p = (r ? "负" : "") + a + "圆" + f;
|
|
884
1171
|
return p === "零圆整" && (p = "零圆"), p;
|
|
885
1172
|
} catch (t) {
|
|
886
1173
|
return console.error("转换失败:", t), "格式错误";
|
|
887
1174
|
}
|
|
888
1175
|
}
|
|
889
1176
|
}
|
|
890
|
-
const
|
|
1177
|
+
const Z = {
|
|
891
1178
|
/**
|
|
892
1179
|
* 中文姓名脱敏
|
|
893
1180
|
* @param name 姓名
|
|
@@ -930,15 +1217,15 @@ const Y = {
|
|
|
930
1217
|
}
|
|
931
1218
|
return `${e.slice(0, c)}${"*".repeat(e.length - c)}`;
|
|
932
1219
|
}
|
|
933
|
-
},
|
|
1220
|
+
}, v = (e) => e > 25 || e < 0 ? "" : "ABCDEFGHIJKLMNOPQRSTUVWXYZ"[e], T = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
934
1221
|
__proto__: null,
|
|
935
|
-
toLetter:
|
|
936
|
-
}, Symbol.toStringTag, { value: "Module" })),
|
|
1222
|
+
toLetter: v
|
|
1223
|
+
}, Symbol.toStringTag, { value: "Module" })), j = (e) => e.toFixed(2).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ","), L = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
937
1224
|
__proto__: null,
|
|
938
|
-
toMoney:
|
|
939
|
-
}, Symbol.toStringTag, { value: "Module" })),
|
|
940
|
-
...
|
|
941
|
-
...
|
|
1225
|
+
toMoney: j
|
|
1226
|
+
}, Symbol.toStringTag, { value: "Module" })), K = {
|
|
1227
|
+
...T,
|
|
1228
|
+
...L,
|
|
942
1229
|
/**
|
|
943
1230
|
* 判断是否为数字
|
|
944
1231
|
* @param val 待判断的值
|
|
@@ -947,38 +1234,7 @@ const Y = {
|
|
|
947
1234
|
isNumber(e) {
|
|
948
1235
|
return typeof e == "number" && !isNaN(e);
|
|
949
1236
|
}
|
|
950
|
-
},
|
|
951
|
-
/**
|
|
952
|
-
* 判断对象是否为空
|
|
953
|
-
* @param obj 对象
|
|
954
|
-
* @returns 是否为空。true 为空;false 不为空
|
|
955
|
-
*/
|
|
956
|
-
isEmptyObject(e) {
|
|
957
|
-
return !e || JSON.stringify(e) === "{}" ? !0 : Object.keys(e).length === 0 && e.constructor === Object;
|
|
958
|
-
},
|
|
959
|
-
/**
|
|
960
|
-
* 复制对象【对象的浅拷贝 把obj1的成员,复制给obj2】
|
|
961
|
-
* @param obj1 源对象
|
|
962
|
-
* @param obj2 目标对象
|
|
963
|
-
*/
|
|
964
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
965
|
-
copy(e, n) {
|
|
966
|
-
for (const t in e)
|
|
967
|
-
n[t] = e[t];
|
|
968
|
-
},
|
|
969
|
-
/**
|
|
970
|
-
* 对象的深拷贝 把o1 的成员,复制给o2
|
|
971
|
-
* @param o1
|
|
972
|
-
* @param o2
|
|
973
|
-
*/
|
|
974
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
975
|
-
deepCopy(e, n) {
|
|
976
|
-
for (const t in e) {
|
|
977
|
-
const r = e[t];
|
|
978
|
-
r instanceof Object ? (n[t] = {}, this.deepCopy(r, n[t])) : r instanceof Array ? (n[t] = [], this.deepCopy(r, n[t])) : n[t] = e[t];
|
|
979
|
-
}
|
|
980
|
-
}
|
|
981
|
-
}, Z = {
|
|
1237
|
+
}, X = {
|
|
982
1238
|
/**
|
|
983
1239
|
* 脱敏
|
|
984
1240
|
* @param phone 电话号码/手机号码
|
|
@@ -987,7 +1243,7 @@ const Y = {
|
|
|
987
1243
|
desensitize(e) {
|
|
988
1244
|
return e ? e.replace(/^(\d{3})\d{4}(\d{4})$/, "$1****$2") || e.slice(0, 3) + "****" + e.slice(7) : "";
|
|
989
1245
|
}
|
|
990
|
-
},
|
|
1246
|
+
}, G = {
|
|
991
1247
|
/**
|
|
992
1248
|
* 生成随机颜色
|
|
993
1249
|
* @returns 随机颜色值
|
|
@@ -1011,7 +1267,7 @@ const Y = {
|
|
|
1011
1267
|
uniqueId() {
|
|
1012
1268
|
return Date.now().toString(36) + Math.random().toString(36).substr(2, 5);
|
|
1013
1269
|
}
|
|
1014
|
-
},
|
|
1270
|
+
}, Q = {
|
|
1015
1271
|
/**
|
|
1016
1272
|
* 验证手机号
|
|
1017
1273
|
*/
|
|
@@ -1048,7 +1304,7 @@ const Y = {
|
|
|
1048
1304
|
* 验证0.01~0.99正则:最多两位小数。0.1、0.10、0.9、0.90
|
|
1049
1305
|
*/
|
|
1050
1306
|
decimal: /^0\.(0[1-9]|[1-9][0-9]*)$/
|
|
1051
|
-
},
|
|
1307
|
+
}, ee = {
|
|
1052
1308
|
/**
|
|
1053
1309
|
* 通过key值获取 localStorage 中存储的某个值
|
|
1054
1310
|
* @param key 获取的key
|
|
@@ -1095,7 +1351,7 @@ const Y = {
|
|
|
1095
1351
|
removeSession(e) {
|
|
1096
1352
|
sessionStorage.removeItem(e);
|
|
1097
1353
|
}
|
|
1098
|
-
},
|
|
1354
|
+
}, te = {
|
|
1099
1355
|
/**
|
|
1100
1356
|
* 判断某元素是否在字符串中-比includes()方法更兼容,includes为ES6新增方法,IE不支持。小程序也不支持
|
|
1101
1357
|
* @param str 字符串
|
|
@@ -1178,19 +1434,19 @@ const Y = {
|
|
|
1178
1434
|
throw new Error("开始位置小于0或结束位置超出字符串长度或开始位置大于结束位置");
|
|
1179
1435
|
return e.slice(0, n) + "*".repeat(t - n + 1) + e.slice(t);
|
|
1180
1436
|
}
|
|
1181
|
-
},
|
|
1437
|
+
}, I = (e) => {
|
|
1182
1438
|
const t = new RegExp("[?&]" + e + "=([^&#]*)", "gi").exec(window.location.href);
|
|
1183
1439
|
return t ? decodeURIComponent(t[1]) : null;
|
|
1184
1440
|
};
|
|
1185
|
-
function
|
|
1441
|
+
function _(e) {
|
|
1186
1442
|
return new URLSearchParams(window.location.search).get(e);
|
|
1187
1443
|
}
|
|
1188
|
-
const
|
|
1444
|
+
const H = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
1189
1445
|
__proto__: null,
|
|
1190
|
-
getQueryInfoByName:
|
|
1191
|
-
getQueryParam:
|
|
1192
|
-
}, Symbol.toStringTag, { value: "Module" })),
|
|
1193
|
-
...
|
|
1446
|
+
getQueryInfoByName: I,
|
|
1447
|
+
getQueryParam: _
|
|
1448
|
+
}, Symbol.toStringTag, { value: "Module" })), ne = {
|
|
1449
|
+
...H,
|
|
1194
1450
|
/**
|
|
1195
1451
|
* 获取当前域名
|
|
1196
1452
|
* @returns 当前url链接的host信息
|
|
@@ -1205,7 +1461,7 @@ const O = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
|
1205
1461
|
getPath() {
|
|
1206
1462
|
return window.location.pathname;
|
|
1207
1463
|
}
|
|
1208
|
-
},
|
|
1464
|
+
}, re = {
|
|
1209
1465
|
/**
|
|
1210
1466
|
* 处理瀑布流数据,使其竖向瀑布流布局呈现横向瀑布流的展现形式。适用于 column-gap: 20rpx; column-count: 2; 布局的瀑布流
|
|
1211
1467
|
* @param list 瀑布流数据-数组
|
|
@@ -1236,33 +1492,33 @@ const O = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
|
1236
1492
|
if (i < s)
|
|
1237
1493
|
a.style.left = (o + c) * i + "px", l[i] = a.offsetHeight;
|
|
1238
1494
|
else {
|
|
1239
|
-
const { index: u, value:
|
|
1240
|
-
a.style.left = (o + c) * u + "px", a.style.top =
|
|
1495
|
+
const { index: u, value: f } = C.getMinValueAndIndex(l);
|
|
1496
|
+
a.style.left = (o + c) * u + "px", a.style.top = f + t + "px", l[u] = a.offsetHeight + t + f;
|
|
1241
1497
|
}
|
|
1242
1498
|
}
|
|
1243
1499
|
}
|
|
1244
1500
|
};
|
|
1245
1501
|
export {
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1502
|
+
N as Base64Utils,
|
|
1503
|
+
J as MoneyFormatter,
|
|
1504
|
+
C as arrayUtils,
|
|
1505
|
+
R as booleanUtils,
|
|
1506
|
+
U as commonUtils,
|
|
1507
|
+
F as cookieUtils,
|
|
1508
|
+
P as dateUtils,
|
|
1509
|
+
q as documentUtils,
|
|
1510
|
+
V as downloadUtils,
|
|
1511
|
+
W as echartsUtils,
|
|
1512
|
+
Y as letterUtils,
|
|
1513
|
+
z as mapUtils,
|
|
1514
|
+
Z as nameUtils,
|
|
1515
|
+
K as numberUtils,
|
|
1516
|
+
m as objectUtils,
|
|
1517
|
+
X as phoneUtils,
|
|
1518
|
+
G as randomUtils,
|
|
1519
|
+
Q as regexpUtils,
|
|
1520
|
+
ee as storageUtils,
|
|
1521
|
+
te as stringUtils,
|
|
1522
|
+
ne as urlUtils,
|
|
1523
|
+
re as waterfallUtils
|
|
1268
1524
|
};
|
package/dist/utils.umd.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
(function(h,w){typeof exports=="object"&&typeof module<"u"?w(exports):typeof define=="function"&&define.amd?define(["exports"],w):(h=typeof globalThis<"u"?globalThis:h||self,w(h.yhkitUtils={}))})(this,function(h){"use strict";const A={...{toEnumObj(e,n="value"){if(!e||!e.length)return{};const t={};return e.forEach(r=>{const o=Object.assign({label:r.label,text:r.label},r);t[r[n]]=o}),t}},...{uniqueBySet(e){return e?Array.from(new Set(e)):[]}},...{isExistByIndexOf(e,n){return!e||!n?!1:e.indexOf(n)!==-1},isExistByIncludes(e,n){return!e||!n?!1:e.includes(n)}},...{sort(e,n="asc"){return e?e.sort((t,r)=>n==="asc"?t>r?1:-1:t<r?1:-1):[]},shuffle(e){if(!e)return[];for(let n=e.length-1;n>0;n--){const t=Math.floor(Math.random()*(n+1));[e[n],e[t]]=[e[t],e[n]]}return e}},...{getMaxValue(e){return e?Math.max(...e):0},getMinValue(e){return e?Math.min(...e):0},getMinValueAndIndex(e){if(e.length===0)return{value:0,index:0};const n={value:e[0],index:0};for(let t=1,r=e.length;t<r;t++){const o=e[t];n.value>o&&(n.value=o,n.index=t)}return n},getMaxValueAndIndex(e){return e.length===0?{value:0,index:0}:e.reduce((n,t,r)=>t<n.value?{value:t,index:r}:n,{value:e[0],index:0})}},...{countOfAppear(e,n){let t=0;for(const r of e)r===n&&t++;return t},indexsOfAppear(e,n){let t=-1;const r=[];do t=e.indexOf(n,t+1),t!==-1&&r.push(t);while(t!==-1);return r}}};class M{static BASE64_CHARS="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";static toBlob(n,t="",r=512){const s=(n.split(",")[1]||n).replace(/-/g,"+").replace(/_/g,"/"),c="=".repeat((4-s.length%4)%4),l=s+c;try{const i=atob(l),d=[];for(let a=0;a<i.length;a+=r){const u=i.slice(a,a+r),f=new Array(u.length);for(let g=0;g<u.length;g++)f[g]=u.charCodeAt(g);const p=new Uint8Array(f);d.push(p)}return new Blob(d,{type:t})}catch(i){return console.error("Failed to convert base64 to blob:",i),null}}static toFile(n,t="file.txt",r="text/plain"){const s=n.replace(/^data:.+;base64,/,"").replace(/-/g,"+").replace(/_/g,"/"),c="=".repeat((4-s.length%4)%4),l=s+c,i=atob(l),d=[];for(let u=0;u<i.length;u+=512){const f=i.slice(u,u+512),p=new Array(f.length);for(let g=0;g<f.length;g++)p[g]=f.charCodeAt(g);d.push(new Uint8Array(p))}const a=new Blob(d,{type:r});return new File([a],t,{type:r})}static encode(n){if(!n)return"";const t=this._stringToUtf8Bytes(n);return this._bytesToBase64(t)}static decode(n){if(!n)return"";n=n.replace(/\s/g,"");const t=this._base64ToBytes(n);return this._utf8BytesToString(t)}static _stringToUtf8Bytes(n){const t=[];for(let r=0;r<n.length;r++){let o=n.charCodeAt(r);if(o<128)t.push(o);else if(o<2048)t.push(192|o>>6),t.push(128|o&63);else if(o<55296||o>=57344)t.push(224|o>>12),t.push(128|o>>6&63),t.push(128|o&63);else{r++;const s=o,c=n.charCodeAt(r);if(isNaN(c))throw new Error("代理对不完整");o=65536+((s&1023)<<10)+(c&1023),t.push(240|o>>18),t.push(128|o>>12&63),t.push(128|o>>6&63),t.push(128|o&63)}}return t}static _utf8BytesToString(n){let t="",r=0;for(;r<n.length;){const o=n[r++];if(o<128)t+=String.fromCharCode(o);else if(o>=192&&o<224){const s=n[r++]&63;t+=String.fromCharCode((o&31)<<6|s)}else if(o>=224&&o<240){const s=n[r++]&63,c=n[r++]&63;t+=String.fromCharCode((o&15)<<12|s<<6|c)}else if(o>=240&&o<248){const s=n[r++]&63,c=n[r++]&63,l=n[r++]&63,i=(o&7)<<18|s<<12|c<<6|l,d=Math.floor((i-65536)/1024)+55296,a=(i-65536)%1024+56320;t+=String.fromCharCode(d,a)}else t+="�"}return t}static _bytesToBase64(n){let t="",r=0;for(;r<n.length;){const o=n[r++],s=r<n.length,c=s?n[r++]:0,l=r<n.length,i=l?n[r++]:0,d=o>>2,a=(o&3)<<4|c>>4,u=(c&15)<<2|i>>6,f=i&63;s?l?t+=this.BASE64_CHARS.charAt(d)+this.BASE64_CHARS.charAt(a)+this.BASE64_CHARS.charAt(u)+this.BASE64_CHARS.charAt(f):t+=this.BASE64_CHARS.charAt(d)+this.BASE64_CHARS.charAt(a)+this.BASE64_CHARS.charAt(u)+"=":t+=this.BASE64_CHARS.charAt(d)+this.BASE64_CHARS.charAt(a)+"=="}return t}static _base64ToBytes(n){const t=n.length;let r=0;t>=2&&(n[t-1]==="="&&r++,n[t-2]==="="&&r++);const o=Math.floor(t*3/4)-r,s=new Array(o),c=new Array(256).fill(-1);for(let d=0;d<this.BASE64_CHARS.length;d++)c[this.BASE64_CHARS.charCodeAt(d)]=d;let l=0,i=0;for(;i<t;){const d=c[n.charCodeAt(i++)],a=c[n.charCodeAt(i++)],u=i<t?c[n.charCodeAt(i++)]:-1,f=i<t?c[n.charCodeAt(i++)]:-1;if(d===-1||a===-1)throw new Error("无效的 Base64 字符");const p=d<<2|a>>4;if(s[l++]=p,u!==-1){const g=(a&15)<<4|u>>2;if(s[l++]=g,f!==-1){const y=(u&3)<<6|f;s[l++]=y}}}return s}}const S={isEmptyString(e){return typeof e=="string"&&e.trim()===""},isNumber(e){return typeof e=="number"&&!isNaN(e)},isObject(e){return e!==null&&typeof e=="object"&&!Array.isArray(e)},isEmptyObject(e){return e?Object.keys(e).length===0&&e.constructor===Object:!0},isBoolean(e){return typeof e=="boolean"},isArray(e){return Array.isArray(e)},isFunction(e){return typeof e=="function"},isPromise(e){return!!e&&(typeof e=="object"||typeof e=="function")&&typeof e.then=="function"},isElement(e){return e instanceof Element},isPhone(e){return/^1[3-9]\d{9}$/.test(e)},isEmail(e){return/^[\w.-]+@[\w.-]+\.\w+$/.test(e)},isJSON(e){try{return JSON.parse(e),!0}catch{return!1}},isImageLoaded(e){return e.complete&&e.naturalWidth!==0},isInViewport(e){const n=e.getBoundingClientRect();return n.top>=0&&n.left>=0&&n.bottom<=window.innerHeight&&n.right<=window.innerWidth},isLeapYear(e){return e%4===0&&e%100!==0||e%400===0},isMobile(){return/Mobi|Android|iPhone/i.test(navigator.userAgent)}},U={getType(e){return Object.prototype.toString.call(e).replace(/\[object\s(\w+)\]/,"$1")}},E={getCookie(e){if(!e)return;const n=document.cookie.match(new RegExp("(^| )"+e+"=([^;]+)"));return n?decodeURIComponent(n[2]):null},setCookie(e,n,t=7){const r=new Date;r.setTime(r.getTime()+t*24*60*60*1e3),document.cookie=`${e}=${encodeURIComponent(n)};expires=${r.toUTCString()};path=/`},deleteCookie(e){this.setCookie(e,"",-1)}},B={getTimeString(e,n=!1){return n?new Date().toLocaleString(e,{hour12:!0}):new Date().toLocaleString("chinese",{hour12:!1})},diffDays(e,n){const t=new Date(e).getTime(),r=new Date(n).getTime();return t>r?Math.abs(Math.floor((t-r)/(24*3600*1e3))):Math.abs(Math.floor((r-t)/(24*3600*1e3)))},uniqueId(){return Date.now().toString(36)+Math.random().toString(36).substr(2,5)},getWhichDays(e,n,t){let r=t;for(let o=1;o<n;o++)switch(o){case 1:case 3:case 5:case 7:case 8:case 10:case 12:r+=31;break;case 2:S.isLeapYear(e)?r+=29:r+=28;break;default:r+=30;break}return r},getTimeStringAutoShort2(e,n){const t=new Date,r=new Date(e),o=t.getFullYear(),s=t.getMonth()+1,c=t.getDate(),l=r.getFullYear(),i=r.getMonth()+1,d=r.getDate();let a="";const u=n?" "+this.formatDate(r,"hh:mm"):"";if(o===l){const g=t.getTime()-e;if(s===i&&c===d)g<60*1e3?a="刚刚":a=this.formatDate(r,"hh:mm");else{const y=new Date;y.setDate(y.getDate()-1);const b=new Date;if(b.setDate(b.getDate()-2),i===y.getMonth()+1&&d===y.getDate())a="昨天"+u;else if(i===b.getMonth()+1&&d===b.getDate())a="前天"+u;else if(g/36e5<=7*24){const m=new Array(7);m[0]="星期日",m[1]="星期一",m[2]="星期二",m[3]="星期三",m[4]="星期四",m[5]="星期五",m[6]="星期六",a=m[r.getDay()]+u}else a=this.formatDate(r,"yyyy/M/d")+u}}else a=this.formatDate(r,"yyyy/M/d")+u;return a},formatDate(e,n){const t={"M+":e.getMonth()+1,"d+":e.getDate(),"h+":e.getHours(),"m+":e.getMinutes(),"s+":e.getSeconds(),"q+":Math.floor((e.getMonth()+3)/3),S:e.getMilliseconds()};/(y+)/.test(n)&&(n=n.replace(RegExp.$1,(e.getFullYear()+"").substr(4-RegExp.$1.length)));for(const r in t)new RegExp("("+r+")").test(n)&&(n=n.replace(RegExp.$1,RegExp.$1.length===1?t[r]:("00"+t[r]).substr((""+t[r]).length)));return n}},C={getOffsetTop(e){if(!e)throw new Error("Element is not provided");if(e instanceof SVGElement){const t=e.getBoundingClientRect(),r=window.pageYOffset||document.documentElement.scrollTop;return t.top+r}let n=0;for(;e;)n+=e.offsetTop,e=e.offsetParent;return n},getScrollValue(){const e={scrollLeft:0,scrollTop:0};return e.scrollLeft=document.body.scrollLeft||document.documentElement.scrollLeft,e.scrollTop=document.body.scrollTop||document.documentElement.scrollTop,e},getPageValue(e){e=e||window.event;const n=e.pageX||e.clientX+this.getScrollValue().scrollLeft,t=e.pageY||e.clientY+this.getScrollValue().scrollTop;return{pageX:n,pageY:t}},addEventListener(e,n,t){e.addEventListener?e.addEventListener(n,t):e.attachEvent?e.attachEvent("on"+n,t):e["on"+n]=t},getViewportWidth(){return window.innerWidth||document.documentElement.clientWidth||document.body.clientWidth},getViewportHeight(){return window.innerHeight||document.documentElement.clientHeight||document.body.clientHeight}},x={saveAsBlob(e,n){const t=document.createElement("a"),r=window.URL.createObjectURL(e);t.href=r,t.download=n,document.body.appendChild(t),t.click(),URL.revokeObjectURL(r),document.body.removeChild(t)},saveAsUrl(e,n){const t=document.createElement("a");t.href=e,t.download=n,document.body.appendChild(t),t.click(),URL.revokeObjectURL(e),document.body.removeChild(t)}},D={animate(e,n){let t=-1;const r=e.series[0].data.length;let o;o=setInterval(()=>{n.dispatchAction({type:"downplay",seriesIndex:0,dataIndex:t}),t=(t+1)%r,n.dispatchAction({type:"highlight",seriesIndex:0,dataIndex:t}),n.dispatchAction({type:"showTip",seriesIndex:0,dataIndex:t}),t>r&&(t=0)},2e3),n.on("mouseover",()=>{clearInterval(o),n.dispatchAction({type:"downplay",seriesIndex:0,dataIndex:t})})}},R={sortFromA2Z(e){return e?.length?e.sort((t,r)=>{const o=t.toUpperCase(),s=r.toUpperCase();return o<s?-1:o>s?1:0}):void 0}},v={degrees2Radians(e){return e*Math.PI/180},getDistance(e,n,t,r){const o=this.degrees2Radians(e),s=this.degrees2Radians(t),c=o-s,l=this.degrees2Radians(n)-this.degrees2Radians(r);let i=2*Math.asin(Math.sqrt(Math.pow(Math.sin(c/2),2)+Math.cos(o)*Math.cos(s)*Math.pow(Math.sin(l/2),2)));return i=i*6378.137,i=Math.round(i*1e4)/1e4,i=+i.toFixed(2),console.log("经纬度计算的距离为:"+i),i},calculateDistanceByHaversine(e,n,t="km"){const r=this,o=e.longitude??e.lng,s=e.latitude??e.lat,c=n.longitude??n.lng,l=n.latitude??n.lat;if(o===void 0||s===void 0||c===void 0||l===void 0)throw new Error("无效的坐标格式,缺少经纬度信息");const i=6371,d=r.degrees2Radians(s),a=r.degrees2Radians(l),u=r.degrees2Radians(l-s),f=r.degrees2Radians(c-o),p=Math.sin(u/2)*Math.sin(u/2)+Math.cos(d)*Math.cos(a)*Math.sin(f/2)*Math.sin(f/2),g=2*Math.atan2(Math.sqrt(p),Math.sqrt(1-p)),y=i*g;switch(t){case"m":return y*1e3;case"mi":return y*.621371;case"nmi":return y*.539957;default:return y}},calculateDistancesByHaversine(e,n="km",t=!1){if(e.length<2)return{segments:[],total:0};const r=[];let o=0;for(let s=0;s<e.length-1;s++){const c=this.calculateDistanceByHaversine(e[s],e[s+1],n);r.push(c),o+=c}if(t&&e.length>2){const s=this.calculateDistanceByHaversine(e[e.length-1],e[0],n);r.push(s),o+=s}return{segments:r,total:o}}};class T{static toStandardFormat(n){try{const t=typeof n=="string"?parseFloat(n):n;if(isNaN(t))throw new Error("输入不是有效的数字");if(!isFinite(t))throw new Error("输入是无穷大");return t.toFixed(2).toString().replace(/\B(?=(\d{3})+(?!\d))/g,",")}catch(t){return console.error("格式化失败:",t),"格式错误"}}static toChineseFormat(n){try{const t=typeof n=="string"?parseFloat(n):n;if(isNaN(t))throw new Error("输入不是有效的数字");if(t>9999999999999e-2||t<-9999999999999e-2)throw new Error("输入数字超出范围");const r=t<0,o=Math.abs(t),s=Math.floor(o),c=Math.round((o-s)*100),l=["零","壹","贰","叁","肆","伍","陆","柒","捌","玖"],i=["","拾","佰","仟","万","拾","佰","仟","亿","拾","佰","仟"],d=["角","分"];let a="",u=s;if(u===0)a=l[0];else{let g=0;for(;u>0;){const y=u%10;y!==0?a=l[y]+i[g]+a:a.charAt(0)!==l[0]&&(a=l[y]+a),u=Math.floor(u/10),g++}a=a.replace(/零+/g,"零"),a=a.replace(/零+$/,"")}let f="";if(c>0){const g=Math.floor(c/10),y=c%10;g>0&&(f+=l[g]+d[0]),y>0&&(f+=l[y]+d[1])}else f="整";let p=(r?"负":"")+a+"圆"+f;return p==="零圆整"&&(p="零圆"),p}catch(t){return console.error("转换失败:",t),"格式错误"}}}const L={desensitizeChineseName(e,n={}){const{keepLength:t=1,keepLast:r=!1}=n;if(!e||e.length===0||e.trim().length===0)throw new Error("姓名不能为空");if(typeof e!="string")throw new Error("姓名必须是字符串");if(e.length<=1)return e;const o=["欧阳","司马","上官","东方","独孤","南宫","闻人","夏侯","诸葛","尉迟","公孙","长孙","宇文","司徒","慕容"];n.compoundSurname&&n.compoundSurname.trim().length>0&&!o.includes(n.compoundSurname)&&o.push(n.compoundSurname);let s="";o.some(l=>e.startsWith(l))?s=o.find(l=>e.startsWith(l))||"":s=e[0]||"";const c=Math.max(t,s.length);if(c>=e.length)return e;if(r&&e.length>2){const l=e.slice(0,c),i=e.slice(-1),d=e.length-c-1;return`${l}${"*".repeat(d)}${i}`}return`${e.slice(0,c)}${"*".repeat(e.length-c)}`}},O={...Object.freeze(Object.defineProperty({__proto__:null,toLetter:e=>e>25||e<0?"":"ABCDEFGHIJKLMNOPQRSTUVWXYZ"[e]},Symbol.toStringTag,{value:"Module"})),...Object.freeze(Object.defineProperty({__proto__:null,toMoney:e=>e.toFixed(2).toString().replace(/\B(?=(\d{3})+(?!\d))/g,",")},Symbol.toStringTag,{value:"Module"})),isNumber(e){return typeof e=="number"&&!isNaN(e)}},_={isEmptyObject(e){return!e||JSON.stringify(e)==="{}"?!0:Object.keys(e).length===0&&e.constructor===Object},copy(e,n){for(const t in e)n[t]=e[t]},deepCopy(e,n){for(const t in e){const r=e[t];r instanceof Object?(n[t]={},this.deepCopy(r,n[t])):r instanceof Array?(n[t]=[],this.deepCopy(r,n[t])):n[t]=e[t]}}},I={desensitize(e){return e?e.replace(/^(\d{3})\d{4}(\d{4})$/,"$1****$2")||e.slice(0,3)+"****"+e.slice(7):""}},k={color:function(){return`#${Math.random().toString(16).slice(2,8)}`},int(e,n){return Math.floor(Math.random()*(n-e+1))+e},uniqueId(){return Date.now().toString(36)+Math.random().toString(36).substr(2,5)}},j={mobile:/^1[3-9]\d{9}$/,email:/^[A-Za-z0-9\u4e00-\u9fa5]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+$/,chinese:/^[\u4e00-\u9fa5]+$/,english:/^[a-zA-Z]+$/,chineseStart:/^[\u4e00-\u9fa5]+\w*$/,integer:/^\d+$/,integerAndzero:/^(0|[1-9]+[0-9]*)$/,strongPassword:/^(?!.*[\s\p{C}])(?:(?=.*[A-Z])(?=.*[a-z])(?=.*[\d\W])|(?=.*\d)(?=.*[^\w\s])).{8,}$/u,decimal:/^0\.(0[1-9]|[1-9][0-9]*)$/},H={getLocal(e){return localStorage.getItem(e)},setLocal(e,n){localStorage.setItem(e,n)},removeLocal(e){localStorage.removeItem(e)},getSession(e){return sessionStorage.getItem(e)},setSession(e,n){sessionStorage.setItem(e,n)},removeSession(e){sessionStorage.removeItem(e)}},$={isExist(e,n){if(!e||!n)return!1;const t=e.split(",");return console.log("判断某元素是否在字符串中",t.indexOf(n)===-1),t.indexOf(n)!==-1},includes(e,n){return!e||!n?!1:e.includes(n)},isJSON(e){try{return JSON.parse(e),!0}catch{return!1}},indexsOfAppear(e,n){let t=-1;const r=[];do t=e.indexOf(n,t+1),t!==-1&&r.push(t);while(t!==-1);return r},getMaxTimesAndVal(e){const n=[0,""],t={};for(let s=0;s<e.length;s++){const c=e.charAt(s);t[c]?t[c]++:t[c]=1}let r=1;for(const s in t)r<t[s]&&(r=t[s]);const o=[];for(const s in t)r==t[s]&&o.push(s);return n[0]=r,n[1]=o.join(),n},mask(e,n,t){if(!e)throw new Error("字符串为空");if(typeof n!="number"||typeof t!="number")throw new Error("开始位置或结束位置为空");if(n<0||t>e.length||n>t)throw new Error("开始位置小于0或结束位置超出字符串长度或开始位置大于结束位置");return e.slice(0,n)+"*".repeat(t-n+1)+e.slice(t)}},N=e=>{const t=new RegExp("[?&]"+e+"=([^&#]*)","gi").exec(window.location.href);return t?decodeURIComponent(t[1]):null};function P(e){return new URLSearchParams(window.location.search).get(e)}const F={...Object.freeze(Object.defineProperty({__proto__:null,getQueryInfoByName:N,getQueryParam:P},Symbol.toStringTag,{value:"Module"})),getHost(){return window.location.host},getPath(){return window.location.pathname}},V={toList(e,n=2){console.log(e,n);const t={};for(let o=0;o<n;o++)t[o]=[];e.forEach((o,s)=>t[s%n].push(o));const r=[];for(const o in t)r.push(...t[o]);return r},jsLayout(e,n,t){const r=e.offsetWidth,o=n[0].offsetWidth,s=parseInt((r/o).toString()),c=(r-o*s)/(s-1),l=[];for(let i=0,d=n.length;i<d;i++){const a=n[i];if(i<s)a.style.left=(o+c)*i+"px",l[i]=a.offsetHeight;else{const{index:u,value:f}=A.getMinValueAndIndex(l);a.style.left=(o+c)*u+"px",a.style.top=f+t+"px",l[u]=a.offsetHeight+t+f}}}};h.Base64Utils=M,h.MoneyFormatter=T,h.arrayUtils=A,h.booleanUtils=S,h.commonUtils=U,h.cookieUtils=E,h.dateUtils=B,h.documentUtils=C,h.downloadUtils=x,h.echartsUtils=D,h.letterUtils=R,h.mapUtils=v,h.nameUtils=L,h.numberUtils=O,h.objectUtils=_,h.phoneUtils=I,h.randomUtils=k,h.regexpUtils=j,h.storageUtils=H,h.stringUtils=$,h.urlUtils=F,h.waterfallUtils=V,Object.defineProperty(h,Symbol.toStringTag,{value:"Module"})});
|
|
1
|
+
(function(f,m){typeof exports=="object"&&typeof module<"u"?m(exports):typeof define=="function"&&define.amd?define(["exports"],m):(f=typeof globalThis<"u"?globalThis:f||self,m(f.yhkitUtils={}))})(this,function(f){"use strict";const M={...{toEnumObj(e,n="value"){if(!e||!e.length)return{};const t={};return e.forEach(r=>{const o=Object.assign({label:r.label,text:r.label},r);t[r[n]]=o}),t}},...{uniqueBySet(e){if(!e)throw new Error("数组不能为空");const n=e;return Array.from(new Set(n))},uniqueByFilter(e){if(!e)throw new Error("数组不能为空");return e.filter((t,r,o)=>r===o.indexOf(t))},uniqueByReduce(e){if(!e)throw new Error("数组不能为空");return e.reduce((t,r)=>(t.includes(r)||t.push(r),t),[])},uniqueByIncludes(e){if(!e)throw new Error("数组不能为空");const n=e,t=[];return n.forEach(r=>{t.includes(r)||t.push(r)}),t},uniqueByFor(e){if(!e)throw new Error("数组不能为空");const n=e,t=[];for(let r=0;r<n.length;r++)t.includes(n[r])||t.push(n[r]);return t},uniqueByKey(e,n){if(!e||!n)throw new Error("数组不能为空或键名不能为空");const t=e,r=new Map;return t.filter(o=>r.has(o[n])?!1:(r.set(o[n],!0),!0))},unique(e,n={}){const{keys:t,compareFn:r}=n;if(!e)throw new Error("数组不能为空");const o=e;if(!t&&!r)return this.uniqueBySet(o);if(t){const s=new Map;return o.filter(a=>{const l=t.map(i=>a[i]).join("|");return s.has(l)?!1:(s.set(l,!0),!0)})}if(r)return o.filter((s,a,l)=>a===l.findIndex(i=>r(s,i)))}},...{isExistByIndexOf(e,n){return!e||!n?!1:e.indexOf(n)!==-1},isExistByIncludes(e,n){return!e||!n?!1:e.includes(n)}},...{sort(e,n="asc"){return e?e.sort((t,r)=>n==="asc"?t>r?1:-1:t<r?1:-1):[]}},...{getMaxValue(e){return e?Math.max(...e):0},getMinValue(e){return e?Math.min(...e):0},getMinValueAndIndex(e){if(e.length===0)return{value:0,index:0};const n={value:e[0],index:0};for(let t=1,r=e.length;t<r;t++){const o=e[t];n.value>o&&(n.value=o,n.index=t)}return n},getMaxValueAndIndex(e){return e.length===0?{value:0,index:0}:e.reduce((n,t,r)=>t<n.value?{value:t,index:r}:n,{value:e[0],index:0})}},...{countOfAppear(e,n){let t=0;for(const r of e)r===n&&t++;return t},indexsOfAppear(e,n){let t=-1;const r=[];do t=e.indexOf(n,t+1),t!==-1&&r.push(t);while(t!==-1);return r}},...{shuffle(e){if(!e)return[];const n=[...e];for(let t=n.length-1;t>0;t--){const r=Math.floor(Math.random()*(t+1));[n[t],n[r]]=[n[r],n[t]]}return n},sample(e,n){if(!e)return[];if(n<=0||n>e.length)throw new Error("抽样次数必须在1次到数组长度之间");const t=[...e];for(let r=0;r<n;r++){const o=Math.floor(Math.random()*(e.length-r))+r;[t[r],t[o]]=[t[o],t[r]]}return t.slice(0,n)},sampleByStart(e,n){if(!e)return[];if(n<=0||n>e.length)throw new Error("抽样次数必须在1次到数组长度之间");const t=[...e];for(let r=n-1;r>=0;r--){const o=Math.floor(Math.random()*(e.length-r))+r;[t[r],t[o]]=[t[o],t[r]]}return t.slice(0,n)},sampleByEnd(e,n){if(!e)return[];if(n<=0||n>e.length)throw new Error("抽样次数必须在1次到数组长度之间");const t=[...e];for(let r=e.length-1;r>=e.length-n;r--){const o=Math.floor(Math.random()*(r+1));[t[r],t[o]]=[t[o],t[r]]}return t.slice(e.length-n)}}};class U{static BASE64_CHARS="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";static toBlob(n,t="",r=512){const s=(n.split(",")[1]||n).replace(/-/g,"+").replace(/_/g,"/"),a="=".repeat((4-s.length%4)%4),l=s+a;try{const i=atob(l),h=[];for(let c=0;c<i.length;c+=r){const u=i.slice(c,c+r),d=new Array(u.length);for(let g=0;g<u.length;g++)d[g]=u.charCodeAt(g);const y=new Uint8Array(d);h.push(y)}return new Blob(h,{type:t})}catch(i){return console.error("Failed to convert base64 to blob:",i),null}}static toFile(n,t="file.txt",r="text/plain"){const s=n.replace(/^data:.+;base64,/,"").replace(/-/g,"+").replace(/_/g,"/"),a="=".repeat((4-s.length%4)%4),l=s+a,i=atob(l),h=[];for(let u=0;u<i.length;u+=512){const d=i.slice(u,u+512),y=new Array(d.length);for(let g=0;g<d.length;g++)y[g]=d.charCodeAt(g);h.push(new Uint8Array(y))}const c=new Blob(h,{type:r});return new File([c],t,{type:r})}static encode(n){if(!n)return"";const t=this._stringToUtf8Bytes(n);return this._bytesToBase64(t)}static decode(n){if(!n)return"";n=n.replace(/\s/g,"");const t=this._base64ToBytes(n);return this._utf8BytesToString(t)}static _stringToUtf8Bytes(n){const t=[];for(let r=0;r<n.length;r++){let o=n.charCodeAt(r);if(o<128)t.push(o);else if(o<2048)t.push(192|o>>6),t.push(128|o&63);else if(o<55296||o>=57344)t.push(224|o>>12),t.push(128|o>>6&63),t.push(128|o&63);else{r++;const s=o,a=n.charCodeAt(r);if(isNaN(a))throw new Error("代理对不完整");o=65536+((s&1023)<<10)+(a&1023),t.push(240|o>>18),t.push(128|o>>12&63),t.push(128|o>>6&63),t.push(128|o&63)}}return t}static _utf8BytesToString(n){let t="",r=0;for(;r<n.length;){const o=n[r++];if(o<128)t+=String.fromCharCode(o);else if(o>=192&&o<224){const s=n[r++]&63;t+=String.fromCharCode((o&31)<<6|s)}else if(o>=224&&o<240){const s=n[r++]&63,a=n[r++]&63;t+=String.fromCharCode((o&15)<<12|s<<6|a)}else if(o>=240&&o<248){const s=n[r++]&63,a=n[r++]&63,l=n[r++]&63,i=(o&7)<<18|s<<12|a<<6|l,h=Math.floor((i-65536)/1024)+55296,c=(i-65536)%1024+56320;t+=String.fromCharCode(h,c)}else t+="�"}return t}static _bytesToBase64(n){let t="",r=0;for(;r<n.length;){const o=n[r++],s=r<n.length,a=s?n[r++]:0,l=r<n.length,i=l?n[r++]:0,h=o>>2,c=(o&3)<<4|a>>4,u=(a&15)<<2|i>>6,d=i&63;s?l?t+=this.BASE64_CHARS.charAt(h)+this.BASE64_CHARS.charAt(c)+this.BASE64_CHARS.charAt(u)+this.BASE64_CHARS.charAt(d):t+=this.BASE64_CHARS.charAt(h)+this.BASE64_CHARS.charAt(c)+this.BASE64_CHARS.charAt(u)+"=":t+=this.BASE64_CHARS.charAt(h)+this.BASE64_CHARS.charAt(c)+"=="}return t}static _base64ToBytes(n){const t=n.length;let r=0;t>=2&&(n[t-1]==="="&&r++,n[t-2]==="="&&r++);const o=Math.floor(t*3/4)-r,s=new Array(o),a=new Array(256).fill(-1);for(let h=0;h<this.BASE64_CHARS.length;h++)a[this.BASE64_CHARS.charCodeAt(h)]=h;let l=0,i=0;for(;i<t;){const h=a[n.charCodeAt(i++)],c=a[n.charCodeAt(i++)],u=i<t?a[n.charCodeAt(i++)]:-1,d=i<t?a[n.charCodeAt(i++)]:-1;if(h===-1||c===-1)throw new Error("无效的 Base64 字符");const y=h<<2|c>>4;if(s[l++]=y,u!==-1){const g=(c&15)<<4|u>>2;if(s[l++]=g,d!==-1){const p=(u&3)<<6|d;s[l++]=p}}}return s}}const S={isEmptyString(e){return typeof e=="string"&&e.trim()===""},isNumber(e){return typeof e=="number"&&!isNaN(e)},isObject(e){return e!==null&&typeof e=="object"&&!Array.isArray(e)},isEmptyObject(e){return e?Object.keys(e).length===0&&e.constructor===Object:!0},isBoolean(e){return typeof e=="boolean"},isArray(e){return Array.isArray(e)},isFunction(e){return typeof e=="function"},isPromise(e){return!!e&&(typeof e=="object"||typeof e=="function")&&typeof e.then=="function"},isElement(e){return e instanceof Element},isPhone(e){return/^1[3-9]\d{9}$/.test(e)},isEmail(e){return/^[\w.-]+@[\w.-]+\.\w+$/.test(e)},isJSON(e){try{return JSON.parse(e),!0}catch{return!1}},isImageLoaded(e){return e.complete&&e.naturalWidth!==0},isInViewport(e){const n=e.getBoundingClientRect();return n.top>=0&&n.left>=0&&n.bottom<=window.innerHeight&&n.right<=window.innerWidth},isLeapYear(e){return e%4===0&&e%100!==0||e%400===0},isMobile(){return/Mobi|Android|iPhone/i.test(navigator.userAgent)}},b={isEmptyObject(e){return e?Object.keys(e).length===0&&e.constructor===Object:!0},copy(e,n){for(const t in e)n[t]=e[t]},deepCopy(e,n){for(const t in e){const r=e[t];r instanceof Object?(n[t]={},this.deepCopy(r,n[t])):r instanceof Array?(n[t]=[],this.deepCopy(r,n[t])):n[t]=e[t]}}},E={...{getType(e){return Object.prototype.toString.call(e).replace(/\[object\s(\w+)\]/,"$1")}},...{shallowClone(e){if(e===null||typeof e!="object")return e;if(b.isEmptyObject(e))return{};const n={};for(const t in e)n[t]=e[t];return n},deepCloneByJSON(e){return e===null||typeof e!="object"?e:b.isEmptyObject(e)?{}:JSON.parse(JSON.stringify(e))},deepCloneByMap(e,n=new WeakMap){if(e===null||typeof e!="object")return e;if(b.isEmptyObject(e))throw new Error("空对象不能进行深拷贝");if(n.has(e))return n.get(e);const t=E.getType(e);let r;switch(t){case"object":case"array":r=Array.isArray(e)?[]:{};break;case"Date":r=new Date(e);break;case"RegExp":r=new RegExp(e);break;case"Map":r=new Map(e);break;case"Set":r=new Set(e);break;default:return e}return n.set(e,r),t==="Map"?(e.forEach((o,s)=>{r.set(this.deepCloneByMap(s,n),this.deepCloneByMap(o,n))}),r):t==="Set"?(e.forEach(o=>{r.add(this.deepCloneByMap(o,n))}),r):(Reflect.ownKeys(e).forEach(o=>{r[o]=this.deepCloneByMap(e[o],n)}),r)}}},B={getCookie(e){if(!e)return;const n=document.cookie.match(new RegExp("(^| )"+e+"=([^;]+)"));return n?decodeURIComponent(n[2]):null},setCookie(e,n,t=7){const r=new Date;r.setTime(r.getTime()+t*24*60*60*1e3),document.cookie=`${e}=${encodeURIComponent(n)};expires=${r.toUTCString()};path=/`},deleteCookie(e){this.setCookie(e,"",-1)}},C={getTimeString(e,n=!1){return n?new Date().toLocaleString(e,{hour12:!0}):new Date().toLocaleString("chinese",{hour12:!1})},diffDays(e,n){const t=new Date(e).getTime(),r=new Date(n).getTime();return t>r?Math.abs(Math.floor((t-r)/(24*3600*1e3))):Math.abs(Math.floor((r-t)/(24*3600*1e3)))},uniqueId(){return Date.now().toString(36)+Math.random().toString(36).substr(2,5)},getWhichDays(e,n,t){let r=t;for(let o=1;o<n;o++)switch(o){case 1:case 3:case 5:case 7:case 8:case 10:case 12:r+=31;break;case 2:S.isLeapYear(e)?r+=29:r+=28;break;default:r+=30;break}return r},getTimeStringAutoShort2(e,n){const t=new Date,r=new Date(e),o=t.getFullYear(),s=t.getMonth()+1,a=t.getDate(),l=r.getFullYear(),i=r.getMonth()+1,h=r.getDate();let c="";const u=n?" "+this.formatDate(r,"hh:mm"):"";if(o===l){const g=t.getTime()-e;if(s===i&&a===h)g<60*1e3?c="刚刚":c=this.formatDate(r,"hh:mm");else{const p=new Date;p.setDate(p.getDate()-1);const A=new Date;if(A.setDate(A.getDate()-2),i===p.getMonth()+1&&h===p.getDate())c="昨天"+u;else if(i===A.getMonth()+1&&h===A.getDate())c="前天"+u;else if(g/36e5<=7*24){const w=new Array(7);w[0]="星期日",w[1]="星期一",w[2]="星期二",w[3]="星期三",w[4]="星期四",w[5]="星期五",w[6]="星期六",c=w[r.getDay()]+u}else c=this.formatDate(r,"yyyy/M/d")+u}}else c=this.formatDate(r,"yyyy/M/d")+u;return c},formatDate(e,n){const t={"M+":e.getMonth()+1,"d+":e.getDate(),"h+":e.getHours(),"m+":e.getMinutes(),"s+":e.getSeconds(),"q+":Math.floor((e.getMonth()+3)/3),S:e.getMilliseconds()};/(y+)/.test(n)&&(n=n.replace(RegExp.$1,(e.getFullYear()+"").substr(4-RegExp.$1.length)));for(const r in t)new RegExp("("+r+")").test(n)&&(n=n.replace(RegExp.$1,RegExp.$1.length===1?t[r]:("00"+t[r]).substr((""+t[r]).length)));return n}},x={getOffsetTop(e){if(!e)throw new Error("Element is not provided");if(e instanceof SVGElement){const t=e.getBoundingClientRect(),r=window.pageYOffset||document.documentElement.scrollTop;return t.top+r}let n=0;for(;e;)n+=e.offsetTop,e=e.offsetParent;return n},getScrollValue(){const e={scrollLeft:0,scrollTop:0};return e.scrollLeft=document.body.scrollLeft||document.documentElement.scrollLeft,e.scrollTop=document.body.scrollTop||document.documentElement.scrollTop,e},getPageValue(e){e=e||window.event;const n=e.pageX||e.clientX+this.getScrollValue().scrollLeft,t=e.pageY||e.clientY+this.getScrollValue().scrollTop;return{pageX:n,pageY:t}},addEventListener(e,n,t){e.addEventListener?e.addEventListener(n,t):e.attachEvent?e.attachEvent("on"+n,t):e["on"+n]=t},getViewportWidth(){return window.innerWidth||document.documentElement.clientWidth||document.body.clientWidth},getViewportHeight(){return window.innerHeight||document.documentElement.clientHeight||document.body.clientHeight}},R={saveAsBlob(e,n){const t=document.createElement("a"),r=window.URL.createObjectURL(e);t.href=r,t.download=n,document.body.appendChild(t),t.click(),URL.revokeObjectURL(r),document.body.removeChild(t)},saveAsUrl(e,n){const t=document.createElement("a");t.href=e,t.download=n,document.body.appendChild(t),t.click(),URL.revokeObjectURL(e),document.body.removeChild(t)}},D={animate(e,n){let t=-1;const r=e.series[0].data.length;let o;o=setInterval(()=>{n.dispatchAction({type:"downplay",seriesIndex:0,dataIndex:t}),t=(t+1)%r,n.dispatchAction({type:"highlight",seriesIndex:0,dataIndex:t}),n.dispatchAction({type:"showTip",seriesIndex:0,dataIndex:t}),t>r&&(t=0)},2e3),n.on("mouseover",()=>{clearInterval(o),n.dispatchAction({type:"downplay",seriesIndex:0,dataIndex:t})})}},O={sortFromA2Z(e){return e?.length?e.sort((t,r)=>{const o=t.toUpperCase(),s=r.toUpperCase();return o<s?-1:o>s?1:0}):void 0}},T={degrees2Radians(e){return e*Math.PI/180},getDistance(e,n,t,r){const o=this.degrees2Radians(e),s=this.degrees2Radians(t),a=o-s,l=this.degrees2Radians(n)-this.degrees2Radians(r);let i=2*Math.asin(Math.sqrt(Math.pow(Math.sin(a/2),2)+Math.cos(o)*Math.cos(s)*Math.pow(Math.sin(l/2),2)));return i=i*6378.137,i=Math.round(i*1e4)/1e4,i=+i.toFixed(2),console.log("经纬度计算的距离为:"+i),i},calculateDistanceByHaversine(e,n,t="km"){const r=this,o=e.longitude??e.lng,s=e.latitude??e.lat,a=n.longitude??n.lng,l=n.latitude??n.lat;if(o===void 0||s===void 0||a===void 0||l===void 0)throw new Error("无效的坐标格式,缺少经纬度信息");const i=6371,h=r.degrees2Radians(s),c=r.degrees2Radians(l),u=r.degrees2Radians(l-s),d=r.degrees2Radians(a-o),y=Math.sin(u/2)*Math.sin(u/2)+Math.cos(h)*Math.cos(c)*Math.sin(d/2)*Math.sin(d/2),g=2*Math.atan2(Math.sqrt(y),Math.sqrt(1-y)),p=i*g;switch(t){case"m":return p*1e3;case"mi":return p*.621371;case"nmi":return p*.539957;default:return p}},calculateDistancesByHaversine(e,n="km",t=!1){if(e.length<2)return{segments:[],total:0};const r=[];let o=0;for(let s=0;s<e.length-1;s++){const a=this.calculateDistanceByHaversine(e[s],e[s+1],n);r.push(a),o+=a}if(t&&e.length>2){const s=this.calculateDistanceByHaversine(e[e.length-1],e[0],n);r.push(s),o+=s}return{segments:r,total:o}}};class j{static toStandardFormat(n){try{const t=typeof n=="string"?parseFloat(n):n;if(isNaN(t))throw new Error("输入不是有效的数字");if(!isFinite(t))throw new Error("输入是无穷大");return t.toFixed(2).toString().replace(/\B(?=(\d{3})+(?!\d))/g,",")}catch(t){return console.error("格式化失败:",t),"格式错误"}}static toChineseFormat(n){try{const t=typeof n=="string"?parseFloat(n):n;if(isNaN(t))throw new Error("输入不是有效的数字");if(t>9999999999999e-2||t<-9999999999999e-2)throw new Error("输入数字超出范围");const r=t<0,o=Math.abs(t),s=Math.floor(o),a=Math.round((o-s)*100),l=["零","壹","贰","叁","肆","伍","陆","柒","捌","玖"],i=["","拾","佰","仟","万","拾","佰","仟","亿","拾","佰","仟"],h=["角","分"];let c="",u=s;if(u===0)c=l[0];else{let g=0;for(;u>0;){const p=u%10;p!==0?c=l[p]+i[g]+c:c.charAt(0)!==l[0]&&(c=l[p]+c),u=Math.floor(u/10),g++}c=c.replace(/零+/g,"零"),c=c.replace(/零+$/,"")}let d="";if(a>0){const g=Math.floor(a/10),p=a%10;g>0&&(d+=l[g]+h[0]),p>0&&(d+=l[p]+h[1])}else d="整";let y=(r?"负":"")+c+"圆"+d;return y==="零圆整"&&(y="零圆"),y}catch(t){return console.error("转换失败:",t),"格式错误"}}}const v={desensitizeChineseName(e,n={}){const{keepLength:t=1,keepLast:r=!1}=n;if(!e||e.length===0||e.trim().length===0)throw new Error("姓名不能为空");if(typeof e!="string")throw new Error("姓名必须是字符串");if(e.length<=1)return e;const o=["欧阳","司马","上官","东方","独孤","南宫","闻人","夏侯","诸葛","尉迟","公孙","长孙","宇文","司徒","慕容"];n.compoundSurname&&n.compoundSurname.trim().length>0&&!o.includes(n.compoundSurname)&&o.push(n.compoundSurname);let s="";o.some(l=>e.startsWith(l))?s=o.find(l=>e.startsWith(l))||"":s=e[0]||"";const a=Math.max(t,s.length);if(a>=e.length)return e;if(r&&e.length>2){const l=e.slice(0,a),i=e.slice(-1),h=e.length-a-1;return`${l}${"*".repeat(h)}${i}`}return`${e.slice(0,a)}${"*".repeat(e.length-a)}`}},L={...Object.freeze(Object.defineProperty({__proto__:null,toLetter:e=>e>25||e<0?"":"ABCDEFGHIJKLMNOPQRSTUVWXYZ"[e]},Symbol.toStringTag,{value:"Module"})),...Object.freeze(Object.defineProperty({__proto__:null,toMoney:e=>e.toFixed(2).toString().replace(/\B(?=(\d{3})+(?!\d))/g,",")},Symbol.toStringTag,{value:"Module"})),isNumber(e){return typeof e=="number"&&!isNaN(e)}},I={desensitize(e){return e?e.replace(/^(\d{3})\d{4}(\d{4})$/,"$1****$2")||e.slice(0,3)+"****"+e.slice(7):""}},_={color:function(){return`#${Math.random().toString(16).slice(2,8)}`},int(e,n){return Math.floor(Math.random()*(n-e+1))+e},uniqueId(){return Date.now().toString(36)+Math.random().toString(36).substr(2,5)}},k={mobile:/^1[3-9]\d{9}$/,email:/^[A-Za-z0-9\u4e00-\u9fa5]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+$/,chinese:/^[\u4e00-\u9fa5]+$/,english:/^[a-zA-Z]+$/,chineseStart:/^[\u4e00-\u9fa5]+\w*$/,integer:/^\d+$/,integerAndzero:/^(0|[1-9]+[0-9]*)$/,strongPassword:/^(?!.*[\s\p{C}])(?:(?=.*[A-Z])(?=.*[a-z])(?=.*[\d\W])|(?=.*\d)(?=.*[^\w\s])).{8,}$/u,decimal:/^0\.(0[1-9]|[1-9][0-9]*)$/},H={getLocal(e){return localStorage.getItem(e)},setLocal(e,n){localStorage.setItem(e,n)},removeLocal(e){localStorage.removeItem(e)},getSession(e){return sessionStorage.getItem(e)},setSession(e,n){sessionStorage.setItem(e,n)},removeSession(e){sessionStorage.removeItem(e)}},$={isExist(e,n){if(!e||!n)return!1;const t=e.split(",");return console.log("判断某元素是否在字符串中",t.indexOf(n)===-1),t.indexOf(n)!==-1},includes(e,n){return!e||!n?!1:e.includes(n)},isJSON(e){try{return JSON.parse(e),!0}catch{return!1}},indexsOfAppear(e,n){let t=-1;const r=[];do t=e.indexOf(n,t+1),t!==-1&&r.push(t);while(t!==-1);return r},getMaxTimesAndVal(e){const n=[0,""],t={};for(let s=0;s<e.length;s++){const a=e.charAt(s);t[a]?t[a]++:t[a]=1}let r=1;for(const s in t)r<t[s]&&(r=t[s]);const o=[];for(const s in t)r==t[s]&&o.push(s);return n[0]=r,n[1]=o.join(),n},mask(e,n,t){if(!e)throw new Error("字符串为空");if(typeof n!="number"||typeof t!="number")throw new Error("开始位置或结束位置为空");if(n<0||t>e.length||n>t)throw new Error("开始位置小于0或结束位置超出字符串长度或开始位置大于结束位置");return e.slice(0,n)+"*".repeat(t-n+1)+e.slice(t)}},N=e=>{const t=new RegExp("[?&]"+e+"=([^&#]*)","gi").exec(window.location.href);return t?decodeURIComponent(t[1]):null};function F(e){return new URLSearchParams(window.location.search).get(e)}const q={...Object.freeze(Object.defineProperty({__proto__:null,getQueryInfoByName:N,getQueryParam:F},Symbol.toStringTag,{value:"Module"})),getHost(){return window.location.host},getPath(){return window.location.pathname}},P={toList(e,n=2){console.log(e,n);const t={};for(let o=0;o<n;o++)t[o]=[];e.forEach((o,s)=>t[s%n].push(o));const r=[];for(const o in t)r.push(...t[o]);return r},jsLayout(e,n,t){const r=e.offsetWidth,o=n[0].offsetWidth,s=parseInt((r/o).toString()),a=(r-o*s)/(s-1),l=[];for(let i=0,h=n.length;i<h;i++){const c=n[i];if(i<s)c.style.left=(o+a)*i+"px",l[i]=c.offsetHeight;else{const{index:u,value:d}=M.getMinValueAndIndex(l);c.style.left=(o+a)*u+"px",c.style.top=d+t+"px",l[u]=c.offsetHeight+t+d}}}};f.Base64Utils=U,f.MoneyFormatter=j,f.arrayUtils=M,f.booleanUtils=S,f.commonUtils=E,f.cookieUtils=B,f.dateUtils=C,f.documentUtils=x,f.downloadUtils=R,f.echartsUtils=D,f.letterUtils=O,f.mapUtils=T,f.nameUtils=v,f.numberUtils=L,f.objectUtils=b,f.phoneUtils=I,f.randomUtils=_,f.regexpUtils=k,f.storageUtils=H,f.stringUtils=$,f.urlUtils=q,f.waterfallUtils=P,Object.defineProperty(f,Symbol.toStringTag,{value:"Module"})});
|
package/package.json
CHANGED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
declare const _default: {
|
|
2
|
+
/**
|
|
3
|
+
* 数组随机打乱-Fisher-Yates算法
|
|
4
|
+
* 要点:
|
|
5
|
+
* 1、倒叙遍历数组;
|
|
6
|
+
* 2、获取随机位置,并交换当前位置和随机位置的元素;
|
|
7
|
+
* 3、返回洗牌后的数组;
|
|
8
|
+
* @param arr 数组
|
|
9
|
+
* @returns 随机打乱后的数组
|
|
10
|
+
*
|
|
11
|
+
* 注意,这个算法会改变原数组。如果不想改变原数组,可以先复制一份再进行操作。
|
|
12
|
+
* 时间复杂度:O(n)
|
|
13
|
+
* 空间复杂度:O(1)
|
|
14
|
+
*/
|
|
15
|
+
shuffle<T>(arr: T[]): T[];
|
|
16
|
+
/**
|
|
17
|
+
* 数组随机抽样-Fisher-Yates算法前k次迭代,再取前k个元素【洗牌开头,返回开头(更常见)】
|
|
18
|
+
* @param arr 数组
|
|
19
|
+
* @param k 抽样次数
|
|
20
|
+
* @returns 抽样后的数组
|
|
21
|
+
*/
|
|
22
|
+
sample<T>(arr: T[], k: number): T[];
|
|
23
|
+
/**
|
|
24
|
+
* 数组随机抽样-Fisher-Yates算法【洗牌开头,返回开头(更常见)】
|
|
25
|
+
* @param arr 数组
|
|
26
|
+
* @param k 抽样次数
|
|
27
|
+
* @returns 抽样后的数组
|
|
28
|
+
*/
|
|
29
|
+
sampleByStart<T>(arr: T[], k: number): T[];
|
|
30
|
+
/**
|
|
31
|
+
* 数组随机抽样-Fisher-Yates算法【洗牌结尾,返回结尾(不常见)】
|
|
32
|
+
* @param arr 数组
|
|
33
|
+
* @param k 抽样次数
|
|
34
|
+
* @returns 抽样后的数组
|
|
35
|
+
*/
|
|
36
|
+
sampleByEnd<T>(arr: T[], k: number): T[];
|
|
37
|
+
};
|
|
38
|
+
export default _default;
|
package/types/array/index.d.ts
CHANGED
|
@@ -3,6 +3,10 @@
|
|
|
3
3
|
* @namespace arrayUtils
|
|
4
4
|
*/
|
|
5
5
|
export declare const arrayUtils: {
|
|
6
|
+
readonly shuffle: <T>(arr: T[]) => T[];
|
|
7
|
+
readonly sample: <T>(arr: T[], k: number) => T[];
|
|
8
|
+
readonly sampleByStart: <T>(arr: T[], k: number) => T[];
|
|
9
|
+
readonly sampleByEnd: <T>(arr: T[], k: number) => T[];
|
|
6
10
|
readonly countOfAppear: <T>(arr: T[], target: T) => number;
|
|
7
11
|
readonly indexsOfAppear: <T>(array: T[], element: T) => number[];
|
|
8
12
|
readonly getMaxValue: (arr: number[]) => number;
|
|
@@ -16,9 +20,14 @@ export declare const arrayUtils: {
|
|
|
16
20
|
index: number;
|
|
17
21
|
};
|
|
18
22
|
readonly sort: <T>(arr: T[], order?: "asc" | "desc") => T[];
|
|
19
|
-
readonly shuffle: <T>(arr: T[]) => T[];
|
|
20
23
|
readonly isExistByIndexOf: <T>(arr: T[], element: T) => boolean;
|
|
21
24
|
readonly isExistByIncludes: <T>(arr: T[], element: T) => boolean;
|
|
22
|
-
readonly uniqueBySet: <T>(
|
|
25
|
+
readonly uniqueBySet: <T>(_arr: T[]) => T[];
|
|
26
|
+
readonly uniqueByFilter: <T>(_arr: T[]) => T[];
|
|
27
|
+
readonly uniqueByReduce: <T>(_arr: T[]) => T[];
|
|
28
|
+
readonly uniqueByIncludes: <T>(_arr: T[]) => T[];
|
|
29
|
+
readonly uniqueByFor: <T>(_arr: T[]) => T[];
|
|
30
|
+
readonly uniqueByKey: <T>(_arr: T[], key: keyof T) => T[];
|
|
31
|
+
readonly unique: <T>(_arr: T[], options?: import("./unique").TUniqueOptions<T>) => T[] | undefined;
|
|
23
32
|
readonly toEnumObj: (arr: import("@yh-kit/types").IOptionItem[], valueKey?: string) => import("@yh-kit/types").TValueEnum;
|
|
24
33
|
};
|
package/types/array/orderby.d.ts
CHANGED
|
@@ -6,17 +6,5 @@ declare const _default: {
|
|
|
6
6
|
* @returns 排序后的数组
|
|
7
7
|
*/
|
|
8
8
|
sort<T>(arr: T[], order?: "asc" | "desc"): T[];
|
|
9
|
-
/**
|
|
10
|
-
* 数组乱序(洗牌算法)
|
|
11
|
-
* 1. 从数组的最后一个元素开始,将其与随机位置的元素交换位置。
|
|
12
|
-
* 2. 然后,从倒数第二个元素开始,将其与随机位置的元素交换位置。
|
|
13
|
-
* 3. 以此类推,直到第一个元素。
|
|
14
|
-
* 4. 这样,数组中的元素就会被随机打乱顺序。
|
|
15
|
-
* 5. 注意,这个算法会改变原数组。如果不想改变原数组,可以先复制一份再进行操作。
|
|
16
|
-
* 6. 时间复杂度:O(n)
|
|
17
|
-
* @param arr 数组
|
|
18
|
-
* @returns
|
|
19
|
-
*/
|
|
20
|
-
shuffle<T>(arr: T[]): T[];
|
|
21
9
|
};
|
|
22
10
|
export default _default;
|
package/types/array/unique.d.ts
CHANGED
|
@@ -1,9 +1,89 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 数组去重选项
|
|
3
|
+
* @template T 数组元素类型
|
|
4
|
+
* @param keys - 要去重的属性键名数组
|
|
5
|
+
* @param compareFn - 自定义比较函数,用于判断两个元素是否相等
|
|
6
|
+
*/
|
|
7
|
+
export interface TUniqueOptions<T> {
|
|
8
|
+
keys?: (keyof T)[];
|
|
9
|
+
compareFn?: (a: T, b: T) => boolean;
|
|
10
|
+
}
|
|
1
11
|
declare const _default: {
|
|
2
12
|
/**
|
|
3
|
-
*
|
|
13
|
+
* 数组去重:针对简单类型数据s
|
|
14
|
+
* 性能 O(n)
|
|
4
15
|
* @param arr 数组
|
|
5
16
|
* @returns 去重后的数组
|
|
6
17
|
*/
|
|
7
|
-
uniqueBySet<T>(
|
|
18
|
+
uniqueBySet<T>(_arr: T[]): T[];
|
|
19
|
+
/**
|
|
20
|
+
* 双重循环之 filter + indexOf 数组去重:
|
|
21
|
+
* 此方法不能去重 NaN 值,也不能去重对象类型数据。
|
|
22
|
+
* 性能 O(n²),每次 indexOf 都是 O(n) 操作
|
|
23
|
+
* @param arr 数组
|
|
24
|
+
* @returns 去重后的数组
|
|
25
|
+
*/
|
|
26
|
+
uniqueByFilter<T>(_arr: T[]): T[];
|
|
27
|
+
/**
|
|
28
|
+
* 双重循环之 reduce + includes 数组去重:
|
|
29
|
+
* 适用于基本类型数据(string、number、boolean),能去重 NaN 值,但不能去重对象类型数据。
|
|
30
|
+
* 性能 O(n²),每次 includes 都是 O(n) 操作
|
|
31
|
+
* @param arr 数组
|
|
32
|
+
* @returns 去重后的数组
|
|
33
|
+
*/
|
|
34
|
+
uniqueByReduce<T>(_arr: T[]): T[];
|
|
35
|
+
/**
|
|
36
|
+
* 双重循环之 forEach + includes 数组去重:
|
|
37
|
+
* 适用于基本类型数据(string、number、boolean),能去重 NaN 值,但不能去重对象类型数据。
|
|
38
|
+
* 性能 O(n²),每次 includes 都是 O(n) 操作
|
|
39
|
+
* @param arr 数组
|
|
40
|
+
* @returns 去重后的数组
|
|
41
|
+
*/
|
|
42
|
+
uniqueByIncludes<T>(_arr: T[]): T[];
|
|
43
|
+
/**
|
|
44
|
+
* 双重循环之 for + includes 数组去重:
|
|
45
|
+
* 适用于基本类型数据(string、number、boolean),能去重 NaN 值,但不能去重对象类型数据。
|
|
46
|
+
* 性能 O(n²),每次 includes 都是 O(n) 操作
|
|
47
|
+
* @param arr 数组
|
|
48
|
+
* @returns 去重后的数组
|
|
49
|
+
*/
|
|
50
|
+
uniqueByFor<T>(_arr: T[]): T[];
|
|
51
|
+
/**
|
|
52
|
+
* Map + 根据指定键去重
|
|
53
|
+
* 适用类型 对象数组(通过指定键进行去重)
|
|
54
|
+
* 键值类型 支持 string、number、boolean、Symbol
|
|
55
|
+
* NaN 处理 ✅ 支持(Map 支持 NaN 作为键)
|
|
56
|
+
* 性能 O(n),Map 的 has 和 set 操作都是 O(1)
|
|
57
|
+
* @param arr 数组
|
|
58
|
+
* @param key 对象的键名
|
|
59
|
+
* @returns 去重后的数组
|
|
60
|
+
*/
|
|
61
|
+
uniqueByKey<T>(_arr: T[], key: keyof T): T[];
|
|
62
|
+
/**
|
|
63
|
+
* 通用数组去重函数 - 根据选项自动选择去重策略
|
|
64
|
+
*
|
|
65
|
+
* @template T - 数组元素类型
|
|
66
|
+
* @param {T[]} _arr - 待去重的数组
|
|
67
|
+
* @param {TUniqueOptions<T>} [options={}] - 去重选项
|
|
68
|
+
* @param {(keyof T)[]} [options.keys] - 按指定键组合去重(适用于对象数组)
|
|
69
|
+
* @param {(a: T, b: T) => boolean} [options.compareFn] - 自定义比较函数
|
|
70
|
+
* @returns {T[]} 去重后的数组
|
|
71
|
+
*
|
|
72
|
+
* @example
|
|
73
|
+
* // 基本类型数组(默认使用 Set 去重)
|
|
74
|
+
* unique([1, 2, 2, 3, 1]); // [1, 2, 3]
|
|
75
|
+
*
|
|
76
|
+
* @example
|
|
77
|
+
* // 对象数组按多个键去重
|
|
78
|
+
* const users = [{ id: 1, name: 'Alice' }, { id: 2, name: 'Bob' }, { id: 1, name: 'Alice' }];
|
|
79
|
+
* unique(users, { keys: ['id', 'name'] }); // [{ id: 1, name: 'Alice' }, { id: 2, name: 'Bob' }]
|
|
80
|
+
*
|
|
81
|
+
* @example
|
|
82
|
+
* // 使用自定义比较函数
|
|
83
|
+
* unique(arr, { compareFn: (a, b) => a.x === b.x && a.y === b.y });
|
|
84
|
+
*
|
|
85
|
+
* @throws {Error} 当输入数组为空时抛出错误
|
|
86
|
+
*/
|
|
87
|
+
unique<T>(_arr: T[], options?: TUniqueOptions<T>): T[] | undefined;
|
|
8
88
|
};
|
|
9
89
|
export default _default;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
declare const _default: {
|
|
2
|
+
/**
|
|
3
|
+
* 浅拷贝
|
|
4
|
+
* @param source 需要处理的源对象
|
|
5
|
+
* @returns 浅拷贝后的新对象
|
|
6
|
+
*/
|
|
7
|
+
shallowClone(source: object): object;
|
|
8
|
+
/**
|
|
9
|
+
* 最便捷实现深克隆/拷贝
|
|
10
|
+
* 存在的问题:
|
|
11
|
+
* (1)序列化会自动忽略 undefined、Symbol、函数等特殊类型
|
|
12
|
+
* (2)序列化会将 NaN、Infinity、-Infinity 转换为 null
|
|
13
|
+
* (3)无法解决循环引用的问题。报错:TypeError: Converting circular structure to JSON
|
|
14
|
+
* @param source 任意对象
|
|
15
|
+
* @returns 深克隆/拷贝后的对象
|
|
16
|
+
*/
|
|
17
|
+
deepCloneByJSON(source: unknown): any;
|
|
18
|
+
/**
|
|
19
|
+
* 深拷贝函数
|
|
20
|
+
* (1)处理对象和数组
|
|
21
|
+
* (2)支持循环引用
|
|
22
|
+
* (3)还支持更多类型的对象,如 Date、RegExp、Error、Map、Set、Symbol、Function、Node 等
|
|
23
|
+
* @param source 任意对象
|
|
24
|
+
* @param map 用于存储已经拷贝过的对象,避免循环引用
|
|
25
|
+
* @returns 深拷贝/拷贝后的对象
|
|
26
|
+
*/
|
|
27
|
+
deepCloneByMap<T>(source: T, map?: WeakMap<object, unknown>): unknown;
|
|
28
|
+
};
|
|
29
|
+
export default _default;
|
package/types/common/index.d.ts
CHANGED
|
@@ -2,10 +2,8 @@
|
|
|
2
2
|
* 通用工具函数
|
|
3
3
|
*/
|
|
4
4
|
export declare const commonUtils: {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
*/
|
|
10
|
-
getType(val: unknown): string;
|
|
5
|
+
readonly shallowClone: (source: object) => object;
|
|
6
|
+
readonly deepCloneByJSON: (source: unknown) => any;
|
|
7
|
+
readonly deepCloneByMap: <T>(source: T, map?: WeakMap<object, unknown>) => unknown;
|
|
8
|
+
readonly getType: (val: unknown) => string;
|
|
11
9
|
};
|