From 687cf2943e2f01e05a66f644a339db1dbcc74f02 Mon Sep 17 00:00:00 2001
From: kjqwer <2990346238@qq.com>
Date: Thu, 28 Aug 2025 11:37:03 +0800
Subject: [PATCH] =?UTF-8?q?=E4=B8=8B=E8=BD=BD=E9=A1=B5=E9=9D=A2=E5=8D=A1?=
=?UTF-8?q?=E4=B8=BB=E9=97=AE=E9=A2=98=E4=BF=AE=E5=A4=8D?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
backend/services/download-executor.js | 62 ++++++++++++++
backend/services/download.js | 12 ++-
ui/src/views/DownloadsView.vue | 111 +++++++++++++++++++++++---
3 files changed, 171 insertions(+), 14 deletions(-)
diff --git a/backend/services/download-executor.js b/backend/services/download-executor.js
index 2139614..bc76eb4 100644
--- a/backend/services/download-executor.js
+++ b/backend/services/download-executor.js
@@ -25,6 +25,12 @@ class DownloadExecutor {
break;
}
+ // 检查是否应该暂停
+ if (this.shouldPause(task.id)) {
+ console.log('任务已暂停,停止下载:', task.id);
+ break;
+ }
+
// 从图片对象中获取指定尺寸的URL
const imageObj = images[index];
let imageUrl;
@@ -158,6 +164,12 @@ class DownloadExecutor {
break;
}
+ // 检查是否应该暂停
+ if (this.shouldPause(task.id)) {
+ console.log('批量下载任务已暂停,停止下载:', task.id);
+ break;
+ }
+
const batch = artworkIds.slice(i, i + concurrent);
const batchPromises = batch.map(async artworkId => {
try {
@@ -503,6 +515,56 @@ class DownloadExecutor {
const match = url.match(/\.([a-zA-Z0-9]+)(?:\?|$)/);
return match ? match[1] : 'jpg';
}
+
+ /**
+ * 恢复暂停的任务
+ */
+ async resumeTask(taskId) {
+ const task = this.taskManager.getTask(taskId);
+ if (!task) {
+ throw new Error('任务不存在');
+ }
+
+ if (task.status !== 'paused') {
+ throw new Error('任务状态不是暂停状态');
+ }
+
+ // 根据任务类型重新开始下载
+ if (task.type === 'artwork') {
+ // 重新获取作品信息和图片URL
+ const artworkResult = await this.downloadService.artworkService.getArtwork(task.artwork_id);
+ if (!artworkResult.success) {
+ throw new Error(`获取作品信息失败: ${artworkResult.error}`);
+ }
+
+ const imagesResult = await this.downloadService.artworkService.getArtworkImages(task.artwork_id, 'original');
+ if (!imagesResult.success) {
+ throw new Error(`获取图片URL失败: ${imagesResult.error}`);
+ }
+
+ const artwork = artworkResult.data;
+ const images = imagesResult.data.images;
+ const artworkDir = await this.fileManager.getArtworkDirectory(artwork);
+
+ // 重新开始下载
+ this.executeArtworkDownload(task, images, 'original', artworkDir, artwork);
+ } else if (task.type === 'batch' || task.type === 'artist') {
+ // 批量下载和作者下载的恢复逻辑
+ // 这里需要根据具体实现来恢复
+ console.log('恢复批量下载任务:', taskId);
+ // TODO: 实现批量下载的恢复逻辑
+ }
+
+ return { success: true };
+ }
+
+ /**
+ * 检查任务是否应该暂停
+ */
+ shouldPause(taskId) {
+ const task = this.taskManager.getTask(taskId);
+ return task && task.status === 'paused';
+ }
}
module.exports = DownloadExecutor;
diff --git a/backend/services/download.js b/backend/services/download.js
index eb3293d..1bbd1a2 100644
--- a/backend/services/download.js
+++ b/backend/services/download.js
@@ -134,11 +134,17 @@ class DownloadService {
return { success: false, error: '任务状态不是暂停状态' };
}
+ // 更新任务状态为下载中
await this.taskManager.updateTask(taskId, { status: 'downloading' });
- this.progressManager.notifyProgressUpdate(taskId, task);
+
+ // 通知进度更新
+ const updatedTask = this.taskManager.getTask(taskId);
+ this.progressManager.notifyProgressUpdate(taskId, updatedTask);
- // 重新开始下载
- return this.downloadArtwork(task.artwork_id, { skipExisting: false });
+ // 重新开始下载执行
+ this.downloadExecutor.resumeTask(taskId);
+
+ return { success: true, data: updatedTask };
}
// 代理方法 - 历史记录管理
diff --git a/ui/src/views/DownloadsView.vue b/ui/src/views/DownloadsView.vue
index 824af2b..81ff890 100644
--- a/ui/src/views/DownloadsView.vue
+++ b/ui/src/views/DownloadsView.vue
@@ -62,7 +62,10 @@
@@ -205,7 +214,7 @@ const history = ref([]);
// SSE连接管理
const sseConnections = ref