一、课程发布分析
1、发布流程图
2、数据表对应
3、课程相关表的关系
二、课程管理–添加课程后端
1、使用代码生成器生成相关课程的代码
2、细节问题
(1)创建vo实体类用户表单数据封装 vo:ViewObject:用于后台向前台显示所创建的实体
(2)把表单提交过来的数据添加到数据库 ==>向两张表添加数据:课程表 和 课程描述表
(3)把讲师和分类使用下拉列表显示 课程分类 做成二级联动
3、创建vo实体类
@ApiModel(value = "课程基本信息", description = "编辑课程基本信息的表单对象") @Data public class CourseInfoVo { private static final long serialVersionUID = 1L; @ApiModelProperty(value = "课程ID") private String id; @ApiModelProperty(value = "课程讲师ID") private String teacherId; @ApiModelProperty(value = "课程专业ID") private String subjectId; @ApiModelProperty(value = "课程专业父级ID") private String subjectParentId; @ApiModelProperty(value = "课程标题") private String title; @ApiModelProperty(value = "课程销售价格,设置为0则可免费观看") private BigDecimal price; @ApiModelProperty(value = "总课时") private Integer lessonNum; @ApiModelProperty(value = "课程封面图片路径") private String cover; @ApiModelProperty(value = "课程简介") private String description; }
4、编写Controller类
@Api(description = "课程管理") @RestController @RequestMapping("/eduservice/course") @CrossOrigin public class EduCourseController { @Autowired private EduCourseService courseService; @ApiOperation("添加课程基本信息") @PostMapping("saveCourseInfo") public R saveCourseInfo(@ApiParam(name = "CourseInfoForm", value = "课程基本信息", required = true) @RequestBody CourseInfoVo courseInfoVo){ //返回课程id,为了跳转到课程大纲使用 String courseId = courseService.saveCourseInfo(courseInfoVo); return R.ok().data("courseId", courseId); } }
5、编写Service类
@Service @Transactional //开启事务管理 public class EduCourseServiceImpl extends ServiceImpl<EduCourseMapper, EduCourse> implements EduCourseService { @Autowired private EduCourseDescriptionService courseDescriptionService; //添加课程基本信息 @Override public String saveCourseInfo(CourseInfoVo courseInfoVo) { //1.添加课程基本信息信息到课程表 EduCourse eduCourse = new EduCourse(); BeanUtils.copyProperties(courseInfoVo,eduCourse); int insert = this.baseMapper.insert(eduCourse); if(insert==0){ throw new GuLiException(20001, "添加课程失败!"); } //2.添加课程简介信息到简介表 String id = eduCourse.getId();//获得添加之后的课程id EduCourseDescription eduCourseDescription = new EduCourseDescription(); BeanUtils.copyProperties(courseInfoVo,eduCourseDescription); eduCourseDescription.setId(id);//因为两张表是一对一关系,所以id也应该相同 boolean save = courseDescriptionService.save(eduCourseDescription); if(save==false){ throw new GuLiException(20001, "添加课程失败!"); } return id; } }
注意问题:
(1)课程和描述是一对一关系,添加之后,id应该是相同的。所以描述的id要填入课程的id.
EduCourseDescription类中id 属性@TableId(value = "id", type = IdType.INPUT)
(2)EduCourse类和EduCourseDescription类中的时间需要自动填充@TableField(fill = FieldFill.INSERT)
6、启动Swagger测试
…
三、课程管理–添加课程前端(填写课程基本信息)
1、添加课程管理路由
api/router/index.js
{ path: '/course', component: Layout, //布局 redirect: '/course/table', name: 'CourseAdd', meta: { title: '课程管理', icon: 'form' }, children: [{ path: 'list', name: 'EduCourseList', component: () => import ('@/views/edu/course/list'), meta: { title: '课程列表', icon: 'table' } }, { path: 'info', name: 'EduCourseInfo', component: () => import ('@/views/edu/course/info'), meta: { title: '发布课程', icon: 'tree' } }, { path: 'info/:id', name: 'EduCourseInfoEdit', component: () => import ('@/views/edu/course/info'), meta: { title: '编辑课程基本信息', noCache: true }, hidden: true }, { path: 'chapter/:id', name: 'EduCourseChapterEdit', component: () => import ('@/views/edu/course/chapter'), meta: { title: '编辑课程大纲', noCache: true }, hidden: true }, { path: 'publish/:id', name: 'EduCoursePublishEdit', component: () => import ('@/views/edu/course/publish'), meta: { title: '发布课程', noCache: true }, hidden: true } ] },
**注意:**这里有三个模块添加隐藏域是为了形成 下一步—>下一步—>确认发布 上一步—>上一步—>取消发布 的效果
2、添加Vue组件
3、整合步骤条组件实现页面跳转
参考:http://element-cn.eleme.io/#/zh-CN/component/steps
1、课程页面信息— info.vue
<template> <div class="app-container"> <h2 style="text-align: center;">发布新课程</h2> <el-steps :active="1" process-status="wait" align-center style="margin-bottom: 40px;"> <el-step title="填写课程基本信息"/> <el-step title="创建课程大纲"/> <el-step title="最终发布"/> </el-steps> <el-form label-width="120px"> <el-form-item> <el-button :disabled="saveBtnDisabled" type="primary" @click="saveOrUpdate">保存并下一步</el-button> </el-form-item> </el-form> </div> </template> <script> export default { data() { return { saveBtnDisabled:false // 保存按钮是否禁用 } }, created() { }, methods:{ saveOrUpdate() { //跳转到第二步 this.$router.push({path:'/course/chapter/1'}) } } } </script>
2、课程大纲页面—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-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> export default { data() { return { saveBtnDisabled: false // 保存按钮是否禁用 } }, created() { }, methods: { previous() { this.$router.push({ path: '/edu/course/info/1' }) }, next() { //跳转到第二步 this.$router.push({ path: '/edu/course/publish/1' }) } } } </script>
3、课程发布页面—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> <el-form label-width="120px"> <el-form-item> <el-button @click="previous">返回修改</el-button> <el-button :disabled="saveBtnDisabled" type="primary" @click="publish">发布课程</el-button> </el-form-item> </el-form> </div> </template> <script> export default { data() { return { saveBtnDisabled: false // 保存按钮是否禁用 } }, created() { console.log('publish created') }, methods: { previous() { console.log('previous') this.$router.push({ path: '/course/chapter/1' }) }, publish() { console.log('publish') this.$router.push({ path: '/course/list' }) } } } </script>
4、定义api
api/edu/course.js
import request from '@/utils/request' export default { //1.添加课程信息 saveCourseInfo(courseInfo) { return request({ url: `/eduservice/course/saveCourseInfo`, method: 'post', data: courseInfo }) } }
5、添加课程表单
src/views/edu/info.vue
<el-form label-width="120px"> <el-form-item label="课程标题"> <el-input v-model="courseInfo.title" placeholder=" 示例:机器学习项目课:从基础到搭建项目视频课程。专业名称注意大小写"/> </el-form-item> <!-- 所属分类 TODO --> <!-- 课程讲师 TODO --> <el-form-item label="总课时"> <el-input-number :min="0" v-model="courseInfo.lessonNum" controls-position="right" placeholder="请填写课程的总课时数"/> </el-form-item> <!-- 课程简介 TODO --> <el-form-item label="课程简介"> <el-input v-model="courseInfo.description" placeholder=" "/> </el-form-item> <!-- 课程封面 TODO --> <el-form-item label="课程价格"> <el-input-number :min="0" v-model="courseInfo.price" controls-position="right" placeholder="免费课程请设置为0元"/> 元 </el-form-item> <el-form-item> <el-button :disabled="saveBtnDisabled" type="primary" @click="saveOrUpdate">保存并下一步</el-button> </el-form-item> </el-form> <script> import course from '@/api/edu/course' export default { data() { return { saveBtnDisabled:false, courseInfo:{ title: '', subjectId: '',//二级分类id subjectParentId:'',//一级分类id teacherId: '', lessonNum: 0, description: '', cover: '', price: 0 }, } }, created() { }, methods:{ //提交课程信息 saveOrUpdate(){ course.saveCourseInfo(this.courseInfo) .then(response=>{ this.$message({ type:'success', message:'保存成功!' }) //跳转到课程大纲页面 this.$router.push({path:'/course/chapter/'+response.data.courseId}) }).catch(response=>{ this.$message({ type:'error', message:'保存失败!' }) }) } } } </script>
**主意:**TODO是为了后续进行完善,一个项目都是从简单到复杂,功能一步步变繁多的.
7、讲师下拉列表
(1)组件模板
<!-- 课程讲师 --> <el-form-item label="课程讲师"> <el-select filterable v-model="courseInfo.teacherId" placeholder="请选择"> <el-option v-for="teacher in teacherList" :key="teacher.id" :label="teacher.name" :value="teacher.id"/> </el-select> </el-form-item>
(2)定义api
api/edu/teacher.js
//查询所有讲师 getTeacherList() { return request({ url: `/eduservice/teacher/findAll`, method: 'get' }) }
组件中引入teacher的api
import teacher from '@/api/edu/teacher'
(3)组件js代码
定义data
teacherList: [] // 讲师列表
表单初始化时获取讲师列表
created() { this.getTeacherList() }, methods: { //.... //查询所有讲师 getTeacherList(){ course.getTeacherList().then(response=>{ this.teacherList = response.data.items }) } }
(4)页面效果展示