import axios, { AxiosError } from 'axios' import { AxiosInstance, AxiosRequestConfig, AxiosResponse, ExtraConfig } from './request.d' import { ElMessage, ElMessageBox, ElLoading } from 'element-plus' import { ls, debounce } from '@/utils' import router from '@/router' import useStore from '@/store' // ElLoading service 创建的单例 let loading: any = null // 创建axios实例 const axiosInstance: AxiosInstance = axios.create({ baseURL: import.meta.env.VITE_APP_BASE_API, // api 的 base_url timeout: 50000 // 请求超时时间 }) // token 过期 const tokenLoseHandler = debounce( function () { // const { user } = useStore() ls.clear() // 清除浏览器全部缓存 router.push('/login') ElMessageBox.alert('当前页面已失效,请重新登录', '提示', {}) }, 3000, true ) // 判断是否配置加载 页面级别Loading 执行相关操作 const showFullPageLoadingHandler = (config: AxiosRequestConfig, cb: () => any) => { const extraConfig: ExtraConfig = config.extraConfig || {} const bool = extraConfig.showFullscreenLoading || false bool && cb && cb() } // request 拦截器 axiosInstance.interceptors.request.use( (config: AxiosRequestConfig) => { if (!config.headers) { throw new Error(`Expected 'config' and 'config.headers' not to be undefined`) } const token = ls.get('token') // const { token } = useStore().user // 让每个请求携带自定义token 请根据实际情况自行修改 if (!config.headers['accessToken'] && token) { config.headers['accessToken'] = token } showFullPageLoadingHandler(config, () => { // 目前只有两种语言 若有新增 请另外处理 todo... const text = useStore().app.language === 'zh-cn' ? '加载中...' : 'Loading...' loading = ElLoading.service({ // lock: true, text, background: 'rgba(0, 0, 0, 0.3)' }) }) return config }, (error: any) => { return Promise.reject({ from: 'request_error', response: error }) } ) // let testTimeOut = null // response 拦截器 axiosInstance.interceptors.response.use( async (response: AxiosResponse) => { const { extraConfig = {} } = response.config showFullPageLoadingHandler(response.config, () => { loading.close() }) /* eslint-disable */ // @ts-ignore let { code, message, data } = response.data || {} /* eslint-enable */ if (code === 200) { /**配置有 responseAll 将会返回 接口整体数据 默认返回 接口返回 对象.data*/ return extraConfig.responseAll ? response.data : data } else { if (code === 4100) { tokenLoseHandler() } else { ElMessage({ message: message || '系统出错', type: 'error' }) } return Promise.reject({ from: 'response_success:code!=200', response }) } }, (error: AxiosError) => { // eslint-disable-next-line // @ts-ignore const response: AxiosResponse = error.response || {} const { data } = response showFullPageLoadingHandler(error.config || {}, () => { loading.close() }) if (!error.response || !data) { let message = '未知错误,请联系管理员' // 请求超时状态 if (error.message.includes('timeout')) { message = '请求超时,请检查网络是否连接正常' } ElMessage.error(message) return Promise.reject({ from: 'response_error:no_res||no_res.data', response }) } const { code, message } = data // /** 如果是通过 transformResponse 对 data 自定义 */ // if (data.isCustomize === true) { // return Promise.reject(error.response) // } if (code === 4100) { tokenLoseHandler() } else { const _statusText: any = { 4000: '业务相关错误代码', 4100: '授权token已过期,请重新登录', 4101: '谷歌验证失败' } ElMessage({ message: message || _statusText[code] || '系统出错!', type: 'error' }) return Promise.reject({ from: 'response_error:code!=200', response }) } } ) // 导出 axios 实例 export default axiosInstance // 用于 数据 取消上次请求绑定 使用 export const CancelToken = axios.CancelToken // import request from '@/utils/request' // // //列表 // export function getList(params) { // return request({ // url: '/api/getList', // method: 'get', // params: params // }) // }