hookehuyr

refactor(AudioPlayer): 优化音频播放器UI布局和样式

调整音频播放器的布局结构,改进封面、进度条和按钮的样式,提升用户体验
...@@ -11,7 +11,7 @@ VITE_PROXY_PREFIX = /srv/ ...@@ -11,7 +11,7 @@ VITE_PROXY_PREFIX = /srv/
11 VITE_OUTDIR = mlaj 11 VITE_OUTDIR = mlaj
12 12
13 # 是否开启调试 13 # 是否开启调试
14 -VITE_CONSOLE = 1 14 +VITE_CONSOLE = 0
15 15
16 # appID相关 16 # appID相关
17 VITE_APPID=微信appID 17 VITE_APPID=微信appID
......
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-04-07 16:41:23 4 + * @LastEditTime: 2025-04-07 17:20:54
5 * @FilePath: /mlaj/src/components/ui/audioPlayer.vue 5 * @FilePath: /mlaj/src/components/ui/audioPlayer.vue
6 * @Description: 音频播放器组件,支持播放控制、进度条调节、音量控制、播放列表等功能 6 * @Description: 音频播放器组件,支持播放控制、进度条调节、音量控制、播放列表等功能
7 --> 7 -->
8 <template> 8 <template>
9 <!-- 音频播放器主容器 --> 9 <!-- 音频播放器主容器 -->
10 - <div class="audio-player bg-white rounded-lg shadow-xl overflow-hidden max-w-3xl mx-auto p-4 sm:p-6"> 10 + <div class="audio-player bg-white rounded-lg shadow-xl overflow-hidden max-w-md mx-auto p-4">
11 - <!-- 封面与控制区:显示当前播放歌曲的封面、标题、艺术家和播放控制按钮 --> 11 + <!-- 封面与歌曲信息 -->
12 - <div class="flex flex-col sm:flex-row items-center space-y-4 sm:space-y-0 sm:space-x-4"> 12 + <div class="flex flex-col items-center mb-6">
13 <!-- 歌曲封面 --> 13 <!-- 歌曲封面 -->
14 - <div class="w-32 h-32 sm:w-24 sm:h-24 rounded-lg overflow-hidden"> 14 + <div class="w-48 h-48 rounded-lg overflow-hidden mb-4">
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="flex-1 text-center sm:text-left"> 19 + <div class="text-center">
20 - <h3 class="text-xl sm:text-lg font-medium">{{ currentSong.title }}</h3> 20 + <h3 class="text-lg font-medium">{{ currentSong.title }}</h3>
21 <p class="text-sm text-gray-500">{{ currentSong.artist }}</p> 21 <p class="text-sm text-gray-500">{{ currentSong.artist }}</p>
22 </div> 22 </div>
23 23
24 - <!-- 播放控制按钮组:上一首、播放/暂停、下一首 -->
25 - <div class="flex items-center justify-center space-x-8 sm:space-x-6 w-full sm:w-auto">
26 - <button
27 - @click="prevSong"
28 - class="w-12 h-12 sm:w-10 sm:h-10 flex items-center justify-center rounded-full bg-gray-100 hover:bg-gray-200 transition-colors"
29 - >
30 - <font-awesome-icon icon="backward-step" class="text-xl text-gray-600" />
31 - </button>
32 - <button
33 - @click="togglePlay"
34 - :class="{'paused': !isPlaying, 'opacity-50 cursor-not-allowed': isLoading}"
35 - :disabled="isLoading"
36 - class="w-16 h-16 sm:w-14 sm:h-14 flex items-center justify-center rounded-full bg-blue-500 hover:bg-blue-600 transition-colors shadow-lg"
37 - >
38 - <font-awesome-icon
39 - :icon="['fas' , isPlaying ? 'pause' : 'play']"
40 - :class="{ 'fa-spin': isLoading }"
41 - class="text-3xl"
42 - />
43 - </button>
44 - <button
45 - @click="nextSong"
46 - class="w-12 h-12 sm:w-10 sm:h-10 flex items-center justify-center rounded-full bg-gray-100 hover:bg-gray-200 transition-colors"
47 - >
48 - <font-awesome-icon icon="forward-step" class="text-xl text-gray-600" />
49 - </button>
50 - </div>
51 </div> 24 </div>
52 25
53 <!-- 进度条与时间:显示当前播放时间、总时长和可拖动的进度条 --> 26 <!-- 进度条与时间:显示当前播放时间、总时长和可拖动的进度条 -->
54 - <div class="mt-4"> 27 + <div class="mt-4 mb-6">
55 - <div class="flex items-center justify-between text-sm text-gray-500"> 28 + <div class="flex items-center justify-between text-xs text-gray-400 mb-2">
56 <span>{{ formatTime(currentTime) }}</span> 29 <span>{{ formatTime(currentTime) }}</span>
57 <span>{{ formatTime(duration) }}</span> 30 <span>{{ formatTime(duration) }}</span>
58 </div> 31 </div>
59 - 32 + <div class="progress-bar relative h-1 bg-gray-200 rounded-full">
60 - <div class="progress-bar relative mt-2">
61 <input 33 <input
62 type="range" 34 type="range"
63 :value="progress" 35 :value="progress"
64 @input="handleProgressChange" 36 @input="handleProgressChange"
65 @change="seekTo" 37 @change="seekTo"
66 - class="w-full appearance-none bg-gray-200 rounded-full h-1.5 cursor-pointer" 38 + class="w-full absolute inset-0 appearance-none bg-transparent cursor-pointer"
67 > 39 >
68 <div 40 <div
69 :style="{ width: `${progress}%` }" 41 :style="{ width: `${progress}%` }"
...@@ -72,45 +44,80 @@ ...@@ -72,45 +44,80 @@
72 </div> 44 </div>
73 </div> 45 </div>
74 46
75 - <!-- 音量与设置:音量控制滑块和播放列表按钮 --> 47 + <!-- 播放控制按钮组:上一首、播放/暂停、下一首 -->
76 - <div class="flex items-center justify-between mt-6"> 48 + <div class="flex items-center space-x-16 mt-6" style="justify-content: space-evenly;">
77 - <div class="flex items-center space-x-2"> 49 + <button
78 - <!-- <font-awesome-icon :icon="volume === 0 ? 'volume-off' : 'volume-up'" /> 50 + @click="prevSong"
79 - <input 51 + class="w-14 h-14 flex items-center justify-center rounded-full bg-gray-100 hover:bg-gray-200 transition-colors"
80 - type="range" 52 + >
81 - :value="volume" 53 + <font-awesome-icon icon="backward-step" class="text-2xl text-gray-600" />
82 - @input="handleVolumeChange" 54 + </button>
83 - min="0" 55 + <button
84 - max="100" 56 + @click="togglePlay"
85 - step="1" 57 + :class="{'paused': !isPlaying, 'opacity-50 cursor-not-allowed': isLoading}"
86 - class="w-24 appearance-none bg-gray-200 rounded-full h-1.5 cursor-pointer" 58 + :disabled="isLoading"
87 - > --> 59 + class="w-14 h-14 flex items-center justify-center rounded-full bg-blue-500 hover:bg-blue-600 transition-colors shadow-lg"
60 + >
61 + <font-awesome-icon
62 + :icon="['fas' , isPlaying ? 'pause' : 'play']"
63 + :class="{ 'fa-spin': isLoading }"
64 + class="text-2xl"
65 + />
66 + </button>
67 + <button
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"
70 + >
71 + <font-awesome-icon icon="forward-step" class="text-2xl text-gray-600" />
72 + </button>
88 </div> 73 </div>
89 74
90 - <div class="flex items-center space-x-4">
91 <!-- 播放列表按钮 --> 75 <!-- 播放列表按钮 -->
92 - <button @click="togglePlaylist"><font-awesome-icon icon="list" /></button> 76 + <div class="flex justify-end mt-4">
93 - </div> 77 + <button @click="togglePlaylist" class="text-gray-500 hover:text-gray-700 transition-colors">
78 + <font-awesome-icon icon="list" class="text-lg" />
79 + </button>
94 </div> 80 </div>
95 81
96 - <!-- 播放列表:可切换显示的歌曲列表面板 --> 82 + <!-- 播放列表弹出层 -->
97 - <div v-show="isPlaylistVisible" class="playlist mt-4 overscroll-contain"> 83 + <van-popup
98 - <div class="playlist-header flex justify-between items-center px-2 py-1 bg-gray-100 rounded-t-lg"> 84 + v-model:show="isPlaylistVisible"
85 + position="bottom"
86 + :overlay="false"
87 + round
88 + class="playlist-popup"
89 + style="height: 100%"
90 + >
91 + <div class="playlist-header flex justify-between items-center px-4 py-3 border-b sticky top-0 bg-white z-10">
99 <h4 class="font-medium">播放列表 ({{ songs.length }})</h4> 92 <h4 class="font-medium">播放列表 ({{ songs.length }})</h4>
100 - <button @click="closePlaylist"><font-awesome-icon icon="xmark" /></button> 93 + <button @click="closePlaylist" class="text-gray-500 hover:text-gray-700 transition-colors">
94 + <font-awesome-icon icon="xmark" />
95 + </button>
101 </div> 96 </div>
102 - <div class="playlist-items" style="max-height: 16rem; overflow-y: auto; -webkit-overflow-scrolling: touch;"> 97 + <div class="playlist-items overflow-y-auto h-full pb-safe">
103 <div 98 <div
104 v-for="(song, index) in songs" 99 v-for="(song, index) in songs"
105 :key="song.id" 100 :key="song.id"
106 - :class="{'active': index === currentIndex}" 101 + :class="{'active bg-blue-50': index === currentIndex}"
107 @click="selectSong(index)" 102 @click="selectSong(index)"
108 - class="px-2 py-3 hover:bg-gray-100 transition-colors" 103 + class="flex items-center px-4 py-3 hover:bg-gray-50 transition-colors relative"
109 > 104 >
110 - {{ song.title }} - {{ song.artist }} 105 + <div class="absolute top-0 left-0 right-0 h-[1px] bg-gray-200"></div>
106 + <div class="w-16 h-16 rounded-lg overflow-hidden mr-4 flex-shrink-0">
107 + <img :src="song.cover" alt="封面" class="w-full h-full object-cover">
111 </div> 108 </div>
109 + <div class="flex-1">
110 + <div class="font-medium">{{ song.title }}</div>
111 + <div class="text-sm text-gray-500">{{ song.artist }}</div>
112 + </div>
113 + <font-awesome-icon
114 + v-if="index === currentIndex"
115 + icon="volume-up"
116 + class="text-blue-500 ml-2"
117 + />
112 </div> 118 </div>
113 </div> 119 </div>
120 + </van-popup>
114 </div> 121 </div>
115 </template> 122 </template>
116 123
...@@ -151,6 +158,7 @@ onMounted(() => { ...@@ -151,6 +158,7 @@ onMounted(() => {
151 const loadAudio = async () => { 158 const loadAudio = async () => {
152 if (!currentSong.value) return 159 if (!currentSong.value) return
153 isLoading.value = true 160 isLoading.value = true
161 + isPlaylistVisible.value = false // 关闭播放列表
154 try { 162 try {
155 if (audio.value) { 163 if (audio.value) {
156 audio.value.removeEventListener('timeupdate', updateProgress) 164 audio.value.removeEventListener('timeupdate', updateProgress)
...@@ -334,6 +342,27 @@ watch([isPlaying, currentIndex], () => { ...@@ -334,6 +342,27 @@ watch([isPlaying, currentIndex], () => {
334 .progress-track { 342 .progress-track {
335 height: var(--progress-height); 343 height: var(--progress-height);
336 border-radius: var(--progress-height); 344 border-radius: var(--progress-height);
345 + background: linear-gradient(90deg, #1a1a1a 0%, #4a4a4a 100%);
346 + transition: width 0.3s ease-in-out;
347 +}
348 +
349 +input[type='range'] {
350 + -webkit-appearance: none;
351 + appearance: none;
352 + background: transparent;
353 +}
354 +
355 +input[type='range']::-webkit-slider-thumb {
356 + -webkit-appearance: none;
357 + appearance: none;
358 + width: 0;
359 + height: 0;
360 +}
361 +
362 +input[type='range']::-moz-range-thumb {
363 + width: 0;
364 + height: 0;
365 + border: 0;
337 } 366 }
338 367
339 /* 按钮交互动画 */ 368 /* 按钮交互动画 */
...@@ -363,11 +392,7 @@ button:disabled { ...@@ -363,11 +392,7 @@ button:disabled {
363 } 392 }
364 393
365 /* 播放列表样式 */ 394 /* 播放列表样式 */
366 -.playlist-items { 395 +
367 - border: 1px solid #e5e7eb;
368 - border-top: 0;
369 - border-radius: 0 0 0.375rem 0.375rem;
370 -}
371 396
372 .active { 397 .active {
373 background-color: #f3f4f6; 398 background-color: #f3f4f6;
......
1 <!-- 1 <!--
2 * @Date: 2025-03-24 13:04:21 2 * @Date: 2025-03-24 13:04:21
3 * @LastEditors: hookehuyr hookehuyr@gmail.com 3 * @LastEditors: hookehuyr hookehuyr@gmail.com
4 - * @LastEditTime: 2025-04-07 14:06:35 4 + * @LastEditTime: 2025-04-07 17:17:52
5 * @FilePath: /mlaj/src/views/profile/settings/AudioPlayerPage.vue 5 * @FilePath: /mlaj/src/views/profile/settings/AudioPlayerPage.vue
6 * @Description: 音频播放页面 6 * @Description: 音频播放页面
7 --> 7 -->
......