|
|
@@ -36,7 +36,9 @@ import javax.websocket.*;
|
|
|
import javax.websocket.server.ServerEndpoint;
|
|
|
import java.io.EOFException;
|
|
|
import java.io.IOException;
|
|
|
+import java.time.LocalDate;
|
|
|
import java.time.LocalDateTime;
|
|
|
+import java.time.ZoneId;
|
|
|
import java.util.*;
|
|
|
import java.util.concurrent.*;
|
|
|
import java.util.concurrent.locks.Lock;
|
|
|
@@ -246,6 +248,9 @@ public class WebSocketServer {
|
|
|
}
|
|
|
redisCache.setCacheObject( "live:user:first:entry:" + liveId + ":" + userId, liveUserFirstEntry,1, TimeUnit.HOURS);
|
|
|
|
|
|
+ // 推送完课积分倒计时配置信息给前端
|
|
|
+ sendCompletionPointsConfigToUser(session, liveId, userId, live);
|
|
|
+
|
|
|
|
|
|
} else {
|
|
|
adminRoom.add(session);
|
|
|
@@ -1392,5 +1397,95 @@ public class WebSocketServer {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * 向用户推送完课积分倒计时配置信息
|
|
|
+ * 在用户连接WebSocket时调用,让前端能够显示倒计时
|
|
|
+ * @param session WebSocket会话
|
|
|
+ * @param liveId 直播间ID
|
|
|
+ * @param userId 用户ID
|
|
|
+ * @param live 直播信息
|
|
|
+ */
|
|
|
+ private void sendCompletionPointsConfigToUser(Session session, Long liveId, Long userId, Live live) {
|
|
|
+ try {
|
|
|
+
|
|
|
+ boolean isLiveStarted = false;
|
|
|
+ if (live.getStatus() != null && live.getStatus() == 2) {
|
|
|
+ isLiveStarted = true;
|
|
|
+ } else if (live.getStartTime() != null) {
|
|
|
+ LocalDateTime now = LocalDateTime.now();
|
|
|
+ isLiveStarted = now.isAfter(live.getStartTime()) || now.isEqual(live.getStartTime());
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!isLiveStarted) {
|
|
|
+ // 直播未开始,不推送完课配置
|
|
|
+ log.debug("[完课配置推送] 直播未开始,跳过推送, liveId={}, userId={}", liveId, userId);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ String configJson = live.getConfigJson();
|
|
|
+ if (configJson == null || configJson.isEmpty()) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ JSONObject jsonConfig = JSON.parseObject(configJson);
|
|
|
+ boolean enabled = jsonConfig.getBooleanValue("enabled");
|
|
|
+ if (!enabled) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ Integer completionRate = jsonConfig.getInteger("completionRate");
|
|
|
+ if (completionRate == null || completionRate <= 0 || completionRate > 100) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 3. 计算完课所需观看时长
|
|
|
+ Long videoDuration = live.getDuration();
|
|
|
+ if (videoDuration == null || videoDuration <= 0) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 完课所需时长(秒) = 视频总时长 × 完课比例 / 100
|
|
|
+ long requiredDuration = (long) Math.ceil(videoDuration * completionRate / 100.0);
|
|
|
+
|
|
|
+ // 4. 获取用户当前观看时长
|
|
|
+ String hashKey = "live:watch:duration:hash:" + liveId;
|
|
|
+ String userIdField = String.valueOf(userId);
|
|
|
+ Object existingDuration = redisCache.hashGet(hashKey, userIdField);
|
|
|
+ long currentDuration = existingDuration != null ? Long.parseLong(existingDuration.toString()) : 0L;
|
|
|
+
|
|
|
+ // 5. 检查今天是否已有完课记录
|
|
|
+ LocalDate today = LocalDate.now();
|
|
|
+ Date currentDate = Date.from(today.atStartOfDay(ZoneId.systemDefault()).toInstant());
|
|
|
+ LiveCompletionPointsRecord todayRecord = completionPointsRecordService.selectByUserAndDate(liveId, userId, currentDate);
|
|
|
+
|
|
|
+ boolean hasCompletedToday = (todayRecord != null);
|
|
|
+
|
|
|
+ // 6. 构建配置信息
|
|
|
+ JSONObject configData = new JSONObject();
|
|
|
+ configData.put("videoDuration", videoDuration); // 视频总时长(秒)
|
|
|
+ configData.put("completionRate", completionRate); // 完课比例(%)
|
|
|
+ configData.put("requiredDuration", requiredDuration); // 完课所需时长(秒)
|
|
|
+ configData.put("currentDuration", currentDuration); // 当前观看时长(秒)
|
|
|
+ configData.put("remainingDuration", Math.max(0, requiredDuration - currentDuration)); // 剩余时长(秒)
|
|
|
+ configData.put("hasCompletedToday", hasCompletedToday); // 今天是否已完课
|
|
|
+
|
|
|
+ // 7. 推送配置消息
|
|
|
+ SendMsgVo sendMsgVo = new SendMsgVo();
|
|
|
+ sendMsgVo.setLiveId(liveId);
|
|
|
+ sendMsgVo.setUserId(userId);
|
|
|
+ sendMsgVo.setCmd("completionPointsConfig");
|
|
|
+ sendMsgVo.setMsg("完课积分配置");
|
|
|
+ sendMsgVo.setData(configData.toJSONString());
|
|
|
+
|
|
|
+ sendMessage(session, JSONObject.toJSONString(R.ok().put("data", sendMsgVo)));
|
|
|
+
|
|
|
+ log.debug("[完课配置推送] 推送成功, liveId={}, userId={}, 所需时长={}秒, 当前时长={}秒, 剩余={}秒",
|
|
|
+ liveId, userId, requiredDuration, currentDuration, Math.max(0, requiredDuration - currentDuration));
|
|
|
+
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("[完课配置推送] 推送失败, liveId={}, userId={}", liveId, userId, e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
}
|
|
|
|