From 661145cf9113ad43f949348fff58855858a4fe5e Mon Sep 17 00:00:00 2001 From: WorldSansha Date: Mon, 26 Oct 2026 11:59:55 +0800 Subject: [PATCH 1/2] =?UTF-8?q?feat:=20=E4=B8=BA=E4=B8=93=E8=BE=91?= =?UTF-8?q?=E6=AD=8C=E6=9B=B2=E5=88=97=E8=A1=A8=E6=B7=BB=E5=8A=A0=E5=88=86?= =?UTF-8?q?=E7=A2=9F=E6=A0=8F=E7=9B=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- shared/types/player.ts | 2 + src/components/list/SongList.vue | 59 +++++++++++++++++++++++++++++- src/components/ui/SVirtualList.vue | 13 +++++-- src/i18n/locales/en-US.json | 1 + src/i18n/locales/zh-CN.json | 1 + src/utils/format/netease.ts | 2 + 6 files changed, 72 insertions(+), 6 deletions(-) diff --git a/shared/types/player.ts b/shared/types/player.ts index 93a93aff2..775db8d72 100644 --- a/shared/types/player.ts +++ b/shared/types/player.ts @@ -128,6 +128,8 @@ export interface Track { artists: Artist[]; /** 专辑 */ album?: Album; + /** 碟号或碟片名称 */ + disc?: string; /** 曲目编号 */ track?: number; /** 时长(毫秒) */ diff --git a/src/components/list/SongList.vue b/src/components/list/SongList.vue index c4c14b1cb..7c2e4481d 100644 --- a/src/components/list/SongList.vue +++ b/src/components/list/SongList.vue @@ -202,8 +202,20 @@ const filteredItems = computed(() => { }); }); +/** 默认顺序下按碟片分组,搜索仍保留原专辑的分碟结构 */ +const discGroups = computed(() => { + if ( + props.collectionType !== "album" || + (props.enableSort && sortField.value !== "none") || + new Set(props.items.map((track) => track.disc ?? "1")).size < 2 + ) + return []; + return [...Map.groupBy(filteredItems.value, (track) => track.disc ?? "1")]; +}); + /** 排序后列表 */ const sortedItems = computed(() => { + if (discGroups.value.length) return discGroups.value.flatMap(([, tracks]) => tracks); if (!props.enableSort || sortField.value === "none") return filteredItems.value; const result = [...filteredItems.value]; const field = sortField.value; @@ -234,6 +246,27 @@ const sortedItems = computed(() => { return result; }); +/** 标题附在每碟第一首歌上,歌曲索引和播放队列保持一致 */ +const discHeaders = computed(() => { + const headers: Record = {}; + let index = 0; + for (const [disc, tracks] of discGroups.value) { + headers[index] = { disc, count: tracks.length }; + index += tracks.length; + } + return headers; +}); + +/** 使用完整专辑计算碟内曲序,搜索时保持原编号 */ +const discTrackNumbers = computed( + () => + new Map( + [...Map.groupBy(props.items, (track) => track.disc ?? "1").values()].flatMap((tracks) => + tracks.map((track, index) => [track.id, index + 1] as const), + ), + ), +); + /** 当前播放歌曲在过滤后列表中的索引 */ const playingIndex = computed(() => { if (!playingId.value) return -1; @@ -421,7 +454,10 @@ defineExpose({ :item-height="isCompactList ? 56 : 88" :padding-bottom="isFloatingPlayerBar ? PLAYER_BAR_GAP : 80" :get-item-key="(item: Track) => item.id" - item-fixed + :item-fixed="!discGroups.length" + :get-item-height=" + (_item: Track, index: number) => (isCompactList ? 56 : 88) + (discHeaders[index] ? 40 : 0) + " height="100%" @scroll="onScroll" @reach-bottom="emit('reachBottom')" @@ -618,6 +654,25 @@ defineExpose({