更新记录

1.0.0(2025-05-13) 下载此版本

  • 目前已知2个问题
  • 问题1.Android运行时控制台会报警告,但不影响插件使用
    ​warning: There is more than one label with such a name in this scope​
    at service/request.uts:32:5
    warning: There is more than one label with such a name in this scope​
    at service/request.uts:34:4
  • 问题2.Android泛型转换无法移入到onSuccess回调中 只能在外层转换
    //  此句代码无法移入onSuccess中 Android会报错
    JSON.parse<T>(JSON.stringify(v)) as T;
  • 1.0.0初始版本发布。

平台兼容性

Vue2 Vue3
×
App 快应用 微信小程序 支付宝小程序 百度小程序 字节小程序 QQ小程序
HBuilderX 4.64,Android:支持,iOS:支持,HarmonyNext:不确定 × × × × ×
钉钉小程序 快手小程序 飞书小程序 京东小程序 鸿蒙元服务
× × × × ×
H5-Safari Android Browser 微信浏览器(Android) QQ浏览器(Android) Chrome IE Edge Firefox PC-Safari

xsd-request

  • Android/IOS已通过自定义基座测试 HarmonyNext已通过模拟器测试 真机尚不确定 欢迎小伙伴们反馈。
  • 有任何问题可直接邮件至liujiaxin@xinshidaike.com联系我
  • 如果觉得好用,请给我一个五星好评吧~
  • 同时该插件配套的一键生成代码工具正在制作中,后端接口需要符合Swagger 3.0规范(类似Alova的代码生成),敬清期待~

使用示例

import { refreshToken } from './api/api';
import { createXRequest, XBaseRequestOptions, XRequestOptions } from '@/uni_modules/xsd-request';

export type APIResponse = {
    code: string;
    message: string;
    data: any | null;
    i18n?: string;
}

async function _xRequest<T>(instanceConfig: RequestOptions<any>): Promise<T>{
    return createXRequest<APIResponse>(
        {
            baseUrl: 'http://192.168.2.10:6080/x-system-server',
            timeout: 1000,
            header: {
                a: '1'
            }
        } as XBaseRequestOptions
        , {
            onRequest: function(config: RequestOptions<any>) {
                //  演示方便 token存在Storage中  请自行替换为更可靠的存储方式
                config.header?.set('Authorization', `Bearer ${uni.getStorageSync('x-accessToken')}`)
                return config;
            },
            onRequestEnd: async function(response: RequestSuccess<APIResponse>) {
                if(401 == response.statusCode){
                    //  无权限/鉴权无效/鉴权过期  无感刷新Token
                    await refreshToken();
                    console.log('已刷新鉴权!');
                    //  返回null 请求重试
                    return null;
                }
                return 200 == response.statusCode;
            },
            onRequestError: function(error: IUniError, response: RequestSuccess<APIResponse> | null) {
                if(null != response){
                    uni.showToast({
                        title: `请求状态码[${response.statusCode}]`
                    })
                }else{
                    /**
                     * 如果uni.request进入了fail 则response为null
                     * 通常是网络原因 无法请求至指定接口
                     * https://doc.dcloud.net.cn/uni-app-x/api/request.html#requestfail-values
                     */
                    uni.showToast({
                        title: `请求错误码[${error.errCode}]`
                    })
                }
            },
            onRequestMonitor: function(response: APIResponse) {
                return response.code == '0000';
            },
            onRequestMonitorError: function(response: APIResponse) {
                //  请求成功 但业务失败
                uni.showToast({
                    title: `[${response.code}]${response.message}`,
                    // 国际化提示
                    // title: $t({response?.i18n})
                })
            },
            onSuccess: function(response: APIResponse) {
                return response.data as any | undefined;
            }
        } as XRequestOptions<APIResponse>
        , instanceConfig
    ) as Promise<T>
}

export async function xRequest<T>(instanceConfig: RequestOptions<any>): Promise<T>{
    // #ifdef APP-ANDROID
    //  解决Android泛型转换失败问题
    //  如果把此处代码移入onSuccess回调中 Android编译会报错 不太清楚什么问题 等研究明白后更新
    //  这样也可以正常使用
    const v = await _xRequest<T>(instanceConfig) as UTSJSONObject;
    return JSON.parse<T>(JSON.stringify(v)) as T;
    // #endif

    // #ifndef APP-ANDROID
    return _xRequest<T>(instanceConfig);
    // #endif
}
import { xRequest } from "../request";

export type XToken = {
    accessToken : string;
    refreshToken : string;
}

export const storageToken = (accessToken: string, refreshToken: string) => {
    uni.setStorageSync('x-accessToken', accessToken);
    uni.setStorageSync('x-refreshToken', refreshToken);
}

export const doLogin = async () => {
    return xRequest<XToken>({
        url: '/auth-free/accountLogin',
        method: 'POST',
        data: {
            account: 'super-admin',
            password: '123456'
        }
    } as RequestOptions<any>)
}

export const refreshToken = async () => {
    const _refreshToken = uni.getStorageSync('x-refreshToken');
    const data = await xRequest<XToken>({
        url: '/auth-free/refreshToken',
        method: 'POST',
        data: {
            refreshToken: _refreshToken
        }
    } as RequestOptions<any>);
    storageToken(data.accessToken, data.refreshToken);
}

export type Info = {
    id: string;
}

export const authApi = () => {
    return xRequest<Info>({
        url: '/admin/tokenGetInfo',
        method: 'GET'
    } as RequestOptions<any>)
}
<template>
    <view>
        <image class="logo" src="/static/logo.png"></image>
        <button @click="b1">调用登录接口</button>
        <button @click="b2">调用鉴权接口</button>
        <button @click="b3">删除accessToken(模拟未鉴权)</button>
        <button @click="b4">修改assessToken(模拟鉴权过期或无效)</button>
        <button @click="b5">清空全部token</button>
    </view>
</template>

<script lang="uts" setup>
    import { authApi, doLogin, storageToken } from '@/service';

    const b1 = async () => {
        const data = await doLogin();
        //  如果请求失败 代码会被throw error阻断 下方代码不会执行
        console.log('登录接口数据=', data);
        storageToken(data.accessToken, data.refreshToken);
    }

    const b2 = async () => {
        const data = await authApi();
        console.log('鉴权接口数据=', data);
        uni.showToast({
            title: data.id
        })
    }

    const b3 = () => {
        uni.removeStorageSync('x-accessToken');
        uni.showToast({
            title: '已删除'
        })
    }

    const b4 = () => {
        uni.setStorageSync('x-accessToken', '1111');
        uni.showToast({
            title: '已修改'
        })
    }

    const b5 = () => {
        uni.clearStorageSync();
        uni.showToast({
            title: '已清空'
        })
    }
</script>

<style>
    .logo {
        height: 100px;
        width: 100px;
        margin: 100px auto 25px auto;
    }

    .title {
        font-size: 18px;
        color: #8f8f94;
        text-align: center;
    }
</style>

隐私、权限声明

1. 本插件需要申请的系统权限列表:

2. 本插件采集的数据、发送的服务器地址、以及数据用途说明:

插件不采集任何数据

3. 本插件是否包含广告,如包含需详细说明广告表达方式、展示频率:

许可协议

MIT协议

暂无用户评论。

使用中有什么不明白的地方,就向插件作者提问吧~ 我要提问