谷粒学院——Day14【首页课程和名师功能】

❤ 作者主页:Java技术一点通的博客
❀ 个人介绍:大家好,我是Java技术一点通!( ̄▽ ̄)~*
记得关注、点赞、收藏、评论⭐️⭐️⭐️
认真学习,共同进步!!!

首页名师功能

一、名师页面静态效果整合

1. 列表页面

pages/teacher/index.vue



2. 详情页面

pages/teacher/_id.vue




二、讲师列表页

一、后端开发

1. controller层

TeacherFrontController

@RestController
@CrossOrigin
@RequestMapping("/eduservice/teacherfront")
public class TeacherFrontController {

    @Autowired
    private EduTeacherService teacherService;

    // 分页查询讲师的方法
    @PostMapping("getTeahcerFrontList/{page}/{limit}")
    public R getTeacherFrontList(@PathVariable long page, @PathVariable long limit) {
        Page pageTeacher = new Page<>(page,limit);
        Map map = teacherService.getTeacherFrontList(pageTeacher);

        // 返回分页所有数据
        return R.ok().data(map);

    }
}

2. service层

  • EduTeacherService

      // 分页查询讲师的方法
        Map getTeacherFrontList(Page pageTeacher);
    
  • EduTeacherServiceImpl

    // 分页查询讲师的方法
        @Override
        public Map getTeacherFrontList(Page pageTeacher) {
    
            QueryWrapper wrapper = new QueryWrapper<>();
            wrapper.orderByDesc("id");
            //把分页数据封装到pageTeacher对象
            baseMapper.selectPage(pageTeacher, wrapper);
    
            // 把分页数据获取出来,放到map集合
            Map map = new HashMap<>();
    
            //总记录数
            long total = pageTeacher.getTotal();
            //当前页
            long current = pageTeacher.getCurrent();
            //每页记录数
            long size = pageTeacher.getSize();
            //查询到的对象
            List teacherList = pageTeacher.getRecords();
            //总页数
            long pages = pageTeacher.getPages();
            //是否有上一页
            boolean hasPrevious = pageTeacher.hasPrevious();
            //是否有下一页
            boolean hasNext = pageTeacher.hasNext();
    
            //将数据封装到map中返回
            map.put("total", total);
            map.put("current", current);
            map.put("size", size);
            map.put("list", teacherList);
            map.put("hasPrevious", hasPrevious);
            map.put("hasNext", hasNext);
            map.put("pages", pages);
    
            return map;
        }
    

3. swagger测试

谷粒学院——Day14【首页课程和名师功能】_第1张图片
 
谷粒学院——Day14【首页课程和名师功能】_第2张图片
 


二、前端列表js

1. 创建api

创建文件夹api,api下创建teacher.js,用于封装讲师模块的请求

import request from '@/utils/request'

export default{

    // 分页讲师查询的方法
    getTeacherList(page, limit) {
        return request({
            url: `/eduservice/teacherfront/getTeahcerFrontList/${page}/${limit}`,
            method: 'post'
        })
    }

}

2. 讲师列表组件中调用api



三、页面渲染

1. 页面模板



2. 无数据提示

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

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

3. 列表


4. 测试

谷粒学院——Day14【首页课程和名师功能】_第3张图片
 


四、分页

1. 分页方法

methods: {
        // 分页切换的方法
        //参数是页码数
        gotoPage(page) {
          teacherApi.getTeacherList(page, 8)
            .then(response => {
              this.data = response.data.data
            })
        }
      }

2. 分页页面渲染

 
        

3. 测试

谷粒学院——Day14【首页课程和名师功能】_第4张图片
 
谷粒学院——Day14【首页课程和名师功能】_第5张图片
 


三、讲师详情页

一、后端开发

1. controller层

TeacherFrontController

@RestController
@CrossOrigin
@RequestMapping("/eduservice/teacherfront")
public class TeacherFrontController {

    @Autowired
    private EduTeacherService teacherService;

    @Autowired
    private EduCourseService courseService;

    // 根据id查询讲师信息(讲师本身信息 + 讲师所讲课程信息)
    @GetMapping("/getTeacherFrontInfo/{teacherId}")
    public R getTeacherFrontInfo(@PathVariable String teacherId) {
        //1.根据讲师id查询讲师基本信息
        EduTeacher eduTeacher = teacherService.getById(teacherId);

        //2.根据讲师id查询所讲课程
        QueryWrapper wrapper = new QueryWrapper<>();
        wrapper.eq("teacher_id", teacherId);
        List courseList = courseService.list(wrapper);

        return R.ok().data("teacher", eduTeacher).data("courseList", courseList);
        
    }

}

2. Swagger测试

谷粒学院——Day14【首页课程和名师功能】_第6张图片
 
谷粒学院——Day14【首页课程和名师功能】_第7张图片
 


二、前端开发

1. 定义api

api/teacher.js:

// 讲师详情的方法
    getTeacherInfo(id) {
        return request({
            url: `/eduservice/teacherfront/getTeacherFrontInfo/${id}`,
            method: 'get'
        })
    }

2. 讲师详情页中调用api

pages/teacher/_id.vue:

import teacherApi from '@/api/teacher'

export default {

   asyncData({ params, error }) {
    return teacherApi.getTeacherInfo(params.id)
      .then(response => {
            // console.log(response)
            return { 
              teacher: response.data.data.teacher,
              courseList: response.data.data.courseList
            }
       })
  }

}


三、页面渲染

1. 讲师基本信息模板



2. 讲师详情显示

{{teacher.name}}  {{teacher.level ===1?'高级讲师':'首席讲师'}}

{{teacher.career}}

{{teacher.intro}}

3. 无数据提示

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

4. 当前讲师课程列表

 
          

5. 测试

  • 讲师列表
    谷粒学院——Day14【首页课程和名师功能】_第8张图片

  • 有课程
    谷粒学院——Day14【首页课程和名师功能】_第9张图片

  • 没有课程
    谷粒学院——Day14【首页课程和名师功能】_第10张图片
     


首页课程功能

课程列表页面

一、后端接口开发

1. 实体类

创建 frontvo 包,在改包下创建 CourseFrontVo 实体类:

@Data
public class CourseFrontVo {
    private static final long serialVersionUID = 1L;

    @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层

CourseFrontController

@RestController
@CrossOrigin
@RequestMapping("/eduservice/coursefront")
public class CourseFrontController {
    
    @Autowired
    private EduCourseService courseService;

    // 条件查询带分页查询课程
    @PostMapping("getFrontCourseList/{page}/{limit}")
    public R getFrontCourseList(@PathVariable long page, @PathVariable long limit,
                                @RequestBody(required = false) CourseFrontVo courseFrontVo) {
        Page pageCourse = new Page<>(page, limit);
        Map map = courseService.getCourseFrontList(pageCourse, courseFrontVo);

        // 返回分页所有数据
        return R.ok().data(map);
    }

}

3. service层

EduCourseService:

// 条件查询带分页查询课程
    Map getCourseFrontList(Page pageCourse, CourseFrontVo courseFrontVo);

EduCourseServiceImpl:

 // 条件查询带分页查询课程
    @Override
    public Map getCourseFrontList(Page pageParam, CourseFrontVo courseFrontVo) {
        QueryWrapper wrapper = new QueryWrapper<>();
        // 判断条件值是否为空,不为空则拼接
        if (!StringUtils.isEmpty(courseFrontVo.getSubjectParentId())) { //一级分类
            wrapper.eq("subject_parent_id", courseFrontVo.getSubjectId());
        }

        if (!StringUtils.isEmpty(courseFrontVo.getSubjectId())) { //二级分类
            wrapper.eq("subject_id", courseFrontVo.getSubjectId());
        }

        if (!StringUtils.isEmpty(courseFrontVo.getBuyCountSort())) { //关注度
            wrapper.orderByDesc("buy_count");
        }

        if (!StringUtils.isEmpty(courseFrontVo.getGmtCreateSort())) { //最新,创建时间
            wrapper.orderByDesc("gmt_create");
        }

        if (!StringUtils.isEmpty(courseFrontVo.getPriceSort())) { //价格
            wrapper.orderByDesc("price");
        }

        baseMapper.selectPage(pageParam, wrapper);

        // 把分页数据获取出来,放到map集合
        Map map = new HashMap<>();

        //总记录数
        long total = pageParam.getTotal();
        //当前页
        long current = pageParam.getCurrent();
        //每页记录数
        long size = pageParam.getSize();
        //查询到的对象
        List records = pageParam.getRecords();
        //总页数
        long pages = pageParam.getPages();
        //是否有上一页
        boolean hasPrevious = pageParam.hasPrevious();
        //是否有下一页
        boolean hasNext = pageParam.hasNext();

        //将数据封装到map中返回
        map.put("total", total);
        map.put("current", current);
        map.put("size", size);
        map.put("items", records);
        map.put("hasPrevious", hasPrevious);
        map.put("hasNext", hasNext);
        map.put("pages", pages);

        return map;

    }

 


二、课程列表前端

1. 定义api

api/course.js

import request from '@/utils/request'

export default{

   // 条件分页课程查询的方法
   getCourseList(page, limit, searchObj) {
       return request({
           url: `/eduservice/coursefront/getFrontCourseList/${page}/${limit}`,
           method: 'post',
           data: searchObj
       })
   },

   // 查询所有分类的方法
   getAllSubject() {
       return request({
           url: `/eduservice/subject/getAllSubject`,
           method: 'get'
       })
   }
}

2. 页面调用接口

pages/course/index.vue



3. 前端页面


4. 测试

谷粒学院——Day14【首页课程和名师功能】_第11张图片
 
谷粒学院——Day14【首页课程和名师功能】_第12张图片
 


课程详情页

一、后端开发

1. 实体类

CourseWebVo

@Data
public class CourseWebVo {
    private static final long serialVersionUID = 1L;
    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;
}

2. controller层

CourseFrontController

 //课程详情的方法
    @GetMapping("getFrontCourseInfo/{courseId}")
    public R getFrontCourseInfo(@PathVariable String courseId) {
        //根据课程id,编写sql语句查询课程信息
        CourseWebVo courseWebVo = courseService.getBaseCourseInfo(courseId);

        //根据课程id查询章节和小节
        List chapterVoList = chapterService.getChapterVideoByCourseId(courseId);

        return R.ok().data("courseWebVo",courseWebVo).data("chapterVoList",chapterVoList);
    }

3. service层

  • EduCourseService

     //根据课程id,编写sql语句查询课程信息
        CourseWebVo getBaseCourseInfo(String courseId);
    
  • EduCourseServiceImpl

    //根据课程id,编写sql语句查询课程信息
        @Override
        public CourseWebVo getBaseCourseInfo(String courseId) {
            return baseMapper.getBaseCourseInfo(courseId);
        }
    

4. dao层

@Mapper
public interface EduCourseMapper extends BaseMapper {

    public CoursePublishVo getPublishCourseInfo(String courseId);

    //根据课程id,编写sql语句查询课程信息
    CourseWebVo getBaseCourseInfo(String courseId);
}

EduCourseMapper.xml:

  
    

5. 测试

谷粒学院——Day14【首页课程和名师功能】_第13张图片
 
谷粒学院——Day14【首页课程和名师功能】_第14张图片
 


二、前端开发

1. 定义api

api/course.js

 //课程详情的方法
    getCourseInfo(courseId) {
        return request({
            url: `/eduservice/coursefront/getFrontCourseInfo/${courseId}`,
            method: 'get'
        })
    }

2. 页面调用接口

pages/course/_id.vue


3. 前端页面


4. 测试

谷粒学院——Day14【首页课程和名师功能】_第15张图片
 
谷粒学院——Day14【首页课程和名师功能】_第16张图片
 


视频播放测试

参考文档:https://help.aliyun.com/document_detail/61109.htmlspm=a2c4g.11186623.6.975.9ea624d8CwyqYN

1. 视频播放器介绍

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

2. 集成视频播放器

参考文档:https://help.aliyun.com/document_detail/51991.html
参考 【播放器简单使用说明】一节

  • 引入脚本文件和css文件

    
    
    
    
  • 初始化视频播放器

    
        

3. 播放地址播放

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

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

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

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

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

encryptType:'1',//如果播放加密视频,则需设置encryptType=1,非加密视频无需设置此项
vid : '视频id',
playauth : '视频授权码',

注意:播放凭证有过期时间,默认值:100秒 。取值范围:100~3000。
设置播放凭证的有效期。
在获取播放凭证的测试用例中添加如下代码。

request.setAuthInfoTimeout(200L);

在线配置参考:https://player.alicdn.com/aliplayer/setting/setting.htmlspm=a2c4g.11186623.2.16.242c6782Kdc4Za
 


整合阿里云视频播放器

一、后端获取播放凭证

1. controller层

VodController

//根据视频id获取视频凭证
    @GetMapping("/getPlayAuth/{id}")
    public R getPlayAuth(@PathVariable String id){
        try {
            //初始化
            DefaultAcsClient client = InitVodClient.initVodClient(ConstantVodUtils.ACCESS_KEY_ID, ConstantVodUtils.ACCESS_KEY_SECRET);

            //请求
            GetVideoPlayAuthRequest request = new GetVideoPlayAuthRequest();
            request.setVideoId(id);

            //响应
            GetVideoPlayAuthResponse response = client.getAcsResponse(request);

            //得到播放凭证
            String playAuth = response.getPlayAuth();

            return R.ok().data("playAuth", playAuth);
            
        } catch (Exception e) {
            throw new GuliException(20001,"获取视频凭证失败");
        }
    }

2. Swagger测试

谷粒学院——Day14【首页课程和名师功能】_第17张图片
 
谷粒学院——Day14【首页课程和名师功能】_第18张图片
 


二、前端播放器整合

1. 点击播放超链接

course/_id.vue


2. 定义api

api/vod.js

import request from '@/utils/request'

export default{
    //根据视频id,获取视频凭证
    getPlayAuthById(id){
        return request({
            url:`/eduvod/video/getPlayAuth/${id}`,
            method: 'get'
        })
    }
}

3. 页面