课程列表页
前端显示课程列表页面
把课程列表页面组件Course.vue放到项目中.
<template> <div class="courses"> <Header :current_page="current_page"/> <div class="main"> <div class="filter"> <el-row class="filter-el-row1"> <el-col :span="2" class="filter-text">课程分类:</el-col> <el-col :span="2" class="current">全部</el-col> <el-col :span="2">Python</el-col> <el-col :span="2">Linux运维</el-col> <el-col :span="2">Python进阶</el-col> <el-col :span="2">开发工具</el-col> <el-col :span="2">Go语言</el-col> <el-col :span="2">机器学习</el-col> <el-col :span="2">技术生涯</el-col> </el-row> <el-row class="filter-el-row2"> <el-col :span="2" class="filter-text filter-text2">筛 选:</el-col> <el-col :span="2" class="current">默认</el-col> <el-col :span="2">人气</el-col> <el-col :span="2" class=""> <span @click.stop="filter_price=!filter_price">价格</span> <div class="filter-price"> <span class="up" @click.stop="filter_price=true" :class="filter_price==true?'active':''"><i class="el-icon-caret-top"></i></span> <span class="down" @click.stop="filter_price=false" :class="filter_price==false?'active':''"><i class="el-icon-caret-bottom"></i></span> </div> </el-col> </el-row> </div> <div class="courses_list"> <el-row class="course-item"> <el-col :span="24" class="course-item-box"> <el-row> <el-col :span="12" class="course-item-left"><img src="/static/courses/675076.jpeg" alt=""></el-col> <el-col :span="12" class="course-item-right"> <div class="course-title"> <p class="box-title">Go编程33天从入门到放弃系列</p> <p class="box-number">30074人已加入学习</p> </div> <div class="author"> <p class="box-author">Alex 金角大王 老男孩Python教学总监</p> <p class="lession">共154课时<span>/更新完成</span></p> </div> <el-row class="course-content"> <el-col :span="12"><i class="el-icon-caret-right"></i>01 | 常用模块学习-模块的种类和... <span class="free">免费</span> </el-col> <el-col :span="12"><i class="el-icon-caret-right"></i>02 | 常用模块学习-模块的种类和... <span class="free">免费</span> </el-col> <el-col :span="12"><i class="el-icon-caret-right"></i>03 | 三元运算符... <span class="free">免费</span> </el-col> <el-col :span="12"><i class="el-icon-caret-right"></i>04 | 常用模块学习-模块的种类和... <span class="free">免费</span> </el-col> </el-row> <div class="course-price"> <p class="course-price-left"> <span class="discount">限时免费</span> <span class="count">¥0.00</span> <span class="old_count">原价: ¥8.00元</span> </p> <button class="buy">立即购买</button> </div> </el-col> </el-row> </el-col> </el-row> <el-row class="course-item"> <el-col :span="24" class="course-item-box"> <el-row> <el-col :span="12" class="course-item-left"><img src="/static/courses/675076.jpeg" alt=""></el-col> <el-col :span="12" class="course-item-right"> <div class="course-title"> <p class="box-title">Go编程33天从入门到放弃系列</p> <p class="box-number">30074人已加入学习</p> </div> <div class="author"> <p class="box-author">Alex 金角大王 老男孩Python教学总监</p> <p class="lession">共154课时<span>/更新完成</span></p> </div> <el-row class="course-content"> <el-col :span="12"><i class="el-icon-caret-right"></i>01 | 常用模块学习-模块的种类和... <span class="free">免费</span> </el-col> <el-col :span="12"><i class="el-icon-caret-right"></i>02 | 常用模块学习-模块的种类和... <span class="free">免费</span> </el-col> <el-col :span="12"><i class="el-icon-caret-right"></i>03 | 三元运算符... <span class="free">免费</span> </el-col> <el-col :span="12"><i class="el-icon-caret-right"></i>04 | 常用模块学习-模块的种类和... <span class="free">免费</span> </el-col> </el-row> <div class="course-price"> <p class="course-price-left"> <span class="discount">限时免费</span> <span class="count">¥0.00</span> <span class="old_count">原价: ¥8.00元</span> </p> <button class="buy">立即购买</button> </div> </el-col> </el-row> </el-col> </el-row> <el-row class="course-item"> <el-col :span="24" class="course-item-box"> <el-row> <el-col :span="12" class="course-item-left"><img src="/static/courses/675076.jpeg" alt=""></el-col> <el-col :span="12" class="course-item-right"> <div class="course-title"> <p class="box-title">Go编程33天从入门到放弃系列</p> <p class="box-number">30074人已加入学习</p> </div> <div class="author"> <p class="box-author">Alex 金角大王 老男孩Python教学总监</p> <p class="lession">共154课时<span>/更新完成</span></p> </div> <el-row class="course-content"> <el-col :span="12"><i class="el-icon-caret-right"></i>01 | 常用模块学习-模块的种类和... <span class="free">免费</span> </el-col> <el-col :span="12"><i class="el-icon-caret-right"></i>02 | 常用模块学习-模块的种类和... <span class="free">免费</span> </el-col> <el-col :span="12"><i class="el-icon-caret-right"></i>03 | 三元运算符... <span class="free">免费</span> </el-col> <el-col :span="12"><i class="el-icon-caret-right"></i>04 | 常用模块学习-模块的种类和... <span class="free">免费</span> </el-col> </el-row> <div class="course-price"> <p class="course-price-left"> <span class="discount">限时免费</span> <span class="count">¥0.00</span> <span class="old_count">原价: ¥8.00元</span> </p> <button class="buy">立即购买</button> </div> </el-col> </el-row> </el-col> </el-row> <el-row class="course-item"> <el-col :span="24" class="course-item-box"> <el-row> <el-col :span="12" class="course-item-left"><img src="/static/courses/675076.jpeg" alt=""></el-col> <el-col :span="12" class="course-item-right"> <div class="course-title"> <p class="box-title">Go编程33天从入门到放弃系列</p> <p class="box-number">30074人已加入学习</p> </div> <div class="author"> <p class="box-author">Alex 金角大王 老男孩Python教学总监</p> <p class="lession">共154课时<span>/更新完成</span></p> </div> <el-row class="course-content"> <el-col :span="12"><i class="el-icon-caret-right"></i>01 | 常用模块学习-模块的种类和... <span class="free">免费</span> </el-col> <el-col :span="12"><i class="el-icon-caret-right"></i>02 | 常用模块学习-模块的种类和... <span class="free">免费</span> </el-col> <el-col :span="12"><i class="el-icon-caret-right"></i>03 | 三元运算符... <span class="free">免费</span> </el-col> <el-col :span="12"><i class="el-icon-caret-right"></i>04 | 常用模块学习-模块的种类和... <span class="free">免费</span> </el-col> </el-row> <div class="course-price"> <p class="course-price-left"> <span class="discount">限时免费</span> <span class="count">¥0.00</span> <span class="old_count">原价: ¥8.00元</span> </p> <button class="buy">立即购买</button> </div> </el-col> </el-row> </el-col> </el-row> </div> </div> <Footer/> </div> </template> <script> import Header from "./common/Header" import Footer from "./common/Footer" export default { name:"Courses", data(){ return { current_page:1, filter_price:false, } }, components:{ Header, Footer, }, methods:{ } } </script> <style scoped> .courses{ padding-top: 80px; } .main{ width: 1100px; height: auto; margin: 0 auto; padding-top: 35px; } .main .filter{ width: 100%; height: auto; margin-bottom: 35px; padding: 25px 0px 25px 0px; background: #fff; border-radius: 4px; box-shadow: 0 2px 4px 0 #f0f0f0; } .filter .el-col{ text-align: center; padding: 6px 0px; line-height: 16px; margin-left: 14px; position: relative; transition: all .3s ease; cursor: pointer; color: #4a4a4a; } .filter-el-row1{ padding-bottom: 18px; margin-bottom: 17px; } .filter .filter-text{ text-align: right; font-size: 16px; color: #888; } .filter .filter-text2{ } .filter .filter-el-row1 .current{ color: #ffc210; border: 1px solid #ffc210!important; border-radius: 30px; } .filter .filter-el-row2 .current{ color: #ffc210; } .filter-price{ display:inline-block; vertical-align: middle; } .filter-price .up, .filter-price .down{ display: block; line-height: 8px; font-size: 13px; margin: -4px; color: #d8d8d8; } .current .filter-price .active{ color: #ffc210; } .course-item{ margin-bottom: 35px; } .course-item .course-item-box{ padding: 20px 30px 20px 20px; } .course-item{ box-shadow: 2px 3px 16px rgba(0,0,0,.1); transition: all .2s ease; } .course-item .course-item-left{ width: 423px; height: 210px; margin-right: 30px; } .course-title{ overflow: hidden;/* 在父元素中使用可以清除子元素的浮动影响 */ } .course-title .box-title{ font-size: 26px; color: #333333; float: left; margin-bottom: 8px; } .course-title .box-number{ font-size: 14px; color: #9b9b9b; font-family: PingFangSC-Light; float: right; padding-top: 12px; } .course-item-right{ width: 56.6%; } .author{ font-size: 14px; color: #9b9b9b; margin-bottom: 14px; padding-bottom: 14px; overflow: hidden; } .author .box-author{ float:left; } .author .lession{ float: right; } .course-content .el-icon-caret-right{ border: 1px solid #000; border-radius: 50%; margin-right: 6px; } .course-content .el-col{ font-size: 14px; color: #666; width: 50%; margin-bottom: 15px; cursor: pointer; } .course-content .el-col:hover{ color: #ffc210; } .course-content .el-col:hover .el-icon-caret-right,.course-content .el-col:hover .free{ border-color: #ffc210; color: #ffc210; } .course-content .el-col .free{ width: 34px; height: 20px; color: #fd7b4d; margin-left: 10px; border: 1px solid #fd7b4d; border-radius: 2px; text-align: center; font-size: 13px; white-space: nowrap; } .course-price{ overflow: hidden; } .course-price .course-price-left{ float: left; } .course-price .discount{ padding: 6px 10px; display: inline-block; font-size: 16px; color: #fff; text-align: center; margin-right: 8px; background: #fa6240; border: 1px solid #fa6240; border-radius: 10px 0 10px 0; } .course-price .course-price-left{ line-height: 22px; } .course-price .count{ font-size: 24px; color: #fa6240; } .course-price .old_count{ font-size: 14px; color: #9b9b9b; text-decoration: line-through; margin-left: 10px; } .course-price .buy{ float: right; width: 120px; height: 38px; font-size: 16px; border-radius: 3px; border: 1px solid #fd7b4d; background: transparent;/* 透明 */ color: #fa6240; cursor: pointer; transition: all .2s ease-in-out;/* css3新版本的样式中支持支持 jQuery里面的动画预设效果 */ /* all表示当前元素的所有样式 .2s表示改变样式完成的时间 ease-in-out */ } .course-price .buy:hover{ color: #fff; background: #ffc210; border: 1px solid #ffc210; } </style>
上面是写死的模板,我们需要在后端开接口获取动态数据
import Courses from "../components/Courses" .... { name:"Courses", path: "/courses", component: Courses, }
课程分类:
课程表:
课程章节:
老师表:
价格服务表:(限时免费\限时折扣\限时满减)
python ../../manage.py startapp courses
INSTALLED_APPS = [ ... 'courses', ]
from django.db import models # Create your models here. class CourseCategory(models.Model): """ 课程分类 """ name = models.CharField(max_length=64, unique=True, verbose_name="分类名称") orders = models.IntegerField(verbose_name='显示顺序') is_show = models.BooleanField(default=True, verbose_name="是否上线") is_delete = models.BooleanField(default=False, verbose_name="逻辑删除") class Meta: db_table = "ly_course_category" verbose_name = "课程分类" verbose_name_plural = "课程分类" def __str__(self): return "%s" % self.name class Course(models.Model): """ 专题课程 """ course_type = ( (0, '付费'), (1, 'VIP专享'), (2, '学位课程') ) level_choices = ( (0, '初级'), (1, '中级'), (2, '高级') ) status_choices = ( (0, '上线'), (1, '下线'), (2, '预上线') ) name = models.CharField(max_length=128, verbose_name="课程名称") course_img = models.ImageField(max_length=255, verbose_name="封面图片", blank=True, null=True) course_type = models.SmallIntegerField(choices=course_type, verbose_name="付费类型") # 使用这个字段的原因 brief = models.TextField(max_length=2048, verbose_name="课程概述", null=True, blank=True) level = models.SmallIntegerField(choices=level_choices, default=1, verbose_name="难度等级划分") pub_date = models.DateField(verbose_name="发布日期", auto_now_add=True) period = models.IntegerField(verbose_name="建议学习周期(day)", default=7) orders = models.IntegerField(verbose_name="课程排序") attachment_path = models.FileField(max_length=128, verbose_name="课件路径", blank=True, null=True) status = models.SmallIntegerField(choices=status_choices, default=0, verbose_name="课程状态") course_category = models.ForeignKey("CourseCategory", on_delete=models.CASCADE, null=True, blank=True,verbose_name="课程分类") students = models.IntegerField(verbose_name="学习人数",default = 0) lessons = models.IntegerField(verbose_name="总课时数量",default = 0) pub_lessons = models.IntegerField(verbose_name="课时更新数量",default = 0) price = models.DecimalField(max_digits=6,decimal_places=2, verbose_name="课程原价",default=0) teacher = models.ForeignKey("Teacher",on_delete=models.DO_NOTHING, null=True, blank=True,verbose_name="授课老师") class Meta: db_table = "ly_course" verbose_name = "专题课程" verbose_name_plural = "专题课程" def __str__(self): return "%s" % self.name class Teacher(models.Model): """讲师、导师表""" role_choices = ( (0, '讲师'), (1, '导师'), ) name = models.CharField(max_length=32, verbose_name="讲师title") role = models.SmallIntegerField(choices=role_choices, default=0, verbose_name="讲师身份") title = models.CharField(max_length=64, verbose_name="职位、职称") signature = models.CharField(max_length=255, help_text="导师签名", blank=True, null=True) image = models.CharField(max_length=128,verbose_name = "讲师封面") brief = models.TextField(max_length=1024, verbose_name="讲师描述") class Meta: db_table = "ly_teacher" verbose_name = "讲师导师" verbose_name_plural = "讲师导师" def __str__(self): return "%s" % self.name class CourseChapter(models.Model): """课程章节""" course = models.ForeignKey("Course", related_name='coursechapters', on_delete=models.CASCADE, verbose_name="课程名称") chapter = models.SmallIntegerField(verbose_name="第几章", default=1) name = models.CharField(max_length=128, verbose_name="章节标题") summary = models.TextField(verbose_name="章节介绍", blank=True, null=True) pub_date = models.DateField(verbose_name="发布日期", auto_now_add=True) class Meta: db_table = "ly_course_chapter" verbose_name = "课程章节" verbose_name_plural = "课程章节" def __str__(self): return "%s:(第%s章)%s" % (self.course, self.chapter, self.name) class CourseLesson(models.Model): """课程课时""" section_type_choices = ( (0, '文档'), (1, '练习'), (2, '视频') ) chapter = models.ForeignKey("CourseChapter", related_name='coursesections', on_delete=models.CASCADE,verbose_name="课程章节") name = models.CharField(max_length=128,verbose_name = "课时标题") orders = models.PositiveSmallIntegerField(verbose_name="课时排序") section_type = models.SmallIntegerField(default=2, choices=section_type_choices, verbose_name="课时种类") section_link = models.CharField(max_length=255, blank=True, null=True, verbose_name="课时链接", help_text = "若是video,填vid,若是文档,填link") duration = models.CharField(verbose_name="视频时长", blank=True, null=True, max_length=32) # 仅在前端展示使用 pub_date = models.DateTimeField(verbose_name="发布时间", auto_now_add=True) free_trail = models.BooleanField(verbose_name="是否可试看", default=False) class Meta: db_table = "ly_course_lesson" verbose_name = "课程课时" verbose_name_plural = "课程课时" def __str__(self): return "%s-%s" % (self.chapter, self.name)
python manage.py makemigrations
python manage.py migrate
把当前新增的模型注册到xadmin里面.
coursers/adminx.py,代码:
import xadmin from .models import CourseCategory class CourseCategoryModelAdmin(object): """课程分类模型管理类""" pass xadmin.site.register(CourseCategory, CourseCategoryModelAdmin) from .models import Course class CourseModelAdmin(object): """课程模型管理类""" pass xadmin.site.register(Course, CourseModelAdmin) from .models import Teacher class TeacherModelAdmin(object): """老师模型管理类""" pass xadmin.site.register(Teacher, TeacherModelAdmin) from .models import CourseChapter class CourseChapterModelAdmin(object): """课程章节模型管理类""" pass xadmin.site.register(CourseChapter, CourseChapterModelAdmin) from .models import CourseLesson class CourseLessonModelAdmin(object): """课程课时模型管理类""" pass xadmin.site.register(CourseLesson, CourseLessonModelAdmin)
courses/serializers.py
from rest_framework import serializers from .models import CourseCategory class CourseCategoryModelSerializer(serializers.ModelSerializer): class Meta: model = CourseCategory fields = ("id","name")
courses/views.py
# Create your views here. from rest_framework.generics import ListAPIView from .models import CourseCategory from .serializers import CourseCategoryModelSerializer class CourseCategoryAPIView(ListAPIView): """课程分类列表""" queryset = CourseCategory.objects.filter( is_delete=False, is_show=True ).order_by("-orders") serializer_class = CourseCategoryModelSerializer
from django.urls import path from . import views urlpatterns = [ path(r"cate/",views.CourseCategoryAPIView.as_view()), ] # 总路由 path('course/', include("courses.urls")),
# 开发中一个序列化器 A 中需要同时序列化其他模型 B 的数据返回给客户端,那么直接通过外键默认只会返回主键ID # 所以我们可以通过再创建一个模型B的序列化器,对模型B的数据进行序列化 # 在序列化器A中直接把模型B的序列化器调用作为字段值来声明即可. from .models import Teacher class TeacherSerializer(serializers.ModelSerializer): class Meta: model = Teacher fields = ("id","name","title") from .models import Course class CourseSerializer(serializers.ModelSerializer): # 这里调用的序列化器,必须事先在前面已经声明好的,否则报错 teacher = TeacherSerializer() class Meta: model= Course fields = ("id","name","course_img","students","lessons","pub_lessons","price","teacher")
视图代码:
from .models import Course from .serializers import CourseSerializer class CourseAPIView(ListAPIView): queryset = Course.objects.filter(status=0).order_by("-orders","-id") serializer_class = CourseSerializer
from .models import CourseLesson class CourseLessonModelSerializer(serializers.ModelSerializer): class Meta: model = CourseLesson fields = ("id","name","free_trail") from .models import CourseChapter class CourseChapterModelSerializer(serializers.ModelSerializer): coursesections = CourseLessonModelSerializer(many=True) class Meta: model = CourseChapter fields = ("id", "name", "coursesections") from .models import Course class CourseModelSerializer(serializers.ModelSerializer): teacher = TeacherModelSerializer() coursechapters = CourseChapterModelSerializer(many=True) # 课程章节多个,所以需要声明 many=True class Meta: model = Course fields = ("id", "name", "course_img", "students", "lessons", "pub_lessons", "price", "teacher","coursechapters")
pip install django-filter
在settings/dev.py配置文件中增加过滤后端的设置:
INSTALLED_APPS = [ ... 'django_filters', # 需要注册应用, ]
from django_filters.rest_framework import DjangoFilterBackend class CourseAPIView(ListAPIView): queryset = Course.objects.filter(status=0).order_by("-orders","-id") serializer_class = CourseModelSerializer # 设置按课程分类过滤课程信息 filter_backends = [DjangoFilterBackend,] filter_fields = ('course_category',)
后端提供排序课程的接口
from .models import Course from .serializers import CourseModelSerializer from rest_framework.filters import OrderingFilter from django_filters.rest_framework import DjangoFilterBackend class CourseAPIView(ListAPIView): queryset = Course.objects.filter(status=0).order_by("-orders","-id") serializer_class = CourseModelSerializer # 设置价格排序 filter_backends = [DjangoFilterBackend,OrderingFilter] filter_fields = ('course_category',) ordering_fields = ('id', 'students', 'price')
组件vue代码
<template> <div class="course"> <Header/> <div class="main"> <!-- 筛选功能 --> <div class="top"> <ul class="condition condition1"> <li class="cate-condition">课程分类:</li> <li class="item" :class="query_params.course_category===0?'current':''" @click="query_params.course_category=0">全部 </li> <li :class="query_params.course_category===catetory.id?'current':''" @click="query_params.course_category=catetory.id" v-for="catetory in catetory_list" :data-key="catetory.id" class="item">{{catetory.name}} </li> </ul> <ul class="condition condition2"> <li class="cate-condition">筛 选:</li> <li class="item" :class="(query_params.ordering==='-id' || query_params.ordering==='id')?'current':''" @click="select_ordering('id')">默认 </li> <li class="item" :class="(query_params.ordering==='-students' || query_params.ordering==='students')?'current':''" @click="select_ordering('students')">人气 </li> <li class="item" :class="query_params.ordering==='price'?'current price':(query_params.ordering==='-price'?'current price2':'')" @click="select_ordering('price')">价格 </li> <li class="course-length">共21个课程</li> </ul> </div> <!-- 课程列表 ---> <div class="list"> <ul> <li class="course-item" v-for="course in course_list"> <router-link :to="{path: '/detail',query:{id:course.id}}" class="course-link"> <div class="course-cover"> <img :src="course.course_img" alt=""> </div> <div class="course-info"> <div class="course-title"> <h3>{{course.name}}</h3> <span>{{course.students}}人已加入学习</span> </div> <p class="teacher"> <span class="info">{{course.teacher.name}} {{course.teacher.title}}</span> <span class="lesson">共{{course.lessons}}课时/{{course.lessons===course.pub_lessons?'更新完成':('已更新'+course.pub_lessons+"课时")}}</span> </p> <ul class="lesson-list"> <li v-for="lesson,key in course.lesson_list"> <p class="lesson-title">0{{key+1}} | {{lesson.name}}</p> <span v-if="lesson.free_trail" class="free">免费</span> </li> </ul> <div class="buy-info"> <span class="discount">限时免费</span> <span class="present-price">¥0.00元</span> <span class="original-price">原价:{{course.price}}元</span> <button class="buy-now">立即购买</button> </div> </div> </router-link> </li> </ul> </div> <div class="pagination"> <el-pagination @current-change="handleCurrentChange" :current-page="query_params.current_page" background layout="prev, pager, next" :page-size="course_page_size" :total="course_count"> </el-pagination> </div> </div> <Footer/> </div> </template> <script> import Header from "./common/Header" import Footer from "./common/Footer" export default { name: "Course", data() { return { catetory_list: [], course_list: [], course_count: 0, course_page_size: 1, query_params: { course_category: 0, ordering: "-id", current_page: 1, } } }, watch: { // 每次点击不同课程时,要重新获取课程列表 "query_params.course_category": function () { this.get_course_list(); // 当切换分类的时候,重置页码 this.query_params.current_page = 1; }, "query_params.ordering": function () { // 当切换排序条件的时候,重置页码 // this.query_params.current_page = 1; this.get_course_list(); }, "query_params.current_page": function () { this.get_course_list(); } }, components: {Header, Footer}, created() { // 获取课程分类 this.$axios.get(this.$settings.Host + "/courses/cate/").then(response => { this.catetory_list = response.data }).catch(error => { console.log(error.response) }); // 获取课程信息 this.get_course_list() }, methods: { select_ordering(selector) { // 默认排序 if (this.query_params.ordering === ('-' + selector)) { this.query_params.ordering = selector; } else { this.query_params.ordering = '-' + selector; } }, get_course_list() { let query_params = { ordering: this.query_params.ordering, page: this.query_params.current_page, }; if (this.query_params.course_category !== 0) { query_params.course_category = this.query_params.course_category; } this.$axios.get(this.$settings.Host + "/courses/list/", { params: query_params }).then(response => { // 课程列表 this.course_list = response.data.results; // 课程总数量 this.course_count = response.data.count; }).catch(error => { console.log(error.response) }); }, handleCurrentChange(page) { // 页码发生改变 this.query_params.current_page = page; } } } </script> <style scoped> .main { width: 1100px; height: auto; margin: 0 auto; padding-top: 35px; } .main .top { margin-bottom: 35px; padding: 25px 30px 25px 20px; background: #fff; border-radius: 4px; box-shadow: 0 2px 4px 0 #f0f0f0; } .condition { border-bottom: 1px solid #333; border-bottom-color: rgba(51, 51, 51, .05); padding-bottom: 18px; margin-bottom: 17px; overflow: hidden; } .condition li { float: left; } .condition .cate-condition { color: #888; font-size: 16px; } .condition .item { padding: 6px 16px; line-height: 16px; margin-left: 14px; position: relative; transition: all .3s ease; border: 1px solid transparent; /* transparent 透明 */ cursor: pointer; color: #4a4a4a; } .condition1 .current { color: #ffc210; border: 1px solid #ffc210 !important; border-radius: 30px; } .condition2 .current { color: #ffc210; } .condition .price:before { content: ""; width: 0; border: 5px solid transparent; border-top-color: #d8d8d8; position: absolute; right: 0; bottom: 2.5px; } .condition .price2:before { content: ""; width: 0; border: 5px solid transparent; position: absolute; right: 0; bottom: 2.5px; border-top-color: #ffc210; } .condition .price2:after { content: ""; width: 0; border: 5px solid transparent; position: absolute; right: 0; top: 2.5px; border-bottom-color: #d8d8d8; } .condition .price:after { content: ""; width: 0; border: 5px solid transparent; border-bottom-color: #ffc210; position: absolute; right: 0; top: 2.5px; } .condition2 .course-length { float: right; font-size: 14px; color: #9b9b9b; } .course-item { background: #fff; padding: 20px 30px 20px 20px; margin-bottom: 35px; border-radius: 2px; cursor: pointer; box-shadow: 2px 3px 16px rgba(0, 0, 0, .1); transition: all .2s ease; overflow: hidden; cursor: pointer; } .course-link { overflow: hidden; } .course-cover { width: 423px; height: 210px; margin-right: 30px; float: left; } .course-info { width: 597px; float: left; } .course-title { margin-bottom: 8px; overflow: hidden; } .course-title h3 { font-size: 26px; color: #333; float: left; } .course-title span { float: right; font-size: 14px; color: #9b9b9b; margin-top: 12px; text-indent: 1em; /* 缩进 2字符宽度 */ background: url("../assets/people.svg") no-repeat 0px 3px; } .teacher { justify-content: space-between; font-size: 14px; color: #9b9b9b; margin-bottom: 14px; padding-bottom: 14px; border-bottom: 1px solid #333; border-bottom-color: rgba(51, 51, 51, .05); } .teacher .lesson { float: right; } .lesson-list { overflow: hidden; } .lesson-list li { width: 49%; margin-bottom: 15px; cursor: pointer; float: left; margin-right: 1%; } .lesson-list li .player { width: 16px; height: 16px; vertical-align: text-bottom; } .lesson-list li .lesson-title { display: inline-block; max-width: 227px; text-overflow: ellipsis; /* 如果字体太多超出元素的宽度,则添加省略符号 */ color: #666; overflow: hidden; white-space: nowrap; font-size: 14px; vertical-align: text-bottom; /* 文本的垂直对齐方式: text-botton 文本底部对齐 */ text-indent: 1.5em; background: url(../../static/player.svg) no-repeat 0px 3px; } .lesson-list .free { width: 34px; height: 20px; color: #fd7b4d; margin-left: 10px; border: 1px solid #fd7b4d; border-radius: 2px; text-align: center; font-size: 13px; white-space: nowrap; } .lesson-list li:hover .lesson-title { color: #ffc210; background-image: url(../../static/player2.svg); } .lesson-list li:hover .free { border-color: #ffc210; color: #ffc210; } .buy-info .discount { padding: 0px 10px; font-size: 16px; color: #fff; display: inline-block; height: 36px; text-align: center; margin-right: 8px; background: #fa6240; border: 1px solid #fa6240; border-radius: 10px 0 10px 0; line-height: 36px; } .present-price { font-size: 24px; color: #fa6240; } .original-price { text-decoration: line-through; font-size: 14px; color: #9b9b9b; margin-left: 10px; } .buy-now { width: 120px; height: 38px; background: transparent; color: #fa6240; font-size: 16px; border: 1px solid #fd7b4d; border-radius: 3px; transition: all .2s ease-in-out; /* 过渡动画 */ float: right; margin-top: 5px; } .buy-now:hover { color: #fff; background: #ffc210; border: 1px solid #ffc210; cursor: pointer; } .pagination { text-align: center; margin: 20px 0px 50px 0px; } </style>