import Vue from 'vue' import axios from 'axios' import { baseURL, contentType, debounce, invalidCode, noPermissionCode, requestTimeout, successCode, recordRoute, loginInterception, } from '@/config' import router from '@/router' import store from '@/store' import qs from 'qs' import { isArray } from '@/utils/validate' let loadingInstance /** * 处理code异常 * @param {*} code * @param {*} msg */ const handleCode = (code, msg) => { switch (code) { case invalidCode: Vue.prototype.$baseMessage(msg || `后端接口${code}异常`, 'error') store.dispatch('user/resetAccessToken') if (loginInterception) { location.reload() } break case noPermissionCode: store.getters['user/accessToken'] && store .dispatch('user/logout') .then(() => { if (recordRoute) { const fullPath = router.currentRoute.fullPath router.push(`/login?redirect=${fullPath}`) } else { router.push('/login') } }) .catch(() => { // logout时可能因为token过期报401错误,此时用href跳转到login页面 window.location.href = '/login' }) break default: Vue.prototype.$baseMessage(msg || `后端接口${code}异常`, 'error') break } } const instance = axios.create({ baseURL, timeout: requestTimeout, headers: { 'Content-Type': contentType, }, }) instance.interceptors.request.use( (config) => { if (config.headers && config.headers.constructor == String) { try { config.headers = JSON.parse(config.headers) } catch (e) { Message.error(`请求头部不是有效的JSON格式:${config.headers}`) throw e } } if (!config.headers || !config.headers.Authorization) { const accessToken = store.getters['user/accessToken'] if (accessToken) { config.headers['Authorization'] = `Bearer ${accessToken}` } } if ( config.data && config.headers['Content-Type'] === 'application/x-www-form-urlencoded;charset=UTF-8' ) config.data = qs.stringify(config.data) config.headers['Accept-Language'] = localStorage.getItem('lang') || 'zh-CN' if (debounce.some((item) => config.url && config.url.includes(item))) loadingInstance = Vue.prototype.$baseLoading() return config }, (error) => { return Promise.reject(error) } ) instance.interceptors.response.use( (response) => { if (loadingInstance) loadingInstance.close() const { data, config, headers } = response const { code, msg, message, state, value } = data if (config) { const { responseType } = config // 请求的返回值类型为arraybuffer时返回headers if (responseType && responseType == 'arraybuffer') { return { data, headers } } } if (headers) { // 附件下载,需要返回 headers const content = headers['content-disposition'] if (content && content.startsWith('attachment;')) { return { data, headers } } } // TODO:暂时允许请求不返回code if (code === undefined) { return data } //如果返回结果不符合EIP后端统一接口格式,直接返回data var isCommonResult = code && state && message if (!isCommonResult) { return data } // 操作正常Code数组 const codeVerificationArray = isArray(successCode) ? [...successCode] : [...[successCode]] // 是否操作正常 if (codeVerificationArray.includes(code)) { return data } else { handleCode(code, message) if (code == '401' && ['4016', '4017'].includes(data.errorCode)) { window.location.href = '/login' } return Promise.reject( '请求异常拦截:' + JSON.stringify({ url: config.url, code, message }) || 'Error' ) } }, (error) => { if (loadingInstance) loadingInstance.close() let { response, message } = error if (error.response && error.response.data) { if ( error.response.status === 500 && error.response.config.url.indexOf( 'dataTemplate/v1/exportByBtnSetting' ) != -1 ) { return Promise.reject(error) } else { const { status, data } = response // 是 arraybuffer 请求 if ( response.request && response.request.responseType === 'arraybuffer' ) { // 格式化返回错误数据,用于提示 try { let enc = new TextDecoder('utf-8') let result = JSON.parse(enc.decode(new Uint8Array(response.data))) if (result) { message = result.msg || result.message return Promise.reject(message) } } catch (error) { console.log(error, 'error') } } //data.msg handleCode(status, data.message || message) return Promise.reject(error) } } else { let { message } = error if (message === 'Network Error') { message = '后端接口连接异常' } if (message.includes('timeout')) { message = '后端接口请求超时' } if (message.includes('Request failed with status code')) { const code = message.substr(message.length - 3) message = '后端接口' + code + '异常' } Vue.prototype.$baseMessage(message || `后端接口未知异常`, 'error') return Promise.reject(error) } } ) export default instance