StudyDetailPage.vue 7.35 KB
<!--
 * @Date: 2025-04-07
 * @Description: 学习详情页面
-->
<template>
    <div class="study-detail-page bg-gradient-to-b from-green-50/70 to-white/90 min-h-screen pb-20">
        <div v-if="course" class="flex flex-col h-screen">
            <!-- 固定区域:视频播放和标签页 -->
            <div class="fixed top-0 left-0 right-0 z-10 top-wrapper">
                <!-- 视频播放区域 -->
                <div class="w-full bg-black relative">
                    <!-- 视频封面和播放按钮 -->
                    <div v-if="!isPlaying" class="relative w-full" style="aspect-ratio: 16/9;">
                        <img :src="course.cover" :alt="course.title" class="w-full h-full object-cover" />
                        <div class="absolute inset-0 flex items-center justify-center cursor-pointer"
                            @click="startPlay">
                            <div
                                class="w-24 h-24 rounded-full bg-black/50 flex items-center justify-center hover:bg-black/70 transition-colors">
                                <font-awesome-icon icon="circle-play" class="text-5xl text-white"
                                    style="font-size: 3rem;" />
                            </div>
                        </div>
                    </div>
                    <!-- 视频播放器 -->
                    <VideoPlayer v-show="isPlaying" ref="videoPlayerRef" :video-url="course.videoUrl" :autoplay="false"
                        @onPlay="handleVideoPlay" @onPause="handleVideoPause" />
                </div>
                <!-- 标签页区域 -->
                <div class="px-4 py-3 bg-white">
                    <van-tabs v-model:active="activeTab" sticky animated swipeable shrink @change="handleTabChange">
                        <van-tab title="介绍" name="intro">
                        </van-tab>
                        <van-tab :title-style="{ 'min-width': '50%' }" name="comments">
                            <template #title>评论(999)</template>
                        </van-tab>
                    </van-tabs>
                </div>
            </div>

            <!-- 滚动区域:介绍和评论内容 -->
            <div class="overflow-y-auto flex-1" :style="{paddingTop: topWrapperHeight, height: 'calc(100vh - ' + topWrapperHeight + ')'}">
                <div id="intro" class="py-4 px-4">
                    <h1 class="text-lg font-bold mb-2">{{ course.title }}</h1>
                    <div class="text-gray-500 text-sm flex items-center gap-2">
                        <span>{{ course.date }}</span>
                        <span class="text-gray-300">|</span>
                        <span>{{ course.studyCount || 0 }}次学习</span>
                    </div>
                </div>

                <div class="h-2 bg-gray-100"></div>

                <div id="comment" class="py-4 px-4 space-y-4">
                    <div v-for="comment in comments" :key="comment.id" class="bg-white rounded-lg p-4 shadow-sm">
                        <div class="flex items-center mb-2">
                            <img :src="comment.avatar" class="w-8 h-8 rounded-full mr-2" />
                            <div>
                                <div class="font-medium">{{ comment.username }}</div>
                                <div class="text-gray-500 text-xs">{{ comment.time }}</div>
                            </div>
                        </div>
                        <div class="text-gray-700">{{ comment.content }}</div>
                    </div>
                </div>
            </div>

            <!-- 底部操作栏 -->
            <div class="fixed bottom-0 left-0 right-0 bg-white border-t px-4 py-2 flex items-center space-x-4">
                <van-button icon="bars" class="flex-none" @click="showCatalog = true">课程目录</van-button>
                <div class="flex-grow">
                    <van-field v-model="newComment" placeholder="说点什么吧~" class="bg-gray-100 rounded-full" />
                </div>
                <van-button type="primary" size="small" @click="submitComment">发送</van-button>
            </div>
        </div>
    </div>
</template>

<script setup>
import { ref, onMounted, nextTick } from 'vue';
import { useRoute } from 'vue-router';
import { useTitle } from '@vueuse/core';
import VideoPlayer from '@/components/ui/VideoPlayer.vue';

const route = useRoute();
const course = ref(null);
const activeTab = ref('intro');
const newComment = ref('');
const showCatalog = ref(false);
const isPlaying = ref(false);
const videoPlayerRef = ref(null);

// 开始播放视频
const startPlay = async () => {
    isPlaying.value = true;
    await nextTick();
    if (videoPlayerRef.value) {
        videoPlayerRef.value.play();
    }
};

// 处理视频播放状态
const handleVideoPlay = () => {
    isPlaying.value = true;
};

const handleVideoPause = () => {
    // 保持视频播放器可见,只在初始状态显示封面
};

// 评论列表
const comments = ref([
    {
        id: 1,
        username: '欢乐马',
        avatar: 'https://fastly.jsdelivr.net/npm/@vant/assets/cat.jpeg',
        content: '教育的顶级传承,是你用什么样的心,传承智慧',
        time: '2024-12-04 18:51'
    },
    {
        id: 2,
        username: '欢乐马',
        avatar: 'https://fastly.jsdelivr.net/npm/@vant/assets/cat.jpeg',
        content: '不要用战术上的勤奋,掩盖战略上的懒惰',
        time: '2024-12-04 08:01'
    },
    {
        id: 3,
        username: '欢乐马',
        avatar: 'https://fastly.jsdelivr.net/npm/@vant/assets/cat.jpeg',
        content: '和老师积极互动,整个课堂像为你而讲',
        time: '2024-12-04 07:54'
    }
]);

// 设置页面标题
useTitle('学习详情');

const topWrapperHeight = ref(0);

onMounted(() => {
    nextTick(() => {
        const topWrapper = document.querySelector('.top-wrapper');
        if (topWrapper) {
            topWrapperHeight.value = topWrapper.clientHeight + 'px';
        }
    })
    const courseId = route.params.id;
    if (courseId) {
        // TODO: 这里需要替换为实际的API调用
        // 临时使用模拟数据
        course.value = {
            id: courseId,
            title: '开学礼·止的智慧·心法老师·20241001(上)',
            videoUrl: 'https://sf1-cdn-tos.huoshanstatic.com/obj/media-fe/xgplayer_doc_video/mp4/xgplayer-demo-360p.mp4',
            progress: 35,
            studyTime: 3600,
            type: '视频课程',
            studyCount: 1896,
            cover: 'https://fastly.jsdelivr.net/npm/@vant/assets/cat.jpeg',
            date: '2024-12-04'
        };
    }
})

// 提交评论
const submitComment = () => {
    if (!newComment.value.trim()) return;

    comments.value.unshift({
        id: Date.now(),
        username: '当前用户',
        avatar: 'https://fastly.jsdelivr.net/npm/@vant/assets/cat.jpeg',
        content: newComment.value,
        time: new Date().toLocaleString()
    });

    newComment.value = '';
};

// 处理标签页切换
const handleTabChange = (name) => {
    nextTick(() => {
        const element = document.getElementById(name === 'intro' ? 'intro' : 'comment');
        if (element && container) {
            const topOffset = element.offsetTop - parseInt(topWrapperHeight.value);
            window.scrollTo({
                top: topOffset,
                behavior: 'smooth'
            });
        }
    })
};


</script>