mirror of
https://github.com/algerkong/AlgerMusicPlayer.git
synced 2026-04-24 08:07:23 +08:00
🐞 fix: 修复下载管理 切换tab程序卡死问题
This commit is contained in:
@@ -44,5 +44,6 @@ export default {
|
|||||||
message: {
|
message: {
|
||||||
downloadComplete: '{filename} download completed',
|
downloadComplete: '{filename} download completed',
|
||||||
downloadFailed: '{filename} download failed: {error}'
|
downloadFailed: '{filename} download failed: {error}'
|
||||||
}
|
},
|
||||||
|
loading: 'Loading...'
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -43,5 +43,6 @@ export default {
|
|||||||
message: {
|
message: {
|
||||||
downloadComplete: '{filename} 下载完成',
|
downloadComplete: '{filename} 下载完成',
|
||||||
downloadFailed: '{filename} 下载失败: {error}'
|
downloadFailed: '{filename} 下载失败: {error}'
|
||||||
}
|
},
|
||||||
|
loading: '加载中...'
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -122,20 +122,37 @@ export function initializeFileManager() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// 获取已下载音乐列表
|
// 获取已下载音乐列表
|
||||||
ipcMain.handle('get-downloaded-music', () => {
|
ipcMain.handle('get-downloaded-music', async () => {
|
||||||
try {
|
try {
|
||||||
const store = new Store();
|
const store = new Store();
|
||||||
const songInfos = store.get('downloadedSongs', {}) as Record<string, any>;
|
const songInfos = store.get('downloadedSongs', {}) as Record<string, any>;
|
||||||
|
|
||||||
// 过滤出实际存在的文件
|
// 异步处理文件存在性检查
|
||||||
const validSongs = Object.entries(songInfos)
|
const entriesArray = Object.entries(songInfos);
|
||||||
.filter(([path]) => fs.existsSync(path))
|
const validEntriesPromises = await Promise.all(
|
||||||
.map(([_, info]) => info)
|
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));
|
.sort((a, b) => (b.downloadTime || 0) - (a.downloadTime || 0));
|
||||||
|
|
||||||
// 更新存储,移除不存在的文件记录
|
// 更新存储,移除不存在的文件记录
|
||||||
const newSongInfos = validSongs.reduce((acc, song) => {
|
const newSongInfos = validSongs.reduce((acc, song) => {
|
||||||
acc[song.path] = song;
|
if (song && song.path) {
|
||||||
|
acc[song.path] = song;
|
||||||
|
}
|
||||||
return acc;
|
return acc;
|
||||||
}, {});
|
}, {});
|
||||||
store.set('downloadedSongs', newSongInfos);
|
store.set('downloadedSongs', newSongInfos);
|
||||||
@@ -175,6 +192,13 @@ export function initializeFileManager() {
|
|||||||
downloadStore.set('history', []);
|
downloadStore.set('history', []);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// 添加清除已下载音乐记录的处理函数
|
||||||
|
ipcMain.handle('clear-downloaded-music', () => {
|
||||||
|
const store = new Store();
|
||||||
|
store.set('downloadedSongs', {});
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
|
||||||
// 添加清除音频缓存的处理函数
|
// 添加清除音频缓存的处理函数
|
||||||
ipcMain.on('clear-audio-cache', () => {
|
ipcMain.on('clear-audio-cache', () => {
|
||||||
audioCacheStore.set('cache', {});
|
audioCacheStore.set('cache', {});
|
||||||
|
|||||||
@@ -90,7 +90,11 @@
|
|||||||
<!-- 已下载列表 -->
|
<!-- 已下载列表 -->
|
||||||
<n-tab-pane name="downloaded" :tab="t('download.tabs.downloaded')" class="h-full">
|
<n-tab-pane name="downloaded" :tab="t('download.tabs.downloaded')" class="h-full">
|
||||||
<div class="downloaded-list">
|
<div class="downloaded-list">
|
||||||
<div v-if="downloadedList.length === 0" class="empty-tip">
|
<div v-if="isLoadingDownloaded" class="loading-tip">
|
||||||
|
<n-spin size="medium" />
|
||||||
|
<span class="loading-text">{{ t('download.loading') }}</span>
|
||||||
|
</div>
|
||||||
|
<div v-else-if="downloadedList.length === 0" class="empty-tip">
|
||||||
<n-empty :description="t('download.empty.noDownloaded')" />
|
<n-empty :description="t('download.empty.noDownloaded')" />
|
||||||
</div>
|
</div>
|
||||||
<div v-else class="downloaded-content">
|
<div v-else class="downloaded-content">
|
||||||
@@ -262,9 +266,7 @@ const downloadedList = ref<DownloadedItem[]>(
|
|||||||
JSON.parse(localStorage.getItem('downloadedList') || '[]')
|
JSON.parse(localStorage.getItem('downloadedList') || '[]')
|
||||||
);
|
);
|
||||||
|
|
||||||
const downList = computed(() => {
|
const downList = computed(() => downloadedList.value);
|
||||||
return (downloadedList.value as DownloadedItem[]).reverse();
|
|
||||||
});
|
|
||||||
|
|
||||||
// 计算下载中的任务数量
|
// 计算下载中的任务数量
|
||||||
const downloadingCount = computed(() => {
|
const downloadingCount = computed(() => {
|
||||||
@@ -350,38 +352,25 @@ const handleDelete = (item: DownloadedItem) => {
|
|||||||
|
|
||||||
// 确认删除
|
// 确认删除
|
||||||
const confirmDelete = async () => {
|
const confirmDelete = async () => {
|
||||||
if (!itemToDelete.value) return;
|
const item = itemToDelete.value;
|
||||||
|
if (!item) return;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const success = await window.electron.ipcRenderer.invoke(
|
const success = await window.electron.ipcRenderer.invoke(
|
||||||
'delete-downloaded-music',
|
'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) {
|
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'));
|
message.success(t('download.delete.success'));
|
||||||
} else {
|
} else {
|
||||||
message.warning(t('download.delete.fileNotFound'));
|
message.warning(t('download.delete.fileNotFound'));
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Failed to delete music:', 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'));
|
message.warning(t('download.delete.recordRemoved'));
|
||||||
} finally {
|
} finally {
|
||||||
showDeleteConfirm.value = false;
|
showDeleteConfirm.value = false;
|
||||||
@@ -393,11 +382,18 @@ const confirmDelete = async () => {
|
|||||||
const showClearConfirm = ref(false);
|
const showClearConfirm = ref(false);
|
||||||
|
|
||||||
// 清空下载记录
|
// 清空下载记录
|
||||||
const clearDownloadRecords = () => {
|
const clearDownloadRecords = async () => {
|
||||||
localStorage.setItem('downloadedList', '[]');
|
try {
|
||||||
downloadedList.value = [];
|
downloadedList.value = [];
|
||||||
message.success(t('download.clear.success'));
|
localStorage.setItem('downloadedList', '[]');
|
||||||
showClearConfirm.value = false;
|
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);
|
// playerStore.setIsPlay(true);
|
||||||
// };
|
// };
|
||||||
|
|
||||||
|
// 添加加载状态
|
||||||
|
const isLoadingDownloaded = ref(false);
|
||||||
|
|
||||||
// 获取已下载音乐列表
|
// 获取已下载音乐列表
|
||||||
const refreshDownloadedList = async () => {
|
const refreshDownloadedList = async () => {
|
||||||
|
if (isLoadingDownloaded.value) return; // 防止重复加载
|
||||||
|
|
||||||
try {
|
try {
|
||||||
let saveList: any = [];
|
isLoadingDownloaded.value = true;
|
||||||
const list = await window.electron.ipcRenderer.invoke('get-downloaded-music');
|
const list = await window.electron.ipcRenderer.invoke('get-downloaded-music');
|
||||||
|
|
||||||
if (!Array.isArray(list) || list.length === 0) {
|
if (!Array.isArray(list) || list.length === 0) {
|
||||||
saveList = [];
|
downloadedList.value = [];
|
||||||
|
localStorage.setItem('downloadedList', '[]');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const songIds = list.filter((item) => item.id).map((item) => item.id);
|
const songIds = list.filter(item => item.id).map(item => item.id);
|
||||||
|
if (songIds.length === 0) {
|
||||||
// 如果有歌曲ID,获取详细信息
|
downloadedList.value = list;
|
||||||
if (songIds.length > 0) {
|
localStorage.setItem('downloadedList', JSON.stringify(list));
|
||||||
try {
|
return;
|
||||||
const detailRes = await getMusicDetail(songIds);
|
}
|
||||||
const songDetails = detailRes.data.songs.reduce((acc, song) => {
|
|
||||||
acc[song.id] = song;
|
try {
|
||||||
return acc;
|
const detailRes = await getMusicDetail(songIds);
|
||||||
}, {});
|
const songDetails = detailRes.data.songs.reduce((acc, song) => {
|
||||||
|
acc[song.id] = song;
|
||||||
saveList = list.map((item) => {
|
return acc;
|
||||||
const songDetail = songDetails[item.id];
|
}, {});
|
||||||
return {
|
|
||||||
...item,
|
const updatedList = list.map(item => ({
|
||||||
picUrl: songDetail?.al?.picUrl || item.picUrl || '/images/default_cover.png',
|
...item,
|
||||||
ar: songDetail?.ar || item.ar || [{ name: t('download.localMusic') }]
|
picUrl: songDetails[item.id]?.al?.picUrl || item.picUrl || '/images/default_cover.png',
|
||||||
};
|
ar: songDetails[item.id]?.ar || item.ar || [{ name: t('download.localMusic') }]
|
||||||
});
|
}));
|
||||||
} catch (detailError) {
|
|
||||||
console.error('Failed to get music details:', detailError);
|
downloadedList.value = updatedList;
|
||||||
saveList = list;
|
localStorage.setItem('downloadedList', JSON.stringify(updatedList));
|
||||||
}
|
} catch (error) {
|
||||||
} else {
|
console.error('Failed to get music details:', error);
|
||||||
saveList = list;
|
downloadedList.value = list;
|
||||||
|
localStorage.setItem('downloadedList', JSON.stringify(list));
|
||||||
}
|
}
|
||||||
setLocalDownloadedList(saveList);
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Failed to get downloaded music list:', error);
|
console.error('Failed to get downloaded music list:', error);
|
||||||
downloadedList.value = [];
|
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(
|
watch(
|
||||||
() => showDrawer.value,
|
() => showDrawer.value,
|
||||||
(newVal) => {
|
(newVal) => {
|
||||||
if (newVal) {
|
if (newVal && !isLoadingDownloaded.value) {
|
||||||
refreshDownloadedList();
|
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) {
|
if (data.success) {
|
||||||
// 从下载列表中移除
|
downloadList.value = downloadList.value.filter(item => item.filename !== data.filename);
|
||||||
downloadList.value = downloadList.value.filter((item) => item.filename !== data.filename);
|
// 延迟刷新已下载列表,避免文件系统未完全写入
|
||||||
// 刷新已下载列表
|
setTimeout(() => refreshDownloadedList(), 500);
|
||||||
refreshDownloadedList();
|
|
||||||
message.success(t('download.message.downloadComplete', { filename: data.filename }));
|
message.success(t('download.message.downloadComplete', { filename: data.filename }));
|
||||||
} else {
|
} else {
|
||||||
const existingItem = downloadList.value.find((item) => item.filename === data.filename);
|
const existingItem = downloadList.value.find(item => item.filename === data.filename);
|
||||||
if (existingItem) {
|
if (existingItem) {
|
||||||
Object.assign(existingItem, {
|
Object.assign(existingItem, {
|
||||||
status: 'error',
|
status: 'error',
|
||||||
@@ -519,12 +513,10 @@ onMounted(() => {
|
|||||||
progress: 0
|
progress: 0
|
||||||
});
|
});
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
downloadList.value = downloadList.value.filter((item) => item.filename !== data.filename);
|
downloadList.value = downloadList.value.filter(item => item.filename !== data.filename);
|
||||||
}, 3000);
|
}, 3000);
|
||||||
}
|
}
|
||||||
message.error(
|
message.error(t('download.message.downloadFailed', { filename: data.filename, error: data.error }));
|
||||||
t('download.message.downloadFailed', { filename: data.filename, error: data.error })
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user