request.js

import axios from 'axios'
import store from '@/store'
import storage from 'store'
import notification from 'geely-design-vue/es/notification'
import { ACCESS_TOKEN } from '@/store/mutation-types'
import { FORM_URLENCODED } from '@/constData/constants'
import Qs from 'qs'
const contentTypesList = [
  'application/octet-stream',
  'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
]

// 创建 axios 实例
const request = axios.create({
  // API 请求的默认前缀
  baseURL: window.__POWERED_BY_QIANKUN__ ? process.env.VUE_APP_QIANKUN_BASE_API : process.env.VUE_APP_BASE_API,
  timeout: 5000, // 请求超时时间
  headers: {
    'client-code': 'PC',
  },
})

const get = function (url, params = {}, _hideError = false) {
  return request({
    method: 'get',
    url,
    params,
    _hideError,
  })
}

const post = function (url, data = {}, contentType, _hideError = false) {
  const obj = {
    method: 'post',
    url,
    data,
    _hideError,
  }

  // 请求头设置,不设置时,axios默认为application/json
  if (contentType) {
    if (contentType === FORM_URLENCODED) {
      obj.data = Qs.stringify(obj.data)
      obj.headers = {
        'Content-Type': contentType,
      }
    } else {
      obj.headers = {
        'Content-Type': contentType,
      }
    }
  }

  return request(obj)
}

/**
 * request downloadFile
 * @param {String} url
 * @param {Object} data
 * @param {Boolean} [_hideError], 是否隐藏错误信息
 * @returns {AxiosPromise}
 */
const downloadsFile = function (url, data = {}, _hideError = false) {
  return request({
    method: 'post',
    responseType: 'blob',
    url,
    data:
      typeof data === 'object'
        ? Object.assign({ ...data })
        : {
            data,
          },
    _hideError,
  })
}

// 异常拦截处理器
const errorHandler = error => {
  if (error.response) {
    const data = error.response.data
    // 从 localstorage 获取 token
    const token = storage.get(ACCESS_TOKEN)
    if (error.response.status === 403) {
      notification.error({
        message: 'Forbidden',
        description: data.message,
      })
    } else if (error.response.status === 401) {
      notification.error({
        message: 'Unauthorized',
        description: 'Authorization verification failed',
      })
      if (token) {
        store.dispatch('Logout').then(() => {
          setTimeout(() => {
            window.location.reload()
          }, 1000)
        })
      }
    } else if (error.response.status === 500) {
      notification.error({
        message: '系统异常',
        description: data.message,
      })
    } else {
      notification.error({
        message: data.error,
        description: data.message,
      })
    }
  }
  return Promise.reject(error)
}

// request interceptor
request.interceptors.request.use(config => {
  const token = storage.get(ACCESS_TOKEN)
  // 如果 token 存在
  // 让每个请求携带自定义 token 请根据实际情况自行修改
  if (token) {
    config.headers['Access-Token'] = token
  }
  // get参数编码,防止特殊字符入参报错
  let url = config.url
  if (config.method === 'get' && config.params) {
    url += '?'
    const keys = Object.keys(config.params)
    for (const key of keys) {
      if (config.params[key] !== undefined && config.params[key] !== null) {
        let val = config.params[key]
        // 斜杠的特殊处理
        if (typeof val === 'string' && val.indexOf('\\') > -1) {
          val = val.replaceAll('\\', '\\\\')
        }
        // 编码
        val = val ? encodeURIComponent(val) : val
        url += `${key}=${val}&`
      }
    }
    url = url.substring(0, url.length - 1)
    config.params = {}
  }
  config.url = url
  return config
}, errorHandler)

// response interceptor
request.interceptors.response.use(response => {
  const { message, success, code } = response.data
  // wms 返回数据在 result,而 tms 返回的数据在 data 中
  // 故此处对接口数据结构先做兼容处理,后期需跟后端约定
  // 前端业务中只使用 data
  if (response.data.hasOwnProperty('result')) {
    response.data.data = response.data.result
    Reflect.deleteProperty(response.data, 'result')
  }
  // 下载文件的请求头有多种
  const str = response.headers['content-type']
  let headerStr = str
  if (str && str.indexOf(';') > -1) {
    headerStr = str.split(';')[0]
  }
  const booleanVal = contentTypesList.includes(headerStr)
  if (success || booleanVal) {
    return response.data
  }
  // token 失效退出
  if (code === '403403') {
    if (response.config.url.includes('logout')) {
      return
    }
    store.dispatch('Logout').then(() => {
      setTimeout(() => {
        window.location.reload()
      }, 1000)
    })
  }
  // _hideError 为默认显示错误参数
  !response.config._hideError && notification.error({ message })
  const error = new Error(response.data.message || 'Error')
  error.response = response
  return Promise.reject(error)
}, errorHandler)

export default request

export { request as axios, get, post, downloadsFile }
posted @   一个爱好城建的程序猿  阅读(323)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 零经验选手,Compose 一天开发一款小游戏!
· 一起来玩mcp_server_sqlite,让AI帮你做增删改查!!
点击右上角即可分享
微信分享提示