import axios from 'axios' import axiosRetry from 'axios-retry' import contentDisposition from 'content-disposition' import { Message } from 'element-ui' import { getToken } from '@/utils/auth' // get token from cookie import { saveBlob } from '@/utils/index' import bridge, { isInApp } from '@/utils/bridge' import store from '@/store' axiosRetry(axios, { retries: 3, retryDelay: (retryCount) => 500 * retryCount, retryCondition: (error) => error.message === 'Network Error' || error.code === 'ECONNABORTED' || false }) const ajax = function(options) { const NODE_ENV = process.env.NODE_ENV const BASE_API = process.env.VUE_APP_BASE_API const token = getToken() const defaults = { responseType: 'json', method: 'post', baseURL: BASE_API, url: '', data: {}, timeout: 30000, withCredentials: true, hideToast: false, headers: { 'X-Requested-With': 'XMLHttpRequest', 'Content-Type': 'application/json;charset=utf-8', 'Authorization': `bearer ${token}` }, transformResponse: [ function(data) { try { return JSON.parse(data) } catch (error) { return data } } ] } if (!token) { delete defaults.headers.Authorization } const clone = (target) => { if (Object.prototype.toString.call(target) === '[object Object]' || Object.prototype.toString.call(target) === '[object Array]') { const result = Array.isArray(target) ? [] : {} for (const key in target) { result[key] = clone(target[key]) } return result // 过滤入参前后空格 } else if (typeof target === 'string') { return target.replace(/(^\s*)|(\s*$)/g, '') } else { return target } } options = { ...defaults, ...options } options.data = options.data ? clone(options.data) : {} if (NODE_ENV !== 'production') { console.log(JSON.stringify(options.data)) const url = options.url.indexOf('http') === 0 ? options.url : `${BASE_API}${options.url}` console.log(`%c ${url}`, 'color: #207928') } return new Promise((resole, reject) => { let data = {} let code = 0 let message = '' axios(options) .then((response) => { const json = response.data || {} data = json.data || {} code = json.code message = json.msg || '接口异常,请稍后再试.' // 文件下载 if (options.responseType === 'blob') { const disposition = response.headers['content-disposition'] let fileName = 'default' let cdResult = null try { cdResult = contentDisposition.parse(disposition) } catch (e) { console.log(e) } if (cdResult && cdResult.parameters && cdResult.parameters.filename) { fileName = decodeURI(cdResult.parameters.filename) } const fileType = response.headers['content-type'] const fileData = new Blob([json], { type: fileType }) // 如果在app中,调用bridge下载 if (isInApp) { const fileReader = new FileReader() fileReader.onload = (e) => { const base64 = e.target.result bridge.saveFileByBase64(base64.slice(base64.indexOf(';base64,') + 8), fileName) } // readAsDataURL fileReader.readAsDataURL(fileData) fileReader.onerror = () => { reject(new Error('blobToBase64 error')) } } else { saveBlob(fileData, fileName) } resole(json) return false } if (NODE_ENV === 'development' || NODE_ENV === 'debug') { console.log(json) } else if (NODE_ENV !== 'production') { console.log(JSON.stringify(json, null, 2)) } if (json.success) { resole(data) } else if (code === 1101 || code === 1102 || code === 1103 || code === 1104) { // 1101 token无效或已过期 // 1102 已在其他终端登录 强制下线 // 1103 用户冻结 强制下线 // 1104 权限变更等原因 强制下线 store.dispatch('user/resetToken').then(() => { window.location.href = `${process.env.VUE_APP_ROUTER}login?redirect=${encodeURIComponent(window.location.href)}` }) } else { reject({ code, message }) // hideToast=true或用户信息失效不展示报错信息 if (options.hideToast || options.url.indexOf('user/eiam/user/getCurrUserInfo') >= 0) { return } Message({ message, type: 'error', duration: 3 * 1000 }) } }) .catch((error) => { if (NODE_ENV !== 'production') { console.log(error.message) } if (error.response) { code = error.response.status message = error.response.statusText || error.response.data && error.response.data.msg } else if (error.request && error.message === 'Network Error') { // 网络异常 message = '连接似乎有问题,请检查网络.' } else if (error.request && error.code === 'ECONNABORTED') { // 请求超时 message = '接口异常,请稍后再试.' } else if (error.__CANCEL__) { // 取消请求 message = 'cancel request' code = '_CANCEL_REQUEST_' } else { message = 'params setting error' } reject({ code, message }) if (options.hideToast) { return } Message({ message, type: 'error', duration: 3 * 1000 }) }) }) } export default ajax