/** * axios 实例 */ import axios from 'axios'; import router from '@/router'; import store from '@/store'; import { MessageBox, Message } from 'element-ui'; import { API_BASE_URL, TOKEN_HEADER_NAME, LAYOUT_PATH, TENANT_HEADER_NAME } from '@/config/setting'; import { getToken, setToken } from './token-util'; import { getTenantId } from './tenant-util'; import { logout } from './page-tab-util'; import JSONBIG from 'json-bigint'; const service = axios.create({ baseURL: API_BASE_URL, transformResponse: [ function (data) { if (data instanceof Blob) { return data; } const json = JSONBIG({ storeAsString: true }); const res = json.parse(data); return res; } ] }); /** * 是否为签发登录凭证的入口(对应后端 TenantIsolationAspect 的 LOGIN_URIS)。 * @param {string} url 请求地址 * @returns {boolean} 是登录入口返回 true */ function isLoginEntry(url) { return typeof url === 'string' && /(^|\/)user\/login(\?|$)/.test(url); } /** * 添加请求拦截器 */ service.interceptors.request.use( (config) => { // 添加 token 到 header // 登录入口必须以匿名身份发出:残留的旧凭证在服务端优先级高于请求头 // (token 的租户声明才是权威),它既会顶掉本次选择的租户,又会让 X-Tenant-ID // 被当成外部伪造而忽略 —— 表现为"选了租户却登进平台库"。 const token = isLoginEntry(config.url) ? '' : getToken(); if (token && config.headers) { config.headers.common[TOKEN_HEADER_NAME] = token; } // 多租户:未登录的请求(登录接口、登录页品牌标识等匿名入口)租户只能靠 // 请求头传递 —— 服务端必须在认证之前就知道连哪个租户库。 // 已登录时租户已写入 token 声明、服务端以声明为准,这里不重复携带, // 避免为"多余且会被忽略"的头部逐个打告警日志。 if (!token && config.headers) { const tenantId = getTenantId(); if (tenantId) { config.headers.common[TENANT_HEADER_NAME] = tenantId; } } return config; }, (error) => { return Promise.reject(error); } ); /** * 添加响应拦截器 */ service.interceptors.response.use( (res) => { // token 自动续期 if (res.data.code == '-1' && res.config?.showErrorToast !== false) { Message.error(res.data.message); } const token = res.headers[TOKEN_HEADER_NAME.toLowerCase()]; if (token) { setToken(token); } return res; }, (error) => { // 登录过期处理 if (error?.response?.status === 401) { const currentPath = router.currentRoute.path; // if (currentPath === LAYOUT_PATH) { // logout(true); // } else { MessageBox.alert('登录状态已过期, 请退出重新登录!', '系统提示', { confirmButtonText: '重新登录', callback: (action) => { if (action === 'confirm') { logout(false, currentPath); } }, beforeClose: () => { MessageBox.close(); } }); // } return Promise.reject(new Error(error.response.data?.message)); }else if(!error?.response?.status){ Message.error('服务调用失败,请联系管理员!'); } return Promise.reject(error); } ); export default service;