3课程管理模块
三课程管理模块
1具体功能
 1.1章节增删改查
 1.2小节增删改查
 1.3视频上传删除
 1.4课程增删改查
 1.4.1查询课程
- 
条件查询加分页 
- 
课程列表(前端主页,基本信息)(封面,课程信息(课程名字,课程分类),讲师,价格,课程状态(已/未发布),发布时间,操作(修该基本信息,编辑大纲,课程统计,删除)) 
 1.4.2课程增加(三步)
- 填写课程基本信息(标题,讲师,一/二级分类,课程简介,封面)
- 创建课程大纲(添加章节,添加小节(同时添加课程,包括是否免费))
- 最终发布(确认信息将未发布改成已发布)
 1.4.3课程修改
- 根据id跳转到课程增加页面
- 修改基本信息
- 修改章节和对应小节
 1.4.4课程删除
- 删除所有章节
- 删除所有小节
 1.5课程统计
- 根据开始时间到结束时间查看观看课程人数统计
2具体知识点
 2.1数据库表关系
 2.2腾讯云点播
- 开通云点播服务
- 前端集成
- 后端引入相关依赖
- 第一步:申请上传签名
- 1创建Signature类(腾讯云有)
- 2里面的getUploadSignature方法获得签名
 
- 第二步:设置腾讯云API秘钥
- 第三步:SDK上传
- 直接使用示例demo
 
 2.2(2)阿里云点播
- 第一步:开通云点播服务
- 第二步:引入相关依赖
- 第三步:初始化操作
- 创建defaultandclient对象(点播服务接入区域,accessKeyId, accessKeySecret)
 
- 第四步:实现将文件转成流,然后调用阿里云sdk的方法
- 第五步:实现根据视频id获取视频播放凭证的方法
- 第六步:前端实现(需要视频id,播放凭证)
 2.3上传视频具体代码(阿里云)
- 
controller 
- 
//上传视频到阿里云 @PostMapping("uploadAlyiVideo") public R uploadAlyiVideo(MultipartFile file) { //返回上传视频id String videoId = vodService.uploadVideoAly(file); return R.ok().data("videoId",videoId); }
- 
service 
- 
@Override public String uploadVideoAly(MultipartFile file) { try { //注意,将文件转成流 //accessKeyId, accessKeySecret //fileName:上传文件原始名称 有可能是01.03.09.mp4 String fileName = file.getOriginalFilename(); //title:上传之后显示名称 可以和上面一样 但是我们希望还是不带.mp4 String title = fileName.substring(0, fileName.lastIndexOf(".")); //inputStream:上传文件输入流 InputStream inputStream = file.getInputStream(); UploadStreamRequest request = new UploadStreamRequest(ConstantVodUtils.ACCESS_KEY_ID, ConstantVodUtils.ACCESS_KEY_SECRET, title, fileName, inputStream); UploadVideoImpl uploader = new UploadVideoImpl(); UploadStreamResponse response = uploader.uploadStream(request); String videoId = null; if (response.isSuccess()) { videoId = response.getVideoId(); } else { //如果设置回调URL无效,不影响视频上传,可以返回VideoId同时会返回错误码。其他情况上传失败时,VideoId为空,此时需要根据返回错误码分析具体错误原因 videoId = response.getVideoId(); } return videoId; }catch(Exception e) { e.printStackTrace(); return null; } }
- 
根据视频id获取视频播放凭证(之后前台会用到) 
- 
//根据视频id获取视频凭证 @GetMapping("getPlayAuth/{id}") public R getPlayAuth(@PathVariable String id) { try { System.out.println(id); //创建初始化对象 DefaultAcsClient client = InitVodCilent.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.4根据课程id查询章节和小节(大纲列表)
- 
@Override public List<ChapterVo> getTreeList(Long courseId) { //1定义最终数据list集合 List<ChapterVo> finalChapterList = new ArrayList<>(); //2根据courseId获取课程里面所有章节 QueryWrapper<Chapter> wrapperChapter = new QueryWrapper<>(); wrapperChapter.eq("course_id",courseId); List<Chapter> chapterList = baseMapper.selectList(wrapperChapter); //3根据courseId获取课程里面所有小节 //换一种方式,Lambda表达方式 LambdaQueryWrapper<Video> wrapperVideo = new LambdaQueryWrapper<>(); wrapperVideo.eq(Video::getCourseId,courseId); List<Video> videoList = videoService.list(wrapperVideo); //4封装章节 //遍历所有章节 for (int i = 0; i < chapterList.size(); i++) { //得到课程每个章节 Chapter chapter = chapterList.get(i); // chapter -- ChapterVo ChapterVo chapterVo = new ChapterVo(); BeanUtils.copyProperties(chapter,chapterVo); //得到每个章节对象放到finalChapterList集合 finalChapterList.add(chapterVo); //5封装章节里面小节 //创建list集合用户封装章节所有小节 List<VideoVo> videoVoList = new ArrayList<>(); //遍历小节list for (Video video:videoList) { //判断小节是哪个章节下面 //章节id 和 小节chapter_id if(chapter.getId().equals(video.getChapterId())) { // video -- VideoVo VideoVo videoVo = new VideoVo(); BeanUtils.copyProperties(video,videoVo); //放到videoVoList videoVoList.add(videoVo); } } //6把章节里面所有小节集合放到每个章节里面 chapterVo.setChildren(videoVoList); } //7返回最终章节集合 return finalChapterList; }
2.5根据课程id查询课程详情
- 
因为有讲师,还有课程分类,涉及多表,所以要自己写xml 
- 
<!--//根据课程id查询课程详情--> <select id="selectCourseVoById" resultType="com.fao.ggkt.vo.vod.CourseVo"> SELECT c.id, c.title, c.lesson_num AS lessonNum, c.price, c.cover, c.buy_count AS buyCount, c.view_count AS viewCount, c.status, c.publish_time AS publishTime, c.teacher_id AS teacherId, t.name AS teacherName, s1.title AS subjectParentTitle, s2.title AS subjectTitle FROM <include refid="tables"></include> WHERE c.id=#{id} </select> <sql id="tables"> course c LEFT OUTER JOIN teacher t ON c.teacher_id=t.id LEFT OUTER JOIN `subject` s1 ON c.subject_parent_id=s1.id LEFT OUTER JOIN `subject` s2 ON c.subject_id=s2.id </sql>
2.6删除课程(一起删)
- 
@Override public void removeCourseId(Long id) { //根据课程id删除小节 videoService.removeVideoByCourseId(id); //根据课程id删除章节 chapterService.removeChapterByCourseId(id); //根据课程id删除课程描述 descriptionService.removeById(id); //根据课程id删除课程 baseMapper.deleteById(id); }
2.7课程统计
- 
后端三个参数:courseId, startDate, endDate 
- 
返回两个list,一个代表所有日期,一个代表日期对应数量 
- 
//课程统计的接口 @Override public Map<String, Object> findCount(Long courseId, String startDate, String endDate) { //调用mapper的方法 List<VideoVisitorCountVo> videoVisitorVoList = baseMapper.findCount(courseId,startDate,endDate); //创建map集合 Map<String, Object> map = new HashMap<>(); //创建两个list集合,一个代表所有日期,一个代表日期对应数量 //封装数据 代表所有日期 List<String> dateList = videoVisitorVoList.stream().map(VideoVisitorCountVo::getJoinTime). collect(Collectors.toList()); //代表日期对应数量 List<Integer> countList = videoVisitorVoList.stream().map(VideoVisitorCountVo::getUserCount) .collect(Collectors.toList()); //放到map集合 map.put("xData", dateList); map.put("yData", countList); return map; }
- 
xml 
- 
public interface VideoVisitorMapper extends BaseMapper<VideoVisitor> { //课程统计的接口 List<VideoVisitorCountVo> findCount(@Param("courseId") Long courseId, @Param("startDate")String startDate, @Param("endDate")String endDate); }
- 
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.fao.ggkt.vod.mapper.VideoVisitorMapper"> <select id="findCount" resultType="com.fao.ggkt.vo.vod.VideoVisitorCountVo"> SELECT DATE(join_time) AS joinTime, COUNT(*) AS userCount FROM video_visitor <where> <if test="startDate != null and startDate != ''"> AND DATE(join_time) >= #{startDate} </if> <if test="endDate != null and endDate != ''"> AND DATE(join_time) <= #{endDate} </if> and course_id=#{courseId} </where> GROUP BY DATE(join_time) ORDER BY DATE(join_time) </select> </mapper>
- 
转成具体sql 
- 
SELECT DATE(join_time) AS joinTime, COUNT(*) AS userCount FROM video_visitor where DATE(join_time) >= '2001-11-22' AND DATE(join_time) <= '2031-11-22 13:39:27' and course_id=1 GROUP BY DATE(join_time) ORDER BY DATE(join_time)
- 
前端安装ECharts组件 
 
                    
                     
                    
                 
                    
                

 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号