提交 | 用户 | age
|
2f6253
|
1 |
// axios配置 可自行根据项目进行更改,只需更改该文件即可,其他文件可以不动 |
陈 |
2 |
// The axios configuration can be changed according to the project, just change the file, other files can be left unchanged |
|
3 |
|
|
4 |
import type { AxiosResponse } from 'axios'; |
b7ce74
|
5 |
import type { RequestOptions, Result } from './types'; |
V |
6 |
import type { AxiosTransform, CreateAxiosOptions } from './axiosTransform'; |
2f6253
|
7 |
|
b7ce74
|
8 |
import { VAxios } from './Axios'; |
2f6253
|
9 |
import { checkStatus } from './checkStatus'; |
陈 |
10 |
|
ba068b
|
11 |
import { useGlobSetting } from '/@/hooks/setting'; |
2f6253
|
12 |
import { useMessage } from '/@/hooks/web/useMessage'; |
陈 |
13 |
|
|
14 |
import { RequestEnum, ResultEnum, ContentTypeEnum } from '/@/enums/httpEnum'; |
|
15 |
|
|
16 |
import { isString } from '/@/utils/is'; |
b7ce74
|
17 |
import { getToken } from '/@/utils/auth'; |
2f6253
|
18 |
import { setObjToUrlParams, deepMerge } from '/@/utils'; |
215d8b
|
19 |
import { useErrorLogStoreWithOut } from '/@/store/modules/errorLog'; |
V |
20 |
|
190112
|
21 |
import { useI18n } from '/@/hooks/web/useI18n'; |
50f94b
|
22 |
import { joinTimestamp, formatRequestDate } from './helper'; |
2f6253
|
23 |
|
737b1b
|
24 |
const globSetting = useGlobSetting(); |
50f94b
|
25 |
const urlPrefix = globSetting.urlPrefix; |
2f6253
|
26 |
const { createMessage, createErrorModal } = useMessage(); |
陈 |
27 |
|
|
28 |
/** |
|
29 |
* @description: 数据处理,方便区分多种处理方式 |
|
30 |
*/ |
|
31 |
const transform: AxiosTransform = { |
|
32 |
/** |
b218f1
|
33 |
* @description: 处理请求数据。如果数据不是预期格式,可直接抛出错误 |
2f6253
|
34 |
*/ |
a821d9
|
35 |
transformRequestHook: (res: AxiosResponse<Result>, options: RequestOptions) => { |
962f90
|
36 |
const { t } = useI18n(); |
56d8af
|
37 |
const { isTransformRequestResult, isReturnNativeResponse } = options; |
Z |
38 |
// 是否返回原生响应头 比如:需要获取响应头时使用该属性 |
|
39 |
if (isReturnNativeResponse) { |
|
40 |
return res; |
|
41 |
} |
2f6253
|
42 |
// 不进行任何处理,直接返回 |
陈 |
43 |
// 用于页面代码可能需要直接获取code,data,message这些信息时开启 |
|
44 |
if (!isTransformRequestResult) { |
|
45 |
return res.data; |
|
46 |
} |
|
47 |
// 错误的时候返回 |
|
48 |
|
|
49 |
const { data } = res; |
|
50 |
if (!data) { |
|
51 |
// return '[HTTP] Request has no return value'; |
b218f1
|
52 |
throw new Error(t('sys.api.apiRequestFailed')); |
2f6253
|
53 |
} |
陈 |
54 |
// 这里 code,result,message为 后台统一的字段,需要在 types.ts内修改为项目自己的接口返回格式 |
|
55 |
const { code, result, message } = data; |
|
56 |
|
|
57 |
// 这里逻辑可以根据项目进行修改 |
|
58 |
const hasSuccess = data && Reflect.has(data, 'code') && code === ResultEnum.SUCCESS; |
b69dcd
|
59 |
if (hasSuccess) { |
e83cb0
|
60 |
return result; |
2f6253
|
61 |
} |
b69dcd
|
62 |
|
无 |
63 |
// 在此处根据自己项目的实际情况对不同的code执行不同的操作 |
|
64 |
// 如果不希望中断当前请求,请return数据,否则直接抛出异常即可 |
49b66e
|
65 |
let timeoutMsg = ''; |
b69dcd
|
66 |
switch (code) { |
无 |
67 |
case ResultEnum.TIMEOUT: |
49b66e
|
68 |
timeoutMsg = t('sys.api.timeoutMessage'); |
b69dcd
|
69 |
default: |
无 |
70 |
if (message) { |
49b66e
|
71 |
timeoutMsg = message; |
b69dcd
|
72 |
} |
2f6253
|
73 |
} |
49b66e
|
74 |
|
X |
75 |
// errorMessageMode=‘modal’的时候会显示modal错误弹窗,而不是消息提示,用于一些比较重要的错误 |
|
76 |
// errorMessageMode='none' 一般是调用时明确表示不希望自动弹出错误提示 |
|
77 |
if (options.errorMessageMode === 'modal') { |
|
78 |
createErrorModal({ title: t('sys.api.errorTip'), content: timeoutMsg }); |
|
79 |
} else if (options.errorMessageMode === 'message') { |
|
80 |
createMessage.error(timeoutMsg); |
|
81 |
} |
|
82 |
|
|
83 |
throw new Error(timeoutMsg || t('sys.api.apiRequestFailed')); |
2f6253
|
84 |
}, |
陈 |
85 |
|
|
86 |
// 请求之前处理config |
|
87 |
beforeRequestHook: (config, options) => { |
f646e3
|
88 |
const { apiUrl, joinPrefix, joinParamsToUrl, formatDate, joinTime = true } = options; |
2f6253
|
89 |
|
陈 |
90 |
if (joinPrefix) { |
50f94b
|
91 |
config.url = `${urlPrefix}${config.url}`; |
2f6253
|
92 |
} |
陈 |
93 |
|
|
94 |
if (apiUrl && isString(apiUrl)) { |
|
95 |
config.url = `${apiUrl}${config.url}`; |
|
96 |
} |
ac1a36
|
97 |
const params = config.params || {}; |
6b3195
|
98 |
if (config.method?.toUpperCase() === RequestEnum.GET) { |
ac1a36
|
99 |
if (!isString(params)) { |
c96002
|
100 |
// 给 get 请求加上时间戳参数,避免从缓存中拿数据。 |
50f94b
|
101 |
config.params = Object.assign(params || {}, joinTimestamp(joinTime, false)); |
2f6253
|
102 |
} else { |
陈 |
103 |
// 兼容restful风格 |
50f94b
|
104 |
config.url = config.url + params + `${joinTimestamp(joinTime, true)}`; |
34c09f
|
105 |
config.params = undefined; |
2f6253
|
106 |
} |
陈 |
107 |
} else { |
ac1a36
|
108 |
if (!isString(params)) { |
V |
109 |
formatDate && formatRequestDate(params); |
|
110 |
config.data = params; |
34c09f
|
111 |
config.params = undefined; |
2f6253
|
112 |
if (joinParamsToUrl) { |
陈 |
113 |
config.url = setObjToUrlParams(config.url as string, config.data); |
|
114 |
} |
|
115 |
} else { |
|
116 |
// 兼容restful风格 |
ac1a36
|
117 |
config.url = config.url + params; |
34c09f
|
118 |
config.params = undefined; |
2f6253
|
119 |
} |
陈 |
120 |
} |
|
121 |
return config; |
|
122 |
}, |
|
123 |
|
|
124 |
/** |
|
125 |
* @description: 请求拦截器处理 |
|
126 |
*/ |
|
127 |
requestInterceptors: (config) => { |
|
128 |
// 请求之前处理config |
b7ce74
|
129 |
const token = getToken(); |
2f6253
|
130 |
if (token) { |
陈 |
131 |
// jwt token |
|
132 |
config.headers.Authorization = token; |
|
133 |
} |
|
134 |
return config; |
|
135 |
}, |
|
136 |
|
|
137 |
/** |
49b66e
|
138 |
* @description: 响应拦截器处理 |
X |
139 |
*/ |
|
140 |
responseInterceptors: (res: AxiosResponse<any>) => { |
|
141 |
return res; |
|
142 |
}, |
|
143 |
|
|
144 |
/** |
2f6253
|
145 |
* @description: 响应错误处理 |
陈 |
146 |
*/ |
|
147 |
responseInterceptorsCatch: (error: any) => { |
962f90
|
148 |
const { t } = useI18n(); |
215d8b
|
149 |
const errorLogStore = useErrorLogStoreWithOut(); |
V |
150 |
errorLogStore.addAjaxErrorInfo(error); |
49b66e
|
151 |
const { response, code, message, config } = error || {}; |
X |
152 |
const errorMessageMode = config?.requestOptions?.errorMessageMode || 'none'; |
de5bf7
|
153 |
const msg: string = response?.data?.error?.message ?? ''; |
V |
154 |
const err: string = error?.toString?.() ?? ''; |
49b66e
|
155 |
let errMessage = ''; |
X |
156 |
|
2f6253
|
157 |
try { |
陈 |
158 |
if (code === 'ECONNABORTED' && message.indexOf('timeout') !== -1) { |
49b66e
|
159 |
errMessage = t('sys.api.apiTimeoutMessage'); |
2f6253
|
160 |
} |
6b3195
|
161 |
if (err?.includes('Network Error')) { |
49b66e
|
162 |
errMessage = t('sys.api.networkExceptionMsg'); |
X |
163 |
} |
|
164 |
|
|
165 |
if (errMessage) { |
|
166 |
if (errorMessageMode === 'modal') { |
|
167 |
createErrorModal({ title: t('sys.api.errorTip'), content: errMessage }); |
|
168 |
} else if (errorMessageMode === 'message') { |
|
169 |
createMessage.error(errMessage); |
|
170 |
} |
|
171 |
return Promise.reject(error); |
2f6253
|
172 |
} |
陈 |
173 |
} catch (error) { |
|
174 |
throw new Error(error); |
|
175 |
} |
49b66e
|
176 |
|
X |
177 |
checkStatus(error?.response?.status, msg, errorMessageMode); |
661db0
|
178 |
return Promise.reject(error); |
2f6253
|
179 |
}, |
陈 |
180 |
}; |
|
181 |
|
|
182 |
function createAxios(opt?: Partial<CreateAxiosOptions>) { |
|
183 |
return new VAxios( |
|
184 |
deepMerge( |
|
185 |
{ |
|
186 |
timeout: 10 * 1000, |
|
187 |
// 基础接口地址 |
|
188 |
// baseURL: globSetting.apiUrl, |
|
189 |
// 接口可能会有通用的地址部分,可以统一抽取出来 |
50f94b
|
190 |
urlPrefix: urlPrefix, |
2f6253
|
191 |
headers: { 'Content-Type': ContentTypeEnum.JSON }, |
f646e3
|
192 |
// 如果是form-data格式 |
V |
193 |
// headers: { 'Content-Type': ContentTypeEnum.FORM_URLENCODED }, |
2f6253
|
194 |
// 数据处理方式 |
陈 |
195 |
transform, |
|
196 |
// 配置项,下面的选项都可以在独立的接口请求中覆盖 |
|
197 |
requestOptions: { |
|
198 |
// 默认将prefix 添加到url |
|
199 |
joinPrefix: true, |
56d8af
|
200 |
// 是否返回原生响应头 比如:需要获取响应头时使用该属性 |
Z |
201 |
isReturnNativeResponse: false, |
2f6253
|
202 |
// 需要对返回数据进行处理 |
陈 |
203 |
isTransformRequestResult: true, |
|
204 |
// post请求的时候添加参数到url |
|
205 |
joinParamsToUrl: false, |
|
206 |
// 格式化提交参数时间 |
|
207 |
formatDate: true, |
|
208 |
// 消息提示类型 |
4ce1d5
|
209 |
errorMessageMode: 'message', |
2f6253
|
210 |
// 接口地址 |
陈 |
211 |
apiUrl: globSetting.apiUrl, |
f646e3
|
212 |
// 是否加入时间戳 |
V |
213 |
joinTime: true, |
3b8ca4
|
214 |
// 忽略重复请求 |
V |
215 |
ignoreCancelToken: true, |
2f6253
|
216 |
}, |
陈 |
217 |
}, |
|
218 |
opt || {} |
|
219 |
) |
|
220 |
); |
|
221 |
} |
|
222 |
export const defHttp = createAxios(); |
|
223 |
|
|
224 |
// other api url |
|
225 |
// export const otherHttp = createAxios({ |
|
226 |
// requestOptions: { |
|
227 |
// apiUrl: 'xxx', |
|
228 |
// }, |
|
229 |
// }); |