hookehuyr

feat(课程详情): 添加音频播放器支持并优化课程类型显示

在课程详情页中增加对音频课程的支持,添加音频播放器组件。同时,优化课程类型显示逻辑,将课程类型统一为英文标识(video/audio),并在前端显示时转换为中文。此外,调整了音频播放器的样式和布局,以提升用户体验。
...@@ -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,
......