request.js 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  1. import axios from 'axios'
  2. import {
  3. MessageBox,
  4. Message
  5. } from 'element-ui'
  6. import store from '@/store'
  7. import router from '@/router'
  8. const config = {
  9. baseURL: process.env.VUE_APP_BASE_API,
  10. withCredentials: true, // send cookies when cross-domain requests
  11. timeout: 10000 // request timeout
  12. }
  13. // create an axios instance
  14. const service = axios.create(config)
  15. let baseUrl = process.env.VUE_APP_KEYCLOAK_OPTIONS_URL
  16. if (baseUrl.charAt(0) === '/') {
  17. baseUrl = `${location.origin}${baseUrl}`
  18. }
  19. const realm = process.env.VUE_APP_KEYCLOAK_OPTIONS_REALM
  20. const keycloakService = axios.create({
  21. ...config,
  22. baseURL: `${baseUrl}/admin/realms/${realm}`
  23. })
  24. const tenantService = axios.create(config)
  25. const CancelToken = axios.CancelToken
  26. let source = null
  27. function getCancelToken () {
  28. if (!source) {
  29. source = CancelToken.source()
  30. }
  31. return source.token
  32. }
  33. export function cancelRequest () {
  34. if (source) {
  35. source.cancel('abort')
  36. source = null
  37. }
  38. }
  39. // request interceptor
  40. service.interceptors.request.use(
  41. defaultRequestInterceptor,
  42. debug
  43. )
  44. keycloakService.interceptors.request.use(
  45. defaultRequestInterceptor,
  46. debug
  47. )
  48. tenantService.interceptors.request.use(
  49. defaultRequestInterceptor,
  50. debug
  51. )
  52. tenantService.interceptors.request.use(
  53. config => {
  54. const { tenant, org, user } = config.params || config.data || {}
  55. console.log('url', config.method, config.url)
  56. console.log('tenant', tenant)
  57. console.log('org', org)
  58. console.log('user', user)
  59. if (!tenant && !org && !user) {
  60. Message({
  61. type: 'warning',
  62. message: '缺失scope信息'
  63. })
  64. return Promise.reject()
  65. }
  66. return config
  67. },
  68. null
  69. )
  70. // response interceptor
  71. service.interceptors.response.use(
  72. responseInterceptor,
  73. responseErrorInterceptor
  74. )
  75. keycloakService.interceptors.response.use(
  76. response => response.data,
  77. responseErrorInterceptor
  78. )
  79. tenantService.interceptors.response.use(
  80. responseInterceptor,
  81. responseErrorInterceptor
  82. )
  83. export default service
  84. export const keycloakRequest = keycloakService
  85. export const tenantRequest = tenantService
  86. function defaultRequestInterceptor (config) {
  87. // do something before request is sent
  88. if (!store.getters.token) {
  89. return Promise.reject()
  90. }
  91. config.headers['Authorization'] = `Bearer ${store.getters.token}`
  92. if (!config.background) {
  93. config.cancelToken = getCancelToken()
  94. }
  95. return config
  96. }
  97. function debug (error) {
  98. console.log('http debug', error) // for debug
  99. return Promise.reject(error)
  100. }
  101. function responseInterceptor (response) {
  102. const res = response.data || {}
  103. if (res.success) {
  104. return res
  105. }
  106. if (!response.config?.custom) {
  107. Message({
  108. type: 'error',
  109. message: res.errMessage || '请求失败'
  110. })
  111. }
  112. return Promise.reject(res)
  113. }
  114. function responseErrorInterceptor (error) {
  115. const isCancel = !error || axios.isCancel(error)
  116. if (isCancel) {
  117. return Promise.reject({ isCancel })
  118. }
  119. const { response, config } = error
  120. if (response) {
  121. const { status } = response
  122. if (status === 401) {
  123. if (store.getters.token) {
  124. try {
  125. store.dispatch('user/clearToken')
  126. MessageBox.close()
  127. } finally {
  128. MessageBox.confirm(
  129. '登录状态已过期,请重新登录',
  130. '系统提示',
  131. {
  132. type: 'warning',
  133. confirmButtonText: '重新登录',
  134. center: true,
  135. showClose: false,
  136. showCancelButton: false,
  137. closeOnClickModal: false,
  138. closeOnPressEscape: false,
  139. closeOnHashChange: false
  140. }
  141. ).then(() => {
  142. store.dispatch('user/logout')
  143. })
  144. }
  145. }
  146. return Promise.reject({ isCancel: true })
  147. }
  148. if (status === 403) {
  149. Message({
  150. type: 'warning',
  151. message: '暂无相关权限,请联系管理员'
  152. })
  153. return Promise.reject({ isCancel: true })
  154. }
  155. if (status === 423) {
  156. try {
  157. store.dispatch('user/clearToken')
  158. MessageBox.close()
  159. } finally {
  160. MessageBox.confirm(
  161. '系统已锁定,请联系管理员',
  162. '系统提示',
  163. {
  164. type: 'warning',
  165. showClose: false,
  166. showConfirmButton: false,
  167. showCancelButton: false,
  168. closeOnClickModal: false,
  169. closeOnPressEscape: false,
  170. closeOnHashChange: false
  171. }
  172. )
  173. router.replace('/error')
  174. }
  175. return Promise.reject({ isCancel: true })
  176. }
  177. if (!config?.custom) {
  178. const { errMessage, errorMessage } = response.data
  179. Message({
  180. type: 'error',
  181. message: errMessage || errorMessage || `请求异常[${status}]`
  182. })
  183. }
  184. return Promise.reject({ ...response.data })
  185. }
  186. let { message } = error
  187. if (!config?.custom) {
  188. if (message) {
  189. if (/timeout/.test(message)) {
  190. message = '请求超时'
  191. }
  192. } else {
  193. message = '请求异常'
  194. }
  195. Message({
  196. type: 'error',
  197. message
  198. })
  199. }
  200. return Promise.reject({ errCode: -1, errMessage: message })
  201. }