学成在线笔记十一:媒资管理系统集成
媒资管理系统集成

学习页面查询课程计划

后端开发

修改xc-service-searcj服务中的代码

API定义

1
2
@ApiOperation("根据id查询课程信息")
Map<String, EsCoursePub> getAll(String id);

EsCourseController

1
2
3
4
5
@Override
@GetMapping("getall/{id}")
public Map<String, EsCoursePub> getAll(@PathVariable String id) {
return esCourseService.getAll(id);
}

EsCourseService

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
/**
* 查询课程信息
*
* @param id 课程id
* @return Map<String, EsCoursePub>
*/
public Map<String, EsCoursePub> getAll(String id) {
Map<String, EsCoursePub> result = new HashMap<>();
NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder();

// 查询条件
nativeSearchQueryBuilder.withQuery(QueryBuilders.termQuery("id", id));

AggregatedPage<EsCoursePub> queryForPage = elasticsearchTemplate.queryForPage(nativeSearchQueryBuilder.build(), EsCoursePub.class);
queryForPage.getContent().forEach(coursePub -> result.put(coursePub.getId(), coursePub));

return result;
}

测试

前端开发

learning_video.vue

主要修改learning_video.vue文件中的create()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
created(){
//当前请求的url
this.url = window.location
//课程id
this.courseId = this.$route.params.courseId
//章节id
this.chapter = this.$route.params.chapter
//取出课程Id
systemApi.course_view(this.courseId).then((view_course)=>{
console.log(view_course)
if(!view_course || !view_course[this.courseId]){
this.$message.error("获取课程信息失败,请重新进入此页面!")
return ;
}

let courseInfo = view_course[this.courseId]
console.log(courseInfo)
this.coursename = courseInfo.name
if(courseInfo.teachplan){
let teachplan = JSON.parse(courseInfo.teachplan);
this.teachplanList = teachplan.children;

}
})

}

Nginx配置文件

截至目前为止,nginx配置文件如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
#user  nobody;
worker_processes 1;

#error_log logs/error.log;
#error_log logs/error.log notice;
#error_log logs/error.log info;

#pid logs/nginx.pid;


events {
worker_connections 1024;
}


http {
include mime.types;
default_type application/octet-stream;

#log_format main '$remote_addr - $remote_user [$time_local] "$request" '
# '$status $body_bytes_sent "$http_referer" '
# '"$http_user_agent" "$http_x_forwarded_for"';

#access_log logs/access.log main;

sendfile on;
#tcp_nopush on;

#keepalive_timeout 0;
keepalive_timeout 65;

#gzip on;


# cms页面预览
upstream cms_server_pool{
server 127.0.0.1:31001 weight=10;
}

# 静态资源服务
upstream static_server_pool{
server 127.0.0.1:91 weight=10;
}

# 前端动态门户
upstream dynamic_portal_server_pool{
server 127.0.0.1:10000 weight=10;
}

# 搜索接口
upstream search_server_pool{
server 127.0.0.1:40100 weight=10;
}


#媒体服务
upstream video_server_pool{
server 127.0.0.1:90 weight=10;
}


server{
listen 80;
server_name www.xuecheng.com;
ssi on;
ssi_silent_errors on;
location / {
alias F:/xcEdu/xcEdu_ui/xc-ui-pc-static-portal/;
index index.html;
}

# 静态资源,包括系统所需要的图片,js、css等静态资源
location /static/img/ {
alias F:/xcEdu/xcEdu_ui/xc-ui-pc-static-portal/img/;
}
location /static/css/ {
alias F:/xcEdu/xcEdu_ui/xc-ui-pc-static-portal/css/;
}
location /static/js/ {
alias F:/xcEdu/xcEdu_ui/xc-ui-pc-static-portal/js/;
}
location /static/plugins/ {
alias F:/xcEdu/xcEdu_ui/xc-ui-pc-static-portal/plugins/;
add_header Access-Control-Allow-Origin *;
add_header Access-Control-Allow-Credentials true;
add_header Access-Control-Allow-Methods GET;
}
location /plugins/ {
alias F:/xcEdu/xcEdu_ui/xc-ui-pc-static-portal/plugins/;
add_header Access-Control-Allow-Origin *;
add_header Access-Control-Allow-Credentials true;
add_header Access-Control-Allow-Methods GET;
}


# 页面预览
location /cms/preview/ {
proxy_pass http://cms_server_pool/cms/preview/;
}
location /static/company/ {
proxy_pass http://static_server_pool;
}
location /static/teacher/ {
proxy_pass http://static_server_pool;
}
location /static/stat/ {
proxy_pass http://static_server_pool;
}
location /course/detail/ {
proxy_pass http://static_server_pool;
}

# 前端门户课程搜索
location ^~ /course/search {
proxy_pass http://dynamic_portal_server_pool;
}
# 后端搜索服务
location /openapi/search/ {
proxy_pass http://search_server_pool/search/;
}
# 分类信息
location /static/category/ {
proxy_pass http://static_server_pool;
}
# 开发环境Webpack定时加载文件
location ^~ /__webpack_hmr {
proxy_pass http://dynamic_portal_server_pool/__webpack_hmr;
}
# 开发环境nuxt访问
location ^~ /_nuxt/ {
proxy_pass http://dynamic_portal_server_pool/_nuxt/;
}

}

#学成网媒体服务代理
map $http_origin $origin_list{
default http://www.xuecheng.com;
"~http://www.xuecheng.com" http://www.xuecheng.com;
"~http://ucenter.xuecheng.com" http://ucenter.xuecheng.com;
}

#学成网媒体服务代理
server {
listen 80;
server_name video.xuecheng.com;

location /video {
proxy_pass http://video_server_pool;
add_header Access-Control-Allow-Origin $origin_list;
#add_header Access-Control-Allow-Origin *;
add_header Access-Control-Allow-Credentials true;
add_header Access-Control-Allow-Methods GET;
}

}

#学成网用户中心
server {
listen 80;
server_name ucenter.xuecheng.com;

#个人中心
location / {
proxy_pass http://ucenter_server_pool;
}

# 后端搜索服务
location /openapi/search/ {
proxy_pass http://search_server_pool/search/;
}
}

#前端ucenter
upstream ucenter_server_pool{
server 127.0.0.1:13000 weight=10;
}



# 学成网静态资源
server {
listen 91;
server_name localhost;

# 公司信息
location /static/company/ {
alias F:/xcEdu/xcEdu_ui/static/company/;
}
# 老师信息
location /static/teacher/ {
alias F:/xcEdu/xcEdu_ui/static/teacher/;
}
# 统计信息
location /static/stat/ {
alias F:/xcEdu/xcEdu_ui/static/stat/;
}
# 课程静态页
location /course/detail/ {
alias F:/xcEdu/xcEdu_ui/static/course/detail/;
}
# 分类信息
location /static/category/ {
alias F:/xcEdu/xcEdu_ui/static/category/;
}
}


#学成网媒体服务
server {
listen 90;
server_name localhost;

#视频目录
location /video/ {
alias E:/nginx/xcEdu/video/;
}
}



# another virtual host using mix of IP-, name-, and port-based configuration
#
#server {
# listen 8000;
# listen somename:8080;
# server_name somename alias another.alias;

# location / {
# root html;
# index index.html index.htm;
# }
#}


# HTTPS server
#
#server {
# listen 443 ssl;
# server_name localhost;

# ssl_certificate cert.pem;
# ssl_certificate_key cert.key;

# ssl_session_cache shared:SSL:1m;
# ssl_session_timeout 5m;

# ssl_ciphers HIGH:!aNULL:!MD5;
# ssl_prefer_server_ciphers on;

# location / {
# root html;
# index index.html index.htm;
# }
#}

}

测试

课程计划展示成功。

学习页面获取视频播放地址

需求分析

在线学习视频播放流程图如下:

  1. 用户进入在线学习页面,页面请求搜索服务获取课程信息(包括课程计划信息)并且在页面展示。
  2. 在线学习请求学习服务获取视频播放地址。
  3. 学习服务校验当前用户是否有权限学习,如果没有权限学习则提示用户。
  4. 学习服务校验通过,请求搜索服务获取课程媒资信息。
  5. 搜索服务请求ElasticSearch获取课程媒资信息。

保存课程媒资数据

实体类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
package com.xuecheng.framework.domain.course;

import lombok.Data;
import lombok.ToString;
import org.hibernate.annotations.GenericGenerator;

import javax.persistence.*;
import java.io.Serializable;
import java.util.Date;

@Data
@ToString
@Entity
@Table(name = "teachplan_media_pub")
@GenericGenerator(name = "jpa‐assigned", strategy = "assigned")
public class TeachplanMediaPub implements Serializable {

private static final long serialVersionUID = -916357110051689485L;

@Id
@GeneratedValue(generator = "jpa‐assigned")
@Column(name = "teachplan_id")
private String teachplanId;

@Column(name = "media_id")
private String mediaId;

@Column(name = "media_fileoriginalname")
private String mediaFileOriginalName;

@Column(name = "media_url")
private String mediaUrl;

@Column(name = "courseid")
private String courseId;

@Column(name = "timestamp")
private Date timestamp;//时间戳

}

Dao修改

  • TeachplanMediaPubRepository

    1
    2
    3
    4
    5
    6
    7
    8
    9
    package com.xuecheng.manage_course.dao;

    import com.xuecheng.framework.domain.course.TeachplanMediaPub;
    import org.springframework.data.jpa.repository.JpaRepository;

    public interface TeachplanMediaPubRepository extends JpaRepository<TeachplanMediaPub, String> {
    //根据课程id删除课程计划媒资信息
    long deleteByCourseId(String courseId);
    }
  • TeachplanMediaRepository新增方法

    1
    List<TeachplanMedia> findByCourseId(String courseId);

CourseService

新增保存课程媒资方法并在发布课程时调用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
   @Autowired
private TeachplanMediaPubRepository teachplanMediaPubRepository;

/**
* 保存指定课程的课程计划媒资信息到索引表中
*
* @param id 课程ID
*/
private void saveTeachplanMediaPub(String id) {
// 查询课程媒资信息
List<TeachplanMedia> teachplanMediaList = teachplanMediaRepository.findByCourseId(id);

// 删除原有数据
teachplanMediaPubRepository.deleteByCourseId(id);

// 将课程计划媒资信息存储待索引表
List<TeachplanMediaPub> teachplanMediaPubList = new ArrayList<>();
teachplanMediaList.forEach(teachplanMedia -> {
TeachplanMediaPub teachplanMediaPub = new TeachplanMediaPub();
BeanUtils.copyProperties(teachplanMedia, teachplanMediaPub);
teachplanMediaPubList.add(teachplanMediaPub);
});

teachplanMediaPubRepository.saveAll(teachplanMediaPubList);
}

Logstash导入数据到索引库

创建索引

1
2
3
4
5
6
7
PUT xc_course_media/doc/_mapping
{
"settings": {
"number_of_shards": 1,
"number_of_replicas": 0
}
}

创建映射

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
POST xc_course_media/doc/_mapping
{
"properties": {
"courseid": {
"type": "keyword"
},
"teachplan_id": {
"type": "keyword"
},
"media_id": {
"type": "keyword"
},
"media_url": {
"index": false,
"type": "text"
},
"media_fileoriginalname": {
"index": false,
"type": "text"
}
}
}

创建模板文件

创建xc_course_media_template.json文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
{
"mappings": {
"doc": {
"properties": {
"courseid": {
"type": "keyword"
},
"teachplan_id": {
"type": "keyword"
},
"media_id": {
"type": "keyword"
},
"media_url": {
"index": false,
"type": "text"
},
"media_fileoriginalname": {
"index": false,
"type": "text"
}
}
},
"template": "xc_course_media"
}
}

Logstash数据导入脚本

与课程发布信息导入类似,只是执行的sql脚本不同和导入的映射不同

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
input {
stdin {
}
jdbc {
jdbc_connection_string => "jdbc:mysql://192.168.136.110:3306/xc_course?useUnicode=true&characterEncoding=utf-8&useSSL=true&serverTimezone=UTC"
# the user we wish to excute our statement as
jdbc_user => "root"
jdbc_password => "123456"
# the path to our downloaded jdbc driver
jdbc_driver_library => "/usr/share/logstash/config/mysql-connector-java-8.0.13.jar"
# the name of the driver class for mysql
jdbc_driver_class => "com.mysql.cj.jdbc.Driver"
jdbc_paging_enabled => "true"
jdbc_page_size => "50000"
#要执行的sql文件
#statement_filepath => "/conf/course.sql"
statement => "select * from teachplan_media_pub where timestamp > date_add(:sql_last_value,INTERVAL 8 HOUR)"
#定时配置
schedule => "* * * * *"
record_last_run => true
last_run_metadata_path => "/usr/share/logstash/config/logstash_metadata"
}
}

filter{
json{
source => "message"
remove_field => ["message"]
}
}


output {
elasticsearch {
#ES的ip地址和端口
hosts => "192.168.136.110:9200"
#hosts => ["localhost:9200","localhost:9202","localhost:9203"]
#ES索引库名称
index => "xc_course_media"
document_id => "%{courseid}"
document_type => "doc"
template => "/usr/share/logstash/config/xc_course_media_template.json"
template_name => "xc_course_media"
template_overwrite => "true"
}
stdout {
#日志输出
codec => json_lines
}
}

查看导入数据

课程媒资接口

xc-service-search中添加相关代码

ES实体类定义

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
package com.xuecheng.framework.domain.search;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.data.annotation.Id;
import org.springframework.data.elasticsearch.annotations.Document;
import org.springframework.data.elasticsearch.annotations.Field;

@Data
@AllArgsConstructor
@NoArgsConstructor
@Document(indexName = "xc_course_media", type = "doc", shards = 1)
public class EsTeachplanMediaPub {

@Id
private String courseid;

@Field
private String media_fileoriginalname;
@Field
private String media_id;
@Field
private String media_url;
@Field
private String teachplan_id;

}

appliction.yml

新增配置

1
2
3
elasticsearch:
es_course_source_field: id,name,grade,mt,st,charge,valid,pic,qq,price,price_old,status,studymodel,teachmode,expires,pub_time,start_time,end_time
es_course_media_source_field: courseid,media_id,media_url,teachplan_id,media_fileoriginalname

配置类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package com.xuecheng.search.config;

import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

@Data
@Component
@ConfigurationProperties(prefix = "elasticsearch")
public class ElasticsearchConfig {

private String esCourseSourceField;

private String esCourseMediaSourceField;
}

API定义

1
2
@ApiOperation("根据课程计划查询媒资信息")
EsTeachplanMediaPub getMedia(String teachplanId);

EsCourseController

1
2
3
4
5
6
7
8
9
10
@Override
@GetMapping("getmedia/{teachplanId}")
public EsTeachplanMediaPub getMedia(@PathVariable String teachplanId) {
//将课程计划id放在数组中,为调用service作准备
String[] teachplanIds = new String[]{teachplanId};
//通过service查询ES获取课程媒资信息
List<EsTeachplanMediaPub> esTeachplanMediaPubList = esCourseService.getMedia(teachplanIds);

return esTeachplanMediaPubList.isEmpty() ? null : esTeachplanMediaPubList.get(0);
}

EsCourseService

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/**
* 查询课程媒资信息
*
* @param teachplanIds 课程计划ID
*/
public List<EsTeachplanMediaPub> getMedia(String[] teachplanIds) {
NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder();

// 结果过滤
nativeSearchQueryBuilder.withSourceFilter(
new FetchSourceFilter(elasticsearchConfig.getEsCourseMediaSourceField().split(","), null));

// 查询条件
nativeSearchQueryBuilder.withQuery(QueryBuilders.termQuery("teachplan_id", Arrays.stream(teachplanIds).reduce((a, b) -> a + "," +b).get()));

return elasticsearchTemplate.queryForList(nativeSearchQueryBuilder.build(), EsTeachplanMediaPub.class);
}

在线学习

微服务项目导入(省略)

OPEN API

开放搜索微服务的API,修改搜索微服务相关代码

引入eureka依赖

1
2
3
4
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>

application.yml配置

新增eureka配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
eureka:
client:
registerWithEureka: true #服务注册开关
fetchRegistry: true #服务发现开关
serviceUrl: #Eureka客户端与Eureka服务端进行交互的地址,多个中间用逗号分隔
defaultZone: ${EUREKA_SERVER:http://localhost:50101/eureka/,http://localhost:50102/eureka/}
instance:
prefer-ip-address: true #将自己的ip地址注册到Eureka服务中
ip-address: ${IP_ADDRESS:127.0.0.1}
instance-id: ${spring.application.name}:${server.port} #指定实例id
ribbon:
MaxAutoRetries: 2 #最大重试次数,当Eureka中可以找到服务,但是服务连不上时将会重试,如果eureka中找不到服务则直接走断路器
MaxAutoRetriesNextServer: 3 #切换实例的重试次数
OkToRetryOnAllOperations: false #对所有操作请求都进行重试,如果是get则可以,如果是post,put等操作没有实现幂等的情况下是很危险的,所以设置为false
ConnectTimeout: 5000 #请求连接的超时时间
ReadTimeout: 6000 #请求处理的超时时间

启动类

在启动类上添加@EnableDiscoveryClient

编写Api Client

在学习微服务中编写Feign Client

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package com.xuecheng.learning.client;

import com.xuecheng.framework.client.XcServiceList;
import com.xuecheng.framework.domain.search.EsTeachplanMediaPub;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;

@FeignClient(value = XcServiceList.XC_SERVICE_SEARCH)
public interface CourseSearchClient {

@GetMapping(value = "search/course/getmedia/{teachplanId}")
EsTeachplanMediaPub getMedia(@PathVariable("teachplanId") String teachplanId);

}

在线学习接口后端

返回结果实体类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package com.xuecheng.framework.domain.learning.response;

import com.xuecheng.framework.model.response.ResponseResult;
import com.xuecheng.framework.model.response.ResultCode;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;

@Data
@ToString
@NoArgsConstructor
public class GetMediaResult extends ResponseResult {

public GetMediaResult(ResultCode resultCode, String fileUrl) {
super(resultCode);
this.fileUrl = fileUrl;
}

//媒资文件播放地址
private String fileUrl;
}

API定义

1
2
3
4
5
6
7
8
9
10
11
12
13
package com.xuecheng.api.learning;

import com.xuecheng.framework.domain.learning.response.GetMediaResult;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;

@Api(value = "录播课程学习管理", description = "录播课程学习管理")
public interface CourseLearningControllerApi {

@ApiOperation("获取课程学习地址")
GetMediaResult getMedia(String courseId, String teachplanId);

}

CourseLearningController

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package com.xuecheng.learning.controller;

import com.xuecheng.api.learning.CourseLearningControllerApi;
import com.xuecheng.framework.domain.learning.response.GetMediaResult;
import com.xuecheng.learning.service.LearningService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("learning")
public class CourseLearningController implements CourseLearningControllerApi {
@Autowired
LearningService learningService;

@Override
@GetMapping("getmedia/{courseId}/{teachplanId}")
public GetMediaResult getMedia(@PathVariable String courseId, @PathVariable String teachplanId) {
//获取课程学习地址
return learningService.getMedia(courseId, teachplanId);
}
}

CourseLearningService

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
package com.xuecheng.learning.service;

import com.xuecheng.framework.domain.learning.response.GetMediaResult;
import com.xuecheng.framework.domain.learning.response.LearningCode;
import com.xuecheng.framework.domain.search.EsTeachplanMediaPub;
import com.xuecheng.framework.exception.ExceptionCast;
import com.xuecheng.framework.model.response.CommonCode;
import com.xuecheng.learning.client.CourseSearchClient;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class LearningService {

@Autowired
CourseSearchClient courseSearchClient;

/**
* 获取课程视频信息
*
* @param courseId 课程ID
* @param teachplanId 课程计划ID
* @return GetMediaResult
*/
public GetMediaResult getMedia(String courseId, String teachplanId) {

// TODO 校验学生的学习权限, 是否资费

// 调用搜索服务查询
EsTeachplanMediaPub teachplanMediaPub = courseSearchClient.getMedia(teachplanId);
if (teachplanMediaPub == null || StringUtils.isEmpty(teachplanMediaPub.getMedia_url())) {
//获取视频播放地址出错
ExceptionCast.cast(LearningCode.LEARNING_GETMEDIA_ERROR);
}
return new GetMediaResult(CommonCode.SUCCESS, teachplanMediaPub.getMedia_url());
}
}

在线学习接口前端

learning_video.vue

  • methods中新增方法

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    getFirstTeachplan(){ 
    for(var i=0;i<this.teachplanList.length;i++) {
    let firstTeachplan = this.teachplanList[i];
    if(firstTeachplan.children && firstTeachplan.children.length>0){
    let secondTeachplan = firstTeachplan.children[0]
    return secondTeachplan.id
    }
    }
    return ;
    },
    //开始学习
    study(chapter){
    // 获取播放地址
    courseApi.get_media(this.courseId,chapter).then((res)=>{
    if(res.success){
    let fileUrl = sysConfig.videoUrl + res.fileUrl
    //播放视频
    this.playvideo(fileUrl)
    } else if(res.message) {
    this.$message.error(res.message)
    } else {
    this.$message.error("播放视频失败,请刷新页面重试")
    }
    }).catch(res => {
    this.$message.error("播放视频失败,请刷新页面重试")
    });
    }
  • 修改created中拿到课程ID后回调逻辑

    1
    2
    3
    4
    5
    6
    7
    if(!this.chapter || this.chapter == '0'){ 
    //取出第一个教学计划
    this.chapter = this.getFirstTeachplan()
    console.log(this.chapter)
    }
    //开始学习
    this.study(this.chapter)

测试

成功点播视频。

代码获取

代码获取

写在这里

学成在线去年年底就开始在做了,后面因为一些原因(因为懒……),停止在了这个阶段,后面还剩下:

  • 16- Spring Security Oauth2

  • 17- 用户认证 Zuul

  • 18-用户授权

  • 19-分布式事务

  • 20-Devops 项目总结

现在捡起来继续做,先把之前写好的笔记发出来(再不发灰都要堆成山了)。

等把这个做完,准备开始搞搞更深层次的东西了,老实讲,应用层面的东西更多的是在业务,对实际工作中的架构和设计帮助甚少。

愿与你共勉!!!!!

文章作者: imxushuai
文章链接: https://www.imxushuai.com/2020/06/10/29.学成在线笔记十一:媒资管理系统集成/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 imxushuai
支付宝打赏
微信打赏