feat(service): 添加请求数据格式转换

This commit is contained in:
Coffee-crocodile 2023-01-12 18:06:23 +08:00
parent b33cb9e353
commit 014f728faf
6 changed files with 122 additions and 45 deletions

View File

@ -31,6 +31,7 @@
"./src/**/*.{vue,js,jsx,ts,tsx,json}": "eslint --fix"
},
"dependencies": {
"@types/qs": "^6.9.7",
"@vueuse/core": "^9.10.0",
"@wangeditor/editor": "^5.1.23",
"@wangeditor/editor-for-vue": "^5.1.12",
@ -39,6 +40,7 @@
"md-editor-v3": "^2.7.2",
"pinia": "^2.0.28",
"pinia-plugin-persist": "^1.0.0",
"qs": "^6.11.0",
"vue": "^3.2.45",
"vue-qr": "^4.0.9",
"vue-router": "^4.1.6"

View File

@ -9,3 +9,9 @@ export enum EnumStorageKey {
/* 标签栏信息 */
tabsRoutes = '__TABS_ROUTES__',
}
export enum EnumContentType {
json = 'application/json',
formUrlencoded = 'application/x-www-form-urlencoded',
formData = 'multipart/form-data',
}

View File

@ -1,6 +1,5 @@
import type { AxiosResponse, AxiosError, AxiosRequestConfig } from 'axios';
import {
ERROR_MSG_DURATION,
DEFAULT_REQUEST_ERROR_CODE,
DEFAULT_REQUEST_ERROR_MSG,
NETWORK_ERROR_CODE,
@ -8,12 +7,11 @@ import {
REQUEST_TIMEOUT_CODE,
REQUEST_TIMEOUT_MSG,
ERROR_STATUS,
ERROR_NO_TIP_STATUS,
} from '@/config';
import { useAuthStore } from '@/store';
import { getRefreshToken } from '@/utils';
import { fetchUpdateToken } from '@/service';
import { setToken, setRefreshToken } from '@/utils';
import { setToken, setRefreshToken, getRefreshToken } from '@/utils';
import { showError } from './utils';
type ErrorStatus = keyof typeof ERROR_STATUS;
@ -141,12 +139,3 @@ export async function handleRefreshToken(config: AxiosRequestConfig) {
resetAuthStore();
return null;
}
export function showError(error: Service.RequestError) {
// 如果error不需要提示,则跳过
const code = Number(error.code);
if (ERROR_NO_TIP_STATUS.includes(code)) return;
window.console.warn(error.code, error.msg);
window.$message?.error(error.msg, { duration: ERROR_MSG_DURATION });
}

View File

@ -9,6 +9,7 @@ import {
handleServiceResult,
handleRefreshToken,
} from './handle';
import { transformRequestData } from './utils';
import { DEFAULT_AXIOS_OPTIONS, DEFAULT_BACKEND_OPTIONS } from '@/config';
@ -32,9 +33,15 @@ export default class createAxiosInstance {
// 设置类拦截器的函数
setInterceptor() {
this.instance.interceptors.request.use(
(config) => {
async (config) => {
const handleConfig = { ...config };
if (handleConfig.headers) {
// 数据格式转换
// handleConfig.headers.setContentType('application/json');
// const contentType = handleConfig.headers.get('Content-Type');
const contentType = 'application/json';
handleConfig.data = await transformRequestData(handleConfig.data, contentType);
// 设置token
typeof handleConfig.headers.set === 'function' &&
handleConfig.headers.set('Authorization', `Bearer ${getToken() || ''}`);

69
src/service/http/utils.ts Normal file
View File

@ -0,0 +1,69 @@
import { ERROR_MSG_DURATION, ERROR_NO_TIP_STATUS } from '@/config';
import { isArray, isFile } from '@/utils';
import { EnumContentType } from '@/enum';
import qs from 'qs';
export function showError(error: Service.RequestError) {
// 如果error不需要提示,则跳过
const code = Number(error.code);
if (ERROR_NO_TIP_STATUS.includes(code)) return;
window.console.warn(error.code, error.msg);
window.$message?.error(error.msg, { duration: ERROR_MSG_DURATION });
}
/**
*
* @param requestData -
* @param contentType - Content-Type
*/
export async function transformRequestData(requestData: any, contentType?: string) {
// application/json类型不处理
let data = requestData;
// form类型转换
if (contentType === EnumContentType.formUrlencoded) {
data = qs.stringify(requestData);
}
// form-data类型转换
if (contentType === EnumContentType.formData) {
data = await handleFormData(requestData);
}
return data;
}
async function handleFormData(data: Record<string, any>) {
const formData = new FormData();
const entries = Object.entries(data);
entries.forEach(async ([key, value]) => {
const isFileType = isFile(value) || (isArray(value) && value.length && isFile(value[0]));
if (isFileType) {
await transformFile(formData, key, value);
} else {
formData.append(key, value);
}
});
return formData;
}
/**
*
* @param key -
* @param file -
*/
async function transformFile(formData: FormData, key: string, file: File[] | File) {
if (isArray(file)) {
// 多文件
await Promise.all(
(file as File[]).map((item) => {
formData.append(key, item);
return true;
})
);
} else {
// 单文件
formData.append(key, file);
}
}

View File

@ -2,87 +2,91 @@
const toString = Object.prototype.toString;
export function is(val: unknown, type: string) {
return toString.call(val) === `[object ${type}]`;
return toString.call(val) === `[object ${type}]`;
}
export function isDef<T = unknown>(val?: T): val is T {
return typeof val !== 'undefined';
return typeof val !== 'undefined';
}
export function isUnDef<T = unknown>(val?: T): val is T {
return !isDef(val);
return !isDef(val);
}
export function isObject(val: any): val is Record<any, any> {
return val !== null && is(val, 'Object');
return val !== null && is(val, 'Object');
}
export function isEmpty<T = unknown>(val: T): val is T {
if (isArray(val) || isString(val)) {
return val.length === 0;
}
if (isArray(val) || isString(val)) {
return val.length === 0;
}
if (val instanceof Map || val instanceof Set) {
return val.size === 0;
}
if (val instanceof Map || val instanceof Set) {
return val.size === 0;
}
if (isObject(val)) {
return Object.keys(val).length === 0;
}
if (isObject(val)) {
return Object.keys(val).length === 0;
}
return false;
return false;
}
export function isDate(val: unknown): val is Date {
return is(val, 'Date');
return is(val, 'Date');
}
export function isNull(val: unknown): val is null {
return val === null;
return val === null;
}
export function isNullAndUnDef(val: unknown): val is null | undefined {
return isUnDef(val) && isNull(val);
return isUnDef(val) && isNull(val);
}
export function isNullOrUnDef(val: unknown): val is null | undefined {
return isUnDef(val) || isNull(val);
return isUnDef(val) || isNull(val);
}
export function isNumber(val: unknown): val is number {
return is(val, 'Number');
return is(val, 'Number');
}
export function isPromise<T = any>(val: unknown): val is Promise<T> {
return is(val, 'Promise') && isObject(val) && isFunction(val.then) && isFunction(val.catch);
return is(val, 'Promise') && isObject(val) && isFunction(val.then) && isFunction(val.catch);
}
export function isString(val: unknown): val is string {
return is(val, 'String');
return is(val, 'String');
}
export function isFunction(val: unknown): val is Function {
return typeof val === 'function';
return typeof val === 'function';
}
export function isFile<T extends File>(val: T | unknown): val is T {
return is(val, 'File');
}
export function isBoolean(val: unknown): val is boolean {
return is(val, 'Boolean');
return is(val, 'Boolean');
}
export function isRegExp(val: unknown): val is RegExp {
return is(val, 'RegExp');
return is(val, 'RegExp');
}
export function isArray(val: any): val is Array<any> {
return val && Array.isArray(val);
return val && Array.isArray(val);
}
export function isWindow(val: any): val is Window {
return typeof window !== 'undefined' && is(val, 'Window');
return typeof window !== 'undefined' && is(val, 'Window');
}
export function isElement(val: unknown): val is Element {
return isObject(val) && !!val.tagName;
return isObject(val) && !!val.tagName;
}
export const isServer = typeof window === 'undefined';
@ -90,8 +94,8 @@ export const isServer = typeof window === 'undefined';
export const isClient = !isServer;
export function isUrl<T>(path: T): boolean {
const reg =
/(((^https?:(?:\/\/)?)(?:[-;:&=\+\$,\w]+@)?[A-Za-z0-9.-]+(?::\d+)?|(?:www.|[-;:&=\+\$,\w]+@)[A-Za-z0-9.-]+)((?:\/[\+~%\/.\w-_]*)?\??(?:[-\+=&;%@.\w_]*)#?(?:[\w]*))?)$/;
// @ts-expect-error
return reg.test(path);
const reg =
/(((^https?:(?:\/\/)?)(?:[-;:&=\+\$,\w]+@)?[A-Za-z0-9.-]+(?::\d+)?|(?:www.|[-;:&=\+\$,\w]+@)[A-Za-z0-9.-]+)((?:\/[\+~%\/.\w-_]*)?\??(?:[-\+=&;%@.\w_]*)#?(?:[\w]*))?)$/;
// @ts-expect-error
return reg.test(path);
}