06-学成在线添加课程,包含课程基本信息,营销信息,课程计划信息,师资信息

news2024/11/13 3:34:12

添加课程

界面原型

第一步: 用户进入课程查询列表,点击添加课程按钮,选择课程类型是直播还是录播,课程类型不同那么授课方式也不同

  • 添加的课程和教学机构是一对一的关系

在这里插入图片描述

第二步: 用户选完课程形式后,点击下一步填写课程的基本信息和营销信息(两张表)

  • 用户只要填完课程信息就会把数据保存到数据库中,可以在课程管理中查看对应的课程发布信息,当审核状态为通过时发布按钮点亮

在这里插入图片描述

第三步: 填写课程计划信息即课程的大纲目录包括章节和小节,每个小节需要上传课程视频,用户点击小节标题即可开始播放视频,如果是直播课程则会进入直播间

在这里插入图片描述

第四步: 填写课程师资信息

在这里插入图片描述

数据模型

添加课程涉及到的数据表课程基本信息表

在这里插入图片描述

课程查询功能涉及到的数据表课程计划信息表

在这里插入图片描述

请求/响应模型(model工程)

第一步: 根据请求参数定义对应的请求模型类,添加课程的初始审核状态为未提交,初始发布状态为未发布

// 新增课程
POST {{content_host}}/content/course
Content-Type: application/json
{
  // 机构名称和Id根据当前登陆的用户获取,以下信息对应课程基本信息表	  
  "mt": "",大分类
  "st": "",小分类
  "name": "",课程名称
  "pic": "",课程图片
  "teachmode": "200002",教育模式
  "users": "初级人员",适用人群
  "tags": "",课程标签
  "grade": "204001",课程等级
  "description": "",课程介绍
   
   //以下信息对应课程营销表 
  "charge": "201000",收费规则
  "price": 0,现价
  "originalPrice":0,原价
  "qq": "",咨询QQ
  "wechat": "",微信
  "phone": "",电话
  "validDays": 365,有效期天数
}
package com.xuecheng.content.model.dto;
/**
 * @version 1.0
 * @description 添加课程dto
 */
@Data
@ApiModel(value = "AddCourseDto", description = "新增课程基本信息")
public class AddCourseDto {
    @ApiModelProperty(value = "课程名称", required = true)
    private String name;
    @ApiModelProperty(value = "适用人群", required = true)
    private String users;
    @ApiModelProperty(value = "课程标签")
    private String tags;
    @ApiModelProperty(value = "大分类", required = true)
    private String mt;
    @ApiModelProperty(value = "小分类", required = true)
    private String st;
    @ApiModelProperty(value = "课程等级", required = true)
    private String grade;
    @ApiModelProperty(value = "教学模式(普通,录播,直播等)", required = true)
    private String teachmode;
    @ApiModelProperty(value = "课程介绍")
    private String description;
    @ApiModelProperty(value = "课程图片", required = true)
    private String pic;
    @ApiModelProperty(value = "收费规则,对应数据字典", required = true)
    private String charge;
    @ApiModelProperty(value = "价格")
    private Float price;
    @ApiModelProperty(value = "原价")
    private Float originalPrice;
    @ApiModelProperty(value = "qq")
    private String qq;
    @ApiModelProperty(value = "微信")
    private String wechat;
    @ApiModelProperty(value = "电话")
    private String phone;

    @ApiModelProperty(value = "有效期")
    private Integer validDays;
}

第二步: 根据响应结果定义对应的响应模型类,由于其大部分信息来自课程基本信息表,所以我们可以将定义的响应结果模型类继承CourseBase

{
  "id": 109,
  "companyId": 1,
  "companyName": null,
  "name": "测试课程103",
  "users": "初级人员",
  "tags": "",
  "mt": "1-1",
  "mtName": null,大分类名称,
  "st": "1-1-1",
  "stName": null,小分类名称
  "grade": "204001",
  "teachmode": "200002",
  "description": "",
  "pic": "",
    
    
    
  "createDate": "2022-09-08 07:35:16",
  "changeDate": null,
  "createPeople": null,
  "changePeople": null,
  "auditStatus": "202002",
  "status": 1,
    
    
  "coursePubId": null,
  "coursePubDate": null,
  "charge": "201000",
  "price": null,
  "originalPrice":0,
  "qq": "",
  "wechat": "",
  "phone": "",
  "validDays": 365
}
package com.xuecheng.content.model.dto;
/**
 * @version 1.0
 * @description 课程基本信息dto
 */
@Data
public class CourseBaseInfoDto extends CourseBase {
    /**
     * 收费规则,对应数据字典
     */
    private String charge;

    /**
     * 价格
     */
    private Float price;

    /**
     * 原价
     */
    private Float originalPrice;

    /**
     * 咨询qq
     */
    private String qq;

    /**
     * 微信
     */
    private String wechat;

    /**
     * 电话
     */
    private String phone;

    /**
     * 有效期天数
     */
    private Integer validDays;

    /**
     * 大分类名称
     */
    private String mtName;

    /**
     * 小分类名称
     */
    private String stName;

}

接口定义(api工程)

@ApiOperation("新增课程基础信息接口")
@PostMapping("/course")
public CourseBaseInfoDto createCourseBase(@RequestBody AddCourseDto addCourseDto) {
    // 获取机构id(添加的课程和教学机构是一对一的关系),暂时以硬编码的方式指定机构Id后期通过当前登陆的教学机构获取
    Long companyId = 22L;
    return courseBaseInfoService.createCourseBase(companyId, addCourseDto);
}

业务开发(service工程)

第一步: 编写Mapper接口及其SQL映射文件

public interface CourseBaseMapper extends BaseMapper<CourseBase> {
}
public interface CourseCategoryMapper extends BaseMapper<CourseCategory> {
    //使用递归查询分类
    public List<CourseCategoryTreeDto> selectTreeNodes(String id);
}
public interface CourseMarketMapper extends BaseMapper<CourseMarket> {
}

第二步: 编写Service接口及其实现类, 在业务逻辑代码中实现添加课程的效果,由于操作两张表所以需要开启事务

  • 首先对请求参数做合法性校验(前端后端都要校验,Service和Controller层都要校验), 即判断一下用户是否输入了表单必填项以及设置一些参数的默认值
  • 然后对请求参数进行封装并调用数据表对应的Mapper接口进行数据持久化,课程基本信息和课程营销信息的Id相同
  • 最后组装要返回给前端的结果信息
public interface CourseBaseInfoService {
    /**
 	* 新增课程基本信息
  	* @param companyId 教学机构id
 	* @param addCourseDto 课程基本信息
 	* @return
 	*/
    CourseBaseInfoDto createCourseBase(Long companyId, AddCourseDto addCourseDto);
}
@Slf4j
@Service
public class CourseBaseInfoServiceImpl implements CourseBaseInfoService {

    @Resource
    CourseBaseMapper courseBaseMapper;
    @Resource
    CourseMarketMapper courseMarketMapper;
    @Resource
    CourseCategoryMapper courseCategoryMapper;

    @Override
    // 操作两张表需要开启事务
    @Transactional
    public CourseBaseInfoDto createCourseBase(Long companyId, AddCourseDto addCourseDto) {
        // 1. 合法性校验
        if (StringUtils.isBlank(addCourseDto.getName())) {
            throw new RuntimeException("课程名称为空");
        }
        if (StringUtils.isBlank(addCourseDto.getMt())) {
            throw new RuntimeException("课程分类为空");
        }
        if (StringUtils.isBlank(addCourseDto.getSt())) {
            throw new RuntimeException("课程分类为空");
        }
        if (StringUtils.isBlank(addCourseDto.getGrade())) {
            throw new RuntimeException("课程等级为空");
        }
        if (StringUtils.isBlank(addCourseDto.getTeachmode())) {
            throw new RuntimeException("教育模式为空");
        }
        if (StringUtils.isBlank(addCourseDto.getUsers())) {
            throw new RuntimeException("适应人群为空");
        }
        if (StringUtils.isBlank(addCourseDto.getCharge())) {
            throw new RuntimeException("收费规则为空");
        }
        // 2. 将请求参数中包含的课程基本信息封装到对应的实体类对象当中
        CourseBase courseBase = new CourseBase();
        BeanUtils.copyProperties(addCourseDto, courseBase);
        // 2.1 设置默认审核状态(去数据字典表中查询状态码)
        courseBase.setAuditStatus("202002");
        // 2.2 设置默认发布状态
        courseBase.setStatus("203001");
        // 2.3 设置机构id
        courseBase.setCompanyId(companyId);
        // 2.4 设置添加时间
        courseBase.setCreateDate(LocalDateTime.now());
        // 2.5 向课程基本信息表中插入一条记录
        int baseInsert = courseBaseMapper.insert(courseBase);

        // 3.获取刚添加记录的课程Id
        Long courseId = courseBase.getId();

        // 4. 将请求参数中包含的课程营销信息封装到对应的实体类对象当中
        CourseMarket courseMarket = new CourseMarket();
        BeanUtils.copyProperties(addCourseDto, courseMarket);
        // 设置课程营销信息的Id即我们刚添加的课程基本信息
        courseMarket.setId(courseId);
        // 4.1 判断收费规则,若课程收费,则价格必须大于0
        String charge = courseMarket.getCharge();
        if ("201001".equals(charge)) {
            // 价格可以使用Float类型存储,计算的时候使用BigDecimal计算
            Float price = addCourseDto.getPrice();
            if (price == null || price.floatValue() <= 0) {
                throw new RuntimeException("课程设置了收费,价格不能为空,且必须大于0");
            }
        }
        // 4.2 向课程营销信息表中插入一条记录
        int marketInsert = courseMarketMapper.insert(courseMarket);
        // 判断课程基本信息和营销信息是否插入成功
        if (baseInsert <= 0 || marketInsert <= 0) {
            throw new RuntimeException("新增课程基本信息失败");
        }

        // 5.根据插入课程基本信息/课程营销信息的Id,去课程基本信息表和课程营销信息表中查询刚添加的记录,组装成CourseBaseInfoDto对象返回给前端
        return getCourseBaseInfo(courseId);
    }
}

第三步: 根据刚插入课程基本信息/课程营销信息的Id,去课程基本信息表和课程营销信息表中查询刚添加的记录,组装成CourseBaseInfoDto对象返回给前端

private CourseBaseInfoDto getCourseBaseInfo(Long courseId) {
    // 创建返回的Dto对象
    CourseBaseInfoDto courseBaseInfoDto = new CourseBaseInfoDto();
    // 1. 根据课程id查询课程基本信息
    CourseBase courseBase = courseBaseMapper.selectById(courseId);
    if (courseBase == null)
        return null;
    // 1.1 拷贝属性
    BeanUtils.copyProperties(courseBase, courseBaseInfoDto);
    // 2. 根据课程id查询课程营销信息
    CourseMarket courseMarket = courseMarketMapper.selectById(courseId);
    // 2.1 拷贝属性
    if (courseMarket != null)
        BeanUtils.copyProperties(courseMarket, courseBaseInfoDto);
    // 3. 查询课程分类名称并封装到到CourseBaseInfoDto对象中
    // 3.1 根据小分类id(1-1-1)查询对应的课程分类对象
    CourseCategory courseCategoryBySt = courseCategoryMapper.selectById(courseBase.getSt());
    // 3.2 设置课程的小分类名称
    courseBaseInfoDto.setStName(courseCategoryBySt.getName());
    // 3.3 根据大分类id(1-1)查询对应的课程分类对象
    CourseCategory courseCategoryByMt = courseCategoryMapper.selectById(courseBase.getMt());
    // 3.4 设置课程大分类名称
    courseBaseInfoDto.setMtName(courseCategoryByMt.getName());
    return courseBaseInfoDto;
}

接口测试

使用HTTP Client测试新增课程接口

POST {{content_host}}/content/course
Content-Type: application/json

{
  "mt": "1-1",
  "st": "1-1-1",
  "name": "测试课程tmp",
  "pic": "",
  "teachmode": "200002",
  "users": "初级人员",
  "tags": "",
  "grade": "204001",
  "description": "这是一门测试课程",
  "charge": "201000",
  "price": 99,
  "originalPrice": 999,
  "qq": "123564",
  "wechat": "123654",
  "phone": "156213",
  "validDays": 365
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1261510.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

SpringCloud--分布式事务实现

一、分布式事务 首先要明白事务是指数据库中的一组操作&#xff0c;这些操作要么全部成功执行&#xff0c;要么全部不执行&#xff0c;以保持数据的一致性和完整性。在本地事务中&#xff0c;也就是传统的单机事务&#xff0c;必须要满足原子性(Atomicity)、一致性(Consistenc…

错误:FinalShell连接CentOs连接失败

需要说明的是:这个错误不是首次连接发生的,而是多次使用后可能发生的错误 正文: 可能的原因是虚拟机的ip地址发生了变更,原因有以下几点: 最最可能的原因:1.DHCP分配变更&#xff1a; 如果虚拟机使用DHCP来获取IP地址&#xff0c;那么DHCP服务器可能会分配给虚拟机一个新的I…

java设计模式学习之【单例模式】

文章目录 引言单例模式简介定义与用途实现方式&#xff1a;饿汉式懒汉式 UML 使用场景优势与劣势单例模式在spring中的应用饿汉式实现懒汉式实现数据库连接示例代码地址 引言 单例模式是一种常用的设计模式&#xff0c;用于确保在一个程序中一个类只有一个实例&#xff0c;并且…

不小心删除了短信,如何在 Android 上恢复已删除的短信

不小心删除了文字消息在 Android 手机上使用可能会是一种令人痛苦的体验。这些消息可能包含有价值的信息、珍贵的回忆或重要的细节。幸运的是&#xff0c;您可以探索多种方法来恢复这些丢失的消息。在本文中&#xff0c;我们将深入研究可用于检索已删除短信的选项&#xff0c;并…

vue3中readonly和shallowReadonly

readonly: 深度只读数据 获取一个对象 (响应式或纯对象) 或 ref 并返回原始代理的只读代理。 只读代理是深层的&#xff1a;访问的任何嵌套 property 也是只读的。 shallowReadonly 浅只读数据 创建一个代理&#xff0c;使其自身的 property 为只读&#xff0c;但不执行…

WhatsApp API号解封教程(内含图片指引和申诉模板)

WhatsApp API 是专门为中大型企业设置的WhatsApp APP页面&#xff0c;API号并不像WhatsApp个人号和企业号一样可以直接从App Store 或Google Play 下载&#xff0c;而是需要对接官方来连接API。 虽然申请WhatsApp API号的程序和手续比较复杂&#xff0c;但是这个操作对于企业来…

算法通关村第二关—手写链表反转(青铜)

链表反转的三种方式 一、建立虚拟头结点辅助反转 为了方便反转&#xff0c;可以创建一个ans结点&#xff0c;让ans.next head,然后后面的结点一次插入到ans.next 在下图中&#xff0c;对&#xff08;1->2->3->4->5&#xff09;进行反转&#xff0c;可以创建ans&…

easyexcel指定sheet页动态给行列加背景色

easyexcel&#xff0c;有多个sheet页&#xff0c;某些sheet页的行、列动态需要加背景色 import com.alibaba.excel.metadata.CellData; import com.alibaba.excel.metadata.Head; import com.alibaba.excel.write.handler.CellWriteHandler; import com.alibaba.excel.write.m…

Spring Cloud,注册中心,配置中心,原理详解

文章目录 Spring Cloud&#xff0c;注册中心&#xff0c;配置中心&#xff0c;原理详解谈谈我个人对 spring Cloud 的理解 注册中心Eureka&#xff1a;服务搭建小结 Ribbo - 负载均衡1. 负载均衡流程2. 负载均衡策略 nacos注册中心1. 配置集群1. 创建 namespace2. 配置命名空间…

MATLAB实战 | 不同形式的三维曲面图

通常&#xff0c;MATLAB中绘制三维曲面图&#xff0c;先要生成网格数据&#xff0c;再调用mesh函数和surf函数绘制三维曲面。若曲面用含两个自变量的参数方程定义&#xff0c;则还可以调用fmesh函数和fsurf函数绘图。若曲面用隐函数定义&#xff0c;则可以调用fimplicit3函数绘…

RuoYi若依前后端分离框架二次开发基础项目

一键改标题&#xff1a;点击ruoyi-ui(ctrlshiftr)改完重启项目 连接本地数据库 全智能生成开发 新建maven项目 菜单创建---栏目创建 无权限删除时&#xff1a;去掉要删除的菜单权限 子菜单&#xff1a;新增 代码生成器cv进去 后端&#xff1a; 前端&#xff1a; 完成&#x…

人工智能与供应链行业融合:预测算法的通用化与实战化

前言 「作者主页」&#xff1a;雪碧有白泡泡 「个人网站」&#xff1a;雪碧的个人网站 让我们一起深入探索人工智能与供应链的融合&#xff0c;以及预测算法在实际应用中的价值&#xff01;&#x1f50d;&#x1f680; 文章目录 前言供应链预测算法的基本流程统计学习模型与机…

顺子日期(14)

顺着日期 public class Main {public static void main(String[] args) {int res 0;//2022年int[] days new int[] {31,28,31,30,31,30,31,31,30,31,30,31};//31,28,31,30,31,30,31,31,30,31,30,31//一三五七八十腊//构造2022年每一天的日期yyyymmddStringBuffer date new…

现在的教师工资这么低了?

最近刷v站看到个帖子t/991351 &#xff0c;程序员转行回乡当老师月薪才2000&#xff0c;现在的教师工资这么低了&#xff1f;月薪3000都不到。 搜索了下&#xff0c;现在有些地方开始#教师全员竞聘上岗# https://weibo.com/1784473157/NpUd3esCv &#xff0c;曾经的铁饭碗也可能…

【开发问题解决方法记录】02.dian

想重命名表名&#xff0c;但是失败了&#xff0c;提示[0A000][3001] ORA-03001: 未实施的功能 Position: 0. 获取到USER_ID和ROLE_ID但是无法新增成功 问题出在哪里捏&#xff1f; 报错&#xff1a;ORA-06502: PL&#x2F;SQL: 数字或值错误 : 字符到数值的转换错误 展示的是…

不受平台限制,Sketch 网页版震撼登场

Sketch 是一种基于 Mac 的矢量图形编辑器&#xff0c;可用于数字设计。其主要功能包括无损矢量编辑、完美像素精度和数百个插件同步功能&#xff0c;可导出预设和代码。它是目前流行的页面交互协作设计工具。但是 Sketch 最大的缺点是对 Windows/PC 用户不友好。严格来说&#…

笔记十七、认识React的路由插件react-router-dom和基本使用

react-router 分类 web使用 react-router-dom native使用 react-router-native anywhere&#xff08;使用麻烦&#xff09; react-router 安装 yarn add react-router-dom main.jsx import React from "react"; import ReactDOM from "react-dom/client"…

宋仕强论道之华强北曼哈商城(十二)

宋仕强论道之华强北曼哈商城&#xff08;十二&#xff09;&#xff1a; 讲了华强北万佳百货以后要讲旁边配套的商场。在1995年&#xff0c;在万佳百货旁边开了一个曼哈商城&#xff0c;名字叫曼哈是因为老板是美国纽约曼哈顿留学回来的&#xff0c;是一个叫张虹女孩子。华强北曼…

DS图—图的最短路径/Dijkstra算法【数据结构】

DS图—图的最短路径/Dijkstra算法【数据结构】 题目描述 给出一个图的邻接矩阵&#xff0c;输入顶点v&#xff0c;用迪杰斯特拉算法求顶点v到其它顶点的最短路径。 输入 第一行输入t&#xff0c;表示有t个测试实例 第二行输入顶点数n和n个顶点信息 第三行起&#xff0c;每行…

C/C++字节对齐

C/C字节对齐 C/C字节对齐1.G_PACKED2.1 pack(push)2.2 pack(1) 全部例子 C/C字节对齐 1.G_PACKED #ifdef __GNUC__#define G_PACKED( __Declaration__ ) __Declaration__ __attribute__((packed)) #else#define G_PACKED( __Declaration__ ) __pragma( pack(push,1)) __Decla…