feat(课程详情): 添加音频播放器支持并优化课程类型显示
在课程详情页中增加对音频课程的支持,添加音频播放器组件。同时,优化课程类型显示逻辑,将课程类型统一为英文标识(video/audio),并在前端显示时转换为中文。此外,调整了音频播放器的样式和布局,以提升用户体验。
Showing
4 changed files
with
150 additions
and
74 deletions
| ... | @@ -11,7 +11,7 @@ | ... | @@ -11,7 +11,7 @@ |
| 11 | <van-image :src="course.thumbnail" width="120" height="100%" fit="cover" class="item-cover"> | 11 | <van-image :src="course.thumbnail" width="120" height="100%" fit="cover" class="item-cover"> |
| 12 | <div class="absolute bg-white/80 px-2 py-0.5 text-xs rounded" | 12 | <div class="absolute bg-white/80 px-2 py-0.5 text-xs rounded" |
| 13 | style="right: 0.25rem; bottom: 0.5rem"> | 13 | style="right: 0.25rem; bottom: 0.5rem"> |
| 14 | - {{ course.type }} | 14 | + {{ course.type === 'video' ? '视频' : '音频' }} |
| 15 | </div> | 15 | </div> |
| 16 | </van-image> | 16 | </van-image> |
| 17 | </div> | 17 | </div> | ... | ... |
| ... | @@ -7,56 +7,56 @@ | ... | @@ -7,56 +7,56 @@ |
| 7 | --> | 7 | --> |
| 8 | <template> | 8 | <template> |
| 9 | <!-- 音频播放器主容器 --> | 9 | <!-- 音频播放器主容器 --> |
| 10 | - <div class="audio-player bg-white rounded-lg shadow-xl overflow-hidden max-w-md mx-auto p-4"> | 10 | + <div class="audio-player bg-white rounded-lg shadow-xl overflow-hidden max-w-md mx-auto p-2"> |
| 11 | <!-- 封面与歌曲信息 --> | 11 | <!-- 封面与歌曲信息 --> |
| 12 | - <div class="flex flex-col items-center mb-6"> | 12 | + <div class="flex flex-col items-center mb-4"> |
| 13 | <!-- 歌曲封面 --> | 13 | <!-- 歌曲封面 --> |
| 14 | - <div class="w-48 h-48 rounded-lg overflow-hidden mb-4"> | 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" alt="封面" class="w-full h-full object-cover"> |
| 16 | </div> | 16 | </div> |
| 17 | 17 | ||
| 18 | <!-- 歌曲信息 --> | 18 | <!-- 歌曲信息 --> |
| 19 | <div class="text-center"> | 19 | <div class="text-center"> |
| 20 | - <h3 class="text-lg font-medium">{{ currentSong.title }}</h3> | 20 | + <h3 class="text-base font-medium">{{ currentSong.title }}</h3> |
| 21 | - <p class="text-sm 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"> |
| 28 | - <div class="flex items-center justify-between text-xs text-gray-400 mb-2"> | 28 | + <div class="flex items-center space-x-4"> |
| 29 | - <span>{{ formatTime(currentTime) }}</span> | 29 | + <span class="text-xs text-gray-400 w-12 text-right">{{ formatTime(currentTime) }}</span> |
| 30 | - <span>{{ formatTime(duration) }}</span> | 30 | + <div class="progress-bar relative h-1 bg-gray-200 rounded-full flex-1"> |
| 31 | - </div> | 31 | + <input |
| 32 | - <div class="progress-bar relative h-1 bg-gray-200 rounded-full"> | 32 | + type="range" |
| 33 | - <input | 33 | + :value="progress" |
| 34 | - type="range" | 34 | + @input="handleProgressChange" |
| 35 | - :value="progress" | 35 | + @change="seekTo" |
| 36 | - @input="handleProgressChange" | 36 | + class="w-full absolute inset-0 appearance-none bg-transparent cursor-pointer" |
| 37 | - @change="seekTo" | 37 | + > |
| 38 | - class="w-full absolute inset-0 appearance-none bg-transparent cursor-pointer" | 38 | + <div |
| 39 | - > | 39 | + :style="{ width: `${progress}%` }" |
| 40 | - <div | 40 | + class="progress-track absolute left-0 top-0 h-full rounded-full bg-gradient-to-r from-blue-500 to-purple-500 transition-all" |
| 41 | - :style="{ width: `${progress}%` }" | 41 | + ></div> |
| 42 | - class="progress-track absolute left-0 top-0 h-full rounded-full bg-gradient-to-r from-blue-500 to-purple-500 transition-all" | 42 | + </div> |
| 43 | - ></div> | 43 | + <span class="text-xs text-gray-400 w-12">{{ formatTime(duration) }}</span> |
| 44 | </div> | 44 | </div> |
| 45 | </div> | 45 | </div> |
| 46 | 46 | ||
| 47 | <!-- 播放控制按钮组:上一首、播放/暂停、下一首 --> | 47 | <!-- 播放控制按钮组:上一首、播放/暂停、下一首 --> |
| 48 | - <div class="flex items-center space-x-16 mt-6" style="justify-content: space-evenly;"> | 48 | + <div class="flex items-center space-x-12 mt-4" style="justify-content: space-evenly;"> |
| 49 | <button | 49 | <button |
| 50 | @click="prevSong" | 50 | @click="prevSong" |
| 51 | - class="w-14 h-14 flex items-center justify-center rounded-full bg-gray-100 hover:bg-gray-200 transition-colors" | 51 | + class="w-10 h-10 flex items-center justify-center rounded-full bg-gray-100 hover:bg-gray-200 transition-colors" |
| 52 | > | 52 | > |
| 53 | - <font-awesome-icon icon="backward-step" class="text-2xl text-gray-600" /> | 53 | + <font-awesome-icon icon="backward-step" class="text-xl text-gray-600" /> |
| 54 | </button> | 54 | </button> |
| 55 | <button | 55 | <button |
| 56 | @click="togglePlay" | 56 | @click="togglePlay" |
| 57 | :class="{'paused': !isPlaying, 'opacity-50 cursor-not-allowed': isLoading}" | 57 | :class="{'paused': !isPlaying, 'opacity-50 cursor-not-allowed': isLoading}" |
| 58 | :disabled="isLoading" | 58 | :disabled="isLoading" |
| 59 | - class="w-14 h-14 flex items-center justify-center rounded-full bg-blue-500 hover:bg-blue-600 transition-colors shadow-lg" | 59 | + class="w-12 h-12 flex items-center justify-center rounded-full bg-blue-500 hover:bg-blue-600 transition-colors shadow-lg" |
| 60 | > | 60 | > |
| 61 | <font-awesome-icon | 61 | <font-awesome-icon |
| 62 | :icon="['fas' , isPlaying ? 'pause' : 'play']" | 62 | :icon="['fas' , isPlaying ? 'pause' : 'play']" |
| ... | @@ -66,9 +66,9 @@ | ... | @@ -66,9 +66,9 @@ |
| 66 | </button> | 66 | </button> |
| 67 | <button | 67 | <button |
| 68 | @click="nextSong" | 68 | @click="nextSong" |
| 69 | - class="w-14 h-14 flex items-center justify-center rounded-full bg-gray-100 hover:bg-gray-200 transition-colors" | 69 | + class="w-10 h-10 flex items-center justify-center rounded-full bg-gray-100 hover:bg-gray-200 transition-colors" |
| 70 | > | 70 | > |
| 71 | - <font-awesome-icon icon="forward-step" class="text-2xl text-gray-600" /> | 71 | + <font-awesome-icon icon="forward-step" class="text-xl text-gray-600" /> |
| 72 | </button> | 72 | </button> |
| 73 | </div> | 73 | </div> |
| 74 | 74 | ||
| ... | @@ -112,7 +112,7 @@ | ... | @@ -112,7 +112,7 @@ |
| 112 | <div class="text-sm text-gray-500">{{ song.artist }}</div> | 112 | <div class="text-sm text-gray-500">{{ song.artist }}</div> |
| 113 | </div> | 113 | </div> |
| 114 | <font-awesome-icon | 114 | <font-awesome-icon |
| 115 | - v-if="index === currentIndex" | 115 | + v-if="index === currentIndex && isPlaying" |
| 116 | icon="volume-up" | 116 | icon="volume-up" |
| 117 | class="text-blue-500 ml-2" | 117 | class="text-blue-500 ml-2" |
| 118 | /> | 118 | /> |
| ... | @@ -281,8 +281,13 @@ watch(() => props.songs, () => { | ... | @@ -281,8 +281,13 @@ watch(() => props.songs, () => { |
| 281 | 281 | ||
| 282 | // 组件卸载时清理事件监听 | 282 | // 组件卸载时清理事件监听 |
| 283 | onUnmounted(() => { | 283 | onUnmounted(() => { |
| 284 | - audio.value?.removeEventListener('timeupdate', updateProgress) | 284 | + if (audio.value) { |
| 285 | - audio.value?.removeEventListener('ended', handleEnded) | 285 | + audio.value.pause(); |
| 286 | + audio.value.removeEventListener('timeupdate', updateProgress); | ||
| 287 | + audio.value.removeEventListener('ended', handleEnded); | ||
| 288 | + audio.value = null; | ||
| 289 | + } | ||
| 290 | + isPlaying.value = false; | ||
| 286 | }) | 291 | }) |
| 287 | 292 | ||
| 288 | // 播放列表相关方法 | 293 | // 播放列表相关方法 | ... | ... |
| ... | @@ -8,7 +8,7 @@ | ... | @@ -8,7 +8,7 @@ |
| 8 | <!-- 固定区域:视频播放和标签页 --> | 8 | <!-- 固定区域:视频播放和标签页 --> |
| 9 | <div class="fixed top-0 left-0 right-0 z-10 top-wrapper"> | 9 | <div class="fixed top-0 left-0 right-0 z-10 top-wrapper"> |
| 10 | <!-- 视频播放区域 --> | 10 | <!-- 视频播放区域 --> |
| 11 | - <div class="w-full bg-black relative"> | 11 | + <div v-if="course.type === 'video'" class="w-full bg-black relative"> |
| 12 | <!-- 视频封面和播放按钮 --> | 12 | <!-- 视频封面和播放按钮 --> |
| 13 | <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;"> |
| 14 | <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" /> |
| ... | @@ -25,6 +25,10 @@ | ... | @@ -25,6 +25,10 @@ |
| 25 | <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" |
| 26 | @onPlay="handleVideoPlay" @onPause="handleVideoPause" /> | 26 | @onPlay="handleVideoPlay" @onPause="handleVideoPause" /> |
| 27 | </div> | 27 | </div> |
| 28 | + <div v-if="course.type === 'audio'" class="w-full relative" style="border-bottom: 1px solid #F3F4F6;"> | ||
| 29 | + <!-- 音频播放器 --> | ||
| 30 | + <AudioPlayer :songs="audioList" /> | ||
| 31 | + </div> | ||
| 28 | <!-- 标签页区域 --> | 32 | <!-- 标签页区域 --> |
| 29 | <div class="px-4 py-3 bg-white"> | 33 | <div class="px-4 py-3 bg-white"> |
| 30 | <van-tabs v-model:active="activeTab" sticky animated swipeable shrink @change="handleTabChange"> | 34 | <van-tabs v-model:active="activeTab" sticky animated swipeable shrink @change="handleTabChange"> |
| ... | @@ -38,7 +42,8 @@ | ... | @@ -38,7 +42,8 @@ |
| 38 | </div> | 42 | </div> |
| 39 | 43 | ||
| 40 | <!-- 滚动区域:介绍和评论内容 --> | 44 | <!-- 滚动区域:介绍和评论内容 --> |
| 41 | - <div class="overflow-y-auto flex-1" :style="{paddingTop: topWrapperHeight, height: 'calc(100vh - ' + topWrapperHeight + ')'}"> | 45 | + <div class="overflow-y-auto flex-1" |
| 46 | + :style="{ paddingTop: topWrapperHeight, height: 'calc(100vh - ' + topWrapperHeight + ')' }"> | ||
| 42 | <div id="intro" class="py-4 px-4"> | 47 | <div id="intro" class="py-4 px-4"> |
| 43 | <h1 class="text-lg font-bold mb-2">{{ course.title }}</h1> | 48 | <h1 class="text-lg font-bold mb-2">{{ course.title }}</h1> |
| 44 | <div class="text-gray-500 text-sm flex items-center gap-2"> | 49 | <div class="text-gray-500 text-sm flex items-center gap-2"> |
| ... | @@ -56,20 +61,19 @@ | ... | @@ -56,20 +61,19 @@ |
| 56 | <div class="text-gray-500 cursor-pointer text-sm" @click="showCommentPopup = true">查看更多</div> | 61 | <div class="text-gray-500 cursor-pointer text-sm" @click="showCommentPopup = true">查看更多</div> |
| 57 | </div> | 62 | </div> |
| 58 | <!-- 显示前三条评论 --> | 63 | <!-- 显示前三条评论 --> |
| 59 | - <div v-for="comment in comments.slice(0, 3)" :key="comment.id" class="border-b border-gray-100 last:border-b-0 py-4"> | 64 | + <div v-for="comment in comments.slice(0, 3)" :key="comment.id" |
| 65 | + class="border-b border-gray-100 last:border-b-0 py-4"> | ||
| 60 | <div class="flex"> | 66 | <div class="flex"> |
| 61 | - <img :src="comment.avatar" class="w-10 h-10 rounded-full flex-shrink-0" style="margin-right: 0.5rem;" /> | 67 | + <img :src="comment.avatar" class="w-10 h-10 rounded-full flex-shrink-0" |
| 68 | + style="margin-right: 0.5rem;" /> | ||
| 62 | <div class="flex-1 ml-3"> | 69 | <div class="flex-1 ml-3"> |
| 63 | <div class="flex justify-between items-center mb-1"> | 70 | <div class="flex justify-between items-center mb-1"> |
| 64 | <span class="font-medium text-gray-900">{{ comment.username }}</span> | 71 | <span class="font-medium text-gray-900">{{ comment.username }}</span> |
| 65 | <div class="flex items-center space-x-1"> | 72 | <div class="flex items-center space-x-1"> |
| 66 | <span class="text-sm text-gray-500">{{ comment.likes }}</span> | 73 | <span class="text-sm text-gray-500">{{ comment.likes }}</span> |
| 67 | - <van-icon | 74 | + <van-icon :name="comment.isLiked ? 'like' : 'like-o'" |
| 68 | - :name="comment.isLiked ? 'like' : 'like-o'" | 75 | + :class="{ 'text-red-500': comment.isLiked, 'text-gray-400': !comment.isLiked }" |
| 69 | - :class="{'text-red-500': comment.isLiked, 'text-gray-400': !comment.isLiked}" | 76 | + @click="toggleLike(comment)" class="text-lg cursor-pointer" /> |
| 70 | - @click="toggleLike(comment)" | ||
| 71 | - class="text-lg cursor-pointer" | ||
| 72 | - /> | ||
| 73 | </div> | 77 | </div> |
| 74 | </div> | 78 | </div> |
| 75 | <p class="text-gray-700 text-sm mb-1">{{ comment.content }}</p> | 79 | <p class="text-gray-700 text-sm mb-1">{{ comment.content }}</p> |
| ... | @@ -77,7 +81,8 @@ | ... | @@ -77,7 +81,8 @@ |
| 77 | </div> | 81 | </div> |
| 78 | </div> | 82 | </div> |
| 79 | </div> | 83 | </div> |
| 80 | - <van-popup v-model:show="showCommentPopup" position="bottom" round closeable safe-area-inset-bottom style="height: 80%"> | 84 | + <van-popup v-model:show="showCommentPopup" position="bottom" round closeable safe-area-inset-bottom |
| 85 | + style="height: 80%"> | ||
| 81 | <div class="flex flex-col h-full"> | 86 | <div class="flex flex-col h-full"> |
| 82 | <!-- 固定头部 --> | 87 | <!-- 固定头部 --> |
| 83 | <div class="flex-none px-4 py-3 border-b bg-white sticky top-0 z-10"> | 88 | <div class="flex-none px-4 py-3 border-b bg-white sticky top-0 z-10"> |
| ... | @@ -87,20 +92,22 @@ | ... | @@ -87,20 +92,22 @@ |
| 87 | <!-- 可滚动的评论列表 --> | 92 | <!-- 可滚动的评论列表 --> |
| 88 | <div class="flex-1 overflow-y-auto"> | 93 | <div class="flex-1 overflow-y-auto"> |
| 89 | <div class="px-4 py-2 pb-16"> | 94 | <div class="px-4 py-2 pb-16"> |
| 90 | - <div v-for="comment in comments" :key="comment.id" class="border-b border-gray-100 last:border-b-0 py-4"> | 95 | + <div v-for="comment in comments" :key="comment.id" |
| 96 | + class="border-b border-gray-100 last:border-b-0 py-4"> | ||
| 91 | <div class="flex"> | 97 | <div class="flex"> |
| 92 | - <img :src="comment.avatar" class="w-10 h-10 rounded-full flex-shrink-0" style="margin-right: 0.5rem;" /> | 98 | + <img :src="comment.avatar" class="w-10 h-10 rounded-full flex-shrink-0" |
| 99 | + style="margin-right: 0.5rem;" /> | ||
| 93 | <div class="flex-1 ml-3"> | 100 | <div class="flex-1 ml-3"> |
| 94 | <div class="flex justify-between items-center mb-1"> | 101 | <div class="flex justify-between items-center mb-1"> |
| 95 | - <span class="font-medium text-gray-900">{{ comment.username }}</span> | 102 | + <span class="font-medium text-gray-900">{{ comment.username |
| 103 | + }}</span> | ||
| 96 | <div class="flex items-center space-x-1"> | 104 | <div class="flex items-center space-x-1"> |
| 97 | - <span class="text-sm text-gray-500">{{ comment.likes }}</span> | 105 | + <span class="text-sm text-gray-500">{{ comment.likes }}</span> |
| 98 | - <van-icon | 106 | + |
| 99 | - :name="comment.isLiked ? 'like' : 'like-o'" | 107 | + <van-icon :name="comment.isLiked ? 'like' : 'like-o'" |
| 100 | - :class="{'text-red-500': comment.isLiked, 'text-gray-400': !comment.isLiked}" | 108 | + :class="{ 'text-red-500': comment.isLiked, 'text-gray-400': !comment.isLiked }" |
| 101 | @click="toggleLike(comment)" | 109 | @click="toggleLike(comment)" |
| 102 | - class="text-lg cursor-pointer" | 110 | + class="text-lg cursor-pointer" /> |
| 103 | - /> | ||
| 104 | </div> | 111 | </div> |
| 105 | </div> | 112 | </div> |
| 106 | <p class="text-gray-700 text-sm mb-1">{{ comment.content }}</p> | 113 | <p class="text-gray-700 text-sm mb-1">{{ comment.content }}</p> |
| ... | @@ -114,19 +121,9 @@ | ... | @@ -114,19 +121,9 @@ |
| 114 | <!-- 固定底部输入框 --> | 121 | <!-- 固定底部输入框 --> |
| 115 | <div class="flex-none border-t px-4 py-2 bg-white sticky bottom-0 z-10"> | 122 | <div class="flex-none border-t px-4 py-2 bg-white sticky bottom-0 z-10"> |
| 116 | <div class="flex items-center space-x-2"> | 123 | <div class="flex items-center space-x-2"> |
| 117 | - <van-field | 124 | + <van-field v-model="popupComment" rows="1" autosize type="textarea" |
| 118 | - v-model="popupComment" | 125 | + placeholder="请输入评论" class="flex-1 bg-gray-100 rounded-lg" /> |
| 119 | - rows="1" | 126 | + <van-button type="primary" size="small" @click="submitPopupComment">发送</van-button> |
| 120 | - autosize | ||
| 121 | - type="textarea" | ||
| 122 | - placeholder="请输入评论" | ||
| 123 | - class="flex-1 bg-gray-100 rounded-lg" | ||
| 124 | - /> | ||
| 125 | - <van-button | ||
| 126 | - type="primary" | ||
| 127 | - size="small" | ||
| 128 | - @click="submitPopupComment" | ||
| 129 | - >发送</van-button> | ||
| 130 | </div> | 127 | </div> |
| 131 | </div> | 128 | </div> |
| 132 | </div> | 129 | </div> |
| ... | @@ -135,15 +132,19 @@ | ... | @@ -135,15 +132,19 @@ |
| 135 | </div> | 132 | </div> |
| 136 | 133 | ||
| 137 | <!-- 底部操作栏 --> | 134 | <!-- 底部操作栏 --> |
| 138 | - <div class="fixed bottom-0 left-0 right-0 bg-white border-t px-4 py-2 flex items-center space-x-4 bottom-wrapper"> | 135 | + <div |
| 139 | - <div class="flex-none flex flex-col items-center gap-1 cursor-pointer active:opacity-80" @click="showCatalog = true"> | 136 | + class="fixed bottom-0 left-0 right-0 bg-white border-t px-4 py-2 flex items-center space-x-4 bottom-wrapper"> |
| 137 | + <div class="flex-none flex flex-col items-center gap-1 cursor-pointer active:opacity-80" | ||
| 138 | + @click="showCatalog = true"> | ||
| 140 | <van-icon name="bars" class="text-lg text-gray-600" /> | 139 | <van-icon name="bars" class="text-lg text-gray-600" /> |
| 141 | <span class="text-xs text-gray-600">课程目录</span> | 140 | <span class="text-xs text-gray-600">课程目录</span> |
| 142 | </div> | 141 | </div> |
| 143 | <div class="flex-grow flex-1 min-w-0"> | 142 | <div class="flex-grow flex-1 min-w-0"> |
| 144 | - <van-field v-model="newComment" rows="1" autosize type="textarea" placeholder="请输入留言" class="bg-gray-100 rounded-lg !p-0"> | 143 | + <van-field v-model="newComment" rows="1" autosize type="textarea" placeholder="请输入留言" |
| 144 | + class="bg-gray-100 rounded-lg !p-0"> | ||
| 145 | <template #input> | 145 | <template #input> |
| 146 | - <textarea v-model="newComment" rows="1" placeholder="请输入留言" class="w-full h-full bg-transparent outline-none resize-none" /> | 146 | + <textarea v-model="newComment" rows="1" placeholder="请输入留言" |
| 147 | + class="w-full h-full bg-transparent outline-none resize-none" /> | ||
| 147 | </template> | 148 | </template> |
| 148 | </van-field> | 149 | </van-field> |
| 149 | </div> | 150 | </div> |
| ... | @@ -158,6 +159,7 @@ import { ref, onMounted, nextTick } from 'vue'; | ... | @@ -158,6 +159,7 @@ import { ref, onMounted, nextTick } from 'vue'; |
| 158 | import { useRoute } from 'vue-router'; | 159 | import { useRoute } from 'vue-router'; |
| 159 | import { useTitle } from '@vueuse/core'; | 160 | import { useTitle } from '@vueuse/core'; |
| 160 | import VideoPlayer from '@/components/ui/VideoPlayer.vue'; | 161 | import VideoPlayer from '@/components/ui/VideoPlayer.vue'; |
| 162 | +import AudioPlayer from '@/components/ui/AudioPlayer.vue'; | ||
| 161 | 163 | ||
| 162 | const route = useRoute(); | 164 | const route = useRoute(); |
| 163 | const course = ref(null); | 165 | const course = ref(null); |
| ... | @@ -245,6 +247,66 @@ const comments = ref([ | ... | @@ -245,6 +247,66 @@ const comments = ref([ |
| 245 | } | 247 | } |
| 246 | ]); | 248 | ]); |
| 247 | 249 | ||
| 250 | +// 测试音频数据 | ||
| 251 | +const audioList = ref([ | ||
| 252 | + { | ||
| 253 | + id: 1, | ||
| 254 | + title: '示例音频 1', | ||
| 255 | + artist: '演唱者 1', | ||
| 256 | + cover: 'https://cdn.ipadbiz.cn/mlaj/images/zMRLZh40kms.jpg', | ||
| 257 | + url: 'https://img.tukuppt.com/newpreview_music/09/03/95/5c8af46b01eb138909.mp3' | ||
| 258 | + }, | ||
| 259 | + { | ||
| 260 | + id: 2, | ||
| 261 | + title: '示例音频 2', | ||
| 262 | + artist: '演唱者 2', | ||
| 263 | + cover: 'https://cdn.ipadbiz.cn/mlaj/images/zMRLZh40kms.jpg', | ||
| 264 | + url: 'https://img.tukuppt.com/newpreview_music/08/99/00/5c88d4a8d1f5745026.mp3' | ||
| 265 | + }, | ||
| 266 | + { | ||
| 267 | + id: 3, | ||
| 268 | + title: '示例音频 3', | ||
| 269 | + artist: '演唱者 3', | ||
| 270 | + cover: 'https://cdn.ipadbiz.cn/mlaj/images/zMRLZh40kms.jpg', | ||
| 271 | + url: 'https://img.tukuppt.com/newpreview_music/09/03/95/5c8af46b01eb138909.mp3' | ||
| 272 | + }, | ||
| 273 | + { | ||
| 274 | + id: 4, | ||
| 275 | + title: '示例音频 4', | ||
| 276 | + artist: '演唱者 4', | ||
| 277 | + cover: 'https://cdn.ipadbiz.cn/mlaj/images/zMRLZh40kms.jpg', | ||
| 278 | + url: 'https://img.tukuppt.com/newpreview_music/09/03/72/5c8ad96fbf47328809.mp3' | ||
| 279 | + }, | ||
| 280 | + { | ||
| 281 | + id: 5, | ||
| 282 | + title: '示例音频 5', | ||
| 283 | + artist: '演唱者 5', | ||
| 284 | + cover: 'https://cdn.ipadbiz.cn/mlaj/images/zMRLZh40kms.jpg', | ||
| 285 | + url: 'https://img.tukuppt.com/newpreview_music/09/03/95/5c8af46b01eb138909.mp3' | ||
| 286 | + }, | ||
| 287 | + { | ||
| 288 | + id: 6, | ||
| 289 | + title: '示例音频 6', | ||
| 290 | + artist: '演唱者 6', | ||
| 291 | + cover: 'https://cdn.ipadbiz.cn/mlaj/images/zMRLZh40kms.jpg', | ||
| 292 | + url: 'https://img.tukuppt.com/newpreview_music/09/03/72/5c8ad96fbf47328809.mp3' | ||
| 293 | + }, | ||
| 294 | + { | ||
| 295 | + id: 7, | ||
| 296 | + title: '示例音频 7', | ||
| 297 | + artist: '演唱者 7', | ||
| 298 | + cover: 'https://cdn.ipadbiz.cn/mlaj/images/zMRLZh40kms.jpg', | ||
| 299 | + url: 'https://img.tukuppt.com/newpreview_music/09/03/95/5c8af46b01eb138909.mp3' | ||
| 300 | + }, | ||
| 301 | + { | ||
| 302 | + id: 8, | ||
| 303 | + title: '示例音频 8', | ||
| 304 | + artist: '演唱者 8', | ||
| 305 | + cover: 'https://cdn.ipadbiz.cn/mlaj/images/zMRLZh40kms.jpg', | ||
| 306 | + url: 'https://img.tukuppt.com/newpreview_music/09/03/72/5c8ad96fbf47328809.mp3' | ||
| 307 | + }, | ||
| 308 | +]); | ||
| 309 | + | ||
| 248 | // 设置页面标题 | 310 | // 设置页面标题 |
| 249 | useTitle('学习详情'); | 311 | useTitle('学习详情'); |
| 250 | 312 | ||
| ... | @@ -294,8 +356,17 @@ onMounted(() => { | ... | @@ -294,8 +356,17 @@ onMounted(() => { |
| 294 | type: '视频课程', | 356 | type: '视频课程', |
| 295 | studyCount: 1896, | 357 | studyCount: 1896, |
| 296 | cover: 'https://fastly.jsdelivr.net/npm/@vant/assets/cat.jpeg', | 358 | cover: 'https://fastly.jsdelivr.net/npm/@vant/assets/cat.jpeg', |
| 297 | - date: '2024-12-04' | 359 | + date: '2024-12-04', |
| 360 | + type: 'video', | ||
| 298 | }; | 361 | }; |
| 362 | + | ||
| 363 | + // TODO: 模拟数据音频和视频显示 | ||
| 364 | + console.warn(courseId); | ||
| 365 | + if (courseId == '2') { | ||
| 366 | + course.value.type = 'audio' | ||
| 367 | + } else { | ||
| 368 | + course.value.type = 'video' | ||
| 369 | + } | ||
| 299 | } | 370 | } |
| 300 | }) | 371 | }) |
| 301 | 372 | ... | ... |
| ... | @@ -100,7 +100,7 @@ const columnCourses = ref([ | ... | @@ -100,7 +100,7 @@ const columnCourses = ref([ |
| 100 | { | 100 | { |
| 101 | id: 1, | 101 | id: 1, |
| 102 | title: "考前赋能冥想", | 102 | title: "考前赋能冥想", |
| 103 | - type: "视频", | 103 | + type: "video", |
| 104 | thumbnail: "https://cdn.ipadbiz.cn/mlaj/images/zMRLZh40kms.jpg", | 104 | thumbnail: "https://cdn.ipadbiz.cn/mlaj/images/zMRLZh40kms.jpg", |
| 105 | progress: 100, | 105 | progress: 100, |
| 106 | duration: 1200, // 20分钟 | 106 | duration: 1200, // 20分钟 |
| ... | @@ -109,7 +109,7 @@ const columnCourses = ref([ | ... | @@ -109,7 +109,7 @@ const columnCourses = ref([ |
| 109 | { | 109 | { |
| 110 | id: 2, | 110 | id: 2, |
| 111 | title: "开学礼·让的智慧·心法老师·20241001(上)", | 111 | title: "开学礼·让的智慧·心法老师·20241001(上)", |
| 112 | - type: "视频", | 112 | + type: "audio", |
| 113 | thumbnail: "https://cdn.ipadbiz.cn/mlaj/images/zMRLZh40kms.jpg", | 113 | thumbnail: "https://cdn.ipadbiz.cn/mlaj/images/zMRLZh40kms.jpg", |
| 114 | progress: 1, | 114 | progress: 1, |
| 115 | duration: 3600, // 1小时 | 115 | duration: 3600, // 1小时 |
| ... | @@ -118,7 +118,7 @@ const columnCourses = ref([ | ... | @@ -118,7 +118,7 @@ const columnCourses = ref([ |
| 118 | { | 118 | { |
| 119 | id: 1, | 119 | id: 1, |
| 120 | title: "考前赋能冥想", | 120 | title: "考前赋能冥想", |
| 121 | - type: "视频", | 121 | + type: "video", |
| 122 | thumbnail: "https://cdn.ipadbiz.cn/mlaj/images/zMRLZh40kms.jpg", | 122 | thumbnail: "https://cdn.ipadbiz.cn/mlaj/images/zMRLZh40kms.jpg", |
| 123 | progress: 100, | 123 | progress: 100, |
| 124 | duration: 1200, // 20分钟 | 124 | duration: 1200, // 20分钟 |
| ... | @@ -127,7 +127,7 @@ const columnCourses = ref([ | ... | @@ -127,7 +127,7 @@ const columnCourses = ref([ |
| 127 | { | 127 | { |
| 128 | id: 2, | 128 | id: 2, |
| 129 | title: "开学礼·让的智慧·心法老师·20241001(上)", | 129 | title: "开学礼·让的智慧·心法老师·20241001(上)", |
| 130 | - type: "视频", | 130 | + type: "video", |
| 131 | thumbnail: "https://cdn.ipadbiz.cn/mlaj/images/zMRLZh40kms.jpg", | 131 | thumbnail: "https://cdn.ipadbiz.cn/mlaj/images/zMRLZh40kms.jpg", |
| 132 | progress: 1, | 132 | progress: 1, |
| 133 | duration: 3600, // 1小时 | 133 | duration: 3600, // 1小时 |
| ... | @@ -139,7 +139,7 @@ const singleCourses = ref([ | ... | @@ -139,7 +139,7 @@ const singleCourses = ref([ |
| 139 | { | 139 | { |
| 140 | id: 3, | 140 | id: 3, |
| 141 | title: "冬季课·影响孩子命运的家族六要素·心法老师20250207", | 141 | title: "冬季课·影响孩子命运的家族六要素·心法老师20250207", |
| 142 | - type: "视频", | 142 | + type: "video", |
| 143 | thumbnail: "https://cdn.ipadbiz.cn/mlaj/images/zMRLZh40kms.jpg", | 143 | thumbnail: "https://cdn.ipadbiz.cn/mlaj/images/zMRLZh40kms.jpg", |
| 144 | progress: 1, | 144 | progress: 1, |
| 145 | duration: 3600, | 145 | duration: 3600, | ... | ... |
-
Please register or login to post a comment