首页 > 其他分享 >实战项目-11(课程管理模块)

实战项目-11(课程管理模块)

时间:2022-10-06 09:44:33浏览次数:50  
标签:11 return String courseId course 课程 课程管理 模块 id

课程管理模块

1. 需求分析

image

2. 配置路由

{
    path: '/course',
    component: Layout,
    redirect: '/course/list',
    name: '课程管理',
    meta: { title: '课程管理', icon: 'example' },
    children: [
      {
        path: 'list',
        name: '课程列表',
        component: () => import('@/views/edu/course/list'),
        meta: { title: '课程分类列表', icon: 'table' }
      },
      {
        path: 'info',
        name: '添加课程',
        component: () => import('@/views/edu/course/info'),
        meta: { title: '添加课程', icon: 'tree' }
      },
      {
        path: 'info/:id',
        name: 'EduCourseInfoEdit',
        component: () => import('@/views/edu/course/info'),
        meta: { title: '编辑课程基本信息', noCache: 'true' },
        hidden: true
      },
      {
        path: 'chapter/:id',
        name: 'EduCourseInfoEdit',
        component: () => import('@/views/edu/course/chapter'),
        meta: { title: '编辑课程大纲', noCache: 'true' },
        hidden: true
      },
      {
        path: 'publish/:id',
        name: 'EduCourseInfoEdit',
        component: () => import('@/views/edu/course/publish'),
        meta: { title: '发布课程', noCache: 'true' },
        hidden: true
      }
    ]
  },

1. 创建路由对应的页面

image

  1. 课程信息页面info.vue
<template>
<div class="app-container">
  <h2 style="text-align: center;">发布新课程</h2>
  <el-steps :active="1" process-status="wait" align-center style="margin-bottom: 40px;">
    <el-step title="填写课程基本信息"/>
    <el-step title="创建课程大纲"/>
    <el-step title="提交审核"/>
  </el-steps>
  <el-form label-width="120px">
    <el-form-item>
      <el-button :disabled="saveBtnDisabled" type="primary" @click="next">保存并下一步</el-button>
    </el-form-item>
  </el-form>
</div>
</template>
<script>
export default {
  data() {
  return {
    saveBtnDisabled: false // 保存按钮是否禁用
    }
  },
  created() {
    console.log('info created')
  },
  methods: {
    next() {

      console.log('next')

      this.$router.push({ path: '/edu/course/chapter/1' })
    }
  }
}
</script>
  1. 课程大纲页面chapter.vue
<template>
  <div class="app-container">
  <h2 style="text-align: center;">发布新课程</h2>
  <el-steps :active="2" process-status="wait" align-center style="margin-bottom: 40px;">
    <el-step title="填写课程基本信息"/>
    <el-step title="创建课程大纲"/>
    <el-step title="提交审核"/>
  </el-steps>
  <el-form label-width="120px">
    <el-form-item>
      <el-button @click="previous">上一步</el-button>
      <el-button :disabled="saveBtnDisabled" type="primary" @click="next">下一步</el-button>
    </el-form-item>
  </el-form>
  </div>
</template>
<script>
export default {
  data() {
    return {
      saveBtnDisabled: false // 保存按钮是否禁用
    }
  },
  created() {
    console.log('chapter created')
  },
  methods: {
    previous() {
      console.log('previous')
      this.$router.push({ path: '/edu/course/info/1' })
    },
    next() {
      console.log('next')
      this.$router.push({ path: '/edu/course/publish/1' })
    }
  }
}
</script>
  1. 课程发布页面publish.vue
<template>
<div class="app-container">
  <h2 style="text-align: center;">发布新课程</h2>
  <el-steps :active="3" process-status="wait" align-center style="margin-bottom: 40px;">
    <el-step title="填写课程基本信息"/>
    <el-step title="创建课程大纲"/>
    <el-step title="提交审核"/>
  </el-steps>
  <el-form label-width="120px">
    <el-form-item>
      <el-button @click="previous">返回修改</el-button>
      <el-button :disabled="saveBtnDisabled" type="primary" @click="publish">发布课程</el-button>
    </el-form-item>
    </el-form>
  </div>
</template>
<script>
export default {
  data() {
    return {
      saveBtnDisabled: false // 保存按钮是否禁用
    }
  },
  created() {
    console.log('publish created')
  },
  methods: {
    previous() {
      console.log('previous')
      this.$router.push({ path: '/edu/course/chapter/1' })
    },
    publish() {
      console.log('publish')
      this.$router.push({ path: '/edu/course/list' })
    }
  }
}
</script>

2. 启动测试发现可以来回跳转

3. 编写三个页面

1. 页面一后端代码

  1. 根据表educhapter educourse educoursedescription eduvideo生成对应的entity....文件
  2. 修改EduCourseDescription的主键生成策略,改为input手动输入,并修改创建时间和修改时间
  3. 在对应的controller中创建方法
@RestController
@RequestMapping("/eduservice/course")
@CrossOrigin
public class EduCourseController {
    @Autowired
    private EduCourseService courseService;


    //添加课程基本信息的方法
    @PostMapping("addCourseInfo")
    public R addCourseInfo(@RequestBody CourseInfoVo courseInfoVo){

        //返回添加之后的id ,为了前端添加使用

        String id = courseService.saveCourseInfo(courseInfoVo);

        return R.ok().data("courseId",id);
    }

}
  1. 定义业务层方法
   //添加课程基本信息的方法
    String saveCourseInfo(CourseInfoVo courseInfoVo);
  1. 定义实现类中的方法
package com.sli.eduservice.service.impl;

import com.sli.eduservice.entity.EduCourse;
import com.sli.eduservice.entity.EduCourseDescription;
import com.sli.eduservice.entity.vo.CourseInfoVo;
import com.sli.eduservice.mapper.EduCourseMapper;
import com.sli.eduservice.service.EduCourseDescriptionService;
import com.sli.eduservice.service.EduCourseService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.sli.servicebase.exceptionhandler.GuliException;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

/**
 * <p>
 * 课程 服务实现类
 * </p>
 *
 * @author sli
 * @since 2021-10-21
 */
@Service
public class EduCourseServiceImpl extends ServiceImpl<EduCourseMapper, EduCourse> implements EduCourseService {

    //课程描述的注入
    @Autowired
    private EduCourseDescriptionService courseDescriptionService;

    //添加课程基本信息的方法
    @Override
    public String saveCourseInfo(CourseInfoVo courseInfoVo) {
        //1. 向课程表中添加课程基本信息
        //CourseInfoVo转换成eduCourse对象
        EduCourse eduCourse = new EduCourse();
        BeanUtils.copyProperties(courseInfoVo,eduCourse);//将courseInfoVo中的值放入eduCourse中
        int insert = baseMapper.insert(eduCourse);

        if (insert <= 0){
            //添加失败
            throw new GuliException(20001,"添加课程信息失败");
        }

        //3.因为测试完之后发现两个生成的id不相同,所以需要设置id
        //获取添加之后的id---->4
        String cid = eduCourse.getId();
        
        
        
        //2. 向课程简介表添加课程信息
        EduCourseDescription courseDescription = new EduCourseDescription();

        courseDescription.setDescription(courseInfoVo.getDescription());

        //4. 设置描述的id就是课程的id
        courseDescription.setId(cid);

        courseDescriptionService.save(courseDescription);
        
        return cid;

    }
}

  1. swagger测试

2. 页面一前端的实现

  1. 定义api
import request from '@/utils/request'
export default {
    //1 添加课程信息功能
    /*2.ajax:
        url就是待载入的页面地址(controller请求)
        data就是待发送的key/value参数(键值对)
        success约等于then(回调函数)
            success中的data约等于response
    */
    addCourseInfo(courseInfo) {
        return request({
            url: '/eduservice/course/addCourseInfo',
            method: 'post',
            data:courseInfo
          })
    },
    //查询所有的讲师
    getListTeacher(){
        return request({
            url: '/eduservice/teacher/findAll',
            method: 'get',
          })
    }
}
  1. 以下的实现(级联显示,还包含了下拉显示所有的讲师)
    image

image

image

  1. 将课程简介加入Tinymce可视化插件
    3.1. 将脚本分别复制到common和static目录下面
    3.2. 在guli-admin/build/webpack.dev.conf.js下面添加配置
new HtmlWebpackPlugin({
      ......,
      templateParameters: {
        BASE_URL: config.dev.assetsPublicPath + config.dev.assetsSubDirectory
     }
    })

3.3. 在/index.html中引入js脚本

  <body>
    <script src=<%= BASE_URL %>/tinymce4.7.5/tinymce.min.js></script>
    <script src=<%= BASE_URL %>/tinymce4.7.5/langs/zh_CN.js></script>
    <div id="app"></div>
    <!-- built files will be auto injected -->
  </body>

3.4 在要使用的页面引入组件
image

  1. 页面的完整实现info.vue
<template>

  <div class="app-container">

    <h2 style="text-align: center;">发布新课程</h2>

    <el-steps :active="1" process-status="wait" align-center style="margin-bottom: 40px;">
      <el-step title="填写课程基本信息"/>
      <el-step title="创建课程大纲"/>
      <el-step title="最终发布"/>
    </el-steps>

    <el-form label-width="120px">

        <el-form-item label="课程标题">
            <el-input v-model="courseInfo.title" placeholder=" 示例:机器学习项目课:从基础到搭建项目视频课程。专业名称注意大小写"/>
        </el-form-item>

        <!-- 所属分类 TODO -->
        <el-form-item label="课程分类">
            <el-select
                v-model="courseInfo.subjectParentId"
                placeholder="一级分类" @change="subjectLevelOneChanged">

                <el-option
                    v-for="subject in subjectOneList"
                    :key="subject.id"
                    :label="subject.title"
                    :value="subject.id"/>

            </el-select>

            <!-- 二级分类 -->
            <el-select v-model="courseInfo.subjectId" placeholder="二级分类" @change="subjectLevelOneChanged">
                <el-option
                    v-for="subject in subjectTwoList"
                    :key="subject.id"
                    :label="subject.title"
                    :value="subject.id"/>
            </el-select>
        </el-form-item>


        <!-- 课程讲师 TODO -->
        <!-- 课程讲师 -->
        <el-form-item label="课程讲师">
        <el-select
            v-model="courseInfo.teacherId"
            placeholder="请选择">

            <el-option
                v-for="teacher in teacherList"
                :key="teacher.id"
                :label="teacher.name"
                :value="teacher.id"/>

        </el-select>
        </el-form-item>

        <el-form-item label="总课时">
            <el-input-number :min="0" v-model="courseInfo.lessonNum" controls-position="right" placeholder="请填写课程的总课时数"/>
        </el-form-item>

        <!-- 课程简介 TODO -->
        <el-form-item label="课程简介">
            <tinymce :height="300" v-model="courseInfo.description"/>
        </el-form-item>


        <!-- 课程封面 TODO -->
        <!-- 课程封面-->
        <el-form-item label="课程封面">

            <el-upload
                :show-file-list="false"
                :on-success="handleAvatarSuccess"
                :before-upload="beforeAvatarUpload"
                :action="BASE_API+'/eduoss/fileoss'"
                class="avatar-uploader">
                <img :src="courseInfo.cover">
            </el-upload>

        </el-form-item>

        <el-form-item label="课程价格">
            <el-input-number :min="0" v-model="courseInfo.price" controls-position="right" placeholder="免费课程请设置为0元"/> 元
        </el-form-item>

        <el-form-item>
            <el-button :disabled="saveBtnDisabled" type="primary" @click="saveOrUpdate">保存并下一步</el-button>
        </el-form-item>
        </el-form>
  </div>
</template>

<script>
import course from '@/api/edu/course'
import subject from '@/api/edu/subject'
import Tinymce from '@/components/Tinymce' //引入组件
export default {
    components: { Tinymce },
  data() {
    return {
      saveBtnDisabled: false, // 保存按钮是否禁用
      courseInfo:{
          title: '',
          subjectId: '',//二级分类id
          subjectParentId:'',//一级分类id
          teacherId: '',
          lessonNum: 0,
          description: '',
          cover: '/static/01.jpg',
          price: 0,
          subjectParentId:'',//一级分类id
          subjectId:''//二级分类id
      },
      //封装所有讲师的数据
      teacherList:[],
      subjectOneList:[],//一级分类
      subjectTwoList:[],//二级分类
      BASE_API: process.env.BASE_API//接口api地址
    };
  },

  created() {
    //初始化所有讲师
    this.getListTeacher()
    //初始化一级分类
    this.getOneSubject()
  },

  methods: {
      //上传封面成功调用的方法
      handleAvatarSuccess(res, file) {
            this.courseInfo.cover = res.data.url
        },
      //上传之前调用的方法
     beforeAvatarUpload(file) {
            const isJPG = file.type === 'image/jpeg'
            const isLt2M = file.size / 1024 / 1024 < 2

            if (!isJPG) {
                this.$message.error('上传头像图片只能是 JPG 格式!')
            }
            if (!isLt2M) {
                this.$message.error('上传头像图片大小不能超过 2MB!')
            }
            return isJPG && isLt2M
        },
      //点击某个一级分类触发change,显示对应的二级分类
      subjectLevelOneChanged(value){
          //value就是一级分类的id值
          //遍历所有的分类(里面包含所有的一级和二级,然后比较value和一级的值来判断二级是哪个)
          for(var i = 0;i < this.subjectOneList.length;i++){
              var oneSubject = this.subjectOneList[i]
              //判断所有一级的id是否和点击的id一样
              if(value === oneSubject.id){
                  //从一级里面获取所有的二级分类
                  this.subjectTwoList = oneSubject.children

                  //将二级分类的id值清空
                  this.courseInfo.subjectId = ''
              }
          }
      },

     //查询所有的一级分类
    getOneSubject() {
        subject.getSubjectList()
            .then(response => {
                this.subjectOneList = response.data.list
            })
    },
    //查询所有的讲师
    getListTeacher() {
         course.getListTeacher()
             .then(response => {
                 this.teacherList = response.data.items
             })
    },
    saveOrUpdate() {
            course.addCourseInfo(this.courseInfo)
                .then(response => {
                    //提示
                    this.$message({
                        type: 'success',
                        message: '添加课程信息成功!'
                    });
                    //跳转到第二步
                    this.$router.push({path:'/course/chapter/'+response.data.courseId})
                })
        }

  },
};
</script>
<style scoped>
.tinymce-container {
  line-height: 29px;
}
</style>

3. 启动测试-->成功

4. 页面二后端代码编写

以上是实现了添加课程的代码,现在点击上一步要回显页面,还有增加章节的CRUD代码和小节的CRUD代码

1. 回显数据

EduChapterController

 //根据课程id查询课程基本信息
    @GetMapping("getCourseInfo/{courseId}")
    public R getCourseInfo(@PathVariable String courseId) {
        CourseInfoVo courseInfoVo = courseService.getCourseInfo(courseId);
        return R.ok().data("courseInfoVo",courseInfoVo);
    }

EduCourseService

    CourseInfoVo getCourseInfo(String courseId);

EduCourseServiceImpl

 //根据课程id查询课程基本信息
    @Override
    public CourseInfoVo getCourseInfo(String courseId) {
        //1 查询课程表
        EduCourse eduCourse = baseMapper.selectById(courseId);
        CourseInfoVo courseInfoVo = new CourseInfoVo();
        BeanUtils.copyProperties(eduCourse,courseInfoVo);

        //2 查询描述表
        EduCourseDescription courseDescription = courseDescriptionService.getById(courseId);
        courseInfoVo.setDescription(courseDescription.getDescription());

        return courseInfoVo;
    }

注意:数据库的edu_course中is_delete键有问题,记得修改

2. 章节的CRUD

需要先创建两个对应的vo类chapter.ChapterVo和chapter.Video
EduChapterController

    @Autowired
    private EduChapterService chapterService;

    //课程大纲列表,根据课程id进行查询
    @GetMapping("getChapterVideo/{courseId}")
    public R getChapterVideo(@PathVariable String courseId){
        List<ChapterVo> list = chapterService.getChapterVideoByCourseId(courseId);
        return R.ok().data("allChapterVideo",list);
    }

    //添加章节
    @PostMapping("addChapter")
    public R addChapter(@RequestBody EduChapter eduChapter){
        chapterService.save(eduChapter);
        return R.ok();
    }

    //根据章节id查询
    @GetMapping("getChapterInfo/{chapterId}")
    public R getChapterInfo(@PathVariable String chapterId){
        EduChapter eduChapter = chapterService.getById(chapterId);
        return R.ok().data("chapter",eduChapter);
    }

    //修改章节
    @PostMapping("updateChapter")
    public R updateChapter(@RequestBody EduChapter eduChapter){
        chapterService.updateById(eduChapter);
        return R.ok();
    }

    //删除
    @DeleteMapping("{chapterId}")
    public R deleteChapter(@PathVariable String chapterId){
        boolean flag = chapterService.deleteChapter(chapterId);
        if (flag) {
            return R.ok();
        }else {
            return R.error();
        }
    }

EduChapterService

List<ChapterVo> getChapterVideoByCourseId(String courseId);

boolean deleteChapter(String chapterId);

EduChapterServiceImpl

@Autowired
    private EduVideoService videoService;//注入小节的service

    //课程大纲列表,根据课程id进行查询
    @Override
    public List<ChapterVo> getChapterVideoByCourseId(String courseId) {

        //1. 根据课程id查询课程里面的章节
        QueryWrapper<EduChapter> wrapperChapter = new QueryWrapper<>();
        wrapperChapter.eq("course_id",courseId);
        List<EduChapter> eduChapterList = baseMapper.selectList(wrapperChapter);

        //2. 根据课程的id查询课程中所有的小结
        QueryWrapper<EduVideo> wrapperVideo = new QueryWrapper<>();
        wrapperChapter.eq("course_id",courseId);
        List<EduVideo> eduVideoList = videoService.list(wrapperVideo);

        //3. 遍历查询的list集合进行封装
            //创建list用于封装
        List<ChapterVo> finalList = new ArrayList<>();
            //遍历查询到的章节集合

        for (int i = 0; i < eduChapterList.size(); i++) {
            EduChapter eduChapter = eduChapterList.get(i);
            //将eduChapter对象的值复制到ChapterVo中
            ChapterVo chapterVo = new ChapterVo();
            BeanUtils.copyProperties(eduChapter,chapterVo);
            finalList.add(chapterVo);


            //创建集合,用于封装章节中的小节
            List<VideoVo> videoList = new ArrayList<>();

            //4. 遍历查询小节的list集合,进行封装
            for (int m = 0; m < eduVideoList.size(); m++) {
                //得到每个小结
                EduVideo eduVideo = eduVideoList.get(m);
                //判断:小节里面chapter id 和章节中的id是否一样
                if (eduVideo.getChapterId().equals(eduChapter.getId())){
                    //进行封装
                    VideoVo videoVo = new VideoVo();
                    BeanUtils.copyProperties(eduVideo,videoVo);
                    //放入小节封装的集合中
                    videoList.add(videoVo);
                }
            }
            //将封装之后的小结list集合封装到章节中
            chapterVo.setChildren(videoList);
        }
        return finalList;
    }

    //删除章节的方法
    @Override
    public boolean deleteChapter(String chapterId) {
        //根据chapterId查询小节表,如果查到,不删
        QueryWrapper<EduVideo> wrapper = new QueryWrapper<>();

        wrapper.eq("chapter_id",chapterId);

        int count = videoService.count(wrapper);

        //判断
        if (count > 0){//查询出小节,不进行删除
            throw new GuliException(20001,"不能删除");
        }else{//不能查询数据,进行删除
            //删除
            int result = baseMapper.deleteById(chapterId);
            return result>0;
        }

    }

小节的CRUD

EduVideoController

  @Autowired
    private EduVideoService videoService;

    //添加
    @PostMapping("addVideo")
    public R addVideo(@RequestBody EduVideo eduVideo){
        videoService.save(eduVideo);
        return R.ok();
    }
    //删除
    // TODO 后面需要完善:删除小节的时候同时把里面的视屏删除
    @DeleteMapping("{id}")
    public R deleteVideo(@PathVariable String id){
        videoService.removeById(id);
        return R.ok();
    }

5. 页面二前端代码实现

编写前端代码记得编写api
image
image
image
chapter.vue

点击查看代码
<template>

  <div class="app-container">

    <h2 style="text-align: center;">发布新课程</h2>

    <el-steps :active="2" process-status="wait" align-center style="margin-bottom: 40px;">
      <el-step title="填写课程基本信息"/>
      <el-step title="创建课程大纲"/>
      <el-step title="最终发布"/>
    </el-steps>

<el-button type="text" @click="openChapterDialog()">添加章节</el-button>

    <!-- 章节 -->
    <ul class="chanpterList">
        <li
            v-for="chapter in chapterVideoList"
            :key="chapter.id">
            <p>
                {{ chapter.title }}

                <span class="acts">
                    <el-button style="" type="text" @click="openVideo(chapter.id)">添加小节</el-button>
                    <el-button style="" type="text" @click="openEditChatper(chapter.id)">编辑</el-button>
                    <el-button type="text" @click="removeChapter(chapter.id)">删除</el-button>
                </span>
            </p>

            <!-- 视频 -->
            <ul class="chanpterList videoList">
                <li
                    v-for="video in chapter.children"
                    :key="video.id">
                    <p>{{ video.title }}

                <span class="acts">
                    
                    <el-button style="" type="text">编辑</el-button>
                    <el-button type="text" @click="removeVideo(video.id)">删除</el-button>
                </span>
                    </p>
                </li>
            </ul>
        </li>
    </ul>
    <div>
        <el-button @click="previous">上一步</el-button>
        <el-button :disabled="saveBtnDisabled" type="primary" @click="next">下一步</el-button>
    </div>

    <!-- 添加和修改章节表单 -->
    <el-dialog :visible.sync="dialogChapterFormVisible" title="添加章节">
        <el-form :model="chapter" label-width="120px">
            <el-form-item label="章节标题">
                <el-input v-model="chapter.title"/>
            </el-form-item>
            <el-form-item label="章节排序">
                <el-input-number v-model="chapter.sort" :min="0" controls-position="right"/>
            </el-form-item>
        </el-form>
        <div slot="footer" class="dialog-footer">
            <el-button @click="dialogChapterFormVisible = false">取 消</el-button>
            <el-button type="primary" @click="saveOrUpdate">确 定</el-button>
        </div>
    </el-dialog>

    <!-- 添加和修改课时表单 -->
<el-dialog :visible.sync="dialogVideoFormVisible" title="添加课时">
  <el-form :model="video" label-width="120px">
    <el-form-item label="课时标题">
      <el-input v-model="video.title"/>
    </el-form-item>
    <el-form-item label="课时排序">
      <el-input-number v-model="video.sort" :min="0" controls-position="right"/>
    </el-form-item>
    <el-form-item label="是否免费">
      <el-radio-group v-model="video.free">
        <el-radio :label="true">免费</el-radio>
        <el-radio :label="false">默认</el-radio>
      </el-radio-group>
    </el-form-item>
    <el-form-item label="上传视频">
      <!-- TODO -->
    </el-form-item>
  </el-form>
  <div slot="footer" class="dialog-footer">
    <el-button @click="dialogVideoFormVisible = false">取 消</el-button>
    <el-button :disabled="saveVideoBtnDisabled" type="primary" @click="saveOrUpdateVideo">确 定</el-button>
  </div>
</el-dialog>

  </div>
</template>
<script>
import chapter from '@/api/edu/chapter'
import video from '@/api/edu/video'

export default {
    data() {
        return {
            saveBtnDisabled:false,
            courseId:'',//课程id
            chapterVideoList:[],
            chapter:{ //封装章节数据
                title: '',
                sort: 0
            },
            video: {
                title: '',
                sort: 0,
                free: 0,
                videoSourceId: ''
            },
            dialogChapterFormVisible:false,//章节弹框
            dialogVideoFormVisible:false //小节弹框
            
        }
    },
    created() {
        //获取路由的id值
        if(this.$route.params && this.$route.params.id) {
            this.courseId = this.$route.params.id
            //根据课程id查询章节和小节
            this.getChapterVideo()
        }
    },
    methods:{
//==============================小节操作====================================
        //删除小节
        removeVideo(id) {
            this.$confirm('此操作将删除小节, 是否继续?', '提示', {
                confirmButtonText: '确定',
                cancelButtonText: '取消',
                type: 'warning'
            }).then(() => {  //点击确定,执行then方法
                //调用删除的方法
                video.deleteVideo(id)
                    .then(response =>{//删除成功
                    //提示信息
                    this.$message({
                        type: 'success',
                        message: '删除小节成功!'
                    });
                    //刷新页面
                    this.getChapterVideo()
                })
            }) //点击取消,执行catch方法
        },
        //添加小节弹框的方法
        openVideo(chapterId) {
            //弹框
            this.dialogVideoFormVisible = true
            //设置章节id
            this.video.chapterId = chapterId
        },
        //添加小节
        addVideo() {
            //设置课程id
            this.video.courseId = this.courseId
            video.addVideo(this.video)
                .then(response => {
                    //关闭弹框
                    this.dialogVideoFormVisible = false
                    //提示
                    this.$message({
                        type: 'success',
                        message: '添加小节成功!'
                    });
                    //刷新页面
                    this.getChapterVideo()
                })
        },
        saveOrUpdateVideo() {
            this.addVideo()
        },

//==============================章节操作====================================
        //删除章节
        removeChapter(chapterId) {
            this.$confirm('此操作将删除章节, 是否继续?', '提示', {
                confirmButtonText: '确定',
                cancelButtonText: '取消',
                type: 'warning'
            }).then(() => {  //点击确定,执行then方法
                //调用删除的方法
                chapter.deleteChapter(chapterId)
                    .then(response =>{//删除成功
                    //提示信息
                    this.$message({
                        type: 'success',
                        message: '删除成功!'
                    });
                    //刷新页面
                    this.getChapterVideo()
                })
            }) //点击取消,执行catch方法
        },
        //修改章节弹框数据回显
        openEditChatper(chapterId) {
            //弹框
            this.dialogChapterFormVisible = true
            //调用接口
            chapter.getChapter(chapterId)   
                .then(response => {
                    this.chapter = response.data.chapter
                })
        },
        //弹出添加章节页面
        openChapterDialog() {
            //弹框
            this.dialogChapterFormVisible = true
            //表单数据清空
            this.chapter.title = ''
            this.chapter.sort = 0
        },
        //添加章节
        addChapter() {
            //设置课程id到chapter对象里面
            this.chapter.courseId = this.courseId
            chapter.addChapter(this.chapter)
                .then(response => {
                    //关闭弹框
                    this.dialogChapterFormVisible = false
                    //提示
                    this.$message({
                        type: 'success',
                        message: '添加章节成功!'
                    });
                    //刷新页面
                    this.getChapterVideo()
                })
        },
        //修改章节的方法
        updateChapter() {
            chapter.updateChapter(this.chapter)
                .then(response =>  {
                    //关闭弹框
                    this.dialogChapterFormVisible = false
                    //提示
                    this.$message({
                        type: 'success',
                        message: '修改章节成功!'
                    });
                    //刷新页面
                    this.getChapterVideo()
                })
        },
        saveOrUpdate() {
            if(!this.chapter.id) {
                this.addChapter()
            } else {
                this.updateChapter()
            }
        },
        //根据课程id查询章节和小节
        getChapterVideo() {
            chapter.getAllChapterVideo(this.courseId)
                .then(response => {
                    this.chapterVideoList = response.data.allChapterVideo
                })
        },
        previous() {
            this.$router.push({path:'/course/info/'+this.courseId})
        },
        next() {
            //跳转到第二步
            this.$router.push({path:'/course/publish/'+this.courseId})
        }
    }
}
</script>
<style scoped>
.chanpterList{
    position: relative;
    list-style: none;
    margin: 0;
    padding: 0;
}
.chanpterList li{
  position: relative;
}
.chanpterList p{
  float: left;
  font-size: 20px;
  margin: 10px 0;
  padding: 10px;
  height: 70px;
  line-height: 50px;
  width: 100%;
  border: 1px solid #DDD;
}
.chanpterList .acts {
    float: right;
    font-size: 14px;
}

.videoList{
  padding-left: 50px;
}
.videoList p{
  float: left;
  font-size: 14px;
  margin: 10px 0;
  padding: 10px;
  height: 50px;
  line-height: 30px;
  width: 100%;
  border: 1px dotted #DDD;
}

</style>
info.vue
点击查看代码
<template>

  <div class="app-container">

    <h2 style="text-align: center;">发布新课程</h2>

    <el-steps :active="1" process-status="wait" align-center style="margin-bottom: 40px;">
      <el-step title="填写课程基本信息"/>
      <el-step title="创建课程大纲"/>
      <el-step title="最终发布"/>
    </el-steps>

    <el-form label-width="120px">

        <el-form-item label="课程标题">
            <el-input v-model="courseInfo.title" placeholder=" 示例:机器学习项目课:从基础到搭建项目视频课程。专业名称注意大小写"/>
        </el-form-item>

        <!-- 所属分类 TODO -->
        <el-form-item label="课程分类">
            <el-select
                v-model="courseInfo.subjectParentId"
                placeholder="一级分类" @change="subjectLevelOneChanged">

                <el-option
                    v-for="subject in subjectOneList"
                    :key="subject.id"
                    :label="subject.title"
                    :value="subject.id"/>

            </el-select>

            <!-- 二级分类 -->
            <el-select v-model="courseInfo.subjectId" placeholder="二级分类">
                <el-option
                    v-for="subject in subjectTwoList"
                    :key="subject.id"
                    :label="subject.title"
                    :value="subject.id"/>
            </el-select>
        </el-form-item>


        <!-- 课程讲师 TODO -->
        <!-- 课程讲师 -->
        <el-form-item label="课程讲师">
        <el-select
            v-model="courseInfo.teacherId"
            placeholder="请选择">

            <el-option
                v-for="teacher in teacherList"
                :key="teacher.id"
                :label="teacher.name"
                :value="teacher.id"/>

        </el-select>
        </el-form-item>

        <el-form-item label="总课时">
            <el-input-number :min="0" v-model="courseInfo.lessonNum" controls-position="right" placeholder="请填写课程的总课时数"/>
        </el-form-item>

        <!-- 课程简介 TODO -->
        <!-- 课程简介-->
        <el-form-item label="课程简介">
            <tinymce :height="300" v-model="courseInfo.description"/>
        </el-form-item>


        <!-- 课程封面 TODO -->
        <!-- 课程封面-->
        <el-form-item label="课程封面">

            <el-upload
                :show-file-list="false"
                :on-success="handleAvatarSuccess"
                :before-upload="beforeAvatarUpload"
                :action="BASE_API+'/eduoss/fileoss'"
                class="avatar-uploader">
                <img :src="courseInfo.cover">
            </el-upload>

        </el-form-item>

        <el-form-item label="课程价格">
            <el-input-number :min="0" v-model="courseInfo.price" controls-position="right" placeholder="免费课程请设置为0元"/> 元
        </el-form-item>

        <el-form-item>
            <el-button :disabled="saveBtnDisabled" type="primary" @click="saveOrUpdate">保存并下一步</el-button>
        </el-form-item>
        </el-form>
  </div>
</template>
<script>
import course from '@/api/edu/course'
import subject from '@/api/edu/subject'
import Tinymce from '@/components/Tinymce' //引入组件

export default {
    //声明组件
    components: { Tinymce },
    data() {
        return {
            saveBtnDisabled:false,
            courseInfo:{
                title: '',
                subjectId: '',//二级分类id
                subjectParentId:'',//一级分类id
                teacherId: '',
                lessonNum: 0,
                description: '',
                cover: '/static/01.jpg',
                price: 0
            },
            courseId:'',
            BASE_API: process.env.BASE_API, // 接口API地址
            teacherList:[],//封装所有的讲师
            subjectOneList:[],//一级分类
            subjectTwoList:[]//二级分类
        }   
    },
    created() {

        //获取路由id值
        if(this.$route.params && this.$route.params.id) {
            this.courseId = this.$route.params.id
            //调用根据id查询课程的方法
            this.getInfo()

        } else {
            //初始化所有讲师
            this.getListTeacher()
            //初始化一级分类
            this.getOneSubject()
        }
        
    },
    methods:{
        //根据课程id查询
        getInfo() {
            course.getCourseInfoId(this.courseId)
                .then(response => {
                    //在courseInfo课程基本信息,包含 一级分类id 和 二级分类id
                    this.courseInfo = response.data.courseInfoVo
                    //1 查询所有的分类,包含一级和二级
                    subject.getSubjectList()
                        .then(response => {
                            //2 获取所有一级分类
                            this.subjectOneList = response.data.list
                            //3 把所有的一级分类数组进行遍历,
                            for(var i=0;i<this.subjectOneList.length;i++) {
                                //获取每个一级分类
                                var oneSubject = this.subjectOneList[i]
                                //比较当前courseInfo里面一级分类id和所有的一级分类id
                                if(this.courseInfo.subjectParentId == oneSubject.id) {
                                    //获取一级分类所有的二级分类
                                    this.subjectTwoList = oneSubject.children
                                }
                            }
                        })
                        //初始化所有讲师
                        this.getListTeacher()
                })
        },
        //上传封面成功调用的方法
        handleAvatarSuccess(res, file) {
            this.courseInfo.cover = res.data.url
        },
        //上传之前调用的方法
        beforeAvatarUpload(file) {
            const isJPG = file.type === 'image/jpeg'
            const isLt2M = file.size / 1024 / 1024 < 2

            if (!isJPG) {
                this.$message.error('上传头像图片只能是 JPG 格式!')
            }
            if (!isLt2M) {
                this.$message.error('上传头像图片大小不能超过 2MB!')
            }
            return isJPG && isLt2M
        },
        //点击某个一级分类,触发change,显示对应二级分类
        subjectLevelOneChanged(value) {
            //value就是一级分类id值
            //遍历所有的分类,包含一级和二级
            for(var i=0;i<this.subjectOneList.length;i++) {
                //每个一级分类
                var oneSubject = this.subjectOneList[i]
                //判断:所有一级分类id 和 点击一级分类id是否一样
                if(value === oneSubject.id) {
                    //从一级分类获取里面所有的二级分类
                    this.subjectTwoList = oneSubject.children
                    //把二级分类id值清空
                    this.courseInfo.subjectId = ''
                }
            }
        },
        //查询所有的一级分类
        getOneSubject() {
            subject.getSubjectList()
                .then(response => {
                    this.subjectOneList = response.data.list
                })
        },
        //查询所有的讲师
        getListTeacher() {
            course.getListTeacher()
                .then(response => {
                    this.teacherList = response.data.items
                })
        },
        //添加课程
        addCourse() {
            course.addCourseInfo(this.courseInfo)
                .then(response => {
                    //提示
                    this.$message({
                        type: 'success',
                        message: '添加课程信息成功!'
                    });
                    //跳转到第二步
                    this.$router.push({path:'/course/chapter/'+response.data.courseId})
                })
        },
        //修改课程
        updateCourse() {
            course.updateCourseInfo(this.courseInfo)
                .then(response => {
                     //提示
                    this.$message({
                        type: 'success',
                        message: '修改课程信息成功!'
                    });
                    //跳转到第二步
                    this.$router.push({path:'/course/chapter/'+this.courseId})
                })
        },
        saveOrUpdate() {
           //判断添加还是修改
           if(!this.courseInfo.id) {
               //添加
               this.addCourse()
           } else {
               this.updateCourse()
           }
        }
    }
}
</script>
<style scoped>
.tinymce-container {
  line-height: 29px;
}
</style>

6.页面三后端代码编写

最终发布页面的实现需要回显前面两个的数据
image
image

select ec.id,ec.title,ec.price,ec.lesson_num,ec.cover,
        et.name as teacherName,
        es1.title as subjectLevelOne,
        es2.title as subjectLevelTwo
    from edu_course ec left outer join edu_course_description ecd on ec.id=ecd.id
                       left outer join edu_teacher et on ec.teacher_id=et.id
                       left outer join edu_subject es1 on ec.subject_parent_id=es1.id
                       left outer join edu_subject es2 on ec.subject_parent_id=es2.id
    where ec.id=#{courseId}
  1. 编写vo类
@Data
public class CoursePublishVo {
    private String id;
    private String title;
    private String cover;
    private Integer lessonNum;
    private String subjectLevelOne;
    private String subjectLevelTwo;
    private String teacherName;
    private String price;
}
  1. 项目中编写mapper接口
    EduCourseMapper

    //根据课程id查询课程基本信息的方法
    public CoursePublishVo getPublishCourseInfo(String courseId);
  1. 编写xml文件(EduCourseMapper.xml)
<?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.sli.eduservice.mapper.EduCourseMapper">
<!--根据课程id查询课程的确认信息,使用了左连接,查询了四张表中的内容-->
    <select id="getPublishCourseInfo" resultType="com.sli.eduservice.entity.vo.CoursePublishVo">
    select ec.id,ec.title,ec.price,ec.lesson_num,ec.cover,
        et.name as teacherName,
        es1.title as subjectLevelOne,
        es2.title as subjectLevelTwo
    from edu_course ec left outer join edu_course_description ecd on ec.id=ecd.id
                       left outer join edu_teacher et on ec.teacher_id=et.id
                       left outer join edu_subject es1 on ec.subject_parent_id=es1.id
                       left outer join edu_subject es2 on ec.subject_parent_id=es2.id
    where ec.id=#{courseId}
    </select>
</mapper>
  1. 业务层在controller中
  //根据课程id查询课程确认信息
    @GetMapping("getPublishCourseInfo/{id}")
    public R getPublishCourseInfo(@PathVariable String id){
        CoursePublishVo coursePublishVo = courseService.publishCourseInfo(id);
        return R.ok().data("publishCourse",coursePublishVo);
    }
  1. service中
    CoursePublishVo publishCourseInfo(String id);
  1. service实现类中调用
 //根据课程id查询课程确认信息
    @Override
    public CoursePublishVo publishCourseInfo(String id) {
        //调用写好的mapper
        CoursePublishVo publishCourseInfo = baseMapper.getPublishCourseInfo(id);
        return publishCourseInfo;
    }
  1. 测试出现问题
    问题:
org.apache.ibatis.binding.BindingException: Invalid bound statement (not found): com.sli.eduservice.mapper.EduCourseMapper.getPublishCourseInfo

问题分析:dao层编译之后只有class文件,没有mapper.xml,因为maven工程在默认情况下将src/main/java目录下面的所有资源文件是不发布到target目录下面的.
解决方案:在pom.xml中配置如下的代码,并且在application.properties中加入如下的代码

<build>
	<resources>
		<directory>src/main/java</directory>
		<includes>
			<include>**/*.xml</include>
		</includes>
		<filterling>false</filterling>
	</resources>
</build>
#配置mapper xml文件的路径
mybatis-plus.mapper-locations=classpath:com/sli/eduservice/mapper/xml/*.xml

重新打包target会出现xml文件
8. 课程最终发布需要修改状态(status)将Draft改为Normal
EduCourseController.java

//课程最终发布
    //需要修改课程的状态(未发布为default.已发布为normal)
    @PostMapping("publishCourse/{id}")
    public R publishCourse(@PathVariable String id){
        EduCourse eduCourse = new EduCourse();
        eduCourse.setId(id);
        eduCourse.setStatus("Normal");
        courseService.updateById(eduCourse);
        return R.ok();
    }

7. 页面三前端的实现

src.spi.edu.course.js

 //根据课程id查询课程基本信息
    getCourseInfoId(id) {
        return request({
            url: '/eduservice/course/getCourseInfo/'+id,
            method: 'get'
          })
    },
    //修改课程信息
    updateCourseInfo(courseInfo) {
        return request({
            url: '/eduservice/course/updateCourseInfo',
            method: 'post',
            data: courseInfo
          })
    },

    //课程确认信息的回显
    getPublihCourseInfo(id) {
        return request({
            url: '/eduservice/course/getPublishCourseInfo/'+id,
            method: 'get'
          })
    },

    //课程最终发布
    publishCourse(id) {
        return request({
            url: '/eduservice/course/publishCourse/'+id,
            method: 'post'
          })
    },

edu.list.vue

<template>

  <div class="app-container">

    <h2 style="text-align: center;">发布新课程</h2>

    <el-steps :active="3" process-status="wait" align-center style="margin-bottom: 40px;">
      <el-step title="填写课程基本信息"/>
      <el-step title="创建课程大纲"/>
      <el-step title="发布课程"/>
    </el-steps>

    <div class="ccInfo">
      <img :src="coursePublish.cover">
      <div class="main">
        <h2>{{ coursePublish.title }}</h2>
        <p class="gray"><span>共{{ coursePublish.lessonNum }}课时</span></p>
        <p><span>所属分类:{{ coursePublish.subjectLevelOne }} — {{ coursePublish.subjectLevelTwo }}</span></p>
        <p>课程讲师:{{ coursePublish.teacherName }}</p>
        <h3 class="red">¥{{ coursePublish.price }}</h3>
      </div>
    </div>

    <div>
      <el-button @click="previous">返回修改</el-button>
      <el-button :disabled="saveBtnDisabled" type="primary" @click="publish">发布课程</el-button>
    </div>
  </div>
</template>

<script>
import course from '@/api/edu/course'
export default {
  data() {
    return {
      saveBtnDisabled: false, // 保存按钮是否禁用
      courseId:'',
      coursePublish:{}
    }
  },

  created() {
    //获取路由课程id值
    if(this.$route.params && this.$route.params.id) {
      this.courseId = this.$route.params.id
      //调用接口方法根据课程id查询
      this.getCoursePublishId()
    }
  },

  methods: {

    //根据课程id查询
    getCoursePublishId() {
      course.getPublihCourseInfo(this.courseId)
        .then(response => {
          this.coursePublish = response.data.publishCourse
        })
    },
    previous() {
      console.log('previous')
      this.$router.push({ path: '/course/chapter/1' })
    },

    publish() {
      course.publishCourse(this.courseId)
        .then(response => {
          //提示
          this.$message({
              type: 'success',
              message: '课程发布成功!'
          });
          //跳转课程列表页面
          this.$router.push({ path: '/course/list' })
        })
      
    }
  }
}
</script>

<style scoped>
.ccInfo {
    background: #f5f5f5;
    padding: 20px;
    overflow: hidden;
    border: 1px dashed #DDD;
    margin-bottom: 40px;
    position: relative;
}
.ccInfo img {
    background: #d6d6d6;
    width: 500px;
    height: 278px;
    display: block;
    float: left;
    border: none;
}
.ccInfo .main {
    margin-left: 520px;
}

.ccInfo .main h2 {
    font-size: 28px;
    margin-bottom: 30px;
    line-height: 1;
    font-weight: normal;
}
.ccInfo .main p {
    margin-bottom: 10px;
    word-wrap: break-word;
    line-height: 24px;
    max-height: 48px;
    overflow: hidden;
}

.ccInfo .main p {
    margin-bottom: 10px;
    word-wrap: break-word;
    line-height: 24px;
    max-height: 48px;
    overflow: hidden;
}
.ccInfo .main h3 {
    left: 540px;
    bottom: 20px;
    line-height: 1;
    font-size: 28px;
    color: #d32f24;
    font-weight: normal;
    position: absolute;
}
</style>
</script>

8. 页面四后端代码

image
image
image
类似于讲师列表的那个页面,先实现删除的那个按钮和条件分页查询
EduCourseController.java

//课程列表
    //条件分页查询
    @PostMapping("/pageCourseCondition/{current}/{limit}")
    public R pageCourseCondition(@PathVariable long current,
                                 @PathVariable long limit,
                                 @RequestBody(required = false)CourseQuery courseQuery){
        //创建一个page对象
        Page<EduCourse> pageCourse = new Page<>(current, limit);
        //构建wrapper条件
        QueryWrapper<EduCourse> wrapper = new QueryWrapper<>();
        //多条件组合查询,判断条件值是否为空
        String title = courseQuery.getTitle();
        String status = courseQuery.getStatus();
        if (!StringUtils.isEmpty(title)){
            wrapper.like("title",title);
        }
        if (!StringUtils.isEmpty(status)){
            wrapper.eq("status",status);
        }
        //排序,使前端添加之后第一个显示
        wrapper.orderByDesc("gmt_create");
        //调用方法,实现条件查询分页
        courseService.page(pageCourse,wrapper);
        long total = pageCourse.getTotal();//总记录数
        List<EduCourse> records = pageCourse.getRecords();//数据的list集合
        return R.ok().data("total",total).data("rows",records);
    }
    //删除课程
    @DeleteMapping("{courseId}")
    public R deleteCourse(@PathVariable String courseId){
        courseService.removeCourse(courseId);
        return R.ok();
    }

实体类CourseQuery(也就是前端的条件)

@Data
public class CourseQuery {
    private static final long serialVersionUID = 1L;

    private String title;//课程名称,模糊查询

    private String status;//默认发布状态 normal为发布 draft为未发布

}

EduCourseService接口

void removeCourse(String courseId);

EduCourseServiceImpl实现类

 //删除课程
    @Override
    public void removeCourse(String courseId) {
        //1 根据课程id删除小节
        eduVideoService.removeVideoByCourseId(courseId);

        //2 根据课程id删除章节
        chapterService.removeChapterByCourseId(courseId);

        //3 根据课程id删除描述
        courseDescriptionService.removeById(courseId);

        //4 根据课程id删除课程本身
        baseMapper.deleteById(courseId);

    }
  1. 根据课程id删除小节 EduVideoService接口
void removeVideoByCourseId(String courseId);
  1. 对应的实现类EduVideoServiceImpl
//课程最终发布
    //需要修改课程状态
@PostMapping("publishCourse/{id}")
    public R publishCourse(@PathVariable String id){
        EduCourse eduCourse = new EduCourse();
        eduCourse.setId(id);
        eduCourse.setStatus("Normal");
        courseService.updateById(eduCourse);
        return R.ok();
    }
 //1. 根据课程id删除小节
    //TODO 删除小节需要删除对应的视屏文件
    @Override
    public void removeVideoByCourseId(String courseId) {
        QueryWrapper<EduVideo> wrapper = new QueryWrapper<>();
        wrapper.eq("course_id",courseId);
        baseMapper.delete(wrapper);
    }
  1. 根据课程id删除章节 EduChapterService接口
//2. 根据课程id删除章节
    void removeChapterByCourseId(String courseId);
  1. 对应的实现类EduChapterServiceImpl
 //2. 根据课程id删除章节
    @Override
    public void removeChapterByCourseId(String courseId) {
        QueryWrapper<EduChapter> wrapper = new QueryWrapper<>();
        wrapper.eq("course_id",courseId);
        baseMapper.delete(wrapper);
    }
  1. 根据课程id删除描述 因为删除描述外键就是courseId
  2. 根据课程id删除课程本身 因为删除本身也是courseId

9. 页面四前端页面的实现

list.vue

<template>
    <div class="app-container">
        
    <!--条件部分,也就是根据条件筛选-->
    <el-form :inline="true" class="demo-form-inline">
      <el-form-item>
        <el-input v-model="courseQuery.title" placeholder="课程名称"/>
      </el-form-item>

      <el-form-item>
        <el-select v-model="courseQuery.status" clearable placeholder="课程状态">
          <el-option :value="Normal" label="已发布"/>
          <el-option :value="Draft" label="未发布"/>
        </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
      :data="list"
      border
      fit
      highlight-current-row>

      <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 prop="title" label="课程名称" width="80" />

      <el-table-column label="课程状态" width="80">
        <template slot-scope="scope">
          {{ scope.row.status==='Normal'?'已发布':'未发布' }}
        </template>
      </el-table-column>

      <el-table-column prop="lessonNum" label="课时数"/>

      <el-table-column prop="gmtCreate" label="添加时间" width="160"/>

      <el-table-column prop="viewCount" label="浏览量" width="60" />

      <el-table-column label="操作" width="200" align="center">

        <template slot-scope="scope">

          <router-link :to="'/teacher/edit/'+scope.row.id">
            <el-button type="text" size="mini" icon="el-icon-edit">编辑课程基本信息</el-button>
          </router-link>

          <router-link :to="'/teacher/edit/'+scope.row.id">
            <el-button type="text" size="mini" icon="el-icon-edit">编辑课程大纲</el-button>
          </router-link>

          <el-button type="danger" size="mini" icon="el-icon-delete" @click="removeDataById(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>

<script>
import course from '@/api/edu/course'

export default{
    //写核心代码位置
    data() {//定义变量和初始值
        return {
            list:null,//查询之后返回的集合
            page:1,//当前页
            limit:10,//每页的记录数
            total:0,//总记录数
            courseQuery:{}//条件封装对象
        }
    },
    created(){//在页面渲染之前执行
        this.getList()
    },

    methods:{//创建具体的方法,调用teacher.js定义的方法
        //讲师列表
        getList(page = 1){
            this.page = page
            course.getCourseListPage(this.page,this.limit,this.courseQuery)
            .then(response =>{
                this.list = response.data.rows
                this.total = response.data.total
            })
            .catch(error =>{
                console.log(error)
            })
        },


        resetData(){//清空的方法
            //表单输入项数据清空
            this.courseQuery = {}
            //查询所有的讲师数据
            this.getList()
        },

        removeDataById(id){
            this.$confirm('此操作将永久删除该课程, 是否继续?', '提示', {
            confirmButtonText: '确定',
            cancelButtonText: '取消',
            type: 'warning'
             }).then(() => { //点击确定 then方法
            //调用删除的方法
            course.deleteCourse(id)
               .then(response => {//删除成功
                 //提示信息
                   this.$message({
                       type: 'success',
                       message: '删除成功!'
                   });
                 //回到刷新列表页面
                 this.getList()
               })
             })
        }
    }
}
</script>

sec.edu.course.js

 //删除课程
    deleteCourse(id){
        return request({
            url: '/eduservice/course/' + id,
            method: 'delete'
          })
    },

    //课程列表(条件查询带分页)
    //current:当前页,limit每页记录数,courseQuery条件对象
    getCourseListPage(current,limit,courseQuery){
        return request({
            // url: 'eduservice/teacher/pageTeacherCondition/' + current + "/" + limit,
            url: `/eduservice/course/pageCourseCondition/${current}/${limit}`,
            method: 'post',
            data: courseQuery
          })
    },

未解决问题:按条件查询的时候的课程状态好像不能使用:value=只能是数字


待解决:课程视频的上传

标签:11,return,String,courseId,course,课程,课程管理,模块,id
From: https://www.cnblogs.com/sli1f/p/15682407.html

相关文章