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/app/course/service/AppHealthCourseService.java |   20 +++++++++++++++++---
 1 files changed, 17 insertions(+), 3 deletions(-)

diff --git a/tcm-training-admin-backend/src/main/java/com/tcm/training/admin/app/course/service/AppHealthCourseService.java b/tcm-training-admin-backend/src/main/java/com/tcm/training/admin/app/course/service/AppHealthCourseService.java
index 5d4fb5e..d83556f 100644
--- a/tcm-training-admin-backend/src/main/java/com/tcm/training/admin/app/course/service/AppHealthCourseService.java
+++ b/tcm-training-admin-backend/src/main/java/com/tcm/training/admin/app/course/service/AppHealthCourseService.java
@@ -311,17 +311,25 @@
         HealthCourse course = requireEnabledCourse(courseId);
         List<HealthCourseVideo> enabledVideos = listEnabledVideos(courseId);
         Map<Long, VideoProgressSnapshot> videoProgressSnapshotMap = buildVideoProgressSnapshotMap(userId, Collections.singletonList(courseId));
+        PurchaseStateSnapshot purchaseStateSnapshot = resolvePurchaseState(courseId);
 
         List<AppMyHealthCourseVideoItemVO> videos = new ArrayList<AppMyHealthCourseVideoItemVO>(enabledVideos.size());
         Long currentVideoId = null;
         LocalDateTime latestLearnAt = null;
         for (HealthCourseVideo video : enabledVideos) {
             VideoProgressSnapshot snapshot = videoProgressSnapshotMap.get(video.getId());
+            boolean freeAccess = isFreeVideo(video.getSalePrice());
+            boolean purchased = purchaseStateSnapshot.isCourseOwned()
+                    || purchaseStateSnapshot.getPurchasedVideoIds().contains(video.getId());
+            boolean locked = !freeAccess && !purchased;
             AppMyHealthCourseVideoItemVO itemVO = new AppMyHealthCourseVideoItemVO();
             itemVO.setVideoId(video.getId());
             itemVO.setChapterName(trimToEmpty(video.getChapterName()));
             itemVO.setDurationSeconds(defaultNumber(video.getDurationSeconds()));
             itemVO.setDurationText(formatVideoDuration(itemVO.getDurationSeconds()));
+            itemVO.setFreeAccess(Boolean.valueOf(freeAccess));
+            itemVO.setPurchased(Boolean.valueOf(purchased));
+            itemVO.setLocked(Boolean.valueOf(locked));
             itemVO.setVideoUrl(trimToEmpty(video.getVideoUrl()));
             itemVO.setCompleted(Boolean.valueOf(snapshot != null && snapshot.isCompleted()));
             itemVO.setProgressPercent(Integer.valueOf(calculateVideoDisplayProgressPercent(
@@ -332,14 +340,20 @@
             itemVO.setLastPlayPositionSeconds(Integer.valueOf(resolveVideoResumePosition(snapshot)));
             itemVO.setDownloadable(Boolean.valueOf(hasVideoDownloadAccess(userId, courseId, video.getId())));
             videos.add(itemVO);
-            if (snapshot != null && snapshot.getLatestLearnAt() != null
+            // 默认播放章节只允许落在当前用户可观看的小节上,未购小节保留展示但不自动选中。
+            if (!locked && snapshot != null && snapshot.getLatestLearnAt() != null
                     && (latestLearnAt == null || snapshot.getLatestLearnAt().isAfter(latestLearnAt))) {
                 latestLearnAt = snapshot.getLatestLearnAt();
                 currentVideoId = video.getId();
             }
         }
-        if (currentVideoId == null && !enabledVideos.isEmpty()) {
-            currentVideoId = enabledVideos.get(0).getId();
+        if (currentVideoId == null) {
+            for (AppMyHealthCourseVideoItemVO itemVO : videos) {
+                if (!Boolean.TRUE.equals(itemVO.getLocked())) {
+                    currentVideoId = itemVO.getVideoId();
+                    break;
+                }
+            }
         }
 
         AppMyHealthCourseDetailVO detailVO = new AppMyHealthCourseDetailVO();

--
Gitblit v1.7.1