谷粒学院(十七)讲师列表页 | 讲师详情 | 整合阿里云视频点播

2023-05-16

一、讲师列表页 - 后端

1、Controller类

@Api(description = "讲师管理前端")
@RestController
@RequestMapping("/eduservice/teacherfront")
@CrossOrigin
public class TeacherFrontController {

    @Autowired
    private EduTeacherService teacherService;

    @Autowired
    private EduCourseService courseService;

    @ApiOperation(value = "分页查询所有讲师")
    @PostMapping("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().data(map);
    }
}

2、Service类

@Override
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集合
    Map<String,Object> map = new HashMap<>();
    map.put("items",records);
    map.put("pages",pages);
    map.put("current",current);
    map.put("size",size);
    map.put("total",total);
    map.put("hasNext",hasNext);
    map.put("hasPrevious",hasPrevious);

    return map;
}

3、使用Swagger测试

http://localhost:8001/swagger-ui.html

二、讲师详情页 - 前端

1、创建api

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

import request from '@/utils/request'

export default {
  //查询讲师信息方法
  getTeacherList(page,limit) {
    return request({
        url: `/eduservice/teacherfront/getTeacherFrontList/${page}/${limit}`,
        method: 'post'
      })
  },
}

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

pages/teacher/index.vue

<script>
import teacherApi from '@/api/teacher'

export default {
  //异步调用,调用一次
  //params: 相当于之前 this.$route.params.id  等价  params.id
  asyncData({ params, error }) {
    return teacherApi.getTeacherList(1,8).then(response => {
          //this.data = response.data.data
          return { data: response.data.data }
       })
  },
  methods:{
    //分页切换的方法
    //参数是页码数
    gotoPage(page) {
      teacherApi.getTeacherList(page,8)
        .then(response => {
          this.data = response.data.data
        })
    }
  }
};
</script>

3、页面展示

<div>
  <!-- /无数据提示 开始-->
  <section class="no-data-wrap" v-if="data.total==0">
    <em class="icon30 no-data-ico">&nbsp;</em>
    <span class="c-666 fsize14 ml10 vam">没有相关数据,小编正在努力整理中...</span>
  </section>
  <!-- /无数据提示 结束-->
  <article v-if="data.total>0" class="i-teacher-list">
    <ul class="of">
      <li v-for="teacher in data.items" :key="teacher.id">
        <section class="i-teach-wrap">
          <div class="i-teach-pic">
            <a :href="'/teacher/'+teacher.id" :title="teacher.name" target="_blank">
              <img :src="teacher.avatar" :alt="teacher.name">
            </a>
          </div>
          <div class="mt10 hLh30 txtOf tac">
            <a :href="'/teacher/'+teacher.id" :title="teacher.name" target="_blank" class="fsize18 c-666">{{teacher.name}}</a>
          </div>
          <div class="hLh30 txtOf tac">
            <span class="fsize14 c-999">{{teacher.intro}}</span>
          </div>
          <div class="mt15 i-q-txt">
            <p class="c-999 f-fA">{{teacher.career}}</p>
          </div>
        </section>
      </li>
      
    </ul>
    <div class="clear"></div>
  </article>
</div>

4、分页展示

<!-- 公共分页 开始 -->
<div>
   <div class="paging">
     <!-- undisable这个class是否存在,取决于数据属性hasPrevious -->
     <a
       :class="{undisable: !data.hasPrevious}"
       href="#"
       title="首页"
       @click.prevent="gotoPage(1)">首页</a>

     <a
       :class="{undisable: !data.hasPrevious}"
       href="#"
       title="前一页"
       @click.prevent="gotoPage(data.current-1)">&lt;</a>

     <a
       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 }}</a>

     <a
       :class="{undisable: !data.hasNext}"
       href="#"
       title="后一页"
       @click.prevent="gotoPage(data.current+1)">&gt;</a>

     <a
       :class="{undisable: !data.hasNext}"
       href="#"
       title="末页"
       @click.prevent="gotoPage(data.pages)">末页</a>

     <div class="clear"/>
   </div>
 </div>
 <!-- 公共分页 结束 -->

5、测试结果

三、讲师详情 - 前后端

1、Controller 类

@ApiOperation(value = "讲师详情功能")
 @GetMapping("getTeacherFrontInfo/{teacherId}")
 public R getTeacherFrontInfo(@PathVariable String teacherId) {
     //根据讲师id 查询讲师基本信息
     EduTeacher teacher = 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",teacher).data("courseList",courseList);
 }

2、swagger测试

3、teacher api

api/teacher.js

//根据讲师id查询详情
getTeacherInfo(id) {
  return request({
    url: `/eduservice/teacherfront/getTeacherFrontInfo/${id}`,
    method: 'get'
  })
}

4、讲师详情页中调用api

pages/teacher/_id.vue

<script>
import teacherApi from '@/api/teacher'

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

};
</script>

5、页面渲染

(1)讲师基本信息模板

<!-- 讲师基本信息 -->
<section class="fl t-infor-box c-desc-content">
  <div class="mt20 ml20">
    <section class="t-infor-pic">
      <img :src="teacher.avatar">
    </section>
    <h3 class="hLh30">
      <span class="fsize24 c-333">{{teacher.name}}&nbsp;
        {{ teacher.level===1?'高级讲师':'首席讲师' }}
      </span>
    </h3>
    <section class="mt10">
      <span class="t-tag-bg">{{teacher.intro}}</span>
    </section>
    <section class="t-infor-txt">
      <p
        class="mt20">{{teacher.career}}</p>
    </section>
    <div class="clear"></div>
  </div>
</section>

(2)无数据提示

<!-- /无数据提示 开始-->
<section class="no-data-wrap" v-if="courseList.length==0">
  <em class="icon30 no-data-ico">&nbsp;</em>
  <span class="c-666 fsize14 ml10 vam">没有相关数据,小编正在努力整理中...</span>
</section>
<!-- /无数据提示 结束-->

(3)当前讲师课程列表

<article class="comm-course-list">
  <ul class="of">
    <li v-for="course in courseList" :key="course.id">
      <div class="cc-l-wrap">
        <section class="course-img">
          <img :src="course.cover" class="img-responsive" >
          <div class="cc-mask">
            <a href="#" title="开始学习" target="_blank" class="comm-btn c-btn-1">开始学习</a>
          </div>
        </section>
        <h3 class="hLh30 txtOf mt10">
          <a href="#" :title="course.title" target="_blank" class="course-title fsize18 c-333">{{course.title}}</a>
        </h3>
      </div>
    </li>
   
  </ul>
  <div class="clear"></div>
</article>

6、测试

四、视频点播后端获取播放凭证

1、VideoController

service_vod微服务中 VodController.java 中创建 getPlayAuth 接口方法

@ApiOperation(value = "根据视频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、在service_edu中VideoVo类中添加属性

private String videoSourceId;//视频id

3、Swagger测试

五、前端播放器整合

1、点击播放超链接

course/_id.vue 中修改课时目录超链接

在这里插入图片描述

<a :href="'/player/'+video.videoSourceId" :title="video.title" target="_blank">

2、layout

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

<template>
  <div class="guli-player">
    <div class="head">
      <a href="#" title="谷粒学院">
        <img class="logo" src="~/assets/img/logo.png" lt="谷粒学院">
    </a></div>
    <div class="body">
      <div class="content"><nuxt/></div>
    </div>
  </div>
</template>
<script>
export default {}
</script>

<style>
html,body{
  height:100%;
}
</style>

<style scoped>
.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;
}
</style>

3、api

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

import request from '@/utils/request'
export default {
  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样式

<template>
  <div>

    <!-- 阿里云视频播放器样式 -->
    <link rel="stylesheet" href="https://g.alicdn.com/de/prismplayer/2.8.1/skins/default/aliplayer-min.css" >
    <!-- 阿里云视频播放器脚本 -->
    <script charset="utf-8" type="text/javascript" src="https://g.alicdn.com/de/prismplayer/2.8.1/aliplayer-min.js" />

    <!-- 定义播放器dom -->
    <div id="J_prismPlayer" class="prism-player" />
  </div>
</template>
<script>

(2)获取播放凭证

<script>
import vod from '@/api/vod'

export default {
    layout: 'video',//应用video布局
    asyncData({ params, error }) {
       return vod.getPlayAuth(params.vid)
        .then(response => {
            return { 
                playAuth: response.data.data.playAuth,
                vid: params.vid
            }
        })
    },
    
}
</script>

(3)创建播放器

mounted() { //页面渲染之后  created
        new Aliplayer({
            id: 'J_prismPlayer',
            vid: this.vid, // 视频id
            playauth: this.playAuth, // 播放凭证
            encryptType: '1', // 如果播放加密视频,则需设置encryptType=1,非加密视频无需设置此项
            width: '100%',
            height: '500px',
        }, function(player) {
            console.log('播放器创建成功')
        })
    }

(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

6、加入播放组件

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


如果有收获!!! 希望老铁们来个三连,点赞、收藏、转发。
创作不易,别忘点个赞,可以让更多的人看到这篇文章,顺便鼓励我写出更好的博客
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

谷粒学院(十七)讲师列表页 | 讲师详情 | 整合阿里云视频点播 的相关文章

  • 谷粒学院(一)项目介绍

    一 项目背景 在线教育顾名思义 xff0c 是以网络为介质的教学方式 xff0c 通过网络 xff0c 学员与教师即使相隔万里也可以开展教学活动 xff0c 此外 xff0c 借助网络课件 xff0c 学员还可以随时随地进行学习 xff0c
  • PyTorch:Dataset()与Dataloader()的使用详解

    目录 1 Dataset类的使用 2 Dataloader类的使用 3 总结 Dataset类与Dataloader类是PyTorch官方封装的用于在数据集中提取一个batch的训练用数据的接口 xff0c 其实我们也可以自定义获取每个ba
  • MyBatisPlus(二)入门案例

    一 快速入门 使用第三方组件 xff1a 导入对应的依赖研究依赖如何配置代码如何编写提高扩展技术能力 操作步骤 1 创建数据库mybatis plus 2 创建user表 span class token keyword DROP span
  • MyBatisPlus(三)CRUD接口操作

    一 CRUD扩展 Insert 插入 span class token comment 测试插入 span span class token annotation punctuation 64 Test span span class to
  • MyBatisPlus(四)性能分析插件 | 条件构造器 | 代码生成器

    文章目录 一 性能分析插件1 导入插件2 测试使用 二 条件构造器1 ge gt le It isNull isNotNull2 eq ne3 between notBetween4 like noLike likeLeft likeRig
  • 谷粒学院(三)讲师管理模块后端 | swagger | 统一日志 | 统一返回结果

    文章目录 一 讲师查询功能二 讲师逻辑删除功能三 配置Swagger2四 统一返回数据格式五 创建统一结果返回类六 统一返回结果使用七 讲师分页查询八 讲师条件查询带分页九 自动填充封装十 讲师添加功能十一 讲师修改功能十二 统一异常处理十
  • 谷粒学院(二)项目搭建

    一 讲师管理模块 xff08 后端 xff09 准备工作 1 创建数据库 xff0c 创建讲师数据库 guli edu sql 2 模块说明 guli parent xff1a 在线教学根目录 xff08 父工程 xff09 xff0c 管

随机推荐