mirror of
https://github.com/m-xlsea/ruoyi-plus-soybean.git
synced 2025-09-24 07:49:47 +08:00
feat(projects): 1.0 beta
This commit is contained in:
@ -1,27 +0,0 @@
|
||||
import type { AxiosRequestConfig } from 'axios';
|
||||
import { useAuthStore } from '@/store';
|
||||
import { localStg } from '@/utils';
|
||||
import { fetchUpdateToken } from '../api';
|
||||
|
||||
/**
|
||||
* 刷新token
|
||||
* @param axiosConfig - token失效时的请求配置
|
||||
*/
|
||||
export async function handleRefreshToken(axiosConfig: AxiosRequestConfig) {
|
||||
const { resetAuthStore } = useAuthStore();
|
||||
const refreshToken = localStg.get('refreshToken') || '';
|
||||
const { data } = await fetchUpdateToken(refreshToken);
|
||||
if (data) {
|
||||
localStg.set('token', data.token);
|
||||
localStg.set('refreshToken', data.refreshToken);
|
||||
|
||||
const config = { ...axiosConfig };
|
||||
if (config.headers) {
|
||||
config.headers.Authorization = data.token;
|
||||
}
|
||||
return config;
|
||||
}
|
||||
|
||||
resetAuthStore();
|
||||
return null;
|
||||
}
|
@ -1,10 +1,25 @@
|
||||
import { getServiceEnvConfig } from '~/.env-config';
|
||||
import { createRequest } from './request';
|
||||
import { localStg } from '@/utils/storage';
|
||||
import { createOfetch as createRequest } from '@sa/request';
|
||||
import { createServiceConfig, createProxyPattern } from '~/env.config';
|
||||
|
||||
const { url, proxyPattern } = getServiceEnvConfig(import.meta.env);
|
||||
const { baseURL, otherBaseURL } = createServiceConfig(import.meta.env);
|
||||
|
||||
const isHttpProxy = import.meta.env.VITE_HTTP_PROXY === 'Y';
|
||||
|
||||
export const request = createRequest({ baseURL: isHttpProxy ? proxyPattern : url });
|
||||
export const request = createRequest({
|
||||
baseURL: isHttpProxy ? createProxyPattern() : baseURL,
|
||||
headers: {
|
||||
apifoxToken: 'XL299LiMEDZ0H5h3A29PxwQXdMJqWyY2'
|
||||
},
|
||||
onRequest({ options }) {
|
||||
if (options.headers) {
|
||||
const token = localStg.get('token');
|
||||
|
||||
export const mockRequest = createRequest({ baseURL: '/mock' });
|
||||
const Authorization = token ? `Bearer ${token}` : '';
|
||||
|
||||
Object.assign(options.headers, { Authorization });
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
export const demoRequest = createRequest({ baseURL: isHttpProxy ? createProxyPattern('demo') : otherBaseURL.demo });
|
||||
|
@ -1,114 +0,0 @@
|
||||
import axios from 'axios';
|
||||
import type { AxiosResponse, AxiosError, AxiosInstance, AxiosRequestConfig } from 'axios';
|
||||
import { REFRESH_TOKEN_CODE } from '@/config';
|
||||
import {
|
||||
localStg,
|
||||
handleAxiosError,
|
||||
handleBackendError,
|
||||
handleResponseError,
|
||||
handleServiceResult,
|
||||
transformRequestData
|
||||
} from '@/utils';
|
||||
import { handleRefreshToken } from './helpers';
|
||||
|
||||
type RefreshRequestQueue = (config: AxiosRequestConfig) => void;
|
||||
|
||||
/**
|
||||
* 封装axios请求类
|
||||
* @author Soybean<honghuangdc@gmail.com>
|
||||
*/
|
||||
export default class CustomAxiosInstance {
|
||||
instance: AxiosInstance;
|
||||
|
||||
backendConfig: Service.BackendResultConfig;
|
||||
|
||||
isRefreshing: boolean;
|
||||
|
||||
retryQueues: RefreshRequestQueue[];
|
||||
|
||||
/**
|
||||
*
|
||||
* @param axiosConfig - axios配置
|
||||
* @param backendConfig - 后端返回的数据配置
|
||||
*/
|
||||
constructor(
|
||||
axiosConfig: AxiosRequestConfig,
|
||||
backendConfig: Service.BackendResultConfig = {
|
||||
codeKey: 'code',
|
||||
dataKey: 'data',
|
||||
msgKey: 'message',
|
||||
successCode: 200
|
||||
}
|
||||
) {
|
||||
this.backendConfig = backendConfig;
|
||||
this.instance = axios.create(axiosConfig);
|
||||
this.setInterceptor();
|
||||
this.isRefreshing = false;
|
||||
this.retryQueues = [];
|
||||
}
|
||||
|
||||
/** 设置请求拦截器 */
|
||||
setInterceptor() {
|
||||
this.instance.interceptors.request.use(
|
||||
async config => {
|
||||
const handleConfig = { ...config };
|
||||
if (handleConfig.headers) {
|
||||
// 数据转换
|
||||
const contentType = handleConfig.headers['Content-Type'] as UnionKey.ContentType;
|
||||
handleConfig.data = await transformRequestData(handleConfig.data, contentType);
|
||||
// 设置token
|
||||
handleConfig.headers.Authorization = localStg.get('token') || '';
|
||||
}
|
||||
return handleConfig;
|
||||
},
|
||||
(axiosError: AxiosError) => {
|
||||
const error = handleAxiosError(axiosError);
|
||||
return handleServiceResult(error, null);
|
||||
}
|
||||
);
|
||||
this.instance.interceptors.response.use(
|
||||
(async response => {
|
||||
const { status, config } = response;
|
||||
if (status === 200 || status < 300 || status === 304) {
|
||||
const backend = response.data;
|
||||
const { codeKey, dataKey, successCode } = this.backendConfig;
|
||||
// 请求成功
|
||||
if (backend[codeKey] === successCode) {
|
||||
return handleServiceResult(null, backend[dataKey]);
|
||||
}
|
||||
|
||||
// token失效, 刷新token
|
||||
if (REFRESH_TOKEN_CODE.includes(backend[codeKey])) {
|
||||
// 原始请求
|
||||
const originRequest = new Promise(resolve => {
|
||||
this.retryQueues.push((refreshConfig: AxiosRequestConfig) => {
|
||||
config.headers.Authorization = refreshConfig.headers?.Authorization;
|
||||
resolve(this.instance.request(config));
|
||||
});
|
||||
});
|
||||
|
||||
if (!this.isRefreshing) {
|
||||
this.isRefreshing = true;
|
||||
const refreshConfig = await handleRefreshToken(response.config);
|
||||
if (refreshConfig) {
|
||||
this.retryQueues.map(cb => cb(refreshConfig));
|
||||
}
|
||||
this.retryQueues = [];
|
||||
this.isRefreshing = false;
|
||||
}
|
||||
return originRequest;
|
||||
}
|
||||
|
||||
const error = handleBackendError(backend, this.backendConfig);
|
||||
return handleServiceResult(error, null);
|
||||
}
|
||||
const error = handleResponseError(response);
|
||||
return handleServiceResult(error, null);
|
||||
}) as (response: AxiosResponse<any, any>) => Promise<AxiosResponse<any, any>>,
|
||||
(axiosError: AxiosError) => {
|
||||
const error = handleAxiosError(axiosError);
|
||||
return handleServiceResult(error, null);
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
@ -1,208 +0,0 @@
|
||||
import { ref } from 'vue';
|
||||
import type { Ref } from 'vue';
|
||||
import type { AxiosInstance, AxiosRequestConfig } from 'axios';
|
||||
import { useBoolean, useLoading } from '@/hooks';
|
||||
import CustomAxiosInstance from './instance';
|
||||
|
||||
type RequestMethod = 'get' | 'post' | 'put' | 'delete';
|
||||
|
||||
interface RequestParam {
|
||||
url: string;
|
||||
method?: RequestMethod;
|
||||
data?: any;
|
||||
axiosConfig?: AxiosRequestConfig;
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建请求
|
||||
* @param axiosConfig - axios配置
|
||||
* @param backendConfig - 后端接口字段配置
|
||||
*/
|
||||
export function createRequest(axiosConfig: AxiosRequestConfig, backendConfig?: Service.BackendResultConfig) {
|
||||
const customInstance = new CustomAxiosInstance(axiosConfig, backendConfig);
|
||||
|
||||
/**
|
||||
* 异步promise请求
|
||||
* @param param - 请求参数
|
||||
* - url: 请求地址
|
||||
* - method: 请求方法(默认get)
|
||||
* - data: 请求的body的data
|
||||
* - axiosConfig: axios配置
|
||||
*/
|
||||
async function asyncRequest<T>(param: RequestParam): Promise<Service.RequestResult<T>> {
|
||||
const { url } = param;
|
||||
const method = param.method || 'get';
|
||||
const { instance } = customInstance;
|
||||
const res = (await getRequestResponse({
|
||||
instance,
|
||||
method,
|
||||
url,
|
||||
data: param.data,
|
||||
config: param.axiosConfig
|
||||
})) as Service.RequestResult<T>;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* get请求
|
||||
* @param url - 请求地址
|
||||
* @param config - axios配置
|
||||
*/
|
||||
function get<T>(url: string, config?: AxiosRequestConfig) {
|
||||
return asyncRequest<T>({ url, method: 'get', axiosConfig: config });
|
||||
}
|
||||
|
||||
/**
|
||||
* post请求
|
||||
* @param url - 请求地址
|
||||
* @param data - 请求的body的data
|
||||
* @param config - axios配置
|
||||
*/
|
||||
function post<T>(url: string, data?: any, config?: AxiosRequestConfig) {
|
||||
return asyncRequest<T>({ url, method: 'post', data, axiosConfig: config });
|
||||
}
|
||||
/**
|
||||
* put请求
|
||||
* @param url - 请求地址
|
||||
* @param data - 请求的body的data
|
||||
* @param config - axios配置
|
||||
*/
|
||||
function put<T>(url: string, data?: any, config?: AxiosRequestConfig) {
|
||||
return asyncRequest<T>({ url, method: 'put', data, axiosConfig: config });
|
||||
}
|
||||
|
||||
/**
|
||||
* delete请求
|
||||
* @param url - 请求地址
|
||||
* @param config - axios配置
|
||||
*/
|
||||
function handleDelete<T>(url: string, config?: AxiosRequestConfig) {
|
||||
return asyncRequest<T>({ url, method: 'delete', axiosConfig: config });
|
||||
}
|
||||
|
||||
return {
|
||||
get,
|
||||
post,
|
||||
put,
|
||||
delete: handleDelete
|
||||
};
|
||||
}
|
||||
|
||||
interface RequestResultHook<T = any> {
|
||||
data: Ref<T | null>;
|
||||
error: Ref<Service.RequestError | null>;
|
||||
loading: Ref<boolean>;
|
||||
network: Ref<boolean>;
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建hooks请求
|
||||
* @param axiosConfig - axios配置
|
||||
* @param backendConfig - 后端接口字段配置
|
||||
*/
|
||||
export function createHookRequest(axiosConfig: AxiosRequestConfig, backendConfig?: Service.BackendResultConfig) {
|
||||
const customInstance = new CustomAxiosInstance(axiosConfig, backendConfig);
|
||||
|
||||
/**
|
||||
* hooks请求
|
||||
* @param param - 请求参数
|
||||
* - url: 请求地址
|
||||
* - method: 请求方法(默认get)
|
||||
* - data: 请求的body的data
|
||||
* - axiosConfig: axios配置
|
||||
*/
|
||||
function useRequest<T>(param: RequestParam): RequestResultHook<T> {
|
||||
const { loading, startLoading, endLoading } = useLoading();
|
||||
const { bool: network, setBool: setNetwork } = useBoolean(window.navigator.onLine);
|
||||
|
||||
startLoading();
|
||||
const data = ref<T | null>(null) as Ref<T | null>;
|
||||
const error = ref<Service.RequestError | null>(null);
|
||||
|
||||
function handleRequestResult(response: any) {
|
||||
const res = response as Service.RequestResult<T>;
|
||||
data.value = res.data;
|
||||
error.value = res.error;
|
||||
endLoading();
|
||||
setNetwork(window.navigator.onLine);
|
||||
}
|
||||
|
||||
const { url } = param;
|
||||
const method = param.method || 'get';
|
||||
const { instance } = customInstance;
|
||||
|
||||
getRequestResponse({ instance, method, url, data: param.data, config: param.axiosConfig }).then(
|
||||
handleRequestResult
|
||||
);
|
||||
|
||||
return {
|
||||
data,
|
||||
error,
|
||||
loading,
|
||||
network
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* get请求
|
||||
* @param url - 请求地址
|
||||
* @param config - axios配置
|
||||
*/
|
||||
function get<T>(url: string, config?: AxiosRequestConfig) {
|
||||
return useRequest<T>({ url, method: 'get', axiosConfig: config });
|
||||
}
|
||||
|
||||
/**
|
||||
* post请求
|
||||
* @param url - 请求地址
|
||||
* @param data - 请求的body的data
|
||||
* @param config - axios配置
|
||||
*/
|
||||
function post<T>(url: string, data?: any, config?: AxiosRequestConfig) {
|
||||
return useRequest<T>({ url, method: 'post', data, axiosConfig: config });
|
||||
}
|
||||
/**
|
||||
* put请求
|
||||
* @param url - 请求地址
|
||||
* @param data - 请求的body的data
|
||||
* @param config - axios配置
|
||||
*/
|
||||
function put<T>(url: string, data?: any, config?: AxiosRequestConfig) {
|
||||
return useRequest<T>({ url, method: 'put', data, axiosConfig: config });
|
||||
}
|
||||
|
||||
/**
|
||||
* delete请求
|
||||
* @param url - 请求地址
|
||||
* @param config - axios配置
|
||||
*/
|
||||
function handleDelete<T>(url: string, config: AxiosRequestConfig) {
|
||||
return useRequest<T>({ url, method: 'delete', axiosConfig: config });
|
||||
}
|
||||
|
||||
return {
|
||||
get,
|
||||
post,
|
||||
put,
|
||||
delete: handleDelete
|
||||
};
|
||||
}
|
||||
|
||||
async function getRequestResponse(params: {
|
||||
instance: AxiosInstance;
|
||||
method: RequestMethod;
|
||||
url: string;
|
||||
data?: any;
|
||||
config?: AxiosRequestConfig;
|
||||
}) {
|
||||
const { instance, method, url, data, config } = params;
|
||||
|
||||
let res: any;
|
||||
if (method === 'get' || method === 'delete') {
|
||||
res = await instance[method](url, config);
|
||||
} else {
|
||||
res = await instance[method](url, data, config);
|
||||
}
|
||||
return res;
|
||||
}
|
Reference in New Issue
Block a user