request.js 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  1. import axios from 'axios'
  2. import { Message } from '@arco-design/web-vue'
  3. import tool from '@/utils/tool'
  4. import { get, isEmpty } from 'lodash'
  5. import qs from 'qs'
  6. import { h } from 'vue'
  7. import { IconFaceFrownFill } from '@arco-design/web-vue/dist/arco-vue-icon'
  8. import router from '@/router'
  9. function createExternalService() {
  10. // 创建一个外部网络 axios 实例
  11. const service = axios.create()
  12. // HTTP request 拦截器
  13. service.interceptors.request.use(
  14. (config) => config,
  15. (error) => Promise.reject(error)
  16. )
  17. // HTTP response 拦截器
  18. service.interceptors.response.use(
  19. (response) => response,
  20. (error) => {
  21. Promise.reject(error.response ?? null)
  22. }
  23. )
  24. return service
  25. }
  26. function createService() {
  27. // 创建一个 axios 实例
  28. const service = axios.create()
  29. // HTTP request 拦截器
  30. service.interceptors.request.use(
  31. (config) => config,
  32. (error) => {
  33. console.log(error)
  34. // 失败
  35. return Promise.reject(error)
  36. }
  37. )
  38. // HTTP response 拦截器
  39. service.interceptors.response.use(
  40. (response) => {
  41. if (
  42. (response.headers['content-disposition'] ||
  43. !/^application\/json/.test(response.headers['content-type'])) &&
  44. response.status === 200
  45. ) {
  46. return response
  47. } else if (response.data.size) {
  48. response.data.code = 500
  49. response.data.message = '服务器内部错误'
  50. response.data.success = false
  51. } else if (response.data.code && response.data.code !== 200) {
  52. if (response.data.code === 401) {
  53. throttle(() => {
  54. Message.error({
  55. content: response.data.message || response.data.msg,
  56. icon: () => h(IconFaceFrownFill)
  57. })
  58. tool.local.clear()
  59. router.push({ name: 'login' })
  60. })()
  61. } else {
  62. Message.error({
  63. content: response.data.message || response.data.msg,
  64. icon: () => h(IconFaceFrownFill)
  65. })
  66. }
  67. }
  68. return response.data
  69. },
  70. (error) => {
  71. const err = (text) => {
  72. Message.error({
  73. content:
  74. error.response && error.response.data && error.response.data.message
  75. ? error.response.data.message
  76. : text,
  77. icon: () => h(IconFaceFrownFill)
  78. })
  79. }
  80. if (error.response && error.response.data) {
  81. switch (error.response.status) {
  82. case 404:
  83. err('服务器资源不存在')
  84. break
  85. case 500:
  86. err('服务器内部错误')
  87. break
  88. case 401:
  89. throttle(() => {
  90. err('登录状态已过期,需要重新登录')
  91. tool.local.clear()
  92. router.push({ name: 'login' })
  93. })()
  94. break
  95. case 403:
  96. err('没有权限访问该资源')
  97. break
  98. default:
  99. err('未知错误!')
  100. }
  101. } else {
  102. err('请求超时,服务器无响应!')
  103. }
  104. return Promise.resolve({
  105. code: error.response.status || 500,
  106. message: error.response.statusText || '未知错误'
  107. })
  108. }
  109. )
  110. return service
  111. }
  112. //节流
  113. function throttle(fn, wait = 1500) {
  114. return function () {
  115. let context = this
  116. if (!throttle.timer) {
  117. fn.apply(context, arguments)
  118. throttle.timer = setTimeout(function () {
  119. throttle.timer = null
  120. }, wait)
  121. }
  122. }
  123. }
  124. function stringify(data) {
  125. return qs.stringify(data, { allowDots: true, encode: false })
  126. }
  127. function formatToken(token) {
  128. return token ? `Bearer ${token}` : null
  129. }
  130. /**
  131. * @description 创建请求方法
  132. * @param service
  133. * @param externalService
  134. */
  135. function createRequest(service, externalService) {
  136. return function (config) {
  137. const env = import.meta.env
  138. const token = tool.local.get(env.VITE_APP_TOKEN_PREFIX)
  139. const setting = tool.local.get('setting')
  140. const configDefault = {
  141. headers: Object.assign(
  142. {
  143. Authorization: formatToken(token),
  144. 'Accept-Language': setting?.language || 'zh_CN',
  145. 'Content-Type': get(
  146. config,
  147. 'headers.Content-Type',
  148. 'application/json;charset=UTF-8'
  149. )
  150. },
  151. config.headers
  152. ),
  153. timeout: 10000,
  154. data: {}
  155. }
  156. delete config.headers
  157. // return
  158. const option = Object.assign(configDefault, config)
  159. // json
  160. if (!isEmpty(option.params)) {
  161. option.url = option.url + '?' + stringify(option.params)
  162. option.params = {}
  163. }
  164. if (!/^(http|https)/g.test(option.url)) {
  165. option.baseURL =
  166. env.VITE_APP_OPEN_PROXY === 'true'
  167. ? env.VITE_APP_PROXY_PREFIX
  168. : env.VITE_APP_BASE_URL
  169. return service(option)
  170. } else {
  171. return externalService(option)
  172. }
  173. }
  174. }
  175. export const service = createService()
  176. export const externalService = createExternalService()
  177. export const request = createRequest(service, externalService)