5.1 内容管理模块 - 课程预览、提交审核

内容管理模块 - 课程预览、提交审核

文章目录

  • 内容管理模块 - 课程预览、提交审核
  • 一、课程预览
    • 1.1 需求分析
    • 1.2 freemarker 模板引擎
      • 1.2.1 Maven 坐标
      • 1.2.2 freemaker 相关配置信息
      • 1.2.3 添加模板
    • 1.3 测试静态页面
      • 1.3.1 部署Nginx
      • 1.3.2 解决端口问题被占用问题
      • 1.3.3 配置host文件
      • 1.3.4 文件服务器
      • 1.3.5 视频播放页面
    • 1.4 课程预览 主页
      • 1.4.1 CoursePublishController
      • 1.4.2 Nginx 配置反向代理
      • 1.4.3 CoursePublishServiceImpl
      • 1.4.4 编写模板
      • 1.4.5 测试
    • 1.5 课程预览 视频
      • 1.5.1 配置Nginx
      • 1.5.2 CourseOpenController
      • 1.5.3 MediaOpenController
      • 1.5.4 测试
  • 二、提交课程审核
    • 2.1 需求分析
    • 2.2 数据模型
      • 2.2.1 课程预发布表 course_publish_pre
    • 2.3 CoursePublishController
    • 2.4 CoursePublishServiceImpl
    • 2.5 测试

一、课程预览

课程预览就是把课程的相关信息进行整合,在课程预览界面进行展示,课程预览界面与课程发布的课程详情界面一致

image-20240114145730567

1.1 需求分析

客户可以通过课程预览页面查看信息是否存在问题

如下课程预览的数据来源

image-20240114144257854

下图显示了整个课程预览的流程图

image-20240114144459438

也就是说现在怎么给前端返回一个页面呢

最最最原始的JSP可以,一些模板引擎技术也可以

前端请求内容管理服务后,后台服务系统要返回一个页面

最终要返回的页面如下图所示(预览页面,如果客户成功确认发布后,发布后的页面和预览时的页面相同)

image-20240114144449211

说明如下

1、点击课程预览,通过Nginx、后台服务网关请求内容管理服务进行课程预览。

2、内容管理服务查询课程相关信息进行整合,并通过模板引擎技术在服务端渲染生成页面,返回给浏览器。

3、通过课程预览页面点击”马上学习“打开视频播放页面。

4、视频播放页面通过Nginx请求后台服务网关,查询课程信息展示课程计划目录,请求媒资服务查询课程计划绑定的视频文件地址,在线浏览播放视频。

在这里我们用到了两个技术,一个Nginx,一个freemarker

freemarker可以在服务端生成网页然后返回给浏览器

Nginx是一个代理服务器,所有的请求都请求到Nginx上,由Nginx进行代理,然后再由Nginx发送到后台服务上

1.2 freemarker 模板引擎

freemarker提供很多指令用于解析各种类型的数据模型

参考地址:http://freemarker.foofun.cn/ref_directives.html

什么是模板引擎

早期采用的jsp技术就是一种模板引擎技术

image-20240114145255995

1、浏览器请求web服务器

2、服务器渲染页面,渲染的过程就是向jsp页面(模板)内填充数据(模型)。

3、服务器将渲染生成的页面返回给浏览器。

所以模板引擎就是:模板+数据=输出,Jsp页面就是模板,页面中嵌入的jsp标签就是数据,两者相结合输出html网页

模板引擎:服务端生成页面的一项技术

常用的java模板引擎还有哪些

Jsp、Freemarker、Thymeleaf 、Velocity 等。

Freemarker官方地址:http://freemarker.foofun.cn/

FreeMarker 是一款 模板引擎: 即一种基于模板和要改变的数据, 并用来生成输出文本(HTML网页,电子邮件,配置文件,源代码等)的通用工具。 它不是面向最终用户的,而是一个Java类库,是一款程序员可以嵌入他们所开发产品的组件。FreeMarker 是免费的, 基于Apache许可证2.0版本发布。

1.2.1 Maven 坐标

在content-api工程中添加如下所示的坐标

<!-- Spring Boot 对结果视图 Freemarker 集成 -->
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>

1.2.2 freemaker 相关配置信息

freemaker 相关配置信息,我们配置在了nacos的freemarker-config-dev.yaml配置文件中

spring:freemarker:enabled: truecache: false   #关闭模板缓存,方便测试settings:template_update_delay: 0suffix: .ftl   #页面模板后缀名charset: UTF-8template-loader-path: classpath:/templates/   #页面模板位置(默认为 classpath:/templates/)resources:add-mappings: false   #关闭项目中的静态资源映射(static、resources文件夹下的资源)

在content-api工程的bootstrap配置文件引入freemarker-config-dev.yaml配置文件

#微服务配置
spring:application:name: content-api # 项目名cloud:nacos:server-addr: 192.168.101.65:8848 #Nacos地址discovery: #服务发现(服务注册)namespace: dev #命名空间group: xuecheng-plus-project #组别config: # 配置中心...............中间省略了好多配置shared-configs: #公用配置- data-id: freemarker-config-dev.yamlgroup: xuecheng-plus-commonrefresh: true

1.2.3 添加模板

模板其实就是一个HTML页面+数据模型

${name} 就是数据模型,也就是后台的模型数据

<!DOCTYPE html>
<html>
<head><meta charset="utf-8"><title>Hello World!</title>
</head>
<body>
Hello ${name}!
</body>
</html>

后台准备模型数据

// 不要使用RestController,因为返回的是JSON数据,这里我们一定不要返回JSON数据
@Controller
public class FreemarkerController {/***ModelAndView 模型和数据*/@GetMapping("/testfreemarker")public ModelAndView test(){ModelAndView modelAndView = new ModelAndView();//指定模型数据modelAndView.addObject("name","小明");// 指定模型视图// 返回的是哪个视图,且不用加后缀.ftl(文件名test.ftl)// 因为我们已经在配置文件中告诉框架我们文件的后缀名称是什么了spring.freemarker.suffix=.ftlmodelAndView.setViewName("test");return modelAndView;}
}

测试效果

还是能展示出来的

image-20240114151839997

1.3 测试静态页面

准备Nginx和门户

1.3.1 部署Nginx

在本机部署Nginx

server {listen       80;server_name  www.51xuecheng.cn localhost;#rewrite ^(.*) https://$server_name$1 permanent;#charset koi8-r;ssi on;ssi_silent_errors on;#access_log  logs/host.access.log  main;location / {alias    D:/zhangjingqi/Note/xuecheng/Code/xc-ui-pc-static-portal/xc-ui-pc-static-portal/;index  index.html index.htm;}#静态资源location /static/img/ {  alias  D:/zhangjingqi/Note/xuecheng/Code/xc-ui-pc-static-portal/xc-ui-pc-static-portal/img/;} location /static/css/ {  alias   D:/zhangjingqi/Note/xuecheng/Code/xc-ui-pc-static-portal/xc-ui-pc-static-portal/css/;} location /static/js/ {  alias   D:/itcast2022/xc_edu3.0/code_1/xc-ui-pc-static-portal/js/;} location /static/plugins/ {  alias   D:/zhangjingqi/Note/xuecheng/Code/xc-ui-pc-static-portal/xc-ui-pc-static-portal/plugins/;add_header Access-Control-Allow-Origin http://ucenter.51xuecheng.cn;  add_header Access-Control-Allow-Credentials true;  add_header Access-Control-Allow-Methods GET;} location /plugins/ {  alias   D:/zhangjingqi/Note/xuecheng/Code/xc-ui-pc-static-portal/xc-ui-pc-static-portal/plugins/;} #error_page  404              /404.html;# redirect server error pages to the static page /50x.html#error_page   500 502 503 504  /50x.html;location = /50x.html {root   html;}# proxy the PHP scripts to Apache listening on 127.0.0.1:80##location ~ \.php$ {#    proxy_pass   http://127.0.0.1;#}# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000##location ~ \.php$ {#    root           html;#    fastcgi_pass   127.0.0.1:9000;#    fastcgi_index  index.php;#    fastcgi_param  SCRIPT_FILENAME  /scripts$fastcgi_script_name;#    include        fastcgi_params;#}# deny access to .htaccess files, if Apache's document root}

修改过后将Nginx服务进行重启

1.3.2 解决端口问题被占用问题

刚开始的时候80端口一直被占用,从任务浏览器中根本结束不掉对应的进程

然后根据下面两篇文章解决掉了

文章1:

https://blog.csdn.net/qq_34272964/article/details/105207651

如果文章1不能解决的话看一下文章2,我是文章2解决的

https://blog.csdn.net/weixin_43833851/article/details/130188302

启动Nginx访问80端口,如果出现下图所示的界面,说明端口问题已经被解决了

image-20240114155645007

image-20240114161836889

假如说按照1.3.1设置了Nginx配置的话,打开网页会是如下页面

image-20240114164237341

主要访问一下预览界面http://www.51xuecheng.cn/course/course_template.html

image-20240114164342143

1.3.3 配置host文件

C:\Windows\System32\drivers\etc目录下有一个host文件

image-20240114161013919

将下面的内容粘贴到里面即可

127.0.0.1 www.51xuecheng.cn 51xuecheng.cn ucenter.51xuecheng.cn teacher.51xuecheng.cn file.51xuecheng.cn

Centos7操作系统的hosts文件在/etc目录下

当我们输入一个域名的时候,最红需要找到这个域名对应的服务器,也就是ip地址,首先会从host文件中中找

比如我们输入 www.51xuecheng.cn域名,首先会从host文件找,然后找到了,对应的ip是127.0.0.1

假如说在host文件中没有找到域名www.51xuecheng.cn对应的ip,那就会再从dns服务器找,请求到dns服务器进行解析,在dns服务器中就记录了ip和域名的对应关系

1.3.4 文件服务器

在进行课程预览时需要展示课程的图片,在线插放课程视频,课程图片、视频这些都在MinIO文件系统存储,下边统一由Nginx代理,通过文件服务域名统一访问。如下图

image-20240114164454502

我们使用的分布式文件系统MinIO来存储的文件,并且MinIO有许多的结点

我们打算前端的请求都请求到Nginx,然后由Nginx代理请求到MinIO中

比如获取一个图片,我们可以先请求到Nginx,然后再由Nginx请求到MinIO中获取图片

host文件配置如下所示信息

127.0.0.1 www.51xuecheng.cn file.51xuecheng.cn

nginx.conf中配置文件服务器的代理地址

相当于nginx.conf中再来一套配置

其实请求/video的时候就会代理到 server 192.168.101.65:9000服务器去请求资源

   #文件服务upstream fileserver{server 192.168.101.65:9000 weight=10;} server {listen       80;server_name  file.51xuecheng.cn;#charset koi8-r;ssi on;ssi_silent_errors on;#access_log  logs/host.access.log  main;location /video {proxy_pass   http://fileserver;}location /mediafiles {proxy_pass   http://fileserver;}}

image-20240114165315288

配置完毕,重新加载nginx配置文件

通过cmd进入nginx.exe所在目录,运行如下命令

nginx.exe -s reload

访问:http://file.51xuecheng.cn/mediafiles/2022/09/13/a16da7a132559daf9e1193166b3e7f52.jpg

如下所示效果

image-20240114165854981

1.3.5 视频播放页面

首先在nginx.conf中配置视频播放页面的地址

        location /course/preview/learning.html {alias D:/zhangjingqi/Note/xuecheng/Code/xc-ui-pc-static-portal/xc-ui-pc-static-portal/course/learning.html;} location /course/search.html {  root    D:/zhangjingqi/Note/xuecheng/Code/xc-ui-pc-static-portal/xc-ui-pc-static-portal;} location /course/learning.html {  root    D:/zhangjingqi/Note/xuecheng/Code/xc-ui-pc-static-portal/xc-ui-pc-static-portal;}

image-20240114170136975

重新加载配置文件

之后

下边需要配置learning.html页面的视频播放路径来测试视频播放页面,找到learning.html页面中videoObject对象的定义处,配置视频的播放地址

image-20240114170429866

换成minio系统中一个可以播放的地址

image-20240114170725677

1.4 课程预览 主页

课程预览接口要将课程信息进行整合,在服务端渲染页面后返回浏览器。

下边对课程预览接口进行分析:

1、请求参数

传入课程id,表示要预览哪一门课程。

2、响应结果

输出课程详情页面到浏览器

响应页面到浏览器使用freemarker模板引擎技术实现,首先从课程资料目录下获取课程预览页面course_template.html,拷贝至内容管理的接口工程的resources/templates下,并将其在本目录复制一份命名为course_template.ftl

也就是说下图中的整个页面都是模板内容

image-20240114200939485

其实就是下图所示的四部分信息

image-20240114210819041

1.4.1 CoursePublishController

@Controller
public class CoursePublishController {@AutowiredCoursePublishServiceImpl coursePublishService;@GetMapping("/coursepreview/{courseId}")public ModelAndView preview(@PathVariable("courseId") Long courseId) {ModelAndView modelAndView = new ModelAndView();// 从数据库查询模型的数据(课程营销信息表、课程师资表、课程基本信息表、课程计划)CoursePreviewDto coursePreviewInfo = coursePublishService.getCoursePreviewInfo(courseId);// 指定模型数据modelAndView.addObject("model", coursePreviewInfo);// 指定模板modelAndView.setViewName("course_template");return modelAndView;}}

其中需要的课程预览模型类

/*** @description 课程预览数据模型*/@Data@ToString
public class CoursePreviewDto {//课程基本信息,课程营销信息CourseBaseInfoDto courseBase;//课程计划信息List<TeachplanDto> teachplans;//师资信息暂时不加...}

1.4.2 Nginx 配置反向代理

课程预览接口虽然可以正常访问,但是页面没有样式,查看浏览器请求记录,发现图片、样式无法正常访问

这些静态资源全在门户下,我们需要由Nginx反向代理访问课程预览接口,通过门户的URL去访问课程预览

Nginx中如下所示配置

  upstream gatewayserver{server 127.0.0.1:63010 weight=10;} server {listen       80;server_name  www.51xuecheng.cn localhost;....#apilocation /api/ {proxy_pass http://gatewayserver/;} 

之后重新启动Nginx

image-20240114203228126

访问地址: http://www.51xuecheng.cn/api/content/coursepreview/74

出现的场景如下图所示

image-20240114210244573

现在的请求其实是下面所示的流程:

image-20240114210441194

1.4.3 CoursePublishServiceImpl

/*** 课程发布相关业务*/
@Service
public class CoursePublishServiceImpl implements CoursePublishService {//课程基础信息(课程营销信息表/课程基本信息表)@AutowiredCourseBaseInfoService courseBaseInfoService;//课程计划@AutowiredTeachplanService teachplanService;/*** @param courseId 课程id* @description 获取课程预览信息*/@Overridepublic CoursePreviewDto getCoursePreviewInfo(Long courseId) {// 从数据库查询模型的数据(课程营销信息表、课程师资表、课程基本信息表、课程计划)// 课程基本信息,营销信息CourseBaseInfoDto courseBaseInfoDto = courseBaseInfoService.getCourseBaseInfo(courseId);//课程计划信息List<TeachplanDto> teachplanTree = teachplanService.findTeachplanTree(courseId);// 组装返回信息CoursePreviewDto coursePreviewDto = new CoursePreviewDto();coursePreviewDto.setCourseBase(courseBaseInfoDto);coursePreviewDto.setTeachplans(teachplanTree);return coursePreviewDto;}
}

1.4.4 编写模板

模型数据准备好后下一步将模型数据填充到course_template.ftl上,填充时注意不要一次填充太多,一边填充一边刷新调试。

freemarker提供很多指令用于解析各种类型的数据模型

参考地址:http://freemarker.foofun.cn/ref_directives.html

<!DOCTYPE html>
<html lang="zh-CN"><head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><!-- 上述3个meta标签*必须*放在最前面,任何其他内容都*必须*跟随其后! --><meta name="description" content=""><meta name="author" content=""><link rel="icon" href="/static/img/asset-favicon.ico"><title>学成在线-${model.courseBase.name}</title><link rel="stylesheet" href="/static/plugins/normalize-css/normalize.css"/><link rel="stylesheet" href="/static/plugins/bootstrap/dist/css/bootstrap.css"/><link rel="stylesheet" href="/static/css/page-learing-article.css"/>
</head><body data-spy="scroll" data-target="#articleNavbar" data-offset="150">
<!-- 页面头部 -->
<!--#include virtual="/include/header.html"-->
<!--页面头部结束sss-->
<div id="learningArea"><div class="article-banner"><div class="banner-bg"></div><div class="banner-info"><div class="banner-left"><p>${model.courseBase.mtName!''}<span>\ ${model.courseBase.stName!''}</span></p><p class="tit">${model.courseBase.name}</p><p class="pic"><#if model.courseBase.charge=='201000'><span class="new-pic">免费</span><#else><span class="new-pic">特惠价格¥${model.courseBase.price!''}</span><span class="old-pic">原价¥${model.courseBase.originalPrice!''}</span></#if></p><p class="info"><a href="#" @click.prevent="startLearning()">马上学习</a><span><em>难度等级</em><#if model.courseBase.grade=='204001'>初级<#elseif model.courseBase.grade=='204002'>中级<#elseif model.courseBase.grade=='204003'>高级</#if></span><span><em>课程时长</em>2小时27分</span><span><em>评分</em>4.7分</span><span><em>授课模式</em><#if model.courseBase.teachmode=='200002'>录播<#elseif model.courseBase.teachmode=='200003'>直播</#if></span></p></div><div class="banner-rit"><p><a href="http://www.51xuecheng.cn/course/preview/learning.html?id=${model.courseBase.id}"target="_blank"><#if model.courseBase.pic??><img src="http://file.51xuecheng.cn${model.courseBase.pic}" alt="" width="270" height="156"><#else><img src="/static/img/widget-video.png" alt="" width="270" height="156"></#if></a></p><p class="vid-act"><span> <i class="i-heart"></i>收藏 23 </span> <span>分享 <i class="i-weixin"></i><iclass="i-qq"></i></span></p></div></div></div><div class="article-cont"><div class="tit-list"><a href="javascript:;" id="articleClass" class="active">课程介绍</a><a href="javascript:;" id="articleItem">目录</a><a href="javascript:;" id="artcleAsk">问答</a><a href="javascript:;" id="artcleNot">笔记</a><a href="javascript:;" id="artcleCod">评价</a><!--<div class="down-fill"><span>资料下载</span><ul><li>java视频资料</li><li>java视频资料</li><li>java视频资料</li></ul></div>--></div><div class="article-box"><div class="articleClass" style="display: block"><!--<div class="rit-title">评价</div>--><div class="article-cont"><div class="article-left-box"><div class="content"><div class="content-com suit"><div class="title"><span>适用人群</span></div><div class="cont cktop"><div><p>${model.courseBase.users!""}</p></div><!--<span class="on-off">更多 <i class="i-chevron-bot"></i></span>--></div></div><div class="content-com course"><div class="title"><span>课程制作</span></div><div class="cont"><div class="img-box"><img src="/static/img/widget-myImg.jpg" alt=""></div><div class="info-box"><p class="name">教学方:<em>XX老师</em></p><!-- <p class="lab">高级前端开发工程师 10年开发经验</p>--><p class="info">JavaEE开发与教学多年,精通JavaEE技术体系,对流行框架JQuery、DWR、Struts1/2,Hibernate,Spring,MyBatis、JBPM、Lucene等有深入研究。授课逻辑严谨,条理清晰,注重学生独立解决问题的能力。</p><!-- <p><span>难度等级</span>中级</p><p><span>课程时长</span>8-16小时/周,共4周</p><p><span>如何通过</span>通过所有的作业及考核,作业共4份,考核为一次终极考核</p><p><span>用户评分</span>平均用户评分 <em>4.9</em> <a href="#">查看全部评价</a></p><p><span>课程价格</span>特惠价格<em>¥999</em> <i> 原价1999 </i></p>--></div></div></div><div class="content-com about"><div class="title"><span>课程介绍</span></div><div class="cont cktop"><div><p>${model.courseBase.description!""}</p></div><!--<span class="on-off">更多 <i class="i-chevron-bot"></i></span>--></div></div><div class="content-com prob"><div class="title"><span>常见问题</span></div><div class="cont"><ul><li class="item"><span class="on-off"><i class="i-chevron-bot"></i> 我什么时候能够访问课程视频与作业?</span><div class="drop-down"><p>课程安排灵活,课程费用支付提供180天全程准入和资格证书。自定进度课程建议的最后期限,但你不会受到惩罚错过期限,只要你赚你的证书在180天内。以会话为基础的课程可能要求你在截止日期前保持正轨,但如果你落后了,你可以切换到以后的会议,你完成的任何工作将与你转移。</p></div></li><li class="item"><span class="on-off"><i class="i-chevron-bot"></i> 如何需要额外的时间来完成课程会怎么样?</span><div class="drop-down"><p>课程安排灵活,课程费用支付提供180天全程准入和资格证书。自定进度课程建议的最后期限,但你不会受到惩罚错过期限,只要你赚你的证书在180天内。以会话为基础的课程可能要求你在截止日期前保持正轨,但如果你落后了,你可以切换到以后的会议,你完成的任何工作将与你转移。</p></div></li><li class="item"><span class="on-off"><i class="i-chevron-bot"></i> 我支付次课程之后会得到什么?</span><div class="drop-down"><p>课程安排灵活,课程费用支付提供180天全程准入和资格证书。自定进度课程建议的最后期限,但你不会受到惩罚错过期限,只要你赚你的证书在180天内。以会话为基础的课程可能要求你在截止日期前保持正轨,但如果你落后了,你可以切换到以后的会议,你完成的任何工作将与你转移。</p></div></li><li class="item"><span class="on-off"><i class="i-chevron-bot"></i> 退款条例是如何规定的?</span><div class="drop-down"><p>课程安排灵活,课程费用支付提供180天全程准入和资格证书。自定进度课程建议的最后期限,但你不会受到惩罚错过期限,只要你赚你的证书在180天内。以会话为基础的课程可能要求你在截止日期前保持正轨,但如果你落后了,你可以切换到以后的会议,你完成的任何工作将与你转移。</p></div></li><li class="item"><span class="on-off"><i class="i-chevron-bot"></i> 有助学金?</span><div class="drop-down"><p>课程安排灵活,课程费用支付提供180天全程准入和资格证书。自定进度课程建议的最后期限,但你不会受到惩罚错过期限,只要你赚你的证书在180天内。以会话为基础的课程可能要求你在截止日期前保持正轨,但如果你落后了,你可以切换到以后的会议,你完成的任何工作将与你转移。</p></div></li></ul></div></div></div></div><!--侧边栏--><!--#include virtual="/include/course_detail_side.html"--><!--侧边栏--></div></div><div class="articleItem" style="display: none"><div class="article-cont-catalog"><div class="article-left-box"><div class="content"><#list model.teachplans as firstNode><div class="item"><div class="title act"><i class="i-chevron-top"></i>${firstNode.pname}<spanclass="time">x小时</span></div><div class="drop-down" style="height: 260px;"><ul class="list-box"><#list firstNode.teachPlanTreeNodes as secondNode><li><a href="http://www.51xuecheng.cn/course/preview/learning.html?id=${model.courseBase.id}&chapter=${secondNode.teachplanMedia.teachplanId!''}"target="_blank">${secondNode.pname}</a></li></#list></ul></div></div></#list><#-- <div class="item"><div class="title act"><i class="i-chevron-top"></i>第一阶段 HTTP协议基础详解<span class="time">8小时</span></div><div class="about">使用Java消息中间件处理异步消息成为了分布式系统中的必修课,通过本门课程可以深入浅出的学习如何在Java中使用消息中间件并且一步一步打造更优雅的最佳实践方案。</div><div class="drop-down" style="height: 260px;"><ul class="list-box"><li class="active">1.1 阅读:分级政策细节 <span>97’33”</span></li><li>1.2 视频:为什么分为 A 部分、B 部分、C 部分 <span>66’15”</span></li><li>1.3 视频:软件安装介绍 <span>86’42”</span></li><li>1.4 阅读:Emacs安装 <span>59’00”</span></li><li>1.5 作业1:Emacs安装 <span>93’29”</span></li><li>阶段测试</li></ul></div></div>--></div></div><!--侧边栏--><!--#include virtual="/include/course_detail_side.html"--><!--侧边栏--></div></div><#--<div class="articleItem" style="display: none"><div class="article-cont-catalog"><div class="article-left-box"><div class="content"><div class="item"><div class="title act"><i class="i-chevron-top"></i>第一阶段 HTTP协议基础详解<span class="time">8小时</span></div><div class="about">使用Java消息中间件处理异步消息成为了分布式系统中的必修课,通过本门课程可以深入浅出的学习如何在Java中使用消息中间件并且一步一步打造更优雅的最佳实践方案。</div><div class="drop-down" style="height: 260px;"><ul class="list-box"><li class="active">1.1 阅读:分级政策细节 <span>97’33”</span></li><li>1.2 视频:为什么分为 A 部分、B 部分、C 部分 <span>66’15”</span></li><li>1.3 视频:软件安装介绍 <span>86’42”</span></li><li>1.4 阅读:Emacs安装 <span>59’00”</span></li><li>1.5 作业1:Emacs安装 <span>93’29”</span></li><li>阶段测试</li></ul></div></div><div class="item"><div class="title"><i class="i-chevron-bot"></i>第二阶段 HTTP协议基础详解<span class="time">8小时</span></div><div class="about">使用Java消息中间件处理异步消息成为了分布式系统中的必修课,通过本门课程可以深入浅出的学习如何在Java中使用消息中间件并且一步一步打造更优雅的最佳实践方案。</div><div class="drop-down"><ul class="list-box"><li class="active">1.1 阅读:分级政策细节 <span>97’33”</span></li><li>1.2 视频:为什么分为 A 部分、B 部分、C 部分 <span>66’15”</span></li><li>1.3 视频:软件安装介绍 <span>86’42”</span></li><li>1.4 阅读:Emacs安装 <span>59’00”</span></li><li>1.5 作业1:Emacs安装 <span>93’29”</span></li><li>阶段测试</li></ul></div></div><div class="item"><div class="title"><i class="i-chevron-bot"></i>第三阶段 HTTP协议基础详解<span class="time">3小时</span></div><div class="about">使用Java消息中间件处理异步消息成为了分布式系统中的必修课,通过本门课程可以深入浅出的学习如何在Java中使用消息中间件并且一步一步打造更优雅的最佳实践方案。</div><div class="drop-down"><ul class="list-box"><li class="active">1.1 阅读:分级政策细节 <span>97’33”</span></li><li>1.2 视频:为什么分为 A 部分、B 部分、C 部分 <span>66’15”</span></li><li>1.3 视频:软件安装介绍 <span>86’42”</span></li><li>1.4 阅读:Emacs安装 <span>59’00”</span></li><li>1.5 作业1:Emacs安装 <span>93’29”</span></li><li>阶段测试</li></ul></div></div><div class="item"><div class="title"><i class="i-chevron-bot"></i>第四阶段 HTTP协议基础详解<span class="time">3小时</span></div><div class="about">使用Java消息中间件处理异步消息成为了分布式系统中的必修课,通过本门课程可以深入浅出的学习如何在Java中使用消息中间件并且一步一步打造更优雅的最佳实践方案。</div><div class="drop-down"><ul class="list-box"><li class="active">1.1 阅读:分级政策细节 <span>97’33”</span></li><li>1.2 视频:为什么分为 A 部分、B 部分、C 部分 <span>66’15”</span></li><li>1.3 视频:软件安装介绍 <span>86’42”</span></li><li>1.4 阅读:Emacs安装 <span>59’00”</span></li><li>1.5 作业1:Emacs安装 <span>93’29”</span></li><li>阶段测试</li></ul></div></div><div class="item"><div class="title"><i class="i-chevron-bot"></i>第五阶段 HTTP协议基础详解<span class="time">3小时</span></div><div class="about">使用Java消息中间件处理异步消息成为了分布式系统中的必修课,通过本门课程可以深入浅出的学习如何在Java中使用消息中间件并且一步一步打造更优雅的最佳实践方案。</div><div class="drop-down"><ul class="list-box"><li class="active">1.1 阅读:分级政策细节 <span>97’33”</span></li><li>1.2 视频:为什么分为 A 部分、B 部分、C 部分 <span>66’15”</span></li><li>1.3 视频:软件安装介绍 <span>86’42”</span></li><li>1.4 阅读:Emacs安装 <span>59’00”</span></li><li>1.5 作业1:Emacs安装 <span>93’29”</span></li><li>阶段测试</li></ul></div></div><div class="item"><a href="#" class="overwrite">毕业考核</a></div></div></div><!--侧边栏&ndash;&gt;<!--#include virtual="/include/course_detail_side.html"&ndash;&gt;<!--侧边栏&ndash;&gt;</div></div>--><div class="artcleAsk" style="display: none"><div class="article-cont-ask"><div class="article-left-box"><div class="content"><div class="content-title"><p><a class="all">全部</a><a>精选</a><a>我的</a></p><p><a class="all">全部</a><span><a>1.1</a><a>1.2</a><a>1.3</a><a>1.4</a><a>1.5</a></span><ahref="$" class="more">更多 <i class="i-chevron-bot"></i></a></p></div><div class="item"><div class="item-left"><p><img src="/static/img/widget-myImg.jpg" width="60px" alt=""></p><p>毛老师</p></div><div class="item-right"><p class="title">如何用微服务重构应用程序?</p><p><span>我来回答</span></p><p>2017-3-20 <span><i></i>回答2</span><span><i></i>浏览2</span></p></div></div><div class="item"><div class="item-left"><p><img src="/static/img/widget-myImg.jpg" width="60px" alt=""></p><p>毛老师</p></div><div class="item-right"><p class="title">如何用微服务重构应用程序?</p><p>在讨论如何将重构转化为微服务之前,退后一步,仔细观察微服务的内容和时间是很重要的。以下两个要点将会对任何微服务重构策略产生重大影响。 【最新 <iclass="new">心跳347890</i> 的回答】</p><p>2017-3-20 <span class="action-box"><span><iclass="i-answer"></i>回答 2</span><span><i class="i-browse"></i>浏览 12</span></span></p></div></div><div class="item"><div class="item-left"><p><img src="/static/img/widget-myImg.jpg" width="60px" alt=""></p><p>毛老师</p></div><div class="item-right"><p class="title">如何用微服务重构应用程序?</p><p>在讨论如何将重构转化为微服务之前,退后一步,仔细观察微服务的内容和时间是很重要的。以下两个要点将会对任何微服务重构策略产生重大影响。 【最新 <iclass="new">心跳347890</i> 的回答】</p><p>2017-3-20 <span class="action-box"><span><iclass="i-answer"></i>回答 2</span><span><i class="i-browse"></i>浏览 12</span></span></p></div></div><div class="item"><div class="item-left"><p><img src="/static/img/widget-myImg.jpg" width="60px" alt=""></p><p>毛老师</p></div><div class="item-right"><p class="title">如何用微服务重构应用程序?</p><p>在讨论如何将重构转化为微服务之前,退后一步,仔细观察微服务的内容和时间是很重要的。以下两个要点将会对任何微服务重构策略产生重大影响。 【最新 <iclass="new">心跳347890</i> 的回答】</p><p>2017-3-20 <span class="action-box"><span><iclass="i-answer"></i>回答 2</span><span><i class="i-browse"></i>浏览 12</span></span></p></div></div><div class="item"><div class="item-left"><p><img src="/static/img/widget-myImg.jpg" width="60px" alt=""></p><p>毛老师</p></div><div class="item-right"><p class="title">如何用微服务重构应用程序?</p><p>在讨论如何将重构转化为微服务之前,退后一步,仔细观察微服务的内容和时间是很重要的。以下两个要点将会对任何微服务重构策略产生重大影响。 【最新 <iclass="new">心跳347890</i> 的回答】</p><p>2017-3-20 <span class="action-box"><span><iclass="i-answer"></i>回答 2</span><span><i class="i-browse"></i>浏览 12</span></span></p></div></div><div class="item"><div class="item-left"><p><img src="/static/img/widget-myImg.jpg" width="60px" alt=""></p><p>毛老师</p></div><div class="item-right"><p class="title">如何用微服务重构应用程序?</p><p>在讨论如何将重构转化为微服务之前,退后一步,仔细观察微服务的内容和时间是很重要的。以下两个要点将会对任何微服务重构策略产生重大影响。 【最新 <iclass="new">心跳347890</i> 的回答】</p><p>2017-3-20 <span class="action-box"><span><iclass="i-answer"></i>回答 2</span><span><i class="i-browse"></i>浏览 12</span></span></p></div></div><div class="itemlast"><a href="#" class="overwrite">显示更多问题</a></div></div></div><!--侧边栏--><!--#include virtual="/include/course_detail_side.html"--><!--侧边栏--></div></div><div class="artcleNot" style="display: none;"><div class="article-cont-note"><div class="article-left-box"><div class="content"><div class="content-title"><p><a class="all">全部</a><a>精选</a><a>我的</a></p><p><a class="all">全部</a><span><a>1.1</a><a>1.2</a><a>1.3</a><a>1.4</a><a>1.5</a></span><ahref="$" class="more">更多 <i class="i-chevron-bot"></i></a></p></div><div class="item"><div class="item-left"><p><img src="/static/img/widget-myImg.jpg" width="60px" alt=""></p><p>毛老师</p></div><div class="item-right"><span class="video-time"><i class="i-play"></i>2`10`</span><p><img src="/static/img/widget-demo.png" width="221" alt=""></p><p class="action-box">4小时前 <span class="active-box"><span><iclass="i-coll"></i>采集</span><span><i class="i-laud"></i></span></span></p></div></div><div class="item"><div class="item-left"><p><img src="/static/img/widget-myImg.jpg" width="60px" alt=""></p><p>毛老师</p></div><div class="item-right"><p>在讨论如何将重构转化为微服务之前,退后一步,<br>仔细观察微服务的内容和时间是很重要的。<br>以下两个要点将会对任何微服务重构策略产生重大影响。 </p><p class="action-box">4小时前 <span class="active-box"><span><iclass="i-edt"></i>编辑</span><span><iclass="i-del"></i>删除</span><span><i class="i-laud"></i></span></span></p></div></div><div class="item"><div class="item-left"><p><img src="/static/img/widget-myImg.jpg" width="60px" alt=""></p><p>毛老师</p></div><div class="item-right"><p>在讨论如何将重构转化为微服务之前,退后一步,<br>仔细观察微服务的内容和时间是很重要的。<br>以下两个要点将会对任何微服务重构策略产生重大影响。 </p><p class="action-box">4小时前 <span class="active-box"><span><iclass="i-edt"></i>编辑</span><span><iclass="i-del"></i>删除</span><span><i class="i-laud"></i></span></span></p></div></div><div class="item"><div class="item-left"><p><img src="/static/img/widget-myImg.jpg" width="60px" alt=""></p><p>毛老师</p></div><div class="item-right"><p>在讨论如何将重构转化为微服务之前,退后一步,<br>仔细观察微服务的内容和时间是很重要的。<br>以下两个要点将会对任何微服务重构策略产生重大影响。 </p><p class="action-box">4小时前 <span class="active-box"><span><iclass="i-edt"></i>编辑</span><span><iclass="i-del"></i>删除</span><span><i class="i-laud"></i></span></span></p></div></div></div></div><!--侧边栏--><!--#include virtual="/include/course_detail_side.html"--><!--侧边栏--></div></div><div class="artcleCod" style="display: none;"><div class="article-cont"><div class="article-left-box"><div class="comment-box"><div class="evaluate"><div class="eva-top"><div class="tit">课程评分</div><div class="star"><div class="score"><i>5</i></div></div><span class="star-score"> <i>5</i></span></div><div class="eva-cont"><div class="tit">学员评语</div><div class="text-box"><textarea class="form-control" rows="5"placeholder="扯淡、吐槽、表扬、鼓励......想说啥说啥!"></textarea><div class="text-right"><span>发表评论</span></div></div></div></div><div class="course-evaluate"><div class="top-tit">评论<span><label><input name="eval" type="radio" value="" checked/> 所有学生 </label><label><input name="eval" type="radio" value=""/> 完成者 </label></span></div><div class="top-cont"><div class="cont-top-left"><div class="star-scor"><div class="star-show"><div class="score"><i>5</i></div></div><div class="scor">4.9分</div></div><div class="all-scor">总评分:12343</div></div><div class="cont-top-right"><div class="star-grade">五星<div class="grade"><div class="grade-percent"><span></span></div><div class="percent-num"><i>95</i>%</div></div></div><div class="star-grade">四星<div class="grade"><div class="grade-percent"><span></span></div><div class="percent-num"><i>5</i>%</div></div></div><div class="star-grade">三星<div class="grade"><div class="grade-percent"><span></span></div><div class="percent-num"><i>0</i>%</div></div></div><div class="star-grade">二星<div class="grade"><div class="grade-percent"><span></span></div><div class="percent-num"><i>2</i>%</div></div></div><div class="star-grade">一星<div class="grade"><div class="grade-percent"><span></span></div><div class="percent-num"><i>1</i>%</div></div></div></div></div><div class="comment-item-box"><div class="title">评论 <span>12453条评论</span></div><div class="item"><div class="item-left"><p><img src="/static/img/widget-pic.png" width="60px" alt=""></p><p>毛老师</p></div><div class="item-cent"><p>很受用,如果再深入下就更好了。虽然都是入门级别的,但是也很使用,后续就需要自己发挥了!虽然都是入门级别的,但是也很使用,后续就需要自己发挥了!虽然都是入门级别的,但是也很使用,后续就需要自己发挥了!虽然都是入门级别的,但是也很使用,后续就需要自己发挥了!</p><p class="time">2017-2-43</p></div><div class="item-rit"><p><div class="star-show"><div class="score"><i>4</i></div></div></p><p>评分 <span>5星</span></p></div></div><div class="item"><div class="item-left"><p><img src="/static/img/widget-pic.png" width="60px" alt=""></p><p>毛老师</p></div><div class="item-cent"><p>很受用,如果再深入下就更好了。虽然都是入门级别的,但是也很使用,后续就需要自己发挥了!虽然都是入门级别的,但是也很使用,后续就需要自己发挥了!虽然都是入门级别的,但是也很使用,后续就需要自己发挥了!虽然都是入门级别的,但是也很使用,后续就需要自己发挥了!</p><p class="time">2017-2-43</p></div><div class="item-rit"><p><div class="star-show"><div class="score"><i>5</i></div></div></p><p>评分 <span>5星</span></p></div></div><div class="item"><div class="item-left"><p><img src="/static/img/widget-pic.png" width="60px" alt=""></p><p>毛老师</p></div><div class="item-cent"><p>很受用,如果再深入下就更好了。虽然都是入门级别的,但是也很使用,后续就需要自己发挥了!虽然都是入门级别的,但是也很使用,后续就需要自己发挥了!虽然都是入门级别的,但是也很使用,后续就需要自己发挥了!虽然都是入门级别的,但是也很使用,后续就需要自己发挥了!</p><p class="time">2017-2-43</p></div><div class="item-rit"><p><div class="star-show"><div class="score"><i>5</i></div></div></p><p>评分 <span>5星</span></p></div></div><div class="item"><div class="item-left"><p><img src="/static/img/widget-pic.png" width="60px" alt=""></p><p>毛老师</p></div><div class="item-cent"><p>很受用,如果再深入下就更好了。虽然都是入门级别的,但是也很使用,后续就需要自己发挥了!虽然都是入门级别的,但是也很使用,后续就需要自己发挥了!虽然都是入门级别的,但是也很使用,后续就需要自己发挥了!虽然都是入门级别的,但是也很使用,后续就需要自己发挥了!</p><p class="time">2017-2-43</p></div><div class="item-rit"><p><div class="star-show"><div class="score"><i>5</i></div></div></p><p>评分 <span>5星</span></p></div></div><div class="get-more">页面加载中...</div></div></div></div></div><!--侧边栏--><!--#include virtual="/include/course_detail_side.html"--><!--侧边栏--></div></div></div></div><div class="popup-course"><div class="mask"></div><!--欢迎访问课程弹窗- start --><div class="popup-course-box"><div class="title">${model.courseBase.name} <span class="close-popup-course-box">×</span></div><div class="content"><p>欢迎学习本课程,本课程免费您可以立即学习,也可加入我的课程表享受更优质的服务。</p><p><a href="#" @click.prevent="addCourseTable()">加入我的课程表</a> <a href="#"@click.prevent="startLearngin()">立即学习</a></p></div></div></div><div class="popup-box"><div class="mask"></div><!--支付弹窗- start --><div class="popup-pay-box"><div class="title">${model.courseBase.name} <span class="close-popup-pay-box">×</span></div><div class="content"><img :src="qrcode" width="200" height="200" alt="请点击支付宝支付按钮,并完成扫码支付。"/><div class="info"><p class="info-tit">${model.courseBase.name}<span>课程有效期:${model.courseBase.validDays}天</span></p><p class="info-pic">课程价格 : <span>¥${model.courseBase.originalPrice!''}元</span></p><p class="info-new-pic">优惠价格 : <span>¥${model.courseBase.price!''}元</span></p></div></div><div class="fact-pic">实际支付: <span>¥${model.courseBase.price!''}元</span></div><div class="go-pay"><a href="#" @click.prevent="wxPay()">微信支付</a><a href="#"@click.prevent="aliPay()">支付宝支付</a><ahref="#" @click.prevent="querypayresult()">支付完成</a><a href="#" @click.prevent="startLearngin()">试学</a></div></div><!--支付弹窗- end --><div class="popup-comment-box"></div></div><!-- 页面底部 --><!--底部版权--><!--#include virtual="/include/footer.html"--><!--底部版权-->
</div>
<script>var courseId = "${model.courseBase.id}";var courseCharge = "${model.courseBase.charge}"</script>
<!--#include virtual="/include/course_detail_dynamic.html"-->
</body>

1.4.5 测试

首先修改一下前端“.env”文件

image-20240114213703151

启动前后端项目进行联调

image-20240114223829465image-20240114223903093

1.5 课程预览 视频

我们在“课程预览”模块右侧有一个目录,点击目录之后可以查看对应的视频

image-20240114224326825

1.5.1 配置Nginx

从路径就能看出来,是公开的,不管用户是否登录都能访问

#openapi
location /open/content/ {proxy_pass http://gatewayserver/content/open/;
} 
location /open/media/ {proxy_pass http://gatewayserver/media/open/;
} 

重新加载一下配置文件

nginx.exe -s reload

1.5.2 CourseOpenController

在content-api模块创建此类

@Api(value = "课程公开查询接口", tags = "课程公开查询接口")
@RestController
@RequestMapping("/open")
public class CourseOpenController {@Autowiredprivate CourseBaseInfoService courseBaseInfoService;@Autowiredprivate CoursePublishService coursePublishService;/*** 根据课程的id查询课程的信息*/@GetMapping("/course/whole/{courseId}")public CoursePreviewDto getPreviewInfo(@PathVariable("courseId") Long courseId) {//获取课程预览信息return coursePublishService.getCoursePreviewInfo(courseId);}}

1.5.3 MediaOpenController

在media-api工程中创建此类

@Api(value = "媒资文件管理接口", tags = "媒资文件管理接口")
@RestController
@RequestMapping("/open")
public class MediaOpenController {@AutowiredMediaFileService mediaFileService;@ApiOperation("预览文件")@GetMapping("/preview/{mediaId}")public RestResponse<String> getPlayUrlByMediaId(@PathVariable String mediaId) {MediaFiles mediaFiles = mediaFileService.getFileById(mediaId);if (mediaFiles == null || StringUtils.isEmpty(mediaFiles.getUrl())) {XueChengPlusException.cast("视频还没有转码处理");}return RestResponse.success(mediaFiles.getUrl());}}
/*** 根据媒资id获取媒资信息*/
@Override
public MediaFiles getFileById(String mediaId) {return mediaFilesMapper.selectById(mediaId);
}

1.5.4 测试

这些如果关联视频的话,都是可以播放的,但是我只关联了一个视频

image-20240114231858162

二、提交课程审核

在如下图所示区域

image-20240114232936421

2.1 需求分析

来自黑马程序员资料

课程发布前要先审核,审核通过方可发布

image-20240114233240683

为什么课程审核通过才可以发布呢

这样做为了防止课程信息有违规情况,课程信息不完善对网站用户体验也不好,课程审核不仅起到监督作用,也是帮助教学机构规范使用平台的手段。

如何控制课程审核通过才可以发布课程呢

在课程基本表course_base表设置课程审核状态字段,包括:未提交、已提交(未审核)、审核通过、审核不通过。

下边是课程状态的转化关系

真的非常的形象

img

说明如下

1、一门课程新增后它的审核状为”未提交“,发布状态为”未发布“。

2、课程信息编辑完成,教学机构人员执行”提交审核“操作。此时课程的审核状态为”已提交“。

3、当课程状态为已提交时运营平台人员对课程进行审核。

4、运营平台人员审核课程,结果有两个:审核通过、审核不通过。

5、课程审核过后不管状态是通过还是不通过,教学机构可以再次修改课程并提交审核,此时课程状态为”已提交“。此时运营平台人员再次审核课程。

6、课程审核通过,教学机构人员可以发布课程,发布成功后课程的发布状态为”已发布“。

7、课程发布后通过”下架“操作可以更改课程发布状态为”下架“

8、课程下架后通过”上架“操作可以再次发布课程,上架后课程发布状态为“发布”。

2.2 数据模型

  • 课程提交审核后还允许修改课程吗

如果不允许修改是不合理的,因为提交审核后可以继续做下一个阶段的课程内容,比如添加课程计划,上传课程视频等。

如果允许修改那么课程审核时看到的课程内容从哪里来?如果也从课程基本信息表、课程营销表、课程计划表查询那么存在什么问题呢

运营人员审核课程和教学机构编辑课程操作的数据是同一份,此时会导致冲突。比如:运营人员正在审核时教学机构把数据修改了

image-20240114235145839

为了解决这个问题,专门设计课程预发布表

image-20240114235212529

提交课程审核,将课程信息汇总后写入课程预发布表,课程预发布表记录了教学机构在某个时间点要发布的课程信息。

课程审核人员从预发布表查询信息进行审核。

课程审核的同时可以对课程进行修改,修改的内容不会写入课程预发布表。

课程审核通过执行课程发布,将课程预发布表的信息写入课程发布表

相当于此时用户修改的内容和运营人员审核的内容给区分开了

  • 提交审核课程后,也修改了课程信息,可以再次提交审核吗

是可以的,只不过提交审核课程后,必须等到课程审核完成才可以再次提交课程

image-20240114235322689

  • 表结构

提交审核将信息写入课程预发布表,课程预发布表course_publish_pre结构如下

预发布表其实就是课程营销信息表、课程师资表、课程计划表、课程基本信息表的大综合

当预发布表的数据审核通过后,就会将预发布表的数据拷贝一份到发布表中,用户发布的内容其实就是发布表中的内容

image-20240114235421252

image-20240115000524773

更新课程基本信息表的课程审核状态为:已经提交

课程审核后更新课程基本信息表的审核状态、课程预发布表的审核状态,并将审核结果写入课程审核记录。

审核记录表结构如下

img

2.2.1 课程预发布表 course_publish_pre

@Data
@TableName("course_publish_pre")
public class CoursePublishPre implements Serializable {private static final long serialVersionUID = 1L;/*** 主键*/private Long id;/*** 机构ID*/private Long companyId;/*** 公司名称*/private String companyName;/*** 课程名称*/private String name;/*** 适用人群*/private String users;/*** 标签*/private String tags;/*** 创建人*/private String username;/*** 大分类*/private String mt;/*** 大分类名称*/private String mtName;/*** 小分类*/private String st;/*** 小分类名称*/private String stName;/*** 课程等级*/private String grade;/*** 教育模式*/private String teachmode;/*** 课程图片*/private String pic;/*** 课程介绍*/private String description;/*** 课程营销信息,json格式*/private String market;/*** 所有课程计划,json格式*/private String teachplan;/*** 教师信息,json格式*/private String teachers;/*** 提交时间*/@TableField(fill = FieldFill.INSERT)private LocalDateTime createDate;/*** 审核时间*/private LocalDateTime auditDate;/*** 状态*/private String status;/*** 备注*/private String remark;/*** 收费规则,对应数据字典--203*/private String charge;/*** 现价*/private Float price;/*** 原价*/private Float originalPrice;/*** 课程有效期天数*/private Integer validDays;}

2.3 CoursePublishController

1、查询课程基本信息、课程营销信息、课程计划信息等课程相关信息,整合为课程预发布信息。

2、向课程预发布表course_publish_pre插入一条记录,如果已经存在则更新,审核状态为:已提交。

3、更新课程基本表course_base课程审核状态为:已提交。

约束:

1、对已提交审核的课程不允许提交审核。

2、本机构只允许提交本机构的课程。

3、没有上传图片不允许提交审核。

4、没有添加课程计划不允许提交审核。

使用代码生成器生成课程发布表、课程预发布表的PO、Mpper,并拷贝到相应的工程下。

首先在content-api工程下添加如下接口

 @ResponseBody
@PostMapping ("/courseaudit/commit/{courseId}")
public void commitAudit(@PathVariable("courseId") Long courseId){Long companyId = 1232141425L;coursePublishService.commitAudit(companyId,courseId);}

2.4 CoursePublishServiceImpl

/*** @description 提交审核* @param courseId  课程id*/@Transactional@Overridepublic void commitAudit(Long companyId, Long courseId) {// 课程基本信息CourseBaseInfoDto courseBaseInfo = courseBaseInfoService.getCourseBaseInfo(courseId);if (courseBaseInfo == null) {XueChengPlusException.cast("课程找不到");}//得到审核状态String auditStatus  = courseBaseInfo.getAuditStatus();//TODO 如果课程的审核状态为已提交则不允许提交if ("202003".equals(auditStatus )) {XueChengPlusException.cast("课程已经提交申请,请您耐心等待审核");}//TODO 本机构只能提交本机构的课程//TODO 如果课程的图片、计划信息没有填写不允许提交if (StringUtils.isEmpty(courseBaseInfo.getPic())) {XueChengPlusException.cast("请上传课程图片");}//查询课程计划CoursePreviewDto coursePreviewInfo = coursePublishService.getCoursePreviewInfo(courseId);if (coursePreviewInfo == null || coursePreviewInfo.getTeachplans().size() == 0) {XueChengPlusException.cast("请上传课程计划");}//TODO 1.查询到课程基本信息、营销信息、计划等信息插入到课程预报布表CoursePublishPre coursePublishPre = new CoursePublishPre();//TODO 1.1课程基本信息加部分营销信息BeanUtils.copyProperties(courseBaseInfo,coursePublishPre);// 设置机构idcoursePublishPre.setCompanyId(companyId);//课程营销信息CourseMarket courseMarket = courseMarketMapper.selectById(courseId);//转为jsonString courseMarketJson = JSON.toJSONString(courseMarket);//将课程营销信息json数据放入课程预发布表coursePublishPre.setMarket(courseMarketJson);//TODO 1.2查询课程计划信息List<TeachplanDto> teachplanTree = teachplanService.findTeachplanTree(courseId);if(teachplanTree.size()<=0){XueChengPlusException.cast("提交失败,还没有添加课程计划");}//转jsonString teachplanTreeString = JSON.toJSONString(teachplanTree);coursePublishPre.setTeachplan(teachplanTreeString);//TODO 1.3设置预发布记录状态,已提交coursePublishPre.setStatus("202003");//教学机构idcoursePublishPre.setCompanyId(companyId);//提交时间coursePublishPre.setCreateDate(LocalDateTime.now());CoursePublishPre coursePublishPreUpdate = coursePublishPreMapper.selectById(courseId);if(coursePublishPreUpdate == null){//添加课程预发布记录coursePublishPreMapper.insert(coursePublishPre);}else{coursePublishPreMapper.updateById(coursePublishPre);}//TODO 2.更新课程基本信息表的审核状态为已提交CourseBase courseBase = courseBaseMapper.selectById(courseId);// 审核状态为已提交courseBase.setAuditStatus("202003");courseBaseMapper.updateById(courseBase);}

补充课程审核状态码

[{"code":"202001","desc":"审核未通过"},{"code":"202002","desc":"未提交"},{"code":"202003","desc":"已提交"},{"code":"202004","desc":"审核通过"}
]

课程发布状态

[{"code":"203001","desc":"未发布"},{"code":"203002","desc":"已发布"},{"code":"203003","desc":"下线"}
]

2.5 测试

首次提交审核

image-20240115004820948

image-20240115004839738

image-20240115010455885

因为我们没有做审核模块,所以我们直接修改数据库的数据即可,作为审核通过

1、修改课程预发布表的状态status字段为审核通过202004。

2、修改课程基本表的审核状态auditStatus字段为审核通过202004。

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

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

相关文章

紫光展锐T770安卓核心板_展锐T770 5G核心板规格参数

紫光展锐T770安卓核心板是一款高性能的5G安卓智能模块&#xff0c;拥有先进的6nm制程工艺和强大的性能。板载8GB Ram 256GBROM的内存单元&#xff0c;支持4K H.265/ H.264视频编解码&#xff0c;搭载Android 13以上操作系统&#xff0c;功能丰富。除了支持5G NSA和SA双模式向下…

我的NPI项目之设备系统启动(三) -- CDT的一个实例

上面说了这么多&#xff0c;这里就添加一个CDT的使用实例和简单的代码解析。 首先生成cdt_configure.xml配置文件&#xff0c;然后执行如下命令&#xff1a; python cdt_generator.py cdt_configure.xml CDT.bin; 就可以生成对应的CDT.bin文件。同时也会生成, 我们会利用ha…

『 C++ 』AVL树详解 ( 万字 )

&#x1f988;STL容器类型 在STL的容器中,分为几种容器: 序列式容器&#xff08;Sequence Containers&#xff09;: 这些容器以线性顺序存储元素&#xff0c;保留了元素的插入顺序。 支持随机访问&#xff0c;因此可以使用索引或迭代器快速访问任何位置的元素。 主要的序列式…

DBA技术栈(三):MySQL 性能影响因素

文章目录 前言一、影响MySQL性能的因素1.1 商业上的需求1.2 应用架构规划1.3 查询语句使用方式1.4 Schema的设计1.5 硬件环境 总结 前言 大部分人都一致认为一个数据库应用系统&#xff08;这里的数据库应用系统概指所有使用数据库的系统&#xff09;的性能瓶颈最容易出现在数…

MOSS 混元 巅峰对话!2024大模型发展都在这里

引言 2023 年&#xff0c;各大厂商争先投入 LLM 研发&#xff0c;一年内&#xff0c;在国内累计就有 200 余个大模型正式发布。尽管很多大模型并不完善&#xff0c;但行业内的研究专家及产业领袖都在为大模型的突破甚至 AGI 的发展&#xff0c;做着不懈探索。 但同时&#xff0…

基于Java (spring-boot)的停车场管理系统

一、项目介绍 基于Java (spring-boot)的停车场管理系统、预订车位系统、停车缴费系统功能&#xff1a; 登录、注册、后台首页、用户信息管理、车辆信息管理、新增车辆、车位费用设置、停泊车辆查询、车辆进出管理、登录日志查询、个人中心、预定停车位、缴费信息。 适用人群&…

Windows系统缺失api-ms-win-crt-runtime-l1-1-0.dll的修复方法

“在Windows操作系统环境下&#xff0c;用户经常遇到丢失api-ms-win-crt-runtime-l1-1-0.dll文件的问题&#xff0c;这一现象引发了广泛的关注与困扰。该dll文件作为Microsoft Visual C Redistributable Package的重要组成部分&#xff0c;对于系统内许多应用程序的正常运行起着…

C++ λ表达式

λ表达式提供了函数对象的另一种编程机制。 在 C 11 和更高版本中&#xff0c;Lambda 表达式&#xff08;通常称为 Lambda&#xff09;是一种在被调用的位置或作为参数传递给函数的位置定义匿名函数对象&#xff08;闭包&#xff09;的简便方法。 Lambda 通常用于封装传递给算法…

论文笔记(三十九)Learning Human-to-Robot Handovers from Point Clouds

Learning Human-to-Robot Handovers from Point Clouds 文章概括摘要1. 介绍2. 相关工作3. 背景3.1. 强化学习3.2. 移交模拟基准 4. 方法4.1. Handover Environment4.2. 感知4.3. 基于视觉的控制4.4. 师生两阶段培训 (Two-Stage Teacher-Student Training) 5. 实验5.1. 模拟评估…

CSS实现平行四边形

1、为什么实现平行四边形 在日常开发过程中&#xff0c;有些时候我们可以会遇到一种情况&#xff0c;如可视化大屏中要求我们横线实现对应的进度条&#xff0c;但进度条的内容是由无数个平行四边形组装类似于进度条的形式&#xff0c;那么我们就需要使用CSS来进行对应的实现。 …

OPT(erlang)打造一套缓存系统(一)

缓存的设计 这个简易缓存存储的是键/值对&#xff0c;其中键与键之间不得重复&#xff0c;并且每个键只能映射到一个值。这个设计背后的核心思想是为写人缓存的每一个值都分配一个独立的存储进程再将对应的键映射至该进程。你可能会对这种为每个值分配一个进程的设计感到惊讶&…

20240114-寻找零损失或一损失的玩家

题目要求 给定一个整数数组 matches&#xff0c;其中 matches[i] [winneri, Loseri] 表示玩家 Winneri 在一场比赛中击败了玩家 Loseri。 返回大小为 2 的列表答案&#xff0c;其中&#xff1a; answer[0] 是所有未输掉任何比赛的玩家的列表。answer[1] 是仅输掉一场比赛的…

京东年度数据报告-2023全年度笔记本十大热门品牌销量(销额)榜单

2023年度&#xff0c;在电脑办公市场整体销售下滑的环境下&#xff0c;笔记本市场的整体销售也不景气。 根据鲸参谋平台的数据显示&#xff0c;京东平台上笔记本的年度销量为650万&#xff0c;同比下滑约16%&#xff1b;销售额约为330亿&#xff0c;同比下滑约19%。同时&#…

71.网游逆向分析与插件开发-角色数据的获取-修复角色名与等级显示问题

内容参考于&#xff1a;易道云信息技术研究院VIP课 上一个内容&#xff1a;自动化助手UI显示角色数据-CSDN博客 码云地址&#xff08;ui显示角色数据 分支&#xff09;&#xff1a;https://gitee.com/dye_your_fingers/sro_-ex.git 码云版本号&#xff1a;0049452c079867779…

微软Office 2021 批量许可版

软件介绍 微软办公软件套件Microsoft Office LTSC 2021 专业增强版2024年1月批量许可版更新推送&#xff01;Office2021正式版和Windows11系统同时于2021年10月份正式推出&#xff0c;Office LTSC 2021相比 Office2019正式版变化不太&#xff0c;最主要强化了LOGO设计趋势&…

电商物流查询:未来的发展方向

在电商日益繁荣的时代&#xff0c;物流信息查询不仅关乎消费者体验&#xff0c;更影响着电商运营的效率。快速、准确地追踪物流信息至关重要。本文将简述物流信息快速追踪的价值&#xff0c;并重点介绍固乔快递查询助手这一高效查询工具及其批量查询功能。 一、物流信息快速追踪…

arcgis javascript api4.x加载天地图wgs84(wkid:4326)坐标系

需求&#xff1a; 使用arcgis javascript api4.x以basetilelayer方式加载天地图wgs84&#xff08;wkid&#xff1a;4326&#xff09;坐标系 效果&#xff1a; 代码&#xff1a; 提示&#xff1a;&#xff08;下述三个文件放同一个文件夹下&#xff09; 4326.js define([ex…

python毕设选题 - 基于时间序列的股票预测于分析

文章目录 1 简介2 时间序列的由来2.1 四种模型的名称&#xff1a; 3 数据预览4 理论公式4.1 协方差4.2 相关系数4.3 scikit-learn计算相关性 5 金融数据的时序分析5.1 数据概况5.2 序列变化情况计算 最后 1 简介 Hi&#xff0c;大家好&#xff0c;今天向大家介绍一个大数据项目…

QTday6作业

思维导图: widget.h #ifndef WIDGET_H #define WIDGET_H#include <QWidget> #include <QSqlDatabase>//数据库管理类 #include <QSqlQuery>//执行sql语句类 #include <QSqlRecord>//数据库记录类 #include <QSqlError>//数据库错误类 #include …

使用ChatGPT对进行论文改写与润色

一、内容改写 关键在于明确改写的具体要求。 例如:[论文内容] 可以指明需要提升该段落的流畅性和逻辑连贯性。 常用指令 细微调整文本 轻微编辑 重写以增强表述清晰度 简化句式 校正语法和拼写错误 提升文本的流畅性和条理性 优化词汇使用 调整文本风格 进行深度编辑…