tools_dj 1.0.82 → 1.0.84

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 CHANGED
@@ -1,12 +1,704 @@
1
- # 工具库模板
1
+ # DJ 工具库
2
2
 
3
- ## 介绍
4
- tools工具库
5
- 后期可以直接安装和修改
3
+ 一个全面的 JavaScript/TypeScript 工具函数集合,包含数据处理、时间格式化、树结构操作、DOM 操作等常用功能。
6
4
 
7
5
  ## 安装
8
- npm i tools_dj
6
+
7
+ ```bash
8
+ npm install tools_dj
9
+ ```
9
10
 
10
11
  ## 使用
11
- import {方法} from "tools_dj";
12
+
13
+ ### 基础使用
14
+
15
+ ```typescript
16
+ import { formatDate, is_empty, formatSize } from "tools_dj";
17
+
18
+ // 格式化日期
19
+ const date = formatDate(new Date(), 'day', '-'); // "2024-03-24"
20
+
21
+ // 检查空值
22
+ const isEmpty = is_empty(""); // true
23
+
24
+ // 格式化文件大小
25
+ const size = formatSize(1024); // "1 KB"
26
+ ```
27
+
28
+ ### 使用类模块
29
+
30
+ ```typescript
31
+ // 权限管理
32
+ import { auth } from "tools_dj";
33
+ const authManager = new auth(['read', 'write', 'delete']);
34
+
35
+ // 时间比较
36
+ import { carbon } from "tools_dj";
37
+ const timeCheck = carbon(new Date());
38
+
39
+ // HTTP请求
40
+ import Request from "tools_dj/request";
41
+ const http = new Request({
42
+ headers: { 'Content-Type': 'application/json' }
43
+ }, { baseUrl: 'https://api.example.com' });
44
+ ```
45
+
46
+ ## API 文档
47
+
48
+ ### 数据类型判断
49
+
50
+ #### `is(obj: any): string`
51
+ 判断数据类型,返回具体类型名称
52
+ ```typescript
53
+ is([1, 2, 3]); // "Array"
54
+ is({}); // "Object"
55
+ is("hello"); // "String"
56
+ ```
57
+
58
+ #### `is_empty(obj: any): boolean`
59
+ 判断值是否为空,支持所有数据类型
60
+ ```typescript
61
+ is_empty(null); // true
62
+ is_empty(""); // true
63
+ is_empty([]); // true
64
+ is_empty({}); // true
65
+ ```
66
+
67
+ #### `isNum(data: any): boolean`
68
+ 判断是否是数字(包括字符型数字)
69
+ ```typescript
70
+ isNum("123"); // true
71
+ isNum(456); // true
72
+ isNum("abc"); // false
73
+ ```
74
+
75
+ ### 数组操作
76
+
77
+ #### `del_repeat(obj: any[]): any[]`
78
+ 删除数组重复元素
79
+ ```typescript
80
+ del_repeat([1, 2, 2, 3]); // [1, 2, 3]
81
+ ```
82
+
83
+ #### `unique(obj: any[]): any[] | false`
84
+ 去除数组重复元素(带空值检查)
85
+ ```typescript
86
+ unique([1, 2, 2, 3]); // [1, 2, 3]
87
+ ```
88
+
89
+ #### `first(obj: any): any`
90
+ 获取数组或对象的第一个元素
91
+ ```typescript
92
+ first([1, 2, 3]); // 1
93
+ ```
94
+
95
+ #### `last(obj: any): any`
96
+ 获取数组或对象的最后一个元素
97
+ ```typescript
98
+ last([1, 2, 3]); // 3
99
+ ```
100
+
101
+ #### `arrayGroup(arr: any[], groupKey: string): object`
102
+ 数组分组
103
+ ```typescript
104
+ arrayGroup([{type: 'A', value: 1}, {type: 'B', value: 2}], 'type');
105
+ // { A: [{type: 'A', value: 1}], B: [{type: 'B', value: 2}] }
106
+ ```
107
+
108
+ ### 时间处理
109
+
110
+ #### `formatDate(time: Date, format: string, type: string): string`
111
+ 格式化时间
112
+ ```typescript
113
+ formatDate(new Date(), 'day', '-'); // "2024-03-24"
114
+ formatDate(new Date(), 'minute', '/'); // "2024/03/24/14/30"
115
+ ```
116
+
117
+ #### `formatTime(time: any, format: string, option?: object): string`
118
+ 高级时间格式化
119
+ ```typescript
120
+ formatTime('2024-03-24', 'YYYY年MM月DD日'); // "2024年03月24日"
121
+ formatTime(new Date(), 'YYYY-MM-DD week'); // "2024-03-24 周日"
122
+ ```
123
+
124
+ #### `getDaysBetween(date1: string, date2: string, negative?: boolean): number`
125
+ 计算两个日期之间的天数
126
+ ```typescript
127
+ getDaysBetween('2024-01-01', '2024-01-05'); // 4
128
+ ```
129
+
130
+ #### `isDateInRange(date: string, startDate: string, endDate: string): boolean`
131
+ 判断日期是否在指定范围内
132
+ ```typescript
133
+ isDateInRange('2024-02-15', '2024-01-01', '2024-12-31'); // true
134
+ ```
135
+
136
+ ### 对象操作
137
+
138
+ #### `merge(obj1: any, obj2: any): any`
139
+ 合并数组或对象
140
+ ```typescript
141
+ merge([1, 2], [3, 4]); // [1, 2, 3, 4] (去重后)
142
+ merge({a: 1}, {b: 2}); // {a: 1, b: 2}
143
+ ```
144
+
145
+ #### `delObj(obj: object, keys?: string | string[]): void`
146
+ 删除对象属性
147
+ ```typescript
148
+ const obj = {a: 1, b: 2, c: 3};
149
+ delObj(obj, 'a'); // {b: 2, c: 3}
150
+ delObj(obj, ['b', 'c']); // {}
151
+ ```
152
+
153
+ #### `delObjEmptyKey(obj: object): void`
154
+ 删除对象中的空属性
155
+ ```typescript
156
+ const obj = {a: 1, b: '', c: null, d: 2};
157
+ delObjEmptyKey(obj); // {a: 1, d: 2}
158
+ ```
159
+
160
+ ### 树结构操作
161
+
162
+ #### `arrToTree(data: any[], option?: object): any[]`
163
+ 平级数组转树形结构
164
+ ```typescript
165
+ const data = [
166
+ {id: 1, parentId: 0, name: 'root'},
167
+ {id: 2, parentId: 1, name: 'child1'}
168
+ ];
169
+ arrToTree(data); // 树形结构
170
+ ```
171
+
172
+ #### `treeToArr(data: any[], option?: object): any[]`
173
+ 树形结构转平级数组
174
+ ```typescript
175
+ treeToArr(treeData); // 扁平化数组
176
+ ```
177
+
178
+ #### `handleTree(data: any[], id: string, parentId: string, children: string): any[]`
179
+ 构造树形结构数据
180
+ ```typescript
181
+ handleTree(data, 'id', 'parentId', 'children');
182
+ ```
183
+
184
+ ### 字符串处理
185
+
186
+ #### `toGetQuery(data: object, option?: object): string`
187
+ 对象转URL查询参数
188
+ ```typescript
189
+ toGetQuery({name: 'test', age: 20}); // "?name=test&age=20"
190
+ ```
191
+
192
+ #### `isLink(str: string): boolean`
193
+ 判断字符串是否为有效链接
194
+ ```typescript
195
+ isLink('https://example.com'); // true
196
+ isLink('not-a-link'); // false
197
+ ```
198
+
199
+ #### `repalce(str: string, index: number, char: string): string`
200
+ 字符串指定位置替换
201
+ ```typescript
202
+ repalce('hello', 1, 'a'); // "hallo"
203
+ ```
204
+
205
+ ### 数字处理
206
+
207
+ #### `formatSize(num: number, option?: object): string`
208
+ 转换大小默认是文件可以是别的
209
+ ```typescript
210
+ formatSize(1024); // "1 KB"
211
+ formatSize(1048576, {decimals: 1}); // "1.0 MB"
212
+ ```
213
+
214
+ #### `numberFixed(number: number, decimalPlaces?: number): number`
215
+ 数字保留小数位(截取不四舍五入)
216
+ ```typescript
217
+ numberFixed(3.14159, 2); // 3.14
218
+ ```
219
+
220
+ #### `numberRepair(str: string, n: number, k: string, d: boolean): string`
221
+ 数字前置补位
222
+ ```typescript
223
+ numberRepair('5', 3, '0'); // "005"
224
+ ```
225
+
226
+ #### `randomNumber(min: number, max: number): number`
227
+ 生成随机数
228
+ ```typescript
229
+ randomNumber(1, 100); // 1-100之间的随机数
230
+ ```
231
+
232
+ ### 工具函数
233
+
234
+ #### `throttle(fn: Function, delay?: number, immediate?: boolean): Function`
235
+ 节流函数
236
+ ```typescript
237
+ const throttled = throttle(() => console.log('throttled'), 1000);
238
+ ```
239
+
240
+ #### `debounce(fn: Function, delay: number): Function`
241
+ 防抖函数
242
+ ```typescript
243
+ const debounced = debounce(() => console.log('debounced'), 300);
244
+ ```
245
+
246
+ #### `memoize(func: Function, options?: object): Function`
247
+ 函数缓存
248
+ ```typescript
249
+ const cachedFn = memoize(expensiveFunction, {ttl: 5000});
250
+ ```
251
+
252
+ ### DOM 相关
253
+
254
+ #### `isMobile(): boolean`
255
+ 检测是否为移动设备
256
+ ```typescript
257
+ isMobile(); // true/false
258
+ ```
259
+
260
+ #### `setMeta(meta: object): void`
261
+ 设置页面meta信息
262
+ ```typescript
263
+ setMeta({title: "页面标题", cZoom: {mobile: 0.8}});
264
+ ```
265
+
266
+ ### 转换工具
267
+
268
+ #### `pxToRem(pxValue: string | number, baseRem?: number): string`
269
+ px转rem
270
+ ```typescript
271
+ pxToRem('16px'); // "0.43rem"
272
+ pxToRem(32, 16); // "2.00rem"
273
+ ```
274
+
275
+ #### `base64Img(base64: string, imgName: string): File`
276
+ base64转文件对象
277
+ ```typescript
278
+ const file = base64Img(base64String, 'image.png');
279
+ ```
280
+
281
+ #### `objToFormData(obj: object, simplify?: boolean): FormData`
282
+ 对象转FormData
283
+ - `obj` - 要转换的对象
284
+ - `simplify` - 是否简化(简化后第一层数组将省略索引),默认true
285
+ ```typescript
286
+ const formData = objToFormData({name: 'test', files: [file1, file2]});
287
+ ```
288
+
289
+ ### 数组高级操作
290
+
291
+ #### `findByIndex(array: any[], key: string, data: any): number`
292
+ 二维数组查找返回下标
293
+ ```typescript
294
+ const users = [{id: 1, name: 'Tom'}, {id: 2, name: 'Jerry'}];
295
+ findByIndex(users, 'id', 2); // 1
296
+ ```
297
+
298
+ #### `setObjData(source: any[], sourceKey: string, sourceData: any, nowKey: string, nowData: any): boolean`
299
+ 设置二维数组的值
300
+ ```typescript
301
+ const data = [{id: 1, name: 'old'}];
302
+ setObjData(data, 'id', 1, 'name', 'new'); // true
303
+ // data: [{id: 1, name: 'new'}]
304
+ ```
305
+
306
+ #### `selectObjData(source: any[], sourceKey: string, sourceData: any): any`
307
+ 查找二维数组数据
308
+ ```typescript
309
+ const users = [{id: 1, name: 'Tom'}, {id: 2, name: 'Jerry'}];
310
+ selectObjData(users, 'id', 2); // {id: 2, name: 'Jerry'}
311
+ ```
312
+
313
+ #### `arrSet(arr: any[], index: number, data: any): void`
314
+ 在数组任意位置插入数据
315
+ ```typescript
316
+ const arr = [1, 2, 4];
317
+ arrSet(arr, 2, 3); // [1, 2, 3, 4]
318
+ ```
319
+
320
+ #### `sArrMove(arr: any[], startIndex: number, endIndex: number): void`
321
+ 源数组移动元素(直接修改原数组)
322
+ ```typescript
323
+ const arr = [1, 2, 3, 4];
324
+ sArrMove(arr, 0, 2); // arr变为 [2, 3, 1, 4]
325
+ ```
326
+
327
+ #### `rArrMove(arr: any[], startIndex: number, endIndex: number): any[]`
328
+ 数组元素位置移动返回新数组(不修改原数组)
329
+ ```typescript
330
+ const arr = [1, 2, 3, 4];
331
+ const newArr = rArrMove(arr, 0, 2); // [2, 3, 1, 4]
332
+ // arr仍为 [1, 2, 3, 4]
333
+ ```
334
+
335
+ #### `inArr(arr: any[], str: any, force?: boolean): number`
336
+ 判断字符是否在数组中,返回索引
337
+ - `force` - 是否强制类型检查,默认false(使用==比较)
338
+ ```typescript
339
+ inArr([1, 2, 3], '2'); // 1 (非强制模式)
340
+ inArr([1, 2, 3], '2', true); // -1 (强制模式)
341
+ ```
342
+
343
+ ### 树结构高级操作
344
+
345
+ #### `treeFor(data: any[], callBack: Function, option?: object): void`
346
+ 树循环返回子项(叶子节点)
347
+ - `option.cKey` - 子节点字段名,默认'children'
348
+ ```typescript
349
+ treeFor(treeData, (node) => {
350
+ console.log('叶子节点:', node);
351
+ });
352
+ ```
353
+
354
+ #### `treeStack(data: any[], callBack: Function, option?: object): void`
355
+ 树栈循环返回子项
356
+ ```typescript
357
+ treeStack(treeData, (node) => {
358
+ console.log('节点:', node);
359
+ });
360
+ ```
361
+
362
+ #### `treeRecursion(data: any[], callBack: Function, option?: object): void`
363
+ 树递归循环返回子项
364
+ ```typescript
365
+ treeRecursion(treeData, (node) => {
366
+ console.log('节点:', node);
367
+ });
368
+ ```
369
+
370
+ #### `treeFind(data: any[], option?: object): any[]`
371
+ 树中查找节点
372
+ - `option.cKey` - 子节点字段名,默认'children'
373
+ - `option.key` - 查找的字段名,默认'id'
374
+ - `option.value` - 查找的值
375
+ - `option.copy` - 是否复制(去除children),默认true
376
+ ```typescript
377
+ treeFind(treeData, {key: 'id', value: 5});
378
+ ```
379
+
380
+ #### `arrToAryTree(items: any[], option?: object): any[]`
381
+ 层级树转换成多叉树(带左右值的嵌套集合模型)
382
+ - `option.idKey` - ID字段,默认'id'
383
+ - `option.pidKey` - 父ID字段,默认'pid'
384
+ - `option.rKey` - 右值字段,默认'rgt'
385
+ - `option.lKey` - 左值字段,默认'lft'
386
+ - `option.levelKey` - 层级字段,默认'level'
387
+ ```typescript
388
+ const tree = arrToAryTree(flatData);
389
+ // 返回带有lft、rgt、level字段的数组
390
+ ```
391
+
392
+ ### 颜色处理
393
+
394
+ #### `colorMix(color1: string, color2: string, weight: number): string`
395
+ 色阶取值(颜色混合)
396
+ - `weight` - 权重0-1,越接近1越接近color2
397
+ ```typescript
398
+ colorMix('#ff0000', '#0000ff', 0.5); // "#7f007f" (混合紫色)
399
+ ```
400
+
401
+ #### `randomColor(): string`
402
+ 生成随机颜色(rgba格式)
403
+ ```typescript
404
+ randomColor(); // "rgba(150,200,180,1)"
405
+ ```
406
+
407
+ ### 排序
408
+
409
+ #### `compare(prop: string, type?: string): Function`
410
+ 数字排序比较函数
411
+ - `type` - 'up'升序(默认)或'down'降序
412
+ ```typescript
413
+ const users = [{age: 25}, {age: 18}, {age: 30}];
414
+ users.sort(compare('age', 'up')); // 按age升序
415
+ ```
416
+
417
+ #### `compareDate(prop: string, type?: string): Function`
418
+ 时间排序比较函数
419
+ ```typescript
420
+ const events = [
421
+ {date: '2024-03-20'},
422
+ {date: '2024-01-15'}
423
+ ];
424
+ events.sort(compareDate('date', 'up')); // 按日期升序
425
+ ```
426
+
427
+ ### 函数工具
428
+
429
+ #### `throttle1(func: Function, delay: number): Function`
430
+ 节流函数(备选实现)
431
+ ```typescript
432
+ const throttled = throttle1(() => {
433
+ console.log('执行');
434
+ }, 1000);
435
+ ```
436
+
437
+ #### `fnRuntime(fn: Function, iterations?: number): void`
438
+ 测量函数执行时间
439
+ - `iterations` - 迭代次数,默认1
440
+ ```typescript
441
+ fnRuntime(() => {
442
+ // 需要测试的代码
443
+ }, 100);
444
+ // 控制台输出: "平均执行时间 100 次数: 0.123456 ms"
445
+ ```
446
+
447
+ #### `mergeObj(obj: object[], callbackCon?: object): object`
448
+ 深层次对象合并
449
+ - `callbackCon.callback` - 回调函数
450
+ - `callbackCon.callType` - 回调类型
451
+ - `callbackCon.afterBack` - 后置回调
452
+ ```typescript
453
+ const merged = mergeObj([
454
+ {a: {b: 1}},
455
+ {a: {c: 2}}
456
+ ]);
457
+ // {a: {b: 1, c: 2}}
458
+ ```
459
+
460
+ ### 其他工具
461
+
462
+ #### `time_change(data: string): number`
463
+ 时间格式转时间戳
464
+ ```typescript
465
+ time_change('2024-03-24 10:30'); // 1711252200000
466
+ ```
467
+
468
+ ## 类模块
469
+
470
+ ### 权限管理 (auth)
471
+
472
+ 基于位运算的高性能权限管理系统
473
+
474
+ ```typescript
475
+ import { auth } from "tools_dj";
476
+
477
+ // 创建权限管理实例
478
+ const authManager = new auth(['read', 'write', 'delete', 'update']);
479
+
480
+ // 初始权限为0
481
+ let userAuth = 0;
482
+
483
+ // 添加权限
484
+ userAuth = authManager.add(userAuth, ['read', 'write']);
485
+
486
+ // 删除权限
487
+ userAuth = authManager.del(userAuth, ['write']);
488
+
489
+ // 判断权限(必须全部存在)
490
+ authManager.andHave(userAuth, ['read', 'write']); // false
491
+
492
+ // 判断权限(只要有一个存在)
493
+ authManager.orHave(userAuth, ['read', 'write']); // true
494
+
495
+ // 获取权限列表
496
+ authManager.getTxt(userAuth); // ['read']
497
+ ```
498
+
499
+ **API说明:**
500
+
501
+ - `constructor(authList: string[])` - 创建权限管理实例
502
+ - `add(base: number, arr: string[]): number` - 添加权限
503
+ - `del(base: number, arr: string[]): number` - 删除权限
504
+ - `andHave(base: number, arr: string[]): boolean` - AND判断(全部存在)
505
+ - `orHave(base: number, arr: string[]): boolean` - OR判断(至少一个存在)
506
+ - `getTxt(number: number): string[]` - 获取权限名称列表
507
+
508
+ ### 时间比较 (date)
509
+
510
+ 提供链式时间比较操作
511
+
512
+ ```typescript
513
+ import { carbon, contrast } from "tools_dj";
514
+
515
+ // 方式1: 使用carbon函数
516
+ const timeCheck = carbon(new Date('2024-03-24'));
517
+
518
+ // 方式2: 使用contrast类
519
+ const timeCheck2 = new contrast(new Date('2024-03-24'));
520
+
521
+ // 大于
522
+ timeCheck.Gt(new Date('2024-03-20')); // true
523
+
524
+ // 小于
525
+ timeCheck.Lt(new Date('2024-03-30')); // true
526
+
527
+ // 等于
528
+ timeCheck.Eq(new Date('2024-03-24')); // true
529
+
530
+ // 不等于
531
+ timeCheck.Ne(new Date('2024-03-25')); // true
532
+
533
+ // 大于等于
534
+ timeCheck.Gte(new Date('2024-03-24')); // true
535
+
536
+ // 小于等于
537
+ timeCheck.Lte(new Date('2024-03-24')); // true
538
+
539
+ // 判断是否在时间段内
540
+ timeCheck.Between(
541
+ new Date('2024-03-20'),
542
+ new Date('2024-03-30')
543
+ ); // true
544
+ ```
545
+
546
+ **API说明:**
547
+
548
+ - `Gt(date: Date): boolean` - 大于
549
+ - `Lt(date: Date): boolean` - 小于
550
+ - `Eq(date: Date): boolean` - 等于
551
+ - `Ne(date: Date): boolean` - 不等于
552
+ - `Gte(date: Date): boolean` - 大于等于
553
+ - `Lte(date: Date): boolean` - 小于等于
554
+ - `Between(date1: Date, date2: Date): boolean` - 是否在时间段内
555
+
556
+ ### 消息通信 (msg)
557
+
558
+ 提供跨页面和页面内的消息通信
559
+
560
+ ```typescript
561
+ import msg from "tools_dj/msg";
562
+
563
+ // 跨页面消息发送(使用BroadcastChannel)
564
+ msg.pageSend('userUpdate', {id: 1, name: 'Tom'});
565
+
566
+ // 跨页面消息接收
567
+ msg.pageRead('userUpdate', (data) => {
568
+ console.log('收到消息:', data);
569
+ });
570
+
571
+ // 页面内消息发送(使用mitt)
572
+ msg.busSend('event1', {data: 'test'});
573
+
574
+ // 页面内消息接收
575
+ msg.busRead('event1', (data) => {
576
+ console.log('收到事件:', data);
577
+ });
578
+
579
+ // 取消特定监听器
580
+ const handler = (data) => console.log(data);
581
+ msg.busRead('event1', handler);
582
+ msg.busOff('event1', handler);
583
+
584
+ // 取消所有同名监听
585
+ msg.busDown('event1');
586
+
587
+ // store消息监听(适用于Vue的Pinia store)
588
+ msg.storeRead(store, (state) => {
589
+ console.log('store变化:', state);
590
+ });
591
+ ```
592
+
593
+ **API说明:**
594
+
595
+ - `pageSend(type: string, data: any): void` - 跨页面消息发送
596
+ - `pageRead(type: string, callback: Function): void` - 跨页面消息接收
597
+ - `busSend(type: string, data: any): void` - 页面内消息发送
598
+ - `busRead(type: string, callback: Function): void` - 页面内消息接收
599
+ - `busOff(type: string, callback: Function): void` - 取消特定监听
600
+ - `busDown(type: string): void` - 取消所有同名监听
601
+ - `storeRead(store: any, callback: Function): void` - store变化监听
602
+
603
+ ### HTTP请求 (request)
604
+
605
+ 基于Fetch API的HTTP请求封装
606
+
607
+ ```typescript
608
+ import Request from "tools_dj/request";
609
+
610
+ // 创建请求实例
611
+ const http = new Request(
612
+ // 默认请求配置
613
+ {
614
+ headers: {
615
+ 'Content-Type': 'application/json'
616
+ },
617
+ mode: 'cors',
618
+ credentials: 'include'
619
+ },
620
+ // 全局配置
621
+ {
622
+ baseUrl: 'https://api.example.com',
623
+ timeout: 10000,
624
+ // 成功回调
625
+ callback: async (response) => {
626
+ return await response.json();
627
+ },
628
+ // 失败回调
629
+ errBack: (error) => {
630
+ console.error('请求失败:', error);
631
+ },
632
+ // 请求前回调
633
+ beforeBack: (options) => {
634
+ console.log('发送请求:', options);
635
+ },
636
+ // 获取中断控制器
637
+ abController: (controller) => {
638
+ // 可以手动中断请求
639
+ // controller.abort();
640
+ }
641
+ }
642
+ );
643
+
644
+ // 发送GET请求
645
+ http.serve('/users', {
646
+ method: 'GET'
647
+ }).then(data => {
648
+ console.log(data);
649
+ });
650
+
651
+ // 发送POST请求
652
+ http.serve('/users', {
653
+ method: 'POST',
654
+ body: JSON.stringify({name: 'Tom', age: 20})
655
+ }, {
656
+ // 单次请求配置
657
+ timeout: 5000,
658
+ callback: async (res) => await res.json()
659
+ }).then(data => {
660
+ console.log(data);
661
+ });
662
+
663
+ // 请求完整URL(会自动检测,不添加baseUrl)
664
+ http.serve('https://other-api.com/data');
665
+ ```
666
+
667
+ **配置参数说明:**
668
+
669
+ 构造函数参数:
670
+ - `option` - Fetch请求配置对象
671
+ - `method` - 请求方法 (GET, POST, PUT, DELETE等)
672
+ - `mode` - 跨域策略 ("cors", "same-origin", "no-cors")
673
+ - `cache` - 缓存策略 ("no-cache", "default", "reload", "force-cache")
674
+ - `credentials` - 凭证策略 ("same-origin", "include", "omit")
675
+ - `headers` - 请求头对象
676
+ - `redirect` - 重定向处理 ("follow", "manual", "error")
677
+ - `referrerPolicy` - 引用策略
678
+ - `body` - 请求体
679
+
680
+ - `conf` - 全局配置对象
681
+ - `baseUrl` - 基础URL前缀
682
+ - `timeout` - 超时时间(毫秒),默认6000
683
+ - `callback(response)` - 成功回调,处理响应
684
+ - `errBack(error)` - 失败回调
685
+ - `abController(controller)` - 获取中断控制器
686
+ - `beforeBack(options)` - 请求前回调
687
+
688
+ serve方法参数:
689
+ - `url` - 请求地址(相对路径或完整URL)
690
+ - `options` - 本次请求的fetch配置(会与构造函数的option合并)
691
+ - `conf` - 本次请求的配置(会与构造函数的conf合并)
692
+
693
+ ## 特性
694
+
695
+ - 🚀 **轻量高效** - 优化的算法实现
696
+ - 📦 **TypeScript 支持** - 完整的类型定义
697
+ - 🔧 **模块化设计** - 按需引入,减少包体积
698
+ - 🌍 **跨平台兼容** - 支持浏览器和 Node.js 环境
699
+ - 📚 **完整文档** - 详细的使用示例和API说明
700
+
701
+ ## 许可证
702
+
703
+ MIT License
12
704
 
package/lib/index.d.ts CHANGED
@@ -279,11 +279,14 @@ export declare function fnRuntime(fn: any, iterations?: number): void;
279
279
  * @return formData 对象
280
280
  */
281
281
  export declare function objToFormData(obj: any, simplify?: boolean): FormData;
282
- /** 2025/3/24 11:19 User: DJ
283
- * content: 自动格式化大小
284
- * @param num number 需要转化的数字
285
- * @param option {decimals:'保留的小数',sizes:单位数组}
286
- * formatSize(1024,{sizes:['KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']})=1kb
282
+ /**
283
+ * 转换大小默认是文件可以是别的
284
+ * @param num - 需要转化的字节数
285
+ * @param option - 配置选项
286
+ * @param option.decimals - 保留小数位数,默认为2位
287
+ * @param option.sizes - 单位数组,默认为 ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']
288
+ * @param option.perUnit - 转换进制,默认为1024
289
+ * @returns 格式化后的文件大小字符串
287
290
  */
288
291
  export declare function formatSize(num: any, option?: any): string;
289
292
  /** 2025/4/23 15:59 User: DJ
package/lib/index.js CHANGED
@@ -1 +1 @@
1
- function e(e){let t={};return e.forEach((function(e){t[JSON.stringify(e)]=e})),e=Object.keys(t).map((function(e){if("undefined"!=e)return JSON.parse(e)}))}function t(e){let t=!1;switch(Object.prototype.toString.call(e).slice(8,-1)){case"Undefined":case"Null":t=!0;break;case"String":t=0===e.replace(/(^[ \t\n\r]*)|([ \t\n\r]*$)/g,"").length;break;case"Boolean":t=!e;break;case"Array":t=0===e.length;break;case"Number":t=0===e||isNaN(e);break;case"Object":t=0===Object.keys(e).length}return t}function r(e){return Object.prototype.toString.call(e).slice(8,-1)}function n(){return!t(navigator.userAgent.match(/(phone|pad|pod|iPhone|iPod|ios|iPad|Android|Mobile|BlackBerry|IEMobile|MQQBrowser|JUC|Fennec|wOSBrowser|BrowserNG|WebOS|Symbian|Windows Phone)/i))}function o(e,t){return Math.round(Math.random()*(t-e))+e}function s(e){let t=e+"";const r=Number(t);return!isNaN(r)&&t.length>0}function c(e=[],t,r=!1){if(r)return e.indexOf(t);{let r=-1,n=e.length;for(let o=0;o<n;o++)e[o]==t&&(r=o);return r}}Object.defineProperty(exports,"__esModule",{value:!0}),exports.memoize=void 0,exports.del_repeat=e,exports.formatDate=function(e,t="day",r="-"){let n=e.getFullYear(),o=(e.getMonth()+1).toString().padStart(2,"0"),s=e.getDate().toString().padStart(2,"0"),c=e.getHours().toString().padStart(2,"0"),i=e.getMinutes().toString().padStart(2,"0"),a={year:1,month:2,day:3,hour:4,minute:5},l="";for(let e=0;e<a[t];e++)0==e&&(l+=n),1==e&&(l+=o),2==e&&(l+=s),3==e&&(l+=c),4==e&&(l+=i),e!=a[t]-1&&(l+=r);return l},exports.time_change=function(e){return Date.parse(e)},exports.formatTime=function(e,t="YYYY-MM-DD hh:mm:ss",r={}){try{e=e.replaceAll("-","/")}catch(e){}e=new Date(e);let n={0:"周日",1:"周一",2:"周二",3:"周三",4:"周四",5:"周五",6:"周六"},{weeks:o=n}=r,s=e.getFullYear(),c=(e.getMonth()+1).toString().padStart(2,"0"),i=e.getDate().toString().padStart(2,"0"),a=e.getHours().toString().padStart(2,"0"),l=e.getMinutes().toString().padStart(2,"0"),u=e.getSeconds().toString().padStart(2,"0"),p=o[e.getDay()],f=t;return[{format:"YYYY",data:s},{format:"yyyy",data:s},{format:"MM",data:c},{format:"DD",data:i},{format:"dd",data:i},{format:"hh",data:a},{format:"HH",data:a},{format:"mm",data:l},{format:"ss",data:u},{format:"week",data:p},{format:"time_slot",data:a>12?"下午":"上午"}].forEach((function(e,r){-1!=t.indexOf(e.format)&&(f=f.replace(e.format,""+e.data))})),f},exports.getDaysBetween=function(e,t,r=!1){var n=Date.parse(e),o=Date.parse(t),s=0;n>o&&(s=(n-o)/864e5);n<o&&(s=(o-n)/864e5,r&&(s=-s));return s},exports.is_empty=t,exports.repalce=function(e,t,r){return e.substring(0,t)+r+e.substring(t+1)},exports.toGetQuery=function(e,n={}){if(t(e))return"";{let{prefix:o="?"}=n,s=[],c=["",void 0,null];const i=(e,n="")=>{const o=Object.keys(e);for(const a of o){const o=e[a];if(c.includes(o))continue;let l=r(o),u=encodeURIComponent(a);if(t(n)||(u=`${n}[${u}]`),"Array"===l)for(const e of o)s.push(`${u}[]=${encodeURIComponent(e)}`);else if("Object"===l)i(o,u);else{let e=encodeURIComponent(o);s.push(`${u}=${e}`)}}};return i(e),s.length?o+s.join("&"):""}},exports.isLink=function(e){const t=e.indexOf("://");if(-1===t)return!1;const r=e.slice(0,t+1);return-1!==c(["http:","https:","ftp:","file:"],r.toLowerCase())},exports.merge=function(t,r){const n=Object.prototype.toString.call(t);if("Array"==n.slice(8,-1))return t.push.apply(t,r),e(t);if("Object"==n.slice(8,-1))return Object.assign(t,r)},exports.is=r,exports.unique=function(r){if(0==t(r)){let t=e(r);return console.log(t),t}return console.log(!1),!1},exports.first=function(e){if(0!=t(e))return console.log(!1),!1;if("[object Object]"===Object.prototype.toString.call(e))for(const t of e)return console.log(t),t;else console.log(e[0])},exports.last=function(e){if(0!=t(e))return console.log(!1),!1;if("[object Object]"===Object.prototype.toString.call(e))for(const t of e)console.log(t);else console.log(e[e.length-1])},exports.findByIndex=function(e,t,r){return(e||[]).findIndex((e=>e[t]===r))},exports.setObjData=function(e,t,r,n,o){try{return e.find((function(e){return e[t]==r}))[n]=o,!0}catch(e){return!1}},exports.selectObjData=function(e,t,r){try{return e.find((function(e){return e[t]==r}))}catch(e){return""}},exports.handleTree=function(e,t,r,n){const o={id:t||"id",parentId:r||"parentId",childrenList:n||"children"},s=new Map,c=new Map,i=[];let a=e.length;for(let t=0;t<a;t++){let r=e[t];const n=r[o.parentId];s.has(n)||s.set(n,[]),c.set(r[o.id],r),s.get(n).push(r)}for(let t=0;t<a;t++){let r=e[t];const n=r[o.parentId];c.has(n)||i.push(r)}const l=[...i];for(;l.length>0;){const e=l.pop(),t=s.get(e[o.id]);t&&(e[o.childrenList]=t,l.push(...t))}return i},exports.arrToTree=function(e,t={}){let{id:r="id",pKey:n="parentId",cKey:o="children",strict:s=!0,copy:c=!0}=t,i=[];i=c?JSON.parse(JSON.stringify(e)):e;return i.filter((e=>{const t=i.filter((t=>s?t[n]===e[r]:t[n]==e[r]));return t.length&&(e[o]=t),0===e[n]}))},exports.treeToArr=function(e,t={}){let r=[],{cKey:n="children",copy:o=!0}=t,s=[...e];for(;s.length;){let e=s.pop();if(e[n])if(s.push(...e[n]),o){let t={},o=Object.keys(e),s=o.length;for(let r=0;r<s;r++)o[r]!=n&&(t[o[r]]=e[o[r]]);r.push(t)}else r.push(e)}return r},exports.treeFor=function(e,r,n={}){let{cKey:o="children"}=n,s=[...e];for(;s.length;){let e=s.shift();t(e[o])?r&&r(e):s.push(...e[o])}},exports.treeStack=function(e,r,n={}){let{cKey:o="children"}=n,s=[...e];for(;s.length;){let e=s.shift();t(e[o])?r&&r(e):s.push(...e[o])}},exports.treeRecursion=function(e,t,r={}){},exports.treeFind=function(e,t={}){let r=[],{cKey:n="children",key:o="id",value:s,copy:c=!0}=t,i=[...e];for(;i.length;){let e=i.pop();if(e[n]&&i.push(...e[n]),e[o]==s)if(c){let t={},o=Object.keys(e),s=o.length;for(let r=0;r<s;r++)o[r]!=n&&(t[o[r]]=e[o[r]]);r.push(t)}else r.push(e)}return r},exports.base64Img=function(e,t){return r=function(e){for(var t=e.split(","),r=t[0].match(/:(.*?);/)[1],n=atob(t[1]),o=n.length,s=new Uint8Array(o);o--;)s[o]=n.charCodeAt(o);return new Blob([s],{type:r})}(e),n=t,new File([r],n);var r,n},exports.compareDate=function(e,t="up"){return function(r,n){return"up"==t?Date.parse(r[e])-Date.parse(n[e]):Date.parse(n[e])-Date.parse(r[e])}},exports.compare=function(e,t="up"){return function(r,n){return"up"==t?r[e]-n[e]:n[e]-r[e]}},exports.numberRepair=function(e="",t=2,r="0",n=!1){let o="",s=(""+e).length;if(s>t&&1==n)return s;{let n=t-s;if(n>0)for(let e=0;e<n;e++)o+=r;return(o+e).slice(-1*t)}},exports.isMobile=n,exports.setMeta=function(e){if(!t(e)){let t=[];document.head.childNodes.forEach((r=>{switch(r.tagName){case"META":t.push(r);break;case"TITLE":document.title=e.title||"模板测试"}}));const r=document.createElement("META");let o=1,s="yes";e.cZoom&&(n()?e.cZoom.mobile&&(o=e.cZoom.mobile):e.cZoom.pc&&(o=e.cZoom.pc),e.cZoom.isScale&&(s=e.cZoom.isScale));let c=`width=device-width,minimum-scale=${o},initial-scale=${o},user-scalable=${s}`;"no"==s&&(c+=`,maximum-scale=${o}`);const i=[{charset:"utf-8"},{name:"viewport",content:c}],a=document.createDocumentFragment();i.forEach((e=>{a.append(r.cloneNode()),Object.entries(e).forEach((e=>{a.lastChild.setAttribute(e[0],e[1])}))})),t.forEach((e=>{document.head.removeChild(e)})),document.head.prepend(a)}},exports.colorMix=function(e,t,r){r=Math.max(Math.min(Number(r),1),0);let n=parseInt(e.substring(1,3),16),o=parseInt(e.substring(3,5),16),s=parseInt(e.substring(5,7),16),c=parseInt(t.substring(1,3),16),i=parseInt(t.substring(3,5),16),a=parseInt(t.substring(5,7),16),l=Math.round(n*(1-r)+c*r),u=Math.round(o*(1-r)+i*r),p=Math.round(s*(1-r)+a*r);return l=("0"+(l||0).toString(16)).slice(-2),u=("0"+(u||0).toString(16)).slice(-2),p=("0"+(p||0).toString(16)).slice(-2),"#"+l+u+p},exports.sArrMove=function(e,t,r){e.splice(r,0,e.splice(t,1)[0])},exports.rArrMove=function(e,t,r){let n=[].concat(e);return n.splice(r,0,n.splice(t,1)[0]),n},exports.arrSet=function(e,t,r){e.splice(t,0,r)},exports.randomColor=function(){let e=o(100,255),t=o(100,255),r=o(100,255);return"rgba("+e+","+t+","+r+",1)"},exports.randomNumber=o,exports.isDateInRange=function(e,t,r){const n=new Date(e),o=new Date(t),s=new Date(r);return n>=o&&n<=s},exports.throttle1=function(e,t){let r,n=0;return function(...o){const s=Date.now(),c=s-n;clearTimeout(r),c>=t?(e(...o),n=s):r=setTimeout((()=>{e(...o),n=Date.now()}),t-c)}},exports.throttle=function(e,t=1e3,r=!0){let n;const o=(...o)=>{n&&clearInterval(n),r?(n||e(...o),n=setTimeout((function(){n=null}),t)):n=setTimeout((()=>{e(...o)}),t)};return o.cancel=()=>{n&&(clearTimeout(n),n=null)},o},exports.debounce=function(e,t){let r;const n=function(...n){clearTimeout(r),r=setTimeout((()=>{e(...n)}),t)};return n.cancel=()=>{r&&(clearTimeout(r),r=null)},n},exports.arrayGroup=function(e,t="type"){return e.reduce(((e,r)=>{var n;return Object.assign(Object.assign({},e),{[r[t]]:[...null!==(n=e[r[t]])&&void 0!==n?n:[],r]})}),{})},exports.numberFixed=function(e,t=1){const r=e.toString(),n=r.indexOf(".");if(-1===n)return e;const o=r.slice(0,n+1+t);return parseFloat(o)},exports.delObj=function(e,n=""){try{if(t(n)){let t=Object.keys(e);for(let r of t)delete e[r]}else if("Array"==r(n))for(const t of n)delete e[t];else delete e[n]}catch(e){}},exports.delObjEmptyKey=function(e){try{let n=Object.keys(e);for(let o of n)"Number"!=r(e[o])&&t(e[o])&&delete e[o]}catch(e){}},exports.isNum=s,exports.pxToRem=function(e,t=37.5){let r=e;if(s(e)||-1!=e.indexOf("px")){r=(parseFloat(e)/t).toFixed(2)+"rem"}return r},exports.inArr=c,exports.fnRuntime=function(e,t=1){let r=0;for(let n=0;n<t;n++){const t=performance.now();e();r+=performance.now()-t}const n=r/t;console.log(`平均执行时间 ${t} 次数: ${n.toFixed(6)} ms`)},exports.objToFormData=function(e,t=!0){let n=new FormData;return function e(o,s="",c={}){let{level:i=0,pk:a="",type:l=""}=c,u=r(o);if(-1==["Array","Object"].indexOf(u)){if(null!=o){let e=s;t&&2==i&&"Array"==l&&(e=a),n.append(e,o)}}else if("Array"==u){let t=o.length;for(let r=0;r<t;r++){let t=`${s}[${r}]`,n={level:i+1,type:"Array",pk:s};e(o[r],t,n)}}else if("Object"==u){let t=Object.keys(o),r={level:i+1,type:"Object",pk:s};for(const n of t)e(o[n],`${s}${""==s?"":"."}${n}`,r)}}(e),n},exports.formatSize=function(e,t={}){if(0===e)return"0 Bytes";let{decimals:r=2,sizes:n=["Bytes","KB","MB","GB","TB","PB","EB","ZB","YB"]}=t;const o=r<0?0:r,s=Math.floor(Math.log(e)/Math.log(1024));return parseFloat((e/Math.pow(1024,s)).toFixed(o))+" "+n[s]},exports.arrToAryTree=function(e,t={}){let{idKey:r="id",pidKey:n="pid",rKey:o="rgt",lKey:s="lft",levelKey:c="level"}=t;const i={},a={};let l=e.length;for(let t=0;t<l;t++){let o=e[t],s=o[n],c=o[r];i[c]=Object.assign({},o),a[s]||(a[s]=[]),a[s].push(c)}const u=Object.keys(a),p=Object.keys(i),f=new Set(p);let d=[];u.filter((e=>{f.has(e)||d.push(...a[e])}));let h=1;const m=[],g=[];for(let e=d.length-1;e>=0;e--)m.push({[r]:d[e],[c]:1,processed:!1});for(;m.length>0;){const e=m.pop(),t=i[e[r]];if(e.processed)t[o]=h++,g.push(t);else if(t[s]=h++,t[c]=e[c],m.push({[r]:e[r],[c]:e[c],processed:!0}),a[e[r]])for(let t=a[e[r]].length-1;t>=0;t--)m.push({[r]:a[e[r]][t],[c]:e[c]+1,processed:!1})}return g},exports.mergeObj=function(e,t={}){let{callback:n=null,callType:o="",afterBack:s=null}=t,c={};function i(e,t){let c=Object.keys(e);for(const a of c){let c=r(e[a]);n&&c==o?t[a]=n(e,a):"Object"===c?(t[a]||(t[a]={}),i(e[a],t[a])):t[a]=e[a],s&&s(t,a)}}for(const t of e)i(t,c);return c},Number.prototype.repair=function(e=2){let t="";for(let r=1;r<e;r++)t+="0";return(t+this).slice(-1*e)};exports.memoize=(e,t={})=>{const{context:r=null,ttl:n=0}=t,o=new Map,s=e=>{if("object"==typeof e&&null!==e){if(Array.isArray(e))return`[${e.map(s).join(",")}]`;return`{${Object.keys(e).sort().map((t=>`${t}:${s(e[t])}`)).join(",")}}`}return String(e)};return(...t)=>{const c=s(t),i=o.get(c);if(i&&(0===n||Date.now()-i.timestamp<=n))return i.value;const a=r?e.apply(r,t):e(...t);return o.set(c,{value:a,timestamp:Date.now()}),a}};
1
+ function e(e){let t={};return e.forEach((function(e){t[JSON.stringify(e)]=e})),e=Object.keys(t).map((function(e){if("undefined"!=e)return JSON.parse(e)}))}function t(e){let t=!1;switch(Object.prototype.toString.call(e).slice(8,-1)){case"Undefined":case"Null":t=!0;break;case"String":t=0===e.replace(/(^[ \t\n\r]*)|([ \t\n\r]*$)/g,"").length;break;case"Boolean":t=!e;break;case"Array":t=0===e.length;break;case"Number":t=0===e||isNaN(e);break;case"Object":t=0===Object.keys(e).length}return t}function r(e){return Object.prototype.toString.call(e).slice(8,-1)}function n(){return!t(navigator.userAgent.match(/(phone|pad|pod|iPhone|iPod|ios|iPad|Android|Mobile|BlackBerry|IEMobile|MQQBrowser|JUC|Fennec|wOSBrowser|BrowserNG|WebOS|Symbian|Windows Phone)/i))}function o(e,t){return Math.round(Math.random()*(t-e))+e}function s(e){let t=e+"";const r=Number(t);return!isNaN(r)&&t.length>0}function c(e=[],t,r=!1){if(r)return e.indexOf(t);{let r=-1,n=e.length;for(let o=0;o<n;o++)e[o]==t&&(r=o);return r}}Object.defineProperty(exports,"__esModule",{value:!0}),exports.memoize=void 0,exports.del_repeat=e,exports.formatDate=function(e,t="day",r="-"){let n=e.getFullYear(),o=(e.getMonth()+1).toString().padStart(2,"0"),s=e.getDate().toString().padStart(2,"0"),c=e.getHours().toString().padStart(2,"0"),i=e.getMinutes().toString().padStart(2,"0"),a={year:1,month:2,day:3,hour:4,minute:5},l="";for(let e=0;e<a[t];e++)0==e&&(l+=n),1==e&&(l+=o),2==e&&(l+=s),3==e&&(l+=c),4==e&&(l+=i),e!=a[t]-1&&(l+=r);return l},exports.time_change=function(e){return Date.parse(e)},exports.formatTime=function(e,t="YYYY-MM-DD hh:mm:ss",r={}){try{e=e.replaceAll("-","/")}catch(e){}e=new Date(e);let n={0:"周日",1:"周一",2:"周二",3:"周三",4:"周四",5:"周五",6:"周六"},{weeks:o=n}=r,s=e.getFullYear(),c=(e.getMonth()+1).toString().padStart(2,"0"),i=e.getDate().toString().padStart(2,"0"),a=e.getHours().toString().padStart(2,"0"),l=e.getMinutes().toString().padStart(2,"0"),u=e.getSeconds().toString().padStart(2,"0"),p=o[e.getDay()],f=t;return[{format:"YYYY",data:s},{format:"yyyy",data:s},{format:"MM",data:c},{format:"DD",data:i},{format:"dd",data:i},{format:"hh",data:a},{format:"HH",data:a},{format:"mm",data:l},{format:"ss",data:u},{format:"week",data:p},{format:"time_slot",data:a>12?"下午":"上午"}].forEach((function(e,r){-1!=t.indexOf(e.format)&&(f=f.replace(e.format,""+e.data))})),f},exports.getDaysBetween=function(e,t,r=!1){var n=Date.parse(e),o=Date.parse(t),s=0;n>o&&(s=(n-o)/864e5);n<o&&(s=(o-n)/864e5,r&&(s=-s));return s},exports.is_empty=t,exports.repalce=function(e,t,r){return e.substring(0,t)+r+e.substring(t+1)},exports.toGetQuery=function(e,n={}){if(t(e))return"";{let{prefix:o="?"}=n,s=[],c=["",void 0,null];const i=(e,n="")=>{const o=Object.keys(e);for(const a of o){const o=e[a];if(c.includes(o))continue;let l=r(o),u=encodeURIComponent(a);if(t(n)||(u=`${n}[${u}]`),"Array"===l)for(const e of o)s.push(`${u}[]=${encodeURIComponent(e)}`);else if("Object"===l)i(o,u);else{let e=encodeURIComponent(o);s.push(`${u}=${e}`)}}};return i(e),s.length?o+s.join("&"):""}},exports.isLink=function(e){const t=e.indexOf("://");if(-1===t)return!1;const r=e.slice(0,t+1);return-1!==c(["http:","https:","ftp:","file:"],r.toLowerCase())},exports.merge=function(t,r){const n=Object.prototype.toString.call(t);if("Array"==n.slice(8,-1))return t.push.apply(t,r),e(t);if("Object"==n.slice(8,-1))return Object.assign(t,r)},exports.is=r,exports.unique=function(r){if(0==t(r)){let t=e(r);return console.log(t),t}return console.log(!1),!1},exports.first=function(e){if(0!=t(e))return console.log(!1),!1;if("[object Object]"===Object.prototype.toString.call(e))for(const t of e)return console.log(t),t;else console.log(e[0])},exports.last=function(e){if(0!=t(e))return console.log(!1),!1;if("[object Object]"===Object.prototype.toString.call(e))for(const t of e)console.log(t);else console.log(e[e.length-1])},exports.findByIndex=function(e,t,r){return(e||[]).findIndex((e=>e[t]===r))},exports.setObjData=function(e,t,r,n,o){try{return e.find((function(e){return e[t]==r}))[n]=o,!0}catch(e){return!1}},exports.selectObjData=function(e,t,r){try{return e.find((function(e){return e[t]==r}))}catch(e){return""}},exports.handleTree=function(e,t,r,n){const o={id:t||"id",parentId:r||"parentId",childrenList:n||"children"},s=new Map,c=new Map,i=[];let a=e.length;for(let t=0;t<a;t++){let r=e[t];const n=r[o.parentId];s.has(n)||s.set(n,[]),c.set(r[o.id],r),s.get(n).push(r)}for(let t=0;t<a;t++){let r=e[t];const n=r[o.parentId];c.has(n)||i.push(r)}const l=[...i];for(;l.length>0;){const e=l.pop(),t=s.get(e[o.id]);t&&(e[o.childrenList]=t,l.push(...t))}return i},exports.arrToTree=function(e,t={}){let{id:r="id",pKey:n="parentId",cKey:o="children",strict:s=!0,copy:c=!0}=t,i=[];i=c?JSON.parse(JSON.stringify(e)):e;return i.filter((e=>{const t=i.filter((t=>s?t[n]===e[r]:t[n]==e[r]));return t.length&&(e[o]=t),0===e[n]}))},exports.treeToArr=function(e,t={}){let r=[],{cKey:n="children",copy:o=!0}=t,s=[...e];for(;s.length;){let e=s.pop();if(e[n])if(s.push(...e[n]),o){let t={},o=Object.keys(e),s=o.length;for(let r=0;r<s;r++)o[r]!=n&&(t[o[r]]=e[o[r]]);r.push(t)}else r.push(e)}return r},exports.treeFor=function(e,r,n={}){let{cKey:o="children"}=n,s=[...e];for(;s.length;){let e=s.shift();t(e[o])?r&&r(e):s.push(...e[o])}},exports.treeStack=function(e,r,n={}){let{cKey:o="children"}=n,s=[...e];for(;s.length;){let e=s.shift();t(e[o])?r&&r(e):s.push(...e[o])}},exports.treeRecursion=function(e,t,r={}){},exports.treeFind=function(e,t={}){let r=[],{cKey:n="children",key:o="id",value:s,copy:c=!0}=t,i=[...e];for(;i.length;){let e=i.pop();if(e[n]&&i.push(...e[n]),e[o]==s)if(c){let t={},o=Object.keys(e),s=o.length;for(let r=0;r<s;r++)o[r]!=n&&(t[o[r]]=e[o[r]]);r.push(t)}else r.push(e)}return r},exports.base64Img=function(e,t){return r=function(e){for(var t=e.split(","),r=t[0].match(/:(.*?);/)[1],n=atob(t[1]),o=n.length,s=new Uint8Array(o);o--;)s[o]=n.charCodeAt(o);return new Blob([s],{type:r})}(e),n=t,new File([r],n);var r,n},exports.compareDate=function(e,t="up"){return function(r,n){return"up"==t?Date.parse(r[e])-Date.parse(n[e]):Date.parse(n[e])-Date.parse(r[e])}},exports.compare=function(e,t="up"){return function(r,n){return"up"==t?r[e]-n[e]:n[e]-r[e]}},exports.numberRepair=function(e="",t=2,r="0",n=!1){let o="",s=(""+e).length;if(s>t&&1==n)return s;{let n=t-s;if(n>0)for(let e=0;e<n;e++)o+=r;return(o+e).slice(-1*t)}},exports.isMobile=n,exports.setMeta=function(e){if(!t(e)){let t=[];document.head.childNodes.forEach((r=>{switch(r.tagName){case"META":t.push(r);break;case"TITLE":document.title=e.title||"模板测试"}}));const r=document.createElement("META");let o=1,s="yes";e.cZoom&&(n()?e.cZoom.mobile&&(o=e.cZoom.mobile):e.cZoom.pc&&(o=e.cZoom.pc),e.cZoom.isScale&&(s=e.cZoom.isScale));let c=`width=device-width,minimum-scale=${o},initial-scale=${o},user-scalable=${s}`;"no"==s&&(c+=`,maximum-scale=${o}`);const i=[{charset:"utf-8"},{name:"viewport",content:c}],a=document.createDocumentFragment();i.forEach((e=>{a.append(r.cloneNode()),Object.entries(e).forEach((e=>{a.lastChild.setAttribute(e[0],e[1])}))})),t.forEach((e=>{document.head.removeChild(e)})),document.head.prepend(a)}},exports.colorMix=function(e,t,r){r=Math.max(Math.min(Number(r),1),0);let n=parseInt(e.substring(1,3),16),o=parseInt(e.substring(3,5),16),s=parseInt(e.substring(5,7),16),c=parseInt(t.substring(1,3),16),i=parseInt(t.substring(3,5),16),a=parseInt(t.substring(5,7),16),l=Math.round(n*(1-r)+c*r),u=Math.round(o*(1-r)+i*r),p=Math.round(s*(1-r)+a*r);return l=("0"+(l||0).toString(16)).slice(-2),u=("0"+(u||0).toString(16)).slice(-2),p=("0"+(p||0).toString(16)).slice(-2),"#"+l+u+p},exports.sArrMove=function(e,t,r){e.splice(r,0,e.splice(t,1)[0])},exports.rArrMove=function(e,t,r){let n=[].concat(e);return n.splice(r,0,n.splice(t,1)[0]),n},exports.arrSet=function(e,t,r){e.splice(t,0,r)},exports.randomColor=function(){let e=o(100,255),t=o(100,255),r=o(100,255);return"rgba("+e+","+t+","+r+",1)"},exports.randomNumber=o,exports.isDateInRange=function(e,t,r){const n=new Date(e),o=new Date(t),s=new Date(r);return n>=o&&n<=s},exports.throttle1=function(e,t){let r,n=0;return function(...o){const s=Date.now(),c=s-n;clearTimeout(r),c>=t?(e(...o),n=s):r=setTimeout((()=>{e(...o),n=Date.now()}),t-c)}},exports.throttle=function(e,t=1e3,r=!0){let n;const o=(...o)=>{n&&clearInterval(n),r?(n||e(...o),n=setTimeout((function(){n=null}),t)):n=setTimeout((()=>{e(...o)}),t)};return o.cancel=()=>{n&&(clearTimeout(n),n=null)},o},exports.debounce=function(e,t){let r;const n=function(...n){clearTimeout(r),r=setTimeout((()=>{e(...n)}),t)};return n.cancel=()=>{r&&(clearTimeout(r),r=null)},n},exports.arrayGroup=function(e,t="type"){return e.reduce(((e,r)=>{var n;return Object.assign(Object.assign({},e),{[r[t]]:[...null!==(n=e[r[t]])&&void 0!==n?n:[],r]})}),{})},exports.numberFixed=function(e,t=1){const r=e.toString(),n=r.indexOf(".");if(-1===n)return e;const o=r.slice(0,n+1+t);return parseFloat(o)},exports.delObj=function(e,n=""){try{if(t(n)){let t=Object.keys(e);for(let r of t)delete e[r]}else if("Array"==r(n))for(const t of n)delete e[t];else delete e[n]}catch(e){}},exports.delObjEmptyKey=function(e){try{let n=Object.keys(e);for(let o of n)"Number"!=r(e[o])&&t(e[o])&&delete e[o]}catch(e){}},exports.isNum=s,exports.pxToRem=function(e,t=37.5){let r=e;if(s(e)||-1!=e.indexOf("px")){r=(parseFloat(e)/t).toFixed(2)+"rem"}return r},exports.inArr=c,exports.fnRuntime=function(e,t=1){let r=0;for(let n=0;n<t;n++){const t=performance.now();e();r+=performance.now()-t}const n=r/t;console.log(`平均执行时间 ${t} 次数: ${n.toFixed(6)} ms`)},exports.objToFormData=function(e,t=!0){let n=new FormData;return function e(o,s="",c={}){let{level:i=0,pk:a="",type:l=""}=c,u=r(o);if(-1==["Array","Object"].indexOf(u)){if(null!=o){let e=s;t&&2==i&&"Array"==l&&(e=a),n.append(e,o)}}else if("Array"==u){let t=o.length;for(let r=0;r<t;r++){let t=`${s}[${r}]`,n={level:i+1,type:"Array",pk:s};e(o[r],t,n)}}else if("Object"==u){let t=Object.keys(o),r={level:i+1,type:"Object",pk:s};for(const n of t)e(o[n],`${s}${""==s?"":"."}${n}`,r)}}(e),n},exports.formatSize=function(e,t={}){let{decimals:r=2,sizes:n=["Bytes","KB","MB","GB","TB","PB","EB","ZB","YB"],perUnit:o=1024}=t;if(0===e)return"0"+n[0];const s=r<0?0:r,c=Math.floor(Math.log(e)/Math.log(o));return parseFloat((e/Math.pow(o,c)).toFixed(s))+" "+n[c]},exports.arrToAryTree=function(e,t={}){let{idKey:r="id",pidKey:n="pid",rKey:o="rgt",lKey:s="lft",levelKey:c="level"}=t;const i={},a={};let l=e.length;for(let t=0;t<l;t++){let o=e[t],s=o[n],c=o[r];i[c]=Object.assign({},o),a[s]||(a[s]=[]),a[s].push(c)}const u=Object.keys(a),p=Object.keys(i),f=new Set(p);let d=[];u.filter((e=>{f.has(e)||d.push(...a[e])}));let h=1;const m=[],g=[];for(let e=d.length-1;e>=0;e--)m.push({[r]:d[e],[c]:1,processed:!1});for(;m.length>0;){const e=m.pop(),t=i[e[r]];if(e.processed)t[o]=h++,g.push(t);else if(t[s]=h++,t[c]=e[c],m.push({[r]:e[r],[c]:e[c],processed:!0}),a[e[r]])for(let t=a[e[r]].length-1;t>=0;t--)m.push({[r]:a[e[r]][t],[c]:e[c]+1,processed:!1})}return g},exports.mergeObj=function(e,t={}){let{callback:n=null,callType:o="",afterBack:s=null}=t,c={};function i(e,t){let c=Object.keys(e);for(const a of c){let c=r(e[a]);n&&c==o?t[a]=n(e,a):"Object"===c?(t[a]||(t[a]={}),i(e[a],t[a])):t[a]=e[a],s&&s(t,a)}}for(const t of e)i(t,c);return c},Number.prototype.repair=function(e=2){let t="";for(let r=1;r<e;r++)t+="0";return(t+this).slice(-1*e)};exports.memoize=(e,t={})=>{const{context:r=null,ttl:n=0}=t,o=new Map,s=e=>{if("object"==typeof e&&null!==e){if(Array.isArray(e))return`[${e.map(s).join(",")}]`;return`{${Object.keys(e).sort().map((t=>`${t}:${s(e[t])}`)).join(",")}}`}return String(e)};return(...t)=>{const c=s(t),i=o.get(c);if(i&&(0===n||Date.now()-i.timestamp<=n))return i.value;const a=r?e.apply(r,t):e(...t);return o.set(c,{value:a,timestamp:Date.now()}),a}};
package/lib/request.d.ts CHANGED
@@ -1,32 +1,34 @@
1
+ /**
2
+ * 请求配置接口
3
+ */
1
4
  interface conf {
5
+ /** 请求的基础URL前缀 */
2
6
  baseUrl?: string;
7
+ /** 请求超时时间,单位毫秒,默认6000ms */
3
8
  timeout?: number;
4
- callback?: any;
5
- errBack?: any;
6
- abController?: any;
7
- beforeBack?: any;
9
+ /** 请求成功后的回调函数,可以处理响应数据 */
10
+ callback?: (response: Response) => Promise<any> | any;
11
+ /** 请求失败时的错误处理回调函数 */
12
+ errBack?: (error: Error) => void;
13
+ /** 获取AbortController实例的回调,用于手动中断请求 */
14
+ abController?: (controller: AbortController) => void;
15
+ /** 请求发送前的预处理回调,可以修改请求选项 */
16
+ beforeBack?: (options: any) => void;
8
17
  }
9
- /** 2025/3/31 15:54 User: DJ
10
- * content: fetch请求
11
- * method: "POST"
12
- * 指定 HTTP 请求方法。在这里是 POST,意味着客户端请求是为了向服务器发送数据。与之相对的还有 GET、PUT、DELETE 等方法。
13
- * mode: "cors"
14
- * 这个设置指定请求的跨域策略。cors 是跨源资源共享(Cross-Origin Resource Sharing)的缩写。当使用 cors 时,浏览器允许在不同域之间发起请求。如果不设置,默认值通常是 same-origin,即只允许发起同源请求(即 URL 与当前页面相同的请求)。
15
- * cache: "no-cache"
16
- * 缓存策略,设置为 no-cache 时,意味着不使用缓存,每次请求都会从服务器获取最新的数据。其他常见的值有 default(默认策略)、reload(重新加载)、force-cache(强制使用缓存)等。
17
- * credentials: "same-origin"
18
- * 这个设置决定了请求是否包含凭证信息(如 Cookies)。same-origin 表示仅在同源请求中发送凭证信息。如果设置为 include,即使是跨域请求,也会发送凭证。如果设置为 omit,则无论请求是否跨域,均不会发送凭证。
19
- * headers: { "Content-Type": "application/json" }
20
- * 请求头,Content-Type 表示请求体的内容类型。在这里,我们将其设置为 application/json,表示请求体的数据是 JSON 格式。其他常见的类型包括 application/x-www-form-urlencoded、multipart/form-data 等。
21
- * redirect: "follow"
22
- * 这个设置指定如何处理 HTTP 重定向。follow 表示如果服务器返回重定向响应(如 301 或 302),浏览器会自动跟随该重定向。其他选项包括 manual(需要手动处理重定向)和 error(遇到重定向直接报错)。
23
- * referrerPolicy: "no-referrer"
24
- * 这个设置控制请求的引用来源信息(Referrer)的处理方式。no-referrer 表示不发送任何引用来源信息。其他常见的选项有:
25
- * no-referrer-when-downgrade(只有在从 HTTPS 到 HTTP 的情况下才不发送引用信息)
26
- * origin(仅发送源信息)
27
- * strict-origin(仅在 HTTPS 请求中发送完整的引用信息)
28
- * body: JSON.stringify(data)
29
- * 请求的主体内容。我们将 data 对象转化为 JSON 字符串发送到服务器。body 是 POST 请求的主要部分,用来发送需要提交的数据。在这里,我们通过 JSON.stringify(data) 将 JavaScript 对象转换为 JSON 字符串。
18
+ /**
19
+ * Fetch请求客户端类
20
+ * @description 基于fetch API的HTTP请求封装,支持超时、拦截器、错误处理等功能
21
+ * 支持的fetch配置项:
22
+ * - method: HTTP请求方法 (GET, POST, PUT, DELETE等)
23
+ * - mode: 跨域策略 ("cors", "same-origin", "no-cors")
24
+ * - cache: 缓存策略 ("no-cache", "default", "reload", "force-cache")
25
+ * - credentials: 凭证策略 ("same-origin", "include", "omit")
26
+ * - headers: 请求头,如 {"Content-Type": "application/json"}
27
+ * - redirect: 重定向处理 ("follow", "manual", "error")
28
+ * - referrerPolicy: 引用策略 ("no-referrer", "origin", "strict-origin")
29
+ * - body: 请求体,通常使用 JSON.stringify(data) 转换对象
30
+ * @author DJ
31
+ * @since 2025/3/31
30
32
  */
31
33
  export default class {
32
34
  options: any;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tools_dj",
3
- "version": "1.0.82",
3
+ "version": "1.0.84",
4
4
  "description": "dj tools 工具库",
5
5
  "main": "./lib/index.js",
6
6
  "module": "./lib/index.js",