feat(打卡页面): 支持多视频播放并优化媒体显示
- 将"团队动态"标题改为"打卡动态"以更符合场景 - 重构视频播放逻辑,支持每个帖子包含多个视频 - 优化图片显示宽度为30%并保持比例 - 完善视频播放控制,确保同时只播放一个视频 - 更新mock数据以支持多视频测试
Showing
1 changed file
with
73 additions
and
27 deletions
| 1 | <!-- | 1 | <!-- |
| 2 | * @Date: 2025-05-29 15:34:17 | 2 | * @Date: 2025-05-29 15:34:17 |
| 3 | * @LastEditors: hookehuyr hookehuyr@gmail.com | 3 | * @LastEditors: hookehuyr hookehuyr@gmail.com |
| 4 | - * @LastEditTime: 2025-05-30 18:31:25 | 4 | + * @LastEditTime: 2025-05-30 20:27:29 |
| 5 | * @FilePath: /mlaj/src/views/checkin/IndexCheckInPage.vue | 5 | * @FilePath: /mlaj/src/views/checkin/IndexCheckInPage.vue |
| 6 | * @Description: 文件描述 | 6 | * @Description: 文件描述 |
| 7 | --> | 7 | --> |
| ... | @@ -59,7 +59,7 @@ | ... | @@ -59,7 +59,7 @@ |
| 59 | </div> | 59 | </div> |
| 60 | 60 | ||
| 61 | <div class="text-wrapper"> | 61 | <div class="text-wrapper"> |
| 62 | - <div class="text-header">团队动态</div> | 62 | + <div class="text-header">打卡动态</div> |
| 63 | <div class="post-card" v-for="post in mockPosts" :key="post.id"> | 63 | <div class="post-card" v-for="post in mockPosts" :key="post.id"> |
| 64 | <div class="post-header"> | 64 | <div class="post-header"> |
| 65 | <van-row> | 65 | <van-row> |
| ... | @@ -78,26 +78,39 @@ | ... | @@ -78,26 +78,39 @@ |
| 78 | <div class="post-text">{{ post.content }}</div> | 78 | <div class="post-text">{{ post.content }}</div> |
| 79 | <div class="post-media"> | 79 | <div class="post-media"> |
| 80 | <div v-if="post.images.length" class="post-images"> | 80 | <div v-if="post.images.length" class="post-images"> |
| 81 | - <van-image width="100" height="100" v-for="(image, index) in post.images" :key="index" :src="image" | 81 | + <van-image width="30%" fit="cover" v-for="(image, index) in post.images" :key="index" :src="image" |
| 82 | @click="openImagePreview(index, post)" /> | 82 | @click="openImagePreview(index, post)" /> |
| 83 | </div> | 83 | </div> |
| 84 | <van-image-preview v-if="currentPost" v-model:show="showImagePreview" :images="currentPost.images" | 84 | <van-image-preview v-if="currentPost" v-model:show="showImagePreview" :images="currentPost.images" |
| 85 | :start-position="startPosition" :show-index="true" @change="onChange" /> | 85 | :start-position="startPosition" :show-index="true" @change="onChange" /> |
| 86 | + | ||
| 87 | + <div v-for="(v, idx) in post.videoList" :key="idx"> | ||
| 86 | <!-- 视频封面和播放按钮 --> | 88 | <!-- 视频封面和播放按钮 --> |
| 87 | - <div v-if="post.video && !post.isPlaying" class="relative w-full rounded-lg overflow-hidden" | 89 | + <div v-if="v.video && !v.isPlaying" class="relative w-full rounded-lg overflow-hidden" style="aspect-ratio: 16/9; margin-bottom: 1rem;"> |
| 88 | - style="aspect-ratio: 16/9;"> | 90 | + <img :src="v.videoCover || 'https://cdn.ipadbiz.cn/space/816560/大国少年_FhnF8lsFMPnTDNTBlM6hYa-UFBlW.jpg'" |
| 89 | - <img :src="post.videoCover || 'https://cdn.ipadbiz.cn/space/816560/大国少年_FhnF8lsFMPnTDNTBlM6hYa-UFBlW.jpg'" | 91 | + :alt="v.content" class="w-full h-full object-cover" /> |
| 90 | - :alt="post.content" class="w-full h-full object-cover" /> | 92 | + <div class="absolute inset-0 flex items-center justify-center cursor-pointer bg-black/20" |
| 91 | - <div class="absolute inset-0 flex items-center justify-center cursor-pointer bg-black/20" | 93 | + @click="startPlay(v)"> |
| 92 | - @click="startPlay(post)"> | 94 | + <div |
| 93 | - <div | 95 | + class="w-16 h-16 rounded-full bg-black/50 flex items-center justify-center hover:bg-black/70 transition-colors"> |
| 94 | - class="w-16 h-16 rounded-full bg-black/50 flex items-center justify-center hover:bg-black/70 transition-colors"> | 96 | + <van-icon name="play-circle-o" class="text-white" size="30" /> |
| 95 | - <van-icon name="play-circle-o" class="text-white" size="30" /> | 97 | + </div> |
| 96 | </div> | 98 | </div> |
| 97 | </div> | 99 | </div> |
| 100 | + <!-- 视频播放器 --> | ||
| 101 | + <VideoPlayer v-if="v.video && v.isPlaying" :video-url="v.video" class="post-video rounded-lg overflow-hidden" | ||
| 102 | + :ref="el => { | ||
| 103 | + if(el) { | ||
| 104 | + // 确保不重复添加 | ||
| 105 | + if (!videoPlayers?.includes(el)) { | ||
| 106 | + videoPlayers?.push(el); | ||
| 107 | + } | ||
| 108 | + } | ||
| 109 | + }" | ||
| 110 | + @onPlay="handleVideoPlay(player, post)" | ||
| 111 | + @onPause="handleVideoPause(post)" /> | ||
| 98 | </div> | 112 | </div> |
| 99 | - <!-- 视频播放器 --> | 113 | + <!-- <VideoPlayer v-if="post.video && post.isPlaying" :video-url="post.video" |
| 100 | - <VideoPlayer v-if="post.video && post.isPlaying" :video-url="post.video" | ||
| 101 | class="post-video rounded-lg overflow-hidden" | 114 | class="post-video rounded-lg overflow-hidden" |
| 102 | :ref="el => { | 115 | :ref="el => { |
| 103 | if(el) { | 116 | if(el) { |
| ... | @@ -108,7 +121,7 @@ | ... | @@ -108,7 +121,7 @@ |
| 108 | } | 121 | } |
| 109 | }" | 122 | }" |
| 110 | @onPlay="handleVideoPlay(player, post)" | 123 | @onPlay="handleVideoPlay(player, post)" |
| 111 | - @onPause="handleVideoPause(post)" /> | 124 | + @onPause="handleVideoPause(post)" /> --> |
| 112 | <AudioPlayer | 125 | <AudioPlayer |
| 113 | v-if="post.audio.length" | 126 | v-if="post.audio.length" |
| 114 | :songs="post.audio" | 127 | :songs="post.audio" |
| ... | @@ -181,9 +194,11 @@ const startPlay = (post) => { | ... | @@ -181,9 +194,11 @@ const startPlay = (post) => { |
| 181 | if (mockPosts.value) { | 194 | if (mockPosts.value) { |
| 182 | // 先暂停所有其他视频 | 195 | // 先暂停所有其他视频 |
| 183 | mockPosts.value.forEach(p => { | 196 | mockPosts.value.forEach(p => { |
| 184 | - if (p.id !== post.id) { | 197 | + p.videoList.forEach(v => { |
| 185 | - p.isPlaying = false; | 198 | + if (v.id !== post.id) { |
| 186 | - } | 199 | + v.isPlaying = false; |
| 200 | + } | ||
| 201 | + }); | ||
| 187 | }); | 202 | }); |
| 188 | } | 203 | } |
| 189 | 204 | ||
| ... | @@ -226,10 +241,12 @@ const stopOtherVideos = (currentPlayer, currentPost) => { | ... | @@ -226,10 +241,12 @@ const stopOtherVideos = (currentPlayer, currentPost) => { |
| 226 | } | 241 | } |
| 227 | 242 | ||
| 228 | // 更新其他帖子的播放状态 | 243 | // 更新其他帖子的播放状态 |
| 229 | - mockPosts.value.forEach(post => { | 244 | + mockPosts.value.forEach(p => { |
| 230 | - if (post.id !== currentPost.id) { | 245 | + p.videoList.forEach(v => { |
| 231 | - post.isPlaying = false; | 246 | + if (v.id !== currentPost.id) { |
| 232 | - } | 247 | + v.isPlaying = false; |
| 248 | + } | ||
| 249 | + }); | ||
| 233 | }); | 250 | }); |
| 234 | }; | 251 | }; |
| 235 | 252 | ||
| ... | @@ -259,6 +276,8 @@ const stopOtherAudio = (currentPlayer, currentPost) => { | ... | @@ -259,6 +276,8 @@ const stopOtherAudio = (currentPlayer, currentPost) => { |
| 259 | post.isPlaying = false; | 276 | post.isPlaying = false; |
| 260 | } | 277 | } |
| 261 | }); | 278 | }); |
| 279 | + // 停止所有视频播放 | ||
| 280 | + stopAllVideos(); | ||
| 262 | } | 281 | } |
| 263 | 282 | ||
| 264 | const stopAllAudio = () => { | 283 | const stopAllAudio = () => { |
| ... | @@ -293,8 +312,10 @@ const stopAllVideos = () => { | ... | @@ -293,8 +312,10 @@ const stopAllVideos = () => { |
| 293 | }); | 312 | }); |
| 294 | 313 | ||
| 295 | // 更新所有帖子的播放状态 | 314 | // 更新所有帖子的播放状态 |
| 296 | - mockPosts.value.forEach(post => { | 315 | + mockPosts.value.forEach(p => { |
| 297 | - post.isPlaying = false; | 316 | + p.videoList.forEach(v => { |
| 317 | + v.isPlaying = false; | ||
| 318 | + }); | ||
| 298 | }); | 319 | }); |
| 299 | }; | 320 | }; |
| 300 | 321 | ||
| ... | @@ -310,11 +331,12 @@ const mockPosts = ref([ | ... | @@ -310,11 +331,12 @@ const mockPosts = ref([ |
| 310 | content: '今天完成了React基础课程的学习,收获满满!', | 331 | content: '今天完成了React基础课程的学习,收获满满!', |
| 311 | images: [ | 332 | images: [ |
| 312 | 'https://cdn.ipadbiz.cn/space/816560/大国少年_FhnF8lsFMPnTDNTBlM6hYa-UFBlW.jpg', | 333 | 'https://cdn.ipadbiz.cn/space/816560/大国少年_FhnF8lsFMPnTDNTBlM6hYa-UFBlW.jpg', |
| 313 | - 'https://cdn.ipadbiz.cn/space/816560/大国少年_FhnF8lsFMPnTDNTBlM6hYa-UFBlW.jpg', | 334 | + 'https://cdn.ipadbiz.cn/mlaj/images/_6HzPU9Hyfg (2).jpg', |
| 314 | 'https://cdn.ipadbiz.cn/space/816560/大国少年_FhnF8lsFMPnTDNTBlM6hYa-UFBlW.jpg', | 335 | 'https://cdn.ipadbiz.cn/space/816560/大国少年_FhnF8lsFMPnTDNTBlM6hYa-UFBlW.jpg', |
| 315 | 'https://cdn.ipadbiz.cn/space/816560/大国少年_FhnF8lsFMPnTDNTBlM6hYa-UFBlW.jpg', | 336 | 'https://cdn.ipadbiz.cn/space/816560/大国少年_FhnF8lsFMPnTDNTBlM6hYa-UFBlW.jpg', |
| 316 | ], | 337 | ], |
| 317 | video: '', | 338 | video: '', |
| 339 | + videoList: [], | ||
| 318 | videoCover: '', | 340 | videoCover: '', |
| 319 | isPlaying: false, | 341 | isPlaying: false, |
| 320 | audio: [], | 342 | audio: [], |
| ... | @@ -330,7 +352,18 @@ const mockPosts = ref([ | ... | @@ -330,7 +352,18 @@ const mockPosts = ref([ |
| 330 | content: '今天完成了React基础课程的学习,收获满满!', | 352 | content: '今天完成了React基础课程的学习,收获满满!', |
| 331 | images: [], | 353 | images: [], |
| 332 | video: 'https://cdn.ipadbiz.cn/space/lk3DmvLO02dUC2zPiFwiClDe3nKL.mp4', | 354 | video: 'https://cdn.ipadbiz.cn/space/lk3DmvLO02dUC2zPiFwiClDe3nKL.mp4', |
| 333 | - videoCover: 'https://cdn.ipadbiz.cn/space/816560/大国少年_FhnF8lsFMPnTDNTBlM6hYa-UFBlW.jpg', | 355 | + videoList: [{ |
| 356 | + id: 1, | ||
| 357 | + video: 'https://cdn.ipadbiz.cn/space/lk3DmvLO02dUC2zPiFwiClDe3nKL.mp4', | ||
| 358 | + videoCover: '', | ||
| 359 | + isPlaying: false, | ||
| 360 | + }, { | ||
| 361 | + id: 2, | ||
| 362 | + video: 'https://cdn.ipadbiz.cn/space/lk3DmvLO02dUC2zPiFwiClDe3nKL.mp4', | ||
| 363 | + videoCover: '', | ||
| 364 | + isPlaying: false, | ||
| 365 | + }], | ||
| 366 | + videoCover: '', | ||
| 334 | isPlaying: false, | 367 | isPlaying: false, |
| 335 | audio: [], | 368 | audio: [], |
| 336 | likes: 12 | 369 | likes: 12 |
| ... | @@ -345,6 +378,7 @@ const mockPosts = ref([ | ... | @@ -345,6 +378,7 @@ const mockPosts = ref([ |
| 345 | content: '今天完成了React基础课程的学习,收获满满!', | 378 | content: '今天完成了React基础课程的学习,收获满满!', |
| 346 | images: [], | 379 | images: [], |
| 347 | video: '', | 380 | video: '', |
| 381 | + videoList: [], | ||
| 348 | videoCover: '', | 382 | videoCover: '', |
| 349 | isPlaying: false, | 383 | isPlaying: false, |
| 350 | audio: [ | 384 | audio: [ |
| ... | @@ -373,7 +407,18 @@ const mockPosts = ref([ | ... | @@ -373,7 +407,18 @@ const mockPosts = ref([ |
| 373 | content: '今天完成了React基础课程的学习,收获满满!', | 407 | content: '今天完成了React基础课程的学习,收获满满!', |
| 374 | images: [], | 408 | images: [], |
| 375 | video: 'https://cdn.ipadbiz.cn/space/lk3DmvLO02dUC2zPiFwiClDe3nKL.mp4', | 409 | video: 'https://cdn.ipadbiz.cn/space/lk3DmvLO02dUC2zPiFwiClDe3nKL.mp4', |
| 376 | - videoCover: 'https://cdn.ipadbiz.cn/space/816560/大国少年_FhnF8lsFMPnTDNTBlM6hYa-UFBlW.jpg', | 410 | + videoList: [{ |
| 411 | + id: 3, | ||
| 412 | + video: 'https://cdn.ipadbiz.cn/space/lk3DmvLO02dUC2zPiFwiClDe3nKL.mp4', | ||
| 413 | + videoCover: '', | ||
| 414 | + isPlaying: false, | ||
| 415 | + }, { | ||
| 416 | + id: 4, | ||
| 417 | + video: 'https://cdn.ipadbiz.cn/space/lk3DmvLO02dUC2zPiFwiClDe3nKL.mp4', | ||
| 418 | + videoCover: '', | ||
| 419 | + isPlaying: false, | ||
| 420 | + }], | ||
| 421 | + videoCover: '', | ||
| 377 | isPlaying: false, | 422 | isPlaying: false, |
| 378 | audio: [], | 423 | audio: [], |
| 379 | likes: 12 | 424 | likes: 12 |
| ... | @@ -388,6 +433,7 @@ const mockPosts = ref([ | ... | @@ -388,6 +433,7 @@ const mockPosts = ref([ |
| 388 | content: '今天完成了React基础课程的学习,收获满满!', | 433 | content: '今天完成了React基础课程的学习,收获满满!', |
| 389 | images: [], | 434 | images: [], |
| 390 | video: '', | 435 | video: '', |
| 436 | + videoList: [], | ||
| 391 | videoCover: '', | 437 | videoCover: '', |
| 392 | isPlaying: false, | 438 | isPlaying: false, |
| 393 | audio: [ | 439 | audio: [ | ... | ... |
-
Please register or login to post a comment