From d699da385dda6257677ee93bef47388c0635f64e Mon Sep 17 00:00:00 2001
From: “mitao” <“2763622819@qq.com”>
Date: 星期五, 17 四月 2026 08:57:41 +0800
Subject: [PATCH] feat:APP个人中心

---
 tcm-training-admin-backend/src/main/java/com/tcm/training/admin/live/service/LiveSessionStatusSyncService.java |   74 +++++++++++++++++++++++++++++++++++++
 1 files changed, 74 insertions(+), 0 deletions(-)

diff --git a/tcm-training-admin-backend/src/main/java/com/tcm/training/admin/live/service/LiveSessionStatusSyncService.java b/tcm-training-admin-backend/src/main/java/com/tcm/training/admin/live/service/LiveSessionStatusSyncService.java
index dfed6df..d322a1d 100644
--- a/tcm-training-admin-backend/src/main/java/com/tcm/training/admin/live/service/LiveSessionStatusSyncService.java
+++ b/tcm-training-admin-backend/src/main/java/com/tcm/training/admin/live/service/LiveSessionStatusSyncService.java
@@ -78,6 +78,18 @@
             return;
         }
 
+        int endedCount = autoEndExpiredLivingSessions(livingSessions, now);
+        if (endedCount > 0) {
+            livingSessions = liveSessionMapper.selectList(new LambdaQueryWrapper<LiveSession>()
+                    .eq(LiveSession::getDeleted, 0)
+                    .eq(LiveSession::getLiveStatus, 1)
+                    .orderByAsc(LiveSession::getLiveCourseId)
+                    .orderByAsc(LiveSession::getId));
+            if (livingSessions == null || livingSessions.isEmpty()) {
+                return;
+            }
+        }
+
         Set<Long> courseIds = new LinkedHashSet<Long>();
         for (LiveSession livingSession : livingSessions) {
             if (livingSession == null || livingSession.getLiveCourseId() == null) {
@@ -94,4 +106,66 @@
             log.info("live session reconcile finished, livingCourses={}, repaired={}", courseIds.size(), repairedCount);
         }
     }
+
+    /**
+     * 自动结束已超过配置时长的直播中场次。
+     */
+    private int autoEndExpiredLivingSessions(List<LiveSession> livingSessions, LocalDateTime now) {
+        if (livingSessions == null || livingSessions.isEmpty()) {
+            return 0;
+        }
+        int endedCount = 0;
+        int skippedCount = 0;
+        for (LiveSession livingSession : livingSessions) {
+            if (!shouldAutoEnd(livingSession, now)) {
+                if (livingSession == null
+                        || livingSession.getDurationSeconds() == null
+                        || livingSession.getDurationSeconds().intValue() <= 0
+                        || resolveSessionStartTime(livingSession) == null) {
+                    skippedCount++;
+                }
+                continue;
+            }
+            LiveSessionStatusVO statusVO = liveSessionAppService.autoEnd(livingSession.getId(), now);
+            if (statusVO != null) {
+                endedCount++;
+            }
+        }
+        if (endedCount > 0 || skippedCount > 0) {
+            log.info("live session auto end finished, scanned={}, ended={}, skipped={}",
+                    livingSessions.size(), endedCount, skippedCount);
+        }
+        return endedCount;
+    }
+
+    /**
+     * 判断直播中场次是否已到自动结束时间。
+     */
+    private boolean shouldAutoEnd(LiveSession session, LocalDateTime now) {
+        if (session == null) {
+            return false;
+        }
+        Integer durationSeconds = session.getDurationSeconds();
+        if (durationSeconds == null || durationSeconds.intValue() <= 0) {
+            return false;
+        }
+        LocalDateTime startTime = resolveSessionStartTime(session);
+        if (startTime == null) {
+            return false;
+        }
+        return !startTime.plusSeconds(durationSeconds.longValue()).isAfter(now);
+    }
+
+    /**
+     * 优先使用实际开播时间,没有时回退到计划开播时间。
+     */
+    private LocalDateTime resolveSessionStartTime(LiveSession session) {
+        if (session == null) {
+            return null;
+        }
+        if (session.getActualStartTime() != null) {
+            return session.getActualStartTime();
+        }
+        return session.getStartTime();
+    }
 }

--
Gitblit v1.7.1