feat(课程详情): 添加音频播放器支持并优化课程类型显示
在课程详情页中增加对音频课程的支持,添加音频播放器组件。同时,优化课程类型显示逻辑,将课程类型统一为英文标识(video/audio),并在前端显示时转换为中文。此外,调整了音频播放器的样式和布局,以提升用户体验。
Showing
4 changed files
with
30 additions
and
25 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,29 +7,27 @@ | ... | @@ -7,29 +7,27 @@ |
| 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> | ||
| 32 | - <div class="progress-bar relative h-1 bg-gray-200 rounded-full"> | ||
| 33 | <input | 31 | <input |
| 34 | type="range" | 32 | type="range" |
| 35 | :value="progress" | 33 | :value="progress" |
| ... | @@ -42,21 +40,23 @@ | ... | @@ -42,21 +40,23 @@ |
| 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" | 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" |
| 43 | ></div> | 41 | ></div> |
| 44 | </div> | 42 | </div> |
| 43 | + <span class="text-xs text-gray-400 w-12">{{ formatTime(duration) }}</span> | ||
| 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 | // 播放列表相关方法 | ... | ... |
This diff is collapsed. Click to expand it.
| ... | @@ -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