hookehuyr

feat(打卡页面): 支持多视频播放并优化媒体显示

- 将"团队动态"标题改为"打卡动态"以更符合场景
- 重构视频播放逻辑,支持每个帖子包含多个视频
- 优化图片显示宽度为30%并保持比例
- 完善视频播放控制,确保同时只播放一个视频
- 更新mock数据以支持多视频测试
<!--
* @Date: 2025-05-29 15:34:17
* @LastEditors: hookehuyr hookehuyr@gmail.com
* @LastEditTime: 2025-05-30 18:31:25
* @LastEditTime: 2025-05-30 20:27:29
* @FilePath: /mlaj/src/views/checkin/IndexCheckInPage.vue
* @Description: 文件描述
-->
......@@ -59,7 +59,7 @@
</div>
<div class="text-wrapper">
<div class="text-header">团队动态</div>
<div class="text-header">打卡动态</div>
<div class="post-card" v-for="post in mockPosts" :key="post.id">
<div class="post-header">
<van-row>
......@@ -78,26 +78,39 @@
<div class="post-text">{{ post.content }}</div>
<div class="post-media">
<div v-if="post.images.length" class="post-images">
<van-image width="100" height="100" v-for="(image, index) in post.images" :key="index" :src="image"
<van-image width="30%" fit="cover" v-for="(image, index) in post.images" :key="index" :src="image"
@click="openImagePreview(index, post)" />
</div>
<van-image-preview v-if="currentPost" v-model:show="showImagePreview" :images="currentPost.images"
:start-position="startPosition" :show-index="true" @change="onChange" />
<div v-for="(v, idx) in post.videoList" :key="idx">
<!-- 视频封面和播放按钮 -->
<div v-if="post.video && !post.isPlaying" class="relative w-full rounded-lg overflow-hidden"
style="aspect-ratio: 16/9;">
<img :src="post.videoCover || 'https://cdn.ipadbiz.cn/space/816560/大国少年_FhnF8lsFMPnTDNTBlM6hYa-UFBlW.jpg'"
:alt="post.content" class="w-full h-full object-cover" />
<div class="absolute inset-0 flex items-center justify-center cursor-pointer bg-black/20"
@click="startPlay(post)">
<div
class="w-16 h-16 rounded-full bg-black/50 flex items-center justify-center hover:bg-black/70 transition-colors">
<van-icon name="play-circle-o" class="text-white" size="30" />
<div v-if="v.video && !v.isPlaying" class="relative w-full rounded-lg overflow-hidden" style="aspect-ratio: 16/9; margin-bottom: 1rem;">
<img :src="v.videoCover || 'https://cdn.ipadbiz.cn/space/816560/大国少年_FhnF8lsFMPnTDNTBlM6hYa-UFBlW.jpg'"
:alt="v.content" class="w-full h-full object-cover" />
<div class="absolute inset-0 flex items-center justify-center cursor-pointer bg-black/20"
@click="startPlay(v)">
<div
class="w-16 h-16 rounded-full bg-black/50 flex items-center justify-center hover:bg-black/70 transition-colors">
<van-icon name="play-circle-o" class="text-white" size="30" />
</div>
</div>
</div>
<!-- 视频播放器 -->
<VideoPlayer v-if="v.video && v.isPlaying" :video-url="v.video" class="post-video rounded-lg overflow-hidden"
:ref="el => {
if(el) {
// 确保不重复添加
if (!videoPlayers?.includes(el)) {
videoPlayers?.push(el);
}
}
}"
@onPlay="handleVideoPlay(player, post)"
@onPause="handleVideoPause(post)" />
</div>
<!-- 视频播放器 -->
<VideoPlayer v-if="post.video && post.isPlaying" :video-url="post.video"
<!-- <VideoPlayer v-if="post.video && post.isPlaying" :video-url="post.video"
class="post-video rounded-lg overflow-hidden"
:ref="el => {
if(el) {
......@@ -108,7 +121,7 @@
}
}"
@onPlay="handleVideoPlay(player, post)"
@onPause="handleVideoPause(post)" />
@onPause="handleVideoPause(post)" /> -->
<AudioPlayer
v-if="post.audio.length"
:songs="post.audio"
......@@ -181,9 +194,11 @@ const startPlay = (post) => {
if (mockPosts.value) {
// 先暂停所有其他视频
mockPosts.value.forEach(p => {
if (p.id !== post.id) {
p.isPlaying = false;
}
p.videoList.forEach(v => {
if (v.id !== post.id) {
v.isPlaying = false;
}
});
});
}
......@@ -226,10 +241,12 @@ const stopOtherVideos = (currentPlayer, currentPost) => {
}
// 更新其他帖子的播放状态
mockPosts.value.forEach(post => {
if (post.id !== currentPost.id) {
post.isPlaying = false;
}
mockPosts.value.forEach(p => {
p.videoList.forEach(v => {
if (v.id !== currentPost.id) {
v.isPlaying = false;
}
});
});
};
......@@ -259,6 +276,8 @@ const stopOtherAudio = (currentPlayer, currentPost) => {
post.isPlaying = false;
}
});
// 停止所有视频播放
stopAllVideos();
}
const stopAllAudio = () => {
......@@ -293,8 +312,10 @@ const stopAllVideos = () => {
});
// 更新所有帖子的播放状态
mockPosts.value.forEach(post => {
post.isPlaying = false;
mockPosts.value.forEach(p => {
p.videoList.forEach(v => {
v.isPlaying = false;
});
});
};
......@@ -310,11 +331,12 @@ const mockPosts = ref([
content: '今天完成了React基础课程的学习,收获满满!',
images: [
'https://cdn.ipadbiz.cn/space/816560/大国少年_FhnF8lsFMPnTDNTBlM6hYa-UFBlW.jpg',
'https://cdn.ipadbiz.cn/space/816560/大国少年_FhnF8lsFMPnTDNTBlM6hYa-UFBlW.jpg',
'https://cdn.ipadbiz.cn/mlaj/images/_6HzPU9Hyfg (2).jpg',
'https://cdn.ipadbiz.cn/space/816560/大国少年_FhnF8lsFMPnTDNTBlM6hYa-UFBlW.jpg',
'https://cdn.ipadbiz.cn/space/816560/大国少年_FhnF8lsFMPnTDNTBlM6hYa-UFBlW.jpg',
],
video: '',
videoList: [],
videoCover: '',
isPlaying: false,
audio: [],
......@@ -330,7 +352,18 @@ const mockPosts = ref([
content: '今天完成了React基础课程的学习,收获满满!',
images: [],
video: 'https://cdn.ipadbiz.cn/space/lk3DmvLO02dUC2zPiFwiClDe3nKL.mp4',
videoCover: 'https://cdn.ipadbiz.cn/space/816560/大国少年_FhnF8lsFMPnTDNTBlM6hYa-UFBlW.jpg',
videoList: [{
id: 1,
video: 'https://cdn.ipadbiz.cn/space/lk3DmvLO02dUC2zPiFwiClDe3nKL.mp4',
videoCover: '',
isPlaying: false,
}, {
id: 2,
video: 'https://cdn.ipadbiz.cn/space/lk3DmvLO02dUC2zPiFwiClDe3nKL.mp4',
videoCover: '',
isPlaying: false,
}],
videoCover: '',
isPlaying: false,
audio: [],
likes: 12
......@@ -345,6 +378,7 @@ const mockPosts = ref([
content: '今天完成了React基础课程的学习,收获满满!',
images: [],
video: '',
videoList: [],
videoCover: '',
isPlaying: false,
audio: [
......@@ -373,7 +407,18 @@ const mockPosts = ref([
content: '今天完成了React基础课程的学习,收获满满!',
images: [],
video: 'https://cdn.ipadbiz.cn/space/lk3DmvLO02dUC2zPiFwiClDe3nKL.mp4',
videoCover: 'https://cdn.ipadbiz.cn/space/816560/大国少年_FhnF8lsFMPnTDNTBlM6hYa-UFBlW.jpg',
videoList: [{
id: 3,
video: 'https://cdn.ipadbiz.cn/space/lk3DmvLO02dUC2zPiFwiClDe3nKL.mp4',
videoCover: '',
isPlaying: false,
}, {
id: 4,
video: 'https://cdn.ipadbiz.cn/space/lk3DmvLO02dUC2zPiFwiClDe3nKL.mp4',
videoCover: '',
isPlaying: false,
}],
videoCover: '',
isPlaying: false,
audio: [],
likes: 12
......@@ -388,6 +433,7 @@ const mockPosts = ref([
content: '今天完成了React基础课程的学习,收获满满!',
images: [],
video: '',
videoList: [],
videoCover: '',
isPlaying: false,
audio: [
......