diff --git a/pom.xml b/pom.xml
index 22d7b2f8..5a8dc60d 100644
--- a/pom.xml
+++ b/pom.xml
@@ -135,7 +135,11 @@
3.12.5
-
+
+ org.bytedeco
+ javacv-platform
+ 1.5.6
+
com.aliyun
@@ -187,7 +191,7 @@
aspose-words
aspose-words-22.10-jdk16
system
- ${project.basedir}/src/main/resources/lib/aspose-words-22.10-jdk16.jar
+ ${pom.basedir}/src/main/resources/lib/aspose-words-22.10-jdk16.jar
org.jsoup
@@ -483,6 +487,16 @@
true
+
+ central
+ https://maven.aliyun.com/repository/central
+
+ true
+
+
+ true
+
+
com.e-iceblue
https://repo.e-iceblue.cn/repository/maven-public/
diff --git a/src/main/java/com/peanut/common/service/AsyncService.java b/src/main/java/com/peanut/common/service/AsyncService.java
new file mode 100644
index 00000000..75754f6e
--- /dev/null
+++ b/src/main/java/com/peanut/common/service/AsyncService.java
@@ -0,0 +1,30 @@
+package com.peanut.common.service;
+
+import com.aliyun.vod20170321.models.GetVideoPlayAuthResponse;
+import com.peanut.common.utils.SpdbUtil;
+import com.peanut.modules.common.dao.CourseCatalogueChapterVideoDao;
+import com.peanut.modules.common.entity.CourseCatalogueChapterVideoEntity;
+import com.peanut.modules.common.entity.UserCourseVideoPositionEntity;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.scheduling.annotation.Async;
+import org.springframework.stereotype.Service;
+
+@Service
+public class AsyncService {
+ @Autowired
+ private CourseCatalogueChapterVideoDao courseCatalogueChapterVideoDao;
+
+ @Async
+ public void pushDurationToVideo(Integer videoId) throws Exception {
+ CourseCatalogueChapterVideoEntity courseCatalogueChapterVideoEntity = courseCatalogueChapterVideoDao.selectById(videoId);
+ if(courseCatalogueChapterVideoEntity.getType()==1){
+ GetVideoPlayAuthResponse p = SpdbUtil.getPlayAuth(courseCatalogueChapterVideoEntity.getVideo());
+ int i = p.getBody().getVideoMeta().getDuration().intValue();
+ courseCatalogueChapterVideoEntity.setDuration(i);
+ }else{
+ Integer mp4Duration = SpdbUtil.getMp4Duration("https://ehh-private-01.oss-cn-beijing.aliyuncs.com/video/taiHuClass/" + courseCatalogueChapterVideoEntity.getVideo());
+ courseCatalogueChapterVideoEntity.setDuration(mp4Duration);
+ }
+ courseCatalogueChapterVideoDao.updateById(courseCatalogueChapterVideoEntity);
+ }
+}
diff --git a/src/main/java/com/peanut/common/utils/SpdbUtil.java b/src/main/java/com/peanut/common/utils/SpdbUtil.java
index 7615fafd..1080f6bd 100644
--- a/src/main/java/com/peanut/common/utils/SpdbUtil.java
+++ b/src/main/java/com/peanut/common/utils/SpdbUtil.java
@@ -5,11 +5,25 @@ import com.aliyun.teautil.models.RuntimeOptions;
import com.aliyun.vod20170321.Client;
import com.aliyun.vod20170321.models.GetVideoPlayAuthRequest;
import com.aliyun.vod20170321.models.GetVideoPlayAuthResponse;
+import org.bytedeco.javacv.FFmpegFrameGrabber;
+import org.bytedeco.javacv.FrameGrabber;
import java.util.HashMap;
public class SpdbUtil {
+ public static Integer getMp4Duration(String url){
+ double duration = 0;
+ try (FFmpegFrameGrabber frameGrabber = new FFmpegFrameGrabber(url)) {
+ frameGrabber.start();
+ duration = frameGrabber.getLengthInTime()/1000000;
+ frameGrabber.stop();
+ } catch (FrameGrabber.Exception e) {
+ e.printStackTrace();
+ }
+ return (int)duration;
+ };
+
public static GetVideoPlayAuthResponse getPlayAuth(String vid) throws Exception {
com.aliyun.teaopenapi.models.Config config = new com.aliyun.teaopenapi.models.Config()
// 必填,请确保代码运行环境设置了环境变量 ALIBABA_CLOUD_ACCESS_KEY_ID。
diff --git a/src/main/java/com/peanut/config/AsyncConfig.java b/src/main/java/com/peanut/config/AsyncConfig.java
new file mode 100644
index 00000000..af100663
--- /dev/null
+++ b/src/main/java/com/peanut/config/AsyncConfig.java
@@ -0,0 +1,24 @@
+package com.peanut.config;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.scheduling.annotation.AsyncConfigurer;
+import org.springframework.scheduling.annotation.EnableAsync;
+import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
+
+import java.util.concurrent.Executor;
+
+@Configuration
+@EnableAsync
+public class AsyncConfig implements AsyncConfigurer {
+ @Override
+ @Bean
+ public Executor getAsyncExecutor() {
+ ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
+ executor.setCorePoolSize(5);
+ executor.setMaxPoolSize(10);
+ executor.setQueueCapacity(25);
+ executor.initialize();
+ return executor;
+ }
+}
diff --git a/src/main/java/com/peanut/modules/common/entity/CourseCatalogueChapterVideoEntity.java b/src/main/java/com/peanut/modules/common/entity/CourseCatalogueChapterVideoEntity.java
index c4253b43..4a4c1043 100644
--- a/src/main/java/com/peanut/modules/common/entity/CourseCatalogueChapterVideoEntity.java
+++ b/src/main/java/com/peanut/modules/common/entity/CourseCatalogueChapterVideoEntity.java
@@ -23,6 +23,8 @@ public class CourseCatalogueChapterVideoEntity {
private Integer sort;
+ private Integer duration;
+
private Date createTime;
@TableLogic
diff --git a/src/main/java/com/peanut/modules/common/entity/CourseCatalogueEntity.java b/src/main/java/com/peanut/modules/common/entity/CourseCatalogueEntity.java
index f27da71f..ffcf94ea 100644
--- a/src/main/java/com/peanut/modules/common/entity/CourseCatalogueEntity.java
+++ b/src/main/java/com/peanut/modules/common/entity/CourseCatalogueEntity.java
@@ -43,4 +43,9 @@ public class CourseCatalogueEntity{
*/
@TableField(exist = false)
private Integer isBuy;
+ /**
+ * 完成度百分比
+ */
+ @TableField(exist = false)
+ private int completion;
}
diff --git a/src/main/java/com/peanut/modules/common/entity/UserCourseVideoPositionEntity.java b/src/main/java/com/peanut/modules/common/entity/UserCourseVideoPositionEntity.java
index e35c3796..d37ebd27 100644
--- a/src/main/java/com/peanut/modules/common/entity/UserCourseVideoPositionEntity.java
+++ b/src/main/java/com/peanut/modules/common/entity/UserCourseVideoPositionEntity.java
@@ -20,8 +20,6 @@ public class UserCourseVideoPositionEntity {
private Integer position;
- private Integer duration;
-
private Date createTime;
@TableLogic
diff --git a/src/main/java/com/peanut/modules/master/service/impl/CourseCatalogueChapterVideoServiceImpl.java b/src/main/java/com/peanut/modules/master/service/impl/CourseCatalogueChapterVideoServiceImpl.java
index d68c29bc..ddd187d6 100644
--- a/src/main/java/com/peanut/modules/master/service/impl/CourseCatalogueChapterVideoServiceImpl.java
+++ b/src/main/java/com/peanut/modules/master/service/impl/CourseCatalogueChapterVideoServiceImpl.java
@@ -4,6 +4,7 @@ import com.aliyun.vod20170321.models.GetVideoPlayAuthResponse;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.peanut.common.service.AsyncService;
import com.peanut.common.utils.ShiroUtils;
import com.peanut.common.utils.SpdbUtil;
import com.peanut.modules.common.dao.*;
@@ -30,11 +31,13 @@ public class CourseCatalogueChapterVideoServiceImpl extends ServiceImpl wrapper = new LambdaQueryWrapper<>();
- wrapper.eq(CourseCatalogueChapterVideoEntity::getChapterId,param.getId());
+ wrapper.eq(CourseCatalogueChapterVideoEntity::getChapterId, param.getId());
wrapper.orderByAsc(CourseCatalogueChapterVideoEntity::getSort);
Page page = this.page(new Page<>(param.getPage(), param.getLimit()), wrapper);
return page;
@@ -42,17 +45,21 @@ public class CourseCatalogueChapterVideoServiceImpl extends ServiceImpl userToCourseEntities = userToCourseDao.selectList(new LambdaQueryWrapper().eq(UserToCourseEntity::getUserId, uId).eq(UserToCourseEntity::getCourseId, courseCatalogueEntity.getCourseId()));
//用户课程足迹
- if(userToCourseEntities.size()!=0){
+ if (userToCourseEntities.size() != 0) {
UserToCourseEntity userToCourseEntity = userToCourseEntities.get(0);
userToCourseEntity.setUpdateTime(new Date());
userToCourseDao.updateById(userToCourseEntity);
- }else{
+ } else {
UserToCourseEntity userToCourseEntity = new UserToCourseEntity();
userToCourseEntity.setUserId(uId);
userToCourseEntity.setCourseId(courseCatalogueEntity.getCourseId());
@@ -61,61 +68,45 @@ public class CourseCatalogueChapterVideoServiceImpl extends ServiceImpl wrapper = new LambdaQueryWrapper<>();
- wrapper.eq(UserCourseVideoPositionEntity::getUserId,uId);
- wrapper.eq(UserCourseVideoPositionEntity::getVideoId,videoId);
+ wrapper.eq(UserCourseVideoPositionEntity::getUserId, uId);
+ wrapper.eq(UserCourseVideoPositionEntity::getVideoId, videoId);
List userCourseVideoPositionEntities = userCourseVideoPositionDao.selectList(wrapper);
- if(userCourseVideoPositionEntities.size()==0){
+ if (userCourseVideoPositionEntities.size() == 0) {
UserCourseVideoPositionEntity userCourseVideoPositionEntity = new UserCourseVideoPositionEntity();
userCourseVideoPositionEntity.setUserId(uId);
userCourseVideoPositionEntity.setVideoId(videoId);
userCourseVideoPositionDao.insert(userCourseVideoPositionEntity);
- }else {
+ } else {
UserCourseVideoPositionEntity userCourseVideoPositionEntity = userCourseVideoPositionEntities.get(0);
userCourseVideoPositionEntity.setPosition(position);
userCourseVideoPositionDao.updateById(userCourseVideoPositionEntity);
}
}
- private UserCourseVideoPositionEntity getVideoPosition(CourseCatalogueChapterVideoEntity video, int userId, int duration){
+ private UserCourseVideoPositionEntity getVideoPosition(CourseCatalogueChapterVideoEntity video, int userId) {
List userCourseVideoPositionEntities = userCourseVideoPositionDao.selectList(new LambdaQueryWrapper().eq(UserCourseVideoPositionEntity::getUserId, userId).eq(UserCourseVideoPositionEntity::getVideoId, video.getId()));
- if(video.getType()==0){
- if(userCourseVideoPositionEntities.size()>0){
- return userCourseVideoPositionEntities.get(0);
- }else{
- UserCourseVideoPositionEntity userCourseVideoPositionEntity = new UserCourseVideoPositionEntity();
- userCourseVideoPositionEntity.setUserId(userId);
- userCourseVideoPositionEntity.setVideoId(video.getId());
- userCourseVideoPositionDao.insert(userCourseVideoPositionEntity);
- return userCourseVideoPositionEntity;
- }
- }else{//加密视频
- if(userCourseVideoPositionEntities.size()>0){
- return userCourseVideoPositionEntities.get(0);
- }else{
- UserCourseVideoPositionEntity userCourseVideoPositionEntity = new UserCourseVideoPositionEntity();
- userCourseVideoPositionEntity.setUserId(userId);
- userCourseVideoPositionEntity.setVideoId(video.getId());
- userCourseVideoPositionEntity.setDuration(duration);
- userCourseVideoPositionDao.insert(userCourseVideoPositionEntity);
- return userCourseVideoPositionEntity;
- }
+ if (userCourseVideoPositionEntities.size() > 0) {
+ return userCourseVideoPositionEntities.get(0);
+ } else {
+ UserCourseVideoPositionEntity userCourseVideoPositionEntity = new UserCourseVideoPositionEntity();
+ userCourseVideoPositionEntity.setUserId(userId);
+ userCourseVideoPositionEntity.setVideoId(video.getId());
+ userCourseVideoPositionEntity.setPosition(0);
+ userCourseVideoPositionDao.insert(userCourseVideoPositionEntity);
+ return userCourseVideoPositionEntity;
}
}
}
diff --git a/src/main/java/com/peanut/modules/sociology/controller/CourseController.java b/src/main/java/com/peanut/modules/sociology/controller/CourseController.java
index 80ac2126..8f812042 100644
--- a/src/main/java/com/peanut/modules/sociology/controller/CourseController.java
+++ b/src/main/java/com/peanut/modules/sociology/controller/CourseController.java
@@ -17,6 +17,8 @@ import com.peanut.modules.master.service.CourseCatalogueChapterVideoService;
import com.peanut.modules.sociology.service.CourseCatalogueChapterService;
import com.peanut.modules.sociology.service.CourseService;
import lombok.extern.slf4j.Slf4j;
+import org.bytedeco.javacv.FFmpegFrameGrabber;
+import org.bytedeco.javacv.FrameGrabber;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
@@ -112,12 +114,13 @@ public class CourseController {
return R.ok().put("playAuth",playAuth);
}
+ @RequestMapping("/saveCoursePosition")
public R saveCoursePosition(@RequestBody Map map){
Integer uId = ShiroUtils.getUId();
Integer videoId = map.get("videoId");
Integer position = map.get("position");
courseCatalogueChapterVideoService.saveCoursePosition(uId,videoId,position);
- return null;
+ return R.ok();
}
/**
* 验证video权限,并解决足迹,加密视频签名问题
diff --git a/src/main/java/com/peanut/modules/sociology/service/impl/CourseCatalogueChapterServiceImpl.java b/src/main/java/com/peanut/modules/sociology/service/impl/CourseCatalogueChapterServiceImpl.java
index 103827fa..ff94edf9 100644
--- a/src/main/java/com/peanut/modules/sociology/service/impl/CourseCatalogueChapterServiceImpl.java
+++ b/src/main/java/com/peanut/modules/sociology/service/impl/CourseCatalogueChapterServiceImpl.java
@@ -38,4 +38,6 @@ public class CourseCatalogueChapterServiceImpl extends ServiceImpl impl
private CourseCatalogueDao courseCatalogueDao;
@Autowired
private UserCourseBuyDao userCourseBuyDao;
+ @Autowired
+ private CourseCatalogueChapterDao courseCatalogueChapterDao;
+ @Autowired
+ private CourseCatalogueChapterVideoDao courseCatalogueChapterVideoDao;
+ @Autowired
+ private UserCourseVideoPositionDao userCourseVideoPositionDao;
//根据标签获取课程列表
@@ -77,15 +84,37 @@ public class CourseServiceImpl extends ServiceImpl impl
@Override
public Map getCourseDetail(Integer id) {
Map flag = new HashMap<>();
+ //基础信息
CourseEntity course = this.getById(id);
flag.put("course",course);
+ //目录信息
List courseCatalogueEntities = courseCatalogueDao.selectList(new LambdaQueryWrapper().eq(CourseCatalogueEntity::getCourseId, id));
Integer uId = ShiroUtils.getUId();
for (CourseCatalogueEntity c :courseCatalogueEntities){
Integer integer = userCourseBuyDao.selectCount(new LambdaQueryWrapper().eq(UserCourseBuyEntity::getUserId, uId).eq(UserCourseBuyEntity::getCatalogueId, c.getId()));
c.setIsBuy(integer>0?1:0);
+ c.setCompletion(catalogueCompletion(c));
}
flag.put("catalogues",courseCatalogueEntities);
return flag;
}
+
+ private Integer catalogueCompletion(CourseCatalogueEntity c){
+ List courseCatalogueChapterEntities = courseCatalogueChapterDao.selectList(new LambdaQueryWrapper().eq(CourseCatalogueChapterEntity::getCatalogueId, c.getId()));
+ Integer act = 0;
+ for (CourseCatalogueChapterEntity cc : courseCatalogueChapterEntities){
+ List courseCatalogueChapterVideoEntities = courseCatalogueChapterVideoDao.selectList(new LambdaQueryWrapper().eq(CourseCatalogueChapterVideoEntity::getChapterId, cc.getId()));
+ List collect = courseCatalogueChapterVideoEntities.stream().map(CourseCatalogueChapterVideoEntity::getId).collect(Collectors.toList());
+ if(collect.size()==0){
+ continue;
+ }
+ Integer integer = userCourseVideoPositionDao.selectCount(new LambdaQueryWrapper().eq(UserCourseVideoPositionEntity::getUserId, ShiroUtils.getUId()).in(UserCourseVideoPositionEntity::getVideoId, collect));
+ if (integer>0){
+ act++;
+ }
+ }
+ return courseCatalogueChapterEntities.size()==0?0:act * 100 / courseCatalogueChapterEntities.size();
+ }
+
+
}