From 27d5bd8f819ab0ea622b46bcdc7fa7f4bfd60a91 Mon Sep 17 00:00:00 2001 From: algerkong Date: Mon, 21 Apr 2025 20:38:05 +0800 Subject: [PATCH] =?UTF-8?q?=F0=9F=90=9E=20fix:=20=E4=BF=AE=E5=A4=8D?= =?UTF-8?q?=E4=B8=8B=E8=BD=BD=E7=AE=A1=E7=90=86=20=E5=88=87=E6=8D=A2tab?= =?UTF-8?q?=E7=A8=8B=E5=BA=8F=E5=8D=A1=E6=AD=BB=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/i18n/lang/en-US/download.ts | 3 +- src/i18n/lang/zh-CN/download.ts | 3 +- src/main/modules/fileManager.ts | 36 ++++- .../components/common/DownloadDrawer.vue | 148 +++++++++--------- 4 files changed, 104 insertions(+), 86 deletions(-) diff --git a/src/i18n/lang/en-US/download.ts b/src/i18n/lang/en-US/download.ts index 61b6baf..d834e1b 100644 --- a/src/i18n/lang/en-US/download.ts +++ b/src/i18n/lang/en-US/download.ts @@ -44,5 +44,6 @@ export default { message: { downloadComplete: '{filename} download completed', downloadFailed: '{filename} download failed: {error}' - } + }, + loading: 'Loading...' }; diff --git a/src/i18n/lang/zh-CN/download.ts b/src/i18n/lang/zh-CN/download.ts index be06a45..b8b7f9e 100644 --- a/src/i18n/lang/zh-CN/download.ts +++ b/src/i18n/lang/zh-CN/download.ts @@ -43,5 +43,6 @@ export default { message: { downloadComplete: '{filename} 下载完成', downloadFailed: '{filename} 下载失败: {error}' - } + }, + loading: '加载中...' }; diff --git a/src/main/modules/fileManager.ts b/src/main/modules/fileManager.ts index 2d2489e..cf7c610 100644 --- a/src/main/modules/fileManager.ts +++ b/src/main/modules/fileManager.ts @@ -122,20 +122,37 @@ export function initializeFileManager() { }); // 获取已下载音乐列表 - ipcMain.handle('get-downloaded-music', () => { + ipcMain.handle('get-downloaded-music', async () => { try { const store = new Store(); const songInfos = store.get('downloadedSongs', {}) as Record; - // 过滤出实际存在的文件 - const validSongs = Object.entries(songInfos) - .filter(([path]) => fs.existsSync(path)) - .map(([_, info]) => info) + // 异步处理文件存在性检查 + const entriesArray = Object.entries(songInfos); + const validEntriesPromises = await Promise.all( + entriesArray.map(async ([path, info]) => { + try { + const exists = await fs.promises.access(path) + .then(() => true) + .catch(() => false); + return exists ? info : null; + } catch (error) { + console.error('Error checking file existence:', error); + return null; + } + }) + ); + + // 过滤有效的歌曲并排序 + const validSongs = validEntriesPromises + .filter(song => song !== null) .sort((a, b) => (b.downloadTime || 0) - (a.downloadTime || 0)); // 更新存储,移除不存在的文件记录 const newSongInfos = validSongs.reduce((acc, song) => { - acc[song.path] = song; + if (song && song.path) { + acc[song.path] = song; + } return acc; }, {}); store.set('downloadedSongs', newSongInfos); @@ -175,6 +192,13 @@ export function initializeFileManager() { downloadStore.set('history', []); }); + // 添加清除已下载音乐记录的处理函数 + ipcMain.handle('clear-downloaded-music', () => { + const store = new Store(); + store.set('downloadedSongs', {}); + return true; + }); + // 添加清除音频缓存的处理函数 ipcMain.on('clear-audio-cache', () => { audioCacheStore.set('cache', {}); diff --git a/src/renderer/components/common/DownloadDrawer.vue b/src/renderer/components/common/DownloadDrawer.vue index f659dce..f4e71f5 100644 --- a/src/renderer/components/common/DownloadDrawer.vue +++ b/src/renderer/components/common/DownloadDrawer.vue @@ -90,7 +90,11 @@
-
+
+ + {{ t('download.loading') }} +
+
@@ -262,9 +266,7 @@ const downloadedList = ref( JSON.parse(localStorage.getItem('downloadedList') || '[]') ); -const downList = computed(() => { - return (downloadedList.value as DownloadedItem[]).reverse(); -}); +const downList = computed(() => downloadedList.value); // 计算下载中的任务数量 const downloadingCount = computed(() => { @@ -350,38 +352,25 @@ const handleDelete = (item: DownloadedItem) => { // 确认删除 const confirmDelete = async () => { - if (!itemToDelete.value) return; + const item = itemToDelete.value; + if (!item) return; try { const success = await window.electron.ipcRenderer.invoke( 'delete-downloaded-music', - itemToDelete.value.path + item.path ); - // 无论删除文件是否成功,都从记录中移除 - localStorage.setItem( - 'downloadedList', - JSON.stringify( - downloadedList.value.filter((item) => item.id !== (itemToDelete.value as DownloadedItem).id) - ) - ); - await refreshDownloadedList(); - if (success) { + const newList = downloadedList.value.filter(i => i.id !== item.id); + downloadedList.value = newList; + localStorage.setItem('downloadedList', JSON.stringify(newList)); message.success(t('download.delete.success')); } else { message.warning(t('download.delete.fileNotFound')); } } catch (error) { console.error('Failed to delete music:', error); - // 即使删除文件出错,也从记录中移除 - localStorage.setItem( - 'downloadedList', - JSON.stringify( - downloadedList.value.filter((item) => item.id !== (itemToDelete.value as DownloadedItem).id) - ) - ); - await refreshDownloadedList(); message.warning(t('download.delete.recordRemoved')); } finally { showDeleteConfirm.value = false; @@ -393,11 +382,18 @@ const confirmDelete = async () => { const showClearConfirm = ref(false); // 清空下载记录 -const clearDownloadRecords = () => { - localStorage.setItem('downloadedList', '[]'); - downloadedList.value = []; - message.success(t('download.clear.success')); - showClearConfirm.value = false; +const clearDownloadRecords = async () => { + try { + downloadedList.value = []; + localStorage.setItem('downloadedList', '[]'); + await window.electron.ipcRenderer.invoke('clear-downloaded-music'); + message.success(t('download.clear.success')); + } catch (error) { + console.error('Failed to clear download records:', error); + message.error(t('download.clear.failed')); + } finally { + showClearConfirm.value = false; + } }; // 播放音乐 @@ -407,65 +403,64 @@ const clearDownloadRecords = () => { // playerStore.setIsPlay(true); // }; +// 添加加载状态 +const isLoadingDownloaded = ref(false); + // 获取已下载音乐列表 const refreshDownloadedList = async () => { + if (isLoadingDownloaded.value) return; // 防止重复加载 + try { - let saveList: any = []; + isLoadingDownloaded.value = true; const list = await window.electron.ipcRenderer.invoke('get-downloaded-music'); + if (!Array.isArray(list) || list.length === 0) { - saveList = []; + downloadedList.value = []; + localStorage.setItem('downloadedList', '[]'); return; } - const songIds = list.filter((item) => item.id).map((item) => item.id); - - // 如果有歌曲ID,获取详细信息 - if (songIds.length > 0) { - try { - const detailRes = await getMusicDetail(songIds); - const songDetails = detailRes.data.songs.reduce((acc, song) => { - acc[song.id] = song; - return acc; - }, {}); - - saveList = list.map((item) => { - const songDetail = songDetails[item.id]; - return { - ...item, - picUrl: songDetail?.al?.picUrl || item.picUrl || '/images/default_cover.png', - ar: songDetail?.ar || item.ar || [{ name: t('download.localMusic') }] - }; - }); - } catch (detailError) { - console.error('Failed to get music details:', detailError); - saveList = list; - } - } else { - saveList = list; + const songIds = list.filter(item => item.id).map(item => item.id); + if (songIds.length === 0) { + downloadedList.value = list; + localStorage.setItem('downloadedList', JSON.stringify(list)); + return; + } + + try { + const detailRes = await getMusicDetail(songIds); + const songDetails = detailRes.data.songs.reduce((acc, song) => { + acc[song.id] = song; + return acc; + }, {}); + + const updatedList = list.map(item => ({ + ...item, + picUrl: songDetails[item.id]?.al?.picUrl || item.picUrl || '/images/default_cover.png', + ar: songDetails[item.id]?.ar || item.ar || [{ name: t('download.localMusic') }] + })); + + downloadedList.value = updatedList; + localStorage.setItem('downloadedList', JSON.stringify(updatedList)); + } catch (error) { + console.error('Failed to get music details:', error); + downloadedList.value = list; + localStorage.setItem('downloadedList', JSON.stringify(list)); } - setLocalDownloadedList(saveList); } catch (error) { console.error('Failed to get downloaded music list:', error); downloadedList.value = []; + localStorage.setItem('downloadedList', '[]'); + } finally { + isLoadingDownloaded.value = false; } }; -const setLocalDownloadedList = (list: DownloadedItem[]) => { - const localList = localStorage.getItem('downloadedList'); - // 合并 去重 - const saveList = [...(localList ? JSON.parse(localList) : []), ...list]; - const uniqueList = saveList.filter( - (item, index, self) => index === self.findIndex((t) => t.id === item.id) - ); - localStorage.setItem('downloadedList', JSON.stringify(uniqueList)); - downloadedList.value = uniqueList; -}; - // 监听抽屉显示状态 watch( () => showDrawer.value, (newVal) => { - if (newVal) { + if (newVal && !isLoadingDownloaded.value) { refreshDownloadedList(); } } @@ -503,15 +498,14 @@ onMounted(() => { }); // 监听下载完成 - window.electron.ipcRenderer.on('music-download-complete', (_, data) => { + window.electron.ipcRenderer.on('music-download-complete', async (_, data) => { if (data.success) { - // 从下载列表中移除 - downloadList.value = downloadList.value.filter((item) => item.filename !== data.filename); - // 刷新已下载列表 - refreshDownloadedList(); + downloadList.value = downloadList.value.filter(item => item.filename !== data.filename); + // 延迟刷新已下载列表,避免文件系统未完全写入 + setTimeout(() => refreshDownloadedList(), 500); message.success(t('download.message.downloadComplete', { filename: data.filename })); } else { - const existingItem = downloadList.value.find((item) => item.filename === data.filename); + const existingItem = downloadList.value.find(item => item.filename === data.filename); if (existingItem) { Object.assign(existingItem, { status: 'error', @@ -519,12 +513,10 @@ onMounted(() => { progress: 0 }); setTimeout(() => { - downloadList.value = downloadList.value.filter((item) => item.filename !== data.filename); + downloadList.value = downloadList.value.filter(item => item.filename !== data.filename); }, 3000); } - message.error( - t('download.message.downloadFailed', { filename: data.filename, error: data.error }) - ); + message.error(t('download.message.downloadFailed', { filename: data.filename, error: data.error })); } });