Flutter Dio 库的简单封装

Flutter dio 3.2.2 简单封装思路(网络层) dio 库进行封装思路,Flutter 网络层 阅读详情

dio 库Flutter 中是比较流行的网络请求库。

其中在拦截器可以拦截请求,响应以及错误

  • 权限验证:比如接口请求后端返回401未授权时可以跳到登录页,403跳到未授权页面;
  • 异常监控:可以在拦截器处理异常,并且上报到异常监控后台或者发送异常预警消息;
  • 缓存接口:可以对于某些接口将请求缓存在本地,设定一定的缓存有效时限,在时限内重复请求时直接返回本地缓存数据,而无需请求后端接口,降低后端服务器负荷。这块可以参考dio-http-cache。
  • Cookie:App 本身是不会缓存 Cookie 信息的,可以使用拦截器在向后端发起请求时自动携带 Cookie信息,可以参考cookie_manager。
  • 生成接口文档:可以在拦截器将请求参数,返回结果输出为 Postman格式的接口文档,参考postman_dio。
  • 自定义拦截器:可以自定义自己的拦截器类,继承Interceptor类,实现 onRequest,onResponse 和 onError方法即可

简单封装三个文件

第一个HttpRequest

import 'package:awsome_flutter/jiezhi/widget/dio%E5%B0%81%E8%A3%85/http_auth_interceptor.dart';
import 'package:dio/dio.dart';
import 'http_config.dart';

class HTTPRequest {
  static final BaseOptions options = BaseOptions(
      baseUrl: HTTPConfig.baseURL,
      connectTimeout: Duration(milliseconds: HTTPConfig.timeout));
  static Dio dio = Dio(options);

  static Future<T> request<T>(String url,
      {String method = "get", Map<String, dynamic>? params}) async {
    // 1请求的单独配置
    final options = Options(method: method);
    // 2 添加一个拦截器
    Interceptor inter = InterceptorsWrapper(
      onRequest: (options, handler) {
        // 很多页面访问必须要求携带token 那么可以在这里判断是否有token
        // 权限验证:比如接口请求后端返回401未授权时可以跳到登录页,403跳到未授权页面;
        // 异常监控:可以在拦截器处理异常,并且上报到异常监控后台或者发送异常预警消息;
        // 缓存接口:可以对于某些接口将请求缓存在本地,设定一定的缓存有效时限,在时限内重复请求时直接返回本地缓存数据,而无需请求后端接口,降低后端服务器负荷。这块可以参考
        print(options.baseUrl);
        print(options.path);
        print(options.uri);
        print("拦截了请求");
        return handler.next(options);
      },
      onResponse: (e, handler) {
        print(e);
        print("拦截了响应");

        return handler.next(e);
      },
      onError: (e, handler) {
        print(e);
        print("拦截了错误");
        return handler.next(e);
      },
    );

    List<Interceptor> inters = [];
    // 添加自己定义的授权拦截器
    inters.add(AuthInterCeptor());
    // 开启一个log 拦截器
    // 此拦截器将帮助您在发出 HTTP 请求和响应的同时创建所有日志。您将能够看到您请求的所有信息。
    /**
     * uri: https://api.oioweb.cn/api/qq/vip?qq=1023954998
      statusCode: 200
      headers:
      access-control-allow-headers: X-Requested-With
      connection: keep-alive
      access-control-allow-origin: *
      date: Sun, 09 Apr 2023 06:30:44 GMT
      access-control-allow-methods: GET,POST,OPTIONS
      content-encoding: gzip
      content-length: 563
      strict-transport-security: max-age=31536000
      content-type: application/json;charset=utf-8
      server: Tengine
     * 
     * */
    inters.add(LogInterceptor());

    dio.interceptors.addAll(inters);
    // 3 发起网络请求
    try {
      Response response =
          await dio.request<T>(url, queryParameters: params, options: options);
      return response.data;
    } on DioError catch (e) {
      print("戳错了????");
      print(e);
      return Future.error(e);
    }
  }
}

第二个就是Http_config

class HTTPConfig {
  static const baseURL = "https://api.oioweb.cn";
  static const timeout = 5000;
}

第三个 自定义的拦截器

// 自定义一个拦截器
import 'package:dio/dio.dart';

class AuthInterCeptor extends Interceptor {
  AuthInterCeptor();

  // 重写其方法
  @override
  void onRequest(RequestOptions options, RequestInterceptorHandler handler) {
    // TODO: implement onRequest
    // 这里你可以创建一个path 列表,标记处不需要access_token的路径
    final listPath = ["/login", "/resgiter", "/sendMsgCode", "/api/qq/vip"];
    // 进行判断 是否需要追加token
    if (listPath.contains(options.path)) {
      print("/api/qq/vip");
      // 不需要token 直接返回
      return handler.next(options);
    }
    // 这里从本地读取自己的token 拼接上去
    String access_token = "access_token";
    options.headers.addAll({'Authorization': access_token});
    return handler.next(options);
  }

  @override
  void onResponse(Response response, ResponseInterceptorHandler handler) {
    // TODO: implement onResponse
    super.onResponse(response, handler);
  }

  @override
  void onError(DioError err, ErrorInterceptorHandler handler) {
    // TODO: implement onError
    super.onError(err, handler);
  }
}

Flutter Dio二次封装 在这里我和身边一些朋友特意整理了一份快速进阶为Android高级工程师的系统且全面的学习资料。涵盖了Android初级——Android高级架构师进阶必备的一些学习技能。附上:我们之前因为秋招收集的二十套一二线互联网公司Android面试真题(含BAT、小米、华为、美团、滴滴)和我自己整理Android复习笔记(包含Android基础知识点、Android扩展知识点、Android源码解析、设计模式汇总、Gradle知识点、常见算法题汇总。 阅读详情

相关推荐

Flutter网络通信-封装Dio

dio 是一个强大的 Dart HTTP 请求库,支持全局配置、Restful API、FormData、拦截器、 请求取消、Cookie 管理、文件上传/下载、超时以及自定义适配器等。code是请求返回的状态码data是后端返回的数据/// 消息(例如成功消息文字/错误消息文字)/// 自定义code(可根据内部定义方式)final int?code;/// 接口返回的数据/// 需要添加更多});

AiFlutter的博客 2061

Flutter之dio请求封装

大家在使用dio的时候 一般会在取得服务端返回后再用entity对象解析,会显得麻烦一点,我们通过自己定义的Basebean基类,然后在封装http返回数据时统一用基类对象解析。在实际使用时可以简便很多,大大提高开发效率。作者:林晓峰。

DTCloud 2684

Flutter Dio 封装方案,简化 Android 开发

Dio 是一个功能强大的 Flutter HTTP 客户端库,它提供了丰富的功能和灵活的 API,使得网络请求变得更加容易。然而,在实际开发中,我们可能会发现一些常用的网络请求功能需要重复编写,这样就会导致代码冗余。为了简化开发流程,我们可以对 Dio 进行封装,以便复用和简化网络请求的代码。当然,根据实际项目需求,您可以根据这个封装方案进行扩展和定制,以满足特定的业务需求。在该方法中,您可以根据实际需求编写自定义的异常处理逻辑,例如打印日志或进行统一错误处理。在上面的示例中,我们创建了一个。

DevGOOD的博客 491

Flutter网络请求框架Dio源码分析以及封装(一)--请求流程分析

利用flutter开发app也已经有些时间了,这个过程中最多接触到的就是网络请求相关的代码。自己目前项目中使用的是现在市面上最流行的网络请求库-dio,相对于flutter自带的HttpClient来说,dio使用起来更简单,功能更强大,支持全局配置、Restful API、FormData、拦截器、 请求取消、Cookie 管理、文件上传/下载、超时以及自定义适配器等。

Yaoobs的博客 5760

振动分析中相位的确定

更是定位不平衡量角度的关键。是确定振动信号与转子旋转位置之间时间关系的核心步骤,而。以内,以确保校正配重安装角度的有效性。在实际动平衡中,相位角的误差需控制在。在振动分析和动平衡中,

轩辕霸天L 2733

外设高级定时器互补输出带死区控制实验

外设高级定时器互补输出带死区控制实验

ff_juju的博客 1652

Flutter使用第三方Dio库进行简单的网络请求封装;Flutter网络请求使用

Flutter网络请求封装;Flutter原始请求使用;基于dart调用第三方Dio库进行网络请求封装;Flutter学习

weixin_49855711的博客 436

ICG setup timing violation介绍?

门控时钟(clock gating)在RTL级电路设计过程中进行低功耗优化常用方法,能够有效降低动态功耗(翻转功耗)。Clock gating cell 可以由与门,与非门,或门或者或非门构成,但很容易产生Glitch。在实际使用中,一般用ICG(集成门控时钟单元)来完成clock gating。 下图展示了glitch的产生原因 在CTS时钟树综合的时候,ICG不会被看作sink,通常放置在source点附近,因此就会出现如上图这种结果。上图可以看出,在分析DFF到ICG的setup timing

m0_61003348的博客 9803

Flutter Dio http简单封装与使用

Flutter Dio http简单封装与使用dio简单封装配置类接口地址类本地缓存读取工具类简单使用使用相关包 初次封装版本,后续更新完善。不足的地方欢迎提供意见,非常乐意学习请教。 dio简单封装 import 'dart:convert'; import 'dart:io'; import 'package:dio/adapter.dart'; import 'package:dio/dio.dart'; import 'package:yunxiaobao/utils/shared_util.dar

qq_43726671的博客 1360

yolov7模型部署流程

yolov7部署流程

算法的猫 1395

无痛安装及初始配置 PHP 8.0.3 + Apache 2.4 + MySQL 8.0

PHP 8.0.3 + Apache 2.4 + MySQL 8.0MySQL 8.0.23 安装下载安装配置环境变量初始化MySQLPHP8.0.3 安装下载安装配置环境变量Apache 2.4 安装下载安装启动 MySQL 8.0.23 安装 下载 到官方网站下载:https://dev.mysql.com/downloads/mysql/ 目前的最新版本是MySQL 8.0.23 在Windows上有两种安装方式,一个是zip压缩文件解压然后配置,另一个是图像化界面安装。 这里选择第一种方法安装:

Kuang Da's Blog 6208

Flutter网络请求Dio库的使用及封装

主要介绍Flutter网络请求第三方库Dio并实现了对Dio的简单封装及使用。

WEB前端李志杰 8794

基于Simulink的固态变压器(SST)多级协同控制

本文基于Simulink平台,详细介绍了固态变压器(SST)多级协同控制的建模与仿真方法。针对SST三级架构(AC-DC、DC-DC、DC-AC)存在的级间耦合问题,提出了纵向解耦与横向联动的协同控制策略。通过搭建10kV/400V级联型SST系统模型,实现了输入电压波动±20%或负载0-100%跳变时直流母线电压波动小于2%的控制目标。文章详细讲解了Simulink建模步骤、控制算法推导及工程部署建议,包括功率前馈控制、虚拟惯性算法等关键技术。仿真结果表明,该协同控制方案能有效抑制负载突变时的电压波动,为

MHD0815的博客 214

flutter 代码仓库_Flutter学习(四)Http请求库 dio 代码封装

Flutter学习(四)Http请求库 dio 代码封装发布时间:2019-01-15 17:26,浏览次数:359, 标签:FlutterHttpdio<>Flutter学习(四)Http请求库 dio代码封装<>第一步 依赖库* 打开flutter package网站,入口 ,找到dio这个组件,查看最新版本* 打开 项目根目录下 ** pubspec.yaml ** ...

weixin_30986517的博客 313

1、动作捕捉技术:概述与历史

本博文全面介绍了动作捕捉技术的概念、历史演变、类型分类以及完整的工作流程。从早期的连续摄影技术到现代数字动作捕捉系统,文章深入探讨了光学、磁性和机械动作捕捉系统的优缺点及适用场景,并详细解析了动作捕捉数据的生成原理与数学基础。此外,还涵盖了特殊部位如手部、面部和木偶的动作捕捉方法,并讨论了动作捕捉在动画制作、虚拟现实、医疗康复等领域的广泛应用与发展前景。

apple5的专栏 219

泛微OA集成阿里云短信(E9保姆教程)

泛微OA集成阿里云短信(E9保姆教程)

技术分享 515

Flutter开发之网络请求

项目中展示的大部分数据都是来自服务器,我们需要向服务器请求数据,并且对他们进行解析展示。 一. 网络请求的方式 在Flutter中常见的网络请求方式有三种:HttpClient、http库、dio库。 1、HttpClient HttpClient是dart自带的请求类,在io包中,实现了基本的网络请求相关的操作。 网络调用通常遵循如下步骤: 创建 client. 构造 Uri. 发起请求, 等待请求,同时您也可以配置请求headers、 body。 关闭请求, 等待响应. 解码响应的内容. .

iOSbird的博客 1084

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

Flutter 基于Dio封装网络层

实现后的效果 case 5: { try{ var res = await DioManager().friend_getSelectionTopic(params: {}); print('成功msg-----------'+res.msg); print('成功code-----------'+res.code); print('成功code---------

iOSTianNan的博客 707

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain's apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath('DeepLearnToolbox'));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand('state',0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W'); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand('state',0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = 'sigm';%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, 'Too big error');```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand('state',0)sae = saesetup([784 100]);sae.ae{1}.activation_function = 'sigm';sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)')% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = 'sigm';nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, 'Too big error');```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x',28,28,60000))/255;test_x = double(reshape(test_x',28,28,10000))/255;train_y = double(train_y');test_y = double(test_y');%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you'll get around 1.2% errorrand('state',0)cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %sub sampling layer struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, 'Too big error');```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand('state',0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, 'Too big error');%% ex2 neural net with L2 weight decayrand('state',0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex3 neural net with dropoutrand('state',0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex4 neural net with sigmoid activation functionrand('state',0)nn = nnsetup([784 100 10]);nn.activation_function = 'sigm'; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex5 plotting functionalityrand('state',0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = 'softmax'; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand('state',0)nn = nnsetup([784 20 10]); nn.output = 'softmax'; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

Flutter:网络请求 Dio简单封装及请求实例和注意问题

flutter中网络请求一般使用 Dio库,下面我就来基于Dio库做一下简单封装和使用实例以及遇到的问题。 具体请去官网l了解:https://pub.dev/packages/dio 首先在项目的 pubspec.yaml文件中 引入相关库: # 网络请求 dio: ^3.0.10 # cookie 管理 dio_cookie_manager: ^1.0.0 Dio是一个强大的Dart Http请求库,支持Restful API、FormData、拦截器、请求取消、Cook...

zhangyiminsunshine的博客 1590

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

[Flutter3] Json转dart模型举例

3.贴入数据, 这里,我们去掉 最外层的 code/msg /data. 仅对data内的 list数据进行处理即。记录一下 Android studio plugin ->案例 json字符串, 一个 response的data返回数据。Android studio 安装插件即可。处理json转dart 模型。重启后, 右击选择生成数据。

iOSTianNan的博客 801

Flutter 网络请求之Dio库

最近再写Flutter系列文章,在了解过状态管理之后,我们再来学习一下网络请求。

晨曦 1万+

Flutter - dio 简单二次封装

### demo 地址: https://github.com/iotjin/jh_flutter_demo Flutter Dio简单二次封装和自定义Header Flutter Dio二次封装 Flutter Dio封装与使用 Flutter 封装 dio,支持 Restful Api Flutter 网络请求框架封装 结构 apis 文件配置API 地址 dio_utils 文件是对dio的封装 error_handle 文件是异常处理 http_utils 项目接口请求 管理类 .

iotjin的专栏 6369
上一篇: Dart中的异步
下一篇: Flutter渲染原理
Leonardo_Fibonacci
博客等级 码龄10年 110粉丝 247原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值