import axios from 'axios' import errorCode from './errorCode' import { Notification, MessageBox, Message } from 'element-ui' import loadingManager from './loadingManager'; // 创建axios实例 const service = axios.create({ // axios中请求配置有baseURL选项,表示请求URL公共部分 baseURL: process.env.VUE_APP_BASE_API, // 超时 timeout: 10000, }) // 网络错误相关配置 const NETWORK_ERROR_THROTTLE_TIME = 5000; // 错误提示节流时间 const RETRY_DELAY = 2000; // 重试间隔时间 const MAX_RETRY_TIMES = 3; // 最大重试次数 const RETRY_WINDOW = 60000; // 60秒重试窗口 let lastNetworkErrorTime = 0; // 上次网络错误提示时间 let pendingRequests = new Map(); // 网络状态监听器 window.addEventListener('online', () => { // 网络恢复时,重试所有待处理的请求 const now = Date.now(); const pendingPromises = []; pendingRequests.forEach(async (request, key) => { if (now - request.timestamp <= RETRY_WINDOW) { try { // 获取新的响应数据 const response = await service(request.config); pendingPromises.push(response); // 执行请求特定的回调 if (request.callback && typeof request.callback === 'function') { request.callback(response); } // 处理特定类型的请求 if (window.vm) { // 处理图表数据请求 if (request.config.url.includes('getPoolPower') && response && response.data) { // 触发图表更新事件 window.dispatchEvent(new CustomEvent('chart-data-updated', { detail: { type: 'poolPower', data: response.data } })); } else if (request.config.url.includes('getNetPower') && response && response.data) { window.dispatchEvent(new CustomEvent('chart-data-updated', { detail: { type: 'netPower', data: response.data } })); } else if (request.config.url.includes('getBlockInfo') && response && response.rows) { window.dispatchEvent(new CustomEvent('chart-data-updated', { detail: { type: 'blockInfo', data: response.rows } })); } } pendingRequests.delete(key); } catch (error) { console.error('重试请求失败:', error); pendingRequests.delete(key); } } else { pendingRequests.delete(key); } }); // 等待所有请求完成 Promise.allSettled(pendingPromises).then(() => { // 重置所有 loading 状态 loadingManager.resetAllLoadingStates(); // 触发网络重试完成事件 window.dispatchEvent(new CustomEvent('network-retry-complete')); }); // 显示网络恢复提示 if (window.vm && window.vm.$message) { window.vm.$message({ message: window.vm.$i18n.t('home.networkReconnected') || '网络已重新连接,正在恢复数据...', type: 'success', duration: 3000 }); } }); window.addEventListener('offline', () => { if (window.vm && window.vm.$message) { window.vm.$message({ message: window.vm.$i18n.t('home.networkOffline') || '网络连接已断开,系统将在恢复连接后自动重试', type: 'warning', duration: 3000 }); } }); service.defaults.retry = 2;// 重试次数 service.defaults.retryDelay = 2000; service.defaults.shouldRetry = (error) => true localStorage.setItem('superReportError', "") let superReportError = localStorage.getItem('superReportError') window.addEventListener("setItem", () => { superReportError = localStorage.getItem('superReportError') }); // request拦截器 service.interceptors.request.use(config => { superReportError = "" // retryCount =0 localStorage.setItem('superReportError', "") // 是否需要设置 token let token try { token = JSON.parse(localStorage.getItem('token')) } catch (e) { console.log(e); } if (token) { config.headers['Authorization'] = token } if (config.method == 'get' && config.data) { config.params = config.data } // get请求映射params参数 if (config.method === 'get' && config.params) { let url = config.url + '?'; for (const propName of Object.keys(config.params)) { const value = config.params[propName]; var part = encodeURIComponent(propName) + "="; if (value !== null && typeof (value) !== "undefined") { if (typeof value === 'object') { for (const key of Object.keys(value)) { if (value[key] !== null && typeof (value[key]) !== 'undefined') { let params = propName + '[' + key + ']'; let subPart = encodeURIComponent(params) + '='; url += subPart + encodeURIComponent(value[key]) + '&'; } } } else { url += part + encodeURIComponent(value) + "&"; } } } url = url.slice(0, -1); config.params = {}; config.url = url; } return config }, error => { Promise.reject(error) }) // 响应拦截器 service.interceptors.response.use(res => { // 未设置状态码则默认成功状态 const code = res.data.code || 200; // 获取错误信息 const msg = errorCode[code] || res.data.msg || errorCode['default'] if (code === 421) { localStorage.removeItem('token') // 系统状态已过期,请重新点击SUPPORT按钮进入 superReportError = localStorage.getItem('superReportError') if (!superReportError) { superReportError = 421 localStorage.setItem('superReportError', superReportError) MessageBox.confirm(window.vm.$i18n.t(`user.loginExpired`), window.vm.$i18n.t(`user.overduePrompt`), { distinguishCancelAndClose: true, confirmButtonText: window.vm.$i18n.t(`user.login`), cancelButtonText: window.vm.$i18n.t(`user.Home`), // showCancelButton: false, // 隐藏取消按钮 closeOnClickModal: false, // 点击空白处不关闭对话框 showClose: false, // 隐藏关闭按钮 type: 'warning' } ).then(() => { window.vm.$router.push("/login") localStorage.removeItem('token') }).catch(() => { window.vm.$router.push("/") localStorage.removeItem('token') }); } return Promise.reject('登录状态已过期') } else if (code >= 500 && !superReportError) { superReportError = 500 localStorage.setItem('superReportError', superReportError) Message({ dangerouslyUseHTMLString: true, message: msg, type: 'error', showClose: true }) // throw msg; // 抛出错误,中断请求链并触发后续的错误处理逻辑 // return Promise.reject(new Error(msg)) } else if (code !== 200) { Notification.error({ title: msg }) return Promise.reject('error') } else { return res.data } }, error => { let { message } = error; if (message == "Network Error" || message.includes("timeout")) { if (!navigator.onLine) { // 断网状态,添加到重试队列 const requestKey = JSON.stringify({ url: error.config.url, method: error.config.method, params: error.config.params, data: error.config.data }); // 根据URL确定请求类型并记录回调 let callback = null; if (error.config.url.includes('getPoolPower')) { callback = (data) => { if (window.vm) { // 清除loading状态 window.vm.minerChartLoading = false; } }; } else if (error.config.url.includes('getBlockInfo')) { callback = (data) => { if (window.vm) { window.vm.reportBlockLoading = false; } }; } if (!pendingRequests.has(requestKey)) { pendingRequests.set(requestKey, { config: error.config, timestamp: Date.now(), retryCount: 0, callback: callback }); console.log('请求已加入断网重连队列:', error.config.url); } } else if ((error.config.retry > 0 && error.config)) { // 保留现有的重试逻辑 error.config.retry--; return new Promise(resolve => { setTimeout(() => { resolve(service(error.config)); }, 2000); }); } } if (!superReportError) { superReportError = "error" localStorage.setItem('superReportError', superReportError) let { message } = error; if (message == "Network Error") { // message = "后端接口网络连接异常,请刷新重试"; const now = Date.now(); if (now - lastNetworkErrorTime > NETWORK_ERROR_THROTTLE_TIME) { lastNetworkErrorTime = now; // 更新最后提示时间 Message({ message: window.vm.$i18n.t(`home.NetworkError`), type: 'error', duration: 4 * 1000, showClose: true }); } } else if (message.includes("timeout")) { // message = "系统接口请求超时,请刷新重试"; Message({ message: window.vm.$i18n.t(`home.requestTimeout`), type: 'error', duration: 5 * 1000, showClose: true }) } else if (message.includes("Request failed with status code")) { // message = "系统接口" + message.substr(message.length - 3) + "异常"; Message({ message: "系统接口" + message.substr(message.length - 3) + "异常", type: 'error', duration: 5 * 1000, showClose: true }) } else { Message({ message: message, type: 'error', duration: 5 * 1000, showClose: true }) } } return Promise.reject(error) } ) export default service