1 课程大纲列表和章节管理
01-课程大纲列表显示
一、后端实现
1、定义vo
章节:ChapterVo
@Data
@ApiModel(value = "章节信息")
public class ChapterVo {
private String id;
private String title;
//表示小节
private List<VideoVo> children = new ArrayList<>();
}
小节:VideoVo
@Data
@ApiModel(value = "课时信息")
public class VideoVo {
private String id;
private String title;
}
2、服务层
接口
public interface EduChapterService extends IService
{ //根据课程id进行查询章节小节
List
getChapterVideoByCourseId(String courseId); }
实现
@Service
public class EduChapterServiceImpl extends ServiceImpl
implements EduChapterService { //在Chapter里面不能查询Video,因此需要将Video的接口注入进来
@Autowired
private EduVideoService videoService;
//根据课程id进行查询章节小节
@Override
public List
getChapterVideoByCourseId(String courseId) { //1 根据课程id查询课程里面的所有章节EduChapter
QueryWrapper<EduChapter> wrapperChapter = new QueryWrapper<>();
wrapperChapter.eq("course_id",courseId);
List
eduChapterList = baseMapper.selectList(wrapperChapter);
//2 根据课程id查询课程里面的所有小节EduVideo
QueryWrapper<EduVideo> wrapperVideo = new QueryWrapper<>();
wrapperVideo.eq("course_id",courseId);
List
eduVideoList = videoService.list(wrapperVideo);
//创建list集合,用于最终封装数据
List
finalList = new ArrayList<>();
//3 遍历查询章节list集合进行封装
//遍历查询章节list集合
for (int i = 0; i < eduChapterList.size(); i++) {
//每个章节
EduChapter eduChapter = eduChapterList.get(i);
//把eduChapter对象值复制到chapterVo里面
ChapterVo chapterVo = new ChapterVo();
BeanUtils.copyProperties(eduChapter,chapterVo);
//把chapterVo放到最终list集合
finalList.add(chapterVo);
//创建集合,用于封装小节
List
videoVoList = 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);
videoVoList.add(videoVo);
}
}
//把封装的小节list集合放到章节对象chapterVo里面
chapterVo.setChildren(videoVoList);
}
return finalList;
}
}
3、web层
@Api(description="课程章节管理")
@RestController
@RequestMapping("/eduservice/chapter")
@CrossOrigin
public class EduChapterController {
@Autowired
EduChapterService chapterService;
//课程大纲列表,查询课程下的章节和小节,根据课程id进行查询章节小节
@ApiOperation(value = "嵌套章节数据列表")
@GetMapping("getChapterVideo/{courseId}")
public R getChapterVideo(@ApiParam(name = "courseId", value = "课程ID", required = true)
@PathVariable String courseId){
List
list = chapterService.getChapterVideoByCourseId(courseId); return R.ok().data("allChapterVideo",list);
}
}
4、Swagger测试
二、前端实现
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、定义组件脚本
定义data
courseId:'', // 所属课程
chapterVideoList:[], // 章节嵌套课时列表
定义相关methods获取章节和课时列表
//根据课程id查询章节和小节
getChapterVideo(){
chapter.getAllChapterVideo(this.courseId)
.then(response=>{
this.chapterVideoList = response.data.allChapterVideo
})
},
获取路由的id
created(){
//获取路由的id
//判断里面如果有参数,并且是id参数,则获取
if(this.$route.params && this.$route.params.id){
this.courseId = this.$route.params.id
//根据课程id查询章节和小节
this.getChapterVideo()
}
},
3、定义组件模板
简单的无样式:
{{chapter.title}}
- chapter.children" :key="video.id">
{{video.title}}
含有样式:
v-for="chapter in chapterVideoList"
:key="chapter.id">
{{ chapter.title }}
添加课时
编辑
删除
v-for="video in chapter.children"
:key="video.id">
{{ video.title }}
编辑
删除
上一步
下一步
http://localhost:9528/#/course/chapter/14
4、定义样式
将样式的定义放在页面的最后
scope表示这里定义的样式只在当前页面范围内生效,不会污染到其他的页面
.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;
}
02-章节管理后端接口开发
一、新增章节
web层
//新增章节
@ApiOperation(value = "新增章节")
@PostMapping("addChapter")
public R addChapter(@RequestBody EduChapter eduChapter){
chapterService.save(eduChapter);
return R.ok();
}
二、根据id查询
web层
//根据id查询
@ApiOperation(value = "根据ID查询章节")
@GetMapping("getChapterById/{id}")
public R getChapterById(@ApiParam(name = "id", value = "章节ID", required = true)
@PathVariable String id){
EduChapter eduChapter = chapterService.getById(id);
return R.ok().data("chapter",eduChapter);
}
三、更新
web层
//根据ID修改章节
@ApiOperation(value = "根据ID修改章节")
@PostMapping("updateChapterById")
public R updateChapterById( @ApiParam(name = "chapter", value = "章节对象", required = true)
@RequestBody EduChapter eduChapter){
chapterService.updateById(eduChapter);
return R.ok();
}
四、删除
1、web层
//根据ID删除章节
//章节里面有小节需要先将小节删除
@ApiOperation(value = "根据ID删除章节")
@DeleteMapping("{chapterId}")
public R deleteChapterById(@PathVariable String chapterId){
boolean flag = chapterService.deleteChapter(chapterId);
if (flag){
return R.ok();
}else {
return R.error();
}
}
2、Service
EduChapterService层:接口
//根据ID删除章节
//章节里面有小节需要先将小节删除
boolean deleteChapter(String chapterId);
ChapterService层:实现
//删除章节的方法
@Override
public boolean deleteChapter(String chapterId) {
//根据chapterId章节id 查询小节表,如果查询数据,不进行删除
QueryWrapper
wrapper = new QueryWrapper<>(); wrapper.eq("chapter_id",chapterId);
//返回的是集合,但是我们只需要判断章节里有没有小节
// List
list = videoService.list(wrapper); int count = videoService.count(wrapper);
//判断
if (count > 0 ){//查询出小节,不进行删除
throw new GuliException(20001,"该分章节下存在视频课程,请先删除视频课程");
}else {
//删除章节
int result = baseMapper.deleteById(chapterId);
//成功 1>0 0>0
return result>0;
}
}
五、Swagger测试
03-章节管理前端页面实现
一、定义api
//添加章节 传入章节对象chapter
addChapter(chapter){
return request({
url:`/eduservice/chapter/addChapter`,
method:'post',
data:chapter
})
},
//根据ID查询章节
getChapter(chapterId){
return request({
url:`/eduservice/chapter/getChapterById/${chapterId}`,
method:'get'
})
},
//修改章节
updateChapter(chapter){
return request({
url:`/eduservice/chapter/updateChapterById`,
method:'post',
data:chapter
})
},
//删除章节
deleteChapter(chapterId){
return request({
url:`/eduservice/chapter/${chapterId}`,
method:'delete'
})
}
二、新增章节页面功能
1、定义data数据
dialogChapterFormVisible:false,//设置默认弹框的值false(即不显示)
chapter:{//章节对象
title:'',
sort:0
},
2、添加章节按钮
@click="dialogChapterFormVisible = true">添加章节
3、章节表单dialog
"dialogChapterFormVisible = false">取 消
saveOrUpdate">确 定
4、添加章节methods
//添加章节
saveOrUpdate(){
chapter.addChapter(this.chapter)
.then(response=>{
//关闭弹框
this.dialogChapterFormVisible = false
//提示信息
this.$message({
type:'success',
message:'添加章节成功'
});
//刷新页面 即把所有数据再查询一次
this.getChapterVideo()
})
},
执行了全局异常处理:说明后端代码有问题了
错误原因:chapter对象的实体类中有courseId没有值
//添加章节
saveOrUpdate(){
//设置课程id到chapter对象里面
//因为chapter对象的实体类中有courseId
this.chapter.courseId = this.courseId
chapter.addChapter(this.chapter)
.then(response=>{
//关闭弹框
this.dialogChapterFormVisible = false
//提示信息
this.$message({
type:'success',
message:'添加章节成功'
});
//刷新页面 即把所有数据再查询一次
this.getChapterVideo()
})
},
问题:
解决方案:每次弹框的时候把表单数据清空
@click="dialogChapterFormVisible = true">添加章节
把添加章节中的值写到一个方法里面:
@click="openChapterDialog()">添加章节
通过方法进行弹框操作:
//弹出添加章节页面
openChapterDialog(){
//弹框
this.dialogChapterFormVisible = true
//表单数据清空
this.chapter.title =''
this.chapter.sort = 0
},
三、修改章节信息
1、编辑章节按钮
v-for="chapter in chapterVideoList"
:key="chapter.id">
{{ chapter.title }}
添加课时
@click="openEditChapter(chapter.id)">编辑
删除
2、定义编辑方法
//修改章节弹框、数据回显
//方法中需要章节id,如chapterId
openEditChapter(chapterId){
//弹框
this.dialogChapterFormVisible = true
//调用接口
chapter.getChapter(chapterId)
.then(response=>{
this.chapter = response.data.chapter
})
},
3、定义更新方法
//修改章节 与添加章节差不多
updateChapter(){
//设置课程id到chapter对象里面
//因为chapter对象的实体类中有courseId
this.chapter.courseId = this.courseId
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()
}
},
四、删除章节
1、按钮
removeChapter(chapter.id)">删除
2、定义删除方法
//删除章节
removeChapter(chapterId){
this.$confirm('此操作将删除章节, 是否继续?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {//点击确定,执行then方法
//调用删除的方法
chapter.deleteChapter(chapterId)
.then(response=>{//删除成功
//提示信息
this.$message({
type: 'success',
message: '删除成功!'
})
//刷新页面 即把所有数据再查询一次
this.getChapterVideo()
})
})//点击取消,执行catch方法
},
2 课时(小节)管理
01-课时管理后端开发
EduVideoController.java
@RestController
@RequestMapping("/eduservice/video")
@CrossOrigin
public class EduVideoController {
@Autowired
private EduVideoService eduVideoService;
//添加小节
@ApiOperation(value = "添加小节")
@PostMapping("addVideo")
public R addVideo(@ApiParam(name = "videoForm", value = "课时对象", required = true)
@RequestBody EduVideo eduVideo){
eduVideoService.save(eduVideo);
return R.ok();
}
//删除小节
//TODO 后面这个方法需要完善:删除小节的时候,同时把里面视频删除
@DeleteMapping("deleteVideo/{id}")
public R deleteVideo(@PathVariable String id){
eduVideoService.removeById(id);
return R.ok();
}
//根据id查询
@ApiOperation(value = "根据ID查询小节")
@GetMapping("getVideoById/{id}")
public R getVideoById(String id){
EduVideo eduVideo = eduVideoService.getById(id);
return R.ok().data("video",eduVideo);
}
//修改小节
@PostMapping("updateVideo")
public R updateVideo(@RequestBody EduVideo eduVideo){
eduVideoService.updateById(eduVideo);
return R.ok();
}
}
openVideo(chapter.id)">添加小节
添加和修改课时表单:课时表单dialog
video.title"/>
video.sort" :min="0" controls-position="right"/>
video.free">
免费
默认
取 消
确 定
data
// video对象的定义
video:{
title:'',
sort:0,
free:0,
videoSourceId:''
},
dialogVideoFormVisible:false
methods
//添加小节弹框方法
openVideo(chapterId){
this.dialogVideoFormVisible = true
},
测试:
http://localhost:9528/#/course/chapter/1281130194916139010
定义api
创建video.js
参考course.js
import request from '@/utils/request'
export default{
//添加小节
addVideo(video){
return request({
url:`/eduservice/video/addVideo`,
method:'post',
data:video
})
},
//根据ID查询小节
getVideo(id){
return request({
url:`/eduservice/video/deleteVideo/${id}`,
method:'get'
})
},
//修改小节
updateVideo(video){
return request({
url:`/eduservice/video/updateVideo`,
method:'post',
data:video
})
},
//删除小节
deleteVideo(id){
return request({
url:`/eduservice/chapter/deleteVideo/${id}`,
method:'delete'
})
}
}
引入到chapter.vue
import video from'@/api/edu/video'
添加小节的时候需要课程id和章节id:
//添加小节弹框方法
openVideo(chapterId){
//弹框
this.dialogVideoFormVisible = true
//添加小节的时候需要课程id和章节id
//设置章节id
this.video.chapterId = chapterId
//设置课程id
this.video.courseId = this.courseId
},
添加小节方法:
//添加小节
addVideo(){
video.addVideo(this.video)
.then(response=>{
//关闭弹框
this.dialogVideoFormVisible = false
//提示信息
this.$message({
type:'success',
message:'添加小节成功'
});
//刷新页面 即把所有数据再查询一次
this.getChapterVideo()
})
},
saveOrUpdateVideo(){
this.addVideo()
},
测试:
清空表单数据:
//添加小节弹框方法
openVideo(chapterId){
//弹框
this.dialogVideoFormVisible = true
//添加小节的时候需要课程id和章节id
//设置章节id
this.video.chapterId = chapterId
//设置课程id
this.video.courseId = this.courseId
//表单数据清空
this.video.title = ''
this.video.sort = 0
this.video.free = 0
this.videoSourceId = ''
},
编辑:
openEditVideo(video.id)">编辑
//小节弹框、数据回显
//方法中需要小节id
openEditVideo(videoId){
//弹框
this.dialogVideoFormVisible = true
//调用接口
video.getVideo(videoId)
.then(response=>{
this.video = response.data.video
})
},
解决是否免费不回显问题:
修改与实体类里面对应:将所有free改为isFree
解决添加小节表单的是否免费没有默认值问题:
02-课时管理前端开发
删除课时
1、按钮
@click="removeVideo(video.id)">删除
2、定义删除方法
//删除小节
removeVideo(videoId){
this.$confirm('此操作将删除小节, 是否继续?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {//点击确定,执行then方法
//调用删除的方法
video.deleteVideo(videoId)
.then(response=>{//删除成功
//提示信息
this.$message({
type: 'success',
message: '删除成功!'
})
//刷新页面 即把所有数据再查询一次
this.getChapterVideo()
})
})//点击取消,执行catch方法
},
http://localhost:9528/#/course/chapter/1281130194916139010
3 课程最终发布
http://localhost:9528/#/course/publish/1281130194916139010
可以根据课程id查询。
把课程信息最终显示进行确认,但是需要查询多张表
方法一:可以使用封装的方式,比如章节小节,一级二级分类。
但是现在不太合适因为表比较多。
在实际中,当查询的表比较多,或者要写一些复杂的查询操作,一般建议手写sql语句实现。
多表连接查询
内连接:查询两张表有关联的数据,比如下表只能查询出前两条数据,运维没有关联,因此查询不出来
左外连接(LEFT OUTER JOIN,OUTER可省略):左边表所有数据都查出来,右边表只查关联
右外连接:右边表所有数据都查出来,左边表只查关联
一般用的比较多的是内连接和左外连接。
本案例中,特点:课程中课程没有简介,即简介为空;可能也没有分类,也没有讲师。所以使用内连接不太合适。因此使用左外连接比较合适。
左外连接查询课程简介、课程讲师:
课程分类:特点有两个ID(一个一级分类,一个二级分类),但是一级分类、二级分类都保存在edu_subject表中,如果一张表中有多个字段都同时关联同一张表,可以查询多次,可以先使用一级分类ID查询表关联出来,再使用二级分类ID查询关联出来,即查询两次。
根据课程id进行查询:
测试:
SELECT *
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_id = es1.id
WHERE ec.id='1281130194916139010'
mapper:
mapper中有接口和接口有对应的配置文件,在接口中可以定义方法,在配置文件中写sql语句。
在配置文件中编写sql语句:
在接口中编方法,根据课程id查询课程基本信息方法,这个方法需要编写一个返回对象(之前定义的对象都不太合适),专门进行封装。
02-课程最终发布后端
一、根据id查询课程发布信息
1、定义vo
CoursePublishVo:
@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;//只用于显示
}
2、数据访问层
在接口EduCourseMapper.java中编方法
public interface EduCourseMapper extends BaseMapper
{ public CoursePublishVo getPublishCourseInfo(String courseId);
}
实现:EduCourseMapper.xml编写sql语句
可通过select标签进行查询,属性一:id值为mapper接口中的方法名称,属性二:resultType返回值类型需要为包和类型的全路径。
在select中编写sql语句,进行修改,需要与实体类进行对应:
课程id是需要传递过来的,法一:where ec.id=#{courseId} 法二:where ec.id=${courseId},但是我们一般不用$,因为$表示字符串拼接,会产生sql注入问题。
SELECT ec.id,ec.price,ec.title,ec.cover,ec.lesson_num AS lessonNum,
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_id = es2.id
WHERE ec.id=#{courseId}
3、web层
//根据ID获取课程发布信息
@ApiOperation(value = "根据ID获取课程发布信息")
@GetMapping("getPublishCourseInfo/{courseId}")
public R getPublishCourseInfo(@PathVariable String courseId){
CoursePublishVo coursePublishVo = courseService.getPublishCourseInfo(courseId);
return R.ok().data("publish",coursePublishVo);
}
4、业务层
接口:
//根据ID获取课程发布信息
CoursePublishVo getPublishCourseInfo(String courseId);
实现:
@Override
public CoursePublishVo getPublishCourseInfo(String courseId) {
return baseMapper.getPublishCourseInfo(courseId);
}
//调用mapper,在impl实现类中调用方法,可以使用baseMapper也可以写this,但是调用我们自己写的mapper,就必须写baseMapper才能调到。
通过controller调service,然后service用baseMapper调mapper中的方法,方法会最终执行到sql语句,得到数据。
测试:报告异常“执行了全局异常处理”
BinDing : 数据绑定异常。
org.apache.ibatis.binding.BindingException: Invalid bound statement (not found): com.atguigu.eduservice.mapper.EduCourseMapper.getPublishCourseInfo
导致这个错误的两个原因:一 看mapper中的方法名......是否写错;二 由于maven默认的加载机制造成的问题,maven加载时候,把java文件夹里面. java类型文件进行编译,如果其他类型文件,不会加载。
问题分析:
dao层编译后只有class文件,没有mapper.xml,因为maven工程在默认情况下src/main/java目录下的所有资源文件是不发布到target目录下的,
解决方案:
1、在guli_edu的pom中配置如下节点
*表示加载的是一级目录
**表示多级目录,在xml前面有很多级目录
src/main/java
**/*.xml
false
2、在Spring Boot配置文件中添加配置(service_edu的application.properties)
#配置mapper xml文件的路径
mybatis-plus.mapper-locations=classpath:com/atguigu/eduservice/mapper/xml/*.xml
classpath表示类路径:src里面的内容
重新启动,在swagger中测试:
courseId:1281130194916139010
01-课程最终发布前端
一、前端代码
发布页面课程信息显示:
1、定义api
分析这个页面一共有两个远程方法:一个是根据课程id获取课程基本预览信息,第二个是发布课程
/api/edu/course.js
//发布课程
getPublicCourseInfo(courseId){
return request({
url:`/eduservice/course/getPublishCourseInfo/${courseId}`,
method:'get'
})
}
2、定义数据模型
/edu/course/publish.vue
data(){
return {
saveBtnDisabled: false, // 保存按钮是否禁用
courseId:'',// 所属课程
coursePublish:{}
}
},
3、组件方法定义
在publish.vue中引入js文件
import course from '@/api/edu/course'
得到路由中的id值:
created(){
if(this.$route.params && this.$route.params.id){
this.courseId = this.$route.params.id
}
},
调用接口中的方法:
created(){
if(this.$route.params && this.$route.params.id){
this.courseId = this.$route.params.id
// 根据id获取课程基本信息
this.getCoursePublishId()
}
},
编写获取数据的方法:
//根据课程id查询
getCoursePublishId(){
course.getPublicCourseInfo(this.courseId)
.then(response=>{
this.coursePublish = response.data.publish
})
}
4、组件模板
把内容在页面中进行显示,获取publishCourse对象里面的值,通过{{}}。
coursePublish.cover">
{{ coursePublish.title }}
共{{ coursePublish.lessonNum }}课时
所属分类:{{ coursePublish.subjectLevelOne }} — {{ coursePublish.subjectLevelTwo }}
课程讲师:{{ coursePublish.teacherName }}
¥{{ coursePublish.price }}
<div>
返回修改
发布课程 div>
5、css样式
.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;
}
http://localhost:9528/#/course/publish/1281130194916139010
发布课程(修改课程状态):
一、根据id发布课程
1、web层
//根据id发布课程
//课程最终发布
//修改课程状态
@ApiOperation(value = "根据id发布课程")
@PostMapping("publishCourse/{courseId}")
public R publishCourse(@PathVariable String courseId){
EduCourse eduCourse = new EduCourse();
eduCourse.setId(courseId);
eduCourse.setStatus("Normal");//设置课程发布状态
courseService.updateById(eduCourse);
return R.ok();
}
二、前端
1、定义api
分析这个页面一共有两个远程方法:一个是根基课程id获取课程基本预览信息,第二个是发布课程
/api/edu/course.js
//课程最终发布
publicCourseInfo(courseId){
return request({
url:`/eduservice/course/publishCourse/${courseId}`,
method:'post'
})
}
2、组件方法定义
发布课程的点击事件
publish(){
this.$confirm('发布课程, 是否继续?', '提示', {
confirmButtonText: '继续',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {//点击继续,执行then方法
course.publicCourseInfo(this.courseId)
.then(response=>{
//提示信息
this.$message({
type: 'success',
message: '发布成功!'
})
//跳转到第二步
this.$router.push({path:'/course/list'})
})
})//点击取消,执行catch方法
},
测试: