一.后端实现
1.创建两个实体类
一个章节有多个小节,章节和小节属于一对多的关系
创建两个实体类,分别表示章节和小节,在章节实体类使用list表示小节
小节类
@Data
public class VideoVo {
private String id;
private String title;
}
章节类
@Data
public class ChapterVo {
private String id;
private String title;
//表示小节
private List<VideoVo> children=new ArrayList<>();
}
EduChapterController
@RestController
@RequestMapping("/eduservice/chapter")
@CrossOrigin
public class 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);
}
}
EduChapterService
public interface EduChapterService extends IService<EduChapter> {
List<ChapterVo> getChapterVideoByCourseId(String courseId);
}
EduChapterServiceImpl
@Service
public class EduChapterServiceImpl extends ServiceImpl<EduChapterMapper, EduChapter> implements EduChapterService {
@Autowired
private EduVideoService videoService;
@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<ChapterVo> finalList = new ArrayList<>();
//遍历查询章节list集合
for (int i = 0; i < eduChapterList.size(); i++) {
//每个章节
EduChapter eduChapter = eduChapterList.get(i);
ChapterVo chapterVo = new ChapterVo();
BeanUtils.copyProperties(eduChapter,chapterVo);
finalList.add(chapterVo);
//封装章节的小节
ArrayList<VideoVo> videoList = new ArrayList<>();
//4.遍历查询小节list集合,进行封装
for (int m = 0; m < eduVideoList.size(); m++) {
//得到每个小节
EduVideo eduVideo = eduVideoList.get(m);
//判断小节里的chaapterid和章节里的id是否一样
if (eduVideo.getChapterId().equals(eduChapter.getId())){
VideoVo videoVo = new VideoVo();
BeanUtils.copyProperties(eduVideo,videoVo);
videoList.add(videoVo);
}
}
//把封装之后小节的list集合,放到章节对象里面
chapterVo.setChildren(videoList);
}
return finalList;
}
}
二.前端实现
1.在api中定义方法chapter.js
import request from '@/utils/request'
export default{
//1.根据课程id获取章节和小节数据列表
getAllChapterVideo(courseId){
return request({
url:'/eduservice/chapter/getChapterVideo/'+courseId,
method: 'get'
})
}
}
2.在chapter.vue中添加方法
import chapter from '@/api/edu/chapter'
//根据课程id查询章节和小节
getChapterVideo(){
chapter.getAllChapterVideo(this.courseId)
.then(resp=>{
this.chapterVideoList= resp.data.allChapterVideo
})
},
3.获取courseId值
因为根据id获取章节和小净,所以需要获取课程id,而id需要从请求路径中获取
如果里面有参数,并且有id参数,则把值赋值给courseId。并且调用获取章节和小节的方法
created(){
//获取路由中的id值
if(this.$route.params&&this.$route.params.id){
this.courseId=this.$route.params.id
//根据课程id值查询章节和小节
this.getChapterVideo()
}
}
4.前端显示
<!-- 章节 -->
<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>
最终代码
<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 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>
<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'
export default {
data(){
return{
saveBtnDisabled:false,
courseId:'',
chapterVideoList:[]
}
},
created(){
//获取路由中的id值
if(this.$route.params&&this.$route.params.id){
this.courseId=this.$route.params.id
//根据课程id值查询章节和小节
this.getChapterVideo()
}
},
methods:{
//根据课程id查询章节和小节
getChapterVideo(){
chapter.getAllChapterVideo(this.courseId)
.then(resp=>{
this.chapterVideoList= resp.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>