day82:luffy:课程详情页面显示&章节和课时显示&视频播放组件&CKEditor富文本编辑器

day82:luffy:课程详情页面显示&章节和课时显示&视频播放组件&CKEditor富文本编辑器,第1张

概述目录 1.初始课程详情页面 2.视频播放组件 3.课程详情页面后端接口实现 4.课程详情页面-前端 5.CKEditor富文本编辑器 6.课程章节和课时显示-后端接口 7.课程章节和课时显示-前端 1 目录

1.初始课程详情页面

2.视频播放组件

3.课程详情页面后端接口实现

4.课程详情页面-前端

5.CKEditor富文本编辑器

6.课程章节和课时显示-后端接口

7.课程章节和课时显示-前端

1.初始课程详情页面1.Detail.vue

@H_403_29@<!-- 课程详情页面初始页面 --><template>    div class="detail">      Vheader/>      ="main">        ="course-info">          ="wrap-left">          </div="wrap-right">            h3 ="course-name">flaskh3p ="data">111人在学&nbsp;&nbsp;&nbsp;&nbsp;课程总时长:111课时/12小时&nbsp;&nbsp;&nbsp;&nbsp;难度:p="sale-time">              ="sale-type">限时免费="expire">距离结束:仅剩 01天 04小时 33分 span ="second">08span>="course-price">活动价="discount">¥0.00="original">¥1111="buy"="buy-btn">                button ="buy-Now">立即购买button="free">免费试学="add-cart"><img src="/static/img/cart-yellow.svg" alt="">加入购物车="course-tab"ul ="tab-List"li :class="tabIndex==1?'active':''" @click="tabIndex=1">详情介绍li="tabIndex==2?'active':''"="tabIndex=2">课程章节 ="tabIndex!=2?'free':''">(试学)></="tabIndex==3?'active':''"="tabIndex=3">用户评论 (42)="tabIndex==4?'active':''"="tabIndex=4">常见问题ul="course-content"="course-tab-List"="tab-item" v-if="tabIndex==1"="course-brIEf" v-HTML="tabIndex==2"="tab-item-Title"="chapter">课程章节="chapter-length">共11章 147个课时="chapter-item"="chapter-Title"="/static/img/1.png">第1章·linux硬件基础="lesson-List">                  ="lesson-item">                    ="name"="index">1-1> 课程介绍-学习流程>免费="time">07:30 ="/static/img/chapter-player.svg"="try">立即试学>1-2> 服务器硬件-详解>第2章·linux发展过程>2-1>  *** 作系统组成-linux发展过程>2-2> 自由软件-GNU-GPL核心讲解="tabIndex==3">              用户评论            ="tabIndex==4"              常见问题            ="course-sIDe">             ="teacher-info">               h4 ="sIDe-Title">授课老师h4="teacher-content">                 ="cont1">                   >                     ="teacher-name">xxx="teacher-Title">ssss="narrative" >kkkkFooter/>    >>script>import Vheader from "./common/Vheaderimport Footer from ./common/Footerexport default {    name: Detail,data(){      return {        tabIndex:1style scoped.main{  background: #fff;  padding-top 30px;}.course-info  wIDth 1200px  margin 0 auto  overflow hIDden.wrap-left  float left 690px  height 388px  background-color #000.wrap-right  position relative.course-name  Font-size 20px  color #333  padding 10px 23px  letter-spacing .45px.data  padding-left 23px  padding-right  padding-bottom 16px 14px #9b9b9b.sale-time 464px #fa6240 #4a4a4a.sale-type  .36px.sale-time .expire right.sale-time .expire .second 24px  display inline-block #fafafa #5e5e5e 6px 0  text-align center.course-price 5px 23px.discount 26px  margin-left 10px  margin-bottom -5px.original  text-decoration line-through.buy 0px 23px absolute  left 0  bottom.buy .buy-btn.buy .buy-Now 125px 40px  border #ffc210  border-radius 4px  cursor pointer  margin-right 15px  outline none.buy .free 1px solID #ffc210.add-cart  margin-top.add-cart img 18px 7px  vertical-align mIDdle.course-tab    wIDth 100%    background    margin-bottom    Box-shadow 0 2px 4px 0 #f0f0f0;.course-tab .tab-List    margin auto    color    overflow.tab-List li    float    margin-right    padding 26px 20px 16px    Font-size 17px    cursor.tab-List .active    border-bottom 2px solID #ffc210.tab-List .free #fb7c55.course-content #FAFAFA    padding-bottom.course-tab-List 880px    height    Box-sizing border-Box    position.tab-item.tab-item-Title    justify-content space-between 25px 20px 11px    border-radius 1px solID #333    border-bottom-color rgba(51,51,.05).chapter.chapter-length    letter-spacing .19px.chapter-Title .26px 12px #eee 2px    display -ms-flexBox flex    -ms-flex-align    align-items.chapter-Title img    vertical-align.lesson-List0 20px.lesson-List .lesson-item 15px 20px 15px 36px.lesson-item .name #666.lesson-item .index 5px.lesson-item .free 100px 1px 9px    margin-left.lesson-item .time .23px    opacity 1    Transition all .15s ease-in-out.lesson-item .time img text-bottom.lesson-item .try 86px 28px    right    top all .2s ease-in-out    outline    border.lesson-item:hover #fcf7ef 0 0 0 0 #f3f3f3.lesson-item:hover .name.lesson-item:hover .try.course-sIDe 300px.teacher-info.sIDe-Title    Font-weight normal 18px 14px.sIDe-Title span    border-left    padding-left.teacher-content 30px 20px.teacher-content .cont1.teacher-content .cont1 img 54px.teacher-content .cont1 .name.teacher-content .cont1 .teacher-name 188px.teacher-content .cont1 .teacher-Title 13px    white-space nowrap.teacher-content .narrative    line-height}style>
初始课程详情页面2.index.Js注册组件
import Detail from "@/components/Detail"{    path:'/course/detail/:ID',// 前端页面动态路由匹配    component:Detail  } :ID ===> this.$route.params.ID  // course/detail/1
3.course.vue

实现:在课程列表页面点击不同的课程可以进入到不同的课程详情页面

router-link :to="'/course/detail/'+course.ID+'/'">django基础知识router-link> ="/static/img/avatar1.svg">5000人已加入学习>           

此时 点击可进入课程详情页面

2.视频播放组件1.安装
npm install vue-vIDeo-player --save
2.main.Js注册组件
 main.Jsrequire('vIDeo.Js/dist/vIDeo-Js.CSS');require('vue-vIDeo-player/src/custom-theme.CSS');import VIDeoPlayer from 'vue-vIDeo-player'Vue.use(VIDeoPlayer);
3.Detail.vue引入HTML部分
 HTML >     vIDeoPlayer ="vIDeo-player vJs-custom-skin"                  ref="vIDeoPlayer"                  :playsinline="true"                  :options="playerOptions"                  @play="onPlayerPlay($event)"                   @pause="onPlayerPause($event)">     vIDeoPlayer>
Js部分
 Jsimport {VIDeoPlayer} from 'vue-vIDeo-player'data(){    return{        ...         playerOptions: {              playbackRates: [0.7,1.0,1.5,2.0],1)"> 播放速度              autoplay: false,1)"> 如果true,则自动播放              muted:  默认情况下将会消除任何音频。              loop:  循环播放              preload: 'auto',1)"> 建议浏览器在<vIDeo>加载元素后是否应该开始下载视频数据。auto浏览器选择最佳行为,立即开始加载视频(如果浏览器支持)              language: 'zh-CN' 将播放器置于流畅模式,并在计算播放器的动态大小时使用该值。值应该代表一个比例 - 用冒号分隔的两个数字(例如"16:9"或"4:3")              fluID: true,1)"> 当true时,VIDeo.Js player将拥有流体大小。换句话说,它将按比例缩放以适应其容器。              sources: [{  播放资源和资源格式                type: "vIDeo/mp4" 你的视频地址(必填)              }],poster: "",1)"> 视频封面图              wIDth: document.documentElement.clIEntWIDth,1)"> 默认视频全屏时的最大宽度              notSupportedMessage: '此视频暂无法播放,请稍后再试',1)"> 允许覆盖VIDeo.Js无法播放媒体源时显示的默认信息。        }            }        }        method:{        ...         视频播放时触发此函数        onPlayerPlay:{            ...        }         视频暂停时触发此函数        onPlayerPause:{            ...        }    }components:{    ...    vIDeoplayer  挂载一下视频播放组件}
4.在Xadmin上传视频

注意:课程详情页的那些视频其实要存到数据库里的,但是数据库并没有课程视频这个字段

所以需要在course表中添加一个course_vIDeo字段

# 将上传的视频保存在本地的vIDeo文件夹中course_vIDeo = models.fileFIEld(upload_to='vIDeo',verbose_name=封面视频python3 manage.py makemigrationspython3 manage.py migrate

在xadmin上传视频,即可在前端页面看到自己上传的视频

3.课程详情页面后端接口实现

接下来做的事情:在课程表里已经有了我们视频数据了,现在我们要想办法写一个后端接口将真实的课程详情数据返回到页面上,把真实的视频播放路径给前端,让前端展示出来。把真实的图片路径或者视频路径给前端,前端加载的时候会往后端发请求获取地址对应的视频数据,然后进行播放就可以了

urls.py
urlpatterns = [    ......    re_path(rdetail/(?P<pk>\d+)/' CourseDetailVIEw(RetrIEveAPIVIEw):    queryset = models.Course.objects.filter(is_deleted=False,is_show=True)    serializer_class = CourseDetailModelSerializer
models.py
 Course(BaseModel):    ......    level_choices = (        (0,初级),(1,中级高级"难度等级")        ......        def level_name(self):        '''level字段默认显示的是数字,通过返回get_字段_display可以返回数字对应的名字'''        return self.get_level_display()
serializers.py
 CourseDetailModelSerializer(serializers.ModelSerializer):     序列化器嵌套    teacher = TeacherModelSerializer()   将外键关联的属性指定为关联表的序列化器对象,就能拿到关联表序列化出来的所有数据,还需要在fIElds中指定一下,注意,名称必须和外键属性名称相同     Meta:        model = models.Course        fIElds = [ID",1)">namecourse_imgstudentslessonspub_lessonspriceteacherlevel_namecourse_vIDeo]                 
后端接口测试

drf后端接口测试 /course/detail/1 可得到course=1所需要的所有数据

 

4.课程详情页面-前端1.注意点

在课程列表页面,我们只展示了四个课时。但是在课程详情页我们要展示所有课时,所以不能用之前那个序列化器了。

现在我们是需要所有章节和所有课时信息、老师信息和课程信息。

如果将所有的信息都定义到一个序列化器的字段中,数据量有些太大。

我们可以利用axios可以发送异步请求的这个特点,分成两次请求来获取数据

将章节信息和课时信息放在一个序列化器中

其它的放在另一个序列化器中

我们先去请求除了章节信息和课时信息的其他信息

现在后端数据已经准备好了,接下来就是前端发送axios请求获取数据了

2.Detail.vue

--> >{{ course_data.name }}>{{course_data.students}}人在学&nbsp;&nbsp;&nbsp;&nbsp;课程总时长:{{course_data.lessons}}&nbsp;&nbsp;&nbsp;&nbsp;难度:{{course_data.level_name}}>¥{{course_data.price}}> 老师部分 >{{course_data.teacher.name}}>{{course_data.teacher.Title}}>{{course_data.teacher.signature}} 视频播放                  ref                 :playsinline                 :options                 @play                 @pause>
前端将从后段获取的数据展示出来-HTML

 Js<script>export default {    name: "Detail" {       ......        course_ID:0 播放资源和资源格式            type: "vIDeo/mp4"          }],1)"> 视频封面图          ......    },created(){      this.get_course_ID();      .get_course_data();    },methods: {           获取课程ID,用处是请求不同的课程详情页面数据时带上不同的url参数来请求不同的课程详情数据      get_course_ID(){        this.course_ID = .$route.params.ID;         可以判断course_ID的合法性 todo      },get_course_data(){        this.$axios.get(`${this.$settings.Host}/course/detail/${this.course_ID}/`)        .then((res)=>{          this.course_data = res.data;  获取课程详情页数据          this.playerOptions.sources[0].src = res.data.course_vIDeo;  获取视频数据          this.playerOptions.poster = res.data.course_img  获取视频封面数据        })      },},}</script>
前端发送axios请求获取后端数据-Js5.CKEditor富文本编辑器1.安装
pip install django-ckeditor
2.settings/dev.py INSTALLAPP配置
INSTALLED_APPS = [    ...    ckeditor 富文本编辑器    ckeditor_uploader 富文本编辑器上传图片模块    ...]
3.setting/dev.py 配置
 富文本编辑器ckeditor配置CKEDITOR_CONfigS = {    default: {        toolbar': full 工具条功能,full表示全部,Basic表示基本功能,功能少很多,还有个Custom自定义功能选项        height': 300,1)"> 编辑器高度         'wIDth': 300,# 编辑器宽    },}CKEDITOR_UPLOAD_PATH = ''   上传图片保存路径,留空则调用django的文件上传功能 也可以自定义配置CKEDITOR_CONfigS =Customtoolbar_Custom: [            [BoldItalicUnderlineImage'],1)"> 通过浏览器f12来查看每个功能的标签,就看到了类值cke_button_工具名称[注意使用驼峰式来写]            [NumberedListBulletedList-OutdentIndentJustifyleftJustifyCenterJustifyRightJustifyBlock],[linkUnlinkRemoveFormatSource]        ]    }}
4.在总路由lyAPI/urls.py添加路由
path(r^ckeditor/ckeditor_uploader.urls')),
5.将brIEf字段升级
 course/models.pyfrom ckeditor_uploader.fIElds import RichTextUploadingFIEld Course(models.Model):         课程概述变为富文本编辑器显示    brIEf = RichTextUploadingFIEld(max_length=2048,1)">课程概述True)    
6.brIEf图片路径转化问题

相对路径转化为绝对路径

在brIEf中,存放的都是一些各种标签组成的字符串,而用户在使用富文本编辑器时,有可能会使用上传图片的功能。而图片上传后,默认都存在了后端的media文件夹中。但是前端并不会将我们的后端地址识别出来。它会默认被存放到前端:www.lycity.com/media中,所以需要我们手动更改一下上传图片存储的路径。这样用户上传的图片才能显示出来。

models.py
# course/models.py Course:    ...     new_brIEf(self):        data = self.brIEf        server_addr = contains.SERVER_ADDR        data = data.replace(/media{server_addr}/media)         data        
settings/constants.py
SERVER_ADDR = http://www.lyAPI.com:8001'
serializers.py
 CourseDetailModelSerializer:    ...    teacher = TeacherModelSerializer()     model.Course        fIElds = [.........,teacher,level_name,new_brIEf]  将new_brIEf添加到字段中                
7.表情和图片应用不同的CSS样式
 contains.SERVER_ADDR                做了两件事:        1.将用户上传图片的相对路径改成了绝对路径        2.让图片和表情应用不同的CSS样式        '''        data = data.replace(src="/media src="{server_addr}/mediareturn data
6.课程章节和课时显示-后端接口urls.py
re_path(rchapter/from django_filters.rest_framework  DjangoFilterBackend ChapterVIEw(ListAPIVIEw):    queryset = models.CourseChapter.objects.filter(is_deleted=False,1)">True)    serializer_class = CourseChapterModelSerializer    filter_backends = [DjangoFilterBackend,]    filter_fIElds = (course CourseLessonModelSerializer:     models.CourseLesson        fIElds = [section_linkdurationfree_traillesson] CourseChapterModelSerialzer:        在一的序列化器嵌套多的序列化器,切记要加参数many=True    coursesection = CourseLessonModelSerializer(many=True)  1201         models.CourseChapter        fIElds = [chapter]        

drf测试接口:course/chapter/?course=1

7.课程章节和课时显示-前端

>共{{chapter_data.length}}章 ="chapter-item" v-for="(chapter,chapterindex) in chapter_data">第{{chapter.chapter}}章·{{chapter.name}}="lesson-item"="(lesson,lesson_index) in chapter.coursesections">{{chapter.chapter}}-{{lesson.lesson}}> 课程介绍-{{lesson.name}}v-show="lesson.free_trail" class>{{lesson.duration}} ="try"="lesson.free_trail" v-else>立即buy>                >
课程章节和课时显示-HTML

 Jsexport  {                chapter_data:{},}    },created(){        .get_chapter_data();    },methods: {                 get_chapter_data(){        this.$settings.Host}/course/chapter/`,{          params:{            course:.course_ID,}        }).then((res)=>{          console.log(res.data);          this.chapter_data = res.data        })      },}
课程章节和课时显示-Js

 

总结

以上是内存溢出为你收集整理的day82:luffy:课程详情页面显示&章节和课时显示&视频播放组件&CKEditor富文本编辑器全部内容,希望文章能够帮你解决day82:luffy:课程详情页面显示&章节和课时显示&视频播放组件&CKEditor富文本编辑器所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/langs/1190086.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-03
下一篇 2022-06-03

发表评论

登录后才能评论

评论列表(0条)

保存