Merge pull request #676 from chengww5217/refactor/persisted-storage

refactor(persist): localStorage 配额防护与历史持久化重写
This commit is contained in:
alger
2026-07-05 13:55:20 +08:00
16 changed files with 573 additions and 201 deletions
+2 -1
View File
@@ -557,6 +557,7 @@ import type { SongResult } from '@/types/music';
import { getImgUrl } from '@/utils';
import type { DownloadTask } from '../../../shared/download';
import { filePathToLocalUrl } from '../../../shared/localUrl';
const { t } = useI18n();
const playerStore = usePlayerStore();
@@ -656,7 +657,7 @@ const shortenPath = (path: string) => {
const getLocalFilePath = (path: string) => {
if (!path) return '';
return `local:///${encodeURIComponent(path)}`;
return filePathToLocalUrl(path);
};
const openDirectory = (path: string) => {
+9 -7
View File
@@ -152,6 +152,7 @@ import { usePlayerStore } from '@/store/modules/player';
import { usePlayHistoryStore } from '@/store/modules/playHistory';
import type { SongResult } from '@/types/music';
import { setAnimationClass } from '@/utils';
import type { MusicHistoryItem } from '@/utils/persistedSong';
const { t } = useI18n();
const playHistoryStore = usePlayHistoryStore();
@@ -220,7 +221,7 @@ const processHistoryData = () => {
const oneYearAgo = Date.now() - 365 * 24 * 60 * 60 * 1000;
// 遍历音乐历史记录
playHistoryStore.musicHistory.forEach((music: SongResult & { count?: number }) => {
playHistoryStore.musicHistory.forEach((music: MusicHistoryItem) => {
// 假设每次播放都记录在当前时间,我们根据 count 分散到最近的日期
const playCount = music.count || 1;
const now = Date.now();
@@ -251,7 +252,7 @@ const processHistoryData = () => {
dailyMap[dateKey].songs.set(songId, {
id: music.id,
name: music.name || 'Unknown',
artist: music.ar?.[0]?.name || music.artists?.[0]?.name || 'Unknown Artist',
artist: music.ar?.[0]?.name || 'Unknown Artist',
playCount: 1
});
}
@@ -307,11 +308,11 @@ const mostPlayedSong = computed<{
{ id: string | number; name: string; artist: string; playCount: number }
>();
playHistoryStore.musicHistory.forEach((music: SongResult & { count?: number }) => {
playHistoryStore.musicHistory.forEach((music: MusicHistoryItem) => {
const id = music.id;
const count = music.count || 1;
const name = music.name || 'Unknown';
const artist = music.ar?.[0]?.name || music.artists?.[0]?.name || 'Unknown Artist';
const artist = music.ar?.[0]?.name || 'Unknown Artist';
if (songPlayCounts.has(id)) {
songPlayCounts.get(id)!.playCount += count;
@@ -382,7 +383,7 @@ const latestNightSong = computed<{
return {
id: randomSong.id,
name: randomSong.name || 'Unknown',
artist: randomSong.ar?.[0]?.name || randomSong.artists?.[0]?.name || 'Unknown Artist',
artist: randomSong.ar?.[0]?.name || 'Unknown Artist',
time: `凌晨 ${randomHour.toString().padStart(2, '0')}:${randomMinute.toString().padStart(2, '0')}`
};
}
@@ -395,7 +396,7 @@ const latestNightSong = computed<{
return {
id: song.id,
name: song.name || 'Unknown',
artist: song.ar?.[0]?.name || song.artists?.[0]?.name || 'Unknown Artist',
artist: song.ar?.[0]?.name || 'Unknown Artist',
time: `凌晨 ${randomHour.toString().padStart(2, '0')}:${randomMinute.toString().padStart(2, '0')}`
};
}
@@ -407,7 +408,8 @@ const latestNightSong = computed<{
const handlePlaySong = async (songId: string | number) => {
const song = playHistoryStore.musicHistory.find((music) => music.id === songId);
if (song) {
await playerStore.setPlay(song);
// MusicHistoryItem 是 SongResult 的精简子集,setPlay 内部用 optional chain 访问字段
await playerStore.setPlay(song as SongResult);
playerStore.setPlayMusic(true);
}
};
+5 -2
View File
@@ -124,6 +124,7 @@ import { useI18n } from 'vue-i18n';
import localData from '@/../main/set.json';
import ClearCacheSettings from '@/components/settings/ClearCacheSettings.vue';
import { usePlayHistoryStore } from '@/store/modules/playHistory';
import { useUserStore } from '@/store/modules/user';
import { isElectron } from '@/utils';
import { openDirectory, selectDirectory } from '@/utils/fileOperation';
@@ -435,7 +436,10 @@ const clearCache = async (selectedCacheTypes: string[]) => {
const clearTasks = selectedCacheTypes.map(async (type) => {
switch (type) {
case 'history':
localStorage.removeItem('musicHistory');
// 与旧版本行为对齐:只清音乐历史,不动 podcast/playlist/album/podcastRadio。
// 数据已迁到 pinia storekey=play-history-store),老 musicHistory key 由
// cleanupLegacyPlayHistoryStorage 在启动时清掉,这里不再需要 removeItem
usePlayHistoryStore().clearMusicHistory();
break;
case 'favorite':
localStorage.removeItem('favoriteList');
@@ -451,7 +455,6 @@ const clearCache = async (selectedCacheTypes: string[]) => {
localStorage.removeItem('theme');
localStorage.removeItem('lyricData');
localStorage.removeItem('lyricFontSize');
localStorage.removeItem('playMode');
break;
case 'downloads':
if (window.electron) {