文章目录
1.项目介绍
1.1.项目流程介绍
1.2项目涉及的一些表
edu_course 课程表:存储课程基本信息
edu_course_description 课程简介表 存储课程简介信息
edu_chapter 课程章节表 存储课程章节信息
edu_video 课程小结表 存储章节里面的小结信息
edu_teacher 讲师表
edu_subject 分类表
表之间的关系
2 编辑课程基本信息
注意问题
- 创建VO实体类用于表单数据的封装
- 表单提交的数据添加到数据库,对两张表进行添加(课程表和课程描述表)
- 把讲师和分类使用下来列表展示
课程分类做成二级联动的效果
2.1创建VO类封装表单提交的数据
在vo下创建CourseInfoVo类
@Data
@ApiModel(value = "课程基本信息", description = "编辑课程基本信息的表单对象")
public class CourseInfoVo {
private static final long serialVersionUID = 1L;
@ApiModelProperty(value = "课程ID")
private String id;
@ApiModelProperty(value = "课程讲师ID")
private String teacherId;
@ApiModelProperty(value = "课程专业ID")
private String subjectId;
@ApiModelProperty(value = "课程标题")
private String title;
@ApiModelProperty(value = "课程销售价格,设置为0则可免费观看")
private BigDecimal price;
@ApiModelProperty(value = "总课时")
private Integer lessonNum;
@ApiModelProperty(value = "课程封面图片路径")
private String cover;
@ApiModelProperty(value = "课程简介")
private String description;
}
2.2 Conroller层
@RestController
@RequestMapping("/eduservice/course")
@Api(tags = "课程相关的接口")
public class EduCourseController {
@Autowired
private EduCourseService eduCourseService;
@ApiOperation("添加课程信息")
@PostMapping("/addCourseInfo")
public Res addCourseInfo(@RequestBody CourseInfoVo courseInfoVo)
{
eduCourseService.saveCourseInfo(courseInfoVo);
return Res.ok();
}
}
2.3service层
@Service
public class EduCourseServiceImpl extends ServiceImpl<EduCourseMapper, EduCourse> implements EduCourseService {
@Autowired
private EduCourseMapper eduCourseMapper;
@Autowired
private EduCourseDescriptionMapper courseDescriptionMapper;
@Override
public void saveCourseInfo(CourseInfoVo courseInfoVo) {
///1.向课程表中添加课程基本信息
EduCourse eduCourse = new EduCourse();
//进行对象装换
BeanUtils.copyProperties(courseInfoVo,eduCourse);
// int insert = eduCourseMapper.insert(eduCourse);
int insert = baseMapper.insert(eduCourse);
if(insert<0)
{
throw new GuliException(20001,"添加课程信息失败");
}
String id = eduCourse.getId();
//向课程描述表中加数据
EduCourseDescription eduCourseDescription = new EduCourseDescription();
eduCourseDescription.setDescription(courseInfoVo.getDescription());
eduCourseDescription.setId(id);
courseDescriptionMapper.insert(eduCourseDescription);
}
}
2.4 编辑课程基本信息
2.4.1添加路由
在route/index.js下添加路由信息
{
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: '编辑课程基本信息',
component: () => import('@/views/edu/course/info'),
meta: { title: '编辑课程基本信息', icon: 'tree' },
hidden: true
},
{
path: 'chapter/:id',
name: '编辑课程大纲',
component: () => import('@/views/edu/course/chapter'),
meta: { title: '编辑课程大纲', icon: 'tree' },
hidden: true
},
{
path: 'publish/:id',
name: '发布课程',
component: () => import('@/views/edu/course/publish'),
meta: { title: '发布课程', icon: 'tree' },
hidden: true
}
]
},
2.4.2 根据路由信息创建响应的文件
在src/views/edu下创建文件夹course,并在course文件夹下分别创建名为chapter.vue,info.vue,list.vue,publish.vue
2.4.3编写表单页面,实现接口调用
views/edu/course/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 -->
<!-- 课程讲师 TODO -->
<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="课程简介">
<el-input v-model="courseInfo.descriptions" placeholder=" " />
</el-form-item>
<!-- 课程封面 TODO -->
<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="next">保存并下一步</el-button> -->
</el-form-item>
</el-form>
<el-form label-width="120px">
<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'
export default {
data() {
return {
saveBtnDisabled: false, // 保存按钮是否禁用,
courseInfo:{}
}
},
created() {
console.log('info created')
},
methods: {
saveOrUpdate() {
course.addCourseInfo(this.courseInfo)
.then(response=>{
//提示信息
this.$message({
type: 'success',
message: '添加课程信息成功!'
});
//路由跳转
this.$router.push({ path: '/course/chapter/1' })
})
//跳转到第二步
// this.$router.push({ path: '/course/chapter/1' })
}
}
}
</script>
由于添加课程id需要课程id,需要返回id
servic返回课程id
前端info.vue更改
2.4.4讲师下拉列表的显示
效果如下:
在添加课程的时候有讲师下拉列表
- 在api/edu/course下添加路由
getListTeacher(){
return request({
url:"/eduservice/teacher/findAll",
menubar:"get"
})
}
- 在views/edu/course/info.vue中添加下拉列表模块
<!-- 课程讲师 -->
<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>
并添加响应的数据和方法
2.4.5分类显示
首次进入页面显示所有的一级分类,二级分类为空,选择某个一级分类后,显示一级分类里面对应的二级分类
views/edu/course/info添加分类显示代码
data添加一级分类和二级
对应的方法
2.4.6添加课程信息前端完善添加封面
组件
方法
2.4.7富文本编辑器
- 复杂文本编辑器相关的组件到文件目录里面
- 在 guli-admin/build/webpack.dev.conf.js 中添加配置
- 找到index.html引入js文件
<script src=<%= BASE_URL %>/tinymce4.7.5/tinymce.min.js></script>
<script src=<%= BASE_URL %>/tinymce4.7.5/langs/zh_CN.js></script>
4. info.vue使用文本编辑器组件
进行替换
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 subjectNestedList"
:key="subject.id"
:label="subject.title"
:value="subject.id"/>
</el-select>
<!-- 二级分类 -->
<el-select v-model="courseInfo.subjectId" placeholder="二级分类">
<el-option
v-for="subject in subSubjectList"
: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>
<!-- <el-form-item label="课程简介">
<el-input v-model="courseInfo.descriptions" placeholder=" " />
</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="next">保存并下一步</el-button> -->
</el-form-item>
</el-form>
<el-form label-width="120px">
<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:{
subjectId:' ',
cover:'/static/01.jpg'
},
BASE_API: process.env.BASE_API,
teacherList:[],
subjectNestedList: [],//一级分类列表
subSubjectList: []//二级分类列表
}
},
created() {
// console.log('info created')
this.getTeacherList()
this.getOneSubject()
},
methods: {
//点击某个一级分类,触发change 显示对应的二级分类
subjectLevelOneChanged(value)//value就是一级分类id
{
//遍历所有分类 包括一级和二级
for(let i = 0; i <this.subjectNestedList.length;i++)
{
//当前一级分类的id和显示数据的一级分类id一致
if(value === this.subjectNestedList[i].id)
{
//得到对应的二级分类
this.subSubjectList=this.subjectNestedList[i].children;
//把二级分类id值情况
this.courseInfo.subjectId=' '
}
}
},
//上传之前
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
},
//上传封面成功
handleAvatarSuccess(res,file){
this.courseInfo.cover=res.data.url
},
getOneSubject(){
subject.getSubjectList()
.then(response =>{
this.subjectNestedList=response.data.list
}
)
},
getTeacherList(){
course.getListTeacher()
.then(respones=>{
this.teacherList=respones.data.teacherList
})
},
saveOrUpdate() {
course.addCourseInfo(this.courseInfo)
.then(response=>{
//提示信息
this.$message({
type: 'success',
message: '添加课程信息成功!'
});
//路由跳转
this.$router.push({ path: '/course/chapter/'+response.data.courseId})
})
//跳转到第二步
// this.$router.push({ path: '/course/chapter/1' })
}
}
}
</script>
<style scoped>
.tinymce-container {
line-height: 29px;
}
</style>
2.5编辑课程大纲后台
- 创建两个实体类,章节和小节,章节里面使用list表示小节
在domian包下建一个名为chapter的包,chapter包下建两个名为ChapterVO和VideoVo的实体类
VideoVo
import lombok.Data;
@Data
//小节实体类
public class VideoVo {
private String id;
private String title;
}
chapterVo
import java.util.ArrayList;
import java.util.List;
@Data
public class ChapterVo {
private String id;
private String title;
//表示小结
private List<VideoVo> children=new ArrayList<>();
}
- controller层
@RestController
@RequestMapping("/eduservice/chapter")
@Api(tags = "课程章节管理")
@CrossOrigin
public class EduChapterController {
@Autowired
private EduChapterService eduChapterService;
//根据课程id查到课程章节信息
@ApiOperation("得到所有的章节信息")
@GetMapping("/getChapterView/{courseId}")
public Res getChapterView(@PathVariable String courseId)
{
List<ChapterVo> chapterVoList= eduChapterService.getCourseInfoById(courseId);
HashMap<String, Object> hashMap = new HashMap<>();
hashMap.put("chapterList",chapterVoList);
return Res.ok().data(hashMap);
}
}
- service层
@Autowired
private EduChapterMapper eduChapterMapper;
@Autowired
private EduVideoMapper eduVideoMapper;
//根据课程id查到课程章节信息
@Override
public List<ChapterVo> getCourseInfoById(String courseId) {
//根据课程id查找所的章节信息
QueryWrapper<EduChapter> eduChapterQueryWrapper = new QueryWrapper<>();
eduChapterQueryWrapper.eq("course_id",courseId);
List<EduChapter> eduChapterList = eduChapterMapper.selectList(eduChapterQueryWrapper);
//查找课程id查找所有的小节信息
QueryWrapper<EduVideo> eduVideoQueryWrapper = new QueryWrapper<>();
eduVideoQueryWrapper.eq("course_id",courseId);
List<EduVideo> videoList = eduVideoMapper.selectList(eduVideoQueryWrapper);
//存放所有的章节信息
ArrayList<ChapterVo> chapterVoArrayList = new ArrayList<>();
//变量所有章节信息
for(EduChapter eduChapter:eduChapterList)
{
ChapterVo chapterVo = new ChapterVo();
BeanUtils.copyProperties(eduChapter,chapterVo);
String id = eduChapter.getId();
//存储;对应章节的所有小节信息
ArrayList<VideoVo> videoVoArrayList = new ArrayList<>();
//获取所有小节信息
for(EduVideo eduVideo:videoList)
{
//小节的章节id和章节id一致
if(id.equals(eduVideo.getChapterId()))
{
VideoVo videoVo = new VideoVo();
BeanUtils.copyProperties(eduVideo,videoVo);
videoVoArrayList.add(videoVo);
}
}
chapterVo.setChildren(videoVoArrayList);
chapterVoArrayList.add(chapterVo);
}
return chapterVoArrayList;
}
3. 编辑课程大纲
3.1编辑课程大纲前端
3.1.1 创建路由信息
在src/api/edu下创建chapter.js
import request from '@/utils/request'
export default{
getChapterVideo(courseId){
return request({
url:`/eduservice/chapter/${courseId}`,
method:"get"
})
}
}
edu/course/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>
<!-- 章节 -->
<ul class="chanpterList">
<li
v-for="chapter in chapterVideoList"
:key="chapter.id">
<p>
{{ chapter.title }}
<span class="acts">
<el-button type="text">添加课时</el-button>
<el-button style="" type="text">编辑</el-button>
<el-button type="text">删除</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 type="text">编辑</el-button>
<el-button type="text">删除</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-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>
import chapter from '@/api/edu/chapter.js'
export default {
data() {
return {
saveBtnDisabled: false, // 保存按钮是否禁用
chapterVideoList:[],
courseId:' '
}
},
created() {
if(this.$route.params && this.$route.params.id)
{
this.courseId = this.$route.params.id
//根据id查询所有的章节和小节
this.getChapterVideos()
}
},
methods: {
//根据ID查询章节和小结
getChapterVideos() {
chapter.getChapterVideo(this.courseId)
.then(response=>{
// alter("1")
this.chapterVideoList=response.data.chapterList
})
},
previous() {
console.log('previous')
this.$router.push({ path: '/course/info/1' })
},
next() {
console.log('next')
this.$router.push({ path: '/course/publish/1' })
}
}
}
</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>
3.1.2修改课程基本信息
达到要求
在填写第二步时,点击上一步,把课程基本信息进行回显
在数据回显页面点击保存后,数据进行保存并更新数据库
后台
在EduCourseController.java中定义根据id查询课程信息和修改课程信息的接口
@ApiOperation("根据ID查询课程基本信息")
@GetMapping("/getCourseInfo/{id}")
public Res getCourseInfoById(@PathVariable String id)
{
CourseInfoVo courseInfoVo=eduCourseService.getCourseInfoById(id);
HashMap<String, Object> hashMap = new HashMap<>();
hashMap.put("courseInfo",courseInfoVo);
return Res.ok().data(hashMap);
}
@ApiOperation("修改课程信息")
@PostMapping("/updateCourseInfo")
public Res updateCourseInfo(@RequestBody CourseInfoVo courseInfoVo)
{
eduCourseService.updateCourseInfo(courseInfoVo);
return Res.ok();
}
在EduCourseServiceImpl中进行实现
@Override
public CourseInfoVo getCourseInfoById(String id) {
CourseInfoVo courseInfoVo = new CourseInfoVo();
//查询课程表
EduCourse eduCourse = eduCourseMapper.selectById(id);
BeanUtils.copyProperties(eduCourse,courseInfoVo);
//查询描述表
EduCourseDescription eduCourseDescription = courseDescriptionMapper.selectById(id);
BeanUtils.copyProperties(eduCourseDescription,courseInfoVo);
return courseInfoVo;
}
//修改课程信息
@Override
public void updateCourseInfo(CourseInfoVo courseInfoVo) {
//修改课程表
EduCourse eduCourse = new EduCourse();
BeanUtils.copyProperties(courseInfoVo,eduCourse);
eduCourseMapper.updateById(eduCourse);
//修改描述表
EduCourseDescription eduCourseDescription = new EduCourseDescription();
BeanUtils.copyProperties(courseInfoVo,eduCourseDescription);
courseDescriptionMapper.updateById(eduCourseDescription);
}
3.2课程章节的添加、修改和删除
- 点击添加按钮 添加章节
- 点击添加章节按钮,弹出添加弹框,输入章节信息,点击保存按钮进行添加
3.2.1前端部分
添加按钮以及弹框
<el-button type="text" @click="dialogChapterFormVisible=true">添加章节</el-button>
<!-- 添加和修改章节表单 -->
<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>
以及添加两个字段
3.2.2章节信息的相关后台代码
controller层
//添加章节
@PostMapping("addchapter")
@ApiOperation("添加章节信息")
public Res saveChapter(@RequestBody EduChapter eduChapter)
{
eduChapterService.save(eduChapter);
return Res.ok();
}
//根据章节id查询
@GetMapping("/getChapterInfo/{chapterId}")
@ApiOperation("根据id查询章节信息")
public Res getChapterInfoById(@PathVariable("chapterId") String chapterId)
{
EduChapter byId = eduChapterService.getById(chapterId);
HashMap<String, Object> hashMap = new HashMap<>();
hashMap.put("chapter",byId);
return Res.ok().data(hashMap);
}
//修改章节信息
@PostMapping("/updateChapter")
@ApiOperation("修改章节信息")
public Res updateChapter(@RequestBody EduChapter eduChapter)
{
eduChapterService.updateById(eduChapter);
return Res.ok();
}
//删除章节信息
@DeleteMapping("/deleteChapter/{chapterId}")
@ApiOperation("删除章节信息")
public Res deleteChapter(@PathVariable String chapterId)
{
boolean deleteChapter = eduChapterService.deleteChapter(chapterId);
return Res.ok();
}
service层
//删除章节
@Override
public boolean deleteChapter(String chapterId) {
//根据章节id查询小节,如果删除到数据进行删除
QueryWrapper<EduVideo> eduVideoQueryWrapper = new QueryWrapper<>();
eduVideoQueryWrapper.eq("chapter_id",chapterId);
Integer count = eduVideoMapper.selectCount(eduVideoQueryWrapper);
//判断
if(count>0)//查询出小节,不进行删除
{
throw new GuliException(20001,"不能进行删除");
}
else {
int deleteById = eduVideoMapper.deleteById(chapterId);
return deleteById>0;
}
}
前端代码
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="openChapterDiglog()">添加章节</el-button>
<!-- 章节 -->
<!-- 章节 -->
<ul class="chanpterList">
<li
v-for="chapter in chapterVideoList"
:key="chapter.id">
<p>
{{ chapter.title }}
<span class="acts">
<el-button type="text">添加课时</el-button>
<el-button style="" type="text" @click="openEditChapter(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 type="text">编辑</el-button>
<el-button type="text">删除</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-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>
import chapter1 from '@/api/edu/chapter.js'
export default {
data() {
return {
saveBtnDisabled: false, // 保存按钮是否禁用
chapterVideoList:[],
courseId:' ',
dialogChapterFormVisible:false,
chapter:{//章节信息
title:'',
sort:0,
ju:0
}
}
},
created() {
if(this.$route.params && this.$route.params.id)
{
this.courseId = this.$route.params.id
//根据id查询所有的章节和小节
this.getChapterVideos()
}
},
methods: {
//修改章节弹框数据回显
openEditChapter(chapterId)
{
//弹框
this.dialogChapterFormVisible=true
//调用接口
chapter1.getChapterById(chapterId)
.then(response=>{
this.chapter=response.data.chapter
this.chapter.ju=1
})
},
//弹出添加章节
openChapterDiglog(){
//弹框
this.dialogChapterFormVisible=true
//表单数据清空
this.chapter.title=' '
this.chapter.sort=0
this.chapter.ju=2
this.chapter.id=' '
},
saveOrUpdate(){
if(this.chapter.ju==2)
{
this.addChapter()
}
else{
this.updateChapter()
}
},
//修改章节信息
updateChapter(){
chapter1.updateChapter(this.chapter)
.then(response=>{
//关闭弹框
this.dialogChapterFormVisible=false
//提示
this.$message({
type: "success",
message:"修改章节成功"
})
//刷新页面
this.getChapterVideos()
})
},
//添加章节信息
addChapter(){
//设置课程id
this.chapter.courseId=this.courseId
chapter1.addChapter(this.chapter)
.then(response=>{
//关闭弹框
this.dialogChapterFormVisible=false
//提示
this.$message({
type: "success",
message:"添加章节成功"
})
//刷新页面
this.getChapterVideos()
})
},
//根据ID查询章节和小结
getChapterVideos() {
chapter1.getChapterVideo(this.courseId)
.then(response=>{
this.chapterVideoList=response.data.chapterList
})
},
//删除章节
removechapter(chapterId){
this.$confirm('此操作将永久删除该章节的记录, 是否继续?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
})
.then(() => { //点击确定执行then方法
//调用删除方法
chapter1.deleteChapter(chapterId)
.then(response=>{ //删除成功
this.$message({
type: 'success',
message: '删除成功!'
});
this.getChapterVideos()
})
//回到列表页面
this.getChapterVideos()
})
},
previous() {
console.log('previous')
this.$router.push({ path: '/course/info/'+this.courseId })
},
next() {
console.log('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>
chapter.js
import request from '@/utils/request'
export default{
//得到课程信息
getChapterVideo(courseId){
return request({
url:`/eduservice/chapter/getChapterView/${courseId}`,
method:"get"
})
},
//添加章节信息
addChapter(chapter){
return request({
url:"/eduservice/chapter//addchapter",
method:"POST",
data:chapter
})
},
getChapterById(chapterId){
return request({
url:`/eduservice/chapter/getChapterInfo/${chapterId}`,
method:"GET"
})
},
//修改章节
updateChapter(chapter)
{
return request({
url:"/eduservice/chapter/updateChapter",
method:"post",
data:chapter
})
},
//删除章节信息
deleteChapter(chapterId)
{
return request({
url:`/eduservice/chapter/deleteChapter/${chapterId}`,
method:"delete"
})
}
}
3.3章节中的小节信息增加、修改和删除
3.3.1后台
controller层
EduVideoController
@RestController
@RequestMapping("/eduservice/video")
@CrossOrigin
public class EduVideoController {
@Autowired
private EduVideoService eduVideoService;
//添加小节信息
@PostMapping("/addVideo")
public Res addVideo(@RequestBody EduVideo eduVideo)
{
eduVideoService.save(eduVideo);
return Res.ok();
}
//删除小节信息
//TOOO 后面此方法需要完善 删除小节的时候同时删除里面的视频
@DeleteMapping("{id}")
public Res deleteVideo(@PathVariable("id") String id)
{
eduVideoService.removeById(id);
return Res.ok();
}
//修改小节信息
@PostMapping("/updateVideo")
public Res updateVideo(@RequestBody EduVideo eduVideo)
{
eduVideoService.updateById(eduVideo);
return Res.ok();
}
//通过id查询小节信息
@GetMapping("/getVideo/{id}")
public Res getVideo(@PathVariable("id") String id)
{
EduVideo eduVideo = eduVideoService.getById(id);
HashMap<String, Object> hashMap = new HashMap<>();
hashMap.put("video",eduVideo);
return Res.ok().data(hashMap);
}
}
3.3.2前端
小节信息的路由信息
在src/api/edu下创建一个video.vue并填入相应的路由信息
import request from '@/utils/request'
export default{
//添加小节
addVideo(video)
{
return request({
url: "/eduservice/video/addVideo",
method: 'POST',
data:video
})
},
//修改小节
updateVideo(video) {
return request({
url:"/eduservice/video/updateVideo",
method: 'POST',
data:video
})
},
//删除小节
deleteVideo(id){
return request({
url:"/eduservice/video/"+id,
method:"delete"
})
},
//通过id查询小节信息
getVideoById(id) {
return request({
url:"/eduservice/video/getVideo/"+id,
method:"get"
})
}
}
在chapter.vue中添加响应的data
添加小节信息的相关函数
//==========添加小节的操作=========================
openEditVideo(id)
{
//弹框
this.dialogVideoFormVisible=true
//调用接口
video1.getVideoById(id)
.then(response =>{
this.video=response.data.video
this.video.ju=1
})
// this.dialogChapterFormVisible=true
},
//添加小节的弹框
openVideo(chapterId)
{
this.video.title='',
this.video.sort=0,
this.video.free==0,
this.video.videoSourceId=''
//弹框
this.dialogVideoFormVisible=true
//设置章节id
this.video.chapterId=chapterId
},
//添加小节信息
addVideo()
{
//设置课程id
this.video.courseId=this.courseId
this.video.id=""
video1.addVideo(this.video)
.then(response=>{
//关闭弹框
this.dialogVideoFormVisible=false
//提示信息
this.$message({
type:"success",
message:"添加小节成功"
});
this.getChapterVideos()
})
this.getChapterVideos()
},
updateVideo(){
video1.updateVideo(this.video)
.then(response=>{
//关闭弹框
this.dialogVideoFormVisible=false
//提示信息
this.$message({
type:"success",
message:"修改小节成功"
});
this.getChapterVideos()
})
},
saveOrUpdateVideo()
{
if(this.video.ju==1)
this.updateVideo()
else
this.addVideo()
this.video.ju=0
},
//删除小节
removeVideo(id) {
this.$confirm('此操作将永久删除该小节的记录, 是否继续?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
})
.then(() => { //点击确定执行then方法
//调用删除方法
video1.deleteVideo(id)
.then(response=>{ //删除成功
this.$message({
type: 'success',
message: '删除成功!'
});
this.getChapterVideos()
})
//回到列表页面
this.getChapterVideos()
})
},
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="openChapterDiglog()">添加章节</el-button>
<!-- 章节 -->
<!-- 章节 -->
<ul class="chanpterList">
<li
v-for="chapter in chapterVideoList"
:key="chapter.id">
<p>
{{ chapter.title }}
<span class="acts">
<el-button type="text" @click="openVideo(chapter.id)">添加课时</el-button>
<el-button style="" type="text" @click="openEditChapter(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 type="text" @click="openEditVideo(video.id)">编辑</el-button>
<el-button type="text" @click="removeVideo(video.id)">删1除</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>
<!-- <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>
import chapter1 from '@/api/edu/chapter.js'
import video1 from '@/api/edu/video.js'
export default {
data() {
return {
saveBtnDisabled: false, // 保存按钮是否禁用
chapterVideoList:[],
courseId:' ',
dialogChapterFormVisible:false,//章节弹框
dialogVideoFormVisible:false,//小节弹框
chapter:{//章节信息
title:'',
sort:0,
ju:0
},
video:{
title: '',
sort: 0,
free: 0,
videoSourceId: '',
ju:0,
id:''
}
}
},
created() {
if(this.$route.params && this.$route.params.id)
{
this.courseId = this.$route.params.id
//根据id查询所有的章节和小节
this.getChapterVideos()
}
},
methods: {
//==========添加小节的操作=========================
openEditVideo(id)
{
//弹框
this.dialogVideoFormVisible=true
//调用接口
video1.getVideoById(id)
.then(response =>{
this.video=response.data.video
this.video.ju=1
})
// this.dialogChapterFormVisible=true
},
//添加小节的弹框
openVideo(chapterId)
{
this.video.title='',
this.video.sort=0,
this.video.free==0,
this.video.videoSourceId=''
//弹框
this.dialogVideoFormVisible=true
//设置章节id
this.video.chapterId=chapterId
},
//添加小节信息
addVideo()
{
//设置课程id
this.video.courseId=this.courseId
this.video.id=""
video1.addVideo(this.video)
.then(response=>{
//关闭弹框
this.dialogVideoFormVisible=false
//提示信息
this.$message({
type:"success",
message:"添加小节成功"
});
this.getChapterVideos()
})
this.getChapterVideos()
},
updateVideo(){
video1.updateVideo(this.video)
.then(response=>{
//关闭弹框
this.dialogVideoFormVisible=false
//提示信息
this.$message({
type:"success",
message:"修改小节成功"
});
this.getChapterVideos()
})
},
saveOrUpdateVideo()
{
if(this.video.ju==1)
this.updateVideo()
else
this.addVideo()
this.video.ju=0
},
//删除小节
removeVideo(id) {
this.$confirm('此操作将永久删除该小节的记录, 是否继续?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
})
.then(() => { //点击确定执行then方法
//调用删除方法
video1.deleteVideo(id)
.then(response=>{ //删除成功
this.$message({
type: 'success',
message: '删除成功!'
});
this.getChapterVideos()
})
//回到列表页面
this.getChapterVideos()
})
},
//==========添加章节的操作====================
//修改章节弹框数据回显
openEditChapter(chapterId)
{
//弹框
this.dialogChapterFormVisible=true
//调用接口
chapter1.getChapterById(chapterId)
.then(response=>{
this.chapter=response.data.chapter
this.chapter.ju=1
})
},
//弹出添加章节
openChapterDiglog(){
//弹框
this.dialogChapterFormVisible=true
//表单数据清空
this.chapter.title=' '
this.chapter.sort=0
this.chapter.ju=2
this.chapter.id=' '
},
saveOrUpdate(){
if(this.chapter.ju==2)
{
this.addChapter()
}
else{
this.updateChapter()
}
},
//修改章节信息
updateChapter(){
chapter1.updateChapter(this.chapter)
.then(response=>{
//关闭弹框
this.dialogChapterFormVisible=false
//提示
this.$message({
type: "success",
message:"修改章节成功"
})
//刷新页面
this.getChapterVideos()
})
},
//添加章节信息
addChapter(){
//设置课程id
this.chapter.courseId=this.courseId
chapter1.addChapter(this.chapter)
.then(response=>{
//关闭弹框
this.dialogChapterFormVisible=false
//提示
this.$message({
type: "success",
message:"添加章节成功"
})
//刷新页面
this.getChapterVideos()
})
},
//根据ID查询章节和小结
getChapterVideos() {
chapter1.getChapterVideo(this.courseId)
.then(response=>{
this.chapterVideoList=response.data.chapterList
})
},
//删除章节
removechapter(chapterId){
this.$confirm('此操作将永久删除该章节的记录, 是否继续?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
})
.then(() => { //点击确定执行then方法
//调用删除方法
chapter1.deleteChapter(chapterId)
.then(response=>{ //删除成功
this.$message({
type: 'success',
message: '删除成功!'
});
this.getChapterVideos()
})
//回到列表页面
this.getChapterVideos()
})
},
previous() {
console.log('previous')
this.$router.push({ path: '/course/info/'+this.courseId })
},
next() {
console.log('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>
3.4课程最终发布信息确认
3.4.1 后台
- 在eduSubjectController添加查询发布信息的接口
@GetMapping("/getAllSubject")
@ApiOperation("得到所有课程的分类信息")
public Res getAllSubject()
{
List<OneSubject> list= eduSubjectService.getOneTwoSubject();
HashMap<String, Object> hashMap = new HashMap<>();
hashMap.put("list",list);
return Res.ok().data(hashMap);
}
- 实现查询发布信息的接口
@Override
public List<CoursePublishVo> getCoursePublish(String id) {
return eduCourseMapper.getCoursePublishInfo(id);
}
- mapper层实现发布信息的查询
@Select("select ec.id,ec.title,ec.price,ec.lesson_num,et.name as teacherName,es1.title as subjectLevelOne ,es2.title as subjectLevelTwo,ec.cover from edu_course ec " +
"LEFT JOIN edu_course_description ed on ec.id=ed.id " +
"LEFT JOIN edu_teacher et on ec.teacher_id=et.id " +
"LEFT JOIN edu_subject es1 on ec.subject_id=es1.id " +
"LEFT JOIN edu_subject es2 on ec.subject_parent_id=es2.id where ec.id=#{id}")
public List<CoursePublishVo> getCoursePublishInfo(String id);
3.4.2前端实现
- 在api/edu/course.js中添加路由信息
getpublishCourses() {
course1.getPublishCourseInfo(this.courseId)
.then(response =>{
console.log(response)
this.coursePublish=response.data.coursePublish[0]
})
}
- views/edu/course/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>
<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 course1 from '@/api/edu/course'
export default {
data() {
return {
saveBtnDisabled: false ,// 保存按钮是否禁用
courseId:'',
coursePublish:{}
}
},
created() {
if(this.$route.params && this.$route.params.id)
{
this.courseId=this.$route.params.id;
//通过id查询发布信息
this.getpublishCourses()
}
},
methods: {
previous() {
console.log('previous')
this.$router.push({ path: '/course/chapter/1' })
},
publish() {
console.log('publish')
this.$router.push({ path: '/course/list' })
},
getpublishCourses() {
course1.getPublishCourseInfo(this.courseId)
.then(response =>{
console.log(response)
this.coursePublish=response.data.coursePublish[0]
})
}
}
}
</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>
3.4.3 课程最终发布
修改课程的static为normal已发布
//课程最终发布,修改课程状态
@PostMapping("/publishCourse/{id}")
@ApiOperation("修改课程状态")
public Res publishCourse(@PathVariable("id") String id)
{
EduCourse eduCourse = new EduCourse();
eduCourse.setId(id);
eduCourse.setStatus("Normal");
eduCourseService.updateById(eduCourse);
return Res.ok();
}
3.5课程列表的显示和课程信息的相关操作
3.5.1前端
- api/edu/course.js中添加相关的路由信息
//获得课程列表
getCourseInfo(current,limit,courseQuery)
{
return request({
url:`/eduservice/course/getCourseList/${current}/${limit}`,
method:"post",
data:courseQuery
})
},
//根据id删除课程信息
deleteCourseInfo(id)
{
return request({
url:`/eduservice/course/${id}`,
method:'delete'
})
}
- 在course/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.level" 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="getTeacherList()">查询</el-button>
<el-button type="default" @click="resetData()">清空</el-button>
</el-form>
<!-- 表格 -->
<el-table
:data="list"
element-loading-text="数据加载中"
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.level===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="'/course/info/'+scope.row.id">
<el-button type="primary" size="mini" icon="el-icon-edit" @click="updataCourse(scope.row.id)">编辑课程信息</el-button>
</router-link>
<router-link :to="'/course/chapter/'+scope.row.id">
<el-button type="primary" 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="getTeacherList"
/>
</div>
</template>
<script>
// 引入调用teacher.js的文件
import course from '@/api/edu/course'
export default {
//写核心代码的位置
data() {//定义变量以及初始值
return{
list:null,
page:1,
limit:5,
total:0,
courseQuery:{} //通过v-module会将属性自动传过来
}
},
created() {//页面渲染之前执行,一般调用methods定义的方法
this.getTeacherList()
},
methods:{//创建具体的方法。调用teacher.js定义的方法
//讲师列表
getTeacherList(page=1){
this.page=page
course.getCourseInfo(this.page,this.limit,this.courseQuery)
.then(respons=>{//请求失败
console.log("请求成功")
console.log(respons)
this.list=respons.data.record
this.total=respons.data.total
console.log(this.list)
console.log(this.total)
})
.catch(err=>{//请求成功
console.log("请求失败")
console.log(err)
})
},
resetData(){//清空方法 1.查询所有数据 2.清空表单数据
//清空表单数据
this.courseQuery={}
//查询所有数据
this.getTeacherList()
},
removeDataById(id)
{
this.$confirm('此操作将永久删除该课程的记录, 是否继续?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
})
.then(() => { //点击确定执行then方法
//调用删除方法
course.deleteCourseInfo(id)
.then(response=>{ //删除成功
this.$message({
type: 'success',
message: '删除成功!'
});
this.getTeacherList()
})
//回到列表页面
this.getTeacherList()
})
}
}
}
</script>
3.5.2后端
eduCourseController.java
//TODO 完善田间查询带分页
@PostMapping("/getCourseList/{current}/{limit}")
@ApiOperation("获取课程列表信息")
public Res getCourseList(@PathVariable int current,@PathVariable int limit,@RequestBody(required = false) EduCourse eduCourse)
{
System.out.println(current);
System.out.println(limit);
// System.out.println();
Page<EduCourse> page = new Page<>(current, limit);
QueryWrapper<EduCourse> queryWrapper = new QueryWrapper<>();
if(!StringUtils.isEmpty(eduCourse.getTitle()))
{
queryWrapper.eq("title",eduCourse.getTitle());
}
if(!StringUtils.isEmpty(eduCourse.getStatus()))
{
queryWrapper.eq("status",eduCourse.getStatus());
}
queryWrapper.orderByDesc("gmt_create");
eduCourseService.page(page, queryWrapper);
//总记录数
long total = page.getTotal();
//数据的集合
List<EduCourse> pageRecords = page.getRecords();
System.out.println(pageRecords);
HashMap<String, Object> hashMap = new HashMap<>();
hashMap.put("total",total);
hashMap.put("record",pageRecords);
return Res.ok().data(hashMap);
}
//删除课程
@DeleteMapping("{courseId}")
public Res deleteCourse(@PathVariable String courseId)
{
//根据id删除小节信息
eduCourseService.deleteCourse(courseId);
return Res.ok();
}
EduCourseServiceImpl.java
//删除课程信息
@Override
public void deleteCourse(String courseId) {
//根据课程id删除小节
eduVideoService.deleteVideoByCourseId(courseId);
//根据课程id删除章节
eduChapterService.deleteChapterBuCourseId(courseId);
//根据课程id删除描述
eduCourseDescriptionService.getById(courseId);
//根据课程id删除课程本身
int i = baseMapper.deleteById(courseId);
if(i==0)
{
throw new GuliException(20001,"删除失败");
}
}
EduVideoServiceImpl.java
@Override
public void deleteVideoByCourseId(String courseId) {
QueryWrapper<EduVideo> eduVideoQueryWrapper = new QueryWrapper<>();
eduVideoQueryWrapper.eq("course_id",courseId);
baseMapper.delete(eduVideoQueryWrapper);
}
EduChapterServiceImpl.java
@Override
public void deleteChapterBuCourseId(String courseId) {
QueryWrapper<EduChapter> chapterQueryWrapper = new QueryWrapper<>();
chapterQueryWrapper.eq("course_id",courseId);
baseMapper.delete(chapterQueryWrapper);
}