当前位置:网站首页>Live Classroom System 09--Tencent Cloud VOD Management Module (1)

Live Classroom System 09--Tencent Cloud VOD Management Module (1)

2022-08-10 21:26:00 z754916067


Said to be an on-demand module,In fact, it is to continue to write the backendcurd…

点播管理模块

需求

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

在这里插入图片描述

数据库相关表

在这里插入图片描述

环境搭建

The following are all generated by the code generator,I write these myself,Take a screenshot to record the format.请添加图片描述

功能实现-课程列表

First, implement the function of querying on-demand courses with paging conditions,大体如下
在这里插入图片描述

创建mapper

继续创建mapper和一个空的xml

@Mapper
public interface CourseMapper extends BaseMapper<Course> {
    
}

编写service

首先创建一个CourseService接口,在serviceThe interface declares the paging query method

public interface TeacherService extends IService<Teacher> {
    
    //Paginate to get a list of courses CourseQueryVoBecause only what is needed
    Map<String,Object> findPage(Page<Course> pageParam, CourseQueryVo courseQueryVo)
}

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

@Service
public class CourseServiceImpl extends ServiceImpl<CourseMapper, Course> implements CourseService  {
    

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

        //封装条件
        QueryWrapper<Course> 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<Course> pages = baseMapper.selectPage(pageParam, wrapper);
        long totalCount = pages.getTotal();//总记录数
        long totalPage = pages.getPages();//总页数
        long currentPage = pages.getCurrent();//当前页
        long size = pages.getSize();//每页记录数
        //每页数据集合
        List<Course> records = pages.getRecords();
        //Encapsulate the collection
        records.stream().forEach(item ->{
    
            //Get the names of its instructors and categories based on storage in the collection
            this.getTeacherOrSubjectName(item);
        });
        //封装返回数据
        HashMap<String, Object> map = new HashMap<>();
        map.put("totalCount",totalCount);
        map.put("totalPage",totalPage);
        map.put("records",records);
        return map;
    }
    //获取讲师和分类名称
    private Course getTeacherOrSubjectName(Course course){
    
        //Because the query came outcourse So it must be passed incourse
        //Look up the specific names of lecturers and categories from other databases
        Teacher teacher = teacherService.getById(course.getTeacherId());
        if(teacher!=null){
    
            //course继承的是BaseEntity There is an additional parameter for Map<String,Object> param
            //Add it to it,This is used when a multi-table join query is required
            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,Note that it is passed in here when it is just loadedVo里面全都是null,所以传到service里面后,will become query all.
CourseIt is already bound to the corresponding database table,So build from itQueryWrapperYou can query directly in the corresponding table.No matter how many columns there are in the database table,will be by definitionmodelThe column returns,The remaining columns will not be returned.

@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<Course> coursePage = new Page<>(page, limit);
        //Pass it into the method for filling 并返回
        Map<String, Object> map = courseService.findPage(coursePage, courseQueryVo);
        return Result.ok(map);
    }
}

课程列表前端

首先在router下的index.jsAdd frontend path,再在apiAdd a method to call the backend interface,再在viewsInside write components and callapi里的方法.

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

在apiDirectory to create routing filescourse.js

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

export default{
    
    //课程列表
    getPageList(page,limit,searchObj){
    
        return request({
    
            //What is written is the backend path
            url:`${
      api_name}/${
      page}/${
      limit}`,
            method: 'get',
            params: searchObj
        })
    },
}

在teacher.jsDefine a get all lecturers inside,以listThe interface returned by the form,之前在controller里面写过,Not to be confused with paginated queries.

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

vue的list编写

再编写index.js里的/views/vod/course/list页面,There is also too much code,More than two hundred lines in total,Read it after copying and pasting…
I really can't put it up,就这样吧.

效果

在这里插入图片描述

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

There are three processes to publish a course:填写课程基本信息,创建课程大纲-发布课程,The first function is implemented here:填写课程基本信息.
Each course has its own description,And will be updated frequently,So create a database tablecourse_description在这里插入图片描述

创建mapper

创建mapper并且将其与CourseDescription模型绑定,Use this latermapperAll searches will be theremodel映射的table里.

public interface CourseDescriptionMapper extends BaseMapper<CourseDescription> {
    
}

Don't forget to build the correspondingxml,虽然是空的.

<?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.atguigu.ggkt.vod.mapper.CourseDescriptionMapper">

</mapper>

创建service

创建service接口,Then create its implementationimpl,Remember to instantiate the correspondingmapper进行查询操作.
I realized when I wrote this,之前的model分为model和vo,其中model对应的是数据库表,voCorresponds to the data sent from the front end,Use it for onemodel接收.

public interface CourseDescriptionService extends IService<CourseDescription> {
    
    //Returns to the basics of creating a new classID
    public Long saveCourseInfo(CourseFormVo vo);
}

实现impl

@Service
public class CourseDescriptionImpl extends ServiceImpl<CourseDescriptionMapper, CourseDescription> implements CourseDescriptionService {
    
    //声明mapper
    @Autowired
    private CourseDescriptionMapper courseDescriptionMapper;
    //declare another homemapper Because it needs to be inserted into the database
    @Autowired
    private CourseMapper courseMapper;
    //将获得的voInformation is passed into the database and stored The table that needs to be inserted: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();
        //I researched why I switched directly Then I found out that the naming is not the same...上面的course是一样的
        courseDescription.setDescription(vo.getDescription());
        courseDescription.setCourseId(course.getId());
        //插入数据库
        //descriptionService.save(courseDescription); This is what is used in the notes 我感觉用mapper好一点吧.
        courseDescriptionMapper.insert(courseDescription);
        
        //返回课程id
        return course.getId();
    }
}

controller

This part of the code is messed up,它service和mapperThey are all built separately,But the class is added,It was written inCourseController里,Researched because ofCourseServiceDo it right in thereDescription表的修改,According to the coding standard,It needs to be injectedservice,所以要将DescriptionThe class is created toService层次,Therefore, a major change has been made to the front.

现在更改CourseController.java

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

前端

在index.jsModify the route inside

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

同时,In the interface of the course list, there is also an add button to trigger the jump,So add it there too.
在这里插入图片描述

    add() {
    
      //The jump to should be routing 不是界面
      this.$router.push({
     path: 'course/info' })
    },

The jump should beindex.jsroutes defined in it
在api的course.js里定义接口,Note that it cannot be written as a note hereparams里,This way the backend cannot receive it,Because the backend receives yesRequestBody,必须把它放在data里!

    saveCourseInfo(courseInfo){
    
        return request({
    
            //What is written is the backend path
            url:`${
      api_name}/save`,
            method: `post`,
            // params: courseInfo
            data: courseInfo
        })
    },

创建index.js里面指向的course/form.vue
在这里插入图片描述
在这里插入图片描述
Note that the route name is obtained here,所以要在前面的index.js里面添加,在created()can jump to the corresponding interface.

      {
    
        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
      },
<template>
  <div class="app-container">
    <h2 style="text-align: center;">发布新课程</h2>
    <el-steps :active="active" finish-status="success" simple style="margin-bottom: 40px">
      <el-step title="填写课程基本信息" />
      <el-step title="创建课程大纲" />
      <el-step title="发布课程" />
    </el-steps>
    <!-- 填写课程基本信息 -->
    <info v-if="active === 0" />
    <!-- 创建课程大纲 -->
    <chapter v-if="active === 1" />
    <!-- 发布课程 -->
    <Publish v-if="active === 2 || active === 3" />
  </div>
</template>
<script>
// 引入子组件
import Info from '@/views/vod/course/components/Info'
import Chapter from '@/views/vod/course/components/Chapter'
import Publish from '@/views/vod/course/components/Publish'
export default {
    
  components: {
     Info, Chapter, Publish }, // 注册子组件
  data() {
    
    return {
    
      active: 0,
      courseId: null
    }
  },
  created() {
    
    // 获取路由id
    if (this.$route.params.id) {
    
      this.courseId = this.$route.params.id
    }
    if (this.$route.name === 'CourseInfoEdit') {
    
      this.active = 0
    }
    if (this.$route.name === 'CourseChapterEdit') {
    
      this.active = 1
    }
  }
}
</script>

Note that three components are introduced aboveInfo Chapter Publish
Its component relationship is as follows
在这里插入图片描述

The code is too long to read directly.
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

效果

在这里插入图片描述

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

This function implements the modified echo,That is, if you have filled in the basic information and click Save,At this time, I want to roll back the modified scene.

修改Service

首先在CourseServiceAdd the corresponding method to the interface.

    //根据ID获取课程信息
    CourseFormVo getCourseFormVoById(long id);
    //根据ID修改课程信息
    void updateCourseById(CourseFormVo courseFormVo);

impl实现

    //根据id获取课程信息
    @Override
    public CourseFormVo getCourseFormVoById(long id) {
    
        //首先拿着id去数据库查数据 Find the corresponding course
        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<CourseDescription> QueryWrapper = new QueryWrapper<>();
        QueryWrapper.eq("course_id",id);
        CourseDescription description = courseDescriptionService.getOne(QueryWrapper);
        //创建Form对象 Because of going back to the front end
        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);
        //需要传入一个实体 according to this entityid更新
        courseMapper.updateById(course);

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

        //更新上去 The same cannot be usedupdateById
        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.jsDefine the method to connect to the backend

    //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界面,Write the specific update method inside

  created() {
    
    if(this.$parent.courseId){
    
      // 回显 如果带有courseId The instructions come back from the next step Only click Save in the previous step to have a savecourseId Load its information first and modify it
      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 // 下一步
      })
    },
原网站

版权声明
本文为[z754916067]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/222/202208102054328693.html