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'