Skip to content

Commit 2e96161

Browse files
committed
✨ feat: 修改播放列表展示形式,优化播放逻辑,添加清空播放列表功能
1 parent 56b3ecf commit 2e96161

File tree

14 files changed

+382
-166
lines changed

14 files changed

+382
-166
lines changed

src/i18n/lang/en-US/player.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,5 +105,13 @@ export default {
105105
playbackStopped: 'Music playback stopped',
106106
minutesRemaining: '{minutes} min remaining',
107107
songsRemaining: '{count} songs remaining'
108+
},
109+
playList: {
110+
clearAll: 'Clear Playlist',
111+
alreadyEmpty: 'Playlist is already empty',
112+
cleared: 'Playlist cleared',
113+
empty: 'Playlist is empty',
114+
clearConfirmTitle: 'Clear Playlist',
115+
clearConfirmContent: 'This will clear all songs in the playlist and stop the current playback. Continue?'
108116
}
109117
};

src/i18n/lang/zh-CN/player.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,5 +106,13 @@ export default {
106106
playbackStopped: '音乐播放已停止',
107107
minutesRemaining: '剩余{minutes}分钟',
108108
songsRemaining: '剩余{count}首歌'
109+
},
110+
playList: {
111+
clearAll: '清空播放列表',
112+
alreadyEmpty: '播放列表已经为空',
113+
cleared: '已清空播放列表',
114+
empty: '播放列表为空',
115+
clearConfirmTitle: '清空播放列表',
116+
clearConfirmContent: '这将清空所有播放列表中的歌曲并停止当前播放。是否继续?'
109117
}
110118
};

src/renderer/components/common/SearchItem.vue

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@
3333
<script setup lang="ts">
3434
import { getAlbum, getListDetail } from '@/api/list';
3535
import MvPlayer from '@/components/MvPlayer.vue';
36-
import { audioService } from '@/services/audioService';
3736
import { usePlayerStore } from '@/store/modules/player';
3837
import { IMvItem } from '@/type/mv';
3938
import { getImgUrl } from '@/utils';
@@ -129,9 +128,7 @@ const handleClick = async () => {
129128
};
130129
131130
const handleShowMv = async () => {
132-
playerStore.setIsPlay(false);
133-
playerStore.setPlayMusic(false);
134-
audioService.getCurrentSound()?.pause();
131+
playerStore.handlePause();
135132
showPop.value = true;
136133
};
137134
</script>

src/renderer/components/common/SongItem.vue

Lines changed: 3 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@
122122
:x="dropdownX"
123123
:y="dropdownY"
124124
:options="dropdownOptions"
125-
:z-index="99999"
125+
:z-index="99999999"
126126
placement="bottom-start"
127127
@clickoutside="showDropdown = false"
128128
@select="handleSelect"
@@ -137,9 +137,8 @@ import { NEllipsis, NImage, useMessage } from 'naive-ui';
137137
import { computed, h, inject, ref, useTemplateRef } from 'vue';
138138
import { useI18n } from 'vue-i18n';
139139
140-
import { getSongUrl } from '@/hooks/MusicListHook';
140+
import { getSongUrl } from '@/store/modules/player';
141141
import { useArtist } from '@/hooks/useArtist';
142-
import { audioService } from '@/services/audioService';
143142
import { usePlayerStore } from '@/store';
144143
import type { SongResult } from '@/type/music';
145144
import { getImgUrl, isElectron } from '@/utils';
@@ -444,18 +443,6 @@ const imageLoad = async () => {
444443
445444
// 播放音乐 设置音乐详情 打开音乐底栏
446445
const playMusicEvent = async (item: SongResult) => {
447-
// 如果是当前正在播放的音乐,则切换播放/暂停状态
448-
if (playMusic.value.id === item.id) {
449-
if (play.value) {
450-
playerStore.setPlayMusic(false);
451-
audioService.getCurrentSound()?.pause();
452-
} else {
453-
playerStore.setPlayMusic(true);
454-
audioService.getCurrentSound()?.play();
455-
}
456-
return;
457-
}
458-
459446
try {
460447
// 使用store的setPlay方法,该方法已经包含了B站视频URL处理逻辑
461448
const result = await playerStore.setPlay(item);
@@ -551,7 +538,7 @@ const handleMouseLeave = () => {
551538
@apply rounded-3xl p-3 flex items-center transition bg-transparent dark:text-white text-gray-900;
552539
553540
&:hover {
554-
@apply bg-gray-100 dark:bg-gray-800;
541+
@apply bg-light-100 dark:bg-dark-100;
555542
556543
.song-item-operating-compact {
557544
.song-item-operating-like,

src/renderer/components/player/MiniPlayBar.vue

Lines changed: 1 addition & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -312,25 +312,7 @@ const handleNext = () => playerStore.nextPlay();
312312
313313
const playMusicEvent = async () => {
314314
try {
315-
if (!playerStore.playMusic?.id || !playerStore.playMusicUrl) {
316-
console.warn('No valid music or URL available');
317-
playerStore.setPlay(playerStore.playMusic);
318-
return;
319-
}
320-
321-
if (play.value) {
322-
if (audioService.getCurrentSound()) {
323-
audioService.pause();
324-
playerStore.setPlayMusic(false);
325-
}
326-
} else {
327-
if (audioService.getCurrentSound()) {
328-
audioService.play();
329-
} else {
330-
await audioService.play(playerStore.playMusicUrl, playerStore.playMusic);
331-
}
332-
playerStore.setPlayMusic(true);
333-
}
315+
playerStore.setPlay(playerStore.playMusic);
334316
} catch (error) {
335317
console.error('播放出错:', error);
336318
playerStore.nextPlay();

src/renderer/components/player/MobilePlayBar.vue

Lines changed: 1 addition & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,6 @@ import SongItem from '@/components/common/SongItem.vue';
158158
import SleepTimerPopover from '@/components/player/SleepTimerPopover.vue';
159159
import { allTime, artistList, nowTime, playMusic, sound, textColors } from '@/hooks/MusicHook';
160160
import MusicFull from '@/layout/components/MusicFull.vue';
161-
import { audioService } from '@/services/audioService';
162161
import { usePlayerStore } from '@/store/modules/player';
163162
import { useSettingsStore } from '@/store/modules/settings';
164163
import type { SongResult } from '@/type/music';
@@ -235,25 +234,7 @@ const toggleFavorite = () => {
235234
// 播放暂停按钮事件
236235
const playMusicEvent = async () => {
237236
try {
238-
if (!playMusic.value?.id || !playerStore.playMusicUrl) {
239-
console.warn('No valid music or URL available');
240-
playerStore.setPlay(playMusic.value);
241-
return;
242-
}
243-
244-
if (play.value) {
245-
if (audioService.getCurrentSound()) {
246-
audioService.pause();
247-
playerStore.setPlayMusic(false);
248-
}
249-
} else {
250-
if (audioService.getCurrentSound()) {
251-
audioService.play();
252-
} else {
253-
await audioService.play(playerStore.playMusicUrl, playMusic.value);
254-
}
255-
playerStore.setPlayMusic(true);
256-
}
237+
playerStore.setPlay(playMusic.value);
257238
} catch (error) {
258239
console.error('播放出错:', error);
259240
playerStore.nextPlay();

src/renderer/components/player/PlayBar.vue

Lines changed: 11 additions & 98 deletions
Original file line numberDiff line numberDiff line change
@@ -155,42 +155,12 @@
155155
</n-popover>
156156
<!-- 定时关闭功能 -->
157157
<sleep-timer-popover mode="desktop" />
158-
<n-popover
159-
trigger="click"
160-
:z-index="99999999"
161-
content-class="music-play"
162-
raw
163-
:show-arrow="false"
164-
:delay="200"
165-
arrow-wrapper-style=" border-radius:1.5rem"
166-
@update-show="scrollToPlayList"
167-
>
158+
<n-tooltip trigger="hover" :z-index="9999999">
168159
<template #trigger>
169-
<n-tooltip trigger="manual" :z-index="9999999">
170-
<template #trigger>
171-
<i class="iconfont icon-list"></i>
172-
</template>
173-
{{ t('player.playBar.playList') }}
174-
</n-tooltip>
160+
<i class="iconfont icon-list text-2xl hover:text-green-500 transition-colors cursor-pointer" @click="openPlayListDrawer"></i>
175161
</template>
176-
<div class="music-play-list">
177-
<div class="music-play-list-back"></div>
178-
<n-virtual-list ref="palyListRef" :item-size="62" item-resizable :items="playList">
179-
<template #default="{ item }">
180-
<div class="music-play-list-content">
181-
<div class="flex items-center justify-between">
182-
<song-item :key="item.id" class="flex-1" :item="item" mini></song-item>
183-
<div class="delete-btn" @click.stop="handleDeleteSong(item)">
184-
<i
185-
class="iconfont ri-delete-bin-line text-gray-400 hover:text-red-500 transition-colors"
186-
></i>
187-
</div>
188-
</div>
189-
</div>
190-
</template>
191-
</n-virtual-list>
192-
</div>
193-
</n-popover>
162+
{{ t('player.playBar.playList') }}
163+
</n-tooltip>
194164
</div>
195165
<!-- 播放音乐 -->
196166
<music-full ref="MusicFullRef" v-model="musicFullVisible" :background="background" />
@@ -200,10 +170,9 @@
200170
<script lang="ts" setup>
201171
import { useThrottleFn } from '@vueuse/core';
202172
import { useMessage } from 'naive-ui';
203-
import { computed, ref, useTemplateRef, watch } from 'vue';
173+
import { computed, ref, watch } from 'vue';
204174
import { useI18n } from 'vue-i18n';
205175
206-
import SongItem from '@/components/common/SongItem.vue';
207176
import EqControl from '@/components/EQControl.vue';
208177
import SleepTimerPopover from '@/components/player/SleepTimerPopover.vue';
209178
import ReparsePopover from '@/components/player/ReparsePopover.vue';
@@ -224,7 +193,6 @@ import {
224193
usePlayerStore
225194
} from '@/store/modules/player';
226195
import { useSettingsStore } from '@/store/modules/settings';
227-
import type { SongResult } from '@/type/music';
228196
import { getImgUrl, isElectron, isMobile, secondToMinute, setAnimationClass } from '@/utils';
229197
230198
const playerStore = usePlayerStore();
@@ -233,8 +201,6 @@ const { t } = useI18n();
233201
const message = useMessage();
234202
// 是否播放
235203
const play = computed(() => playerStore.isPlay);
236-
// 播放列表
237-
const playList = computed(() => playerStore.playList as SongResult[]);
238204
// 背景颜色
239205
const background = ref('#000');
240206
@@ -372,42 +338,12 @@ const showSliderTooltip = ref(false);
372338
// 播放暂停按钮事件
373339
const playMusicEvent = async () => {
374340
try {
375-
// 检查是否有有效的音乐对象
376-
if (!playMusic.value?.id) {
377-
console.warn('没有有效的播放对象');
378-
return;
379-
}
380-
381-
// 当前处于播放状态 -> 暂停
382-
if (play.value) {
383-
if (audioService.getCurrentSound()) {
384-
audioService.pause();
385-
playerStore.setPlayMusic(false);
386-
}
387-
return;
388-
}
389-
390-
// 当前处于暂停状态 -> 播放
391-
// 有音频实例,直接播放
392-
if (audioService.getCurrentSound()) {
393-
audioService.play();
341+
const result = await playerStore.setPlay({ ...playMusic.value});
342+
if (result) {
394343
playerStore.setPlayMusic(true);
395-
return;
396-
}
397-
398-
// 没有音频实例,重新获取并播放(包括重新获取B站视频URL)
399-
try {
400-
// 复用当前播放对象,但强制重新获取URL
401-
const result = await playerStore.setPlay({ ...playMusic.value, playMusicUrl: undefined });
402-
if (result) {
403-
playerStore.setPlayMusic(true);
404-
}
405-
} catch (error) {
406-
console.error('重新获取播放链接失败:', error);
407-
message.error(t('player.playFailed'));
408344
}
409345
} catch (error) {
410-
console.error('播放出错:', error);
346+
console.error('重新获取播放链接失败:', error);
411347
message.error(t('player.playFailed'));
412348
}
413349
};
@@ -423,15 +359,6 @@ const setMusicFull = () => {
423359
}
424360
};
425361
426-
const palyListRef = useTemplateRef('palyListRef') as any;
427-
428-
const scrollToPlayList = (val: boolean) => {
429-
if (!val) return;
430-
setTimeout(() => {
431-
palyListRef.value?.scrollTo({ top: playerStore.playListIndex * 62 });
432-
}, 50);
433-
};
434-
435362
const isFavorite = computed(() => {
436363
// 对于B站视频,使用ID匹配函数
437364
if (playMusic.value.source === 'bilibili' && playMusic.value.bilibiliData?.bvid) {
@@ -473,25 +400,11 @@ const handleArtistClick = (id: number) => {
473400
navigateToArtist(id);
474401
};
475402
476-
// 监听播放栏显示状态
477-
watch(
478-
() => MusicFullRef.value?.config?.hidePlayBar,
479-
(newVal) => {
480-
if (newVal && musicFullVisible.value) {
481-
// 使用 animate.css 动画,不需要手动设置样式
482-
}
483-
}
484-
);
485-
486403
const isEQVisible = ref(false);
487404
488-
// 在 script setup 部分添加删除歌曲的处理函数
489-
const handleDeleteSong = (song: SongResult) => {
490-
// 如果删除的是当前播放的歌曲,先切换到下一首
491-
if (song.id === playMusic.value.id) {
492-
playerStore.nextPlay();
493-
}
494-
playerStore.removeFromPlayList(song.id as number);
405+
// 打开播放列表抽屉
406+
const openPlayListDrawer = () => {
407+
playerStore.setPlayListDrawerVisible(true);
495408
};
496409
</script>
497410

0 commit comments

Comments
 (0)