setup.ts 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275
  1. import Axios from 'axios'
  2. import { ResCode } from './constant'
  3. import type { AxiosResponse, AxiosRequestConfig } from 'axios'
  4. import { ui18n } from '@/lang'
  5. export type ResErrorHandler = <D, T extends ResData<D>>(
  6. response: AxiosResponse<T>,
  7. data?: T
  8. ) => void
  9. export type ReqErrorHandler = <T>(
  10. err: Error,
  11. response: AxiosRequestConfig<T>
  12. ) => void
  13. export type ResData<T> = {
  14. code: ResCode
  15. message: string
  16. data: T
  17. msg: string
  18. }
  19. export type Hook = {
  20. before?: (config: AxiosRequestConfig) => void
  21. after?: (config: AxiosRequestConfig) => void
  22. }
  23. export const axiosFactory = () => {
  24. const axiosRaw = Axios.create()
  25. const axiosConfig = {
  26. token: localStorage.getItem('token'),
  27. unTokenSet: [] as string[],
  28. unReqErrorSet: [] as string[],
  29. unResErrorSet: [] as string[],
  30. resErrorHandler: [] as ResErrorHandler[],
  31. reqErrorHandler: [] as ReqErrorHandler[],
  32. unLoadingSet: [] as string[],
  33. hook: [] as Hook[]
  34. }
  35. type AxiosConfig = typeof axiosConfig
  36. type ExponseApi<K extends keyof AxiosConfig> = {
  37. set: (val: AxiosConfig[K]) => void
  38. } & (AxiosConfig[K] extends Array<any>
  39. ? {
  40. add: (...val: AxiosConfig[K]) => void
  41. del: (...val: AxiosConfig[K]) => void
  42. }
  43. : { del: () => void })
  44. const getExponseApi = <K extends keyof AxiosConfig>(
  45. key: K
  46. ): ExponseApi<K> => {
  47. let axiosObj = axiosConfig[key] as any[]
  48. const apis: any = {
  49. set(val: AxiosConfig[K]) {
  50. axiosObj = axiosConfig[key] = val as any
  51. }
  52. }
  53. if (Array.isArray(axiosObj)) {
  54. apis.add = (...val: any[]) => {
  55. axiosObj.push(...val)
  56. }
  57. apis.del = (...val: any[]) => {
  58. if (val) {
  59. apis.set(axiosObj.filter((item: any) => !val?.includes(item)) as any)
  60. } else {
  61. axiosObj.length = 0
  62. }
  63. }
  64. } else {
  65. apis.del = () => {
  66. axiosConfig[key] = undefined as any
  67. }
  68. }
  69. return apis
  70. }
  71. const getToken = () => axiosConfig.token
  72. const setToken = (token: string) => {
  73. localStorage.setItem('token', token)
  74. axiosConfig.token = token
  75. }
  76. const delToken = () => {
  77. localStorage.removeItem('token')
  78. axiosConfig.token = null
  79. }
  80. const {
  81. set: setUnsetTokenURLS,
  82. add: addUnsetTokenURLS,
  83. del: delUnsetTokenURLS
  84. } = getExponseApi('unTokenSet')
  85. const {
  86. set: setResErrorHandler,
  87. add: addResErrorHandler,
  88. del: delResErrorHandler
  89. } = getExponseApi('resErrorHandler')
  90. const {
  91. set: setUnsetReqErrorURLS,
  92. add: addUnsetReqErrorURLS,
  93. del: delUnsetReqErrorURLS
  94. } = getExponseApi('unReqErrorSet')
  95. const {
  96. set: setReqErrorHandler,
  97. add: addReqErrorHandler,
  98. del: delReqErrorHandler
  99. } = getExponseApi('reqErrorHandler')
  100. const {
  101. set: setUnsetResErrorURLS,
  102. add: addUnsetResErrorURLS,
  103. del: delUnsetResErrorURLS
  104. } = getExponseApi('unResErrorSet')
  105. const { set: setHook, add: addHook, del: delHook } = getExponseApi('hook')
  106. const setDefaultURI = (url: string) => {
  107. axiosRaw.defaults.baseURL = url
  108. }
  109. const matchURL = (urls: string[], config: AxiosRequestConfig<any>) =>
  110. config && config.url && urls.includes(config.url)
  111. const callErrorHandler = (key: 'req' | 'res', ...args: any[]) => {
  112. Promise.resolve().then(() => {
  113. const api = `${key}ErrorHandler`
  114. ;(axiosConfig as any)[api].forEach((handler: any) => handler(...args))
  115. })
  116. }
  117. axiosRaw.interceptors.request.use(config => {
  118. for (const hook of axiosConfig.hook) {
  119. hook.before && hook.before(config)
  120. }
  121. if (!matchURL(axiosConfig.unTokenSet, config)) {
  122. if (!axiosConfig.token) {
  123. if (!matchURL(axiosConfig.unReqErrorSet, config)) {
  124. const error = new Error(ui18n.t('sys.NO_ACCESS'))
  125. callErrorHandler('req', error, config)
  126. throw error
  127. }
  128. } else {
  129. config.headers = {
  130. ...config.headers,
  131. token: axiosConfig.token
  132. }
  133. }
  134. }
  135. return config
  136. })
  137. axiosRaw.interceptors.response.use(
  138. (response: AxiosResponse<ResData<any>>) => {
  139. for (const hook of axiosConfig.hook) {
  140. hook.after && hook.after(response.config)
  141. }
  142. if (matchURL(axiosConfig.unResErrorSet, response.config)) {
  143. return response
  144. }
  145. if (response.status !== 200) {
  146. callErrorHandler('res', response)
  147. throw new Error(response.statusText)
  148. } else if (response.data.code !== ResCode.SUCCESS) {
  149. callErrorHandler('res', response, response.data)
  150. if (response.data.code === ResCode.TOKEN_INVALID) {
  151. delToken()
  152. }
  153. throw new Error(response?.data?.message)
  154. } else {
  155. return response.data.data
  156. }
  157. },
  158. err => {
  159. for (const hook of axiosConfig.hook) {
  160. hook.after && hook.after(err.config)
  161. }
  162. if (!matchURL(axiosConfig.unResErrorSet, err.config)) {
  163. callErrorHandler('res', err.response)
  164. }
  165. throw new Error(err.response ? err.response.statusText : err)
  166. }
  167. )
  168. type AxiosProcess = {
  169. getUri(config?: AxiosRequestConfig): string
  170. request<R = any, D = any>(config: AxiosRequestConfig<D>): Promise<R>
  171. get<R = any, D = any>(
  172. url: string,
  173. config?: AxiosRequestConfig<D>
  174. ): Promise<R>
  175. delete<R = any, D = any>(
  176. url: string,
  177. config?: AxiosRequestConfig<D>
  178. ): Promise<R>
  179. head<R = any, D = any>(
  180. url: string,
  181. config?: AxiosRequestConfig<D>
  182. ): Promise<R>
  183. options<R = any, D = any>(
  184. url: string,
  185. config?: AxiosRequestConfig<D>
  186. ): Promise<R>
  187. post<R = any, D = any>(
  188. url: string,
  189. data?: D,
  190. config?: AxiosRequestConfig<D>
  191. ): Promise<R>
  192. put<R = any, D = any>(
  193. url: string,
  194. data?: D,
  195. config?: AxiosRequestConfig<D>
  196. ): Promise<R>
  197. patch<R = any, D = any>(
  198. url: string,
  199. data?: D,
  200. config?: AxiosRequestConfig<D>
  201. ): Promise<R>
  202. postForm<R = any, D = any>(
  203. url: string,
  204. data?: D,
  205. config?: AxiosRequestConfig<D>
  206. ): Promise<R>
  207. putForm<R = any, D = unknown>(
  208. url: string,
  209. data?: D,
  210. config?: AxiosRequestConfig<D>
  211. ): Promise<R>
  212. patchForm<R = any, D = any>(
  213. url: string,
  214. data?: D,
  215. config?: AxiosRequestConfig<D>
  216. ): Promise<R>
  217. }
  218. interface AxiosInstanceProcess extends AxiosProcess {
  219. <R = any>(config: AxiosRequestConfig): Promise<R>
  220. <R = any>(url: string, config?: AxiosRequestConfig): Promise<R>
  221. }
  222. const axios: AxiosInstanceProcess = axiosRaw as any
  223. return {
  224. axios,
  225. getToken,
  226. setToken,
  227. delToken,
  228. setUnsetTokenURLS,
  229. addUnsetTokenURLS,
  230. delUnsetTokenURLS,
  231. setResErrorHandler,
  232. addResErrorHandler,
  233. delResErrorHandler,
  234. setUnsetReqErrorURLS,
  235. addUnsetReqErrorURLS,
  236. delUnsetReqErrorURLS,
  237. setReqErrorHandler,
  238. addReqErrorHandler,
  239. delReqErrorHandler,
  240. setUnsetResErrorURLS,
  241. addUnsetResErrorURLS,
  242. delUnsetResErrorURLS,
  243. setDefaultURI,
  244. setHook,
  245. addHook,
  246. delHook
  247. }
  248. }
  249. export default axiosFactory