From c387cc24873604645cd048822294a1a00eb60a67 Mon Sep 17 00:00:00 2001 From: liumangmang Date: Wed, 18 Mar 2026 23:02:31 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20Local->Many=20=E4=BC=A0=E8=BE=93?= =?UTF-8?q?=E7=AD=89=E5=BE=85=E5=90=8E=E7=AB=AF=E4=BB=BB=E5=8A=A1=E7=9C=9F?= =?UTF-8?q?=E6=AD=A3=E5=AE=8C=E6=88=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 改用 uploadFile + subscribeUploadProgress 替代 uploadFileWithProgress - 只有后端任务状态为 success 才标记成功 - 修复显示成功但远端无文件的问题 --- frontend/src/stores/transfers.ts | 48 +++++++++++++------------------- 1 file changed, 19 insertions(+), 29 deletions(-) diff --git a/frontend/src/stores/transfers.ts b/frontend/src/stores/transfers.ts index d207a1b..081cabc 100644 --- a/frontend/src/stores/transfers.ts +++ b/frontend/src/stores/transfers.ts @@ -1,7 +1,7 @@ import { defineStore } from 'pinia' import { ref, computed } from 'vue' -import { createRemoteTransferTask, subscribeRemoteTransferProgress, uploadFileWithProgress } from '../api/sftp' +import { createRemoteTransferTask, subscribeRemoteTransferProgress, uploadFile, subscribeUploadProgress } from '../api/sftp' export type TransferMode = 'LOCAL_TO_MANY' | 'REMOTE_TO_MANY' export type TransferItemStatus = 'queued' | 'running' | 'success' | 'error' | 'cancelled' @@ -188,17 +188,11 @@ export const useTransfersStore = defineStore('transfers', () => { runs.value = [run, ...runs.value] - const activeXhrs: XMLHttpRequest[] = [] + let cancelled = false const unsubscribers: (() => void)[] = [] controllers.set(runId, { abortAll: () => { - for (const xhr of activeXhrs) { - try { - xhr.abort() - } catch { - // ignore - } - } + cancelled = true }, unsubscribers, }) @@ -211,7 +205,7 @@ export const useTransfersStore = defineStore('transfers', () => { if (itemIndex === -1) continue const item = runItems[itemIndex]! tasks.push(async () => { - if (item.status === 'cancelled') return + if (item.status === 'cancelled' || cancelled) return item.status = 'running' item.progress = 0 item.startedAt = now() @@ -219,28 +213,24 @@ export const useTransfersStore = defineStore('transfers', () => { const stopPseudoProgress = startPseudoProgress(item) try { - const xhr = uploadFileWithProgress(connectionId, targetDir || '', file) - activeXhrs.push(xhr) + // 发起上传并获取 taskId + const uploadRes = await uploadFile(connectionId, targetDir || '', file) + const taskId = uploadRes.data.taskId + // 订阅上传任务进度,等待真正完成 await new Promise((resolve, reject) => { - let lastTick = 0 - xhr.onProgress = (percent) => { - console.log('[Transfers] onProgress callback fired:', percent, 'item:', item.label) - const t = now() - if (t - lastTick < 100 && percent !== 100) return - lastTick = t - const newProgress = Math.max(item.progress || 0, Math.max(0, Math.min(100, percent))) - console.log('[Transfers] Updating item.progress from', item.progress, 'to', newProgress) - item.progress = newProgress + const unsubscribe = subscribeUploadProgress(taskId, (task) => { + const progress = Math.max(0, Math.min(100, task.progress || 0)) + item.progress = progress runs.value = [...runs.value] - } - console.log('[Transfers] Set onProgress callback for:', item.label) - xhr.onload = () => { - if (xhr.status >= 200 && xhr.status < 300) resolve() - else reject(new Error(xhr.responseText || `HTTP ${xhr.status}`)) - } - xhr.onerror = () => reject(new Error('Network error')) - xhr.onabort = () => reject(new Error('Cancelled')) + + if (task.status === 'success') { + resolve() + } else if (task.status === 'error') { + reject(new Error(task.error || 'Upload failed')) + } + }) + unsubscribers.push(unsubscribe) }) item.status = 'success'