一、讲师列表页 - 后端
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"> </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)"><</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)">">></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}}
{{ 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"> </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
如果有收获!!! 希望老铁们来个三连,点赞、收藏、转发。
创作不易,别忘点个赞,可以让更多的人看到这篇文章,顺便鼓励我写出更好的博客