1818
1919<script setup lang="ts">
2020import { usePlayerController } from " @/core/player/PlayerController" ;
21- import { useDataStore , useMusicStore , useSettingStore , useStatusStore } from " @/stores" ;
21+ import {
22+ useDataStore ,
23+ useLocalStore ,
24+ useMusicStore ,
25+ useSettingStore ,
26+ useStatusStore ,
27+ } from " @/stores" ;
2228import type { CoverType } from " @/types/main" ;
2329import { isLogin } from " @/utils/auth" ;
2430import { isElectron } from " @/utils/env" ;
@@ -34,11 +40,13 @@ import {
3440 NButton ,
3541 NEllipsis ,
3642 NText ,
43+ NPopselect ,
3744} from " naive-ui" ;
3845import { RouterLink , useRouter } from " vue-router" ;
3946
4047const router = useRouter ();
4148const dataStore = useDataStore ();
49+ const localStore = useLocalStore ();
4250const musicStore = useMusicStore ();
4351const statusStore = useStatusStore ();
4452const settingStore = useSettingStore ();
@@ -47,6 +55,7 @@ const player = usePlayerController();
4755// 菜单数据
4856const menuRef = ref <MenuInst | null >(null );
4957const menuActiveKey = ref <string | number >((router .currentRoute .value .name as string ) || " home" );
58+ const playlistMode = ref <" online" | " local" >(" online" );
5059
5160// 菜单内容
5261const menuOptions = computed <MenuOption [] | MenuGroupOption []>(() => {
@@ -166,14 +175,38 @@ const menuOptions = computed<MenuOption[] | MenuGroupOption[]>(() => {
166175 key: " divider-two" ,
167176 type: " divider" ,
168177 },
169- // 创建的歌单
170178 {
171179 key: " user-playlists" ,
172180 show: ! settingStore .sidebarHide .hideUserPlaylists ,
173181 icon: statusStore .menuCollapsed ? renderIcon (" PlaylistAdd" ) : undefined ,
174182 label : () =>
175183 h (" div" , { class: " user-list" }, [
176- h (NText , { depth: 3 }, () => [" 创建的歌单" ]),
184+ h (NText , { depth: 3 }, () =>
185+ playlistMode .value === " online" ? " 创建的歌单" : " 本地歌单" ,
186+ ),
187+ h (
188+ NPopselect ,
189+ {
190+ options: [
191+ { label: " 在线歌单" , value: " online" },
192+ { label: " 本地歌单" , value: " local" },
193+ ],
194+ value: playlistMode .value ,
195+ trigger: " click" ,
196+ onUpdateValue : (value : " online" | " local" ) => {
197+ playlistMode .value = value ;
198+ },
199+ },
200+ () =>
201+ h (NButton , {
202+ type: " tertiary" ,
203+ round: true ,
204+ strong: true ,
205+ secondary: true ,
206+ renderIcon: renderIcon (" Menu" ),
207+ onClick : (e : Event ) => e .stopPropagation (),
208+ }),
209+ ),
177210 h (NButton , {
178211 type: " tertiary" ,
179212 round: true ,
@@ -182,11 +215,14 @@ const menuOptions = computed<MenuOption[] | MenuGroupOption[]>(() => {
182215 renderIcon: renderIcon (" Add" ),
183216 onclick : (event : Event ) => {
184217 event .stopPropagation ();
185- openCreatePlaylist ();
218+ openCreatePlaylist (playlistMode . value === " local " );
186219 },
187220 }),
188221 ]),
189- children: [... createPlaylist .value ],
222+ children:
223+ playlistMode .value === " online"
224+ ? [... createPlaylist .value ]
225+ : [... localPlaylistMenu .value ],
190226 },
191227 // 收藏的歌单
192228 {
@@ -249,6 +285,27 @@ const likedPlaylist = computed<MenuOption[]>(() => {
249285 return renderPlaylist (list , settingStore .menuShowCover );
250286});
251287
288+ // 本地歌单菜单
289+ const localPlaylistMenu = computed <MenuOption []>(() => {
290+ const playlists = localStore .localPlaylists ;
291+ if (! playlists || playlists .length === 0 ) return [];
292+ return playlists .map ((playlist ) => ({
293+ key: ` local-${playlist .id } ` ,
294+ label : () =>
295+ settingStore .menuShowCover
296+ ? h (" div" , { class: " pl-cover" }, [
297+ h (NAvatar , {
298+ src: playlist .cover || " /images/album.jpg?asset" ,
299+ fallbackSrc: " /images/album.jpg?asset" ,
300+ lazy: true ,
301+ }),
302+ h (NEllipsis , null , () => playlist .name ),
303+ ])
304+ : h (NEllipsis , null , () => playlist .name ),
305+ icon: settingStore .menuShowCover ? undefined : renderIcon (" PlayList" ),
306+ }));
307+ });
308+
252309// 渲染菜单路由
253310const renderMenuLabel = (option : MenuOption ) => {
254311 // 路由链接
@@ -283,6 +340,13 @@ const menuUpdate = (key: string, item: MenuOption) => {
283340 name: " playlist" ,
284341 query: { id: item .key },
285342 });
343+ } else if (typeof key === " string" && key .startsWith (" local-" )) {
344+ // 本地歌单
345+ const localId = key .replace (" local-" , " " );
346+ router .push ({
347+ name: " playlist" ,
348+ query: { id: localId },
349+ });
286350 } else {
287351 switch (key ) {
288352 case " like-songs" :
@@ -334,8 +398,18 @@ const checkMenuItem = () => {
334398 const isUserPlaylist = dataStore .userLikeData .playlists .some (
335399 (playlist ) => playlist ?.id === playlistId ,
336400 );
337- if (playlistId ) menuActiveKey .value = isUserPlaylist ? Number (playlistId ) : " home" ;
338- menuRef .value ?.showOption (playlistId );
401+ // 是否为本地歌单
402+ const isLocalPlaylist = playlistId .toString ().length === 16 ;
403+ if (! playlistId ) menuActiveKey .value = " home" ;
404+ if (isUserPlaylist ) {
405+ menuActiveKey .value = Number (playlistId );
406+ menuRef .value ?.showOption (playlistId );
407+ } else if (isLocalPlaylist ) {
408+ menuActiveKey .value = ` local-${playlistId } ` ;
409+ menuRef .value ?.showOption (` local-${playlistId } ` );
410+ } else {
411+ menuActiveKey .value = " home" ;
412+ }
339413 break ;
340414 }
341415 default :
@@ -401,11 +475,11 @@ watch(
401475.user-list {
402476 display : flex ;
403477 align-items : center ;
478+ gap : 8px ;
404479 .n-text {
405480 font-size : 0.93em ;
406481 }
407482 .n-button {
408- margin-left : 12px ;
409483 --n-height : 22px ;
410484 --n-padding : 0 12px ;
411485 --n-icon-size : 12px ;
0 commit comments