day14【首页课程和名师功能】-02 首页课程功能

01-课程页面静态效果整合

一、列表页面

创建 pages/course/index.vue

二、详情页面

创建 pages/course/_id.vue



02-课程列表页面

一、课程后端接口

1、课程列表

(1)课程列表vo类(条件查询需要的对象)

@ApiModel(value = "课程查询对象", description = "课程查询对象封装")

@Data

public class CourseFrontVo {

    @ApiModelProperty(value = "课程名称")

    private String title;

    @ApiModelProperty(value = "讲师id")

    private String teacherId;

    @ApiModelProperty(value = "一级类别id")

    private String subjectParentId;

    @ApiModelProperty(value = "二级类别id")

    private String subjectId;

    @ApiModelProperty(value = "销量排序")

    private String buyCountSort;

    @ApiModelProperty(value = "最新时间排序")

    private String gmtCreateSort;

    @ApiModelProperty(value = "价格排序")

    private String priceSort;

}

(2)课程列表controller

@RestController

@CrossOrigin

@RequestMapping("/eduservice/coursefront")

public class CourseFrontController {

    @Autowired

    private EduCourseService courseService;

    //1 条件查询带分页查询课程

    @ApiOperation(value = "分页课程列表")

    @PostMapping("pageCourseCondition/{current}/{limit}")

    public R pageCourseCondition(@PathVariable long limit,

                                @PathVariable long current,

                                @RequestBody(required = false) CourseFrontVo courseFrontVo){

        //@RequestBody(required = false)使用RequestBody必须是post提交,不添加required = false必须要有值,添加后表示可以没有值

        Page pageParam = new Page(current,limit);

        Map map = courseService.pageListWeb(pageParam, courseFrontVo);

        return R.ok().data(map);

    }

}

//@RequestBody(required = false)使用RequestBody必须是post提交,不添加required = false必须要有值,添加后可以没有值

(3)课程列表service

//1 条件查询带分页查询课程

    @Override

    public Map pageListWeb(Page pageParam, CourseFrontVo courseFrontVo) {

        QueryWrapper queryWrapper = new QueryWrapper<>();

        //判断条件值是否为空,不为空拼接

        if (!StringUtils.isEmpty(courseFrontVo.getSubjectParentId())){//一级分类

            queryWrapper.eq("subject_parent_id",courseFrontVo.getSubjectParentId());

        }

        if (!StringUtils.isEmpty(courseFrontVo.getSubjectId())){//二级分类

            queryWrapper.eq("subject_id",courseFrontVo.getSubjectId());

        }

        if (!StringUtils.isEmpty(courseFrontVo.getBuyCountSort())){//销售数量

            queryWrapper.orderByDesc("buy_count",courseFrontVo.getBuyCountSort());

        }

        if (!StringUtils.isEmpty(courseFrontVo.getGmtCreateSort())){//创建时间

            queryWrapper.orderByDesc("gmt_create",courseFrontVo.getGmtCreateSort());

        }

        if (!StringUtils.isEmpty(courseFrontVo.getPriceSort())){//价格

            queryWrapper.orderByDesc("price",courseFrontVo.getPriceSort());

        }

        baseMapper.selectPage(pageParam, queryWrapper);


        List records = pageParam.getRecords();

        long pages = pageParam.getPages();

        long current = pageParam.getCurrent();

        long total = pageParam.getTotal();

        long size = pageParam.getSize();

        boolean hasNext = pageParam.hasNext(); //下一页

        boolean hasPrevious = pageParam.hasPrevious(); //上一页


        Map map = new HashMap();

        map.put("items",records);

        map.put("current", current);

        map.put("pages", pages);

        map.put("size", size);

        map.put("total", total);

        map.put("hasNext", hasNext);

        map.put("hasPrevious", hasPrevious);

        return map;

    }

二、课程列表前端

1、定义api

api/course.js

import request from '@/utils/request'

export default {

  //1 条件查询带分页查询课程

  getCourseList(current,limit,searchObj) {

    return request({

      url: `/eduservice/coursefront/pageCourseCondition/${current}/${limit}`,

      method: 'post',

      data:searchObj

    })

  },

  //查询所有分类的方法

  getAllSubject(){

    return request({

        url: `/eduservice/edu-subject/getAllSubject`,

        method: 'get'

      })

  }

}

2、页面调用接口

pages/course/index.vue

完善当点击一级分类时,页面中显示的是该一级分类下的所有课程:

day14【首页课程和名师功能】-02 首页课程功能_第1张图片

完善点击添一级分类显示样式:

  .active {

    background: #bdbdbd;

  }

  .hide {

    display: none;

  }

  .show {

    display: block;

  }

如果oneIndex==index则添加样式:

day14【首页课程和名师功能】-02 首页课程功能_第2张图片
day14【首页课程和名师功能】-02 首页课程功能_第3张图片
day14【首页课程和名师功能】-02 首页课程功能_第4张图片
day14【首页课程和名师功能】-02 首页课程功能_第5张图片

结果:

day14【首页课程和名师功能】-02 首页课程功能_第6张图片

完善点击某个二级分类实现查询

day14【首页课程和名师功能】-02 首页课程功能_第7张图片
day14【首页课程和名师功能】-02 首页课程功能_第8张图片

结果:

day14【首页课程和名师功能】-02 首页课程功能_第9张图片

完善排序方式显示

            

              

              

                销量

                  

                

              

              

                最新

                  

                

              

              

                价格 

                  

                

              

            

          

day14【首页课程和名师功能】-02 首页课程功能_第10张图片

    //6 根据销量进行排序

    searchBuyCount(){

      //设置对应变量值,为了样式生效

      this.buyCountSort = "1"

      this.gmtCreateSort = ""

      this.priceSort = ""

      //把值赋值到search0bj

      this.searchObj.buyCountSort = this.buyCountSort

      this.searchObj.gmtCreateSort = this.gmtCreateSort

      this.searchObj.priceSort = this.priceSort


      //调用方法查询

      this.gotoPage(1)

    },

    //7 最新排序

    searchGmtCreate(){

      //设置对应变量值,为了样式生效

      this.buyCountSort = ""

      this.gmtCreateSort = "1"

      this.priceSort = ""

      //把值赋值到search0bj

      this.searchObj.buyCountSort = this.buyCountSort

      this.searchObj.gmtCreateSort = this.gmtCreateSort

      this.searchObj.priceSort = this.priceSort

      //调用方法查询

      this.gotoPage(1)

    },

    //8 价格排序

    searchPrice(){

      //设置对应变量值,为了样式生效

      this.buyCountSort = ""

      this.gmtCreateSort = ""

      this.priceSort = "1"

      //把值赋值到search0bj

      this.searchObj.buyCountSort = this.buyCountSort

      this.searchObj.gmtCreateSort = this.gmtCreateSort

      this.searchObj.priceSort = this.priceSort

      //调用方法查询

      this.gotoPage(1)

    }

day14【首页课程和名师功能】-02 首页课程功能_第11张图片

三、课程列表渲染

1、课程类别显示

    

          

            

              课程类别

            

            

              

                

  •                   全部

                    

  •                 

                      {{item.title}}

                    

                  

                

              

              

                

                  

                

                

                  

                    

                      {{item.title}}

                    

                  

                

              

              

            

    2、无数据提示

    添加:v-if="data.total==0"

             

              

                 

                没有相关数据,小编正在努力整理中...

              

              

    3、列表

        0" class="comm-course-list">

                

                  

                    

                      

                        

                        

                          开始学习

                        

                      

                      

                        {{ item.title }}

                      

                      

                        

                          免费

                        

                        

                          {{ item.viewCount }}人学习

                          |

                          9634评论

                        

                      

                    

                  

                

                

              

    4、分页页面渲染

        

              

         

                

                  

                  

                    :class="{undisable: !data.hasPrevious}"

                    href="#"

                    title="首页"

                    @click.prevent="gotoPage(1)">首页

                  

                    :class="{undisable: !data.hasPrevious}"

                    href="#"

                    title="前一页"

                    @click.prevent="gotoPage(data.current-1)"><

                  

                    v-for="page in data.pages"

                    :key="page"

                    :class="{current: data.current == page, undisable: data.current == page}"

                    :title="'第'+page+'页'"

                    href="#"

                    @click.prevent="gotoPage(page)">{{ page }}

                  

                    :class="{undisable: !data.hasNext}"

                    href="#"

                    title="后一页"

                    @click.prevent="gotoPage(data.current+1)">>

                  

                    :class="{undisable: !data.hasNext}"

                    href="#"

                    title="末页"

                    @click.prevent="gotoPage(data.pages)">末页

                  

                

              

            

    day14【首页课程和名师功能】-02 首页课程功能_第12张图片
    day14【首页课程和名师功能】-02 首页课程功能_第13张图片



    03-课程详情页

    一、vo对象的定义

    在项目中很多时候需要把model转换成dto用于网站信息的展示,按前端的需要传递对象的数据,保证model对外是隐私的,例如密码之类的属性能很好地避免暴露在外,同时也会减小数据传输的体积。

    CourseWebInfoVo.java(用于封装课程的详情信息)

    @ApiModel(value="课程信息", description="网站课程详情页需要的相关字段")

    @Data

    public class CourseWebInfoVo {

        private String id;

        @ApiModelProperty(value = "课程标题")

        private String title;

        @ApiModelProperty(value = "课程销售价格,设置为0则可免费观看")

        private BigDecimal price;

        @ApiModelProperty(value = "总课时")

        private Integer lessonNum;

        @ApiModelProperty(value = "课程封面图片路径")

        private String cover;

        @ApiModelProperty(value = "销售数量")

        private Long buyCount;

        @ApiModelProperty(value = "浏览数量")

        private Long viewCount;

        @ApiModelProperty(value = "课程简介")

        private String description;

        @ApiModelProperty(value = "讲师ID")

        private String teacherId;

        @ApiModelProperty(value = "讲师姓名")

        private String teacherName;

        @ApiModelProperty(value = "讲师资历,一句话说明讲师")

        private String intro;

        @ApiModelProperty(value = "讲师头像")

        private String avatar;

        @ApiModelProperty(value = "课程一级类别ID")

        private String subjectLevelOneId;

        @ApiModelProperty(value = "类别一级名称")

        private String subjectLevelOne;

        @ApiModelProperty(value = "课程二级类别ID")

        private String subjectLevelTwoId;

        @ApiModelProperty(value = "类别二级名称")

        private String subjectLevelTwo;

    }

    二、课程和讲师信息的获取

    1、CourseFrontController

         //根据课程id,编写sq1语句查询课程信息

        @ApiOperation(value = "根据ID查询课程")

        @GetMapping("getFrontCourseInfo/{courseId}")

        public R getFrontCourseInfo(@PathVariable String courseId){

            //根据课程id,编写sql语句查询课程信息

            CourseWebInfoVo courseWebInfoVo = courseService.getBaseCourseInfo(courseId);

            //根据课程id查询章节和小节

            List chapterVideoByCourseId = chapterService.getChapterVideoByCourseId(courseId);

            return R.ok().data("courseWebVo",courseWebInfoVo).data("chapterVideoList",chapterVideoByCourseId);

        }

    2、EduCourseService

        //根据课程id,编写sq1语句查询课程信息

        CourseWebInfoVo getBaseCourseInfo(String courseId);

    3、EduCourseServiceImpl

        //根据课程id,编写sq1语句查询课程信息

        @Override

        public CourseWebInfoVo getBaseCourseInfo(String courseId) {

            return baseMapper.getBaseCourseInfo(courseId);

        }

    4、Mapper中关联查询课程和讲师信息

    EduCourseMapper.java

        //根据课程id,编写sq1语句查询课程信息

        CourseWebInfoVo getBaseCourseInfo(String courseId);

    EduCourseMapper.xml

        

       

    因为现在方法中只有一个参数,当只有一个参数时,WHEREec.id=#{courseId}中courseId可以随便写。

    默认xml文件不加载问题:

    day14【首页课程和名师功能】-02 首页课程功能_第14张图片
    day14【首页课程和名师功能】-02 首页课程功能_第15张图片


    三、前端js

    1、api/course.js

      // 课程详情的方法

      getCourseInfo(courseId){

        return request({

            url: `/eduservice/coursefront/getFrontCourseInfo/${courseId}`,

            method: 'get'

        })

      }

    2、pages/course/_id.vue

    四、页面模板

    pages/course/_id.vue

    1、课程所属分类

       

        

          

            首页

            \

            课程列表

            \

            {{courseWebVo.subjectLevelOne}}

            \

            {{courseWebVo.subjectLevelTwo}}

          

          

    2、课程基本信息

          

          

            

              

                

              

            

            

              

                

                  {{courseWebVo.title}}

                

                

                  价格:

                  ¥{{courseWebVo.price}}

                

                

                  主讲: {{courseWebVo.teacherName}}   

                

                

                  

                    

                    收藏

                  

                

                

                  立即观看

                

              

            

            

              

                

  •               

     

                  

                

  •             

  •               

     

                  

                

  •             

  •               

     

                  

                

  •           

            

            

          

          

    3、课程详情介绍

    在后端添加课程简介时可以添加样式,但是 {{courseWebVo.description}}只是进行了原样输出。

    day14【首页课程和名师功能】-02 首页课程功能_第16张图片

                        

                          

                            {{courseWebVo.description}}

                          

    day14【首页课程和名师功能】-02 首页课程功能_第17张图片

    4、课程大纲

                

                    

                      

                        课程大纲

                      

                      

                        

                          

                            

                          

                        

                      

                    

                    

    5、主讲讲师

       

                

                  

                    主讲讲师

                  

                  

                    

                      

  •                     

                          

                            

                          

                        

  •                     

                           {{courseWebVo.teacherName}}

                        

                        

                          {{courseWebVo.intro}}

                        

                      

                    

                  

                

                

    最终显示结果:

    day14【首页课程和名师功能】-02 首页课程功能_第18张图片



    04-视频播放测试

    一、获取播放地址播放

    获取播放地址

    参考文档:https://help.aliyun.com/document_detail/61064.html

    前面的 03-使用服务端SDK 介绍了如何获取非加密视频的播放地址。直接使用03节的例子获取加密视频播放地址会返回如下错误信息

    Currently only the AliyunVoDEncryption stream exists, you must use the Aliyun player to play or set the value of ResultType to Multiple.

    目前只有AliyunVoDEncryption流存在,您必须使用Aliyun player来播放或将ResultType的值设置为Multiple。

    因此在testGetPlayInfo测试方法中添加 ResultType 参数,并设置为true

    privateParams.put("ResultType","Multiple");

    此种方式获取的视频文件不能直接播放,必须使用阿里云播放器播放

    二、视频播放器

    参考文档:https://help.aliyun.com/document_detail/61109.html

    1、视频播放器介绍

    阿里云播放器SDK(ApsaraVideo Player SDK)是阿里视频服务的重要一环,除了支持点播和直播的基础播放功能外,深度融合视频云业务,如支持视频的加密播放、安全下载、清晰度切换、直播答题等业务场景,为用户提供简单、快速、安全、稳定的视频播放服务。

    2、集成视频播放器

    参考文档:https://help.aliyun.com/document_detail/51991.html

    参考 【播放器简单使用说明】一节

    引入脚本文件和css文件

         

        

    初始化视频播放器

        

            

    3、播放地址播放

    在Aliplayer的配置参数中添加如下属性

                    //播放方式一:支持播放地址播放,此播放优先级最高,此种方式不能播放加密视频

                    source : '你的视频播放地址',

    测试:创建html文件(01播放地址播放.html)

        

        

        Document


        

        

        

            

    启动浏览器运行,测试视频的播放:

    day14【首页课程和名师功能】-02 首页课程功能_第19张图片

    4、播放凭证播放(推荐)

    阿里云播放器支持通过播放凭证自动换取播放地址进行播放,接入方式更为简单,且安全性更高。播放凭证默认时效为100秒(最大为3000秒),只能用于获取指定视频的播放地址,不能混用或重复使用。如果凭证过期则无法获取播放地址,需要重新获取凭证。

    encryptType:'1',//如果播放加密视频,则需设置encryptType=1,非加密视频无需设置此项

    vid:'视频id',

    playauth:'视频授权码',

    注意:播放凭证有过期时间,默认值:100秒 。取值范围:100~3000。

    设置播放凭证的有效期

    在获取播放凭证的测试用例中添加如下代码

    request.setAuthInfoTimeout(200L);

    在线配置参考:https://player.alicdn.com/aliplayer/setting/setting.html

    测试:创建html文件(02播放凭证播放.html)

    playauth是根据视频id获取。

    day14【首页课程和名师功能】-02 首页课程功能_第20张图片
    day14【首页课程和名师功能】-02 首页课程功能_第21张图片

        

        

        Document


        

        

        

            

    启动浏览器运行,测试视频的播放:

    day14【首页课程和名师功能】-02 首页课程功能_第22张图片



    05-整合阿里云视频播放器

    一、后端获取播放凭证

    1、VodController

    service-vod微服务中创建 VodController.java

    controller中创建 getPlayAuth接口方法

        //根据视频id获取视频凭证

        @GetMapping("getPlayAuth/{id}")

        public R getPlayAuth(@PathVariable String id){

            try {

                //创建初始化对象

                DefaultAcsClient client = InitObjectV.initVodClient(ConstantPropertiesUtil.ACCESS_KEY_ID,ConstantPropertiesUtil.ACCESS_KEY_SECRET);

                //创建获取凭证request和response对象

                GetVideoPlayAuthRequest request = new GetVideoPlayAuthRequest();

                //向request设置视频id

                request.setVideoId(id);

                //调用方法得到凭证

                GetVideoPlayAuthResponse response = client.getAcsResponse(request);

                String playAuth = response.getPlayAuth();

                return R.ok().data("playAuth",playAuth);

            } catch (ClientException e) {

                throw new GuliException(20001,"获取凭证失败");

            }

        }

    2、Swagger测试

    day14【首页课程和名师功能】-02 首页课程功能_第23张图片

    二、前端播放器整合

    day14【首页课程和名师功能】-02 首页课程功能_第24张图片

    1、点击播放超链接

    course/_id.vue

    修改课时目录超链接

    day14【首页课程和名师功能】-02 首页课程功能_第25张图片

    2、layout

    因为播放器的布局和其他页面的基本布局不一致,因此创建新的布局容器 layouts/video.vue

    .head {

      height: 50px;

      position: absolute;

      top: 0;

      left: 0;

      width: 100%;

    }

    .head .logo{

      height: 50px;

      margin-left: 10px;

    }

    .body {

      position: absolute;

      top: 50px;

      left: 0;

      right: 0;

      bottom: 0;

      overflow: hidden;

    }

    3、api

    创建api模块 api/vod.js,从后端获取播放凭证

    import request from '@/utils/request'

    export default {

        //根据视频id获取视频凭证

        getPlayAuth(vid) {

            return request({

                url: `/eduvod/video/getPlayAuth/${vid}`,

                method: 'get'

            })

        }

    }

    4、播放组件相关文档

    集成文档:https://help.aliyun.com/document_detail/51991.html?spm=a2c4g.11186623.2.39.478e192b8VSdEn

    在线配置:https://player.alicdn.com/aliplayer/setting/setting.html

    功能展示:https://player.alicdn.com/aliplayer/presentation/index.html

    5、创建播放页面

    创建pages/player/_vid.vue

    (1)引入播放器js库和css样式

    (2)获取播放凭证

    day14【首页课程和名师功能】-02 首页课程功能_第26张图片

    (3)创建播放器

         /**

         * 页面渲染完成时:此时js脚本已加载,Aliplayer已定义,可以使用

         * 如果在created生命周期函数中使用,Aliplayer is not defined错误

         */

        mounted() {

            new Aliplayer({

                id: 'J_prismPlayer',

                vid: this.vid, // 视频id

                playauth: this.playAuth, // 播放凭证

                encryptType: '1', // 如果播放加密视频,则需设置encryptType=1,非加密视频无需设置此项

                width: '100%',

                height: '500px'

            }, function(player) {

                console.log('播放器创建成功')

            })

        }

    day14【首页课程和名师功能】-02 首页课程功能_第27张图片

    (4)其他常见的可选配置

            // 以下可选设置

                cover: 'http://guli.shop/photo/banner/1525939573202.jpg', // 封面

                qualitySort: 'asc', // 清晰度排序

                mediaType: 'video', // 返回音频还是视频

                autoplay: false, // 自动播放

                isLive: false, // 直播

                rePlay: false, // 循环播放

                preload: true,

                controlBarVisibility: 'hover', // 控制条的显示方式:鼠标悬停

                useH5Prism: true, // 播放器类型:html5

    day14【首页课程和名师功能】-02 首页课程功能_第28张图片

    6、加入播放组件

    功能展示:https://player.alicdn.com/aliplayer/presentation/index.html

    你可能感兴趣的:(day14【首页课程和名师功能】-02 首页课程功能)