谷粒学院(十)课程管理模块 | 课程大纲列表 | 二级联动 | 富文本编辑器(一)

简介: 谷粒学院(十)课程管理模块 | 课程大纲列表 | 二级联动 | 富文本编辑器

一、课程发布分析

1、发布流程图

9412dc92ed8ced8fb41e4f4569a8f971.png

2、数据表对应


f3b674a3e2010f4346fddc3fb4af52b3.png


3、课程相关表的关系


10b6997ef709ba8de7652e922218c5e6.png

二、课程管理–添加课程后端

1、使用代码生成器生成相关课程的代码


6d4249e539813d7bdde102868e0da402.png


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组件


aa2f14be17769fde2e272d34d9befb39.png


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)页面效果展示


e020eb54885cae945fcd0512546f952a.png


相关文章
|
7月前
|
Linux 开发工具 C语言
Linux课程四课---Linux开发环境的使用(vim编辑器的相关)
Linux课程四课---Linux开发环境的使用(vim编辑器的相关)
|
JSON 小程序 Java
java oop经典案例开发与源码 -java swing 羊了*羊 简易版本开发 (1) 地图模块编辑器开发(附github源码地址)
java oop经典案例开发与源码 -java swing 羊了*羊 简易版本开发 (1) 地图模块编辑器开发(附github源码地址)
java oop经典案例开发与源码 -java swing 羊了*羊 简易版本开发 (1) 地图模块编辑器开发(附github源码地址)
|
前端开发 JavaScript API
谷粒学院(十)课程管理模块 | 课程大纲列表 | 二级联动 | 富文本编辑器(三)
谷粒学院(十)课程管理模块 | 课程大纲列表 | 二级联动 | 富文本编辑器
谷粒学院(十)课程管理模块 | 课程大纲列表 | 二级联动 | 富文本编辑器(三)
|
JavaScript 数据可视化
谷粒学院(十)课程管理模块 | 课程大纲列表 | 二级联动 | 富文本编辑器(二)
谷粒学院(十)课程管理模块 | 课程大纲列表 | 二级联动 | 富文本编辑器
谷粒学院(十)课程管理模块 | 课程大纲列表 | 二级联动 | 富文本编辑器(二)
|
JSON Android开发 数据格式
Flutter从0到1实现高性能、多功能的富文本编辑器(模块分析篇)
经过前面两篇文章的基础知识铺垫,我们终于要进入到专栏的核心内容 — 富文本。富文本编辑器可以说是APP中最复杂,但使用场景又极广的组件之一。例如各大笔记APP的核心功能、闲鱼的商品发布功能、还
Flutter从0到1实现高性能、多功能的富文本编辑器(模块分析篇)
|
前端开发 JavaScript API
谷粒学院(十)课程管理模块 | 课程大纲列表 | 二级联动 | 富文本编辑器(四)
谷粒学院(十)课程管理模块 | 课程大纲列表 | 二级联动 | 富文本编辑器
|
5月前
|
开发工具
vi编辑器,现在vi\vim是文本文件进行编辑的最佳选择,Vim是vi的加强的版本,兼容vi的所有指令,vim编辑器有三种工作模式,一开始进入的是命令模式,命令模式i是插入的意思,两下y+p复制内容
vi编辑器,现在vi\vim是文本文件进行编辑的最佳选择,Vim是vi的加强的版本,兼容vi的所有指令,vim编辑器有三种工作模式,一开始进入的是命令模式,命令模式i是插入的意思,两下y+p复制内容
|
6月前
|
开发工具
Vim 编辑器:高效文本编辑的瑞士军刀
**Vim 概览:** Vim 是一个功能丰富的文本编辑器,以其高度可定制性著称。文章介绍了 Vim 的高效使用技巧,包括快捷打开文件、命令行模式下的常用命令、查找与替换、删除和复制文本。还讨论了配置 `.vimrc` 文件以自定义设置,如改变 leader 键、设置缩进和高亮,并展示了安装插件如 vim-airline 和 vim-snazzy 的方法。通过这些技巧,用户能提升 Vim 使用效率。
73 5