• 直播课堂系统10--腾讯云点播管理模块(二)


    功能:创建课程大纲

    此时已经完成第一个功能:填写课程基本信息,开始做第二个:创建课程大纲。
    因为这一部分需要对Video做读取,所以需要创建Video的mapper service xml impl,全部先为空。

    @Mapper
    public interface VideoMapper extends BaseMapper<Video> {
    }
    
    • 1
    • 2
    • 3
    public interface VideoService extends IService<Video> {
    }
    
    • 1
    • 2
    @Service
    public class VideoServiceImpl extends ServiceImpl<VideoMapper, Video> implements VideoService {
    }
    
    • 1
    • 2
    • 3

    课程章节接口

    实现课程章节的列表,增删改查功能

    mapper

    起手创建mapper和xml

    @Mapper
    public interface ChapterMapper extends BaseMapper<Chapter> {
    }
    
    
    • 1
    • 2
    • 3
    • 4

    service

    创建service接口并且声明方法

    public interface ChapterService extends IService<Chapter> {
        //章节小结列表
        List<ChapterVo> getNestedTreeList(Long courseId);
    }
    
    • 1
    • 2
    • 3
    • 4

    impl实现方法

    @Service
    public class ChapterServiceUImpl extends ServiceImpl<ChapterMapper, Chapter> implements ChapterService {
        @Autowired
        private ChapterMapper chapterMapper;
        @Autowired
        private VideoService videoService;
        //章节小结列表封装
        @Override
        public List<ChapterVo> getNestedTreeList(Long courseId) {
            List<ChapterVo> chapterVos = new ArrayList<>();
            //获取章信息
            LambdaQueryWrapper<Video> queryWrapperVideo = new LambdaQueryWrapper<>();
            queryWrapperVideo.eq(Video::getCourseId,courseId);
            //按照sort排序 sort一样的按照id排
            queryWrapperVideo.orderByAsc(Video::getSort,Video::getId);
            //将查询出的章节作为list合集
            List<Chapter> chapters = chapterMapper.selectList(queryWrapperVideo);
    
            //获取课时信息 要从Video表里查 故声明其service
            LambdaQueryWrapper<Video> videoLambdaQueryWrapper = new LambdaQueryWrapper<>();
            videoLambdaQueryWrapper.eq(Video::getCourseId,courseId);
            videoLambdaQueryWrapper.orderByAsc(Video::getSort,Video::getId);
            List<Video> videoList = videoService.list(videoLambdaQueryWrapper);
    
            //填充Vo的数据 因为返回的是vo
            for(int i=0;i<chapters.size();i++){
                //首先取出里面的每个章节
                Chapter chapter = chapters.get(i);
                //创建一个vo对象 并加入要返回的list
                ChapterVo chapterVo = new ChapterVo();
                BeanUtils.copyProperties(chapter,chapterVo);
                chapterVos.add(chapterVo);
    
                //填充列表数据:video列表 一个章节含有多个视频
                List<VideoVo> videoVoList = new ArrayList<>();
                for(int j=0;j<videoList.size();j++){
                    Video video = videoList.get(j);
                    //emmm 对里面所有video进行判断 如果是这个章节的就进行操作...好弱智的逻辑
                    if(chapter.getId().equals(video.getChapterId())){
                        VideoVo videoVo = new VideoVo();
                        BeanUtils.copyProperties(video,videoVo);
                        videoVoList.add(videoVo);
                    }
                }
                //章节下的课时列表
                chapterVo.setChildren(videoList);
            }
            return chapterVos;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50

    controller

    编写章节controller,注意其增删改都可以直接调API实现,查询的时候因为要查列表展示到前端所以要自己写。

    @RestController
    @RequestMapping(value = "/admin/vod/chapter")
    @CrossOrigin
    public class ChapterController {
        @Autowired
        private ChapterService chapterService;
    
        //获取章节小结列表
        @ApiOperation("嵌套章节数据列表")
        @GetMapping("getNestedTreeList/{courseId}")
        public Result getNestedTreeList(
                @ApiParam(value = "课程ID",required = true)
                @PathVariable Long courseId) {
            List<ChapterVo> nestedTreeList = chapterService.getNestedTreeList(courseId);
            return Result.ok(nestedTreeList);
        }
        
        //添加章节
        @PostMapping("save")
        public Result save(@RequestBody Chapter chapter){
            chapterService.save(chapter);
            return Result.ok(null);
        }
        
        //修改-根据id查询
        @GetMapping("get/{id}")
        public Result get(@PathVariable Long id){
            Chapter chapter = chapterService.getById(id);
            return Result.ok(chapter);
        }
        //修改-实现查询
        @PostMapping("update")
        public Result update(@RequestBody Chapter chapter){
            chapterService.updateById(chapter);
            return Result.ok(null);
        }
        //删除章节
        @DeleteMapping("remove/{id}")
        public Result remove(@PathVariable Long id){
            chapterService.removeById(id);
            return Result.ok(null);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43

    课程小节接口

    编写controller

    因为小节指的就是视频了,所以编写的为VideoController。

    @Api(tags = "课程小结(课时)")
    @RestController
    @RequestMapping(value = "/admin/vod/video")
    @CrossOrigin
    public class VideoController {
        @Autowired
        private VideoService videoService;
    
        //获取视频
        @ApiOperation(value = "获取")
        @GetMapping("get/{id}")
        public Result get(@PathVariable Long id){
            Video video = videoService.getById(id);
            return Result.ok(video);
        }
    
        //新增视频
        @ApiOperation(value = "新增")
        @PostMapping("save")
        public Result save(@RequestBody Video video){
            videoService.save(video);
            return Result.ok(null);
        }
    
        //修改视频
        @ApiOperation(value = "修改")
        @PutMapping("update")
        public Result updateById(@RequestBody Video video) {
            videoService.updateById(video);
            return Result.ok(null);
        }
    
        //删除视频
        @ApiOperation(value = "删除")
        @DeleteMapping("remove/{id}")
        public Result remove(@PathVariable Long id) {
            videoService.removeById(id);
            return Result.ok(null);
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41

    前端

    定义和后端交互的接口,首先定义chapter.js

    import request from '@/utils/request'
    const api_name = '/admin/vod/chapter'
    export default {
      getNestedTreeList(courseId) {
        return request({
          url: `${api_name}/getNestedTreeList/${courseId}`,
          method: 'get'
        })
      },
      removeById(id) {
        return request({
          url: `${api_name}/remove/${id}`,
          method: 'delete'
        })
      },
      save(chapter) {
        return request({
          url: `${api_name}/save`,
          method: 'post',
          data: chapter
        })
      },
      getById(id) {
        return request({
          url: `${api_name}/get/${id}`,
          method: 'get'
        })
      },
      updateById(chapter) {
        return request({
          url: `${api_name}/update`,
          method: 'put',
          data: chapter
        })
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36

    然后创建video.js

    import request from '@/utils/request'
    const api_name = '/admin/vod/video'
    export default {
      save(video) {
        return request({
          url: `${api_name}/save`,
          method: 'post',
          data: video
        })
      },
      getById(id) {
        return request({
          url: `${api_name}/get/${id}`,
          method: 'get'
        })
      },
      updateById(video) {
        return request({
          url: `${api_name}/update`,
          method: 'put',
          data: video
        })
      },
      removeById(id) {
        return request({
          url: `${api_name}/remove/${id}`,
          method: 'delete'
        })
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30

    然后编写章节的页面,在views/vod/course/components/Chapter/下填充index.vue组件和Form.vue组件,然后在同级的Video下添加Form.vue组件
    代码实在太多了,还都是前端,懒得看了,也不放上来了。

    效果

    在这里插入图片描述

    发布课程-课程最终发布

    mapper

    编写CouseMapper

    @Mapper
    public interface CourseMapper extends BaseMapper<Course> {
        //根据id获取课程发布信息
        CoursePublishVo selectCoursePublishVoById(Long id);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    编写xml文件

    这么久,第一次碰到xml文件可以写…感动。
    subject_id是一级分类 subject_parent_id是二级分类
    #{id}是方法传过来的id

    
    DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    <mapper namespace="vod.mapper.CourseMapper">
    
        <select id="selectCoursePublishVoById" resultType="vo.vod.CoursePublishVo">
            SELECT
                c.id,
                c.title,
                c.cover,
                c.lesson_num AS lessonNum,
                c.price,
                t.name AS teacherName,
                s1.title AS subjectParentTitle,
                s2.title AS subjectTitle
            FROM 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
            WHERE c.id=#{id}
        select>
    mapper>
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    Service

    在Service里添加方法

        //根据ID获取课程发布信息
        CoursePublishVo getCoursePublishVo(Long id);
        //根据ID发布课程
        boolean publishCourseById(Long id);
    
    • 1
    • 2
    • 3
    • 4

    impl

    在impl里实现这两个方法,很奇怪,其实新增的方法之前不是写过了吗…研究了一下,应该是补全了一下其他的字段…因为最后用的是update

        //根据id获取课程发布信息
        @Override
        public CoursePublishVo getCoursePublishVo(Long id) {
            return courseMapper.selectCoursePublishVoById(id);
        }
        
        //根据id发布课程
        @Override
        public boolean publishCourseById(Long id) {
            Course course = new Course();
            course.setId(id);
            course.setPublishTime(new Date());
            course.setStatus(1);
            return this.updateById(course);
        }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    编写Controller

        @ApiOperation("根据id获取课程发布信息")
        @GetMapping("getCoursePublishVo/{id}")
        public Result getCoursePublishVoById(
                @ApiParam(value = "课程ID", required = true)
                @PathVariable Long id){
            CoursePublishVo coursePublishVo = courseService.getCoursePublishVo(id);
            return Result.ok(coursePublishVo);
        }
        @ApiOperation("根据id发布课程")
        @PutMapping("publishCourseById/{id}")
        public Result publishCourseById(
                @ApiParam(value = "课程ID", required = true)
                @PathVariable Long id){
            boolean result = courseService.publishCourseById(id);
            return Result.ok(null);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    移动mapper

    原本mapper写在resource外面的话需要添加配置,但我这边半天不成功,直接把mapper移到resource里面就一劳永逸了。
    在这里插入图片描述

    前端

    首先在api的course.js里定义接口

    //获取发布课程信息  
    getCoursePublishById(id) {
       return request({
         url: `${api_name}/getCoursePublishVo/${id}`,
         method: 'get'
       })
    },
    //发布课程  
    publishCourseById(id) {
       return request({
         url: `${api_name}/publishCourseById/${id}`,
         method: 'put'
       })
    },
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    再编写view/vod/course/components/Publish.vue,直接开抄,懒得看了。

    效果

    在这里插入图片描述
    在这里插入图片描述
    点完发布后咋跳404了,去改一下,跳回原来的数据列表。
    将Publish.vue的这里的路由修改成/course/list路由
    在这里插入图片描述

    功能实现-课程删除

    为了做前面的测试添加了好多课程,现在都删了吧。
    需要删除的东西有很多:小节(video) 章节(chapter)章节描述(description)课程(Course)

    编写ChapterService

        //根据课程id删除章节
        @Override
        public void removeChapterByCourseId(Long id){
            QueryWrapper<Chapter> wrapper = new QueryWrapper<>();
            wrapper.eq("course_id",id);
            chapterMapper.delete(wrapper);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    编写VideoService

        @Override
        public void removeVideoByCourseId(Long id) {
            QueryWrapper<Video> wrapper = new QueryWrapper<>();
            wrapper.eq("course_id",id);
            baseMapper.delete(wrapper);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    编写课程Service

        @Autowired
        private VideoService videoService;
        @Autowired
        private ChapterService chapterService;
        @Autowired
        private CourseDescriptionService courseDescriptionService;
        @Override
        public void removeCourseById(Long id) {
            //根据课程id删除小节
            videoService.removeVideoByCourseId(id);
            //根据课程id删除章节
            chapterService.removeChapterByCourseId(id);
            //根据课程id删除描述
            courseDescriptionService.removeById(id);
            //根据课程id删除课程
            courseMapper.deleteById(id);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    编写课程controller

        @ApiOperation(value = "删除课程")
        @DeleteMapping("remove/{id}")
        public Result remove(@PathVariable Long id){
            courseService.removeCourseById(id);
            return Result.ok(null);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    前端

    在course.js里定义接口

    removeById(id) {
        return request({
          url: `${api_name}/remove/${id}`,
          method: 'delete'
        })
      },
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    在course里的list.vue里添加方法

    // 根据id删除数据
        removeById(id) {
          this.$confirm('此操作将永久删除该课程,以及该课程下的章节和视频,是否继续?', '提示', {
            confirmButtonText: '确定',
            cancelButtonText: '取消',
            type: 'warning'
          }).then(() => {
            return courseApi.removeById(id)
          }).then(response => {
            this.fetchData()
            this.$message.success(response.message)
          }).catch((response) => { // 失败
            if (response === 'cancel') {
              this.$message.info('取消删除')
            }
          })
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
  • 相关阅读:
    R语言使用epiDisplay包的lsNoFunction函数列出当前空间中的所有对象、除了用户自定义的函数对象
    SAP UI5 应用开发教程之一百零三 - 如何在 SAP UI5 应用中消费第三方库试读版
    SpringSecurity6 | 核心过滤器
    递归&回溯&剪枝-括号生成
    数据看板的动态截图推送方案
    项目记录:使用SpringBoot + MyBatisPlus 在MySQL字段设置外键后ID自增失效导致添加失败问题(ID生成策略)
    Python编程学习第一篇——制作一个小游戏休闲一下
    DOM节点(节点查找、节点创建、节点克隆、节点删除)
    Javafx集成sqlite数据库
    中小企业如何做网络安全? 避免这 8 个容易被黑客利用的基本错误
  • 原文地址:https://blog.csdn.net/z754916067/article/details/126263307