栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

直播课堂系统09--腾讯云点播管理模块(一)

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

直播课堂系统09--腾讯云点播管理模块(一)

目录
  • 点播管理模块
    • 需求
    • 数据库相关表
    • 环境搭建
  • 功能实现-课程列表
    • 创建mapper
    • 编写service
    • 编写controller
    • 课程列表前端
      • index.js
      • api
      • vue的list编写
    • 效果
  • 功能实现-发布课程-填写课程基本信息
    • 创建mapper
    • 创建service
    • controller
    • 前端
    • 效果
  • 功能实现:修改课程基本信息
    • 修改Service
    • impl实现
    • controller实现
    • 前端实现

说是点播模块,其实就是继续写后端的curd…

点播管理模块 需求

添加点播课程,包含课程基本信息,课程章节,课程小结和最终发布

数据库相关表

环境搭建

以下全都是代码生成器生成,这些我自己写,截图记录一下格式。

功能实现-课程列表

首先实现分页条件查询点播课程的功能,大体如下

创建mapper

继续创建mapper和一个空的xml

@Mapper
public interface CourseMapper extends BaseMapper {
}
编写service

首先创建一个CourseService接口,在service接口里面声明分页查询方法

public interface TeacherService extends IService {
    //分页获取课程列表 CourseQueryVo是因为只取需要的
    Map findPage(Page pageParam, CourseQueryVo courseQueryVo)
}

然后编写impl,记住impl首先extends在implements

@Service
public class CourseServiceImpl extends ServiceImpl implements CourseService  {

    @Autowired
    private CourseService courseService;
    @Autowired
    private TeacherService teacherService;
    @Autowired
    private SubjectService subjectService;
    @Override
    public Map findPage(Page pageParam, CourseQueryVo courseQueryVo) {
        //获取Vo里面的各种属性
        String title = courseQueryVo.getTitle();//名称
        Long subjectId = courseQueryVo.getSubjectId();//二级分类
        Long subjectParentId = courseQueryVo.getSubjectParentId();//一级分类
        Long teacherId = courseQueryVo.getTeacherId();//讲师

        //封装条件
        QueryWrapper wrapper = new QueryWrapper<>();
        //判断字符串是否为空
        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);
        }

        //调用方法查询
        Page pages = baseMapper.selectPage(pageParam, wrapper);
        long totalCount = pages.getTotal();//总记录数
        long totalPage = pages.getPages();//总页数
        long currentPage = pages.getCurrent();//当前页
        long size = pages.getSize();//每页记录数
        //每页数据集合
        List records = pages.getRecords();
        //将集合进行封装
        records.stream().forEach(item ->{
            //根据集合里的存储获取其讲师和分类的名称
            this.getTeacherOrSubjectName(item);
        });
        //封装返回数据
        HashMap map = new HashMap<>();
        map.put("totalCount",totalCount);
        map.put("totalPage",totalPage);
        map.put("records",records);
        return map;
    }
    //获取讲师和分类名称
    private Course getTeacherOrSubjectName(Course course){
        //因为查询出来的是course 所以肯定也要传入course
        //从其他的数据库里查询讲师和分类的具体名称
        Teacher teacher = teacherService.getById(course.getTeacherId());
        if(teacher!=null){
            //course继承的是BaseEntity 有一个其他参数为Map param
            //将其加入其中,需要多表连接查询时便这样使用
            course.getParam().put("teacherName",teacher.getName());
        }
        //查询分类名称
        Subject subjectOne = subjectService.getById(course.getSubjectParentId());
        if(subjectOne != null) {
            course.getParam().put("subjectParentTitle",subjectOne.getTitle());
        }
        Subject subjectTwo = subjectService.getById(course.getSubjectId());
        if(subjectTwo != null) {
            course.getParam().put("subjectTitle",subjectTwo.getTitle());
        }
        return course;
    }
}
编写controller

创建CourseController.java,注意刚加载时这里传入的Vo里面全都是null,所以传到service里面后,会变成查询所有。
Course本身已经与对应的数据库表绑定,所以由它构建QueryWrapper可以直接在对应表中进行查询。无论数据库表里有多少列,都会按定义的model的列返回,其余的列不会被返回。

@Api(tags = "课程管理接口")
@RestController
@CrossOrigin
@RequestMapping(value = "/admin/vod/course")
public class CourseController {
    @Autowired
    private CourseService courseService;

    @ApiOperation(value = "获取分页列表")
    @GetMapping("{page}/{limit}")
    public Result index(
            @ApiParam(name = "page", value = "当前页码", required = true)
            @PathVariable Long page,
            @ApiParam(name = "limit", value = "每页记录数", required = true)
            @PathVariable Long limit,
            @ApiParam(name = "courseVo", value = "查询对象", required = false)
                    CourseQueryVo courseQueryVo){
        //根据传入的page和limit构建page对象
        Page coursePage = new Page<>(page, limit);
        //将其传入方法中进行填充 并返回
        Map map = courseService.findPage(coursePage, courseQueryVo);
        return Result.ok(map);
    }
}
课程列表前端

首先在router下的index.js添加前端路径,再在api里添加调用后端接口的方法,再在views里面写组件且调用api里的方法。

index.js

在router下的index.js下添加路由

  //课程管理
  {
    path: '/vod',
    component: Layout,
    redirect: '/vod/course/list',
    name: 'Vod',
    meta: {
      title: '点播管理',
      icon: 'el-icon-bank-card'
    },
    alwaysShow: true,
    children: [
      {
        path: 'course/list',
        name: 'CourseList',
        component: () => import('@/views/vod/course/list'),
        meta: { title: '课程列表' }
      },
    ]
  },
api

在api目录创建路由文件course.js

import request from '@/utils/request'
const api_name = 'admin/vod/course'

export default{
    //课程列表
    getPageList(page,limit,searchObj){
        return request({
            //写的是后端路径
            url:`${api_name}/${page}/${limit}`,
            method: 'get',
            params: searchObj
        })
    },
}

在teacher.js里面定义一个获取所有讲师,以list形式返回的接口,之前在controller里面写过,不要和分页查询搞混。

    //获取所有讲师 不分页
    list(){
        return request({
            url:`${api_name}/findAll`,
            method:`get`
        })
    },
vue的list编写

再编写index.js里的/views/vod/course/list页面,代码也太多了,整整两百多行,复制粘贴后读一下吧…
实在摆不上来了,就这样吧。

效果

功能实现-发布课程-填写课程基本信息

发布课程一共有三个流程:填写课程基本信息,创建课程大纲-发布课程,这里实现第一个功能:填写课程基本信息。
每个课程都有自己的描述,并且也会经常更新,故创建一个数据库表course_description

创建mapper

创建mapper并且将其与CourseDescription模型绑定,以后使用这个mapper进行的搜索都会在其model映射的table里。

public interface CourseDescriptionMapper extends BaseMapper {
}

不要忘记建对应的xml,虽然是空的。







创建service

创建service接口,然后创建其实现impl,记住实例化对应的mapper进行查询操作。
写到这里时悟了,之前的model分为model和vo,其中model对应的是数据库表,vo对应的是前端传来的数据,将其用一个model接收。

public interface CourseDescriptionService extends IService {
    //返回新建课程的基本ID
    public Long saveCourseInfo(CourseFormVo vo);
}

实现impl

@Service
public class CourseDescriptionImpl extends ServiceImpl implements CourseDescriptionService {
    //声明mapper
    @Autowired
    private CourseDescriptionMapper courseDescriptionMapper;
    //声明别家mapper 因为需要插入它的数据库
    @Autowired
    private CourseMapper courseMapper;
    //将获得的vo信息传入数据库中并存储 需要插入的表用:course表 courseDescription表
    @Override
    public Long saveCourseInfo(CourseFormVo vo) {
        Course course = new Course();
        //把传入的vo复制给course
        BeanUtils.copyProperties(vo,course);
        //插入course数据库
        courseMapper.insert(course);

        //插入coursedescription
        CourseDescription courseDescription = new CourseDescription();
        //研究了一下为什么直接转 然后发现命名不太一样...上面的course是一样的
        courseDescription.setDescription(vo.getDescription());
        courseDescription.setCourseId(course.getId());
        //插入数据库
        //descriptionService.save(courseDescription); 笔记里用的是这句 我感觉用mapper好一点吧。
        courseDescriptionMapper.insert(courseDescription);
        
        //返回课程id
        return course.getId();
    }
}
controller

这部分代码很坑,它service和mapper都是分开建的,但是课程添加,竟然是写在CourseController里,研究了下是因为在CourseService里面要做到对Description表的修改,按编码规范来说,需要注入其service,所以要将Description的类创建到Service层次,故对前面进行大改。

现在更改CourseController.java

    @ApiOperation(value = "新增")
    @PostMapping("save")
    public Result save(@RequestBody CourseFormVo vo){
        Long id = courseService.saveCourseInfo(vo);
        return Result.ok(id);
    }
前端

在index.js里面修改路由

      {
        path: 'course/info',
        name: 'CourseInfo',
        component: () => import('@/views/vod/course/form'),
        meta: { title: '发布课程' },
        hidden: true
      },

同时,在课程列表的界面也有添加键触发跳转,所以那里也要加上。

    add() {
      //跳转到的应该是路由 不是界面
      this.$router.push({ path: 'course/info' })
    },

跳转的应该是index.js里面定义的路由
在api的course.js里定义接口,注意这里不能按笔记一样写在params里,这样后端接收不到,因为后端接收的是RequestBody,必须把它放在data里!

    saveCourseInfo(courseInfo){
        return request({
            //写的是后端路径
            url:`${api_name}/save`,
            method: `post`,
            // params: courseInfo
            data: courseInfo
        })
    },

创建index.js里面指向的course/form.vue


注意这里要获取路由名字,所以要在前面的index.js里面添加,在created()时能跳转到对应界面。

      {
        path: 'course/info',
        name: 'CourseInfo',
        component: () => import('@/views/vod/course/form'),
        meta: { title: '发布课程' },
        hidden: true
      },
      {
        path: 'course/info/:id',
        name: 'CourseInfoEdit',
        component: () => import('@/views/vod/course/form'),
        meta: { title: '编辑课程' },
        hidden: true
      },
      {
        path: 'course/chapter/:id',
        name: 'CourseChapterEdit',
        component: () => import('@/views/vod/course/form'),
        meta: { title: '编辑大纲' },
        hidden: true
      },


注意一下上面引入了三个组件Info Chapter Publish
其组件关系如下

代码太长直接解读一下。


效果

功能实现:修改课程基本信息

这个功能实现修改回显,即假如已经填写好基本信息并且点击保存,此时又想回退修改的情景。

修改Service

首先在CourseService接口里面添加对应的方法。

    //根据ID获取课程信息
    CourseFormVo getCourseFormVoById(long id);
    //根据ID修改课程信息
    void updateCourseById(CourseFormVo courseFormVo);
impl实现
    //根据id获取课程信息
    @Override
    public CourseFormVo getCourseFormVoById(long id) {
        //首先拿着id去数据库查数据 查到对应的课程
        Course course = courseMapper.selectById(id);
        if(course==null) return null;
        //从course_description表取数据
        //需要注意的是在course_description表里,课程id的存储方式是course_id 而非id 所以不能使用getById方法
        //需要建一个wapper 用eq
//        CourseDescription byId = courseDescriptionService.getById(id);
        QueryWrapper QueryWrapper = new QueryWrapper<>();
        QueryWrapper.eq("course_id",id);
        CourseDescription description = courseDescriptionService.getOne(QueryWrapper);
        //创建Form对象 因为要返回前端
        CourseFormVo courseFormVo = new CourseFormVo();
        BeanUtils.copyProperties(course,courseFormVo);
        if(description!=null){
            courseFormVo.setDescription(description.getDescription());
        }
        return courseFormVo;
    }

    //根据id修改课程信息
    @Override
    public void updateCourseById(CourseFormVo courseFormVo) {
        //获取课程
        Course course = new Course();
        BeanUtils.copyProperties(courseFormVo,course);
        //需要传入一个实体 根据这个实体的id更新
        courseMapper.updateById(course);

        //修改课程详情信息 同理如上 不能直接getid 修改的有详情和课程id
        QueryWrapper QueryWrapper = new QueryWrapper<>();
        QueryWrapper.eq("course_id",courseFormVo.getid());
        CourseDescription description = courseDescriptionService.getOne(QueryWrapper);
        
        description.setDescription(courseFormVo.getDescription());
        description.setId(course.getId());

        //更新上去 同理不能用updateById
        QueryWrapper.eq("course_id",description.getid());
        courseDescriptionService.update(QueryWrapper);
    }
controller实现
    @ApiOperation(value = "获取")
    @GetMapping("get/{id}")
    public Result get(@PathVariable Long id) {
        CourseFormVo course = courseService.getCourseFormVoById(id);
        return Result.ok(course);
    }
    @ApiOperation(value = "修改")
    @PutMapping("update")
    public Result updateById(@RequestBody CourseFormVo courseFormVo) {
        courseService.updateCourseById(courseFormVo);
        return Result.ok(null);
    }
前端实现

在api的course.js里定义连接后端的方法

    //id获取课程信息
    getCourseInfoById(id) {
        return request({
        url: `${api_name}/get/${id}`,
        method: 'get'
        })
    },
    //修改课程信息
    updateCourseInfoById(courseInfo) {
        return request({
        url: `${api_name}/update`,
        method: 'put',
        data: courseInfo
        })
    },

再修改info.vue界面,里面写具体的更新方法

  created() {
    if(this.$parent.courseId){
      // 回显 如果带有courseId 说明是从下一个步骤里回来的 只有在上一个步骤里点击保存 才能带有一个保存的courseId 先加载它的信息并修改就完事
      this.fetchCourseInfoById(this.$parent.courseId)
    }else{ //新增
      // 初始化分类列表
      this.initSubjectList()
    }
    // 获取讲师列表
    this.initTeacherList()
  },
    // 获取课程信息
    fetchCourseInfoById(id) {
      courseApi.getCourseInfoById(id).then(response => {
        this.courseInfo = response.data
        // 初始化分类列表
        subjectApi.getChildList(0).then(response => {
          this.subjectList = response.data
          // 填充二级菜单:遍历一级菜单列表,
          this.subjectList.forEach(subject => {
            // 找到和courseInfo.subjectParentId一致的父类别记录
            if (subject.id === this.courseInfo.subjectParentId) {
              // 拿到当前类别下的子类别列表,将子类别列表填入二级下拉菜单列表
              subjectApi.getChildList(subject.id).then(response => {
                this.subjectLevelTwoList = response.data
              })
            }
          })
        })
      })
    },
    // 保存并下一步
    saveAndNext() {
      this.saveBtnDisabled = true
      if (!this.$parent.courseId) {
        this.saveData()
      } else {
        this.updateData()
      }
    },
    // 修改
    updateData() {
      courseApi.updateCourseInfoById(this.courseInfo).then(response => {
        this.$message.success(response.message)
        this.$parent.courseId = response.data // 获取courseId
        this.$parent.active = 1 // 下一步
      })
    },
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/1041155.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号