一、先书写查询接口
1.创建两个实体类
@Data public class ChapterVO { private String id; private String title; private List<VideoVO> children=new ArrayList<VideoVO>(); }
@Data public class VideoVO { private String id; private String title; }
2.给实体类
EduChapter
加注解
3.书写controller方法
@RestController @CrossOrigin @RequestMapping("/eduservice/edu-chapter") public class EduChapterController { @Autowired EduChapterService chapterService; //根据课程id进行查询 @GetMapping("getChapterVideo/{courseId}") public R getChapterVideo(@PathVariable String courseId){ List<ChapterVO> list= chapterService.getChapterVideoBYcourseId(courseId); return R.OK().data("AllChapterVideo",list); } }
4.service
public interface EduChapterService extends IService<EduChapter> { List<ChapterVO> getChapterVideoBYcourseId(String courseId); }
5.serviceImpl
@Service public class EduChapterServiceImpl extends ServiceImpl<EduChapterMapper, EduChapter> implements EduChapterService { @Autowired EduVideoService eduVideoService; @Override public List<ChapterVO> getChapterVideoBYcourseId(String courseId) { //1根据id查询出课程里面所有的章节 QueryWrapper<EduChapter> wrapper=new QueryWrapper<>(); wrapper.eq("course_id",courseId); List<EduChapter> Chapterlist=baseMapper.selectList(wrapper); //2根据id查询出课程里面所有的小节 QueryWrapper<EduVideo> Videowrapper=new QueryWrapper<>(); Videowrapper.eq("course_id",courseId); List<EduVideo> eduVideolist=eduVideoService.list(Videowrapper); List<ChapterVO> finalList=new ArrayList<>(); //3便利查询章节list集合进行封装 for (int i = 0; i < Chapterlist.size() ; i++) { EduChapter eduChapter=Chapterlist.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); //eduChapter对象里的值复制到ChapterVO里 //判断小节的chapter_id和章节的id是否一样 if(eduVideo.getChapterId().equals(eduChapter.getId())){ VideoVO videoVO=new VideoVO(); BeanUtils.copyProperties(eduVideo,videoVO); videoList.add(videoVO); } } chapterVO.setChildren(videoList); } return finalList; } }
测试:
二、前端
当前页面
<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() { }, methods:{ previous() { this.$router.push({path:'/course/info/1'}) }, next() { //跳转到第二步 this.$router.push({path:'/course/publish/1'}) } } } </script>
添加js
页面
<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>
<el-button type="text" @click="openChapterDialog()">添加章节</el-button>
<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> <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>
最终页面
js代码
data() { return { saveBtnDisabled: false, chapterVideoList: [], courseId: "", 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 }) }, getChapterVideo() { chapter.getChapterVideo(this.courseId).then(response => { this.chapterVideoList = response.data.AllChapterVideo; }); }, previous() { this.$router.push({ path: "/course/info/1" }); }, 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; 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; 100%; border: 1px dotted #DDD; } </style>
向js中添加方法
import request from '@/utils/request' export default { getChapterVideo(courseid) { return request({ url: '/eduservice/edu-chapter/getChapterVideo/'+courseid, method: 'get' }) }, //添加章节 addChapter(chapter) { return request({ url: '/eduservice/edu-chapter/addChapter', method: 'post', data: chapter }) }, //根据id查询章节 getChapter(chapterId) { return request({ url: '/eduservice/edu-chapter/getChapterInfo/'+chapterId, method: 'get' }) }, //修改章节 updateChapter(chapter) { return request({ url: '/eduservice/edu-chapter/updateChapter', method: 'post', data: chapter }) }, //删除章节 deleteChapter(chapterId) { return request({ url: '/eduservice/edu-chapter/'+chapterId, method: 'delete' }) }, }
编写具体方法
controller
@RestController @CrossOrigin @RequestMapping("/eduservice/edu-chapter") public class EduChapterController { @Autowired 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(); } } }
service
public interface EduChapterService extends IService<EduChapter> { List<ChapterVO> getChapterVideoBYcourseId(String courseId); //删除章节的方法 boolean deleteChapter(String chapterId); }
serviceImpl
@Service public class EduChapterServiceImpl extends ServiceImpl<EduChapterMapper, EduChapter> implements EduChapterService { @Autowired EduVideoService eduVideoService; @Override public List<ChapterVO> getChapterVideoBYcourseId(String courseId) { //1根据id查询出课程里面所有的章节 QueryWrapper<EduChapter> wrapper=new QueryWrapper<>(); wrapper.eq("course_id",courseId); List<EduChapter> Chapterlist=baseMapper.selectList(wrapper); //2根据id查询出课程里面所有的小节 QueryWrapper<EduVideo> Videowrapper=new QueryWrapper<>(); Videowrapper.eq("course_id",courseId); List<EduVideo> eduVideolist=eduVideoService.list(Videowrapper); List<ChapterVO> finalList=new ArrayList<>(); //3便利查询章节list集合进行封装 for (int i = 0; i < Chapterlist.size() ; i++) { EduChapter eduChapter=Chapterlist.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); //eduChapter对象里的值复制到ChapterVO里 //判断小节的chapter_id和章节的id是否一样 if(eduVideo.getChapterId().equals(eduChapter.getId())){ VideoVO videoVO=new VideoVO(); BeanUtils.copyProperties(eduVideo,videoVO); videoList.add(videoVO); } } chapterVO.setChildren(videoList); } return finalList; } ////删除章节的方法 @Override public boolean deleteChapter(String chapterId) { //根据chapterid章节id 查询小节表,如果查询数据,不进行删除 QueryWrapper<EduVideo> wrapper = new QueryWrapper<>(); wrapper.eq("chapter_id",chapterId); int count = eduVideoService.count(wrapper); //判断 if(count >0) {//查询出小节,不进行删除 throw new onlineEduException(20001,"不能删除"); } else { //不能查询数据,进行删除 //删除章节 int result = baseMapper.deleteById(chapterId); //成功 1>0 0>0 return result>0; } } }
@RestController
@CrossOrigin
@RequestMapping("/eduservice/edu-chapter")
public class EduChapterController {
@Autowired
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();
}
}
}
<el-button type="text" @click="openChapterDialog()">添加章节</el-button>