declare const window: any // axios import axios from 'axios' // 全局配置 import _config from '@/config' // utils import { toFormData } from '@/utils' import { defaultHeaders, handleResponse, handleMessage } from '@/utils/request-utils' // mock import { mockRouter, isMockEnabled } from '@/mock' // 多系统绑定一个全局网关到window里面(作用: 方便运维打包自己可以修改网关) ;(function () { window.VUE_APP_SERVERAPI = window.VUE_APP_SERVERAPI // || process.env.VUE_APP_SERVERAPI })() // 处理瘦身api路由 const replaceApiUrl = (url) => { if (typeof url !== 'string') { console.error('[replaceApiUrl] url is not a string! typeof:', typeof url, 'value:', url) return url || '' } const newUrl = url.replace(/^\//, '') // 获取不到全局变量就返回默认值 if (!window.VUE_API_URLS || !window.VUE_VERSION_TYPE) return url // 正则匹配默认值 const defaultRoute = window.VUE_API_URLS['premium'] // 查询当前url的路由 const key = Object.keys(defaultRoute).find((key) => { return newUrl.startsWith(defaultRoute[key]) }) // 需要替换的api路由 const value = window.VUE_API_URLS[window.VUE_VERSION_TYPE][key] // 只替换api的开头 return newUrl.replace(new RegExp(`^${defaultRoute[key]}`), value) } // 创建axios const service = axios.create({ // `withCredentials` 表示跨域请求时是否需要使用凭证 withCredentials: true, // api的 base_url baseURL: window.VUE_APP_SERVERAPI, // 超时时间 timeout: 50000, headers: { 'Access-Control-Allow-Origin': '*', }, }) // ====== Mock 拦截器(先注册,请求阶段后执行,响应阶段先执行) ====== if (isMockEnabled()) { service.interceptors.request.use( (config) => { const url = config.url || '' const method = config.method || 'get' const data = typeof config.data === 'string' ? JSON.parse(config.data) : config.data const mockData = mockRouter(url, method, data) if (mockData !== null) { // 匹配到 mock handler,短路请求 return new Promise((_, reject) => setTimeout( () => reject({ __MOCK__: true, data: mockData, config }), 80 + Math.random() * 120, ), ) } return config }, (error) => Promise.reject(error), ) service.interceptors.response.use( (response) => response, (error) => { if (error?.__MOCK__) { // 将 mock 数据转为正常响应,交给后续拦截器处理 return Promise.resolve({ data: error.data, status: 200, statusText: 'OK', headers: {}, config: error.config, }) } return Promise.reject(error) }, ) } // 请求前拦截 service.interceptors.request.use( (config) => { // 瘦身api路由 const url = replaceApiUrl(config.url) // 合并请求config(使用者传入的级别高) const mergedConfig: any = { ...config, url, headers: { ...defaultHeaders(config), ...config.headers }, } // 把这个类型的接口转成带格式的json 流程用? if (mergedConfig.contentType === 'application/x-www-form-urlencoded;charset=UTF-8') { mergedConfig.data = toFormData(mergedConfig.data) } if ( (url || '').indexOf( `${window.getVersionTypeApiUrl('filecenterUrl')}/iot-base-attachment/single/file-upload`, ) !== -1 ) { mergedConfig.timeout = 1000000 } return mergedConfig }, (error) => { return Promise.reject(error) }, ) // 请求回调拦截 service.interceptors.response.use( async (response) => { await handleResponse(response) // 消息 handleMessage(response) // 请求的是json文件的话,直接返回文件数据 if (response.config.url.includes('.json')) { return Promise.resolve(response.data) } return (response.config as any).importFlag ? Promise.resolve(response) : Promise.resolve(response.data) }, (error) => { handleResponse(error) handleMessage(error) return Promise.reject(error) }, ) export default service