跳到主要内容

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>