课程管理 需要用到的表格
edu_course 课程表:存储课程的基本信息
edu_course_description 课程简介表:存储课程的简介
edu_chapter 课程章节表:存储课程章节信息
edu_video 课程小节表:存储章节里的小节信息
edu_teacher 讲师表
edu_subject 分类表
添加课程基本信息
分析:
(1)创建vo实体类用于单表数据封装(已有的数据不全,要重新进行封装)
(2)把表单提交过来的数据添加到数据库,要向两张表添加数据,课程表和课程简介表 一对一关系
(3)把讲师和分类使用下拉列表显示
课程分类需要做成二级联动效果
实现:
1.使用代码生成器生成课程相关的代码
strategy.setInclude("edu_course","edu_course_description","edu_chapter","edu_video");
//数据库表名,多个的话,可以逗号隔开
2.创建vo类封装表单提交的数据
package com.atguigu.eduservice.entity.vo;
import com.alibaba.excel.event.AbstractIgnoreExceptionReadListener;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.math.BigDecimal;
/**
* @author XueYanhong
* @description
* @date 2022/5/5 10:49
*/
@Data
public class CourseInfoVo {private String id;
@ApiModelProperty(value = "https://www.it610.com/article/课程讲师ID")
private String teacherId;
@ApiModelProperty(value = "https://www.it610.com/article/课程专业ID")
private String subjectId;
@ApiModelProperty(value = "https://www.it610.com/article/课程专业父级ID")
private String subjectParentId;
@ApiModelProperty(value = "https://www.it610.com/article/课程标题")
private String title;
@ApiModelProperty(value = "https://www.it610.com/article/课程销售价格,设置为0则可免费观看")
private BigDecimal price;
@ApiModelProperty(value = "https://www.it610.com/article/总课时")
private Integer lessonNum;
@ApiModelProperty(value = "https://www.it610.com/article/课程封面图片路径")
private String cover;
@ApiModelProperty(value = "https://www.it610.com/article/课程简介")
private String description;
}
3.编写controller和service
课程和简介要是一对一的关系
解决:设置简介id就是课程id,修改简介实体类id生成策略—修改EduCourseDescription的id的策略为input
@ApiModelProperty(value = "https://www.it610.com/article/课程ID")
@TableId(value = "https://www.it610.com/article/id", type = IdType.INPUT)
private String id;
input表示手动设置/输入
controller
package com.atguigu.eduservice.controller;
import com.atguigu.commonutils.R;
import com.atguigu.eduservice.entity.EduCourse;
import com.atguigu.eduservice.entity.vo.CourseInfoVo;
import com.atguigu.eduservice.service.EduCourseService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/eduservice/course")
@CrossOrigin
public class EduCourseController {@Autowired
private EduCourseService courseService;
//添加课程基本信息
@PostMapping("addCourseInfo")
public R addCourseInfo(@RequestBody CourseInfoVo courseInfoVo) {
courseService.saveCourseInfo(courseInfoVo);
return R.ok();
}
}
serviceImpl
package com.atguigu.eduservice.service.impl;
import com.atguigu.eduservice.entity.EduCourse;
import com.atguigu.eduservice.entity.EduCourseDescription;
import com.atguigu.eduservice.entity.vo.CourseInfoVo;
import com.atguigu.eduservice.mapper.EduCourseMapper;
import com.atguigu.eduservice.service.EduCourseDescriptionService;
import com.atguigu.eduservice.service.EduCourseService;
import com.atguigu.servicebase.exceptionhandler.GuliException;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class EduCourseServiceImpl extends ServiceImpl implements EduCourseService {@Autowired
private EduCourseDescriptionService eduCourseDescriptionService;
@Override
public void saveCourseInfo(CourseInfoVo courseInfoVo) {
//1.向课程表添加课程基本信息
//courseInfoVo对象转换成eduCourse对象
EduCourse eduCourse = new EduCourse();
BeanUtils.copyProperties(courseInfoVo,eduCourse);
int insert = baseMapper.insert(eduCourse);
if (insert == 0 ) {
//添加失败
throw new GuliException(20001,"添加课程信息失败");
}
//获取添加之后的课程id
String cid = eduCourse.getId();
//2.向课程简介表添加
EduCourseDescription courseDescription = new EduCourseDescription();
courseDescription.setDescription(courseInfoVo.getDescription());
//手动设置简介id就是课程id
courseDescription.setId(cid);
eduCourseDescriptionService.save(courseDescription);
}
}
前端实现
【项目|7-谷粒学苑】1.添加课程管理路由
2.添加隐藏路由
hidden:true
{
path: '/course',
component: Layout,
redirect: '/course/list',
name: '课程管理',
meta: { title: '课程管理', icon: 'el-icon-s-help' },
children: [
{
path: 'list',
name: '课程列表',
component: () => import('@/views/edu/course/list'),
meta: { title: '课程列表', icon: 'table' }
},
{
path: 'info',
name: '添加课程',
component: () => import('@/views/edu/course/info'),
meta: { title: '添加课程', icon: 'tree' }
},
{
path: 'chapter/:id',
name: '编辑课程大纲',
component: () => import('@/views/edu/course/chapter'),
meta: { title: '编辑课程大纲', icon: 'tree' },
hidden: true
},
{
path: 'publish/:id',
name: '发布课程',
component: () => import('@/views/edu/course/publish'),
meta: { title: '发布课程', icon: 'tree' },
hidden: true
}
]
},
3.Vue页面
课程基本信息页面 info.vue
发布新课程
保存并下一步
>export default {
name: 'Info',
data() {
return {
active: 0,
saveBtnDisabled: false
}
},
created() {
console.log('info created')
},
methods: {next() {
console.log('next')
// 跳转到第二步
this.$router.push({ path: '/course/chapter/1' })
}
}
}
>
课程大纲页面 chapter.vue
发布新课程
上一步
下一步
>export default {
name: 'Chapter',
data() {
return {
saveBtnDisabled: false
}
},
created() {
console.log('chapter created')
},
methods: {
previous() {
console.log('previous')
// 跳转到第一步
this.$router.push({ path: '/course/info' })
},
next() {
console.log('next')
// 跳转到第三步
this.$router.push({ path: '/course/publish/1' })
}
}
}
>
课程发布页面 publish.vue
发布新课程
返回修改
发布课程
>export default {
name: 'Publish',
data() {
return {
saveBtnDisabled: false
}
},
created() {
console.log('publish created')
},
methods: {
previous() {
console.log('previous')
// 跳转到第二步
this.$router.push({ path: '/course/chapter/1' })
},
next() {
console.log('next')
// 跳转到第三步
this.$router.push({ path: '/course/list' })
}
}
}
>
组件模板
元
保存并下一步
3.定义api
import request from '@/utils/request'export default {
// 添加课程列表
addCourseInfo(courseInfo) {
return request({
url: `/eduservice/course/addCourseInfo`,
method: 'post',
data: courseInfo
})
}
}
4.编写表单页面,实现接口调用
5.添加之后,返回课程id
在controller中增加返回的内容
@RestController
@RequestMapping("/eduservice/course")
@CrossOrigin
public class EduCourseController {@Autowired
private EduCourseService courseService;
//添加课程基本信息
@PostMapping("addCourseInfo")
public R addCourseInfo(@RequestBody CourseInfoVo courseInfoVo) {
//返回添加之后课程id,为了后面添加大纲使用
String id = courseService.saveCourseInfo(courseInfoVo);
return R.ok().data("courseId",id);
}
}
public interface EduCourseService extends IService {//添加课程基本信息
String saveCourseInfo(CourseInfoVo courseInfoVo);
}
@Service
public class EduCourseServiceImpl extends ServiceImpl implements EduCourseService {@Autowired
private EduCourseDescriptionService eduCourseDescriptionService;
@Override
public String saveCourseInfo(CourseInfoVo courseInfoVo) {
//1.向课程表添加课程基本信息
//courseInfoVo对象转换成eduCourse对象
EduCourse eduCourse = new EduCourse();
BeanUtils.copyProperties(courseInfoVo,eduCourse);
int insert = baseMapper.insert(eduCourse);
if (insert == 0 ) {
//添加失败
throw new GuliException(20001,"添加课程信息失败");
}
//获取添加之后的课程id
String cid = eduCourse.getId();
//2.向课程简介表添加
EduCourseDescription courseDescription = new EduCourseDescription();
courseDescription.setDescription(courseInfoVo.getDescription());
//手动设置简介id就是课程id
courseDescription.setId(cid);
eduCourseDescriptionService.save(courseDescription);
return cid;
}
}
前端获取接口的id
this.$router.push({ path: '/course/chapter/' + response.data.courseId })
讲师下拉列表
1.Info.vue
v-for进行遍历,label是下拉列表显示的内容,key是唯一标识
2.定义data
teacherList: [] // 封装所有讲师
3.查询所有讲师并且进行初始化
created() {
// 初始化所有讲师
this.getListTeacher()
},
methods: {
// 查询所有的讲师
getListTeacher() {
course.getListTeacher()
.then(response => {
this.teacherList = response.data.items
})
},
3.定义api
// 查询所有讲师
getListTeacher() {
return request({
url: `/eduservice/teacher/findAll`,
method: 'get'
})
}
课程分类的二级联动
第一次进入页面,显示所有一级,二级为空
选择了某个一级分类,显示选择一级中对应的二级分类
一级分类 1.组件模板
2.引入subject api
import subject from '@/api/edu/subject'
3.定义方法
created() {
// 初始化所有讲师
this.getListTeacher()
// 初始化一级课程分类
this.getOneSubject()
},
methods: {
// 查询所有一级分类
getOneSubject() {
subject.getSubjectList()
.then(response => {
this.subjectOneList = response.data.list
})
},
4.定义data
subjectOneList: [], // 封装一级分类
subjectTwoList: [] // 封装二级分类
二级分类 1.组件模板
2.定义方法
在一级分类的组件中注册change事件
@change 当一级分类改变就取对应的二级分类的值
@change="subjectLevelOneChanged"
// 点击某个一级分类,触发change,显示对应二级分类
subjectLevelOneChanged(value) {
// value 就是一级分类的id
// 遍历所有分类,包含一级和二级
for (let i = 0;
i < this.subjectOneList.length;
i++) {
// 每个一级分类
var oneSubject = this.subjectOneList[i]
// 判断 所有一级分类id 和点击一级分类id是否一样
if (value =https://www.it610.com/article/== oneSubject.id) {
// 从一级分类获取里面所有的二级分类
this.subjectTwoList = oneSubject.children
// 把二级分类的id值清空
this.courseInfo.subjectId =''
}
}
},
完整代码-info.vue
发布新课程
元
保存并下一步
>
import course from '@/api/edu/course'
import subject from '@/api/edu/subject'
export default {
name: 'Info',
data() {
return {
active: 0,
saveBtnDisabled: false,
courseInfo: {
title: '',
subjectId: '', // 二级分类id
teacherId: '',
subjectParentId: '', // 一级分类id
lessonNum: 0,
description: '',
cover: '',
price: 0
},
teacherList: [],
subjectOneList: [], // 封装一级分类
subjectTwoList: [] // 封装二级分类
}
},
created() {
// 初始化所有讲师
this.getListTeacher()
// 初始化一级课程分类
this.getOneSubject()
},
methods: {
// 点击某个一级分类,触发change,显示对应二级分类
subjectLevelOneChanged(value) {
// value 就是一级分类的id
// 遍历所有分类,包含一级和二级
for (let i = 0;
i < this.subjectOneList.length;
i++) {
// 每个一级分类
var oneSubject = this.subjectOneList[i]
// 判断 所有一级分类id 和点击一级分类id是否一样
if (value =https://www.it610.com/article/== oneSubject.id) {
// 从一级分类获取里面所有的二级分类
this.subjectTwoList = oneSubject.children
// 把二级分类的id值清空
this.courseInfo.subjectId =''
}
}
},
// 查询所有一级分类
getOneSubject() {
subject.getSubjectList()
.then(response => {
this.subjectOneList = response.data.list
})
},
// 查询所有的讲师
getListTeacher() {
course.getListTeacher()
.then(response => {
this.teacherList = response.data.items
})
},
saveOrUpdate() {
course.addCourseInfo(this.courseInfo)
.then(response => {
// 提示
this.$message({
type: 'success',
message: '添加课程信息成功!'
})
// 跳转到第二步
this.$router.push({ path: '/course/chapter/' + response.data.courseId })
})
}
}
}
>
课程封面上传
1.组件模板
文章图片
2.定义data数据
BASE_API: process.env.VUE_APP_BASE_API, // 接口API地址
3.上传方法
beforeAvatarUpload()对文件的类型和大小进行限制
methods: {
// 上传封面成功调用的方法
handleAvatarSuccess(res, file) {
this.courseInfo.cover = res.data.url
},
// 上传之前调用的方法,对文件的大小和类型进行限制
beforeAvatarUpload(file) {
const isJPG = file.type === 'image/jpeg'
const isLt2M = file.size / 1024 / 1024 < 2if (!isJPG) {
this.$message.error('上传头像图片只能是 JPG 格式!')
}
if (!isLt2M) {
this.$message.error('上传头像图片大小不能超过 2MB!')
}
return isJPG && isLt2M
},
Tinymce可视化编辑器
Tinymce是一个传统javascript插件,默认不能用于Vue.js,因此需要做一些特殊的整合步骤
1.复制文本编辑器组件
tinymce复制到components里面
tinymce4.7.5复制到static里面
2.配置html变量
找到build/webpack.dev.conf.js中添加配置
在这里插入代码片
推荐阅读
- #|Vue----任务列表案例
- 前端|VUE + Echart 5.3.2 graph关系图代码
- springboot情操陶冶-SpringApplication
- Vue|Vue父子组件如何通信(6种)
- #|第003课(运行程序,纠正程序编写问题)
- 面试官(Spring MVC 如何保证 Controller 的并发安全性(面试必问。。))
- Java 13 的 switch 语句改进
- SpringBoot加载运行时监听器(SpringApplicationRunListeners)
- 百度|这个微信小程序开源!