import axios, { AxiosInstance } from 'axios';
import { ElMessage, ElMessageBox } from 'element-plus';
import { MessageType } from 'element-plus/lib/el-message/src/types';
import { Base64 } from 'js-base64';
import { IRequests, ServiceOptions, SvcParams, whiteListUrl } from '../model/requst';
import { RESPONSETYPE } from '../model/requst';
import store from '../store';
import { getTenant, getToken } from './auth';
// 预防 出现option跨域请求
axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';
let invalidationMark = true;
const servicesOptions:ServiceOptions = {
mesRequest: {
timeout: 60000,
baseURL: `${import.meta.env.VITE_APP_BASE_API}`,
// withCredentials: true
}
}
function permissionHandler() {
if (invalidationMark) {
invalidationMark = false;
ElMessageBox.alert(
'你已被登出,可以取消继续留在该页面,或者重新登录',
'确定登出',
{
confirmButtonText: '确定',
callback: () => {
store.dispatch('FedLogOut').then(() =>{
location.reload(); // 莫名其妙代码
});
invalidationMark = true;
}
}
)
}
}
function arrayBufferHandler(responseData: Iterable<number>) {
const enc = new TextDecoder('utf-8');
const errorData = JSON.parse(enc.decode(new Uint8Array(responseData)));
return errorData;
}
function messageHandler(msg: string, type: MessageType) {
ElMessage({
message: msg,
type: type,
duration: 3000
});
}
function decorateService(service: AxiosInstance) {
// 请求拦截
service.interceptors.request.use(
// 请求配置
(config) => {
const clientId = import.meta.env.VITE_APP_CLIENT_ID;
const clientSecret = import.meta.env.VITE_APP_CLIENT_SECRET;
const isToken = config.headers['X-isToken'] === false ? config.headers['X-isToken'] : true;
const isTenant = config.headers['X-isTenant'] === false ? config.headers['X-isTenant'] : true
&& import.meta.env.VITE_APP_IS_MULTI_TENANT_TYPE !== "NONE";
isToken && (config.headers.token = 'Bearer ' + getToken());
isTenant && (config.headers.tenant = getTenant());
config.headers['Authorization'] = `Basic ${Base64.encode(`${clientId}:${clientSecret}`)}`;
return config;
},
(error) => {
Promise.reject(error);
}
);
service.interceptors.response.use(
(response) => {
const responseData = response.data;
const url = response.config.url?.substring(0, response.config.url.lastIndexOf('/'));
const isWhite = url && whiteListUrl.includes(url);
const contentType = response.headers['content-type'];
const isJson = contentType && contentType === 'application/json; charset=UTF-8';
if (responseData.code === 0 || !isJson) {
return Promise.resolve(responseData);
}
!isWhite && messageHandler(responseData.msg, 'error');
return Promise.reject(responseData);
},
(error) => {
const responseType = error.config?.responseType;
const errorData = responseType === RESPONSETYPE.ARRAYBUFFER ? arrayBufferHandler(error.response.data) : error.response?.data;
const status = error.response?.status
switch(status) {
case 500:
case 501:
case 502:
case 503:
messageHandler('服务暂未启动,请稍等一会儿再试~~', 'error');
return Promise.reject(Error('服务暂未启动'));
case 401:
return permissionHandler();
default:
const msg = errorData?.msg || errorData?.errorMsg || '系统内部异常,请联系网站管理员';
messageHandler(msg, 'error');
return Promise.reject(errorData);
}
}
)
}
function getServices(options: ServiceOptions): IRequests {
const requests:IRequests = {};
Object.keys(options).forEach((svcName) => {
requests[svcName] = axios.create(options[svcName as SvcParams]);
decorateService(requests[svcName]);
});
return requests;
}
export default getServices(servicesOptions);
// requst的接口
import type { AxiosInstance, AxiosRequestConfig } from "axios";
export const whiteListUrl = [
'/componentBom/batchImport',
'/componentBom/importBomBasic',
'/componentBom/importMaterial',
'/componentBom/importBomRebar',
'/stackLoadPlan/planImport'
]
export const RESPONSETYPE = {
ARRAYBUFFER: 'arraybuffer',
BLOB: 'blob',
DOCUMENT: 'document',
JSON: 'json',
STREAM: 'stream',
TEXT: 'text',
}
export interface ServiceOptions {
mesRequest: AxiosRequestConfig;
}
export interface IRequests {
[axiosSvcName: string]: AxiosInstance
}
export type SvcParams = 'mesRequest';