@base-web-kits/base-tools-web 1.2.0-alpha.0 → 1.2.2
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/async/index.d.ts +2 -2
- package/dist/async/index.d.ts.map +1 -1
- package/dist/base-tools-web.umd.global.js +50 -54
- package/dist/base-tools-web.umd.global.js.map +1 -1
- package/dist/index.cjs +40 -979
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +224 -994
- package/dist/index.js.map +1 -1
- package/dist/network/request.d.ts +33 -28
- package/dist/network/request.d.ts.map +1 -1
- package/dist/network/uploadFile.d.ts +1 -1
- package/dist/network/uploadFile.d.ts.map +1 -1
- package/package.json +2 -2
- package/src/web/async/index.ts +6 -6
- package/src/web/network/request.ts +62 -57
- package/src/web/network/uploadFile.ts +3 -7
|
@@ -39,22 +39,24 @@ export type RequestConfigBase<D extends RequestData = RequestData> = {
|
|
|
39
39
|
successCode: (number | string)[];
|
|
40
40
|
/** 登录过期状态码 */
|
|
41
41
|
reloginCode: (number | string)[];
|
|
42
|
-
/**
|
|
43
|
-
|
|
42
|
+
/** 是否开启流式传输 (如 SSE) */
|
|
43
|
+
enableChunked?: boolean;
|
|
44
|
+
/** 响应类型 (默认 json, enableChunked为true时忽略) */
|
|
45
|
+
responseType?: 'text' | 'arraybuffer' | 'json';
|
|
46
|
+
/** 响应数据的缓存时间, 单位毫秒。仅在成功时缓存;仅缓存在内存,应用退出,缓存消失。(默认0,不开启缓存) */
|
|
47
|
+
cacheTime?: number;
|
|
44
48
|
/** 是否提示接口异常 (默认true) */
|
|
45
49
|
toastError?: boolean;
|
|
50
|
+
/** 是否显示进度条: 支持字符串,自定义文本 (默认true) */
|
|
51
|
+
showLoading?: boolean | string;
|
|
46
52
|
/** 是否输出日志 (默认true) */
|
|
47
|
-
|
|
53
|
+
showLog?: boolean;
|
|
48
54
|
/** 成功和失败时,额外输出的日志数据 (可覆盖内部log参数,如'name') */
|
|
49
55
|
logExtra?: Record<string, unknown>;
|
|
50
|
-
/**
|
|
51
|
-
|
|
52
|
-
/**
|
|
53
|
-
|
|
54
|
-
/** 响应类型 (默认 json, enableChunked为true时忽略) */
|
|
55
|
-
responseType?: 'text' | 'arraybuffer' | 'json';
|
|
56
|
-
/** 响应拦截 */
|
|
57
|
-
responseInterceptor?: (data: ResponseData) => ResponseData;
|
|
56
|
+
/** 响应数据的转换 */
|
|
57
|
+
resMap?: (data: ResponseData) => ResponseData;
|
|
58
|
+
/** 获取task对象, 用于取消请求或监听流式数据 */
|
|
59
|
+
onTaskReady?: (task: RequestTask) => void;
|
|
58
60
|
};
|
|
59
61
|
/**
|
|
60
62
|
* 请求任务对象 (用于取消请求或监听流式数据)
|
|
@@ -77,7 +79,6 @@ export type ChunkCallback = (response: {
|
|
|
77
79
|
* 基础请求 (返回 Promise 和 Task 对象)
|
|
78
80
|
* 基于 fetch API 封装,支持流式请求
|
|
79
81
|
* @param config 请求配置
|
|
80
|
-
* @returns Promise<T> & { task?: RequestTask }
|
|
81
82
|
* @example
|
|
82
83
|
* // 在入口文件完成配置 (确保请求失败有toast提示,登录过期能够触发重新登录,log有日志输出)
|
|
83
84
|
* setBaseToolsConfig({
|
|
@@ -100,7 +101,7 @@ export type ChunkCallback = (response: {
|
|
|
100
101
|
* export function requestApi<T>(config: RequestConfig) {
|
|
101
102
|
* return request<T>({
|
|
102
103
|
* header: { token: 'xx', version: 'xx', tid: 'xx' }, // 会自动过滤空值
|
|
103
|
-
* //
|
|
104
|
+
* // resMap: (res) => res, // 响应数据的转换, 如解密操作 (可选)
|
|
104
105
|
* resKey: 'data',
|
|
105
106
|
* msgKey: 'message',
|
|
106
107
|
* codeKey: 'status',
|
|
@@ -122,32 +123,36 @@ export type ChunkCallback = (response: {
|
|
|
122
123
|
* return requestApi<GoodItem[]>({ url: '/goods/list', resKey: 'data.list', ...config });
|
|
123
124
|
* }
|
|
124
125
|
*
|
|
125
|
-
* const goodList = await apiGoodList({ data: { page:1, size:10 }
|
|
126
|
+
* const goodList = await apiGoodList({ data: { page:1, size:10 } });
|
|
126
127
|
*
|
|
127
128
|
* // 3. 基于上面 requestApi 的流式接口
|
|
128
|
-
* export function apiChatStream(
|
|
129
|
-
* return requestApi
|
|
129
|
+
* export function apiChatStream(config: RequestConfig) {
|
|
130
|
+
* return requestApi({
|
|
131
|
+
* ...config,
|
|
130
132
|
* url: '/sse/chatStream',
|
|
131
|
-
* data,
|
|
132
133
|
* resKey: false,
|
|
133
134
|
* showLoading: false,
|
|
134
|
-
* responseType: 'arraybuffer',
|
|
135
|
-
* enableChunked: true,
|
|
135
|
+
* responseType: 'arraybuffer', // 流式响应类型
|
|
136
|
+
* enableChunked: true, // 开启分块传输
|
|
136
137
|
* });
|
|
137
138
|
* }
|
|
138
139
|
*
|
|
139
|
-
*
|
|
140
|
+
* // 流式监听
|
|
141
|
+
* const onTaskReady = (task: RequestTask) => {
|
|
142
|
+
* task.onChunkReceived((res) => {
|
|
143
|
+
* console.log('ArrayBuffer', res.data);
|
|
144
|
+
* });
|
|
145
|
+
* }
|
|
140
146
|
*
|
|
141
|
-
*
|
|
142
|
-
*
|
|
143
|
-
* });
|
|
147
|
+
* // 流式发起
|
|
148
|
+
* const data = { content: '你好', chatId: 123 };
|
|
149
|
+
* await apiChatStream({ data, onTaskReady });
|
|
144
150
|
*
|
|
145
|
-
*
|
|
146
|
-
* task
|
|
151
|
+
* // 流式取消 (在组件销毁或页面关闭时调用)
|
|
152
|
+
* task?.offChunkReceived(); // 取消监听,中断流式接收
|
|
153
|
+
* task?.abort(); // 取消请求 (若流式已生成,此时abort无效,因为请求已成功)
|
|
147
154
|
*/
|
|
148
|
-
export declare function request<T, D extends RequestData = RequestData>(config: RequestConfigBase<D>): Promise<T
|
|
149
|
-
task?: RequestTask;
|
|
150
|
-
};
|
|
155
|
+
export declare function request<T, D extends RequestData = RequestData>(config: RequestConfigBase<D>): Promise<T>;
|
|
151
156
|
/**
|
|
152
157
|
* 参数过滤undefined, 避免接口处理异常 (不可过滤 null 、 "" 、 false 、 0 这些有效值)
|
|
153
158
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"request.d.ts","sourceRoot":"","sources":["../../src/web/network/request.ts"],"names":[],"mappings":"AAUA,aAAa;AACb,MAAM,MAAM,aAAa,GACrB,KAAK,GACL,MAAM,GACN,KAAK,GACL,QAAQ,GACR,SAAS,GACT,MAAM,GACN,SAAS,GACT,OAAO,GACP,OAAO,CAAC;AAEZ;;;GAGG;AACH,MAAM,MAAM,WAAW,GACnB,MAAM,GACN,WAAW,GACX,eAAe,GACf,IAAI,GACJ,QAAQ,GACR,eAAe,GACf,cAAc,CAAC,UAAU,CAAC,GAC1B,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GACvB,OAAO,EAAE,GACT,IAAI,CAAC;AAET;;GAEG;AACH,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,WAAW,GAAG,IAAI,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,EAAE,GAAG,IAAI,CAAC;AAEpG;;GAEG;AACH,MAAM,MAAM,aAAa,CAAC,CAAC,SAAS,WAAW,GAAG,WAAW,IAAI,OAAO,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC,CAAC;AAE/F;;GAEG;AACH,MAAM,MAAM,iBAAiB,CAAC,CAAC,SAAS,WAAW,GAAG,WAAW,IAAI;IACnE,WAAW;IACX,GAAG,EAAE,MAAM,CAAC;IAEZ,WAAW;IACX,MAAM,CAAC,EAAE,aAAa,CAAC;IAEvB,gEAAgE;IAChE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,GAAG,SAAS,CAAC,CAAC;IAEtE,WAAW;IACX,IAAI,CAAC,EAAE,CAAC,CAAC;IAET,0BAA0B;IAC1B,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB,uDAAuD;IACvD,MAAM,EAAE,MAAM,GAAG,KAAK,CAAC;IAEvB,mCAAmC;IACnC,MAAM,EAAE,MAAM,CAAC;IAEf,oCAAoC;IACpC,OAAO,EAAE,MAAM,CAAC;IAEhB,kDAAkD;IAClD,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB,YAAY;IACZ,WAAW,EAAE,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,CAAC;IAEjC,cAAc;IACd,WAAW,EAAE,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,CAAC;IAEjC,
|
|
1
|
+
{"version":3,"file":"request.d.ts","sourceRoot":"","sources":["../../src/web/network/request.ts"],"names":[],"mappings":"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"}
|
|
@@ -53,5 +53,5 @@ export type UploadFail = {
|
|
|
53
53
|
* task.onProgressUpdate((res) => console.log('上传进度:', res.progress)),
|
|
54
54
|
* });
|
|
55
55
|
*/
|
|
56
|
-
export declare function uploadFile(option: UploadFileOption, config?: UploadConfig & WebApiConfig): Promise<
|
|
56
|
+
export declare function uploadFile(option: UploadFileOption, config?: UploadConfig & WebApiConfig): Promise<string>;
|
|
57
57
|
//# sourceMappingURL=uploadFile.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"uploadFile.d.ts","sourceRoot":"","sources":["../../src/web/network/uploadFile.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAE7C;;GAEG;AACH,MAAM,MAAM,gBAAgB,GAAG;IAC7B,aAAa;IACb,GAAG,EAAE,MAAM,CAAC;IAEZ,eAAe;IACf,IAAI,EAAE,IAAI,CAAC;IAEX,mDAAmD;IACnD,IAAI,CAAC,EAAE,MAAM,CAAC;IAEd,UAAU;IACV,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,CAAC;IAEzC,oBAAoB;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,CAAC;IAE3C,2BAA2B;IAC3B,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,MAAM,MAAM,sBAAsB,GAAG,CAAC,GAAG,EAAE,mBAAmB,KAAK,IAAI,CAAC;AAExE,MAAM,MAAM,mBAAmB,GAAG;IAChC,qBAAqB;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa;IACb,MAAM,EAAE,MAAM,CAAC;IACf,WAAW;IACX,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,MAAM,MAAM,UAAU,GAAG;IACvB,WAAW;IACX,gBAAgB,EAAE,CAAC,QAAQ,EAAE,sBAAsB,KAAK,IAAI,CAAC;IAC7D,WAAW;IACX,KAAK,EAAE,MAAM,IAAI,CAAC;CACnB,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG;IACzB,eAAe;IACf,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE,UAAU,KAAK,IAAI,CAAC;CAC1C,CAAC;AAEF,MAAM,MAAM,UAAU,GAAG;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;
|
|
1
|
+
{"version":3,"file":"uploadFile.d.ts","sourceRoot":"","sources":["../../src/web/network/uploadFile.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAE7C;;GAEG;AACH,MAAM,MAAM,gBAAgB,GAAG;IAC7B,aAAa;IACb,GAAG,EAAE,MAAM,CAAC;IAEZ,eAAe;IACf,IAAI,EAAE,IAAI,CAAC;IAEX,mDAAmD;IACnD,IAAI,CAAC,EAAE,MAAM,CAAC;IAEd,UAAU;IACV,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,CAAC;IAEzC,oBAAoB;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,CAAC;IAE3C,2BAA2B;IAC3B,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,MAAM,MAAM,sBAAsB,GAAG,CAAC,GAAG,EAAE,mBAAmB,KAAK,IAAI,CAAC;AAExE,MAAM,MAAM,mBAAmB,GAAG;IAChC,qBAAqB;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa;IACb,MAAM,EAAE,MAAM,CAAC;IACf,WAAW;IACX,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,MAAM,MAAM,UAAU,GAAG;IACvB,WAAW;IACX,gBAAgB,EAAE,CAAC,QAAQ,EAAE,sBAAsB,KAAK,IAAI,CAAC;IAC7D,WAAW;IACX,KAAK,EAAE,MAAM,IAAI,CAAC;CACnB,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG;IACzB,eAAe;IACf,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE,UAAU,KAAK,IAAI,CAAC;CAC1C,CAAC;AAEF,MAAM,MAAM,UAAU,GAAG;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAyEF;;;;;;;;;;;;;GAaG;AACH,wBAAgB,UAAU,CAAC,MAAM,EAAE,gBAAgB,EAAE,MAAM,CAAC,EAAE,YAAY,GAAG,YAAY,mBAExF"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@base-web-kits/base-tools-web",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.2",
|
|
4
4
|
"sideEffects": false,
|
|
5
5
|
"description": "Independent Web utilities package built from src/web.",
|
|
6
6
|
"keywords": [
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
"src"
|
|
26
26
|
],
|
|
27
27
|
"dependencies": {
|
|
28
|
-
"@base-web-kits/base-tools-ts": "^1.
|
|
28
|
+
"@base-web-kits/base-tools-ts": "^1.2.0"
|
|
29
29
|
},
|
|
30
30
|
"peerDependencies": {
|
|
31
31
|
"axios": ">=0.18.0"
|
package/src/web/async/index.ts
CHANGED
|
@@ -23,8 +23,8 @@ export type WebApiConfig<Res = any, Err = any> = {
|
|
|
23
23
|
/** 是否显示日志, 默认 true */
|
|
24
24
|
showLog?: boolean;
|
|
25
25
|
|
|
26
|
-
/**
|
|
27
|
-
|
|
26
|
+
/** 响应数据的转换, 如解密操作 (返回值在成功日志中输出'resMap'字段) */
|
|
27
|
+
resMap?: (res: any) => Res;
|
|
28
28
|
|
|
29
29
|
/** 成功和失败时,额外输出的日志数据 (可覆盖内部log参数,如'name') */
|
|
30
30
|
logExtra?: Record<string, unknown>;
|
|
@@ -50,7 +50,7 @@ export function enhanceWebApi<Option = any, Res = any, Err = any, Config = any>(
|
|
|
50
50
|
toastSuccess = false,
|
|
51
51
|
toastError = true,
|
|
52
52
|
showLog = true,
|
|
53
|
-
|
|
53
|
+
resMap,
|
|
54
54
|
logExtra,
|
|
55
55
|
} = finalConfig;
|
|
56
56
|
|
|
@@ -72,14 +72,14 @@ export function enhanceWebApi<Option = any, Res = any, Err = any, Config = any>(
|
|
|
72
72
|
.then((res) => {
|
|
73
73
|
if (showLoading) hideLoadingFn?.();
|
|
74
74
|
|
|
75
|
-
const finalRes =
|
|
75
|
+
const finalRes = resMap ? resMap(res) : res;
|
|
76
76
|
|
|
77
77
|
if (showLog) {
|
|
78
78
|
const logData: AppLogInfo = { name: fname, status: 'success', option, ...logExtra };
|
|
79
79
|
|
|
80
|
-
if (
|
|
80
|
+
if (resMap) {
|
|
81
81
|
logData.res = res; // 输出原始数据
|
|
82
|
-
logData.
|
|
82
|
+
logData.resMap = cloneDeep(finalRes); // 深拷贝处理后数据,避免外部修改对象,造成输出不一致
|
|
83
83
|
} else {
|
|
84
84
|
logData.res = cloneDeep(res); // 深拷贝原始数据,避免外部修改对象,造成输出不一致
|
|
85
85
|
}
|
|
@@ -83,29 +83,32 @@ export type RequestConfigBase<D extends RequestData = RequestData> = {
|
|
|
83
83
|
/** 登录过期状态码 */
|
|
84
84
|
reloginCode: (number | string)[];
|
|
85
85
|
|
|
86
|
-
/**
|
|
87
|
-
|
|
86
|
+
/** 是否开启流式传输 (如 SSE) */
|
|
87
|
+
enableChunked?: boolean;
|
|
88
|
+
|
|
89
|
+
/** 响应类型 (默认 json, enableChunked为true时忽略) */
|
|
90
|
+
responseType?: 'text' | 'arraybuffer' | 'json';
|
|
91
|
+
|
|
92
|
+
/** 响应数据的缓存时间, 单位毫秒。仅在成功时缓存;仅缓存在内存,应用退出,缓存消失。(默认0,不开启缓存) */
|
|
93
|
+
cacheTime?: number;
|
|
88
94
|
|
|
89
95
|
/** 是否提示接口异常 (默认true) */
|
|
90
96
|
toastError?: boolean;
|
|
91
97
|
|
|
98
|
+
/** 是否显示进度条: 支持字符串,自定义文本 (默认true) */
|
|
99
|
+
showLoading?: boolean | string;
|
|
100
|
+
|
|
92
101
|
/** 是否输出日志 (默认true) */
|
|
93
|
-
|
|
102
|
+
showLog?: boolean;
|
|
94
103
|
|
|
95
104
|
/** 成功和失败时,额外输出的日志数据 (可覆盖内部log参数,如'name') */
|
|
96
105
|
logExtra?: Record<string, unknown>;
|
|
97
106
|
|
|
98
|
-
/**
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
/** 是否开启流式传输 (如 SSE) */
|
|
102
|
-
enableChunked?: boolean;
|
|
103
|
-
|
|
104
|
-
/** 响应类型 (默认 json, enableChunked为true时忽略) */
|
|
105
|
-
responseType?: 'text' | 'arraybuffer' | 'json';
|
|
107
|
+
/** 响应数据的转换 */
|
|
108
|
+
resMap?: (data: ResponseData) => ResponseData;
|
|
106
109
|
|
|
107
|
-
/**
|
|
108
|
-
|
|
110
|
+
/** 获取task对象, 用于取消请求或监听流式数据 */
|
|
111
|
+
onTaskReady?: (task: RequestTask) => void;
|
|
109
112
|
};
|
|
110
113
|
|
|
111
114
|
/**
|
|
@@ -134,7 +137,6 @@ const requestCache = new Map<string, { res: unknown; expire: number }>();
|
|
|
134
137
|
* 基础请求 (返回 Promise 和 Task 对象)
|
|
135
138
|
* 基于 fetch API 封装,支持流式请求
|
|
136
139
|
* @param config 请求配置
|
|
137
|
-
* @returns Promise<T> & { task?: RequestTask }
|
|
138
140
|
* @example
|
|
139
141
|
* // 在入口文件完成配置 (确保请求失败有toast提示,登录过期能够触发重新登录,log有日志输出)
|
|
140
142
|
* setBaseToolsConfig({
|
|
@@ -157,7 +159,7 @@ const requestCache = new Map<string, { res: unknown; expire: number }>();
|
|
|
157
159
|
* export function requestApi<T>(config: RequestConfig) {
|
|
158
160
|
* return request<T>({
|
|
159
161
|
* header: { token: 'xx', version: 'xx', tid: 'xx' }, // 会自动过滤空值
|
|
160
|
-
* //
|
|
162
|
+
* // resMap: (res) => res, // 响应数据的转换, 如解密操作 (可选)
|
|
161
163
|
* resKey: 'data',
|
|
162
164
|
* msgKey: 'message',
|
|
163
165
|
* codeKey: 'status',
|
|
@@ -179,30 +181,57 @@ const requestCache = new Map<string, { res: unknown; expire: number }>();
|
|
|
179
181
|
* return requestApi<GoodItem[]>({ url: '/goods/list', resKey: 'data.list', ...config });
|
|
180
182
|
* }
|
|
181
183
|
*
|
|
182
|
-
* const goodList = await apiGoodList({ data: { page:1, size:10 }
|
|
184
|
+
* const goodList = await apiGoodList({ data: { page:1, size:10 } });
|
|
183
185
|
*
|
|
184
186
|
* // 3. 基于上面 requestApi 的流式接口
|
|
185
|
-
* export function apiChatStream(
|
|
186
|
-
* return requestApi
|
|
187
|
+
* export function apiChatStream(config: RequestConfig) {
|
|
188
|
+
* return requestApi({
|
|
189
|
+
* ...config,
|
|
187
190
|
* url: '/sse/chatStream',
|
|
188
|
-
* data,
|
|
189
191
|
* resKey: false,
|
|
190
192
|
* showLoading: false,
|
|
191
|
-
* responseType: 'arraybuffer',
|
|
192
|
-
* enableChunked: true,
|
|
193
|
+
* responseType: 'arraybuffer', // 流式响应类型
|
|
194
|
+
* enableChunked: true, // 开启分块传输
|
|
193
195
|
* });
|
|
194
196
|
* }
|
|
195
197
|
*
|
|
196
|
-
*
|
|
198
|
+
* // 流式监听
|
|
199
|
+
* const onTaskReady = (task: RequestTask) => {
|
|
200
|
+
* task.onChunkReceived((res) => {
|
|
201
|
+
* console.log('ArrayBuffer', res.data);
|
|
202
|
+
* });
|
|
203
|
+
* }
|
|
197
204
|
*
|
|
198
|
-
*
|
|
199
|
-
*
|
|
200
|
-
* });
|
|
205
|
+
* // 流式发起
|
|
206
|
+
* const data = { content: '你好', chatId: 123 };
|
|
207
|
+
* await apiChatStream({ data, onTaskReady });
|
|
201
208
|
*
|
|
202
|
-
*
|
|
203
|
-
* task
|
|
209
|
+
* // 流式取消 (在组件销毁或页面关闭时调用)
|
|
210
|
+
* task?.offChunkReceived(); // 取消监听,中断流式接收
|
|
211
|
+
* task?.abort(); // 取消请求 (若流式已生成,此时abort无效,因为请求已成功)
|
|
204
212
|
*/
|
|
205
213
|
export function request<T, D extends RequestData = RequestData>(config: RequestConfigBase<D>) {
|
|
214
|
+
const {
|
|
215
|
+
url,
|
|
216
|
+
data,
|
|
217
|
+
header,
|
|
218
|
+
method = 'GET',
|
|
219
|
+
resKey,
|
|
220
|
+
msgKey,
|
|
221
|
+
codeKey,
|
|
222
|
+
successKey,
|
|
223
|
+
successCode,
|
|
224
|
+
reloginCode,
|
|
225
|
+
showLoading = true,
|
|
226
|
+
toastError = true,
|
|
227
|
+
enableChunked = false,
|
|
228
|
+
cacheTime,
|
|
229
|
+
resMap,
|
|
230
|
+
responseType = 'json',
|
|
231
|
+
timeout = 60000,
|
|
232
|
+
onTaskReady,
|
|
233
|
+
} = config;
|
|
234
|
+
|
|
206
235
|
// 1. 初始化控制对象
|
|
207
236
|
const controller = new AbortController();
|
|
208
237
|
const signal = controller.signal;
|
|
@@ -218,30 +247,11 @@ export function request<T, D extends RequestData = RequestData>(config: RequestC
|
|
|
218
247
|
chunkCallback = null;
|
|
219
248
|
},
|
|
220
249
|
};
|
|
250
|
+
onTaskReady?.(task);
|
|
221
251
|
|
|
222
252
|
// 2. 创建 Promise
|
|
223
|
-
|
|
253
|
+
return new Promise<T>((resolve, reject) => {
|
|
224
254
|
const execute = async () => {
|
|
225
|
-
const {
|
|
226
|
-
url,
|
|
227
|
-
data,
|
|
228
|
-
header,
|
|
229
|
-
method = 'GET',
|
|
230
|
-
resKey,
|
|
231
|
-
msgKey,
|
|
232
|
-
codeKey,
|
|
233
|
-
successKey,
|
|
234
|
-
successCode,
|
|
235
|
-
reloginCode,
|
|
236
|
-
showLoading = true,
|
|
237
|
-
toastError = true,
|
|
238
|
-
enableChunked = false,
|
|
239
|
-
cacheTime,
|
|
240
|
-
responseInterceptor,
|
|
241
|
-
responseType = 'json',
|
|
242
|
-
timeout = 60000,
|
|
243
|
-
} = config;
|
|
244
|
-
|
|
245
255
|
const isGet = method === 'GET';
|
|
246
256
|
const isObjectData = isPlainObject(data);
|
|
247
257
|
const isArrayData = !isObjectData && Array.isArray(data);
|
|
@@ -353,7 +363,7 @@ export function request<T, D extends RequestData = RequestData>(config: RequestC
|
|
|
353
363
|
if (showLoading) appConfig.hideLoading?.();
|
|
354
364
|
|
|
355
365
|
// 响应拦截
|
|
356
|
-
const res =
|
|
366
|
+
const res = resMap ? resMap(resData) : resData;
|
|
357
367
|
|
|
358
368
|
// 2.10 业务状态码解析
|
|
359
369
|
const code = getObjectValue(res, codeKey);
|
|
@@ -399,12 +409,7 @@ export function request<T, D extends RequestData = RequestData>(config: RequestC
|
|
|
399
409
|
};
|
|
400
410
|
|
|
401
411
|
execute();
|
|
402
|
-
})
|
|
403
|
-
|
|
404
|
-
// 3. 挂载 Task
|
|
405
|
-
promise.task = task;
|
|
406
|
-
|
|
407
|
-
return promise;
|
|
412
|
+
});
|
|
408
413
|
}
|
|
409
414
|
|
|
410
415
|
/**
|
|
@@ -443,9 +448,9 @@ function logRequestInfo(options: {
|
|
|
443
448
|
e?: unknown;
|
|
444
449
|
}) {
|
|
445
450
|
const { log } = getBaseToolsConfig();
|
|
446
|
-
const {
|
|
451
|
+
const { showLog = true } = options.config;
|
|
447
452
|
|
|
448
|
-
if (!log || !
|
|
453
|
+
if (!log || !showLog) return;
|
|
449
454
|
|
|
450
455
|
const { config, res, fromCache = false, startTime, status, e } = options;
|
|
451
456
|
const { url, data, header, method, logExtra } = config;
|
|
@@ -52,19 +52,15 @@ export type UploadFail = {
|
|
|
52
52
|
status: number;
|
|
53
53
|
};
|
|
54
54
|
|
|
55
|
-
function upload
|
|
56
|
-
return new Promise<
|
|
55
|
+
function upload(option: UploadFileOption, config?: UploadConfig) {
|
|
56
|
+
return new Promise<string>((resolve, reject) => {
|
|
57
57
|
const xhr = new XMLHttpRequest();
|
|
58
58
|
const { url, file, name = 'file', header, formData, timeout = 0 } = option;
|
|
59
59
|
|
|
60
60
|
const fail = (error: UploadFail) => reject(error);
|
|
61
61
|
|
|
62
62
|
const success = (responseText: string) => {
|
|
63
|
-
|
|
64
|
-
resolve(JSON.parse(responseText) as T);
|
|
65
|
-
} catch (e) {
|
|
66
|
-
resolve(responseText as T);
|
|
67
|
-
}
|
|
63
|
+
resolve(responseText);
|
|
68
64
|
};
|
|
69
65
|
|
|
70
66
|
// 构造任务对象
|