【Vue+DRF生鲜电商】26.订单接口功能,Vue和订单接口联调

专题:Vue+Django REST framework前后端分离生鲜电商

Vue+Django REST framework 打造前后端分离的生鲜电商项目(慕课网视频)。
Github地址:https://github.com/xyliurui/DjangoOnlineFreshSupermarket
Django版本:2.2、djangorestframework:3.9.2。

更多内容请点击 我的博客 查看,欢迎来访。

订单管理接口功能

先看下之前的模型

class OrderInfo(models.Model):
    """
    订单
    """
    ORDER_STATUS = (
        ('success', '成功'),
        ('cancel', '取消'),
        ('topaid', '待支付')
    )
    user = models.ForeignKey(User, verbose_name='用户', help_text='用户', on_delete=models.CASCADE, related_name='order_infos')
    order_sn = models.CharField(max_length=30, unique=True, verbose_name='订单号', help_text='订单号')
    trade_no = models.CharField(max_length=100, unique=True, null=True, blank=True, verbose_name='支付')
    pay_status = models.CharField(choices=ORDER_STATUS, max_length=20, verbose_name='订单状态', help_text='订单状态')
    post_script = models.CharField(max_length=50, blank=True, null=True, verbose_name='订单留言', help_text='订单留言')
    order_amount = models.FloatField(default=0.0, verbose_name='订单金额', help_text='订单金额')
    pay_time = models.DateTimeField(null=True, blank=True, verbose_name='支付时间', help_text='支付时间')
    # 用户信息
    address = models.CharField(max_length=200, default='', verbose_name='收货地址', help_text='收货地址')
    signer_name = models.CharField(max_length=20, default='', verbose_name='签收人', help_text='签收人')
    signer_mobile = models.CharField(max_length=11, verbose_name='联系电话', help_text='联系电话')

    add_time = models.DateTimeField(auto_now_add=True, verbose_name='添加时间')

    class Meta:
        verbose_name_plural = verbose_name = '订单'

    def __str__(self):
        return "{}".format(self.order_sn)

分析,order_sn字段不能为空,这是不行的,订单号需要由后台生成。但用户点击去结算时,后台需要生成一个订单号,但是如果我们用到CreateModelMixin,这个会对该字段进行验证,在用户界面是不可能post一个订单号到后台,从而导致验证失败,所以该字段增加设置blank=True, null=True

pay_status可以设置一个默认值,为待支付状态default='topaid',提交订单时,用户也不用指定该字段了。

address不直接使用外键的原因是:用户如果修改了个人中心的收货地址,订单中地址就会跟着变化,显然是不对的,所以订单中的地址就保存一个当时下单的地址组合的字符串。

修改后

# apps/trade/models.py

class OrderInfo(models.Model):
    """
    订单
    """
    ORDER_STATUS = (
        ('success', '成功'),
        ('cancel', '取消'),
        ('topaid', '待支付')
    )
    user = models.ForeignKey(User, verbose_name='用户', help_text='用户', on_delete=models.CASCADE, related_name='order_infos')
    order_sn = models.CharField(max_length=30, unique=True, blank=True, null=True, verbose_name='订单号', help_text='订单号')
    trade_no = models.CharField(max_length=100, unique=True, null=True, blank=True, verbose_name='支付交易号', help_text='支付交易号')
    pay_status = models.CharField(choices=ORDER_STATUS, default='topaid', max_length=20, verbose_name='订单状态', help_text='订单状态')
    post_script = models.CharField(max_length=50, blank=True, null=True, verbose_name='订单留言', help_text='订单留言')
    order_amount = models.FloatField(default=0.0, verbose_name='订单金额', help_text='订单金额')
    pay_time = models.DateTimeField(null=True, blank=True, verbose_name='支付时间', help_text='支付时间')
    # 用户信息
    address = models.CharField(max_length=200, default='', verbose_name='收货地址', help_text='收货地址')
    signer_name = models.CharField(max_length=20, default='', verbose_name='签收人', help_text='签收人')
    signer_mobile = models.CharField(max_length=11, verbose_name='联系电话', help_text='联系电话')

    add_time = models.DateTimeField(auto_now_add=True, verbose_name='添加时间')

    class Meta:
        verbose_name_plural = verbose_name = '订单'

    def __str__(self):
        return "{}".format(self.order_sn)

对于一个订单,有多个商品,所以需要设置另外一个model,用外键关联。

OrderInfoSerializer创建订单序列化

序列化中用户也是需要不可见的

# apps/trade/serializers.py

from trade.models import ShoppingCart, OrderInfo

class OrderInfoSerializer(serializers.ModelSerializer):
    user = serializers.HiddenField(
        default=serializers.CurrentUserDefault()  # 表示user为隐藏字段,默认为获取当前登录用户
    )

    class Meta:
        model = OrderInfo
        fields = "__all__"

OrderInfoViewSet订单管理视图

不使用viewsets.ModelViewSet原因是,订单一般不允许修改的,所有要自定义继承

# apps/trade/views.py

from .serializers import ShoppingCartSerializer, ShoppingCartListSerializer, OrderInfoSerializer
from .models import ShoppingCart, OrderInfo


class OrderInfoViewSet(mixins.ListModelMixin, mixins.CreateModelMixin, mixins.RetrieveModelMixin,mixins.DestroyModelMixin, viewsets.GenericViewSet):
    """
    订单管理
    list:
        获取个人订单
    create:
        新建订单
    delete:
        删除订单
    detail:
        订单详情
    """
    permission_classes = (IsAuthenticated, IsOwnerOrReadOnly)  # 用户必须登录才能访问
    authentication_classes = (JWTAuthentication, SessionAuthentication)  # 配置登录认证:支持JWT认证和DRF基本认证
    queryset = OrderInfo.objects.all()
    serializer_class = OrderInfoSerializer  # 添加序列化

    def get_queryset(self):
        return self.queryset.filter(user=self.request.user)

配置订单管理的URL

# DjangoOnlineFreshSupermarket/urls.py

from trade.views import ShoppingCartViewSet, OrderInfoViewSet

router.register(r'orderinfo', OrderInfoViewSet, base_name='orderinfo')  # 订单管理

现在访问 http://127.0.0.1:8000/orderinfo/ 可以看到DRF生成的页面

BLOG_20190722_210550_48

对于订单提交,会告诉后台创建一个订单,在这提交订单是一个比较简单的逻辑,即将购物车ShoppingCart中的该用户对应的单品和数量,添加到订单商品OrderGoods中,然后清空该用户的购物车。

OrderInfoViewSet添加购物车的商品到订单

可以在OrderInfoViewSet中重载perform_create(self, serializer)方法(这个在mixins.CreateModelMixin类中)

    def perform_create(self, serializer):
        serializer.save()

.save()之前,需要生成一个订单号,所以修改序列化类,在数据验证通过后生成一个订单号,修改OrderInfoSerializer,重载validate(self, attrs)方法

# apps/trade/serializers.py

class OrderInfoSerializer(serializers.ModelSerializer):
    user = serializers.HiddenField(
        default=serializers.CurrentUserDefault()  # 表示user为隐藏字段,默认为获取当前登录用户
    )

    def generate_order_sn(self):
        # 当前时间+userid+随机数
        import time
        from random import randint
        order_sn = '{time_str}{user_id}{random_str}'.format(time_str=time.strftime('%Y%m%d%H%M%S'), user_id=self.context['request'].user.id, random_str=randint(10, 99))
        return order_sn

    def validate(self, attrs):
        # 数据验证成功后,生成一个订单号
        attrs['order_id'] = self.generate_order_sn()
        return attrs

    class Meta:
        model = OrderInfo
        fields = "__all__"

之后修改OrderInfoViewSet,重载perform_create(self, serializer)方法

class OrderInfoViewSet(mixins.ListModelMixin, mixins.CreateModelMixin, mixins.RetrieveModelMixin, mixins.DestroyModelMixin, viewsets.GenericViewSet):
    """
    订单管理
    list:
        获取个人订单
    create:
        新建订单
    delete:
        删除订单
    detail:
        订单详情
    """
    permission_classes = (IsAuthenticated, IsOwnerOrReadOnly)  # 用户必须登录才能访问
    authentication_classes = (JWTAuthentication, SessionAuthentication)  # 配置登录认证:支持JWT认证和DRF基本认证
    queryset = OrderInfo.objects.all()
    serializer_class = OrderInfoSerializer  # 添加序列化

    def get_queryset(self):
        return self.queryset.filter(user=self.request.user)

    def perform_create(self, serializer):
        # 完成创建后保存到数据库,可以拿到保存的OrderInfo对象
        order = serializer.save()
        shopping_carts = ShoppingCart.objects.filter(user=self.request.user)
        # 将该用户购物车所有商品都取出来放在订单商品中
        for shopping_cart in shopping_carts:
            OrderGoods.objects.create(
                order=order,
                goods=shopping_cart.goods,
                goods_nums=shopping_cart.nums
            )
        # 然后清空该用户购物车
        shopping_carts.delete()

OrderInfoSerializer隐藏不能显示的字段

在上面的图中,订单号、支付交易号、订单状态、支付日期(需要支付后才有时间)信息是不能显示给用户的,只能后台去修改

# apps/trade/serializers.py

class OrderInfoSerializer(serializers.ModelSerializer):
    user = serializers.HiddenField(
        default=serializers.CurrentUserDefault()  # 表示user为隐藏字段,默认为获取当前登录用户
    )
    order_sn = serializers.CharField(read_only=True)  # 只能读,不能显示给用户修改,只能后台去修改
    trade_no = serializers.CharField(read_only=True)  # 只读
    pay_status = serializers.CharField(read_only=True)  # 只读
    pay_time = serializers.DateTimeField(read_only=True)  # 只读

    def generate_order_sn(self):
        # 当前时间+userid+随机数
        import time
        from random import randint
        order_sn = '{time_str}{user_id}{random_str}'.format(time_str=time.strftime('%Y%m%d%H%M%S'), user_id=self.context['request'].user.id, random_str=randint(10, 99))
        return order_sn

    def validate(self, attrs):
        # 数据验证成功后,生成一个订单号
        attrs['order_sn'] = self.generate_order_sn()
        return attrs

    class Meta:
        model = OrderInfo
        fields = "__all__"

BLOG_20190722_210534_86

return attrs打上断点调试,在DRF中 http://127.0.0.1:8000/orderinfo/ 填入一些信息后POST,可以在后端看到attrs的内容

BLOG_20190722_210527_85

然后进入OrderInfoViewSet完成创建perform_create处理,将购物车的商品添加到订单商品中,并删除购物车商品

BLOG_20190722_210522_17

访问 http://127.0.0.1:8000/orderinfo/1/ 可以看到有订单删除

BLOG_20190722_210516_45

该功能可以将订单关联的商品一起删除。

Vue中订单接口联调

访问 http://127.0.0.1:8080/#/app/home/member/order 可以查看我的订单

BLOG_20190722_210510_51

由于刚才订单删除了,所以为空。在Vue中,添加商品到购物车,然后选择配送地址,点击去结算

BLOG_20190722_210501_44

BLOG_20190722_210455_85

订单创建功能分析

当用户准备创建订单时,会点击去结算

<!-- src/views/cart/cart.vue -->

<p class="sumup"><a class="btn" @click="balanceCount">去结算</a></p>

点击之后进入

// src/views/cart/cart.vue

balanceCount() { // 结算
    if (this.addrInfo.length == 0) {
        alert("请选择收货地址")
    } else {
        createOrder(
            {
                post_script: this.post_script,
                address: this.address,
                signer_name: this.signer_name,
                signer_mobile: this.signer_mobile,
                order_amount: this.totalPrice
            }
        ).then((response) => {
            alert('订单创建成功');
            window.location.href = response.data.alipay_url;
        }).catch(function (error) {
            console.log(error);
        });
    }
},

当没有选择地址弹框提示,接下来请求createOrder()也就是调用 api.js 中的接口

//添加订单
export const createOrder = params => {
    return axios.post(`${local_host}/orderinfo/`, params)
};

传递用户留言、收货地址、签收人、电话、订单总金额这个信息到后台,订单创建成功后会跳转到 http://127.0.0.1:8080/undefined 因为给出支付的地址,所以地址有误。

订单列表显示

用户中心可以查看订单列表 http://127.0.0.1:8080/#/app/home/member/order

<!--src/views/member/order.vue-->

<tr v-for="item in orders">
    <td align="center" bgcolor="#ffffff"><a class="f6" @click="goDetail(item.id)">{{item.order_sn}}</a></td>
    <td align="center" bgcolor="#ffffff">{{item.add_time}}</td>
    <td align="right" bgcolor="#ffffff">¥{{item.order_amount}}元</td>
    <td v-if="item.pay_status == 'topaid' " align="center" bgcolor="#ffffff">待支付</td>
    <td v-if="item.pay_status == 'success' " align="center" bgcolor="#ffffff">已支付</td>
    <td align="center" bgcolor="#ffffff"><font class="f6"><a @click="cancelOrder(item.id)">取消订单</a></font></td>
</tr>

当组件创建时,调用

// src/views/member/order.vue

created () {
    this.getOrder();
},

// src/views/member/order.vue

getOrder () {
    getOrders().then((response)=> {
        this.orders = response.data;
    }).catch(function (error) {
        console.log(error);
    });
},

该函数会请求api获取订单数据

// src/api/api.js

//获取订单
export const getOrders = () => {
    return axios.get(`${local_host}/orderinfo/`)
};

将结果遍历显示到表格中。

BLOG_20190722_210439_56

这是一个待支付状态,另外还有一个取消订单操作,用户点击取消订单,将该订单id传递给cancelOrder (id)函数

//src/views/member/order.vue

cancelOrder (id) {
    alert('您确认要取消该订单吗?取消后此订单将视为无效订单');
    delOrder(id).then((response)=> {
      alert('订单删除成功')
    }).catch(function (error) {
        console.log(error);
    });
},

请求api对订单进行删除

//src/api/api.js

//删除订单
export const delOrder = orderId => {
    return axios.delete(`${local_host}/orderinfo/` + orderId + '/')
};

订单详情显示

点击订单号可以进入订单详情

BLOG_20190722_210425_66

但是订单中的商品列表没有正常显示出来,所以要动态使用序列化,在显示订单详情时,使用另一个Serializer,并返回商品详情信息

创建OrderInfoDetailSerializer用于订单详情显示

添加一个新的序列化类,用于显示订单详情

# apps/trade/serializers.py

from trade.models import ShoppingCart, OrderInfo, OrderGoods
from goods.serializers import GoodsSerializer

# 订单中的商品序列化
class OrderGoodsSerializer(serializers.ModelSerializer):
    goods = GoodsSerializer()  # 直接用goods.serializers商品详情的序列化

    class Meta:
        model = OrderGoods
        fields = "__all__"


# 订单详情序列化
class OrderInfoDetailSerializer(serializers.ModelSerializer):
    order_goods = OrderGoodsSerializer(many=True)  # 为OrderGoods中外键关联名称

    class Meta:
        model = OrderInfo
        fields = "__all__"
修改OrderInfoViewSet动态获取Serializer

当访问订单详情就会使用专用的Serializer

# apps/trade/views.py

class OrderInfoViewSet(mixins.ListModelMixin, mixins.CreateModelMixin, mixins.RetrieveModelMixin, mixins.DestroyModelMixin, viewsets.GenericViewSet):
    """
    订单管理
    list:
        获取个人订单
    create:
        新建订单
    delete:
        删除订单
    detail:
        订单详情
    """
    permission_classes = (IsAuthenticated, IsOwnerOrReadOnly)  # 用户必须登录才能访问
    authentication_classes = (JWTAuthentication, SessionAuthentication)  # 配置登录认证:支持JWT认证和DRF基本认证
    queryset = OrderInfo.objects.all()
    # serializer_class = OrderInfoSerializer  # 添加序列化

    def get_queryset(self):
        return self.queryset.filter(user=self.request.user)

    def get_serializer_class(self):  # 动态序列化,当显示订单详情,用另一个Serializer
        if self.action == 'retrieve':
            return OrderInfoDetailSerializer
        else:
            return OrderInfoSerializer

    def perform_create(self, serializer):
        # 完成创建后保存到数据库,可以拿到保存的值
        order = serializer.save()
        shopping_carts = ShoppingCart.objects.filter(user=self.request.user)
        # 将该用户购物车所有商品都取出来放在订单商品中
        for shopping_cart in shopping_carts:
            OrderGoods.objects.create(
                order=order,
                goods=shopping_cart.goods,
                goods_nums=shopping_cart.nums
            )
        # 然后清空该用户购物车
        shopping_carts.delete()

访问 http://127.0.0.1:8000/orderinfo/3/?format=json 可以看到订单详情序列化的内容,格式化为json,变化收起

BLOG_20190722_210414_88

Vue中订单商品列表分析

BLOG_20190722_210407_18

访问 http://127.0.0.1:8080/#/app/home/member/orderDetail/3 可以进入该订单详情页

组件创建时,获取url的订单id,然后请求订单详情

// src/views/member/orderDetail.vue

created() {
    this.orderId = this.$route.params.orderId;
    this.getOrderInfo();
    //this.getReceiveByOrderId();
},

获取订单详情

// src/views/member/orderDetail.vue

getOrderInfo() { //获取订单信息
    getOrderDetail(this.orderId).then((response) => {
        this.orderInfo = response.data;
        var totalPrice = 0;
        //console.log(response.data.order_goods);
        response.data.order_goods.forEach(function (entry) {
            totalPrice += entry.goods_nums * entry.goods.shop_price
        });
        this.totalPrice = totalPrice

    }).catch(function (error) {
        console.log(error);
    });
},

这里面请求api

// src/api/api.js

//获取订单详情
export const getOrderDetail = orderId => {
    return axios.get(`${local_host}/orderinfo/` + orderId + '/')
};

请求成功后,在页面中显示

<!-- src/views/member/orderDetail.vue -->

<div class="userCenterBox boxCenterList clearfix" style="_height:1%;">
    <h5><span>订单状态</span></h5>
    <div class="blank"></div>
    <table width="100%" border="0" cellpadding="5" cellspacing="1" bgcolor="#dddddd">
        <tbody>
        <tr>
            <td width="15%" align="right" bgcolor="#ffffff">订单号:</td>
            <td align="left" bgcolor="#ffffff">{{orderInfo.order_sn}}
                <!-- <a href="http://sx.youxueshop.com/user.php?act=message_list&amp;order_id=778" class="f6">[发送/查看商家留言]</a> -->
            </td>
        </tr>
        <tr>
            <td align="right" bgcolor="#ffffff">订单状态:</td>
            <td v-if="orderInfo.pay_status == 'topaid' " align="left" bgcolor="#ffffff">待支付&nbsp;&nbsp;&nbsp;&nbsp;<div style="text-align:center"><a :href="orderInfo.alipay_url"><input type="button" onclick="" value="立即使用支付宝支付"></a></div>
            </td>
            <td v-if="orderInfo.pay_status == 'success' " align="left" bgcolor="#ffffff">已支付</td>
        </tr>
        </tbody>
    </table>
    <table></table>
    <div class="blank"></div>
    <h5>
        <span>商品列表</span>
    </h5>
    <div class="blank"></div>
    <table width="100%" border="0" cellpadding="5" cellspacing="1" bgcolor="#dddddd">
        <tbody>
        <tr>
            <th width="30%" align="center" bgcolor="#ffffff">商品名称</th>
            <!--<th>市场价</th>-->
            <th width="19%" align="center" bgcolor="#ffffff">商品价格</th>
            <th width="9%" align="center" bgcolor="#ffffff">购买数量</th>
            <th width="20%" align="center" bgcolor="#ffffff">小计</th>
        </tr>
        <tr v-for="item in orderInfo.order_goods">
            <td bgcolor="#ffffff">
                <router-link :to="'/app/home/productDetail/'+item.id" class="f6">{{item.goods.name}}</router-link>
                <!-- <a href="" target="_blank" class="f6">{{item.name}}</a> -->
            </td>
            <td align="center" bgcolor="#ffffff">¥{{item.goods.shop_price}}元</td>
            <td align="center" bgcolor="#ffffff">{{item.goods_nums}}</td>
            <td align="center" bgcolor="#ffffff">¥{{item.goods.shop_price*item.goods_nums}}元</td>
        </tr>
        <tr>
            <td colspan="8" bgcolor="#ffffff" align="right">
                商品总价: ¥{{totalPrice}}元
            </td>
        </tr>
        </tbody>
    </table>
    <div class="blank"></div>
    <div class="blank"></div>
    <h5><span>收货人信息</span></h5>
    <div class="blank"></div>
    <form name="formAddress" id="formAddress">
        <table width="100%" border="0" cellpadding="5" cellspacing="1" bgcolor="#dddddd">
            <tbody>
            <tr>
                <td width="15%" align="right" bgcolor="#ffffff">收货人姓名:</td>
                <td width="35%" align="left" bgcolor="#ffffff"><input name="consignee" type="text" class="inputBg" v-model="orderInfo.signer_name" size="25">
                </td>
                <td width="15%" align="right" bgcolor="#ffffff">收货地址:</td>
                <td width="35%" align="left" bgcolor="#ffffff"><input name="email" type="text" class="inputBg" v-model="orderInfo.address" size="25">
                </td>
            </tr>

            <tr>
                <td align="right" bgcolor="#ffffff">电话:</td>
                <td align="left" bgcolor="#ffffff"><input name="address" type="text" class="inputBg" v-model="orderInfo.signer_mobile" size="25"></td>
            </tr>
            </tbody>
        </table>
    </form>
    <div class="blank"></div>
</div>

也就是上图中的效果。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Vue和SpringCloud是两个独立的技术,分别用于前端和后端开发。在一个项目中,Vue通常用于构建前端界面和实现交互逻辑,而SpringCloud用于实现后端的业务逻辑和系统架构。 Vue是一个前端框架,它的特点是轻量级、灵活和易学习,非常适合开发单页面应用。Vue使用组件化的思想,将一个页面分解为多个独立的组件,每个组件负责不同的功能,从而实现页面的高复用性和可维护性。在项目中,可以使用Vue来实现品列表、购物车、订单管理等功能页面。 SpringCloud是一个微服务框架,它提供了一系列的服务组件和工具,用于快速开发、部署和管理分布式系统。SpringCloud基于Spring Boot,可以轻松地与其他Spring组件集成,如Spring MVC、Spring Data等。在项目中,可以使用SpringCloud来实现用户管理、品管理、订单管理等后端服务。 关于项目的源码,一般来说,前端和后端的源码是分开的。前端的源码主要是基于Vue进行开发,通常包含HTML、CSS、JavaScript等文件。而后端的源码主要是基于SpringCloud进行开发,通常包含Java代码、配置文件等。 前端的源码主要用于构建用户界面和实现页面交互逻辑。它通过用后端的接口获取数据,并将数据展示给用户。用户在前端界面上的操作会触发相应的事件,前端通过用后端的接口来处理这些事件。 后端的源码主要用于实现业务逻辑和系统架构。它通过定义接口、编写业务逻辑和用后台数据库等方式来处理请求。这些请求可以来自前端,也可以来自其他后端服务。 总之,Vue和SpringCloud是项目中常用的技术,用于实现前端和后端的功能项目的源码通常分为前端和后端两部分,前端主要基于Vue开发,后端主要基于SpringCloud开发。 ### 回答2: Vue springcloud 项目源码是一个基于 Vue.js 和 Spring Cloud 架构开发的项目的代码,它提供了一个完整的平台的功能Vue.js 是一个流行的前端框架,通过使用它,开发人员可以轻松地构建用户界面。Vue.js 对数据的双向绑定和组件化的开发方式,使得开发人员能够高效地开发出动态和可交互的用户界面。 Spring Cloud 是一个微服务架构的解决方案,它提供了一套完整的解决方案来构建分布式系统。通过使用 Spring Cloud,开发人员可以轻松实现服务注册与发现、负载均衡、熔断器等功能,从而简化了分布式系统的开发和部署。 这个项目源码结合了 Vue.js 和 Spring Cloud 的优点,提供了一个高可扩展性、易于维护的平台。它包含了用户注册、登录、品浏览、购物车管理、订单管理、支付等常见的功能。开发者可以根据实际需求对其进行定制和扩展。 该项目源码还提供了一套完整的开发文档和示例,开发人员可以根据文档来了解项目的整体架构和各个模块的功能实现细节,从而快速上手并进行二次开发。 总之,Vue springcloud 项目源码是一个基于 Vue.js 和 Spring Cloud 架构开发的项目的代码,提供了一个完整的平台的功能,并附带了详细的开发文档和示例,方便开发人员进行二次开发和定制。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值