|
@@ -854,7 +854,123 @@ public class FsCourseWatchLogServiceImpl extends ServiceImpl<FsCourseWatchLogMap
|
|
|
return fsCourseWatchLogMapper.getWatchLogByFsUser(videoId, fsUserId, companyUserId);
|
|
|
}
|
|
|
|
|
|
+ @Override
|
|
|
+ public void scheduleUpdateDurationToDatabase() {
|
|
|
+ log.info("开始更新会员看课时长,检查完课>>>>>>");
|
|
|
+ //读取所有的key
|
|
|
+ Collection<String> keys = redisCache.keys("h5wxuser:watch:duration::*");
|
|
|
+ //读取看课配置
|
|
|
+ String json = configService.selectConfigByKey("course.config");
|
|
|
+ CourseConfig config = JSONUtil.toBean(json, CourseConfig.class);
|
|
|
+
|
|
|
+ List<FsCourseWatchLog> logs = new ArrayList<>();
|
|
|
+ for (String key : keys) {
|
|
|
+ //取key中数据
|
|
|
+ String[] parts = key.split(":");
|
|
|
+ Long userId = Long.parseLong(parts[3]);
|
|
|
+ Long videoId = Long.parseLong(parts[4]);
|
|
|
+ Long companyUserId = Long.parseLong(parts[5]);
|
|
|
+ String durationStr = redisCache.getCacheObject(key);
|
|
|
+ if(durationStr==null){
|
|
|
+ log.error("key中数据为null:{}",key);
|
|
|
+ continue; // 如果 Redis 中没有记录,跳过
|
|
|
+ }
|
|
|
+ Long duration = Long.valueOf(durationStr);
|
|
|
+
|
|
|
+ FsCourseWatchLog watchLog = new FsCourseWatchLog();
|
|
|
+ watchLog.setVideoId(videoId);
|
|
|
+ watchLog.setUserId(userId);
|
|
|
+ watchLog.setCompanyUserId(companyUserId);
|
|
|
+ watchLog.setDuration(duration);
|
|
|
+
|
|
|
+ //取对应视频的时长
|
|
|
+ Long videoDuration = getVideoDuration(videoId);
|
|
|
+ if (videoDuration != null && videoDuration != 0) {
|
|
|
+ //判断是否完课
|
|
|
+ long percentage = (duration * 100 / videoDuration);
|
|
|
+ if (percentage >= config.getAnswerRate()) {
|
|
|
+ watchLog.setLogType(2); // 设置状态为“已完成”
|
|
|
+ watchLog.setFinishTime(new Date());
|
|
|
+ String heartbeatKey ="h5wxuser:watch:heartbeat:" + userId+ ":" + videoId + ":" + companyUserId;
|
|
|
+ // 完课删除心跳记录
|
|
|
+ redisCache.deleteObject(heartbeatKey);
|
|
|
+ // 完课删除看课时长记录
|
|
|
+ redisCache.deleteObject(key);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ //集合中增加
|
|
|
+ logs.add(watchLog);
|
|
|
+ }
|
|
|
+ batchUpdateFsUserCourseWatchLog(logs,100);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void checkFsUserWatchStatus() {
|
|
|
+ log.info("开始更新会员看课中断记录>>>>>");
|
|
|
+ // 从 Redis 中获取所有正在看课的用户记录
|
|
|
+ Collection<String> keys = redisCache.keys("h5wxuser:watch:heartbeat:*");
|
|
|
+ LocalDateTime now = LocalDateTime.now();
|
|
|
+ List<FsCourseWatchLog> logs = new ArrayList<>();
|
|
|
+ for (String key : keys) {
|
|
|
+ FsCourseWatchLog watchLog = new FsCourseWatchLog();
|
|
|
+ String[] parts = key.split(":");
|
|
|
+ Long userId = Long.parseLong(parts[3]);
|
|
|
+ Long videoId = Long.parseLong(parts[4]);
|
|
|
+ Long companyUserId = Long.parseLong(parts[5]);
|
|
|
+ // 获取最后心跳时间
|
|
|
+ String lastHeartbeatStr = redisCache.getCacheObject(key);
|
|
|
+ if (lastHeartbeatStr == null) {
|
|
|
+ continue; // 如果 Redis 中没有记录,跳过
|
|
|
+ }
|
|
|
+ LocalDateTime lastHeartbeatTime = LocalDateTime.parse(lastHeartbeatStr);
|
|
|
+ Duration duration = Duration.between(lastHeartbeatTime, now);
|
|
|
+
|
|
|
+ watchLog.setVideoId(videoId);
|
|
|
+ watchLog.setUserId(userId);
|
|
|
+ watchLog.setCompanyUserId(companyUserId);
|
|
|
+ // 如果超过一分钟没有心跳,标记为“观看中断”
|
|
|
+ if (duration.getSeconds() >= 60) {
|
|
|
+ watchLog.setLogType(4);
|
|
|
+ // 从 Redis 中删除该记录
|
|
|
+ redisCache.deleteObject(key);
|
|
|
+ }else {
|
|
|
+ watchLog.setLogType(1);
|
|
|
+ }
|
|
|
+ logs.add(watchLog);
|
|
|
+ }
|
|
|
+ batchUpdateFsUserCourseWatchLog(logs,100);
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
private void processDelCourseLogs(List<Long> logIds) {
|
|
|
|
|
|
}
|
|
|
+
|
|
|
+ public void batchUpdateFsUserCourseWatchLog(List<FsCourseWatchLog> logs, int batchSize) {
|
|
|
+ if (logs == null || logs.isEmpty()) {
|
|
|
+ log.info("待更新的日志列表为空,无需处理");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 记录总日志数量
|
|
|
+ log.info("开始批量更新日志,总日志数量: {}", logs.size());
|
|
|
+
|
|
|
+ // 分批处理
|
|
|
+ for (int i = 0; i < logs.size(); i += batchSize) {
|
|
|
+ int end = Math.min(i + batchSize, logs.size());
|
|
|
+ List<FsCourseWatchLog> batchList = logs.subList(i, end);
|
|
|
+
|
|
|
+ // 记录当前批次的数量
|
|
|
+ log.info("正在更新第 {} 批日志,数量: {}", (i / batchSize) + 1, batchList.size());
|
|
|
+
|
|
|
+ // 执行批量更新
|
|
|
+ fsCourseWatchLogMapper.batchUpdateFsUserWatchLog(batchList);
|
|
|
+
|
|
|
+ // 记录当前批次更新完成
|
|
|
+ log.info("第 {} 批日志更新完成,数量: {}", (i / batchSize) + 1, batchList.size());
|
|
|
+ }
|
|
|
+
|
|
|
+ // 记录全部更新完成
|
|
|
+ log.info("所有日志更新完成,总日志数量: {}", logs.size());
|
|
|
+ }
|
|
|
}
|