152 lines
5.0 KiB
JavaScript
152 lines
5.0 KiB
JavaScript
import axios from 'axios';
|
||
import { ElMessage } from 'element-plus';
|
||
import { getBaseUrl } from './url.js';
|
||
|
||
// baseURL 由主进程动态分配端口,通过 getBaseUrl() 运行时获取
|
||
const axiosInstance = axios.create({
|
||
baseURL: getBaseUrl(),
|
||
timeout: 300000,
|
||
headers: {
|
||
'Content-Type': 'application/json;charset=utf-8',
|
||
},
|
||
responseType: 'json',
|
||
});
|
||
|
||
// 每次请求前动态更新 baseURL,确保服务启动后端口变更能被感知
|
||
axiosInstance.interceptors.request.use((config) => {
|
||
config.baseURL = getBaseUrl();
|
||
return config;
|
||
});
|
||
|
||
// 请求拦截
|
||
axiosInstance.interceptors.request.use((config) => {
|
||
config.headers = config.headers || {};
|
||
let Authorization = localStorage.getItem('Authorization');
|
||
// 优先使用本地持久化的 Authorization 头(完整值)
|
||
config.headers.Authorization = Authorization || '';
|
||
|
||
if ('get' === config?.method?.toLowerCase()) {
|
||
if (config.params) {
|
||
config.params.timestamp = new Date().getTime();
|
||
}
|
||
}
|
||
// 移除敏感信息日志
|
||
// console.log(config, 'axios request.use config')
|
||
return config;
|
||
});
|
||
axiosInstance.interceptors.response.use(
|
||
(response) => {
|
||
// 移除敏感信息日志
|
||
// console.log(response, 'response response')
|
||
// 若请求为二进制下载(blob),直接透传响应,交由调用方自行处理
|
||
try {
|
||
const isBlob = response?.config?.responseType === 'blob';
|
||
if (isBlob) {
|
||
// 仍然尝试持久化可能返回的 Authorization
|
||
const respHeaders = response?.headers || {};
|
||
const newAuthorization = respHeaders['authorization'] || respHeaders['Authorization'];
|
||
if (newAuthorization && typeof newAuthorization === 'string') {
|
||
localStorage.setItem('Authorization', newAuthorization);
|
||
}
|
||
return response;
|
||
}
|
||
} catch (e) {
|
||
console.log(e);
|
||
// 忽略检查失败
|
||
}
|
||
// 如果响应头里带有 Authorization,则使用 useStorage 持久化到 localStorage,
|
||
// 以便后续请求自动携带该请求头
|
||
try {
|
||
const respHeaders = response?.headers || {};
|
||
const newAuthorization = respHeaders['authorization'] || respHeaders['Authorization'];
|
||
if (newAuthorization && typeof newAuthorization === 'string') {
|
||
localStorage.setItem('Authorization', newAuthorization);
|
||
}
|
||
} catch (e) {
|
||
// 忽略持久化失败,避免影响主流程
|
||
console.warn('持久化 Authorization 失败:', e);
|
||
}
|
||
// 204 No Content(如 prompt_async)直接视为成功
|
||
if (response.status === 204) {
|
||
return Promise.resolve(null);
|
||
}
|
||
|
||
if (response.status === 200) {
|
||
const res = response.data || {};
|
||
const code = res.code;
|
||
const msg = res.message || res.msg;
|
||
|
||
// 明确的 200 成功,但需要按业务码再判断
|
||
if (code === 0) {
|
||
// 业务成功
|
||
return Promise.resolve(res);
|
||
}
|
||
|
||
// 特殊业务码处理
|
||
if (code === 401) {
|
||
// 清除持久化的 Authorization,避免后续使用失效的头部
|
||
localStorage.removeItem('Authorization');
|
||
sessionStorage.removeItem('Token');
|
||
// 延迟跳转,确保消息显示
|
||
setTimeout(() => {
|
||
window.location.href = '/#/login';
|
||
}, 500);
|
||
return Promise.reject(new Error('认证失败,请重新登录'));
|
||
}
|
||
|
||
// 其余非 0 的业务码统一拦截提示,但不在这里显示 ElMessage
|
||
// 交由业务层使用 await-to-js 处理
|
||
return Promise.reject(new Error(msg || '请求失败'));
|
||
}
|
||
|
||
// 非 2xx 按错误分支处理(通常会进入 error 拦截器)
|
||
return Promise.reject(new Error('请求失败'));
|
||
},
|
||
(error) => {
|
||
console.error('请求错误:', error);
|
||
|
||
if (error.response) {
|
||
// 服务器响应错误
|
||
const status = error.response.status;
|
||
const message = error.response.data?.message || error.response.data?.msg || '请求失败';
|
||
|
||
switch (status) {
|
||
case 400:
|
||
ElMessage.error(`无效的请求参数:${message}`);
|
||
break;
|
||
case 401:
|
||
// 清除持久化的 Authorization,避免后续使用失效的头部
|
||
localStorage.removeItem('Authorization');
|
||
ElMessage.error('未授权访问或登录已过期,请重新登录');
|
||
break;
|
||
case 403:
|
||
ElMessage.error('访问被拒绝');
|
||
break;
|
||
case 404:
|
||
ElMessage.error('资源未找到');
|
||
break;
|
||
case 500:
|
||
ElMessage.error('服务器内部错误');
|
||
break;
|
||
case 502:
|
||
case 503:
|
||
case 504:
|
||
ElMessage.error('服务暂时不可用,请稍后重试');
|
||
break;
|
||
default:
|
||
ElMessage.error(`请求失败: ${message}`);
|
||
}
|
||
} else if (error.request) {
|
||
// 网络错误
|
||
ElMessage.error('网络连接失败,请检查网络连接');
|
||
} else {
|
||
// 其他错误
|
||
ElMessage.error('请求发送失败');
|
||
}
|
||
|
||
return Promise.reject(error);
|
||
}
|
||
);
|
||
|
||
export default axiosInstance;
|