/**
* 章节和小节的vo类
*/
@Data
@ApiModel("章节和小节的vo类")
public class ChapterVo {
private String id;
private String title;
//如果是章节用于存放其包含小节
//如果是小节则为空
private List<ChapterVo> children = null;
}
接口
public interface EduChapterService extends IService<EduChapter> {
List<ChapterVo> getChapterByCourseId(String courseId);
}
实现
@Service
public class EduChapterServiceImpl extends ServiceImpl<EduChapterMapper, EduChapter> implements EduChapterService {
@Autowired
private EduVideoMapper videoMapper;
/**
* 根据课程id获取课程包含的章节和小节信息
* 并以ChapterVo的形式作为结果集返回
* @param courseId
* @return
*/
@Override
public List<ChapterVo> getChapterByCourseId(String courseId) {
//用于存放章节和小节列表(树状)
List<ChapterVo> res = new ArrayList<>();
//根据课程id插入课程所有的章节
QueryWrapper<EduChapter> chapterWrapper = new QueryWrapper<>();
chapterWrapper.eq("course_id", courseId);
List<EduChapter> chapters = baseMapper.selectList(chapterWrapper);
//根绝课程id查询出该课程所有小节
QueryWrapper<EduVideo> videoWrapper = new QueryWrapper<>();
chapterWrapper.eq("course_id", courseId);
List<EduVideo> videos = videoMapper.selectList(videoWrapper);
for (EduChapter chapter : chapters) {
ChapterVo chapterVo = new ChapterVo();
BeanUtils.copyProperties(chapter, chapterVo);
//为章节创建children列表
chapterVo.setChildren(new ArrayList<>());
String chapterId = chapterVo.getId();
//遍历所有小节,将与chapterVo对应的小节存入children列表中
for (EduVideo video : videos) {
if (chapterId != null && chapterId.equals(video.getChapterId())){
ChapterVo videoVo = new ChapterVo();
BeanUtils.copyProperties(video, videoVo);
chapterVo.getChildren().add(videoVo);
}
}
//将章节存入结果集中
res.add(chapterVo);
}
return res;
}
}
@RestController
@RequestMapping("/eduservice/chapter")
@CrossOrigin
@Api("课程章节管理")
public class EduChapterController {
@Autowired
private EduChapterService chapterService;
@ApiOperation("根绝课程id获取其对应的章节和小节")
@GetMapping("list/{courseId}")
public R getCourseChapter(
@PathVariable("courseId") String courseId) {
List<ChapterVo> list = chapterService.getChapterByCourseId(courseId);
return R.ok().data("list", list);
}
}
在scr/api/edu
下创建chapter.js,内容如下:
import request from '@/utils/request'
//表示导出,别的文件可以使用
export default {
/**
* 添加课程信息
*/
getCourseChapter(courseId){
return request({
url: `/eduservice/chapter/list/${courseId}`,
method: 'get',
})
},
}
定义data
courseId: '', // 所属课程
chapterNestedList: [] // 章节嵌套课时列表
methods中添加方法
methods: {
//根据课程id获取章节和小节信息
getCourseChapter(){
chapterApi.getCourseChapter(this.courseId)
.then(response => {
this.chapterNestedList = response.data.list
})
},
...//其他方法
}
created中调用上述方法
created() {
//根据路由获取url中的id值
if(this.$route.params && this.$route.params.id){
this.courseId = this.$route.params.id
//根据课程id获取章节和小节信息
this.getCourseChapter()
}
},
<el-button type="text">添加章节el-button>
<ul class="chanpterList">
<li
v-for="chapter in chapterNestedList"
: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>
将样式的定义放在页面的最后
scope表示这里定义的样式只在当前页面范围内生效,不会污染到其他的页面
<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>
接口:CourseService.java
CourseInfoVo getCourseInfoById(String id);
实现:CourseServiceImpl.java
/**
* 根据课程id获取课程基本信息和课程描述信息
* 并封装到CourseInfoVo中
* @param id
* @return
*/
@Override
public CourseInfoVo getCourseInfoById(String id) {
CourseInfoVo courseInfo = new CourseInfoVo();
//从数据库获取课程基本信息
EduCourse eduCourse = baseMapper.selectById(id);
//将基本信息赋值给courseInfo
BeanUtils.copyProperties(eduCourse, courseInfo);
//从数据库获取课程描述信息,描述信息id和课程信息一致
EduCourseDescription description = descriptionService.getById(id);
courseInfo.setDescription(description.getDescription());
return courseInfo;
}
@ApiOperation(value = "根据id获取课程基本信息")
@GetMapping("{id}")
public R getCourseById(@PathVariable String id) {
//根据id获取课程基本信息,包括课程描述信息
CourseInfoVo course = courseService.getCourseInfoById(id);
return R.ok().data("course", course);
}
后端实现之后,接下来实现前端的内容
在api/edu/course.js
中添加如下内容
/**
* 根据课程id获取课程基本信息和课程描述信息
*/
getCourseInfoById(id){
return request({
url: `/eduservice/course/${id}`,
method: 'get',
})
},
previous() {
console.log('previous')
this.$router.push({ path: '/course/info/'+this.courseId })
},
next() {
console.log('next')
this.$router.push({ path: '/course/publish/'+this.courseId })
}
在course.vue中
data() {
return {
...
courseId: '', //修改时路径中传来的课程id
...
}
}
在course.vue中
methods: {
//根据课程id获取课程信息
getCourseInfo(id){
courseApi.getCourseInfoById(id)
.then(response => {
this.courseInfo = response.data.course
})
},
...
}
在course.vue中
created() {
//根据路由获取url中的id值
if(this.$route.params && this.$route.params.id){
this.courseId = this.$route.params.id
this.getCourseInfo(this.courseId)
}
this.getAllTeacherList()
this.getAllSubjectrList()
},
可以看到上面的测试中课程的二级类编显示是id而不是名称,所以我们需要进行解决
将 this.initSubjectList()移至else
created() {
//根据路由获取url中的id值
if(this.$route.params && this.$route.params.id){ //修改
this.courseId = this.$route.params.id
this.getCourseInfo(this.courseId)
} else{ //添加
this.getAllSubjectrList()
}
//获取讲师列表
this.getAllTeacherList()
},
//根据课程id获取课程信息
getCourseInfo(id){
courseApi.getCourseInfoById(id)
.then(response => {
this.courseInfo = response.data.course
//调用接口获取所有的课程分类信息
subjectApi.getAllSubject()
.then(response => {
debugger
this.subjectParentList = response.data.list
//对一级分类进行遍历找到其中courseId与this.courseId相等的一级分类
//并将其中包含的二级分类信息赋值为this.subSubjidectList
for (let i = 0; i < this.subjectParentList.length; i++) {
if (this.subjectParentList[i].id === this.courseInfo.subjectParentId) {
this.subSubjectList = this.subjectParentList[i].children
}
}
})
})
},
接口:CourseService.java
void updateCourseInfo(CourseInfoVo course);
实现:CourseServiceImpl.java
/**
* 更新课程基本信息和描述信息
* @param courseInfo
*/
@Override
public void updateCourseInfo(CourseInfoVo courseInfo) {
//创建并赋值EduCourse对象
EduCourse course = new EduCourse();
BeanUtils.copyProperties(courseInfo, course);
//更新数据库
int update1 = baseMapper.updateById(course);
if (update1 == 0) {
throw new CustomException(20001, "修改课程基本信息失败");
}
//创建并赋值EduCourseDescription对象
EduCourseDescription description = new EduCourseDescription();
description.setId(courseInfo.getId());
description.setDescription(courseInfo.getDescription());
description.setGmtModified(new Date());
//更新数据库
boolean update2 = descriptionService.updateById(description);
if (!update2) {
throw new CustomException(20001, "修改课程描述信息失败");
}
}
@ApiOperation(value = "根据课程基本信息,包括课程描述信息")
@PostMapping("update")
public R updateCourse(@RequestBody CourseInfoVo course) {
courseService.updateCourseInfo(course);
return R.ok();
}
后端实现之后,接下来实现前端的内容
在api/edu/course.js
中添加如下内容
/**
* 更新课程基本信息和描述信息
*/
updateCourseInfo(courseInfo){
return request({
url: `/eduservice/course/update`,
method: 'post',
data:courseInfo
})
},
将之前的next方法修改为下面的内容
//添加或者修改课程信息
next() {
//更新时会从接口查询出courseInfo,其中会包括id
if(this.courseInfo.id){ //修改
this.updateCourse()
} else {
this.addCourse()
}
},
//修改课程信息
updateCourse(){
courseApi.updateCourseInfo(this.courseInfo)
.then(response => {
this.$message({
type: 'success',
message: '修改课程信息成功'
})
this.$router.push({ path: '/course/chapter/'+this.courseId })
})
.catch(error => {
this.saveBtnDisabled = false
console.log(error)
}) //请求失败
},
//添加课程信息
addCourse(){
console.log('next')
this.saveBtnDisabled = true
courseApi.addCourseInfo(this.courseInfo)
.then(response=>{
this.$message({
type: 'success',
message: '添加课程信息成功'
})
this.$router.push({ path: '/course/chapter/'+response.data.id })
})
.catch(error => {
this.saveBtnDisabled = false
console.log(error)
}) //请求失败
}
首先在表单中输入信息并点击保存下一步
之后点击上一步,再次修改表单内容表单
点击保存并下一步,提示修改课程信息成功
查看数据库中已经修改成功