3、Service类
//对课程进行分页查询 @Override public Page <EduCourse> pageQuery(Integer current, Integer limit, CourseQuery courseQuery) { Page <EduCourse> page = new Page <>(current,limit); QueryWrapper <EduCourse> wrapper = new QueryWrapper <>(); String title = courseQuery.getTitle(); String subjectId = courseQuery.getSubjectId(); String subjectParentId = courseQuery.getSubjectParentId(); String teacherId = courseQuery.getTeacherId(); //判空,构造查询条件 if(!StringUtils.isEmpty(title)){ wrapper.like("title",title); } if(!StringUtils.isEmpty(subjectId)){ wrapper.eq("subject_id",subjectId); } if(!StringUtils.isEmpty(subjectParentId)){ wrapper.eq("subject_parent_id",subjectParentId); } if(!StringUtils.isEmpty(teacherId)){ wrapper.eq("teacher_id",teacherId); } wrapper.orderByDesc("gmt_create"); //进行分页查询 this.baseMapper.selectPage(page, wrapper);//分页查询后自动封装到page中 return page; } //根据id删除课程信息 @Override public void removeCourse(String id) { //1.删除小节 videoService.removeVideoByCourseId(id); //2.删除章节 chapterService.removeChapterByCourseId(id); //3.删除课程描述信息 courseDescriptionService.removeById(id); //4.删除课程信息 this.baseMapper.deleteById(id); }
五、课程列表 – 前端
1、定义api接口
//删除课程 removeCourse(id) { return request({ url: `/eduservice/course/removeCourse/${id}`, method: 'delete' }) }, //分页查询课程 pageQuery(current, limit, courseQuery) { return request({ url: `/eduservice/course/pageQuery/${current}/${limit}`, method: 'post', data: courseQuery }) }
2、 前端页面—list.vue
<template> <div class="app-container"> <!--查询表单--> <el-form :inline="true" class="demo-form-inline"> <!-- 所属分类:级联下拉列表 --> <!-- 一级分类 --> <el-form-item label="课程类别"> <el-select v-model="searchObj.subjectParentId" placeholder="请选择" @change="subjectLevelOneChanged"> <el-option v-for="subject in subjectNestedList" :key="subject.id" :label="subject.title" :value="subject.id"/> </el-select> <!-- 二级分类 --> <el-select v-model="searchObj.subjectId" placeholder="请选择"> <el-option v-for="subject in subSubjectList" :key="subject.id" :label="subject.title" :value="subject.id"/> </el-select> </el-form-item> <!-- 标题 --> <el-form-item> <el-input v-model="searchObj.title" placeholder="课程标题"/> </el-form-item> <!-- 讲师 --> <el-form-item> <el-select v-model="searchObj.teacherId" placeholder="请选择讲师"> <el-option v-for="teacher in teacherList" :key="teacher.id" :label="teacher.name" :value="teacher.id"/> </el-select> </el-form-item> <el-button type="primary" icon="el-icon-search" @click="getList()">查询</el-button> <el-button type="default" @click="resetData()">清空</el-button> </el-form> <!-- 表格 --> <el-table v-loading="listLoading" :data="list" element-loading-text="数据加载中" border fit highlight-current-row row-class-name="myClassList"> <el-table-column label="序号" width="70" align="center"> <template slot-scope="scope"> {{ (page - 1) * limit + scope.$index + 1 }} </template> </el-table-column> <el-table-column label="课程信息" width="470" align="center"> <template slot-scope="scope"> <div class="info"> <div class="pic"> <img :src="scope.row.cover" alt="scope.row.title" width="150px"> </div> <div class="title"> <a href="">{{ scope.row.title }}</a> <p>{{ scope.row.lessonNum }}课时</p> </div> </div> </template> </el-table-column> <el-table-column label="创建时间" align="center"> <template slot-scope="scope"> {{ scope.row.gmtCreate.substr(0, 10) }} </template> </el-table-column> <el-table-column label="发布时间" align="center"> <template slot-scope="scope"> {{ scope.row.gmtModified.substr(0, 10) }} </template> </el-table-column> <el-table-column label="价格" width="100" align="center" > <template slot-scope="scope"> {{ Number(scope.row.price) === 0 ? '免费' : '¥' + scope.row.price.toFixed(2) }} </template> </el-table-column> <el-table-column prop="buyCount" label="付费学员" width="100" align="center" > <template slot-scope="scope"> {{ scope.row.buyCount }}人 </template> </el-table-column> <el-table-column prop="viewCount" label="播放次数" width="100" align="center" > <template slot-scope="scope"> {{ scope.row.viewCount }}次 </template> </el-table-column> <el-table-column label="操作" width="150" align="center"> <template slot-scope="scope"> <router-link :to="'/course/info/'+scope.row.id"> <el-button type="text" size="mini" icon="el-icon-edit" >编辑课程信息</el-button> </router-link> <router-link :to="'/course/chapter/'+scope.row.id"> <el-button type="text" size="mini" icon="el-icon-edit" >编辑课程大纲</el-button> </router-link> <el-button type="text" size="mini" icon="el-icon-delete" @click="removeCourse(scope.row.id)">删除</el-button> </template> </el-table-column> </el-table> <!-- 分页 --> <el-pagination :current-page="page" :page-size="limit" :total="total" style="padding: 30px 0; text-align: center;" layout="total, prev, pager, next, jumper" @current-change="getList" /> </div> </template>
3、页面样式
<style scoped> .myClassList .info { width: 450px; overflow: hidden; } .myClassList .info .pic { width: 150px; height: 90px; overflow: hidden; float: left; } .myClassList .info .pic a { display: block; width: 100%; height: 100%; margin: 0; padding: 0; } .myClassList .info .pic img { display: block; width: 100%; } .myClassList td .info .title { width: 280px; float: right; height: 90px; } .myClassList td .info .title a { display: block; height: 48px; line-height: 24px; overflow: hidden; color: #00baf2; margin-bottom: 12px; } .myClassList td .info .title p { line-height: 20px; margin-top: 5px; color: #818181; } </style>
4、编写前端js
<script> import course from '@/api/edu/course' import subject from '@/api/edu/subject' export default { data() { return { listLoading: false, // 是否显示loading信息 list: null, // 数据列表 total: 0, // 总记录数 page: 1, // 页码 limit: 10, // 每页记录数 searchObj: { subjectParentId: '', subjectId: '', title: '', teacherId: '' }, // 查询条件 teacherList: [], // 讲师列表 subjectNestedList: [], // 一级分类列表 subSubjectList: [] // 二级分类列表, } }, created() { this.init() }, methods: { //编辑课程大纲 updateChapter(id){ this.$router.push({path:'/course/chapter/'+id}) }, //编辑课程基本信息 updateCourse(id){ this.$router.push({path:'/course/info/'+id}) }, removeCourse(id){ this.$confirm('此操作将永久删除该课程的所有内容,是否继续?','提示',{ confirmButtonText:'确定', cancelButtonText:'取消', type:'warning' }).then(()=>{//点击确定 course.removeCourse(id).then((response)=>{ this.$message({ type:'success', message:'删除成功!' }) //回到列表页面 this.getList() }).catch(()=>{ this.$message({ type:'error', message:'删除失败!' }) }) }).catch(() => { // 点击取消 this.$message({ type: 'info', message: '已取消删除!' }) }) }, //分页+条件查询 getList(page = 1){//page默认值为1,当使用分页组件时会传入新的page参数 this.page = page course.pageQuery(this.page,this.limit,this.searchObj).then(response=>{ this.list = response.data.list this.total = response.data.total }) }, //查询表单重置方法 resetData(){ this.searchObj = {}, this.subSubjectList = [] }, //当一级分类下拉菜单改变时的方法 subjectLevelOneChanged(id){ // console.log(id); for(var i = 0;i < this.subjectNestedList.length;i++){ if(this.subjectNestedList[i].id == id){ this.subSubjectList = this.subjectNestedList[i].children } } }, //初始化方法 init(){ //1.查询一级分类 subject.getAllSubject().then(response=>{ this.subjectNestedList = response.data.list }) //2.查询所有讲师 course.getTeacherList().then(response=>{ this.teacherList = response.data.items }) //3.查询课程列表 this.getList() } } } </script>
五、页面效果图
六、阿里云视频点播服务
视频点播(ApsaraVideo for VoD)是集音视频采集、编辑、上传、自动化转码处理、媒体资源管理、分发加速于一体的一站式音视频点播解决方案。
1、开通视频点播
进入阿里云官网:https://www.aliyun.com/,找到视频点播
开通视频点播服务(选择按流量计费)
2、资费说明
https://www.aliyun.com/price/product?spm=a2c4g.11186623.2.12.7fbd59b9vmXVN6#/vod/detail
3、整体流程
使用视频点播实现音视频上传、存储、处理和播放的整体流程如下:
4、视频点播服务的基本使用
完整的参考文档 https://help.aliyun.com/product/29932.html?spm=a2c4g.11186623.6.540.3c356a58OEmVZJ
服务端:后端接口
客户端:浏览器、安卓、ios
API:阿里云提供固定的地址,只需要调用这个固定的地址,向地址传递参数,实现功能。
SDK:sdk对api方式进行封装,更方便使用。之前使用EayExcel调用阿里云提供类或者接口里面的方法实现视频功能。
5、使用Java代码具体使用SDK方式
注意:因为上传视频可以进行加密,加密之后,使用加密之后的地址不能进行视频播放,所以在数据库存储不存地址,而是存储视频id。
(1)在service下创建子模块service_vod模块
POM.xml
<dependencies> <dependency> <groupId>com.aliyun</groupId> <artifactId>aliyun-java-sdk-core</artifactId> </dependency> <dependency> <groupId>com.aliyun.oss</groupId> <artifactId>aliyun-sdk-oss</artifactId> </dependency> <dependency> <groupId>com.aliyun</groupId> <artifactId>aliyun-java-sdk-vod</artifactId> </dependency> <dependency> <groupId>com.aliyun</groupId> <artifactId>aliyun-sdk-vod-upload</artifactId> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> </dependency> <dependency> <groupId>org.json</groupId> <artifactId>json</artifactId> </dependency> <dependency> <groupId>com.google.code.gson</groupId> <artifactId>gson</artifactId> </dependency> <dependency> <groupId>joda-time</groupId> <artifactId>joda-time</artifactId> </dependency> </dependencies>