在线教育-谷粒学院学习笔记(十二)

1 内容介绍

  • 名师列表、详情功能
  • 课程列表、详情功能
  • 整合阿里云视频播放
  • 课程评论功能

2 名师列表功能

1 分页查询名师接口

controller

@RestController
@RequestMapping("/eduservice/teacherfront")
@CrossOrigin
public class TeacherFrontController {
    @Autowired
    private EduTeacherService teacherService;

    // 1. 分页查询讲师
    @GetMapping("getTeacherFrontList/{page}/{limit}")
    public R getTeacherFrontList(@PathVariable long page, @PathVariable long limit) {
        Page<EduTeacher> pageTeacher = new Page<>(page, limit);
        Map<String, Object> map = teacherService.getTeacherFrontList(pageTeacher);
        // 返回分页所有数据
        return R.ok();
    }
}

service

public Map<String, Object> getTeacherFrontList(Page<EduTeacher> pageParam) {
    QueryWrapper<EduTeacher> wrapper = new QueryWrapper<>();
    wrapper.orderByDesc("id");
    baseMapper.selectPage(pageParam, wrapper);

    List<EduTeacher> records = pageParam.getRecords();
    long current = pageParam.getCurrent();
    long pages = pageParam.getPages();
    long size = pageParam.getSize();
    long total = pageParam.getTotal();
    boolean hasNext = pageParam.hasNext(); // 下一页
    boolean hasPrevious = pageParam.hasPrevious(); // 上一页
    // 分页数据放到map
    HashMap<String, Object> 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;
}

2 整合前端页面

查看评论p210 解决分页bug

  • api创建js文件,定义接口地址
  • 页面中引入,调用方法显示
export default {
  // 异步调用
  // params:相当于之前的 this$route.params.id==params.id
  asyncData({ params, error }) {
    return teacherApi.getTeacherList(1, 8).then(response => {
      console.log(response.data.data)
      return { data: response.data.data }
    })
  },
  methods: {
    // 分页切换方法
    gotoPage(page) {
      teacherApi.getTeacherList(page, 8)
        .then(response => {
          this.data = response.data.data
        })
    }
  }
}

3 讲师详情功能

1 修改讲师列表页面超链接,改成讲师id

:href="'/teacher/'+teacher.id"

2 编写讲师详情接口

  • 根据讲师id查询讲师基本信息

  • 根据讲师id查询课程

    @GetMapping("getTeacherFrontInfo/{teacherId}")
    public R getTeacherFrontInfo(@PathVariable String teacherId) {
        // 根据讲师id查询讲师基本信息
        EduTeacher eduTeacher = teacherService.getById(teacherId);
    
        // 根据讲师id查询课程
        QueryWrapper<EduCourse> wrapper = new QueryWrapper<>();
        wrapper.eq("teacher_id", teacherId);
        List<EduCourse> courseList = courseService.list(wrapper);
        return R.ok().data("teacher", eduTeacher).data("courseList", courseList);
    }
    

3 前端页面调用

teacher/_id.vue

asyncData({ params, error }) {
  // params.id获取路由中的id值
  return teacherApi.getTeacherInfo(params.id)
    .then(response => {
      return {
        teacher: response.data.data.teacher,
        courseList: response.data.data.courseList
      }
    })
}

4 课程条件查询带分页

1 创建vo对象,实现

@ApiModel(value = "课程查询对象", description = "课程查询对象封装")
@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、service

controller

@PostMapping("getCourseFrontList/{page}/{limit}")
public R getCourseFrontList(@PathVariable long page, @PathVariable long limit,
                            @RequestBody(required = false)CourseFrontVo courseFrontVo) {
    Page<EduCourse> pageCourse = new Page<>(page, limit);
    Map<String, Object> map = courseService.getCourseFrontList(pageCourse, courseFrontVo);
    // 返回分页所有数据
    return R.ok().data(map);
}

service

public Map<String, Object> getCourseFrontList(Page<EduCourse> pageParam, CourseFrontVo courseFrontVo) {
    QueryWrapper<EduCourse> wrapper = new QueryWrapper<>();
    // 判断条件值是否为空,不为空拼接
    if (!StringUtils.isEmpty(courseFrontVo.getSubjectParentId())) { // 一级分类
        wrapper.eq("subject_parent_id", courseFrontVo.getSubjectParentId());
    }
    if (!StringUtils.isEmpty(courseFrontVo.getSubjectId())) { // 二级分类
        wrapper.eq("subject_id", courseFrontVo.getSubjectParentId());
    }
    if (!StringUtils.isEmpty(courseFrontVo.getBuyCountSort())) { // 关注度
        wrapper.orderByDesc("buy_count", courseFrontVo.getSubjectParentId());
    }
    if (!StringUtils.isEmpty(courseFrontVo.getGmtCreateSort())) { // 最新
        wrapper.orderByDesc("gmt_create", courseFrontVo.getSubjectParentId());
    }
    if (!StringUtils.isEmpty(courseFrontVo.getPriceSort())) { // 价格
        wrapper.orderByDesc("price", courseFrontVo.getSubjectParentId());
    }
    baseMapper.selectPage(pageParam, wrapper);

    List<EduCourse> records = pageParam.getRecords();
    long current = pageParam.getCurrent();
    long pages = pageParam.getPages();
    long size = pageParam.getSize();
    long total = pageParam.getTotal();
    boolean hasNext = pageParam.hasNext(); // 下一页
    boolean hasPrevious = pageParam.hasPrevious(); // 上一页
    // 分页数据放到map
    HashMap<String, Object> 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;
}

3 前端整合

  • api/course.js中引入接口地址

    // 条件查询带分页:课程列表
    getCourseList(page, limit, searchObj) {
      return request({
        url: `/eduservice/coursefront/getCourseFrontList/${page}/${limit}`,
        method: 'post',
        data: searchObj
      })
    },
    // 查询所有分类
    getAllSubject() {
      return request({
        url: `/eduservice/subject/getAllSubject`,
        method: 'get'
      })
    }
    
  • 在页面中调用

    显示所有一级分类,点击某个一级分类,显示其对应的二级分类

    // 4 点击某个一级分类,查询对应二级分类
    searchOne(subjectParentId, index) {
      // 把传递index值赋值给oneIndex,为了active样式生效
      this.oneIndex = index
    
      // 清空二级分类
      this.twoIndex = -1
      this.searchObj.subjectId = ''
      this.subSubjectList = []
    
      // 把一级分类点击id值,赋值给searchObj
      this.searchObj.subjectParentId = subjectParentId
      // 点击某个一级分类进行条件查询
      this.gotoPage(1)
    
      // 拿着点击一级分类id 和 所有一级分类id进行比较,
      // 如果id相同,从一级分类里面获取对应的二级分类
      for (let i = 0; i < this.subjectNestedList.length; i++) {
        // 获取每个一级分类
        const oneSubject = this.subjectNestedList[i]
        // 比较id是否相同
        if (subjectParentId === oneSubject.id) {
          // 从一级分类里面获取对应的二级分类
          this.subSubjectList = oneSubject.children
        }
      }
    },
    
    // 5 点击某个二级分类实现查询
    searchTwo(subjectId, index) {
      // index赋值
      this.twoIndex = index
      this.searchObj.subjectId = subjectId
      this.gotoPage(1)
    },
    // 6 根据销量排序
        searchBuyCount() {
          // 设置对应变量值,为了样式生效
          this.buyCountSort = '1'
          this.gmtCreateSort = ''
          this.priceSort = ''
          // 赋值
          this.searchObj.buyCount = this.buyCountSort
          this.searchObj.gmtCreateSort = this.gmtCreateSort
          this.searchObj.priceSort = this.priceSort
          // 调用方法查询
          this.gotoPage(1)
        },
    

5 课程详细接口

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

课程基本信息、课程分类、课程描述、所属讲师

<!-- 2 根据课程id查询课程信息 -->
<select id="getBaseCourseInfo" resultType="com.mys.eduservice.entity.frontvo.CourseWebVo">
    select ec.id,ec.title,ec.price,ec.lesson_num AS lessonNum,ec.cover,
           ec.buy_count As buyCount,ec.view_count AS viewCount,
           ecd.description,
           et.id as teacherId,et.name as teacherName,et.intro,et.avatar,
           es1.title as subjectLevelOne,
           es2.title AS subjectLevelTwo
    from edu_course ec LEFT OUTER JOIN edu_course_description ecd ON ec.id=ecd.id
                       LEFT OUTER JOIN edu_teacher et ON ec.teacher_id=et.id
                       LEFT OUTER JOIN edu_subject es1 ON ec.subject_parent_id=es1.id
                       LEFT OUTER JOIN edu_subject es2 ON ec.subject_id=es2.id
    WHERE ec.id=#{courseId}
</select>

2 根据课程id查询章节、小节

// 2. 课程详情
@GetMapping("getFrontCourseInfo/{courseId}")
public R getFrontCourseInfo(@PathVariable String courseId) {
    // 根据课程id,编写sql语句,查询课程信息
    CourseWebVo courseWebVo = courseService.getBaseCourseInfo(courseId);
    // 根据课程id,查询章节、小节信息
    List<ChapterVo> chapterVideoList = chapterService.getChapterVideoByCourseId(courseId);
    return R.ok().data("courseWebVo", courseWebVo).data("chapterVideoList", chapterVideoList);
}

6 整合前端视频播放

1 创建接口,根据视频id获取视频凭证

// 根据视频id获取视频凭证
@GetMapping("getPlayAuth/{id}")
public R getPlayAuth(@PathVariable String id) {
    try {
        // 创建初始化对象
        DefaultAcsClient client = InitVodClient.initVodClient(ConstantVodUtils.ACCESS_KEY_ID, ConstantVodUtils.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 (Exception e) {
        throw new GuliException(20001, "获取凭证失败");
    }
}

2 点击某个小节,打开新的页面进行视频播放

修改超链接地址:<a :href="'/player/'+video.videoSourceId">

在pages创建文件夹和文件,使用动态路由的方式 /player/_vid.vue

细节:添加属性 com.mys.eduservice.entity.chapter.VideoVo

private String videoSourceId; // 视频id

player/_vid.vue

asyncData({ params, error }) {
  return vod.getPlayAuth(params.vid)
    .then(response => {
      return {
        playAuth: response.data.data.playAuth,
        vid: params.vid
      }
    })
},
mounted() { // 页面渲染之后  created
  // eslint-disable-next-line no-undef
  new Aliplayer({
    id: 'J_prismPlayer',
    vid: this.vid, // 视频id
    playauth: this.playAuth, // 播放凭证
    encryptType: '1', // 如果播放加密视频,则需设置encryptType=1,非加密视频无需设置此项
    width: '100%',
    height: '500px',
    // 以下可选设置
    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
  }, function(player) {
    console.log('播放器创建成功')
  })
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值