From 10aff74072ea05ce0696daf66b03a7b4cfc8d6e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BA=8C=E4=B8=AB=E8=AE=B2=E6=A2=B5?= Date: Fri, 26 Jun 2026 18:50:25 +0800 Subject: [PATCH] =?UTF-8?q?feat(export-tracker):=20=E5=A2=9E=E5=BC=BA?= =?UTF-8?q?=E5=AF=BC=E5=87=BA=E4=BB=BB=E5=8A=A1=E8=B7=9F=E8=B8=AA=E5=8A=9F?= =?UTF-8?q?=E8=83=BD=20(#1958)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 添加了对数据库导出、SQL 文件导出和数据传输任务的支持 - 引入了新的状态和错误处理机制 - 实现了任务的重叠检查,防止同时进行相同目标表的数据传输 - 更新了 API 调用以支持新的任务类型 - 增加了相应的国际化文本 - 添加了单元测试以确保新功能的正确性 --- .../export/DatabaseExportDialog.vue | 20 ++ .../export/ExportProgressPopover.vue | 99 ++++-- .../src/components/layout/AppDialogs.vue | 4 +- .../sql-file/SqlFileExecutionDialog.vue | 33 +- .../transfer/DataTransferDialog.vue | 196 ++--------- .../src/composables/useExportTracker.ts | 255 +++++++++++++- apps/desktop/src/i18n/locales/en.ts | 20 +- apps/desktop/src/i18n/locales/zh-CN.ts | 20 +- apps/desktop/src/lib/http.ts | 2 +- apps/desktop/src/lib/tauri.ts | 2 +- apps/desktop/src/lib/transferProgressState.ts | 19 +- crates/dbx-web/src/routes/transfer.rs | 14 +- .../app-tests/transferProgressState.test.ts | 24 +- packages/app-tests/useExportTracker.test.ts | 323 ++++++++++++++++++ src-tauri/src/commands/transfer.rs | 15 +- 15 files changed, 838 insertions(+), 208 deletions(-) create mode 100644 packages/app-tests/useExportTracker.test.ts diff --git a/apps/desktop/src/components/export/DatabaseExportDialog.vue b/apps/desktop/src/components/export/DatabaseExportDialog.vue index 9cad3c2770..934641b666 100644 --- a/apps/desktop/src/components/export/DatabaseExportDialog.vue +++ b/apps/desktop/src/components/export/DatabaseExportDialog.vue @@ -17,9 +17,11 @@ import { isTauriRuntime } from "@/lib/tauriRuntime"; import { useToast } from "@/composables/useToast"; import { Input } from "@/components/ui/input"; import { Download, Square, CheckSquare, Search, X } from "@lucide/vue"; +import { useExportTracker } from "@/composables/useExportTracker"; const { t } = useI18n(); const { toast } = useToast(); +const { addDatabaseExportTask, updateDatabaseExportTask } = useExportTracker(); const open = defineModel("open", { default: false }); const store = useConnectionStore(); @@ -203,9 +205,12 @@ async function startExport() { batchSize: 1000, }; + addDatabaseExportTask(exportId.value, database.value || "database", filePath); + try { await api.exportDatabaseSql(request, (progress) => { exportProgress.value = { ...progress }; + updateDatabaseExportTask(progress.exportId, progress); if (progress.status === "Done") { exportDone.value = true; isExporting.value = false; @@ -220,6 +225,18 @@ async function startExport() { }); } catch (e: any) { exportError.value = e?.message || String(e); + const lastProgress = exportProgress.value as api.ExportProgress | null; + const fallbackProgress: api.ExportProgress = { + exportId: exportId.value, + currentObject: database.value || "database", + objectIndex: lastProgress?.objectIndex ?? 0, + totalObjects: lastProgress?.totalObjects ?? 0, + rowsExported: lastProgress?.rowsExported ?? 0, + totalRows: lastProgress?.totalRows ?? null, + status: "Error", + error: exportError.value, + }; + updateDatabaseExportTask(exportId.value, fallbackProgress); isExporting.value = false; } } @@ -489,6 +506,9 @@ watch(