Tinymce可视化编辑器
组件初始化
new HtmlWebpackPlugin({
......,
templateParameters: {
BASE_URL: config.dev.assetsPublicPath + config.dev.assetsSubDirectory
}
})
引入js脚本
<script src=<%= BASE_URL %>/tinymce4.7.5/tinymce.min.js></script>
<script src=<%= BASE_URL %>/tinymce4.7.5/langs/zh_CN.js></script>
组件引入
<el-form-item label="课程简介">
<tinymce :height="300" v-model="courseInfo.description"/>
el-form-item>
<script>
import Tinymce from '@/components/Tinymce'
export default {
components: { Tinymce },
......
}
script>
<style scoped>
.tinymce-container {
line-height: 29px;
}
style>
@Data
public class ChapterVo {
private String id;
private String title;
// 表示小节
private List<VideoVo> children = new ArrayList<>();
}
@Data
public class VideoVo {
private String id;
private String title;
}
@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);
}
}
public interface EduChapterService extends IService<EduChapter> {
// 课程大纲列表,根据课程id进行查询
List<ChapterVo> getChapterVideoByCourseId(String courseId);
}
@Service
public class EduChapterServiceImpl extends ServiceImpl<EduChapterMapper, EduChapter> implements EduChapterService {
@Autowired
private EduVideoService videoService; // 注入小节service
// 课程大纲列表,根据课程id进行查询
@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<>();
wrapperVideo.eq("course_id", courseId);
List<EduVideo> eduVideoList = videoService.list(wrapperVideo);
// 创建list集合,用于最终封装数据
List<ChapterVo> 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<VideoVo> videoList = new ArrayList<>();
// 4.遍历查询小节list集合进行封装
for (int m = 0; m < eduVideoList.size(); m++) {
// 得到每个小节
EduVideo eduVideo = eduVideoList.get(m);
// 判断:小节里面chapterId和章节里面的id是否一样
if(eduVideo.getChapterId().equals(eduChapter.getId())) {
// 进行封装
VideoVo videoVo = new VideoVo();
BeanUtils.copyProperties(eduVideo,videoVo);
// 放到小节封装集合
videoList.add(videoVo);
}
}
// 把封装之后小节list集合,放到章节对象里面
chapterVo.setChildren(videoList);
}
return finalList;
}
}
// src\api\edu\chapter.js
import request from '@/utils/request'
export default {
// 1. 根据课程id获取章节和小节数据列表
getAllChapterVideo(courseId) {
return request({
url: '/eduservice/chapter/getChapterVideo/' + courseId,
method: 'get'
})
}
}
<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 }}
p>
<ul class="chanpterList videoList">
<li
v-for="video in chapter.children"
:key="video.id">
<p>{{ video.title }}
p>
li>
ul>
li>
ul>
<div>
<el-button @click="previous">上一步el-button>
<el-button :disabled="saveBtnDisabled" type="primary" @click="next">下一步el-button>
div>
div>
template>
<script>
import chapter from '@/api/edu/chapter'
export default {
data() {
return {
saveBtnDisabled: false, // 保存按钮是否禁用
courseId: '', // 课程id
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(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;
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>
@RestController
@RequestMapping("/eduservice/course")
@CrossOrigin
public class EduCourseController {
@Autowired
private EduCourseService courseService;
// 根据课程id查询课程基本信息
@GetMapping("getCourseInfo/{courseId}")
public R getCourseInfo(@PathVariable String courseId) {
CourseInfoVo courseInfoVo = courseService.getCourseInfo(courseId);
return R.ok().data("courseInfoVo", courseInfoVo);
}
// 修改课程信息
@PostMapping("updateCourseInfo")
public R updateCourseInfo(@RequestBody CourseInfoVo courseInfoVo) {
courseService.updateCourseInfo(courseInfoVo);
return R.ok();
}
}
public interface EduCourseService extends IService<EduCourse> {
// 根据课程id查询课程基本信息
CourseInfoVo getCourseInfo(String courseId);
// 修改课程信息
void updateCourseInfo(CourseInfoVo courseInfoVo);
}
@Service
public class EduCourseServiceImpl extends ServiceImpl<EduCourseMapper, EduCourse> implements EduCourseService {
@Autowired
private EduCourseDescriptionService courseDescriptionService;
// 根据课程id查询课程基本信息
@Override
public CourseInfoVo getCourseInfo(String courseId) {
// 1.查询课程表
EduCourse eduCourse = baseMapper.selectById(courseId);
CourseInfoVo courseInfoVo = new CourseInfoVo();
BeanUtils.copyProperties(eduCourse, courseInfoVo);
// 2.查询描述表
EduCourseDescription courseDescription = courseDescriptionService.getById(courseId);
courseInfoVo.setDescription(courseDescription.getDescription());
return courseInfoVo;
}
// 修改课程信息
@Override
public void updateCourseInfo(CourseInfoVo courseInfoVo) {
// 1.修改课程表
EduCourse eduCourse = new EduCourse();
BeanUtils.copyProperties(courseInfoVo, eduCourse);
int update = baseMapper.updateById(eduCourse);
if(update == 0) {
throw new LemonException(20001, "修改课程信息失败");
}
// 2.修改描述表
EduCourseDescription description = new EduCourseDescription();
description.setId(courseInfoVo.getId());
description.setDescription(courseInfoVo.getDescription());
courseDescriptionService.updateById(description);
}
}
// src\api\edu\course.js
import request from '@/utils/request'
export default {
// 1. 添加课程信息
addCourseInfo(courseInfo) {
return request({
url: '/eduservice/course/addCourseInfo',
method: 'post',
data: courseInfo
})
},
// 2. 查询所有讲师
getListTeacher() {
return request({
url: '/eduservice/teacher/findAll',
method: 'get'
})
},
// 3. 根据课程id查询课程基本信息
getCourseInfoId(id) {
return request({
url: '/eduservice/course/getCourseInfo/' + id,
method: 'get'
})
},
// 4. 修改课程信息
updateCourseInfo(courseInfo) {
return request({
url: '/eduservice/course/updateCourseInfo/',
method: 'post',
data: courseInfo
})
},
}
// src\views\edu\course\chapter.vue
methods: {
previous(){
this.$router.push({ path: '/course/info/' + this.courseId })
},
next() {
this.$router.push({ path: '/course/publish/' + this.courseId })
}
// src\views\edu\course\chapter.vue
created() {
// 获取路由id值
if(this.$route.params && this.$route.params.id) {
this.courseId = this.$route.params.id
// 调用根据id查询课程的方法
this.getInfo()
}
// 初始化所有讲师
this.getListTeacher()
// 初始化一级分类
this.getOneSubject()
},
methods: {
// 根据课程id查询
getInfo() {
course.getCourseInfoId(this.courseId)
.then(response => {
this.courseInfo = response.data.courseInfoVo
})
}
}
// src\views\edu\course\info.vue
<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: {
title: '',
subjectId: '', // 二级分类ID
subjectParentId: '', // 一级分类ID
teacherId: '',
lessonNum: 0,
description: '',
cover: '/static/04.jpg',
price: 0
},
courseId: '',
BASE_API: process.env.BASE_API, // 接口API地址
teacherList: [], // 封装所有的讲师
subjectOneList: [], // 一级分类
subjectTwoList: [] // 二级分类
}
},
created() {
// 获取路由id值
if(this.$route.params && this.$route.params.id) {
this.courseId = this.$route.params.id
// 调用根据id查询课程的方法
this.getInfo()
} else {
// 初始化所有讲师
this.getListTeacher()
// 初始化一级分类
this.getOneSubject()
}
},
watch: {
$route(to,from) {
this.courseInfo = {
title: '',
subjectId: '', // 二级分类ID
subjectParentId: '', // 一级分类ID
teacherId: '',
lessonNum: 0,
description: '',
cover: '/static/04.jpg',
price: 0
},
this.getListTeacher();
this.getOneSubject()
}
},
methods: {
// 根据课程id查询
getInfo() {
course.getCourseInfoId(this.courseId)
.then(response => {
this.courseInfo = response.data.courseInfoVo
// 1 查询所有的分类,包含一级和二级
subject.getSubjectList()
.then(response => {
// 2 获取所有一级分类
this.subjectOneList = response.data.list
// 3 把所有的一级分类数组进行遍历
for(var i = 0; i < this.subjectOneList.length; i++) {
// 获取一级分类
var oneSubject = this.subjectOneList[i]
// 比较当前 courseInfo 里面一级分类id和所有的一级分类id
if(this.courseInfo.subjectParentId == oneSubject.id) {
// 获取一级分类所有的二级分类
this.subjectTwoList = oneSubject.children
}
}
})
// 初始化所有讲师
this.getListTeacher()
})
},
// 查询所有的一级分类
getOneSubject() {
subject.getSubjectList()
.then(response => {
this.subjectOneList = response.data.list
})
},
// 添加课程
addCourse() {
course.addCourseInfo(this.courseInfo)
.then(response => {
// 提示
this.$message({
type: 'success',
message: '添加课程信息成功!'
});
// 跳转到第二步
this.$router.push({ path: '/course/chapter/' + response.data.courseId })
})
},
// 修改课程
updateCourse() {
course.updateCourseInfo(this.courseInfo)
.then(response => {
// 提示
this.$message({
type: 'success',
message: '修改课程信息成功!'
});
// 跳转到第二步
this.$router.push({ path: '/course/chapter/' + this.courseId })
})
},
saveOrUpdate() {
// 判断添加还是修改
if(!this.courseId) {
// 添加
this.addCourse()
} else {
this.updateCourse()
}
}
}
}
script>
@RestController
@RequestMapping("/eduservice/chapter")
@CrossOrigin
public class EduChapterController {
@Autowired
private EduChapterService chapterService;
// 添加章节
@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();
}
}
}
public interface EduChapterService extends IService<EduChapter> {
// 删除章节的方法
boolean deleteChapter(String chapterId);
}
@Service
public class EduChapterServiceImpl extends ServiceImpl<EduChapterMapper, EduChapter> implements EduChapterService {
@Autowired
private EduVideoService videoService; // 注入小节service
// 删除章节的方法
@Override
public boolean deleteChapter(String chapterId) {
// 根据chapterId 章节id查询小节表,如果查出数据,不进行删除
QueryWrapper<EduVideo> wrapper = new QueryWrapper<>();
wrapper.eq("chapter_id", chapterId);
int count = videoService.count(wrapper);
// 判断
if(count > 0) { // 查询出小节,不进行删除
throw new LemonException(20001, "不能删除");
} else { // 不能查询数据,进行删除
// 删除章节
int result = baseMapper.deleteById(chapterId);
// 成功 1>0
return result > 0;
}
}
}
// src\api\edu\chapter.js
import request from '@/utils/request'
export default {
// 添加章节
addChapter(chapter) {
return request({
url: '/eduservice/chapter/addChapter',
method: 'post',
data: chapter
})
},
// 根据id查询章节
getChapter(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/' + chapterId,
method: 'delete'
})
}
}
// src\views\edu\course\chapter.vue
<script>
import chapter from '@/api/edu/chapter'
export default {
data() {
return {
saveBtnDisabled: false, // 保存按钮是否禁用
courseId: '', // 课程id
chapterVideoList: [],
chapter: { // 封装章节数据
title: '',
sort: 0
},
dialogChapterFormVisible: false // 章节弹框
}
},
methods: {
// 弹出添加章节页面
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()
})
},
saveOrUpdate() {
// 设置课程id到chapter对象里面
this.addChapter()
}
}
}
script>
// src\views\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>
<el-button type="text" @click="openChapterDialog()">添加章节el-button>
<ul class="chanpterList">
<li
v-for="chapter in chapterVideoList"
:key="chapter.id">
<p>
{{ chapter.title }}
<span class="acts">
<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 }}
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>
div>
template>
<script>
import chapter from '@/api/edu/chapter'
export default {
data() {
return {
saveBtnDisabled: false, // 保存按钮是否禁用
courseId: '', // 课程id
chapterVideoList: [],
chapter: { // 封装章节数据
title: '',
sort: 0
},
dialogChapterFormVisible: false // 章节弹框
}
},
created() {
// 获取路由的id值
if(this.$route.params && this.$route.params.id) {
this.courseId = this.$route.params.id
// 根据课程id查询章节和小节
this.getChapterVideo()
}
},
methods: {
// 删除章节
removeChapter(chapterId) {
this.$confirm('此操作将删除章节, 是否继续?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => { // 点击确定,执行then方法
// 调用删除方法
chapter.deleteChapter(chapterId)
.then(response => { // 删除成功
// 提示信息
this.$message({
type: 'success',
message: '删除成功!'
});
// 回到列表页面
this.getChapterVideo()
})
})
},
// 修改章节弹框数据回显
openEditChapter(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到chapter对象里面
this.addChapter()
},
// 根据课程id查询章节和小节
getChapterVideo() {
chapter.getAllChapterVideo(this.courseId)
.then(response => {
this.chapterVideoList = response.data.allChapterVideo
})
},
previous(){
this.$router.push({ path: '/course/info/' + this.courseId })
},
next() {
this.$router.push({ path: '/course/publish/' + this.courseId })
}
}
}
script>
@Data
public class VideoVo {
@ApiModelProperty(value = "视频ID")
private String id;
@ApiModelProperty(value = "节点名称")
private String title;
@ApiModelProperty(value = "课程ID")
private String courseId;
@ApiModelProperty(value = "章节ID")
private String chapterId;
@ApiModelProperty(value = "视频资源")
private String videoSourceId;
@ApiModelProperty(value = "显示排序")
private Integer sort;
@ApiModelProperty(value = "是否可以试听:0默认 1免费")
private Boolean free;
}
@RestController
@RequestMapping("/eduservice/video")
@CrossOrigin
public class EduVideoController {
@Autowired
private EduVideoService videoService;
// 添加小节
@PostMapping("addVideo")
public R addVideo(@RequestBody VideoVo videoVo) {
videoService.saveVideoInfo(videoVo);
return R.ok();
}
// 删除小节
// TODO 后面这个方法需要完善:删除小节时候,同时把里面视频删除
@DeleteMapping("{id}")
public R deleteVideo(@PathVariable String id) {
videoService.removeById(id);
return R.ok();
}
// 根据章节id查询
@GetMapping("getVideoInfo/{videoId}")
public R getVideoInfo(@PathVariable String videoId) {
VideoVo videoVo = videoService.getVideoInfo(videoId);
return R.ok().data("video", videoVo);
}
// 修改小节
@PostMapping("updateVideo")
public R updateVideoInfo(@RequestBody VideoVo videoVo) {
videoService.updateVideoInfo(videoVo);
return R.ok();
}
}
public interface EduVideoService extends IService<EduVideo> {
void saveVideoInfo(VideoVo videoVo);
void updateVideoInfo(VideoVo videoVo);
VideoVo getVideoInfo(String videoId);
}
@Service
public class EduVideoServiceImpl extends ServiceImpl<EduVideoMapper, EduVideo> implements EduVideoService {
@Override
public void saveVideoInfo(VideoVo videoVo) {
EduVideo eduVideo = new EduVideo();
BeanUtils.copyProperties(videoVo,eduVideo);
if(videoVo.getFree()) {
eduVideo.setIsFree(true);
} else {
eduVideo.setIsFree(false);
}
boolean result = this.save(eduVideo);
if(!result) {
throw new LemonException(20001, "保存失败");
}
}
@Override
public void updateVideoInfo(VideoVo videoVo) {
EduVideo eduVideo = new EduVideo();
BeanUtils.copyProperties(videoVo,eduVideo);
if(videoVo.getFree()) {
eduVideo.setIsFree(true);
} else {
eduVideo.setIsFree(false);
}
boolean result = this.updateById(eduVideo);
if(!result) {
throw new LemonException(20001, "保存失败");
}
}
@Override
public VideoVo getVideoInfo(String videoId) {
EduVideo eduVideo = this.getById(videoId);
if(eduVideo == null) {
throw new LemonException(20001, "数据不存在");
}
VideoVo videoVo = new VideoVo();
if(eduVideo.getIsFree()) {
videoVo.setFree(true);
} else {
videoVo.setFree(false);
}
BeanUtils.copyProperties(eduVideo, videoVo);
return videoVo;
}
}
// src\views\edu\course\chapter.vue
<script>
import chapter from '@/api/edu/chapter'
import video from '@/api/edu/video'
export default {
data() {
return {
saveBtnDisabled: false, // 保存按钮是否禁用
saveVideoBtnDisabled: false, // 课时按钮是否禁用
courseId: '', // 课程id
chapterVideoList: [],
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: {
openEditVideo(videoId) {
// 弹框
this.dialogVideoFormVisible = true
// 调用接口
video.getVideo(videoId)
.then(response => {
this.video = response.data.video
})
},
// ==========================================小节操作==========================================
// 删除小节
removeVideo(videoId) {
this.$confirm('此操作将删除小节, 是否继续?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => { // 点击确定,执行then方法
// 调用删除方法
video.deleteVideo(videoId)
.then(response => { // 删除成功
// 提示信息
this.$message({
type: 'success',
message: '删除小节成功!'
});
// 回到列表页面
this.getChapterVideo()
})
})
},
// 添加小节弹框的方法
openVideo(chapterId){
// 弹框
this.dialogVideoFormVisible = true
// 设置章节id
this.video.chapterId = chapterId
// 表单数据清空
this.video.id = '',
this.video.title = '',
this.video.sort = 0,
this.video.free = 0,
this.video.videoSourceId = ''
},
// 添加小节
addVideo() {
// 设置课程id
this.video.courseId = this.courseId
video.addVideo(this.video)
.then(response => {
// 关闭弹框
this.dialogVideoFormVisible = false
// 提示
this.$message({
type: 'success',
message: '添加小节成功!'
});
// 刷新页面
this.getChapterVideo()
})
},
updateVideo() {
video.updateVideo(this.video)
.then(response => {
// 关闭弹框
this.dialogVideoFormVisible = false
// 提示
this.$message({
type: 'success',
message: '修改小节成功!'
});
// 刷新页面
this.getChapterVideo()
})
},
saveOrUpdateVideo() {
if(!this.video.id) {
this.addVideo()
} else {
this.updateVideo()
}
}
}
script>
@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; //只用于显示
}
public interface EduCourseMapper extends BaseMapper<EduCourse> {
public CoursePublishVo getPublishCourseInfo(String courseId);
}
DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.alex.eduservice.mapper.EduCourseMapper">
<select id="getPublishCourseInfo" resultType="com.alex.eduservice.entity.vo.CoursePublishVo">
SELECT ec.id, ec.title, ec.price, ec.lesson_num AS lessonNum,ec.cover,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}
select>
mapper>
@RestController
@RequestMapping("/eduservice/course")
@CrossOrigin
public class EduCourseController {
@Autowired
private EduCourseService courseService;
// 根据课程id查询课程确认信息
@GetMapping("getPublishCourseInfo/{id}")
public R getPublishCourseInfo(@PathVariable String id) {
CoursePublishVo coursePublishVo = courseService.publishCourseInfo(id);
return R.ok().data("publishCourse", coursePublishVo);
}
}
public interface EduCourseService extends IService<EduCourse> {
CoursePublishVo publishCourseInfo(String id);
}
@Service
public class EduCourseServiceImpl extends ServiceImpl<EduCourseMapper, EduCourse> implements EduCourseService {
@Autowired
private EduCourseDescriptionService courseDescriptionService;
@Override
public CoursePublishVo publishCourseInfo(String id) {
// 调用mapper
CoursePublishVo publishCourseInfo = baseMapper.getPublishCourseInfo(id);
return publishCourseInfo;
}
}
pom.xml(service)
<build>
<resources>
<resource>
<directory>src/main/javadirectory>
<includes>
<include>**/*.xmlinclude>
includes>
<filtering>falsefiltering>
resource>
resources>
build>
src/main/resources/application.properties
#配置mapper xml文件的路径
mybatis-plus.mapper-locations=classpath:com/alex/eduservice/mapper/xml/*.xml
// src\api\edu\course.js
import request from '@/utils/request'
export default {
// 课程确认信息显示
getPublishCourseInfo(id) {
return request({
url: '/eduservice/course/getPublishCourseInfo/' + id,
method: 'get'
})
}
}
// src\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 course from '@/api/edu/course'
export default {
data() {
return {
saveBtnDisabled: false, // 保存按钮是否禁用
courseId: '',
coursePublish: {}
}
},
created() {
// 获取路由课程id值
if(this.$route.params && this.$route.params.id) {
this.courseId = this.$route.params.id
// 调用接口方法根据课程id查询
this.getCoursePublishId()
}
},
methods: {
// 根据课程id查询
getCoursePublishId() {
course.getPublishCourseInfo(this.courseId)
.then(response => {
this.coursePublish = response.data.publishCourse
})
},
previous() {
console.log('previous')
this.$router.push({ path: '/course/chapter/1' })
},
publish() {
console.log('publish')
this.$router.push({ path: '/course/list' })
}
}
}
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>