tenth_支付页面

2. 创建子应用
cd luffy/apps
python ../../manage.py startapp orders
# 注册子应用,settings/dev.py,代码: INSTALLED_APPS = [ # 子应用 。。。 'orders', ]
3. 订单模型
from django.db import models # Create your models here. from luffy.utils.models import BaseModel from users.models import User from courses.models import Course class Order(BaseModel): """订单记录""" status_choices = ( (0, '未支付'), (1, '已支付'), (2, '已取消'), (3, '超时取消'), ) pay_choices = ( (0, '支付宝'), (1, '微信支付') ) order_title = models.CharField(max_length=150,verbose_name="订单标题") total_price = models.DecimalField(max_digits=6, decimal_places=2, verbose_name="订单总价", default=0) real_price = models.DecimalField(max_digits=6, decimal_places=2, verbose_name="实付金额", default=0) order_number = models.CharField(max_length=64,verbose_name="订单号") order_status = models.SmallIntegerField(choices=status_choices, default=0, verbose_name="订单状态") pay_type = models.SmallIntegerField(choices=pay_choices, default=0, verbose_name="支付方式") use_coupon = models.BooleanField(default=False,verbose_name="是否使用优惠券") coupon = models.IntegerField(null=True, verbose_name="用户优惠券ID") order_desc = models.TextField(max_length=500, verbose_name="订单描述") pay_time = models.DateTimeField(null=True, verbose_name="支付时间") user = models.ForeignKey(User, related_name='user_orders', on_delete=models.DO_NOTHING,verbose_name="下单用户") class Meta: db_table="ly_order" verbose_name= "订单记录" verbose_name_plural= "订单记录" def __str__(self): return "%s,总价: %s,实付: %s" % (self.order_title, self.total_price, self.real_price) class OrderDetail(BaseModel): """订单详情""" order = models.ForeignKey(Order, related_name='order_courses', on_delete=models.CASCADE, verbose_name="订单") course = models.ForeignKey(Course, related_name='course_orders', on_delete=models.CASCADE, verbose_name="课程") expire = models.IntegerField(default='-1', verbose_name="有效期周期") price = models.DecimalField(max_digits=6, decimal_places=2, verbose_name="课程原价") real_price = models.DecimalField(max_digits=6, decimal_places=2, verbose_name="课程实价") discount_name = models.CharField(max_length=120,default="",verbose_name="优惠活动类型") class Meta: db_table="ly_order_detail" verbose_name= "订单详情" verbose_name_plural= "订单详情"
# 在当前子应用下创建adminx.py,代码: import xadmin from .models import Order class OrderModelAdmin(object): """订单模型管理类""" pass xadmin.site.register(Order, OrderModelAdmin) from .models import OrderDetail class OrderDetailModelAdmin(object): """订单详情模型管理类""" pass xadmin.site.register(OrderDetail, OrderDetailModelAdmin)
from django.shortcuts import render from rest_framework.views import APIView from rest_framework.permissions import IsAuthenticated from django_redis import get_redis_connection from rest_framework.response import Response from .models import Order,OrderDetail from datetime import datetime from courses.models import Course, CourseTime import random class OrderAPIView(APIView): # permission_classes = [IsAuthenticated] def post(self,request): """生成订单""" # 获取用户ID user_id = 1 # user_id = request.user.id # 订单号,必须保证唯一 order_number = datetime.now().strftime("%Y%m%d%H%M%S") + "%08d" % user_id + "%04d" % random.randint(0,9999) # 生成空的订单 order = Order.objects.create( order_title="路飞学城课程购买", total_price=0, real_price=0, order_number= order_number, user_id=user_id, ) # 到redis获取购物车信息 redis = get_redis_connection("cart") # 勾选状态 course_selects_set = redis.smembers("cart_selected_%s" % user_id ) print( course_selects_set ) # 购物车中商品课程列表 cart_course_list = redis.hgetall("cart_%s" % user_id ) print( cart_course_list ) # 通过购物车信息到数据中提取相关数据 # 计算订单总价 total_price = 0 # 开启redis的管道操作[事务操作] pipeline = redis.pipeline() pipeline.multi() for course_id_byte,expire_byte in cart_course_list.items(): if course_id_byte in course_selects_set: expire = expire_byte.decode() course_id = course_id_byte.decode() course = Course.objects.get(pk=course_id) if expire == '-1': """永久有效""" course_price = course.get_course_price() else: """有购买周期""" coursetime = CourseTime.objects.get(course=course_id,timer=expire) course_price = coursetime.course.get_course_price(coursetime.price) total_price += course_price # 生成订单详情 OrderDetail.objects.create( order_id=order.id, course_id=course_id, expire=expire, price=course.price if expire=='-1' else coursetime.price, real_price=course_price, discount_name=course.get_course_discount_type() ) # 从购物车中移除已经加入订单的商品 pipeline.srem("cart_selected_%s" % user_id, course_id ) pipeline.hdel("cart_%s" % user_id, course_id ) # 提交redis的事务操作 pipeline.execute() # 补充订单的总价格 order.total_price=total_price order.real_price=total_price order.save() # 响应结果 return Response({"message":"ok"})
# 更新 utils from django.db import models class BaseModel(models.Model): """公共字段模型""" orders = models.IntegerField(null=True, blank=True, verbose_name='显示顺序') is_show=models.BooleanField(verbose_name="是否上架",default=False) is_delete=models.BooleanField(verbose_name="逻辑删除",default=False) create_time = models.DateTimeField(auto_now_add=True,verbose_name="添加时间") update_time = models.DateTimeField(auto_now=True,verbose_name="更新时间") class Meta: # 设置当前模型在数据迁移的时候不要为它创建表 abstract = True
上面我们使用了redis的事务操作保证数据的一致性。但是mysql里面我们也是在进行多表操作,所以也是需要使用事务来保证数据的一致性的。
事务有四大特性: 原子性(Atomicity) 一致性(Consistency) 隔离性(Isolation)[事务隔离级别->幻读,脏读] 持久性(Durability)
django框架本身就提供了2种事务操作的用法。
django的事务操作方法主要通过 django.db.transation模块完成的。
# 启用事务用法1: from django.db import transaction from rest_framework.views import APIView class OrderAPIView(APIView): @transaction.atomic # 开启事务,当方法执行完成以后,自动提交事务 def post(self,request): .... # 启用事务用法2: from django.db import transaction from rest_framework.views import APIView class OrderAPIView(APIView): def post(self,request): .... with transation.atomic(): # 开启事务,当with语句执行完成以后,自动提交事务 # 数据库操作
# 在使用事务过程中, 有时候会出现异常,当出现异常的时候,我们需要让程序停止下来,同时需要回滚事务。 from django.db import transaction from rest_framework.views import APIView class OrderAPIView(APIView): def post(self,request): .... with transation.atomic(): # 设置事务回滚的标记点 sid = transation.savepoint() .... try: .... except: transation.savepoint_rallback(sid)
# 视图代码: from django.shortcuts import render from rest_framework.views import APIView from rest_framework.permissions import IsAuthenticated from django_redis import get_redis_connection from rest_framework.response import Response from .models import Order,OrderDetail from datetime import datetime from courses.models import Course, CourseTime import random from django.db import transaction from rest_framework import status import logging log = logging.getLogger("django") class OrderAPIView(APIView): permission_classes = [IsAuthenticated] def post(self,request): """生成订单""" # 获取用户ID # user_id = 1 user_id = request.user.id # 订单号,必须保证唯一 order_number = datetime.now().strftime("%Y%m%d%H%M%S") + "%08d" % user_id + "%04d" % random.randint(0,9999) with transaction.atomic(): # 数据库事务的回滚标记 save_id = transaction.savepoint() # 生成空的订单 try: order = Order.objects.create( order_title="路飞学城课程购买", total_price=0, real_price=0, order_number= order_number, user_id=user_id, ) # 到redis获取购物车信息 redis = get_redis_connection("cart") # 勾选状态 course_selects_set = redis.smembers("cart_selected_%s" % user_id ) print( course_selects_set ) # 购物车中商品课程列表 cart_course_list = redis.hgetall("cart_%s" % user_id ) print( cart_course_list ) # 通过购物车信息到数据中提取相关数据 # 计算订单总价 total_price = 0 # 开启redis的管道操作[事务操作] pipeline = redis.pipeline() pipeline.multi() for course_id_byte,expire_byte in cart_course_list.items(): if course_id_byte in course_selects_set: expire = expire_byte.decode() course_id = course_id_byte.decode() course = Course.objects.get(pk=course_id) if expire == '-1': """永久有效""" course_price = course.get_course_price() else: """有购买周期""" coursetime = CourseTime.objects.get(course=course_id,timer=expire) course_price = coursetime.course.get_course_price(coursetime.price) total_price += course_price # 生成订单详情 OrderDetail.objects.create( order_id=order.id, course_id=course_id, expire=expire, price=course.price if expire=='-1' else coursetime.price, real_price=course_price, discount_name=course.get_course_discount_type() ) # 从购物车中移除已经加入订单的商品 pipeline.srem("cart_selected_%s" % user_id, course_id ) pipeline.hdel("cart_%s" % user_id, course_id ) # 提交redis的事务操作 pipeline.execute() # 补充订单的总价格 order.total_price=total_price order.real_price=total_price order.save() except Exception: # 记录错误日志 log.error( "%s" % Exception ) # 回滚事务 transaction.savepoint_rollback(save_id) # 响应结果 return Response({"message":"系统异常"},status=status.HTTP_507_INSUFFICIENT_STORAGE) # 响应结果 return Response({"message":"ok","order":order.order_number})
<template> 。。。 <span class="go-pay" @click="gotopay">去结算</span> 。。。 </template> <script> import Header from "./common/Header" import Footer from "./common/Footer" export default { name: "Cart", 。。。。 methods:{ 。。。。 gotopay(){ // 提交结算,生成订单 this.$axios.post(this.$settings.Host+"/orders/",{},{ headers:{ // 注意:jwt后面必须有且只有一个空格!!!! "Authorization":"jwt " + this.token } }).then(response=>{ let _this = this; this.$alert(response.data.message,"提示",{ callback(){ _this.$router.push(`orders/${response.data.order}`); } }) }).catch(error=>{ console.log(error.response) }) } }, components:{Header,Footer} } </script>
<template> <div class="cart"> <Header/> <div class="cart-info"> <h3 class="cart-top">购物车结算 <span>共1门课程</span></h3> <div class="cart-title"> <el-row> <el-col :span="2"> </el-col> <el-col :span="10">课程</el-col> <el-col :span="8">有效期</el-col> <el-col :span="4">价格</el-col> </el-row> </div> <div class="cart-item" v-for="item in course_list"> <el-row> <el-col :span="2" class="checkbox"> </el-col> <el-col :span="10" class="course-info"> <img :src="item.course.course_http_img" alt=""> <span>{{item.course.name}}</span> </el-col> <el-col :span="8"><span>永久有效</span></el-col> <el-col :span="4" class="course-price">¥{{item.unit_price}}</el-col> </el-row> </div> <div class="calc"> <el-row class="pay-row"> <el-col :span="4" class="pay-col"><span class="pay-text">支付方式:</span></el-col> <el-col :span="8"> <span class="alipay"><img src="../../static/img/alipay2.png" alt=""></span> <span class="alipay wechat"><img src="../../static/img/wechat.png" alt=""></span> </el-col> <el-col :span="8" class="count">实付款: <span>¥{{total}}</span></el-col> <el-col :span="4" class="cart-pay"><span @click="payhander">支付宝支付</span></el-col> </el-row> </div> </div> <Footer/> </div> </template> <script> import Header from "./common/Header" import Footer from "./common/Footer" export default { name:"Order", data(){ return { token: localStorage.token || sessionStorage.token, id: localStorage.id || sessionStorage.id, order_id:sessionStorage.order_id || null, course_list:[], total:0, } }, components:{ Header, Footer, }, created(){ }, methods: { payhander(){ } } } </script> <style scoped> .cart{ margin-top: 80px; } .cart-info{ overflow: hidden; width: 1200px; margin: auto; } .cart-top{ font-size: 18px; color: #666; margin: 25px 0; font-weight: normal; } .cart-top span{ font-size: 12px; color: #d0d0d0; display: inline-block; } .cart-title{ background: #F7F7F7; height: 70px; } .calc{ margin-top: 25px; margin-bottom: 40px; } .calc .count{ text-align: right; margin-right: 10px; vertical-align: middle; } .calc .count span{ font-size: 36px; color: #333; } .calc .cart-pay{ margin-top: 5px; width: 110px; height: 38px; outline: none; border: none; color: #fff; line-height: 38px; background: #ffc210; border-radius: 4px; font-size: 16px; text-align: center; cursor: pointer; } .cart-item{ height: 120px; line-height: 120px; } .course-info img{ width: 175px; height: 115px; margin-right: 35px; vertical-align: middle; } .alipay{ display: inline-block; height: 48px; } .alipay img{ height: 100%; width:auto; } .pay-text{ display: block; text-align: right; height: 100%; line-height: 100%; vertical-align: middle; margin-top: 20px; } </style>
# orders/serializers.py,序列化器,代码: from rest_framework import serializers from .models import Order,OrderDetail class OrderCourseSerializer(serializers.ModelSerializer): class Meta: model = OrderDetail fields = ("course_name","expire_text","price","real_price","discount_name","course_img") class OrderDetailModelSerializer(serializers.ModelSerializer): order_courses = OrderCourseSerializer(many=True) class Meta: model = Order fields = ("id", "total_price", "real_price","pay_type","use_coupon","coupon","order_courses") # 模型中新增返回课程图片的字段,代码: from courses.models import CourseTime class OrderDetail(BaseModel): """订单详情""" order = models.ForeignKey(Order, related_name='order_courses', on_delete=models.CASCADE, verbose_name="订单") course = models.ForeignKey(Course, related_name='course_orders', on_delete=models.CASCADE, verbose_name="课程") expire = models.IntegerField(default='-1', verbose_name="有效期周期") price = models.DecimalField(max_digits=6, decimal_places=2, verbose_name="课程原价") real_price = models.DecimalField(max_digits=6, decimal_places=2, verbose_name="课程实价") discount_name = models.CharField(max_length=120,default="",verbose_name="优惠活动类型") class Meta: db_table="ly_order_detail" verbose_name= "订单详情" verbose_name_plural= "订单详情" def course_img(self): # 返回图片的url地址 return self.course.course_img.url def expire_text(self): if self.expire == -1: return "永久有效" else: print( self.expire ) coursetime = CourseTime.objects.get(timer=self.expire,course=self.course) return coursetime.title def course_name(self): return self.course.name # 视图代码: from .serializers import OrderDetailModelSerializer class OrderDetailAPIView(APIView): permission_classes = [IsAuthenticated] def get(self,request,pk): try: order = Order.objects.get(order_number=pk) except Order.DoesNotExist: return Response({"message":"订单信息有误!"},status=status.HTTP_400_BAD_REQUEST) serializer = OrderDetailModelSerializer(instance=order) return Response(serializer.data, status=status.HTTP_200_OK) # 路由代码: re_path(r"(?P<pk>\d+)/",views.OrderDetailAPIView.as_view()),
<template> <div class="cart"> <Header/> <div class="cart-info"> <h3 class="cart-top">购物车结算 <span>共1门课程</span></h3> <div class="cart-title"> <el-row> <el-col :span="2"> </el-col> <el-col :span="10">课程</el-col> <el-col :span="8">有效期</el-col> <el-col :span="4">价格</el-col> </el-row> </div> <div class="cart-item" v-for="course in order_info.order_courses"> <el-row> <el-col :span="2" class="checkbox"> </el-col> <el-col :span="10" class="course-info"> <img style="float: left;" :src="$settings.Host+course.course_img" alt=""> <span class="course_name"> <span>{{course.course_name}}</span><br> <span class="discount_name">{{course.discount_name}}</span> </span> </el-col> <el-col :span="8" class="lh"><span>{{course.expire_text}}</span></el-col> <el-col :span="4"> <div class="course-price"> <p class="real_price">¥{{course.real_price}}</p> <span class="original_price">原价: ¥{{course.price}}</span> </div> </el-col> </el-row> </div> <div> <div class="coupon"> <div id="accordion"> <div class="coupon-box"> <div class="coupon-title"> <span class="select-coupon">使用优惠劵:</span> <a data-toggle="collapse" data-parent="#accordion" href="#collapseOne" style="width: 20px; height: 20px" class="collapsed" aria-expanded="false"> <img class="sign" src="../../static/img/12.png" width="20" height="20" alt=""></a> <span class="coupon-num">有0张可用</span> </div> <p class="sum-price-wrap" style="margin-right: 45px">商品总金额:<span class="sum-price">{{order_info.total_price}}元</span></p> </div> <div style="text-align: left; height: 0px;" id="collapseOne" class="panel-collapse out collapse" aria-expanded="false"> <ul class="coupon-list" style="display: none;"> </ul> <div style="text-align: center; width: 100%; padding: 50px 0px; align-items: center; justify-content: center; border-bottom: 1px solid rgb(232, 232, 232);"> <span style="font-size: 16px; color: #9b9b9b">暂无可用优惠券</span> </div> </div> </div> <div style="height: 30px; margin-top: 40px; display: flex; align-items: center; justify-content: flex-end"> <input type="checkbox" class="ok" id="color-input-red"> <label for="color-input-red"><img src="data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPHN2ZyB3aWR0aD0iMTFweCIgaGVpZ2h0PSI5cHgiIHZpZXdCb3g9IjAgMCAxMSA5IiB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiPgogICAgPCEtLSBHZW5lcmF0b3I6IFNrZXRjaCA0OS4zICg1MTE2NykgLSBodHRwOi8vd3d3LmJvaGVtaWFuY29kaW5nLmNvbS9za2V0Y2ggLS0+CiAgICA8dGl0bGU+5Yu+6YCJPC90aXRsZT4KICAgIDxkZXNjPkNyZWF0ZWQgd2l0aCBTa2V0Y2guPC9kZXNjPgogICAgPGRlZnM+PC9kZWZzPgogICAgPGcgaWQ9IumAgumFjU3pobUyIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMSIgZmlsbD0ibm9uZSIgZmlsbC1ydWxlPSJldmVub2RkIj4KICAgICAgICA8ZyBpZD0i5o+Q5Lqk6K6i5Y2VIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgtMzM4LjAwMDAwMCwgLTQyMi4wMDAwMDApIiBmaWxsPSIjRkZGRkZGIj4KICAgICAgICAgICAgPGcgaWQ9IkNoZWNrYm94LUNvcHkiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDMzMi4wMDAwMDAsIDQxNC4wMDAwMDApIj4KICAgICAgICAgICAgICAgIDxwYXRoIGQ9Ik0xMC4wNzc0NjQ3LDEwLjgyMTM3MSBMMTUuMzYwNDQ5NCwxNi4xMDQzNTU3IEMxNS41NTU1OTAyLDE2LjI5OTQ5NjUgMTUuNTU2NDcwOCwxNi42MTUwMDE2IDE1LjM1NTgxMDIsMTYuODE1NjYyMSBMMTQuOTQwMzg1LDE3LjIzMTA4NzQgQzE0Ljc0MjY4MjEsMTcuNDI4NzkwMyAxNC40Mjg3Nzc4LDE3LjQzNTQyNTggMTQuMjI5MDc4NSwxNy4yMzU3MjY1IEw4LjE4NzExODU4LDExLjE5Mzc2NjYgQzguMDc5MzUwNDgsMTEuMDg1OTk4NSA4LjAzMDgyOTYyLDEwLjk0MTUyMDYgOC4wNDI3ODIzNCwxMC43OTk5NDk3IEM4LjA0MjQ1NjUsMTAuNjcyNTEyOSA4LjA4OTMwMDA2LDEwLjU0Njc5MzkgOC4xODE0NjU5OCwxMC40NTQ2MjggTDExLjI1MzU2ODcsNy4zODI1MjUzMyBDMTEuNDQ1NTg3Niw3LjE5MDUwNjM3IDExLjc1ODU2Miw3LjE5MjE1NjUyIDExLjk1OTIyMjYsNy4zOTI4MTcwNiBMMTIuMzc0NjQ3OCw3LjgwODI0MjI5IEMxMi41NzIzNTA3LDguMDA1OTQ1MjEgMTIuNTcwNzM3Myw4LjMyODA5ODM1IDEyLjM4NDkzOTUsOC41MTM4OTYxOCBMMTAuMDc3NDY0NywxMC44MjEzNzEgWiIgaWQ9IuWLvumAiSIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMTEuNzczNzg0LCAxMi4zMTE0MjMpIHJvdGF0ZSgtOTAuMDAwMDAwKSB0cmFuc2xhdGUoLTExLjc3Mzc4NCwgLTEyLjMxMTQyMykgIj48L3BhdGg+CiAgICAgICAgICAgIDwvZz4KICAgICAgICA8L2c+CiAgICA8L2c+Cjwvc3ZnPgo=" alt=""></label> <p class="discount-num" style="color:#9B9B9B">使用我的贝里</p> <p class="discount-num" style="margin-right: 45px"> <span style="display: none;">可用0个已抵扣 ¥0</span> </p> </div> <p class="sun-coupon-num" style="margin-right: 45px;margin-bottom:43px">优惠券抵扣:<span>0元</span></p> </div> </div> <div class="calc"> <el-row class="pay-row"> <el-col :span="4" class="pay-col"><span class="pay-text">支付方式:</span></el-col> <el-col :span="8"> <span class="alipay"><img src="../../static/img/alipay2.png" alt=""></span> <span class="alipay wechat"><img src="../../static/img/wechat.png" alt=""></span> </el-col> <el-col :span="8" class="count">实付款: <span>¥{{order_info.total_price}}</span></el-col> <el-col :span="4" class="cart-pay"><span @click="payhander">支付宝支付</span></el-col> </el-row> </div> </div> <Footer/> </div> </template> <script> import Header from "./common/Header" import Footer from "./common/Footer" export default { name:"Order", data(){ return { order_info:{}, } }, components:{ Header, Footer, }, created(){ // 判断用户是否已经登录 let token = sessionStorage.token || localStorage.token; let _this = this; if(!token){ this.$alert("对不起,您尚未登录!请登录!","警告",{ callback(){ _this.$router.push("/login"); } }) } // 获取地址栏上面的订单号 let order_number = this.$route.params.order; // 发送请求获取数据 this.$axios.get(this.$settings.Host+`/orders/${order_number}/`,{ headers:{ // 注意下方的空格!!! "Authorization":"jwt " + token, }, }).then(response=>{ this.order_info = response.data; }).catch(error=>{ console.log(error.response); }) }, methods: { payhander(){ } } } </script> <style scoped> .cart{ margin-top: 80px; } .cart-info{ overflow: hidden; width: 1200px; margin: auto; } .cart-top{ font-size: 18px; color: #666; margin: 25px 0; font-weight: normal; } .cart-top span{ font-size: 12px; color: #d0d0d0; display: inline-block; } .cart-title{ background: #F7F7F7; height: 70px; } .calc{ margin-top: 25px; margin-bottom: 40px; } .calc .count{ text-align: right; margin-right: 10px; vertical-align: middle; } .calc .count span{ font-size: 36px; color: #333; } .calc .cart-pay{ margin-top: 5px; width: 110px; height: 38px; outline: none; border: none; color: #fff; line-height: 38px; background: #ffc210; border-radius: 4px; font-size: 16px; text-align: center; cursor: pointer; } .cart-item{ height: 120px; /*line-height: 120px;*/ } .cart-item .lh{ line-height: 120px; } .course-info img{ width: 175px; height: 115px; margin-right: 35px; vertical-align: middle; } .course-price{ margin-top: 40px; } .alipay{ display: inline-block; height: 48px; } .alipay img{ height: 100%; width:auto; } .pay-text{ display: block; text-align: right; height: 100%; line-height: 100%; vertical-align: middle; margin-top: 20px; } .real_price{ color: #333; margin-bottom: 10px; } .original_price{ color: #9b9b9b; letter-spacing: .36px; text-decoration: line-through; } .coupon{ margin-top: 30px; } .coupon-box{ text-align: left; display: flex; padding-bottom: 22px; padding-left:30px; border-bottom: 1px solid #e8e8e8; } .coupon-title{ display: flex; } .sum-price-wrap{ display: inline-block; margin-left: auto; font-size: 16px; color: #4a4a4a; } .discount_name{ color: #ffc210; margin-top: 24px; font-size: 14px; letter-spacing: .32px; } .course_name{ margin-top: 40px; display: block; } </style>

浙公网安备 33010602011771号