feat(播放器): 实现音视频互斥播放功能并优化默认封面
在VideoPlayer和AudioPlayer组件中添加互斥播放逻辑,当播放视频时自动暂停音频,反之亦然 为音频播放器添加默认封面图片 更新所有测试图片和音频资源URL为正式CDN地址 添加组件卸载时的清理逻辑
Showing
3 changed files
with
220 additions
and
38 deletions
| 1 | <!-- | 1 | <!-- |
| 2 | * @Date: 2025-04-07 12:35:35 | 2 | * @Date: 2025-04-07 12:35:35 |
| 3 | * @LastEditors: hookehuyr hookehuyr@gmail.com | 3 | * @LastEditors: hookehuyr hookehuyr@gmail.com |
| 4 | - * @LastEditTime: 2025-05-16 16:50:23 | 4 | + * @LastEditTime: 2025-05-30 15:26:15 |
| 5 | * @FilePath: /mlaj/src/components/ui/AudioPlayer.vue | 5 | * @FilePath: /mlaj/src/components/ui/AudioPlayer.vue |
| 6 | * @Description: 音频播放器组件,支持播放控制、进度条调节、音量控制、播放列表等功能 | 6 | * @Description: 音频播放器组件,支持播放控制、进度条调节、音量控制、播放列表等功能 |
| 7 | --> | 7 | --> |
| ... | @@ -12,7 +12,7 @@ | ... | @@ -12,7 +12,7 @@ |
| 12 | <div class="flex flex-col items-center mb-4"> | 12 | <div class="flex flex-col items-center mb-4"> |
| 13 | <!-- 歌曲封面 --> | 13 | <!-- 歌曲封面 --> |
| 14 | <div class="w-24 h-24 rounded-lg overflow-hidden mb-2"> | 14 | <div class="w-24 h-24 rounded-lg overflow-hidden mb-2"> |
| 15 | - <img :src="currentSong?.cover" alt="封面" class="w-full h-full object-cover"> | 15 | + <img :src="currentSong?.cover ? currentSong?.cover : 'https://cdn.ipadbiz.cn/mlaj/images/audio_d_cover.jpg'" alt="封面" class="w-full h-full object-cover"> |
| 16 | </div> | 16 | </div> |
| 17 | 17 | ||
| 18 | <!-- 歌曲信息 --> | 18 | <!-- 歌曲信息 --> |
| ... | @@ -21,7 +21,7 @@ | ... | @@ -21,7 +21,7 @@ |
| 21 | <p class="text-xs text-gray-500">{{ currentSong?.artist }}</p> | 21 | <p class="text-xs text-gray-500">{{ currentSong?.artist }}</p> |
| 22 | </div> | 22 | </div> |
| 23 | 23 | ||
| 24 | - </div> | 24 | + </div> |
| 25 | 25 | ||
| 26 | <!-- 进度条与时间:显示当前播放时间、总时长和可拖动的进度条 --> | 26 | <!-- 进度条与时间:显示当前播放时间、总时长和可拖动的进度条 --> |
| 27 | <div class="mt-4 mb-6"> | 27 | <div class="mt-4 mb-6"> |
| ... | @@ -105,7 +105,7 @@ | ... | @@ -105,7 +105,7 @@ |
| 105 | > | 105 | > |
| 106 | <div class="absolute top-0 left-0 right-0 h-[1px] bg-gray-200"></div> | 106 | <div class="absolute top-0 left-0 right-0 h-[1px] bg-gray-200"></div> |
| 107 | <div class="w-16 h-16 rounded-lg overflow-hidden mr-4 flex-shrink-0"> | 107 | <div class="w-16 h-16 rounded-lg overflow-hidden mr-4 flex-shrink-0"> |
| 108 | - <img :src="song?.cover" alt="封面" class="w-full h-full object-cover"> | 108 | + <img :src="song?.cover ? song?.cover : 'https://cdn.ipadbiz.cn/mlaj/images/audio_d_cover.jpg'" alt="封面" class="w-full h-full object-cover"> |
| 109 | </div> | 109 | </div> |
| 110 | <div class="flex-1"> | 110 | <div class="flex-1"> |
| 111 | <div class="font-medium">{{ song?.title }}</div> | 111 | <div class="font-medium">{{ song?.title }}</div> |
| ... | @@ -177,6 +177,9 @@ const loadAudio = async () => { | ... | @@ -177,6 +177,9 @@ const loadAudio = async () => { |
| 177 | } | 177 | } |
| 178 | } | 178 | } |
| 179 | 179 | ||
| 180 | +// 定义组件事件 | ||
| 181 | +const emit = defineEmits(['play', 'pause']) | ||
| 182 | + | ||
| 180 | // 播放控制:切换播放/暂停状态 | 183 | // 播放控制:切换播放/暂停状态 |
| 181 | const togglePlay = async () => { | 184 | const togglePlay = async () => { |
| 182 | if (isLoading.value) return | 185 | if (isLoading.value) return |
| ... | @@ -186,8 +189,10 @@ const togglePlay = async () => { | ... | @@ -186,8 +189,10 @@ const togglePlay = async () => { |
| 186 | } | 189 | } |
| 187 | if (isPlaying.value) { | 190 | if (isPlaying.value) { |
| 188 | await audio.value?.pause() | 191 | await audio.value?.pause() |
| 192 | + emit('pause', audio.value) | ||
| 189 | } else { | 193 | } else { |
| 190 | await audio.value?.play() | 194 | await audio.value?.play() |
| 195 | + emit('play', audio.value) | ||
| 191 | } | 196 | } |
| 192 | isPlaying.value = !isPlaying.value | 197 | isPlaying.value = !isPlaying.value |
| 193 | } catch (error) { | 198 | } catch (error) { |
| ... | @@ -195,6 +200,19 @@ const togglePlay = async () => { | ... | @@ -195,6 +200,19 @@ const togglePlay = async () => { |
| 195 | } | 200 | } |
| 196 | } | 201 | } |
| 197 | 202 | ||
| 203 | +// 暴露给父组件的方法 | ||
| 204 | +defineExpose({ | ||
| 205 | + togglePlay, | ||
| 206 | + pause: () => { | ||
| 207 | + if (isPlaying.value && audio.value) { | ||
| 208 | + audio.value.pause(); | ||
| 209 | + isPlaying.value = false; | ||
| 210 | + emit('pause', audio.value); | ||
| 211 | + } | ||
| 212 | + }, | ||
| 213 | + isPlaying: () => isPlaying.value | ||
| 214 | +}) | ||
| 215 | + | ||
| 198 | // 进度更新 | 216 | // 进度更新 |
| 199 | const updateProgress = () => { | 217 | const updateProgress = () => { |
| 200 | if (!audio.value) return | 218 | if (!audio.value) return |
| ... | @@ -223,6 +241,8 @@ const prevSong = async () => { | ... | @@ -223,6 +241,8 @@ const prevSong = async () => { |
| 223 | const normalizedVolume = Math.pow(volume.value / 100, 2) | 241 | const normalizedVolume = Math.pow(volume.value / 100, 2) |
| 224 | audio.value.volume = normalizedVolume | 242 | audio.value.volume = normalizedVolume |
| 225 | isPlaying.value = true | 243 | isPlaying.value = true |
| 244 | + // 发射播放事件 | ||
| 245 | + emit('play', audio.value) | ||
| 226 | } | 246 | } |
| 227 | } | 247 | } |
| 228 | 248 | ||
| ... | @@ -241,6 +261,8 @@ const nextSong = async () => { | ... | @@ -241,6 +261,8 @@ const nextSong = async () => { |
| 241 | const normalizedVolume = Math.pow(volume.value / 100, 2) | 261 | const normalizedVolume = Math.pow(volume.value / 100, 2) |
| 242 | audio.value.volume = normalizedVolume | 262 | audio.value.volume = normalizedVolume |
| 243 | isPlaying.value = true | 263 | isPlaying.value = true |
| 264 | + // 发射播放事件 | ||
| 265 | + emit('play', audio.value) | ||
| 244 | } | 266 | } |
| 245 | } | 267 | } |
| 246 | 268 | ||
| ... | @@ -312,6 +334,8 @@ const selectSong = async (index) => { | ... | @@ -312,6 +334,8 @@ const selectSong = async (index) => { |
| 312 | if (audio.value) { | 334 | if (audio.value) { |
| 313 | await audio.value.play() | 335 | await audio.value.play() |
| 314 | isPlaying.value = true | 336 | isPlaying.value = true |
| 337 | + // 发射播放事件 | ||
| 338 | + emit('play', audio.value) | ||
| 315 | // 关闭播放列表 | 339 | // 关闭播放列表 |
| 316 | isPlaylistVisible.value = false | 340 | isPlaylistVisible.value = false |
| 317 | // 滚动到当前播放的音频 | 341 | // 滚动到当前播放的音频 | ... | ... |
| ... | @@ -119,12 +119,12 @@ onBeforeUnmount(() => { | ... | @@ -119,12 +119,12 @@ onBeforeUnmount(() => { |
| 119 | defineExpose({ | 119 | defineExpose({ |
| 120 | pause() { | 120 | pause() { |
| 121 | if (player.value) { | 121 | if (player.value) { |
| 122 | - player.value.pause(); | 122 | + player.value?.pause(); |
| 123 | } | 123 | } |
| 124 | }, | 124 | }, |
| 125 | play() { | 125 | play() { |
| 126 | if (player.value) { | 126 | if (player.value) { |
| 127 | - player.value.play(); | 127 | + player.value?.play(); |
| 128 | } | 128 | } |
| 129 | }, | 129 | }, |
| 130 | }); | 130 | }); | ... | ... |
| 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 15:11:36 | 4 | + * @LastEditTime: 2025-05-30 15:54:33 |
| 5 | * @FilePath: /mlaj/src/views/checkin/IndexCheckInPage.vue | 5 | * @FilePath: /mlaj/src/views/checkin/IndexCheckInPage.vue |
| 6 | * @Description: 文件描述 | 6 | * @Description: 文件描述 |
| 7 | --> | 7 | --> |
| ... | @@ -38,7 +38,7 @@ | ... | @@ -38,7 +38,7 @@ |
| 38 | <van-progress :percentage="progress2" color="#4caf50" :show-pivot="false" /> | 38 | <van-progress :percentage="progress2" color="#4caf50" :show-pivot="false" /> |
| 39 | </div> | 39 | </div> |
| 40 | <div style="padding: 0.75rem 1rem;"> | 40 | <div style="padding: 0.75rem 1rem;"> |
| 41 | - <van-image round width="2.8rem" height="2.8rem" src="https://fastly.jsdelivr.net/npm/@vant/assets/cat.jpeg" | 41 | + <van-image round width="2.8rem" height="2.8rem" src="https://cdn.ipadbiz.cn/space/816560/大国少年_FhnF8lsFMPnTDNTBlM6hYa-UFBlW.jpg" |
| 42 | v-for="(item, index) in teamAvatars" :key="index" | 42 | v-for="(item, index) in teamAvatars" :key="index" |
| 43 | :style="{ marginLeft: index > 0 ? '-0.5rem' : '', border: '2px solid #FFF' }" /> | 43 | :style="{ marginLeft: index > 0 ? '-0.5rem' : '', border: '2px solid #FFF' }" /> |
| 44 | </div> | 44 | </div> |
| ... | @@ -86,7 +86,7 @@ | ... | @@ -86,7 +86,7 @@ |
| 86 | <!-- 视频封面和播放按钮 --> | 86 | <!-- 视频封面和播放按钮 --> |
| 87 | <div v-if="post.video && !post.isPlaying" class="relative w-full rounded-lg overflow-hidden" | 87 | <div v-if="post.video && !post.isPlaying" class="relative w-full rounded-lg overflow-hidden" |
| 88 | style="aspect-ratio: 16/9;"> | 88 | style="aspect-ratio: 16/9;"> |
| 89 | - <img :src="post.videoCover || 'https://fastly.jsdelivr.net/npm/@vant/assets/cat.jpeg'" | 89 | + <img :src="post.videoCover || 'https://cdn.ipadbiz.cn/space/816560/大国少年_FhnF8lsFMPnTDNTBlM6hYa-UFBlW.jpg'" |
| 90 | :alt="post.content" class="w-full h-full object-cover" /> | 90 | :alt="post.content" class="w-full h-full object-cover" /> |
| 91 | <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" |
| 92 | @click="startPlay(post)"> | 92 | @click="startPlay(post)"> |
| ... | @@ -98,9 +98,31 @@ | ... | @@ -98,9 +98,31 @@ |
| 98 | </div> | 98 | </div> |
| 99 | <!-- 视频播放器 --> | 99 | <!-- 视频播放器 --> |
| 100 | <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" ref="(el) => { if(el) videoPlayers.value.push(el) }" | 101 | + class="post-video rounded-lg overflow-hidden" |
| 102 | - @onPlay="(player) => handleVideoPlay(player, post)" @onPause="() => handleVideoPause(post)" /> | 102 | + :ref="el => { |
| 103 | - <AudioPlayer v-if="post.audio.length" :songs="post.audio" class="post-audio" /> | 103 | + if(el) { |
| 104 | + // 确保不重复添加 | ||
| 105 | + if (!videoPlayers?.includes(el)) { | ||
| 106 | + videoPlayers?.push(el); | ||
| 107 | + } | ||
| 108 | + } | ||
| 109 | + }" | ||
| 110 | + @onPlay="(player) => handleVideoPlay(player, post)" | ||
| 111 | + @onPause="() => handleVideoPause(post)" /> | ||
| 112 | + <AudioPlayer | ||
| 113 | + v-if="post.audio.length" | ||
| 114 | + :songs="post.audio" | ||
| 115 | + class="post-audio" | ||
| 116 | + :ref="el => { | ||
| 117 | + if(el) { | ||
| 118 | + // 确保不重复添加 | ||
| 119 | + if (!audioPlayers?.includes(el)) { | ||
| 120 | + audioPlayers?.push(el); | ||
| 121 | + } | ||
| 122 | + } | ||
| 123 | + }" | ||
| 124 | + @play="(player) => handleAudioPlay(player, post)" | ||
| 125 | + /> | ||
| 104 | </div> | 126 | </div> |
| 105 | </div> | 127 | </div> |
| 106 | <div class="post-footer"> | 128 | <div class="post-footer"> |
| ... | @@ -116,7 +138,7 @@ | ... | @@ -116,7 +138,7 @@ |
| 116 | </template> | 138 | </template> |
| 117 | 139 | ||
| 118 | <script setup> | 140 | <script setup> |
| 119 | -import { ref } from 'vue' | 141 | +import { ref, onBeforeUnmount } from 'vue' |
| 120 | import { useRoute, useRouter } from 'vue-router' | 142 | import { useRoute, useRouter } from 'vue-router' |
| 121 | import AppLayout from "@/components/layout/AppLayout.vue"; | 143 | import AppLayout from "@/components/layout/AppLayout.vue"; |
| 122 | import FrostedGlass from "@/components/ui/FrostedGlass.vue"; | 144 | import FrostedGlass from "@/components/ui/FrostedGlass.vue"; |
| ... | @@ -126,17 +148,43 @@ import AudioPlayer from "@/components/ui/AudioPlayer.vue"; | ... | @@ -126,17 +148,43 @@ import AudioPlayer from "@/components/ui/AudioPlayer.vue"; |
| 126 | // 存储所有视频播放器的引用 | 148 | // 存储所有视频播放器的引用 |
| 127 | const videoPlayers = ref([]); | 149 | const videoPlayers = ref([]); |
| 128 | 150 | ||
| 151 | +// 存储所有音频播放器的引用 | ||
| 152 | +const audioPlayers = ref([]); | ||
| 153 | + | ||
| 154 | +// 组件卸载前清理播放器引用 | ||
| 155 | +onBeforeUnmount(() => { | ||
| 156 | + // 停止所有视频和音频播放 | ||
| 157 | + if (videoPlayers.value) { | ||
| 158 | + videoPlayers.value.forEach(player => { | ||
| 159 | + if (player && typeof player.pause === 'function') { | ||
| 160 | + player.pause(); | ||
| 161 | + } | ||
| 162 | + }); | ||
| 163 | + } | ||
| 164 | + | ||
| 165 | + stopAllAudio(); | ||
| 166 | + | ||
| 167 | + // 清空引用数组 | ||
| 168 | + if (videoPlayers.value) videoPlayers.value = []; | ||
| 169 | + if (audioPlayers.value) audioPlayers.value = []; | ||
| 170 | + | ||
| 171 | +}); | ||
| 172 | + | ||
| 173 | + | ||
| 129 | /** | 174 | /** |
| 130 | * 开始播放指定帖子的视频 | 175 | * 开始播放指定帖子的视频 |
| 131 | * @param {Object} post - 要播放视频的帖子对象 | 176 | * @param {Object} post - 要播放视频的帖子对象 |
| 132 | */ | 177 | */ |
| 133 | const startPlay = (post) => { | 178 | const startPlay = (post) => { |
| 134 | - // 先暂停所有其他视频 | 179 | + // 确保mockPosts.value是一个数组 |
| 135 | - mockPosts.value.forEach(p => { | 180 | + if (mockPosts.value) { |
| 136 | - if (p.id !== post.id) { | 181 | + // 先暂停所有其他视频 |
| 137 | - p.isPlaying = false; | 182 | + mockPosts.value.forEach(p => { |
| 138 | - } | 183 | + if (p.id !== post.id) { |
| 139 | - }); | 184 | + p.isPlaying = false; |
| 185 | + } | ||
| 186 | + }); | ||
| 187 | + } | ||
| 140 | 188 | ||
| 141 | // 设置当前视频为播放状态 | 189 | // 设置当前视频为播放状态 |
| 142 | post.isPlaying = true; | 190 | post.isPlaying = true; |
| ... | @@ -167,12 +215,15 @@ const handleVideoPause = (post) => { | ... | @@ -167,12 +215,15 @@ const handleVideoPause = (post) => { |
| 167 | * @param {Object} currentPost - 当前播放的帖子对象 | 215 | * @param {Object} currentPost - 当前播放的帖子对象 |
| 168 | */ | 216 | */ |
| 169 | const stopOtherVideos = (currentPlayer, currentPost) => { | 217 | const stopOtherVideos = (currentPlayer, currentPost) => { |
| 170 | - // 暂停其他视频播放器 | 218 | + // 确保videoPlayers.value是一个数组 |
| 171 | - videoPlayers.value.forEach(player => { | 219 | + if (videoPlayers.value) { |
| 172 | - if (player !== currentPlayer && player.pause) { | 220 | + // 暂停其他视频播放器 |
| 173 | - player.pause(); | 221 | + videoPlayers.value.forEach(player => { |
| 174 | - } | 222 | + if (player !== currentPlayer && player.pause) { |
| 175 | - }); | 223 | + player.pause(); |
| 224 | + } | ||
| 225 | + }); | ||
| 226 | + } | ||
| 176 | 227 | ||
| 177 | // 更新其他帖子的播放状态 | 228 | // 更新其他帖子的播放状态 |
| 178 | mockPosts.value.forEach(post => { | 229 | mockPosts.value.forEach(post => { |
| ... | @@ -180,6 +231,91 @@ const stopOtherVideos = (currentPlayer, currentPost) => { | ... | @@ -180,6 +231,91 @@ const stopOtherVideos = (currentPlayer, currentPost) => { |
| 180 | post.isPlaying = false; | 231 | post.isPlaying = false; |
| 181 | } | 232 | } |
| 182 | }); | 233 | }); |
| 234 | + | ||
| 235 | + // 同时暂停所有音频播放器 | ||
| 236 | + stopAllAudio(); | ||
| 237 | +}; | ||
| 238 | + | ||
| 239 | +/** | ||
| 240 | + * 处理音频播放事件 | ||
| 241 | + * @param {Object} player - 音频播放器实例 | ||
| 242 | + * @param {Object} post - 包含音频的帖子对象 | ||
| 243 | + */ | ||
| 244 | +const handleAudioPlay = (player, post) => { | ||
| 245 | + // 停止其他音频播放 | ||
| 246 | + stopOtherAudio(player, post); | ||
| 247 | + | ||
| 248 | + // 同时暂停所有视频 | ||
| 249 | + if (videoPlayers.value) { | ||
| 250 | + videoPlayers.value.forEach(videoPlayer => { | ||
| 251 | + if (videoPlayer.pause) { | ||
| 252 | + videoPlayer.pause(); | ||
| 253 | + } | ||
| 254 | + }); | ||
| 255 | + } | ||
| 256 | + | ||
| 257 | + // 更新所有视频的播放状态为false | ||
| 258 | + mockPosts.value.forEach(p => { | ||
| 259 | + p.isPlaying = false; | ||
| 260 | + }); | ||
| 261 | +}; | ||
| 262 | + | ||
| 263 | +/** | ||
| 264 | + * 停止除当前播放器外的所有其他音频 | ||
| 265 | + * @param {Object} currentPlayer - 当前播放的音频播放器实例 | ||
| 266 | + * @param {Object} currentPost - 当前播放的帖子对象 | ||
| 267 | + */ | ||
| 268 | +const stopOtherAudio = (currentPlayer, currentPost) => { | ||
| 269 | + // 确保audioPlayers.value是一个数组 | ||
| 270 | + if (!audioPlayers.value) return; | ||
| 271 | + | ||
| 272 | + // 暂停其他音频播放器 | ||
| 273 | + audioPlayers.value.forEach(player => { | ||
| 274 | + // 只处理不是当前播放器的实例 | ||
| 275 | + if (player !== currentPlayer) { | ||
| 276 | + // 使用组件暴露的pause方法 | ||
| 277 | + if (typeof player.pause === 'function') { | ||
| 278 | + player.pause(); | ||
| 279 | + } | ||
| 280 | + // 如果没有pause方法,尝试使用togglePlay方法 | ||
| 281 | + else if (typeof player.togglePlay === 'function' && player.isPlaying && player.isPlaying()) { | ||
| 282 | + player.togglePlay(); | ||
| 283 | + } | ||
| 284 | + // 最后尝试直接操作DOM | ||
| 285 | + else if (player.$el && player.$el.querySelector('audio')) { | ||
| 286 | + const audioElement = player.$el.querySelector('audio'); | ||
| 287 | + if (audioElement) { | ||
| 288 | + audioElement.pause(); | ||
| 289 | + } | ||
| 290 | + } | ||
| 291 | + } | ||
| 292 | + }); | ||
| 293 | +}; | ||
| 294 | + | ||
| 295 | +/** | ||
| 296 | + * 停止所有音频播放 | ||
| 297 | + */ | ||
| 298 | +const stopAllAudio = () => { | ||
| 299 | + // 确保audioPlayers.value是一个数组 | ||
| 300 | + if (!audioPlayers.value) return; | ||
| 301 | + | ||
| 302 | + audioPlayers.value.forEach(player => { | ||
| 303 | + // 使用组件暴露的pause方法 | ||
| 304 | + if (typeof player.pause === 'function') { | ||
| 305 | + player.pause(); | ||
| 306 | + } | ||
| 307 | + // 如果没有pause方法,尝试使用togglePlay方法 | ||
| 308 | + else if (typeof player.togglePlay === 'function' && player.isPlaying && player.isPlaying()) { | ||
| 309 | + player.togglePlay(); | ||
| 310 | + } | ||
| 311 | + // 最后尝试直接操作DOM | ||
| 312 | + else if (player.$el && player.$el.querySelector('audio')) { | ||
| 313 | + const audioElement = player.$el.querySelector('audio'); | ||
| 314 | + if (audioElement) { | ||
| 315 | + audioElement.pause(); | ||
| 316 | + } | ||
| 317 | + } | ||
| 318 | + }); | ||
| 183 | }; | 319 | }; |
| 184 | 320 | ||
| 185 | // Mock数据 | 321 | // Mock数据 |
| ... | @@ -187,8 +323,8 @@ const mockPosts = ref([ | ... | @@ -187,8 +323,8 @@ const mockPosts = ref([ |
| 187 | { | 323 | { |
| 188 | id: 1, | 324 | id: 1, |
| 189 | user: { | 325 | user: { |
| 190 | - name: '小林', | 326 | + name: '图片预览', |
| 191 | - avatar: 'https://fastly.jsdelivr.net/npm/@vant/assets/cat.jpeg', | 327 | + avatar: 'https://cdn.ipadbiz.cn/space/816560/大国少年_FhnF8lsFMPnTDNTBlM6hYa-UFBlW.jpg', |
| 192 | time: '2小时前' | 328 | time: '2小时前' |
| 193 | }, | 329 | }, |
| 194 | content: '今天完成了React基础课程的学习,收获满满!', | 330 | content: '今天完成了React基础课程的学习,收获满满!', |
| ... | @@ -208,13 +344,13 @@ const mockPosts = ref([ | ... | @@ -208,13 +344,13 @@ const mockPosts = ref([ |
| 208 | id: 2, | 344 | id: 2, |
| 209 | user: { | 345 | user: { |
| 210 | name: '小林', | 346 | name: '小林', |
| 211 | - avatar: 'https://fastly.jsdelivr.net/npm/@vant/assets/cat.jpeg', | 347 | + avatar: 'https://cdn.ipadbiz.cn/space/816560/大国少年_FhnF8lsFMPnTDNTBlM6hYa-UFBlW.jpg', |
| 212 | time: '2小时前' | 348 | time: '2小时前' |
| 213 | }, | 349 | }, |
| 214 | content: '今天完成了React基础课程的学习,收获满满!', | 350 | content: '今天完成了React基础课程的学习,收获满满!', |
| 215 | images: [], | 351 | images: [], |
| 216 | video: 'https://cdn.ipadbiz.cn/space/lk3DmvLO02dUC2zPiFwiClDe3nKL.mp4', | 352 | video: 'https://cdn.ipadbiz.cn/space/lk3DmvLO02dUC2zPiFwiClDe3nKL.mp4', |
| 217 | - videoCover: 'https://fastly.jsdelivr.net/npm/@vant/assets/cat.jpeg', | 353 | + videoCover: 'https://cdn.ipadbiz.cn/space/816560/大国少年_FhnF8lsFMPnTDNTBlM6hYa-UFBlW.jpg', |
| 218 | isPlaying: false, | 354 | isPlaying: false, |
| 219 | audio: [], | 355 | audio: [], |
| 220 | likes: 12 | 356 | likes: 12 |
| ... | @@ -223,7 +359,7 @@ const mockPosts = ref([ | ... | @@ -223,7 +359,7 @@ const mockPosts = ref([ |
| 223 | id: 3, | 359 | id: 3, |
| 224 | user: { | 360 | user: { |
| 225 | name: '小林', | 361 | name: '小林', |
| 226 | - avatar: 'https://fastly.jsdelivr.net/npm/@vant/assets/cat.jpeg', | 362 | + avatar: 'https://cdn.ipadbiz.cn/space/816560/大国少年_FhnF8lsFMPnTDNTBlM6hYa-UFBlW.jpg', |
| 227 | time: '2小时前' | 363 | time: '2小时前' |
| 228 | }, | 364 | }, |
| 229 | content: '今天完成了React基础课程的学习,收获满满!', | 365 | content: '今天完成了React基础课程的学习,收获满满!', |
| ... | @@ -235,8 +371,8 @@ const mockPosts = ref([ | ... | @@ -235,8 +371,8 @@ const mockPosts = ref([ |
| 235 | { | 371 | { |
| 236 | title: '学习心得分享', | 372 | title: '学习心得分享', |
| 237 | artist: '小林', | 373 | artist: '小林', |
| 238 | - url: 'https://example.com/audio.mp3', | 374 | + url: 'https://cdn.ipadbiz.cn/space/816560/双手合十迎客来_Fs2W-5mnQSFL8S5CDsHho-_xcvaY.mp3', |
| 239 | - cover: 'https://fastly.jsdelivr.net/npm/@vant/assets/cat.jpeg' | 375 | + cover: 'https://cdn.ipadbiz.cn/space/816560/大国少年_FhnF8lsFMPnTDNTBlM6hYa-UFBlW.jpg' |
| 240 | } | 376 | } |
| 241 | ], | 377 | ], |
| 242 | likes: 12 | 378 | likes: 12 |
| ... | @@ -245,17 +381,39 @@ const mockPosts = ref([ | ... | @@ -245,17 +381,39 @@ const mockPosts = ref([ |
| 245 | id: 4, | 381 | id: 4, |
| 246 | user: { | 382 | user: { |
| 247 | name: '小林', | 383 | name: '小林', |
| 248 | - avatar: 'https://fastly.jsdelivr.net/npm/@vant/assets/cat.jpeg', | 384 | + avatar: 'https://cdn.ipadbiz.cn/space/816560/大国少年_FhnF8lsFMPnTDNTBlM6hYa-UFBlW.jpg', |
| 249 | time: '2小时前' | 385 | time: '2小时前' |
| 250 | }, | 386 | }, |
| 251 | content: '今天完成了React基础课程的学习,收获满满!', | 387 | content: '今天完成了React基础课程的学习,收获满满!', |
| 252 | images: [], | 388 | images: [], |
| 253 | video: 'https://cdn.ipadbiz.cn/space/lk3DmvLO02dUC2zPiFwiClDe3nKL.mp4', | 389 | video: 'https://cdn.ipadbiz.cn/space/lk3DmvLO02dUC2zPiFwiClDe3nKL.mp4', |
| 254 | - videoCover: 'https://fastly.jsdelivr.net/npm/@vant/assets/cat.jpeg', | 390 | + videoCover: 'https://cdn.ipadbiz.cn/space/816560/大国少年_FhnF8lsFMPnTDNTBlM6hYa-UFBlW.jpg', |
| 255 | isPlaying: false, | 391 | isPlaying: false, |
| 256 | audio: [], | 392 | audio: [], |
| 257 | likes: 12 | 393 | likes: 12 |
| 258 | }, | 394 | }, |
| 395 | + { | ||
| 396 | + id: 5, | ||
| 397 | + user: { | ||
| 398 | + name: '小林', | ||
| 399 | + avatar: 'https://cdn.ipadbiz.cn/space/816560/大国少年_FhnF8lsFMPnTDNTBlM6hYa-UFBlW.jpg', | ||
| 400 | + time: '2小时前' | ||
| 401 | + }, | ||
| 402 | + content: '今天完成了React基础课程的学习,收获满满!', | ||
| 403 | + images: [], | ||
| 404 | + video: '', | ||
| 405 | + videoCover: '', | ||
| 406 | + isPlaying: false, | ||
| 407 | + audio: [ | ||
| 408 | + { | ||
| 409 | + title: '学习心得分享', | ||
| 410 | + artist: '小林', | ||
| 411 | + url: 'https://cdn.ipadbiz.cn/space/816560/双手合十迎客来_Fs2W-5mnQSFL8S5CDsHho-_xcvaY.mp3', | ||
| 412 | + cover: 'https://cdn.ipadbiz.cn/space/816560/大国少年_FhnF8lsFMPnTDNTBlM6hYa-UFBlW.jpg' | ||
| 413 | + } | ||
| 414 | + ], | ||
| 415 | + likes: 12 | ||
| 416 | + }, | ||
| 259 | ]); | 417 | ]); |
| 260 | 418 | ||
| 261 | const themeVars = { | 419 | const themeVars = { |
| ... | @@ -266,10 +424,10 @@ const progress1 = ref(50); | ... | @@ -266,10 +424,10 @@ const progress1 = ref(50); |
| 266 | const progress2 = ref(76); | 424 | const progress2 = ref(76); |
| 267 | 425 | ||
| 268 | const teamAvatars = ref([ | 426 | const teamAvatars = ref([ |
| 269 | - 'https://fastly.jsdelivr.net/npm/@vant/assets/cat.jpeg', | 427 | + 'https://cdn.ipadbiz.cn/space/816560/大国少年_FhnF8lsFMPnTDNTBlM6hYa-UFBlW.jpg', |
| 270 | - 'https://fastly.jsdelivr.net/npm/@vant/assets/cat.jpeg', | 428 | + 'https://cdn.ipadbiz.cn/space/816560/大国少年_FhnF8lsFMPnTDNTBlM6hYa-UFBlW.jpg', |
| 271 | - 'https://fastly.jsdelivr.net/npm/@vant/assets/cat.jpeg', | 429 | + 'https://cdn.ipadbiz.cn/space/816560/大国少年_FhnF8lsFMPnTDNTBlM6hYa-UFBlW.jpg', |
| 272 | - 'https://fastly.jsdelivr.net/npm/@vant/assets/cat.jpeg' | 430 | + 'https://cdn.ipadbiz.cn/space/816560/大国少年_FhnF8lsFMPnTDNTBlM6hYa-UFBlW.jpg' |
| 273 | ]) | 431 | ]) |
| 274 | 432 | ||
| 275 | // 图片预览相关 | 433 | // 图片预览相关 | ... | ... |
-
Please register or login to post a comment