@jetlinks-web/core 2.2.18 → 2.3.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/src/axios.ts CHANGED
@@ -1,354 +1,556 @@
1
1
  import { TOKEN_KEY, BASE_API, LOCAL_BASE_API } from '@jetlinks-web/constants'
2
- import {getToken, randomString} from '@jetlinks-web/utils'
2
+ import { getToken, randomString } from '@jetlinks-web/utils'
3
3
  import axios from 'axios'
4
+ import type { AxiosInstance } from 'axios'
5
+ import { isFunction, isObject } from 'lodash-es'
6
+
4
7
  import type {
5
- AxiosInstance,
6
- } from 'axios'
7
- import type { AxiosResponseRewrite } from '@jetlinks-web/types'
8
- import {isFunction, isObject} from 'lodash-es'
9
- import type { Options, ExpandRequestConfig, ExpandAxiosResponse, ExpandAxiosError, RequestOptions, PageResult, UpdateResult } from './type'
10
-
11
- export let instance: AxiosInstance = (window as any).JetlinksCore?.instance || null
12
-
13
- let _options: Options = {
14
- filter_url: [],
15
- code: 200,
16
- codeKey: 'status',
17
- timeout: 1000 * 15,
18
- handleRequest: undefined,
19
- handleResponse: undefined,
20
- handleError: undefined,
21
- langKey: 'lang',
22
- requestOptions: (config) => ({}),
23
- tokenExpiration: () => {},
24
- handleReconnect: () => Promise.resolve(),
25
- isCreateTokenRefresh: false
8
+ Options,
9
+ ExpandRequestConfig,
10
+ ExpandAxiosResponse,
11
+ AxiosResponseRewrite,
12
+ ExpandAxiosError,
13
+ RequestOptions,
14
+ PageResult,
15
+ UpdateResult
16
+ } from './type'
17
+
18
+ /**
19
+ * 扩展的 Options 接口,添加重复请求控制
20
+ */
21
+ export interface ExtendedOptions extends Options {
22
+ /**
23
+ * 是否取消重复请求,只保留最后一次
24
+ * @default false
25
+ */
26
+ cancelDuplicateRequests?: boolean
26
27
  }
27
28
 
28
- let failedQueue = [];
29
- let isRefreshing = false;
29
+ /**
30
+ * AxiosService 类 - 封装所有 axios 相关功能
31
+ */
32
+ export class AxiosService {
33
+ private instance: AxiosInstance | null = null
34
+ private options: ExtendedOptions
35
+ private failedQueue: Array<{ resolve: (token: string) => void; reject: (error: any) => void }> = []
36
+ private isRefreshing = false
37
+ private pendingRequests = new Map<string, AbortController>()
38
+ private isApp = (window as any).__MICRO_APP_ENVIRONMENT__
39
+
40
+ constructor(options?: Partial<ExtendedOptions>) {
41
+ this.options = {
42
+ filter_url: [],
43
+ code: 200,
44
+ codeKey: 'status',
45
+ timeout: 1000 * 15,
46
+ handleRequest: undefined,
47
+ handleResponse: undefined,
48
+ handleError: undefined,
49
+ langKey: 'lang',
50
+ requestOptions: (config) => ({}),
51
+ tokenExpiration: () => {},
52
+ handleReconnect: () => Promise.resolve(),
53
+ isCreateTokenRefresh: false,
54
+ cancelDuplicateRequests: false, // 默认关闭
55
+ ...options
56
+ }
30
57
 
31
- const isApp = (window as any).__MICRO_APP_ENVIRONMENT__
58
+ // 如果已经存在全局实例,使用它
59
+ if ((window as any).JetlinksCore?.instance) {
60
+ this.instance = (window as any).JetlinksCore.instance
61
+ }
62
+ }
32
63
 
33
- const pendingRequests = new Map<string, AbortController>();
34
- const requestRecords = (config: ExpandRequestConfig) => {
35
- const key = config.__requestKey
64
+ /**
65
+ * 初始化 axios 实例
66
+ */
67
+ initialize(options?: Partial<ExtendedOptions>): void {
68
+ if (options) {
69
+ this.options = { ...this.options, ...options }
70
+ }
36
71
 
37
- // 取消重复请求
38
- if (pendingRequests.has(key)) {
39
- pendingRequests.get(key)?.abort()
72
+ this.instance = axios.create({
73
+ withCredentials: false,
74
+ timeout: this.options.timeout,
75
+ baseURL: BASE_API
76
+ })
77
+
78
+ this.instance.interceptors.request.use(
79
+ (config) => this.handleRequest(config as ExpandRequestConfig),
80
+ (error) => this.errorHandler(error)
81
+ )
82
+
83
+ this.instance.interceptors.response.use(
84
+ (response) => this.handleResponse(response as unknown as ExpandAxiosResponse),
85
+ (error) => this.errorHandler(error as ExpandAxiosError<any>)
86
+ )
40
87
  }
41
88
 
42
- const controller = new AbortController()
43
- config.signal = controller.signal;
44
- config.__requestKey = randomString(32);
45
-
46
- pendingRequests.set(key, controller)
47
- }
89
+ /**
90
+ * 获取 axios 实例
91
+ */
92
+ getInstance(): AxiosInstance {
93
+ if (!this.instance) {
94
+ this.initialize()
95
+ }
96
+ return this.instance!
97
+ }
48
98
 
49
- const handleRequest = (config: ExpandRequestConfig) => {
50
- requestRecords(config)
51
- const token = getToken();
52
- const lang = localStorage.getItem(_options.langKey)
53
- const localBaseApi = localStorage.getItem(LOCAL_BASE_API)
99
+ /**
100
+ * 生成请求的唯一标识
101
+ * 如果启用了 cancelDuplicateRequests,则基于 method + url + params/data
102
+ * 否则使用随机字符串
103
+ */
104
+ private generateRequestKey(config: ExpandRequestConfig): string {
105
+
106
+ // 统一接口请求的唯一标识
107
+ const method = config.method?.toUpperCase() || 'GET'
108
+ const url = config.url || ''
109
+
110
+ // 序列化参数,用于判断是否为同一请求
111
+ const params = config.params || {}
112
+ const data = config.data || {}
113
+ const payload = method === 'GET' ? params : data
114
+
115
+ // 生成稳定的请求标识
116
+ let payloadStr = ''
117
+ try {
118
+ payloadStr = JSON.stringify(payload, Object.keys(payload).sort())
119
+ } catch {
120
+ payloadStr = randomString(16) // 降级为随机标识
121
+ }
54
122
 
55
- if (lang) {
56
- config.headers[_options.langKey] = lang
123
+ return `${method}:${url}:${payloadStr}`
57
124
  }
58
125
 
59
- if (localBaseApi && !config.baseURL) {
60
- const _url = config.url.startsWith('/') ? config.url : `/${config.url}`
61
- config.url = localBaseApi + _url
62
- }
126
+ /**
127
+ * 记录请求 - 支持 AbortController
128
+ */
129
+ private requestRecords(config: ExpandRequestConfig): void {
130
+ if (!this.options.cancelDuplicateRequests) {
131
+ return
132
+ }
63
133
 
64
- // 没有token,并且该接口需要token校验
65
- if (!token && !_options.filter_url?.some((url) => config.url?.includes(url))) {
66
- // 跳转登录页
67
- _options.tokenExpiration?.()
68
- return config
69
- }
134
+ const key = this.generateRequestKey(config)
135
+
136
+ // 如果启用了取消重复请求,且存在相同的请求,则取消前一个
137
+ if (this.pendingRequests.has(key)) {
138
+ this.pendingRequests.get(key)?.abort()
139
+ this.pendingRequests.delete(key)
140
+ }
141
+
142
+ const controller = new AbortController()
143
+ config.signal = controller.signal
144
+ config.__requestKey = key
70
145
 
71
- if (!config.headers[TOKEN_KEY]) {
72
- config.headers[TOKEN_KEY] = token
146
+ this.pendingRequests.set(key, controller)
73
147
  }
74
148
 
75
- if (_options.requestOptions && isFunction(_options.requestOptions)) {
76
- const extraOptions = _options.requestOptions(config)
77
- if (extraOptions && isObject(extraOptions)) {
78
- for (const key in extraOptions) {
79
- config[key] = extraOptions[key]
149
+ /**
150
+ * 请求拦截器处理
151
+ */
152
+ private handleRequest(config: ExpandRequestConfig): ExpandRequestConfig {
153
+ this.requestRecords(config)
154
+ const token = getToken()
155
+ const lang = localStorage.getItem(this.options.langKey!)
156
+ const localBaseApi = localStorage.getItem(LOCAL_BASE_API)
157
+
158
+ if (lang) {
159
+ config.headers[this.options.langKey!] = lang
160
+ }
161
+
162
+ if (localBaseApi && !config.baseURL) {
163
+ const _url = config.url!.startsWith('/') ? config.url : `/${config.url}`
164
+ config.url = localBaseApi + _url
165
+ }
166
+
167
+ // 没有token,并且该接口需要token校验
168
+ if (!token && !this.options.filter_url?.some((url) => config.url?.includes(url))) {
169
+ this.options.tokenExpiration?.()
170
+ return config
171
+ }
172
+
173
+ if (!config.headers[TOKEN_KEY]) {
174
+ config.headers[TOKEN_KEY] = token
175
+ }
176
+
177
+ if (this.options.requestOptions && isFunction(this.options.requestOptions)) {
178
+ const extraOptions = this.options.requestOptions(config)
179
+ if (extraOptions && isObject(extraOptions)) {
180
+ for (const key in extraOptions) {
181
+ config[key] = extraOptions[key]
182
+ }
80
183
  }
81
184
  }
185
+
186
+ return config
82
187
  }
83
188
 
84
- return config
85
- }
189
+ /**
190
+ * 响应拦截器处理
191
+ */
192
+ private handleResponse(response: ExpandAxiosResponse): any {
193
+ const __key = response.config?.__requestKey
194
+ if (__key) {
195
+ this.pendingRequests.delete(__key)
196
+ }
86
197
 
87
- const handleResponse = (response: ExpandAxiosResponse) => {
88
- if (_options.handleResponse && isFunction(_options.handleResponse)) {
89
- return _options.handleResponse(response)
90
- }
198
+ if (this.options.handleResponse && isFunction(this.options.handleResponse)) {
199
+ return this.options.handleResponse(response)
200
+ }
91
201
 
92
- const __key = response.config?.__requestKey
93
- if(__key){
94
- pendingRequests.delete(__key)
95
- }
202
+ if (response.data instanceof ArrayBuffer) {
203
+ return response
204
+ }
96
205
 
97
- if (response.data instanceof ArrayBuffer) {
98
- return response
99
- }
206
+ const status = response.data[this.options.codeKey || 'status']
100
207
 
101
- const status = response.data[_options.codeKey || 'status']
208
+ // 增加业务接口处理成功判断方式,只需要判断返回参数包含:success为true
209
+ if (
210
+ typeof response.data === 'object' &&
211
+ typeof response.data.success === 'undefined'
212
+ ) {
213
+ response.data.success = status === this.options.code
214
+ }
102
215
 
103
- // 增加业务接口处理成功判断方式,只需要判断返回参数包含:success为true
104
- if (
105
- typeof response.data === 'object' &&
106
- typeof response.data.success === 'undefined'
107
- ) {
108
- response.data.success = status === _options.code
216
+ return response.data
109
217
  }
110
218
 
111
- return response.data
112
- }
219
+ /**
220
+ * Token 刷新处理
221
+ */
222
+ private async createTokenRefreshHandler(err: ExpandAxiosError<any>): Promise<any> {
223
+ const originalRequest = err.config!
224
+
225
+ if (this.isRefreshing) {
226
+ // 记录之后失败的请求
227
+ return new Promise((resolve, reject) => {
228
+ this.failedQueue.push({ resolve, reject })
229
+ })
230
+ .then((_token) => {
231
+ if (originalRequest.signal?.aborted) {
232
+ return Promise.reject(new axios.Cancel('Request aborted'))
233
+ }
234
+
235
+ originalRequest.headers[TOKEN_KEY] = _token
236
+ return this.instance!(originalRequest)
237
+ })
238
+ .catch((err) => Promise.reject(err))
239
+ }
113
240
 
114
- const createTokenRefreshHandler = async (err) => {
115
- const originalRequest = err.config;
116
- if (isRefreshing) { // 记录之后失败的请求
117
- return new Promise((resolve, reject) => {
118
- failedQueue.push({ resolve, reject });
119
- }).then((_token) => {
120
- originalRequest.headers[TOKEN_KEY] = _token;
121
- return instance(originalRequest)
122
- }).catch(err => Promise.reject(err))
123
- }
124
- originalRequest._retry = true;
125
- isRefreshing = true;
126
- try {
127
- const loginResult = await _options.handleReconnect?.()
128
- if(loginResult){
129
- const token = getToken() // 更新请求头, 修改全部的token
130
- originalRequest.headers[TOKEN_KEY] = token;
131
- failedQueue.forEach(a => a.resolve(token));
132
- return instance(originalRequest);
241
+ originalRequest._retry = true
242
+ this.isRefreshing = true
243
+
244
+ try {
245
+ const loginResult = await this.options.handleReconnect?.()
246
+ if (loginResult) {
247
+ const token = getToken() // 更新请求头, 修改全部的token
248
+ originalRequest.headers[TOKEN_KEY] = token
249
+ this.failedQueue.forEach((a) => a.resolve(token))
250
+ return this.instance!(originalRequest)
251
+ }
252
+ } catch (err) {
253
+ this.failedQueue.forEach((cb) => cb.reject(err))
254
+ throw err
255
+ } finally {
256
+ this.failedQueue = []
257
+ this.isRefreshing = false
133
258
  }
134
- } catch (err) {
135
- failedQueue.forEach(cb => cb.reject(err));
136
- throw err;
137
- } finally {
138
- failedQueue = [];
139
- isRefreshing = false;
140
259
  }
141
- }
142
- const errorHandler = async (err: ExpandAxiosError<any>) => {
143
- let description = err.response?.message || 'Error'
144
- let _status: string | number = 0
145
- if (err.response) {
146
- const {data, status} = err.response
147
- _status = status
148
- switch (status) {
149
- case 400:
150
- case 403:
151
- case 500:
152
- description = (`${data?.message}`).substring(0, 90)
153
- break;
154
- case 401:
155
- description = err.response.data.result?.text || '用户未登录';
156
- _options.tokenExpiration?.(err)
157
- if(_options.isCreateTokenRefresh){
158
- return createTokenRefreshHandler(err)
159
- }
160
- break;
161
- case 404:
162
- description = err?.response?.data?.message || `${data?.error} ${data?.path}`
163
- break;
164
- default:
165
- break;
260
+
261
+ /**
262
+ * 错误处理
263
+ */
264
+ private async errorHandler(err: ExpandAxiosError<any>): Promise<any> {
265
+ // 清理请求记录
266
+ const __key = err.config?.__requestKey
267
+ if (__key) {
268
+ this.pendingRequests.delete(__key)
166
269
  }
167
- } else if (err.response === undefined) {
168
- description = err.message.includes('timeout') ? '接口响应超时' : err.message
169
- _status = 'timeout'
170
- }
171
270
 
172
- if (_options.handleError && isFunction(_options.handleError)) {
173
- _options.handleError(description, _status, err)
174
- }
271
+ // 如果是用户主动取消的请求,不做错误处理
272
+ if (axios.isCancel(err as any)) {
273
+ return Promise.reject(err)
274
+ }
175
275
 
176
- return Promise.reject(err)
177
- }
276
+ let description = err.response?.message || 'Error'
277
+ let _status: string | number = 0
278
+
279
+ const response = err.response
280
+ if (response) {
281
+ const { data, status } = response
282
+ _status = status
283
+
284
+ switch (status) {
285
+ case 400:
286
+ case 403:
287
+ case 500:
288
+ description = `${data?.message}`.substring(0, 90)
289
+ break
290
+ case 401:
291
+ description = (data as any)?.result?.text || '用户未登录'
292
+ this.options.tokenExpiration?.(err as any)
293
+ if (this.options.isCreateTokenRefresh) {
294
+ return this.createTokenRefreshHandler(err)
295
+ }
296
+ break
297
+ case 404:
298
+ description = data?.message || `${(data as any)?.error} ${(data as any)?.path}`
299
+ break
300
+ default:
301
+ break
302
+ }
303
+ } else {
304
+ const errAny = err as any
305
+ if (errAny.message) {
306
+ description = errAny.message.includes('timeout') ? '接口响应超时' : errAny.message
307
+ _status = 'timeout'
308
+ }
309
+ }
178
310
 
179
- export const abortAllRequests = () => {
180
- pendingRequests.forEach(controller => controller.abort())
181
- pendingRequests.clear()
182
- }
311
+ if (this.options.handleError && isFunction(this.options.handleError)) {
312
+ this.options.handleError(description, _status, err as any)
313
+ }
183
314
 
184
- export const crateAxios = (options: Options) => {
185
- if (options) {
186
- _options = Object.assign(_options, options)
315
+ return Promise.reject(err)
187
316
  }
188
317
 
189
- instance = axios.create({
190
- withCredentials: false,
191
- timeout: _options.timeout,
192
- baseURL: BASE_API
193
- })
318
+ /**
319
+ * 取消所有进行中的请求
320
+ */
321
+ abortAllRequests(): void {
322
+ this.pendingRequests.forEach((controller) => controller.abort())
323
+ this.pendingRequests.clear()
324
+ }
194
325
 
195
- instance.interceptors.request.use(
196
- handleRequest,
197
- errorHandler
198
- )
326
+ /**
327
+ * 取消特定请求
328
+ */
329
+ abortRequest(requestKey: string): void {
330
+ const controller = this.pendingRequests.get(requestKey)
331
+ if (controller) {
332
+ controller.abort()
333
+ this.pendingRequests.delete(requestKey)
334
+ }
335
+ }
199
336
 
200
- instance.interceptors.response.use(
201
- handleResponse,
202
- errorHandler
203
- )
204
- }
337
+ /**
338
+ * 获取当前进行中的请求数量
339
+ */
340
+ getPendingRequestsCount(): number {
341
+ return this.pendingRequests.size
342
+ }
205
343
 
206
- export const post = <T = any>(url: string, data: any = {}, ext?: any) => {
207
- return (instance<any, AxiosResponseRewrite<T>>({
208
- method: 'POST',
209
- url,
210
- data,
211
- ...ext,
212
- }))
213
- }
344
+ /**
345
+ * HTTP 方法封装 - POST
346
+ */
347
+ post<T = any>(url: string, data: any = {}, ext?: any): Promise<AxiosResponseRewrite<T>> {
348
+ return this.getInstance()<any, AxiosResponseRewrite<T>>({
349
+ method: 'POST',
350
+ url,
351
+ data,
352
+ ...ext
353
+ })
354
+ }
214
355
 
215
- export const get = <T = any>(url: string, params: any = undefined, ext?: any) => {
216
- return instance<any, AxiosResponseRewrite<T>>({
217
- method: 'GET',
218
- url,
219
- params,
220
- ...ext,
221
- })
222
- }
356
+ /**
357
+ * HTTP 方法封装 - GET
358
+ */
359
+ get<T = any>(url: string, params: any = undefined, ext?: any): Promise<AxiosResponseRewrite<T>> {
360
+ return this.getInstance()<any, AxiosResponseRewrite<T>>({
361
+ method: 'GET',
362
+ url,
363
+ params,
364
+ ...ext
365
+ })
366
+ }
223
367
 
224
- export const put = <T = any>(url: string, data: any = {}, ext?: any) => {
225
- return instance<any, AxiosResponseRewrite<T>>({
226
- method: 'PUT',
227
- url,
228
- data,
229
- ...ext,
230
- })
231
- }
368
+ /**
369
+ * HTTP 方法封装 - PUT
370
+ */
371
+ put<T = any>(url: string, data: any = {}, ext?: any): Promise<AxiosResponseRewrite<T>> {
372
+ return this.getInstance()<any, AxiosResponseRewrite<T>>({
373
+ method: 'PUT',
374
+ url,
375
+ data,
376
+ ...ext
377
+ })
378
+ }
232
379
 
233
- export const patch = <T = any>(url: string, data: any = {}, ext?: any) => {
234
- return instance<any, AxiosResponseRewrite<T>>({
235
- method: 'patch',
236
- url,
237
- data,
238
- ...ext,
239
- })
240
- }
380
+ /**
381
+ * HTTP 方法封装 - PATCH
382
+ */
383
+ patch<T = any>(url: string, data: any = {}, ext?: any): Promise<AxiosResponseRewrite<T>> {
384
+ return this.getInstance()<any, AxiosResponseRewrite<T>>({
385
+ method: 'PATCH',
386
+ url,
387
+ data,
388
+ ...ext
389
+ })
390
+ }
241
391
 
242
- export const remove = <T = any>(url: string, params: any = undefined, ext?: any) => {
243
- return instance<any, AxiosResponseRewrite<T>>({
244
- method: 'DELETE',
245
- url,
246
- params,
247
- ...ext,
248
- })
249
- }
392
+ /**
393
+ * HTTP 方法封装 - DELETE
394
+ */
395
+ remove<T = any>(url: string, params: any = undefined, ext?: any): Promise<AxiosResponseRewrite<T>> {
396
+ return this.getInstance()<any, AxiosResponseRewrite<T>>({
397
+ method: 'DELETE',
398
+ url,
399
+ params,
400
+ ...ext
401
+ })
402
+ }
250
403
 
251
- export const getStream = (url: string, params?: any, ext?: any) => {
252
- return get(url, params, { responseType: 'arraybuffer', ...ext })
253
- }
404
+ /**
405
+ * 获取流数据 - GET
406
+ */
407
+ getStream(url: string, params?: any, ext?: any): Promise<any> {
408
+ return this.get(url, params, { responseType: 'arraybuffer', ...ext })
409
+ }
254
410
 
255
- export const postStream = (url: string, data: any, ext?: any) => {
256
- return post(url, data, { responseType: 'arraybuffer', ...ext })
411
+ /**
412
+ * 获取流数据 - POST
413
+ */
414
+ postStream(url: string, data: any, ext?: any): Promise<any> {
415
+ return this.post(url, data, { responseType: 'arraybuffer', ...ext })
416
+ }
257
417
  }
258
418
 
259
- export const request = {
260
- post, get, put, patch, remove, getStream, postStream
419
+ // 创建默认的 AxiosService 实例
420
+ const defaultAxiosService = new AxiosService()
421
+
422
+ // 导出默认实例和工厂函数
423
+ export const createAxiosService = (options?: Partial<ExtendedOptions>): AxiosService => {
424
+ const service = new AxiosService(options)
425
+ service.initialize()
426
+ return service
261
427
  }
262
428
 
429
+
430
+ /**
431
+ * Request 类 - 业务请求封装
432
+ * 默认使用全局共享的 axios 实例,特殊情况可传入自定义实例
433
+ */
263
434
  export class Request {
435
+ private _instance?: AxiosInstance
264
436
 
265
- constructor(public basePath: string) {
437
+ constructor(public basePath: string, instance?: AxiosInstance) {
266
438
  this.basePath = basePath.startsWith('/') ? basePath : `/${basePath}`
439
+ this._instance = instance
440
+ }
441
+
442
+ /**
443
+ * 获取 axios 实例
444
+ * 延迟获取以确保全局实例已初始化
445
+ */
446
+ private get instance(): AxiosInstance {
447
+ return this._instance || defaultAxiosService.getInstance()
267
448
  }
268
449
 
269
450
  private requestWrapper<T = any>(
270
451
  defaultUrl: string,
271
- defaultMethod: 'post'| 'get'| 'put'| 'patch'| 'remove'| 'getStream'| 'postStream',
452
+ defaultMethod: 'post' | 'get' | 'put' | 'patch' | 'remove' | 'getStream' | 'postStream',
272
453
  dataOrParams: any = {},
273
454
  options: RequestOptions = {}
274
455
  ): Promise<AxiosResponseRewrite<T>> {
275
456
  const { url = defaultUrl, method = defaultMethod, ...rest } = options
276
- return request[method]<T>(`${this.basePath}${url}`, dataOrParams, rest)
457
+ const fn = this[method] as (url: string, dataOrParams: any, options?: any) => Promise<AxiosResponseRewrite<T>>
458
+ return fn.call(this, url, dataOrParams, rest)
277
459
  }
278
460
 
279
461
  /**
280
462
  * 分页查询
281
- * @param {object} data 查询参数
282
- * @param {object} options 请求配置
463
+ * @param data 查询参数
464
+ * @param options 请求配置
283
465
  */
284
- page<T = any>(data: any={}, options: RequestOptions= {
285
- url: undefined,
286
- method: undefined,
287
- }) {
466
+ page<T = any>(
467
+ data: any = {},
468
+ options: RequestOptions = {
469
+ url: undefined,
470
+ method: undefined
471
+ }
472
+ ): Promise<AxiosResponseRewrite<PageResult<T>>> {
288
473
  return this.requestWrapper<PageResult<T>>('/_query', 'post', data, options)
289
474
  }
290
475
 
291
476
  /**
292
477
  * 不分页查询
293
- * @param {object} data 查询参数
294
- * @param {object} options 请求配置
478
+ * @param data 查询参数
479
+ * @param options 请求配置
295
480
  */
296
- noPage<T = any>(data: any={}, options: RequestOptions = {
297
- url: undefined,
298
- method: undefined,
299
- }) {
481
+ noPage<T = any>(
482
+ data: any = {},
483
+ options: RequestOptions = {
484
+ url: undefined,
485
+ method: undefined
486
+ }
487
+ ): Promise<AxiosResponseRewrite<T[]>> {
300
488
  return this.requestWrapper<T[]>('/_query/no-paging', 'post', { paging: false, ...data }, options)
301
489
  }
302
490
 
303
491
  /**
304
492
  * 详情查询
305
- * @param {string} id 详情ID
306
- * @param {object} params 查询参数
307
- * @param {object} options 请求配置
493
+ * @param id 详情ID
494
+ * @param params 查询参数
495
+ * @param options 请求配置
308
496
  */
309
- detail<T = any>(id: string, params?: any, options: RequestOptions= {
310
- url: undefined,
311
- method: undefined,
312
- }) {
497
+ detail<T = any>(
498
+ id: string,
499
+ params?: any,
500
+ options: RequestOptions = {
501
+ url: undefined,
502
+ method: undefined
503
+ }
504
+ ): Promise<AxiosResponseRewrite<T>> {
313
505
  return this.requestWrapper<T>(`/${id}/detail`, 'get', params, options)
314
506
  }
315
507
 
316
508
  /**
317
509
  * 保存
318
- * @param {object} data 保存参数
319
- * @param {object} options 请求配置
510
+ * @param data 保存参数
511
+ * @param options 请求配置
320
512
  */
321
- save<T = any>(data: any={}, options: RequestOptions = {
322
- url: undefined,
323
- method: undefined,
324
- }) {
513
+ save<T = any>(
514
+ data: any = {},
515
+ options: RequestOptions = {
516
+ url: undefined,
517
+ method: undefined
518
+ }
519
+ ): Promise<AxiosResponseRewrite<T>> {
325
520
  return this.requestWrapper<T>('', 'post', data, options)
326
521
  }
327
522
 
328
523
  /**
329
524
  * 更新
330
- * @param {object} data 更新参数
331
- * @param {object} options 请求配置
525
+ * @param data 更新参数
526
+ * @param options 请求配置
332
527
  */
333
- update<T extends UpdateResult>(data: any={}, options: RequestOptions = {
334
- url: undefined,
335
- method: undefined,
336
- }) {
528
+ update<T extends UpdateResult>(
529
+ data: any = {},
530
+ options: RequestOptions = {
531
+ url: undefined,
532
+ method: undefined
533
+ }
534
+ ): Promise<AxiosResponseRewrite<T>> {
337
535
  return this.requestWrapper<T>('', 'patch', data, options)
338
536
  }
339
537
 
340
538
  /**
341
539
  * 删除
342
- * @param {string} id 删除ID
343
- * @param {object} params 请求参数
344
- * @param {object} options 请求配置
540
+ * @param id 删除ID
541
+ * @param params 请求参数
542
+ * @param options 请求配置
345
543
  * @example ${basePath}/${id}
346
544
  */
347
- delete<T = any>(id: string, params?: any, options: RequestOptions = {
348
- url: undefined,
349
- method: undefined,
350
- }) {
351
- return this.requestWrapper<T>(`/${id}`, 'post', params, options)
545
+ delete<T = any>(
546
+ id: string,
547
+ params?: any,
548
+ options: RequestOptions = {
549
+ url: undefined,
550
+ method: undefined
551
+ }
552
+ ): Promise<AxiosResponseRewrite<T>> {
553
+ return this.requestWrapper<T>(`/${id}`, 'remove', params, options)
352
554
  }
353
555
 
354
556
  /**
@@ -357,39 +559,98 @@ export class Request {
357
559
  * @param type
358
560
  * @param options
359
561
  */
360
- batch<T = any>(data = {}, type?: string, options?: RequestOptions) {
562
+ batch<T = any>(data = {}, type?: string, options?: RequestOptions): Promise<AxiosResponseRewrite<T>> {
361
563
  const url = `/_batch${type ? '/' + type : ''}`
362
564
  return this.requestWrapper<T>(url, 'post', data, options)
363
565
  }
364
566
 
365
- post<T = any>(url: string, data?: any, options?: any) {
366
- return post<T>(`${this.basePath}${url}`, data, options)
567
+ post<T = any>(url: string, data?: any, options?: any): Promise<AxiosResponseRewrite<T>> {
568
+ return this.instance<any, AxiosResponseRewrite<T>>({
569
+ method: 'POST',
570
+ url: `${this.basePath}${url}`,
571
+ data,
572
+ ...options
573
+ })
367
574
  }
368
575
 
369
- get<T = any>(url: string, params?: any, options?: any) {
370
- return get<T>(`${this.basePath}${url}`, params, options)
576
+ get<T = any>(url: string, params?: any, options?: any): Promise<AxiosResponseRewrite<T>> {
577
+ return this.instance<any, AxiosResponseRewrite<T>>({
578
+ method: 'GET',
579
+ url: `${this.basePath}${url}`,
580
+ params,
581
+ ...options
582
+ })
371
583
  }
372
584
 
373
- put<T = any>(url: string, data?: any, options?: any) {
374
- return put<T>(`${this.basePath}${url}`, data, options)
585
+ put<T = any>(url: string, data?: any, options?: any): Promise<AxiosResponseRewrite<T>> {
586
+ return this.instance<any, AxiosResponseRewrite<T>>({
587
+ method: 'PUT',
588
+ url: `${this.basePath}${url}`,
589
+ data,
590
+ ...options
591
+ })
375
592
  }
376
593
 
377
- patch<T = any>(url: string, data?: any, options?: any) {
378
- return patch<T>(`${this.basePath}${url}`, data, options)
594
+ patch<T = any>(url: string, data?: any, options?: any): Promise<AxiosResponseRewrite<T>> {
595
+ return this.instance<any, AxiosResponseRewrite<T>>({
596
+ method: 'PATCH',
597
+ url: `${this.basePath}${url}`,
598
+ data,
599
+ ...options
600
+ })
379
601
  }
380
602
 
381
- remove<T = any>(url: string, params?: any, options?: any) {
382
- return remove<T>(`${this.basePath}${url}`, params, options)
603
+ remove<T = any>(url: string, params?: any, options?: any): Promise<AxiosResponseRewrite<T>> {
604
+ return this.instance<any, AxiosResponseRewrite<T>>({
605
+ method: 'DELETE',
606
+ url: `${this.basePath}${url}`,
607
+ params,
608
+ ...options
609
+ })
383
610
  }
384
611
 
385
- getStream(url: string, params?: any, options?: any) {
386
- return get(`${this.basePath}${url}`, params, { responseType: 'arraybuffer', ...options })
612
+ getStream(url: string, params?: any, options?: any): Promise<any> {
613
+ return this.get(`${url}`, params, { responseType: 'arraybuffer', ...options })
387
614
  }
388
615
 
389
- postStream(url: string, data?: any, options?: any) {
390
- return post(`${this.basePath}${url}`, data, { responseType: 'arraybuffer', ...options })
616
+ postStream(url: string, data?: any, options?: any): Promise<any> {
617
+ return this.post(`${url}`, data, { responseType: 'arraybuffer', ...options })
391
618
  }
392
619
  }
393
620
 
621
+ // 导出默认 request 对象(保持向后兼容)
622
+ export const request = {
623
+ post: defaultAxiosService.post.bind(defaultAxiosService),
624
+ get: defaultAxiosService.get.bind(defaultAxiosService),
625
+ put: defaultAxiosService.put.bind(defaultAxiosService),
626
+ patch: defaultAxiosService.patch.bind(defaultAxiosService),
627
+ remove: defaultAxiosService.remove.bind(defaultAxiosService),
628
+ getStream: defaultAxiosService.getStream.bind(defaultAxiosService),
629
+ postStream: defaultAxiosService.postStream.bind(defaultAxiosService)
630
+ }
631
+
632
+ // 导出便捷函数(保持向后兼容)
633
+ export const post = defaultAxiosService.post.bind(defaultAxiosService)
634
+ export const get = defaultAxiosService.get.bind(defaultAxiosService)
635
+ export const put = defaultAxiosService.put.bind(defaultAxiosService)
636
+ export const patch = defaultAxiosService.patch.bind(defaultAxiosService)
637
+ export const remove = defaultAxiosService.remove.bind(defaultAxiosService)
638
+ export const getStream = defaultAxiosService.getStream.bind(defaultAxiosService)
639
+ export const postStream = defaultAxiosService.postStream.bind(defaultAxiosService)
394
640
 
641
+ // 导出工具函数
642
+ export const abortAllRequests = () => defaultAxiosService.abortAllRequests()
643
+
644
+ export const getInstance = () => defaultAxiosService.getInstance()
645
+
646
+ // 导出 axios 实例(兼容旧代码)
647
+ export let instance: AxiosInstance
648
+
649
+ // 导出初始化函数(兼容旧代码)
650
+ export const crateAxios = (options: ExtendedOptions) => {
651
+ defaultAxiosService.initialize(options)
652
+ instance = defaultAxiosService.getInstance()
653
+ }
395
654
 
655
+ // 导出默认服务实例
656
+ export default defaultAxiosService