VueAntdAdmin 架构设计方案
前言
封装特色:
-
type.d.ts
类型声明interface ResponseData {
code: number;
msg?: string;
data?: string | number | [];
token?: string | null;
}
interface User {
id: number;
name: string;
avatar: string;
} -
server>request.ts
封装axios
import axios, { AxiosPromise, AxiosRequestConfig, AxiosResponse } from 'axios';
import { notification } from 'ant-design-vue';
import router from '@/router';
const customCodeMessage: { [key: number]: string } = {
10002: '当前用户登入信息已失效,请重新登入再操作', // 未登陆
};
const serverCodeMessage: { [key: number]: string } = {
200: '服务器成功返回请求的数据',
400: 'Bad Request',
401: 'Unauthorized',
403: 'Forbidden',
404: 'Not Found',
500: '服务器发生错误,请检查服务器(Internal Server Error)',
502: '网关错误(Bad Gateway)',
503: '服务不可用,服务器暂时过载或维护(Service Unavailable)',
504: '网关超时(Gateway Timeout)',
};
const ajaxResponseNoVerifyUrl = [
'/user/login', // 用户登录
'/user/info', // 获取用户信息
];
const ajaxHeadersTokenKey = 'x-token';
const getToken = (): Promise<string | null> => {
return new Promise((resolve) => {
resolve('token');
});
};
const setToken = (token: string): Promise<string | null> => {
return new Promise((resolve) => {
resolve(token);
});
};
const errorHandler = (error: any) => {
const { response, message } = error;
if (message === 'CustomError') {
// 自定义错误
const { config, data } = response;
const { url, baseURL } = config;
const { code, msg } = data;
const reqUrl = url.split('?')[0].replace(baseURL, '');
const noVerifyBool = ajaxResponseNoVerifyUrl.includes(reqUrl);
if (!noVerifyBool) {
notification.error({
message: `提示`,
description: customCodeMessage[code] || msg || 'Error',
});
if (code === 10002) {
router.replace('/user/login');
}
}
} else if (message === 'CancelToken') {
// 取消请求 Token
// eslint-disable-next-line no-console
console.log(message);
} else if (response && response.status) {
const errorText = serverCodeMessage[response.status] || response.statusText;
const { status, request } = response;
notification.error({
message: `请求错误 ${status}: ${request.responseURL}`,
description: errorText,
});
} else if (!response) {
notification.error({
description: '您的网络发生异常,无法连接服务器',
message: '网络异常',
});
}
return Promise.reject(error);
};
const request = axios.create({
baseURL: (import.meta.env.VITE_APP_APIHOST || '') as string, // url = api url + request url
withCredentials: true, // 当跨域请求时发送cookie
timeout: 0, // 请求超时时间,5000(单位毫秒) / 0 不做限制
});
request.interceptors.request.use(async (config: AxiosRequestConfig) => {
// 自定义添加token header
const headerToken = await getToken();
if (headerToken) {
config.headers[ajaxHeadersTokenKey] = headerToken;
}
return config;
});
request.interceptors.response.use(async (response: AxiosResponse) => {
const res: ResponseData = response.data;
const { code, token } = res;
// 自定义状态码验证
if (code !== 0) {
return Promise.reject({
response,
message: 'CustomError',
});
}
// 重置刷新token
if (token) {
await setToken(token);
}
return response;
});
export default function Request(config: AxiosRequestConfig): AxiosPromise<any> {
return request(config)
.then((response: AxiosResponse) => response.data)
.catch((error) => errorHandler(error));
} -
server>api.ts
用于管理api
接口import request from '@/server/request';
export async function login(): Promise<any> {
return request({
url: '/user/info',
method: 'get',
});
}
export async function logout(): Promise<any> {
return request({
url: '/user/info',
method: 'get',
});
} -
Home.vue
接口调用<template>
<div>
<h3>首页</h3>
<a-button @click="handleShowMessage">提示</a-button>
</div>
</template>
<script lang="ts">
import { defineComponent } from 'vue';
import { login } from '@/server/api';
export default defineComponent({
name: 'App',
components: {},
setup() {
onBeforeMount(async () => {
await login();
});
},
});
</script>
<style></style>