From be31ae0391f0438274dc897fe1c64ac0bb876d2e Mon Sep 17 00:00:00 2001
From: kazukokawagawa <2580099704@qq.com>
Date: Fri, 5 Dec 2025 23:40:45 +0800
Subject: [PATCH 1/6] =?UTF-8?q?=E2=9C=A8=20feat:=20=E5=A2=9E=E5=8A=A0?=
=?UTF-8?q?=E4=B8=8B=E8=BD=BD=E9=87=8D=E8=AF=95=E6=8C=89=E9=92=AE=EF=BC=8C?=
=?UTF-8?q?=E8=A7=A3=E5=86=B3=E5=8D=A10%=E9=97=AE=E9=A2=98?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/components/Menu/SongListMenu.vue | 12 +++++++++++-
src/views/Download/downloading.vue | 1 -
2 files changed, 11 insertions(+), 2 deletions(-)
diff --git a/src/components/Menu/SongListMenu.vue b/src/components/Menu/SongListMenu.vue
index 7bc612fbf..afc9a1829 100644
--- a/src/components/Menu/SongListMenu.vue
+++ b/src/components/Menu/SongListMenu.vue
@@ -19,6 +19,7 @@
import type { SongType } from "@/types/main";
import { NAlert, type DropdownOption } from "naive-ui";
import { useStatusStore, useLocalStore, useDataStore, useMusicStore } from "@/stores";
+import DownloadManager from "@/utils/downloadManager";
import { renderIcon, copyData } from "@/utils/helper";
import { deleteCloudSong, importCloudSong } from "@/api/cloud";
import {
@@ -74,6 +75,8 @@ const openDropdown = (
const isCurrent = statusStore.playIndex === index;
// 是否为用户歌单
const isUserPlaylist = !!playListId && userPlaylistsData.some((pl) => pl.id === playListId);
+ // 是否正在下载或下载失败
+ const isDownloading = dataStore.downloadingSongs.some((item) => item.song.id === song.id);
// 生成菜单
nextTick().then(() => {
dropdownOptions.value = [
@@ -246,10 +249,17 @@ const openDropdown = (
{
key: "download",
label: "下载歌曲",
- show: !isLocal && type === "song",
+ show: !isLocal && type === "song" && !isDownloading,
props: { onClick: () => openDownloadSong(song) },
icon: renderIcon("Download"),
},
+ {
+ key: "retry-download",
+ label: "重试下载",
+ show: isDownloading,
+ props: { onClick: () => DownloadManager.retryDownload(song.id) },
+ icon: renderIcon("Refresh"),
+ },
];
// 显示菜单
dropdownX.value = e.clientX;
diff --git a/src/views/Download/downloading.vue b/src/views/Download/downloading.vue
index 894de7740..0fcfd0d95 100644
--- a/src/views/Download/downloading.vue
+++ b/src/views/Download/downloading.vue
@@ -73,7 +73,6 @@
Date: Sat, 6 Dec 2025 00:03:35 +0800
Subject: [PATCH 2/6] =?UTF-8?q?=E2=9C=A8=20feat:=20=E5=A2=9E=E5=8A=A0?=
=?UTF-8?q?=E5=85=A8=E9=83=A8=E9=87=8D=E8=AF=95=E7=9A=84=E5=88=B7=E6=96=B0?=
=?UTF-8?q?=E6=8C=89=E9=92=AE?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/utils/downloadManager.ts | 12 ++++++++++++
src/views/Download/layout.vue | 12 ++++++++++--
2 files changed, 22 insertions(+), 2 deletions(-)
diff --git a/src/utils/downloadManager.ts b/src/utils/downloadManager.ts
index fabb2c67e..70767fa7d 100644
--- a/src/utils/downloadManager.ts
+++ b/src/utils/downloadManager.ts
@@ -327,6 +327,18 @@ class DownloadManager {
// 继续处理队列
this.processQueue();
}
+
+ /**
+ * 重试所有下载任务
+ */
+ public retryAllDownloads() {
+ const dataStore = useDataStore();
+ const songsToRetry = dataStore.downloadingSongs.map((item) => item.song.id);
+
+ songsToRetry.forEach((id) => {
+ this.retryDownload(id);
+ });
+ }
}
export default DownloadManager.getInstance();
diff --git a/src/views/Download/layout.vue b/src/views/Download/layout.vue
index 5c72399f9..984e0711c 100644
--- a/src/views/Download/layout.vue
+++ b/src/views/Download/layout.vue
@@ -35,13 +35,21 @@
From 4fca789b9564f4b324669ef6ebc4bdc74180e0e6 Mon Sep 17 00:00:00 2001
From: kazukokawagawa <2580099704@qq.com>
Date: Sat, 6 Dec 2025 02:28:56 +0800
Subject: [PATCH 3/6] =?UTF-8?q?=F0=9F=90=9E=20fix:=20=E4=BF=AE=E5=A4=8D?=
=?UTF-8?q?=E4=B8=8B=E8=BD=BD=E5=88=97=E8=A1=A8=E7=9A=84=E6=8E=92=E5=BA=8F?=
=?UTF-8?q?=E3=80=81=E5=90=84=E9=A1=B9=E9=97=AE=E9=A2=98?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
electron/main/ipc/ipc-file.ts | 8 +-
src/stores/data.ts | 43 +++---
src/utils/downloadManager.ts | 5 +-
src/views/Download/downloading.vue | 214 ++++++++++++++++++-----------
4 files changed, 168 insertions(+), 102 deletions(-)
diff --git a/electron/main/ipc/ipc-file.ts b/electron/main/ipc/ipc-file.ts
index af2a3c538..4cb7a683f 100644
--- a/electron/main/ipc/ipc-file.ts
+++ b/electron/main/ipc/ipc-file.ts
@@ -379,10 +379,10 @@ const initFileIpc = (): void => {
songData?: any;
skipIfExist?: boolean;
} = {
- fileName: "未知文件名",
- fileType: "mp3",
- path: app.getPath("downloads"),
- },
+ fileName: "未知文件名",
+ fileType: "mp3",
+ path: app.getPath("downloads"),
+ },
): Promise<{ status: "success" | "skipped" | "error"; message?: string }> => {
try {
// 获取窗口
diff --git a/src/stores/data.ts b/src/stores/data.ts
index 0f3957a6d..833de354b 100644
--- a/src/stores/data.ts
+++ b/src/stores/data.ts
@@ -40,8 +40,8 @@ interface ListState {
song: SongType;
/** 音质 */
quality: SongLevelType;
- /** 状态:下载中 / 失败 */
- status: "downloading" | "failed";
+ /** 状态:下载中 / 等待中 / 失败 */
+ status: "downloading" | "waiting" | "failed";
/** 下载进度 */
progress: number;
/** 已传输大小 */
@@ -350,7 +350,7 @@ export const useDataStore = defineStore("data", {
this.downloadingSongs.push({
song: cloneDeep(song),
quality,
- status: "downloading",
+ status: "waiting",
progress: 0,
transferred: "0MB",
totalSize: "0MB",
@@ -358,6 +358,15 @@ export const useDataStore = defineStore("data", {
// 保存到本地存储
musicDB.setItem("downloadingSongs", cloneDeep(this.downloadingSongs));
},
+ // 更新下载状态
+ updateDownloadStatus(songId: number, status: "downloading" | "waiting" | "failed") {
+ const index = this.downloadingSongs.findIndex((item) => item.song.id === songId);
+ if (index !== -1) {
+ this.downloadingSongs[index].status = status;
+ // 强制触发响应式更新 (Fix: 下一首歌曲状态更新UI不变化的问题)
+ this.downloadingSongs = [...this.downloadingSongs];
+ }
+ },
// 更新下载进度
updateDownloadProgress(
songId: number,
@@ -370,7 +379,7 @@ export const useDataStore = defineStore("data", {
item.progress = progress;
item.transferred = transferred;
item.totalSize = totalSize;
- // 进度更新过于频繁,不再实时保存到本地存储,仅在添加/删除时保存
+ // 进度更新过于频繁,不需要强制更新整个数组,以免影响性能
}
},
// 移除正在下载的歌曲(下载失败时)
@@ -383,23 +392,25 @@ export const useDataStore = defineStore("data", {
},
// 标记下载失败(保留在列表中)
markDownloadFailed(songId: number) {
- const item = this.downloadingSongs.find((item) => item.song.id === songId);
- if (item) {
- item.status = "failed";
- item.progress = 0;
- item.transferred = "0MB";
- item.totalSize = "0MB";
+ const index = this.downloadingSongs.findIndex((item) => item.song.id === songId);
+ if (index !== -1) {
+ this.downloadingSongs[index].status = "failed";
+ this.downloadingSongs[index].progress = 0;
+ this.downloadingSongs[index].transferred = "0MB";
+ this.downloadingSongs[index].totalSize = "0MB";
+ this.downloadingSongs = [...this.downloadingSongs];
musicDB.setItem("downloadingSongs", cloneDeep(this.downloadingSongs));
}
},
// 重置下载任务状态(用于重试)
resetDownloadingSong(songId: number) {
- const item = this.downloadingSongs.find((item) => item.song.id === songId);
- if (item) {
- item.status = "downloading";
- item.progress = 0;
- item.transferred = "0MB";
- item.totalSize = "0MB";
+ const index = this.downloadingSongs.findIndex((item) => item.song.id === songId);
+ if (index !== -1) {
+ this.downloadingSongs[index].status = "waiting";
+ this.downloadingSongs[index].progress = 0;
+ this.downloadingSongs[index].transferred = "0MB";
+ this.downloadingSongs[index].totalSize = "0MB";
+ this.downloadingSongs = [...this.downloadingSongs];
}
},
},
diff --git a/src/utils/downloadManager.ts b/src/utils/downloadManager.ts
index 70767fa7d..8bef3f53e 100644
--- a/src/utils/downloadManager.ts
+++ b/src/utils/downloadManager.ts
@@ -118,7 +118,7 @@ class DownloadManager {
const total = (totalBytes / 1024 / 1024).toFixed(2) + "MB";
dataStore.updateDownloadProgress(
song.id,
- Number((percent * 100).toFixed(0)),
+ Number((percent * 100).toFixed(1)),
transferred,
total,
);
@@ -126,6 +126,9 @@ class DownloadManager {
removeListener = window.electron.ipcRenderer.on("download-progress", progressHandler);
}
+ // 更新状态为下载中
+ dataStore.updateDownloadStatus(song.id, "downloading");
+
// 开始下载
try {
const result = await this.processDownload({
diff --git a/src/views/Download/downloading.vue b/src/views/Download/downloading.vue
index 0fcfd0d95..a4d3eea81 100644
--- a/src/views/Download/downloading.vue
+++ b/src/views/Download/downloading.vue
@@ -11,92 +11,98 @@
-
-
-
-
-
- {{ index + 1 }}
-
-
-
-
-
-
- {{ item.song.name }}
-
-
-
- {{
- Array.isArray(item.song.artists)
- ? item.song.artists.map((a) => a.name).join(" / ")
- : item.song.artists
- }}
-
-
+
+
+
+
+ {{ index + 1 }}
+
+
+
+
+
+
+ {{ item.song.name }}
+
+
+
+ {{
+ Array.isArray(item.song.artists)
+ ? item.song.artists.map((a) => a.name).join(" / ")
+ : item.song.artists
+ }}
+
-
-
-
-
- {{ item.progress }}%
-
- {{ item.transferred }} / {{ item.totalSize }}
-
-
-
+
+
+
+
+
+ {{ item.progress }}%
+
+ {{ item.transferred }} / {{ item.totalSize }}
+
-
- 下载失败
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+ 等待下载...
+
+
+
+ 下载失败
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
@@ -104,10 +110,23 @@