From c2bae3b9579bfc542caaab5618d01ededb2e70f5 Mon Sep 17 00:00:00 2001 From: t8y2 <1156263951@qq.com> Date: Wed, 1 Jul 2026 02:10:21 +0800 Subject: [PATCH] fix(grid): refresh copied insert after row edits --- .../src/composables/useDataGridExport.ts | 9 ++- packages/app-tests/useDataGridExport.test.ts | 56 +++++++++++++++++++ 2 files changed, 63 insertions(+), 2 deletions(-) diff --git a/apps/desktop/src/composables/useDataGridExport.ts b/apps/desktop/src/composables/useDataGridExport.ts index 4d3ec84f7..662284f55 100644 --- a/apps/desktop/src/composables/useDataGridExport.ts +++ b/apps/desktop/src/composables/useDataGridExport.ts @@ -178,7 +178,7 @@ export function useDataGridExport(options: UseDataGridExportOptions) { } function updateCopyKey(): string { - const rows = updateEligibleRows().map((item) => item.id); + const rows = copyStatementRowsKey(updateEligibleRows()); return JSON.stringify({ databaseType: databaseType.value ?? null, schema: tableMeta.value?.schema ?? null, @@ -191,7 +191,7 @@ export function useDataGridExport(options: UseDataGridExportOptions) { } function insertCopyKey(excludePrimaryKeys: boolean): string { - const rows = insertEligibleRows().map((item) => item.id); + const rows = copyStatementRowsKey(insertEligibleRows()); return JSON.stringify({ databaseType: databaseType.value ?? null, schema: tableMeta.value?.schema ?? null, @@ -204,6 +204,11 @@ export function useDataGridExport(options: UseDataGridExportOptions) { }); } + function copyStatementRowsKey(rows: RowItem[]): Array<{ id: number; data: CellValue[] }> { + // Prepared copy SQL depends on current cell values; edited rows keep the same id while their data changes. + return rows.map((item) => ({ id: item.id, data: item.data })); + } + function insertCopyCache(excludePrimaryKeys: boolean): CopyStatementCache { return excludePrimaryKeys ? copyRowInsertWithoutPrimaryKeysCache.value : copyRowInsertCache.value; } diff --git a/packages/app-tests/useDataGridExport.test.ts b/packages/app-tests/useDataGridExport.test.ts index a42edd319..ecc531fd2 100644 --- a/packages/app-tests/useDataGridExport.test.ts +++ b/packages/app-tests/useDataGridExport.test.ts @@ -379,6 +379,62 @@ test("copy MongoDB rows as INSERT excludes _id for insert without primary keys", assert.equal(clipboardMock.copyToClipboard.mock.calls[0][0], 'db.getCollection("accounting_reconciliations").insertMany([{"status":"done"},{"status":"draft"}]);'); }); +test("copy row as INSERT refreshes prepared SQL after row data changes", async () => { + const contextCell = ref({ rowId: 1, rowIndex: 0, col: 0 }); + const row = { + id: 1, + data: [1, "before"], + isNew: false, + isDeleted: false, + isDirtyCol: [false, false], + status: "", + }; + apiMock.buildDataGridCopyInsertStatement + .mockResolvedValueOnce("INSERT INTO users (id, name) VALUES (1, 'before');") + .mockResolvedValueOnce("INSERT INTO users (id, name) VALUES (1, 'after');"); + const composable = useDataGridExport({ + columns: computed(() => ["id", "name"]), + displayItems: computed(() => [row]), + sql: computed(() => undefined), + tableMeta: computed(() => ({ + tableName: "users", + primaryKeys: ["id"], + })), + databaseType: computed(() => "mysql"), + connectionId: computed(() => "conn-1"), + database: computed(() => "db"), + context: computed(() => "table-data"), + sourceColumns: computed(() => undefined), + columnTypes: computed(() => undefined), + whereInput: computed(() => undefined), + orderBy: computed(() => undefined), + exportBatchSize: computed(() => 1000), + hasCellSelection: computed(() => false), + selectedCells: computed(() => ({ columns: [], rows: [] })), + selectedRange: computed(() => null), + contextCell, + getRowItem: () => row, + selectedRowIds: ref(new Set()), + hasRowSelection: computed(() => false), + }); + + await composable.prefetchRowAsInsertStatement(false); + await composable.copyRowAsInsert(); + row.data = [1, "after"]; + await composable.prefetchRowAsInsertStatement(false); + await composable.copyRowAsInsert(); + + assert.equal(apiMock.buildDataGridCopyInsertStatement.mock.calls.length, 2); + assert.deepEqual(apiMock.buildDataGridCopyInsertStatement.mock.calls.map((call) => call[0].rows), [ + [[1, "before"]], + [[1, "after"]], + ]); + assert.deepEqual(clipboardMock.copyToClipboard.mock.calls.map((call) => call[0]), [ + "INSERT INTO users (id, name) VALUES (1, 'before');", + "INSERT INTO users (id, name) VALUES (1, 'after');", + ]); +}); + test("default data grid export file names use sanitized base names and compact local timestamps", () => { vi.useFakeTimers(); try {