refactor(StudyDetailPage): 重构页面布局以优化用户体验
将视频播放和标签页区域固定,滚动区域独立,提升页面交互流畅性。添加标签页切换时的平滑滚动效果,优化用户浏览体验。
Showing
1 changed file
with
54 additions
and
21 deletions
| ... | @@ -4,16 +4,20 @@ | ... | @@ -4,16 +4,20 @@ |
| 4 | --> | 4 | --> |
| 5 | <template> | 5 | <template> |
| 6 | <div class="study-detail-page bg-gradient-to-b from-green-50/70 to-white/90 min-h-screen pb-20"> | 6 | <div class="study-detail-page bg-gradient-to-b from-green-50/70 to-white/90 min-h-screen pb-20"> |
| 7 | - <div v-if="course" class="flex flex-col"> | 7 | + <div v-if="course" class="flex flex-col h-screen"> |
| 8 | + <!-- 固定区域:视频播放和标签页 --> | ||
| 9 | + <div class="fixed top-0 left-0 right-0 z-10 top-wrapper"> | ||
| 8 | <!-- 视频播放区域 --> | 10 | <!-- 视频播放区域 --> |
| 9 | <div class="w-full bg-black relative"> | 11 | <div class="w-full bg-black relative"> |
| 10 | <!-- 视频封面和播放按钮 --> | 12 | <!-- 视频封面和播放按钮 --> |
| 11 | <div v-if="!isPlaying" class="relative w-full" style="aspect-ratio: 16/9;"> | 13 | <div v-if="!isPlaying" class="relative w-full" style="aspect-ratio: 16/9;"> |
| 12 | <img :src="course.cover" :alt="course.title" class="w-full h-full object-cover" /> | 14 | <img :src="course.cover" :alt="course.title" class="w-full h-full object-cover" /> |
| 13 | - <div class="absolute inset-0 flex items-center justify-center cursor-pointer" @click="startPlay"> | 15 | + <div class="absolute inset-0 flex items-center justify-center cursor-pointer" |
| 16 | + @click="startPlay"> | ||
| 14 | <div | 17 | <div |
| 15 | class="w-24 h-24 rounded-full bg-black/50 flex items-center justify-center hover:bg-black/70 transition-colors"> | 18 | class="w-24 h-24 rounded-full bg-black/50 flex items-center justify-center hover:bg-black/70 transition-colors"> |
| 16 | - <font-awesome-icon icon="circle-play" class="text-5xl text-white" style="font-size: 3rem;" /> | 19 | + <font-awesome-icon icon="circle-play" class="text-5xl text-white" |
| 20 | + style="font-size: 3rem;" /> | ||
| 17 | </div> | 21 | </div> |
| 18 | </div> | 22 | </div> |
| 19 | </div> | 23 | </div> |
| ... | @@ -21,25 +25,33 @@ | ... | @@ -21,25 +25,33 @@ |
| 21 | <VideoPlayer v-show="isPlaying" ref="videoPlayerRef" :video-url="course.videoUrl" :autoplay="false" | 25 | <VideoPlayer v-show="isPlaying" ref="videoPlayerRef" :video-url="course.videoUrl" :autoplay="false" |
| 22 | @onPlay="handleVideoPlay" @onPause="handleVideoPause" /> | 26 | @onPlay="handleVideoPlay" @onPause="handleVideoPause" /> |
| 23 | </div> | 27 | </div> |
| 24 | - | ||
| 25 | <!-- 标签页区域 --> | 28 | <!-- 标签页区域 --> |
| 26 | - <div class="px-4 py-3"> | 29 | + <div class="px-4 py-3 bg-white"> |
| 27 | - <van-tabs v-model:active="activeTab" sticky animated swipeable> | 30 | + <van-tabs v-model:active="activeTab" sticky animated swipeable shrink @change="handleTabChange"> |
| 28 | - <!-- 介绍标签页 --> | ||
| 29 | <van-tab title="介绍" name="intro"> | 31 | <van-tab title="介绍" name="intro"> |
| 30 | - <div class="py-4"> | 32 | + </van-tab> |
| 31 | - <h1 class="text-xl font-bold mb-2">{{ course.title }}</h1> | 33 | + <van-tab :title-style="{ 'min-width': '50%' }" name="comments"> |
| 32 | - <div class="text-gray-500 text-sm"> | 34 | + <template #title>评论(999)</template> |
| 33 | - {{ course.studyCount || 0 }}次学习 | 35 | + </van-tab> |
| 36 | + </van-tabs> | ||
| 34 | </div> | 37 | </div> |
| 35 | </div> | 38 | </div> |
| 36 | - </van-tab> | ||
| 37 | 39 | ||
| 38 | - <!-- 评论标签页 --> | 40 | + <!-- 滚动区域:介绍和评论内容 --> |
| 39 | - <van-tab title="评论" :title-style="{ 'min-width': '50%' }" name="comments"> | 41 | + <div class="overflow-y-auto flex-1" :style="{paddingTop: topWrapperHeight, height: 'calc(100vh - ' + topWrapperHeight + ')'}"> |
| 40 | - <div class="py-4 space-y-4"> | 42 | + <div id="intro" class="py-4 px-4"> |
| 41 | - <div v-for="comment in comments" :key="comment.id" | 43 | + <h1 class="text-lg font-bold mb-2">{{ course.title }}</h1> |
| 42 | - class="bg-white rounded-lg p-4 shadow-sm"> | 44 | + <div class="text-gray-500 text-sm flex items-center gap-2"> |
| 45 | + <span>{{ course.date }}</span> | ||
| 46 | + <span class="text-gray-300">|</span> | ||
| 47 | + <span>{{ course.studyCount || 0 }}次学习</span> | ||
| 48 | + </div> | ||
| 49 | + </div> | ||
| 50 | + | ||
| 51 | + <div class="h-2 bg-gray-100"></div> | ||
| 52 | + | ||
| 53 | + <div id="comment" class="py-4 px-4 space-y-4"> | ||
| 54 | + <div v-for="comment in comments" :key="comment.id" class="bg-white rounded-lg p-4 shadow-sm"> | ||
| 43 | <div class="flex items-center mb-2"> | 55 | <div class="flex items-center mb-2"> |
| 44 | <img :src="comment.avatar" class="w-8 h-8 rounded-full mr-2" /> | 56 | <img :src="comment.avatar" class="w-8 h-8 rounded-full mr-2" /> |
| 45 | <div> | 57 | <div> |
| ... | @@ -50,8 +62,6 @@ | ... | @@ -50,8 +62,6 @@ |
| 50 | <div class="text-gray-700">{{ comment.content }}</div> | 62 | <div class="text-gray-700">{{ comment.content }}</div> |
| 51 | </div> | 63 | </div> |
| 52 | </div> | 64 | </div> |
| 53 | - </van-tab> | ||
| 54 | - </van-tabs> | ||
| 55 | </div> | 65 | </div> |
| 56 | 66 | ||
| 57 | <!-- 底部操作栏 --> | 67 | <!-- 底部操作栏 --> |
| ... | @@ -126,9 +136,15 @@ const comments = ref([ | ... | @@ -126,9 +136,15 @@ const comments = ref([ |
| 126 | // 设置页面标题 | 136 | // 设置页面标题 |
| 127 | useTitle('学习详情'); | 137 | useTitle('学习详情'); |
| 128 | 138 | ||
| 129 | -// 获取课程详情 | 139 | +const topWrapperHeight = ref(0); |
| 130 | 140 | ||
| 131 | onMounted(() => { | 141 | onMounted(() => { |
| 142 | + nextTick(() => { | ||
| 143 | + const topWrapper = document.querySelector('.top-wrapper'); | ||
| 144 | + if (topWrapper) { | ||
| 145 | + topWrapperHeight.value = topWrapper.clientHeight + 'px'; | ||
| 146 | + } | ||
| 147 | + }) | ||
| 132 | const courseId = route.params.id; | 148 | const courseId = route.params.id; |
| 133 | if (courseId) { | 149 | if (courseId) { |
| 134 | // TODO: 这里需要替换为实际的API调用 | 150 | // TODO: 这里需要替换为实际的API调用 |
| ... | @@ -141,7 +157,8 @@ onMounted(() => { | ... | @@ -141,7 +157,8 @@ onMounted(() => { |
| 141 | studyTime: 3600, | 157 | studyTime: 3600, |
| 142 | type: '视频课程', | 158 | type: '视频课程', |
| 143 | studyCount: 1896, | 159 | studyCount: 1896, |
| 144 | - cover: 'https://fastly.jsdelivr.net/npm/@vant/assets/cat.jpeg' | 160 | + cover: 'https://fastly.jsdelivr.net/npm/@vant/assets/cat.jpeg', |
| 161 | + date: '2024-12-04' | ||
| 145 | }; | 162 | }; |
| 146 | } | 163 | } |
| 147 | }) | 164 | }) |
| ... | @@ -160,4 +177,20 @@ const submitComment = () => { | ... | @@ -160,4 +177,20 @@ const submitComment = () => { |
| 160 | 177 | ||
| 161 | newComment.value = ''; | 178 | newComment.value = ''; |
| 162 | }; | 179 | }; |
| 180 | + | ||
| 181 | +// 处理标签页切换 | ||
| 182 | +const handleTabChange = (name) => { | ||
| 183 | + nextTick(() => { | ||
| 184 | + const element = document.getElementById(name === 'intro' ? 'intro' : 'comment'); | ||
| 185 | + if (element && container) { | ||
| 186 | + const topOffset = element.offsetTop - parseInt(topWrapperHeight.value); | ||
| 187 | + window.scrollTo({ | ||
| 188 | + top: topOffset, | ||
| 189 | + behavior: 'smooth' | ||
| 190 | + }); | ||
| 191 | + } | ||
| 192 | + }) | ||
| 193 | +}; | ||
| 194 | + | ||
| 195 | + | ||
| 163 | </script> | 196 | </script> | ... | ... |
-
Please register or login to post a comment