Skip to content

Commit

Permalink
feat(service): 添加请求数据格式转换
Browse files Browse the repository at this point in the history
  • Loading branch information
chansee97 committed Jan 12, 2023
1 parent b33cb9e commit 014f728
Show file tree
Hide file tree
Showing 6 changed files with 122 additions and 45 deletions.
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand All @@ -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"
Expand Down
6 changes: 6 additions & 0 deletions src/enum/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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',
}
15 changes: 2 additions & 13 deletions src/service/http/handle.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,17 @@
import type { AxiosResponse, AxiosError, AxiosRequestConfig } from 'axios';
import {
ERROR_MSG_DURATION,
DEFAULT_REQUEST_ERROR_CODE,
DEFAULT_REQUEST_ERROR_MSG,
NETWORK_ERROR_CODE,
NETWORK_ERROR_MSG,
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;

Expand Down Expand Up @@ -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 });
}
9 changes: 8 additions & 1 deletion src/service/http/instance.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
handleServiceResult,
handleRefreshToken,
} from './handle';
import { transformRequestData } from './utils';

import { DEFAULT_AXIOS_OPTIONS, DEFAULT_BACKEND_OPTIONS } from '@/config';

Expand All @@ -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() || ''}`);
Expand Down
69 changes: 69 additions & 0 deletions src/service/http/utils.ts
Original file line number Diff line number Diff line change
@@ -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);
}
}
66 changes: 35 additions & 31 deletions src/utils/is.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,96 +2,100 @@
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';

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);
}

1 comment on commit 014f728

@vercel
Copy link

@vercel vercel bot commented on 014f728 Jan 12, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

ench-admin – ./

ench-admin-git-main-whyhenin.vercel.app
ench-admin.vercel.app
ench-admin-whyhenin.vercel.app

Please sign in to comment.