@base-web-kits/base-tools-web 1.2.6 → 1.2.7

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.
@@ -0,0 +1,640 @@
1
+ /**
2
+ * 复制文本到剪贴板(兼容移动端和PC)
3
+ * @returns Promise<void> 复制成功时 resolve,失败时 reject。
4
+ * @example
5
+ * await copyText('hello');
6
+ * toast('复制成功');
7
+ */
8
+ declare function copyText(text: string): Promise<void>;
9
+ /**
10
+ * 复制富文本 HTML 到剪贴板(移动端与 PC)
11
+ * 使用场景:图文混排文章、带样式段落,保留格式粘贴。
12
+ * @param html HTML字符串
13
+ * @example
14
+ * await copyHtml('<p><b>加粗</b> 与 <i>斜体</i></p>');
15
+ */
16
+ declare function copyHtml(html: string): Promise<void>;
17
+ /**
18
+ * 复制 DOM 节点到剪贴板(移动端与 PC)
19
+ * 使用场景:页面已有区域的可视化复制;元素使用 `outerHTML`,非元素使用其文本内容。
20
+ * @param node DOM 节点(元素或文本节点)
21
+ * @example
22
+ * const el = document.querySelector('#article')!;
23
+ * await copyNode(el);
24
+ */
25
+ declare function copyNode(node: Node): Promise<void>;
26
+ /**
27
+ * 复制单张图片到剪贴板(移动端与 PC,需浏览器支持 `ClipboardItem`)
28
+ * 使用场景:把本地 `canvas` 或 `Blob` 生成的图片直接粘贴到聊天/文档。
29
+ * @param image 图片源(Blob/Canvas/ImageBitmap)
30
+ * @example
31
+ * const canvas = document.querySelector('canvas')!;
32
+ * await copyImage(canvas);
33
+ */
34
+ declare function copyImage(image: Blob | HTMLCanvasElement | ImageBitmap): Promise<void>;
35
+ /**
36
+ * 复制 URL 到剪贴板(移动端与 PC)
37
+ * 写入 `text/uri-list` 与 `text/plain`,在支持 URI 列表的应用中可识别为链接。
38
+ * @param url 完整的 URL 字符串
39
+ * @example
40
+ * await copyUrl('https://example.com/page');
41
+ */
42
+ declare function copyUrl(url: string): Promise<void>;
43
+ /**
44
+ * 复制任意 Blob 到剪贴板(移动端与 PC,需 `ClipboardItem`)
45
+ * 使用场景:原生格式粘贴(如 `image/svg+xml`、`application/pdf` 等)。
46
+ * @param blob 任意 Blob 数据
47
+ * @example
48
+ * const svg = new Blob(['<svg></svg>'], { type: 'image/svg+xml' });
49
+ * await copyBlob(svg);
50
+ */
51
+ declare function copyBlob(blob: Blob): Promise<void>;
52
+ /**
53
+ * 复制 RTF 富文本到剪贴板(移动端与 PC)
54
+ * 同时写入 `text/plain`,增强与 Office/富文本编辑器的兼容性。
55
+ * @param rtf RTF 字符串(如:`{\\rtf1\\ansi ...}`)
56
+ * @example
57
+ * await copyRtf('{\\rtf1\\ansi Hello \\b World}');
58
+ */
59
+ declare function copyRtf(rtf: string): Promise<void>;
60
+ /**
61
+ * 复制表格到剪贴板(移动端与 PC)
62
+ * 同时写入多种 MIME:`text/html`(表格)、`text/tab-separated-values`(TSV)、`text/csv`、`text/plain`(TSV)。
63
+ * 使用场景:优化粘贴到 Excel/Google Sheets/Docs 的体验
64
+ * @param rows 二维数组,每行一个数组(字符串/数字)
65
+ * @example
66
+ * await copyTable([
67
+ * ['姓名', '分数'],
68
+ * ['张三', 95],
69
+ * ['李四', 88],
70
+ * ]);
71
+ */
72
+ declare function copyTable(rows: Array<Array<string | number>>): Promise<void>;
73
+
74
+ type AppConfig = {
75
+ /** 全局 Toast 提示 */
76
+ toast?: (option: {
77
+ msg: string;
78
+ status: 'success' | 'fail';
79
+ }) => void;
80
+ /** 显示全局 Loading */
81
+ showLoading?: (option?: {
82
+ title?: string;
83
+ }) => void;
84
+ /** 隐藏全局 Loading */
85
+ hideLoading?: () => void;
86
+ /** 跳转登录页的方法 */
87
+ toLogin?: () => void;
88
+ /** 日志记录函数 */
89
+ log?: (level: 'info' | 'error' | 'warn' | 'debug', data: AppLogInfo) => void;
90
+ };
91
+ type AppLogInfo = {
92
+ /** 调用函数的名称 */
93
+ name: string;
94
+ /** 函数的调用状态 */
95
+ status?: 'success' | 'fail';
96
+ /** 函数的调用参数 */
97
+ option?: unknown;
98
+ /** 函数的调用结果 */
99
+ res?: unknown;
100
+ /** 函数的调用错误 */
101
+ e?: unknown;
102
+ /** 日志描述 */
103
+ desc?: string;
104
+ [key: string]: unknown;
105
+ };
106
+ /**
107
+ * 获取应用配置
108
+ */
109
+ declare function getBaseToolsConfig(): AppConfig;
110
+ /**
111
+ * 初始化应用配置 (在入口文件设置)
112
+ * @example
113
+ * setBaseToolsConfig({
114
+ * toast: ({ msg, status }) => (status === 'fail' ? message.error(msg) : message.success(msg)),
115
+ * showLoading: () => message.loading('加载中...'),
116
+ * hideLoading: () => message.destroy(),
117
+ * toLogin: () => reLogin(),
118
+ * log(level, data) {
119
+ * if (data.name === 'request') {
120
+ * sendLog('request', data); // 请求日志
121
+ * } else if (level === 'error') {
122
+ * sendLog('error', data); // 错误日志
123
+ * } else {
124
+ * sendLog('action', data); // 操作日志
125
+ * }
126
+ * },
127
+ * });
128
+ */
129
+ declare function setBaseToolsConfig(newConfig: AppConfig): void;
130
+
131
+ /**
132
+ * 设置 Cookie(路径默认为 `/`)
133
+ * @param name Cookie 名称
134
+ * @param value Cookie 值(内部已使用 `encodeURIComponent` 编码)
135
+ * @param days 过期天数(从当前时间起算)
136
+ * @example
137
+ * setCookie('token', 'abc', 7);
138
+ */
139
+ declare function setCookie(name: string, value: string, days: number): void;
140
+ /**
141
+ * 获取 Cookie
142
+ * @param name Cookie 名称
143
+ * @returns 若存在返回解码后的值,否则 `null`
144
+ * @example
145
+ * const token = getCookie('token');
146
+ */
147
+ declare function getCookie(name: string): string | null;
148
+ /**
149
+ * 移除 Cookie(通过设置过期时间为过去)
150
+ * 路径固定为 `/`,确保与默认写入路径一致。
151
+ * @param name Cookie 名称
152
+ * @example
153
+ * removeCookie('token');
154
+ */
155
+ declare function removeCookie(name: string): void;
156
+
157
+ /**
158
+ * 获取用户代理字符串(UA)
159
+ * @returns navigator.userAgent.toLowerCase();
160
+ */
161
+ declare function getUA(): string;
162
+ /**
163
+ * 是否为移动端设备(含平板)
164
+ */
165
+ declare function isMobile(): boolean;
166
+ /**
167
+ * 是否为平板设备
168
+ */
169
+ declare function isTablet(): boolean;
170
+ /**
171
+ * 是否为 PC 设备
172
+ */
173
+ declare function isPC(): boolean;
174
+ /**
175
+ * 是否为 iOS 系统
176
+ */
177
+ declare function isIOS(): boolean;
178
+ /**
179
+ * 是否为 Android 系统
180
+ */
181
+ declare function isAndroid(): boolean;
182
+ /**
183
+ * 是否微信内置浏览器
184
+ */
185
+ declare function isWeChat(): boolean;
186
+ /**
187
+ * 是否为 Chrome 浏览器
188
+ * 已排除 Edge、Opera 等基于 Chromium 的浏览器
189
+ */
190
+ declare function isChrome(): boolean;
191
+ /**
192
+ * 检测是否支持触摸事件
193
+ */
194
+ declare function isTouchSupported(): boolean;
195
+ /**
196
+ * 获取设备像素比
197
+ */
198
+ declare function getDevicePixelRatio(): number;
199
+ /**
200
+ * 获取浏览器名字
201
+ */
202
+ declare function getBrowserName(): string | null;
203
+ /**
204
+ * 获取浏览器版本号
205
+ */
206
+ declare function getBrowserVersion(): string | null;
207
+ /**
208
+ * 获取操作系统信息
209
+ */
210
+ declare function getOS(): string;
211
+
212
+ /**
213
+ * 获取窗口宽度(不含滚动条)
214
+ * @returns 窗口宽度
215
+ */
216
+ declare function getWindowWidth(): number;
217
+ /**
218
+ * 获取窗口高度(不含滚动条)
219
+ * @returns 窗口高度
220
+ */
221
+ declare function getWindowHeight(): number;
222
+ /**
223
+ * 获取文档垂直滚动位置
224
+ * @example
225
+ * const top = getWindowScrollTop();
226
+ */
227
+ declare function getWindowScrollTop(): number;
228
+ /**
229
+ * 获取文档水平滚动位置
230
+ * @example
231
+ * const left = getWindowScrollLeft();
232
+ */
233
+ declare function getWindowScrollLeft(): number;
234
+ /**
235
+ * 平滑滚动到指定位置
236
+ * @param top 目标纵向滚动位置
237
+ * @param behavior 滚动行为,默认 'smooth'
238
+ * @example
239
+ * windowScrollTo(0);
240
+ */
241
+ declare function windowScrollTo(top: number, behavior?: ScrollBehavior): void;
242
+ /**
243
+ * 元素是否在视口内(可设置阈值)
244
+ * @param el 目标元素
245
+ * @param offset 额外判定偏移(像素,正数放宽,负数收紧)
246
+ * @returns 是否在视口内
247
+ */
248
+ declare function isInViewport(el: Element, offset?: number): boolean;
249
+ /**
250
+ * 锁定页面滚动(移动端/PC)
251
+ * 使用 `body{ position: fixed }` 技术消除滚动条抖动,记录并恢复滚动位置。
252
+ * @example
253
+ * lockBodyScroll();
254
+ */
255
+ declare function lockBodyScroll(): void;
256
+ /**
257
+ * 解除页面滚动锁定,恢复原始滚动位置
258
+ * @example
259
+ * unlockBodyScroll();
260
+ */
261
+ declare function unlockBodyScroll(): void;
262
+
263
+ /**
264
+ * 下载文件
265
+ * @param url 完整的下载地址 | base64字符串 | Blob对象
266
+ * @param fileName 自定义文件名(需含后缀)
267
+ * @example
268
+ * download('https://xx/xx.pdf');
269
+ * download('https://xx/xx.pdf', 'xx.pdf');
270
+ * download(blob, '图片.jpg');
271
+ */
272
+ declare function download(url: string | Blob, fileName?: string): Promise<void>;
273
+ /**
274
+ * 获取文件名
275
+ * @param disposition content-disposition头值
276
+ * @returns content-disposition中的filename
277
+ * @example
278
+ * const fileName = getDispositionFileName(headers['content-disposition']);
279
+ */
280
+ declare function getDispositionFileName(disposition?: string): string;
281
+ /**
282
+ * 动态加载 JS(重复执行不会重复加载,内部已排重)
283
+ * @param src js 文件路径
284
+ * @param attrs 可选的脚本属性,如 async、defer、crossOrigin
285
+ * @example
286
+ * await loadJs('https://xx/xx.js');
287
+ * await loadJs('/a.js', { defer: true });
288
+ */
289
+ declare function loadJs(src: string, attrs?: Pick<HTMLScriptElement, 'async' | 'defer' | 'crossOrigin'>): Promise<void>;
290
+ /**
291
+ * 判断某个 JS 地址是否已在页面中加载过
292
+ * @param src 相对、绝对路径的 JS 地址
293
+ * @returns 是否已加载过
294
+ * @example
295
+ * hasJs('https://xx/xx.js'); // boolean
296
+ * hasJs('/xx.js'); // boolean
297
+ * hasJs('xx.js'); // boolean
298
+ */
299
+ declare function hasJs(src: string): boolean;
300
+ /**
301
+ * 动态加载 CSS(重复执行不会重复加载,内部已排重)
302
+ * @param href css 文件地址
303
+ * @param attrs 可选属性,如 crossOrigin、media
304
+ * @example
305
+ * await loadCss('https://xx/xx.css');
306
+ * await loadCss('/a.css', { media: 'print' });
307
+ */
308
+ declare function loadCss(href: string, attrs?: Pick<HTMLLinkElement, 'crossOrigin' | 'media'>): Promise<void>;
309
+ /**
310
+ * 判断某个 CSS 地址是否已在页面中加载过
311
+ * @param href 相对、绝对路径的 CSS 地址
312
+ * @returns 是否已加载过
313
+ * @example
314
+ * hasCss('https://xx/xx.css'); // boolean
315
+ */
316
+ declare function hasCss(href: string): boolean;
317
+ /**
318
+ * 预加载图片
319
+ * @param src 图片地址
320
+ * @returns Promise<HTMLImageElement>
321
+ * @example
322
+ * await preloadImage('/a.png');
323
+ */
324
+ declare function preloadImage(src: string): Promise<HTMLImageElement>;
325
+
326
+ /** 请求方法类型 */
327
+ type RequestMethod = 'GET' | 'POST' | 'PUT' | 'DELETE' | 'CONNECT' | 'HEAD' | 'OPTIONS' | 'TRACE' | 'PATCH';
328
+ /**
329
+ * 请求参数类型
330
+ * 包含 fetch 原生支持的 BodyInit 类型,以及支持自动 JSON 序列化的对象和数组
331
+ */
332
+ type RequestData = string | ArrayBuffer | ArrayBufferView | Blob | FormData | URLSearchParams | ReadableStream<Uint8Array> | Record<string, unknown> | unknown[] | null;
333
+ /**
334
+ * 响应数据类型
335
+ */
336
+ type ResponseData = string | ArrayBuffer | Blob | Record<string, unknown> | unknown[] | null;
337
+ /**
338
+ * 发起请求的配置 (对外,参数可选)
339
+ */
340
+ type RequestConfig<D extends RequestData = RequestData> = Partial<RequestConfigBase<D>>;
341
+ /**
342
+ * 自定义请求的配置 (接口字段参数必填)
343
+ */
344
+ type RequestConfigBase<D extends RequestData = RequestData> = {
345
+ /** 接口地址 */
346
+ url: string;
347
+ /** 请求方法 */
348
+ method?: RequestMethod;
349
+ /** 请求头(会自动过滤undefined, null, "";不过滤0和false; 数字和布尔值会自动转换为字符串) */
350
+ header?: Record<string, string | number | boolean | null | undefined>;
351
+ /** 请求参数 */
352
+ data?: D;
353
+ /** 超时时间 (毫秒), 默认 60000 */
354
+ timeout?: number;
355
+ /** 接口返回响应数据的字段, 支持"a[0].b.c"的格式, 当配置false时返回完整的响应数据 */
356
+ resKey: string | false;
357
+ /** 接口返回响应消息的字段, 支持"a[0].b.c"的格式 */
358
+ msgKey: string;
359
+ /** 接口返回响应状态码的字段, 支持"a[0].b.c"的格式 */
360
+ codeKey: string;
361
+ /** 接口返回成功状态码的字段, 支持"a[0].b.c"的格式 (默认取 codeKey) */
362
+ successKey?: string;
363
+ /** 成功状态码 */
364
+ successCode: (number | string)[];
365
+ /** 登录过期状态码 */
366
+ reloginCode: (number | string)[];
367
+ /** 是否开启流式传输 (如 SSE) */
368
+ enableChunked?: boolean;
369
+ /** 响应类型 (默认 json, enableChunked为true时忽略) */
370
+ responseType?: 'text' | 'arraybuffer' | 'json';
371
+ /** 响应数据的缓存时间, 单位毫秒。仅在成功时缓存;仅缓存在内存,应用退出,缓存消失。(默认0,不开启缓存) */
372
+ cacheTime?: number;
373
+ /** 是否提示接口异常 (默认true) */
374
+ toastError?: boolean;
375
+ /** 是否显示进度条: 支持字符串,自定义文本 (默认true) */
376
+ showLoading?: boolean | string;
377
+ /** 是否输出日志 (默认true) */
378
+ showLog?: boolean;
379
+ /** 成功和失败时,额外输出的日志数据 (可覆盖内部log参数,如'name') */
380
+ logExtra?: Record<string, unknown>;
381
+ /** 响应数据的转换 */
382
+ resMap?: (data: ResponseData) => ResponseData;
383
+ /** 获取task对象, 用于取消请求或监听流式数据 */
384
+ onTaskReady?: (task: RequestTask) => void;
385
+ };
386
+ /**
387
+ * 请求任务对象 (用于取消请求或监听流式数据)
388
+ */
389
+ interface RequestTask {
390
+ /** 取消请求 */
391
+ abort: () => void;
392
+ /** 监听流式数据块接收事件 */
393
+ onChunkReceived: (callback: ChunkCallback) => void;
394
+ /** 取消监听流式数据块接收事件 */
395
+ offChunkReceived: () => void;
396
+ }
397
+ /**
398
+ * 流式数据块接收事件回调
399
+ */
400
+ type ChunkCallback = (response: {
401
+ data: ArrayBuffer;
402
+ }) => void;
403
+ /**
404
+ * 基础请求 (返回 Promise 和 Task 对象)
405
+ * 基于 fetch API 封装,支持流式请求
406
+ * @param config 请求配置
407
+ * @example
408
+ * // 在入口文件完成配置 (确保请求失败有toast提示,登录过期能够触发重新登录,log有日志输出)
409
+ * setBaseToolsConfig({
410
+ * toast: ({ msg, status }) => (status === 'fail' ? message.error(msg) : message.success(msg)),
411
+ * showLoading: ({ title }) => message.loading(title || '加载中...'),
412
+ * hideLoading: () => message.destroy(),
413
+ * toLogin: () => reLogin(),
414
+ * log(level, data) {
415
+ * if (data.name === 'request') {
416
+ * sendLog('request', data); // 请求日志
417
+ * } else if (level === 'error') {
418
+ * sendLog('error', data); // 错误日志
419
+ * } else {
420
+ * sendLog('action', data); // 操作日志
421
+ * }
422
+ * },
423
+ * });
424
+ *
425
+ * // 封装项目的基础请求
426
+ * export function requestApi<T>(config: RequestConfig) {
427
+ * return request<T>({
428
+ * header: { token: 'xx', version: 'xx', tid: 'xx' }, // 会自动过滤空值
429
+ * // resMap: (res) => res, // 响应数据的转换, 如解密操作 (可选)
430
+ * resKey: 'data',
431
+ * msgKey: 'message',
432
+ * codeKey: 'status',
433
+ * successCode: [1],
434
+ * reloginCode: [-10],
435
+ * ...config,
436
+ * });
437
+ * }
438
+ *
439
+ * // 1. 基于上面 requestApi 的普通接口
440
+ * export function apiGoodList(data: { page: number, size: number }) {
441
+ * return requestApi<GoodItem[]>({ url: '/goods/list', data, resKey: 'data.list' });
442
+ * }
443
+ *
444
+ * const goodList = await apiGoodList({ page:1, size:10 });
445
+ *
446
+ * // 2. 参数泛型的写法
447
+ * export function apiGoodList(config: RequestConfig<{ page: number, size: number }>) {
448
+ * return requestApi<GoodItem[]>({ url: '/goods/list', resKey: 'data.list', ...config });
449
+ * }
450
+ *
451
+ * const goodList = await apiGoodList({ data: { page:1, size:10 } });
452
+ *
453
+ * // 3. 基于上面 requestApi 的流式接口
454
+ * export function apiChatStream(config: RequestConfig) {
455
+ * return requestApi({
456
+ * ...config,
457
+ * url: '/sse/chatStream',
458
+ * resKey: false,
459
+ * showLoading: false,
460
+ * responseType: 'arraybuffer', // 流式响应类型
461
+ * enableChunked: true, // 开启分块传输
462
+ * });
463
+ * }
464
+ *
465
+ * // 流式监听
466
+ * const onTaskReady = (task: RequestTask) => {
467
+ * task.onChunkReceived((res) => {
468
+ * console.log('ArrayBuffer', res.data);
469
+ * });
470
+ * }
471
+ *
472
+ * // 流式发起
473
+ * const data = { content: '你好', chatId: 123 };
474
+ * await apiChatStream({ data, onTaskReady });
475
+ *
476
+ * // 流式取消 (在组件销毁或页面关闭时调用)
477
+ * task?.offChunkReceived(); // 取消监听,中断流式接收
478
+ * task?.abort(); // 取消请求 (若流式已生成,此时abort无效,因为请求已成功)
479
+ */
480
+ declare function request<T, D extends RequestData = RequestData>(config: RequestConfigBase<D>): Promise<T>;
481
+ /**
482
+ * 参数过滤undefined, 避免接口处理异常 (不可过滤 null 、 "" 、 false 、 0 这些有效值)
483
+ */
484
+ declare function filterRequestData(data: Record<string, any>): Record<string, any>;
485
+ /**
486
+ * 请求头过滤空值 (undefined, null, ""), 不过滤0和false
487
+ */
488
+ declare function filterRequestHeader(header: RequestConfigBase['header']): Record<string, string>;
489
+
490
+ /**
491
+ * web api 的调用配置
492
+ */
493
+ type WebApiConfig<Res = any, Err = any> = {
494
+ /** 是否显示加载提示, 默认 false. (支持字符串,自定义文本) */
495
+ showLoading?: boolean | string;
496
+ /** 操作成功的toast提示, 默认不显示 */
497
+ toastSuccess?: ((res: Res) => false | string) | false | string;
498
+ /** 是否显示操作失败的详细错误信息, 默认 true. (支持字符串,自定义文本; 支持根据errMsg判断是否显示, 例如: (e) => !e.errMsg.includes('cancel') */
499
+ toastError?: ((e: Err) => boolean | string) | boolean | string;
500
+ /** 是否显示日志, 默认 true */
501
+ showLog?: boolean;
502
+ /** 响应数据的转换, 如解密操作 (返回值在成功日志中输出'resMap'字段) */
503
+ resMap?: (res: any) => Res;
504
+ /** 成功和失败时,额外输出的日志数据 (可覆盖内部log参数,如'name') */
505
+ logExtra?: Record<string, unknown>;
506
+ };
507
+
508
+ /**
509
+ * 上传文件的选项
510
+ */
511
+ type UploadFileOption = {
512
+ /** 上传接口地址 */
513
+ url: string;
514
+ /** 要上传的文件对象 */
515
+ file: File;
516
+ /** 文件对应的 key, 默认'file' (服务端通过这个 key 获取文件的二进制内容) */
517
+ name?: string;
518
+ /** 请求头 */
519
+ header?: Record<string, string | number>;
520
+ /** 额外的formData参数 */
521
+ formData?: Record<string, string | number>;
522
+ /** 超时时间,单位 ms,默认 0(不超时) */
523
+ timeout?: number;
524
+ };
525
+ type OnUploadProgressUpdate = (res: UploadProgressEvent) => void;
526
+ type UploadProgressEvent = {
527
+ /** 上传进度百分比: 0-100 */
528
+ progress: number;
529
+ /** 已上传字节数 */
530
+ loaded: number;
531
+ /** 总字节数 */
532
+ total: number;
533
+ };
534
+ type UploadTask = {
535
+ /** 上传进度 */
536
+ onProgressUpdate: (callback: OnUploadProgressUpdate) => void;
537
+ /** 取消上传 */
538
+ abort: () => void;
539
+ };
540
+ type UploadConfig = {
541
+ /** 获取task对象 */
542
+ onTaskReady?: (task: UploadTask) => void;
543
+ };
544
+ type UploadFail = {
545
+ message: string;
546
+ status: number;
547
+ };
548
+ /**
549
+ * 上传文件
550
+ * @param option 上传文件的选项
551
+ * @param config 配置项
552
+ * @example
553
+ * // 上传
554
+ * const res = await uploadFile({ url: 'https://xx', file: file});
555
+ *
556
+ * // 监听上传进度
557
+ * const res = await uploadFile({ url: 'https://xx', file: file}, {
558
+ * onTaskReady: (task) =>
559
+ * task.onProgressUpdate((res) => console.log('上传进度:', res.progress)),
560
+ * });
561
+ *
562
+ * // 解析上传结果
563
+ * console.log('uploadFile ok', JSON.parse(res));
564
+ */
565
+ declare function uploadFile(option: UploadFileOption, config?: UploadConfig & WebApiConfig): Promise<string>;
566
+
567
+ /**
568
+ * 写入 localStorage(自动 JSON 序列化)
569
+ * @param key 键名
570
+ * @param value 任意可序列化的值:对象、数组、字符串、数字、布尔值。(`null` 或 `undefined` 会自动移除该键)
571
+ * @param days 过期天数(从当前时间起算)
572
+ * @example
573
+ * setLocalStorage('user', { id: 1, name: 'Alice' }); // 对象
574
+ * setLocalStorage('age', 18); // 数字
575
+ * setLocalStorage('vip', true); // 布尔值
576
+ * setLocalStorage('token', 'abc123', 7); // 7 天后过期
577
+ */
578
+ declare function setLocalStorage(key: string, value: unknown, days?: number): void;
579
+ /**
580
+ * 读取 localStorage(自动 JSON 反序列化)
581
+ * 若值为合法 JSON,则返回反序列化后的数据;
582
+ * 若值非 JSON(如外部写入的纯字符串),则原样返回字符串。
583
+ * 不存在时返回 `null`。
584
+ * @param key 键名
585
+ * @returns 解析后的值或 `null`
586
+ * @example
587
+ * const user = getLocalStorage<{ id: number; name: string }>('user');
588
+ * const age = getLocalStorage<number>('age');
589
+ * const vip = getLocalStorage<boolean>('vip');
590
+ */
591
+ declare function getLocalStorage<T = unknown>(key: string): T | null;
592
+ /**
593
+ * 移除 localStorage 指定键
594
+ * @param key 键名
595
+ * @example
596
+ * removeLocalStorage('token');
597
+ */
598
+ declare function removeLocalStorage(key: string): void;
599
+
600
+ /**
601
+ * 获取url的查询参数值
602
+ * @param key 参数名
603
+ * @param url 完整 URL 或仅查询串(如 "a=1&b=2")
604
+ * @returns 解码后的参数值 (若不存在|"null"|"undefined",则返回 null)
605
+ * @example
606
+ * const q = getUrlParam('q'); // 默认当前地址
607
+ * const q = getUrlParam('q', 'https://a.com/?q=%E6%B5%8B%E8%AF%95'); // "测试"
608
+ * const a = getUrlParam('a', 'a=1'); // "1"
609
+ * const list = getUrlParam('list', 'list=[1,2]'); // "[1,2]"
610
+ * const list = getUrlParam('list', 'list=null'); // null
611
+ * const list = getUrlParam('list', 'list=undefined'); // null
612
+ */
613
+ declare function getUrlParam(key: string, url?: string): string | null;
614
+ /**
615
+ * 获取url的查询参数值,并转为number类型
616
+ * @param key 参数名
617
+ * @param url 完整 URL 或仅查询串(如 "a=1&b=2")
618
+ * @returns 解码后的参数值 (若不存在|"非数字字符串",则返回 null)
619
+ * @example
620
+ * const a = getUrlNumber('a'); // 默认当前地址
621
+ * const a = getUrlNumber('a', 'https://a.com/?a=1'); // 1
622
+ * const a = getUrlNumber('a', 'a=1'); // 1
623
+ * const a = getUrlNumber('a', 'a=1.2'); // 1.2
624
+ * const a = getUrlNumber('a', 'a=abc'); // null
625
+ */
626
+ declare function getUrlNumber(key: string, url?: string): number | null;
627
+ /**
628
+ * 获取url的所有查询参数值
629
+ * @param url 完整 URL 或仅查询串(如 "a=1&b=2")
630
+ * @returns 解码后的键值对象(无参数返回空对象; "null"|"undefined"的参数会被忽略)
631
+ * @example
632
+ * const params = getUrlParams(); // 默认当前地址
633
+ * const params = getUrlParams('a=1&b=2'); // { a: "1", b: "2" }
634
+ * const params = getUrlParams('https://a.com/?a=1&b=2'); // { a: "1", b: "2" }
635
+ * const params = getUrlParams('a=1&b=null'); // { a: "1" }
636
+ * const params = getUrlParams('a=1&b=undefined'); // { a: "1" }
637
+ */
638
+ declare function getUrlParams(url?: string): Record<string, string>;
639
+
640
+ export { type AppConfig, type AppLogInfo, type ChunkCallback, type OnUploadProgressUpdate, type RequestConfig, type RequestConfigBase, type RequestData, type RequestMethod, type RequestTask, type ResponseData, type UploadConfig, type UploadFail, type UploadFileOption, type UploadProgressEvent, type UploadTask, copyBlob, copyHtml, copyImage, copyNode, copyRtf, copyTable, copyText, copyUrl, download, filterRequestData, filterRequestHeader, getBaseToolsConfig, getBrowserName, getBrowserVersion, getCookie, getDevicePixelRatio, getDispositionFileName, getLocalStorage, getOS, getUA, getUrlNumber, getUrlParam, getUrlParams, getWindowHeight, getWindowScrollLeft, getWindowScrollTop, getWindowWidth, hasCss, hasJs, isAndroid, isChrome, isIOS, isInViewport, isMobile, isPC, isTablet, isTouchSupported, isWeChat, loadCss, loadJs, lockBodyScroll, preloadImage, removeCookie, removeLocalStorage, request, setBaseToolsConfig, setCookie, setLocalStorage, unlockBodyScroll, uploadFile, windowScrollTo };