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 + </div>
25 +
26 + <!-- 进度条与时间:显示当前播放时间、总时长和可拖动的进度条 -->
27 + <div class="mt-4 mb-6">
28 + <div class="flex items-center justify-between text-xs text-gray-400 mb-2">
29 + <span>{{ formatTime(currentTime) }}</span>
30 + <span>{{ formatTime(duration) }}</span>
31 + </div>
32 + <div class="progress-bar relative h-1 bg-gray-200 rounded-full">
33 + <input
34 + type="range"
35 + :value="progress"
36 + @input="handleProgressChange"
37 + @change="seekTo"
38 + class="w-full absolute inset-0 appearance-none bg-transparent cursor-pointer"
39 + >
40 + <div
41 + :style="{ width: `${progress}%` }"
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"
43 + ></div>
44 + </div>
45 + </div>
46 +
24 <!-- 播放控制按钮组:上一首、播放/暂停、下一首 --> 47 <!-- 播放控制按钮组:上一首、播放/暂停、下一首 -->
25 - <div class="flex items-center justify-center space-x-8 sm:space-x-6 w-full sm:w-auto"> 48 + <div class="flex items-center space-x-16 mt-6" style="justify-content: space-evenly;">
26 <button 49 <button
27 @click="prevSong" 50 @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" 51 + class="w-14 h-14 flex items-center justify-center rounded-full bg-gray-100 hover:bg-gray-200 transition-colors"
29 > 52 >
30 - <font-awesome-icon icon="backward-step" class="text-xl text-gray-600" /> 53 + <font-awesome-icon icon="backward-step" class="text-2xl text-gray-600" />
31 </button> 54 </button>
32 <button 55 <button
33 @click="togglePlay" 56 @click="togglePlay"
34 :class="{'paused': !isPlaying, 'opacity-50 cursor-not-allowed': isLoading}" 57 :class="{'paused': !isPlaying, 'opacity-50 cursor-not-allowed': isLoading}"
35 :disabled="isLoading" 58 :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" 59 + class="w-14 h-14 flex items-center justify-center rounded-full bg-blue-500 hover:bg-blue-600 transition-colors shadow-lg"
37 > 60 >
38 <font-awesome-icon 61 <font-awesome-icon
39 :icon="['fas' , isPlaying ? 'pause' : 'play']" 62 :icon="['fas' , isPlaying ? 'pause' : 'play']"
40 :class="{ 'fa-spin': isLoading }" 63 :class="{ 'fa-spin': isLoading }"
41 - class="text-3xl" 64 + class="text-2xl"
42 /> 65 />
43 </button> 66 </button>
44 <button 67 <button
45 @click="nextSong" 68 @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" 69 + class="w-14 h-14 flex items-center justify-center rounded-full bg-gray-100 hover:bg-gray-200 transition-colors"
47 > 70 >
48 - <font-awesome-icon icon="forward-step" class="text-xl text-gray-600" /> 71 + <font-awesome-icon icon="forward-step" class="text-2xl text-gray-600" />
49 </button> 72 </button>
50 </div> 73 </div>
51 - </div>
52 74
53 - <!-- 进度条与时间:显示当前播放时间、总时长和可拖动的进度条 --> 75 + <!-- 播放列表按钮 -->
54 - <div class="mt-4"> 76 + <div class="flex justify-end mt-4">
55 - <div class="flex items-center justify-between text-sm text-gray-500"> 77 + <button @click="togglePlaylist" class="text-gray-500 hover:text-gray-700 transition-colors">
56 - <span>{{ formatTime(currentTime) }}</span> 78 + <font-awesome-icon icon="list" class="text-lg" />
57 - <span>{{ formatTime(duration) }}</span> 79 + </button>
58 - </div>
59 -
60 - <div class="progress-bar relative mt-2">
61 - <input
62 - type="range"
63 - :value="progress"
64 - @input="handleProgressChange"
65 - @change="seekTo"
66 - class="w-full appearance-none bg-gray-200 rounded-full h-1.5 cursor-pointer"
67 - >
68 - <div
69 - :style="{ width: `${progress}%` }"
70 - class="progress-track absolute left-0 top-0 h-full rounded-full bg-gradient-to-r from-blue-500 to-purple-500 transition-all"
71 - ></div>
72 - </div>
73 </div> 80 </div>
74 81
75 - <!-- 音量与设置:音量控制滑块和播放列表按钮 --> 82 + <!-- 播放列表弹出层 -->
76 - <div class="flex items-center justify-between mt-6"> 83 + <van-popup
77 - <div class="flex items-center space-x-2"> 84 + v-model:show="isPlaylistVisible"
78 - <!-- <font-awesome-icon :icon="volume === 0 ? 'volume-off' : 'volume-up'" /> 85 + position="bottom"
79 - <input 86 + :overlay="false"
80 - type="range" 87 + round
81 - :value="volume" 88 + class="playlist-popup"
82 - @input="handleVolumeChange" 89 + style="height: 100%"
83 - min="0" 90 + >
84 - max="100" 91 + <div class="playlist-header flex justify-between items-center px-4 py-3 border-b sticky top-0 bg-white z-10">
85 - step="1"
86 - class="w-24 appearance-none bg-gray-200 rounded-full h-1.5 cursor-pointer"
87 - > -->
88 - </div>
89 -
90 - <div class="flex items-center space-x-4">
91 - <!-- 播放列表按钮 -->
92 - <button @click="togglePlaylist"><font-awesome-icon icon="list" /></button>
93 - </div>
94 - </div>
95 -
96 - <!-- 播放列表:可切换显示的歌曲列表面板 -->
97 - <div v-show="isPlaylistVisible" class="playlist mt-4 overscroll-contain">
98 - <div class="playlist-header flex justify-between items-center px-2 py-1 bg-gray-100 rounded-t-lg">
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">
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 + />
111 </div> 118 </div>
112 </div> 119 </div>
113 - </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 -->
......