From 067868f7863cf4a221ffec292c2ec4c3ae97f57a Mon Sep 17 00:00:00 2001 From: alger Date: Thu, 12 Mar 2026 18:31:29 +0800 Subject: [PATCH] =?UTF-8?q?perf:=20=E4=BC=98=E5=8C=96=E6=92=AD=E6=94=BE?= =?UTF-8?q?=E5=88=97=E8=A1=A8=E6=8C=81=E4=B9=85=E5=8C=96=EF=BC=8C=E7=B2=BE?= =?UTF-8?q?=E7=AE=80=E5=BA=8F=E5=88=97=E5=8C=96=E5=AD=97=E6=AE=B5=E5=B9=B6?= =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E9=98=B2=E6=8A=96=E5=86=99=E5=85=A5=20(H-010?= =?UTF-8?q?)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 自定义序列化器仅保留必要字段,排除 lyric/song/playMusicUrl 等大体积数据 添加防抖 localStorage 包装降低写入频率,beforeunload 时刷新未写入数据 --- src/renderer/store/modules/playlist.ts | 65 ++++++++++++++++++++++++-- 1 file changed, 61 insertions(+), 4 deletions(-) diff --git a/src/renderer/store/modules/playlist.ts b/src/renderer/store/modules/playlist.ts index f396111..6b29580 100644 --- a/src/renderer/store/modules/playlist.ts +++ b/src/renderer/store/modules/playlist.ts @@ -1,4 +1,5 @@ import { useThrottleFn } from '@vueuse/core'; +import { debounce } from 'lodash'; import { createDiscreteApi } from 'naive-ui'; import { defineStore, storeToRefs } from 'pinia'; import { computed, ref, shallowRef, triggerRef } from 'vue'; @@ -16,6 +17,53 @@ import { useSleepTimerStore } from './sleepTimer'; const { message } = createDiscreteApi(['message']); +/** + * 精简 SongResult 对象,只保留持久化必要字段 + * 排除大体积字段:lyric, song, playMusicUrl, backgroundColor, primaryColor + */ +const minifySong = (s: SongResult) => ({ + id: s.id, + name: s.name, + picUrl: s.picUrl, + ar: s.ar?.map((a) => ({ id: a.id, name: a.name })), + al: s.al, + source: s.source, + dt: s.dt +}); + +const minifySongList = (list: SongResult[] | undefined) => list?.map(minifySong) ?? []; + +/** + * 防抖 localStorage 包装,降低写入频率 + * 通过 pendingWrites 跟踪未写入数据,beforeunload 时刷新 + */ +const pendingWrites = new Map(); + +const flushPendingWrites = () => { + pendingWrites.forEach((value, key) => { + localStorage.setItem(key, value); + }); + pendingWrites.clear(); +}; + +const debouncedSetItem = debounce((key: string, value: string) => { + localStorage.setItem(key, value); + pendingWrites.delete(key); +}, 2000); + +const debouncedLocalStorage = { + getItem: (key: string) => localStorage.getItem(key), + setItem: (key: string, value: string) => { + pendingWrites.set(key, value); + debouncedSetItem(key, value); + } +}; + +// 正常关闭时刷新未写入的数据 +if (typeof window !== 'undefined') { + window.addEventListener('beforeunload', flushPendingWrites); +} + /** * 播放列表管理 Store * 负责:播放列表、索引、播放模式、预加载、上/下一首 @@ -711,12 +759,21 @@ export const usePlaylistStore = defineStore( }; }, { - // 配置 pinia-plugin-persistedstate + // 配置 pinia-plugin-persistedstate(精简序列化 + 防抖写入) persist: { key: 'playlist-store', - storage: localStorage, - // 持久化所有状态,除了 playListDrawerVisible(UI 状态不需要持久化) - pick: ['playList', 'playListIndex', 'playMode', 'originalPlayList'] + storage: debouncedLocalStorage, + pick: ['playList', 'playListIndex', 'playMode', 'originalPlayList'], + serializer: { + serialize: (state: any) => { + return JSON.stringify({ + ...state, + playList: minifySongList(state.playList), + originalPlayList: minifySongList(state.originalPlayList) + }); + }, + deserialize: JSON.parse + } } } );