90
90
<!-- 已下载列表 -->
91
91
<n-tab-pane name =" downloaded" :tab =" t('download.tabs.downloaded')" class =" h-full" >
92
92
<div class =" downloaded-list" >
93
- <div v-if =" downloadedList.length === 0" class =" empty-tip" >
93
+ <div v-if =" isLoadingDownloaded" class =" loading-tip" >
94
+ <n-spin size =" medium" />
95
+ <span class =" loading-text" >{{ t('download.loading') }}</span >
96
+ </div >
97
+ <div v-else-if =" downloadedList.length === 0" class =" empty-tip" >
94
98
<n-empty :description =" t('download.empty.noDownloaded')" />
95
99
</div >
96
100
<div v-else class =" downloaded-content" >
@@ -262,9 +266,7 @@ const downloadedList = ref<DownloadedItem[]>(
262
266
JSON .parse (localStorage .getItem (' downloadedList' ) || ' []' )
263
267
);
264
268
265
- const downList = computed (() => {
266
- return (downloadedList .value as DownloadedItem []).reverse ();
267
- });
269
+ const downList = computed (() => downloadedList .value );
268
270
269
271
// 计算下载中的任务数量
270
272
const downloadingCount = computed (() => {
@@ -350,38 +352,25 @@ const handleDelete = (item: DownloadedItem) => {
350
352
351
353
// 确认删除
352
354
const confirmDelete = async () => {
353
- if (! itemToDelete .value ) return ;
355
+ const item = itemToDelete .value ;
356
+ if (! item ) return ;
354
357
355
358
try {
356
359
const success = await window .electron .ipcRenderer .invoke (
357
360
' delete-downloaded-music' ,
358
- itemToDelete .value .path
359
- );
360
-
361
- // 无论删除文件是否成功,都从记录中移除
362
- localStorage .setItem (
363
- ' downloadedList' ,
364
- JSON .stringify (
365
- downloadedList .value .filter ((item ) => item .id !== (itemToDelete .value as DownloadedItem ).id )
366
- )
361
+ item .path
367
362
);
368
- await refreshDownloadedList ();
369
363
370
364
if (success ) {
365
+ const newList = downloadedList .value .filter (i => i .id !== item .id );
366
+ downloadedList .value = newList ;
367
+ localStorage .setItem (' downloadedList' , JSON .stringify (newList ));
371
368
message .success (t (' download.delete.success' ));
372
369
} else {
373
370
message .warning (t (' download.delete.fileNotFound' ));
374
371
}
375
372
} catch (error ) {
376
373
console .error (' Failed to delete music:' , error );
377
- // 即使删除文件出错,也从记录中移除
378
- localStorage .setItem (
379
- ' downloadedList' ,
380
- JSON .stringify (
381
- downloadedList .value .filter ((item ) => item .id !== (itemToDelete .value as DownloadedItem ).id )
382
- )
383
- );
384
- await refreshDownloadedList ();
385
374
message .warning (t (' download.delete.recordRemoved' ));
386
375
} finally {
387
376
showDeleteConfirm .value = false ;
@@ -393,11 +382,18 @@ const confirmDelete = async () => {
393
382
const showClearConfirm = ref (false );
394
383
395
384
// 清空下载记录
396
- const clearDownloadRecords = () => {
397
- localStorage .setItem (' downloadedList' , ' []' );
398
- downloadedList .value = [];
399
- message .success (t (' download.clear.success' ));
400
- showClearConfirm .value = false ;
385
+ const clearDownloadRecords = async () => {
386
+ try {
387
+ downloadedList .value = [];
388
+ localStorage .setItem (' downloadedList' , ' []' );
389
+ await window .electron .ipcRenderer .invoke (' clear-downloaded-music' );
390
+ message .success (t (' download.clear.success' ));
391
+ } catch (error ) {
392
+ console .error (' Failed to clear download records:' , error );
393
+ message .error (t (' download.clear.failed' ));
394
+ } finally {
395
+ showClearConfirm .value = false ;
396
+ }
401
397
};
402
398
403
399
// 播放音乐
@@ -407,65 +403,64 @@ const clearDownloadRecords = () => {
407
403
// playerStore.setIsPlay(true);
408
404
// };
409
405
406
+ // 添加加载状态
407
+ const isLoadingDownloaded = ref (false );
408
+
410
409
// 获取已下载音乐列表
411
410
const refreshDownloadedList = async () => {
411
+ if (isLoadingDownloaded .value ) return ; // 防止重复加载
412
+
412
413
try {
413
- let saveList : any = [] ;
414
+ isLoadingDownloaded . value = true ;
414
415
const list = await window .electron .ipcRenderer .invoke (' get-downloaded-music' );
416
+
415
417
if (! Array .isArray (list ) || list .length === 0 ) {
416
- saveList = [];
418
+ downloadedList .value = [];
419
+ localStorage .setItem (' downloadedList' , ' []' );
417
420
return ;
418
421
}
419
422
420
- const songIds = list .filter ((item ) => item .id ).map ((item ) => item .id );
421
-
422
- // 如果有歌曲ID,获取详细信息
423
- if (songIds .length > 0 ) {
424
- try {
425
- const detailRes = await getMusicDetail (songIds );
426
- const songDetails = detailRes .data .songs .reduce ((acc , song ) => {
427
- acc [song .id ] = song ;
428
- return acc ;
429
- }, {});
430
-
431
- saveList = list .map ((item ) => {
432
- const songDetail = songDetails [item .id ];
433
- return {
434
- ... item ,
435
- picUrl: songDetail ?.al ?.picUrl || item .picUrl || ' /images/default_cover.png' ,
436
- ar: songDetail ?.ar || item .ar || [{ name: t (' download.localMusic' ) }]
437
- };
438
- });
439
- } catch (detailError ) {
440
- console .error (' Failed to get music details:' , detailError );
441
- saveList = list ;
442
- }
443
- } else {
444
- saveList = list ;
423
+ const songIds = list .filter (item => item .id ).map (item => item .id );
424
+ if (songIds .length === 0 ) {
425
+ downloadedList .value = list ;
426
+ localStorage .setItem (' downloadedList' , JSON .stringify (list ));
427
+ return ;
428
+ }
429
+
430
+ try {
431
+ const detailRes = await getMusicDetail (songIds );
432
+ const songDetails = detailRes .data .songs .reduce ((acc , song ) => {
433
+ acc [song .id ] = song ;
434
+ return acc ;
435
+ }, {});
436
+
437
+ const updatedList = list .map (item => ({
438
+ ... item ,
439
+ picUrl: songDetails [item .id ]?.al ?.picUrl || item .picUrl || ' /images/default_cover.png' ,
440
+ ar: songDetails [item .id ]?.ar || item .ar || [{ name: t (' download.localMusic' ) }]
441
+ }));
442
+
443
+ downloadedList .value = updatedList ;
444
+ localStorage .setItem (' downloadedList' , JSON .stringify (updatedList ));
445
+ } catch (error ) {
446
+ console .error (' Failed to get music details:' , error );
447
+ downloadedList .value = list ;
448
+ localStorage .setItem (' downloadedList' , JSON .stringify (list ));
445
449
}
446
- setLocalDownloadedList (saveList );
447
450
} catch (error ) {
448
451
console .error (' Failed to get downloaded music list:' , error );
449
452
downloadedList .value = [];
453
+ localStorage .setItem (' downloadedList' , ' []' );
454
+ } finally {
455
+ isLoadingDownloaded .value = false ;
450
456
}
451
457
};
452
458
453
- const setLocalDownloadedList = (list : DownloadedItem []) => {
454
- const localList = localStorage .getItem (' downloadedList' );
455
- // 合并 去重
456
- const saveList = [... (localList ? JSON .parse (localList ) : []), ... list ];
457
- const uniqueList = saveList .filter (
458
- (item , index , self ) => index === self .findIndex ((t ) => t .id === item .id )
459
- );
460
- localStorage .setItem (' downloadedList' , JSON .stringify (uniqueList ));
461
- downloadedList .value = uniqueList ;
462
- };
463
-
464
459
// 监听抽屉显示状态
465
460
watch (
466
461
() => showDrawer .value ,
467
462
(newVal ) => {
468
- if (newVal ) {
463
+ if (newVal && ! isLoadingDownloaded . value ) {
469
464
refreshDownloadedList ();
470
465
}
471
466
}
@@ -503,28 +498,25 @@ onMounted(() => {
503
498
});
504
499
505
500
// 监听下载完成
506
- window .electron .ipcRenderer .on (' music-download-complete' , (_ , data ) => {
501
+ window .electron .ipcRenderer .on (' music-download-complete' , async (_ , data ) => {
507
502
if (data .success ) {
508
- // 从下载列表中移除
509
- downloadList .value = downloadList .value .filter ((item ) => item .filename !== data .filename );
510
- // 刷新已下载列表
511
- refreshDownloadedList ();
503
+ downloadList .value = downloadList .value .filter (item => item .filename !== data .filename );
504
+ // 延迟刷新已下载列表,避免文件系统未完全写入
505
+ setTimeout (() => refreshDownloadedList (), 500 );
512
506
message .success (t (' download.message.downloadComplete' , { filename: data .filename }));
513
507
} else {
514
- const existingItem = downloadList .value .find (( item ) => item .filename === data .filename );
508
+ const existingItem = downloadList .value .find (item => item .filename === data .filename );
515
509
if (existingItem ) {
516
510
Object .assign (existingItem , {
517
511
status: ' error' ,
518
512
error: data .error ,
519
513
progress: 0
520
514
});
521
515
setTimeout (() => {
522
- downloadList .value = downloadList .value .filter (( item ) => item .filename !== data .filename );
516
+ downloadList .value = downloadList .value .filter (item => item .filename !== data .filename );
523
517
}, 3000 );
524
518
}
525
- message .error (
526
- t (' download.message.downloadFailed' , { filename: data .filename , error: data .error })
527
- );
519
+ message .error (t (' download.message.downloadFailed' , { filename: data .filename , error: data .error }));
528
520
}
529
521
});
530
522
0 commit comments