From 8d5c0968950ab46221fc2a253bc56da9bc224b4c Mon Sep 17 00:00:00 2001 From: t8y2 <1156263951@qq.com> Date: Wed, 13 May 2026 22:02:14 +0800 Subject: [PATCH] fix(grid): keep row position after commit and preserve dirty cell color - Don't reload data after committing edits, merge dirty data in place - Preserve dirty cell yellow highlight when row/cell is selected - Use original row data for search filtering to prevent row shifting --- src/components/grid/DataGrid.vue | 15 ++++++++----- src/composables/useDataGridEditor.ts | 33 +++++++--------------------- 2 files changed, 18 insertions(+), 30 deletions(-) diff --git a/src/components/grid/DataGrid.vue b/src/components/grid/DataGrid.vue index 3de0e085a..0f93d8181 100644 --- a/src/components/grid/DataGrid.vue +++ b/src/components/grid/DataGrid.vue @@ -1050,7 +1050,7 @@ const sortedRows = computed(() => { if (q) { const rows = props.result.rows; indices = indices.filter((sourceIndex) => { - const data = rowDataWithChanges(rows[sourceIndex], sourceIndex); + const data = rows[sourceIndex]; return data.some((cell) => cell !== null && String(cell).toLowerCase().includes(q)); }); } @@ -1180,7 +1180,6 @@ const hasVisibleRows = computed(() => displayItems.value.length > 0); const hasActiveFilter = computed( () => !!deferredClientSearchText.value || rowStatusFilter.value !== "all" || hasLocalColumnFilters.value, ); -const totalFilterableRowCount = computed(() => props.result.rows.length + newRows.value.length); const emptyTitle = computed(() => (hasActiveFilter.value ? t("grid.noFilteredRows") : t("grid.noRows"))); const emptyDescription = computed(() => hasActiveFilter.value ? t("grid.noFilteredRowsDescription") : t("grid.noRowsDescription"), @@ -2475,8 +2474,9 @@ defineExpose({ :style="{ width: `var(--col-w-${visibleColIdx})` }" :class="{ 'text-muted-foreground italic': isNull(item.data[actualColIdx]), - 'bg-yellow-500/10': item.isDirtyCol[actualColIdx], - 'cell-selected': cellIsSelected(index, visibleColIdx), + 'bg-yellow-500/10 cell-dirty': item.isDirtyCol[actualColIdx], + 'cell-selected': cellIsSelected(index, visibleColIdx) && !item.isDirtyCol[actualColIdx], + 'cell-selected-dirty': cellIsSelected(index, visibleColIdx) && item.isDirtyCol[actualColIdx], 'bg-yellow-200/60 dark:bg-yellow-500/20': cellIsSearchMatch(index, actualColIdx), 'ring-2 ring-inset ring-yellow-500 bg-yellow-300/60 dark:bg-yellow-500/40': cellIsCurrentMatch( index, @@ -2990,7 +2990,12 @@ defineExpose({ box-shadow: inset 0 0 0 1px color-mix(in oklab, var(--primary) 55%, transparent); } -.active-row > div { +.cell-selected-dirty { + background-color: color-mix(in oklab, oklch(0.8 0.15 85) 30%, color-mix(in oklab, var(--primary) 12%, transparent)); + box-shadow: inset 0 0 0 1px color-mix(in oklab, var(--primary) 55%, transparent); +} + +.active-row > div:not(.cell-dirty) { background-color: color-mix(in oklab, var(--primary) 10%, transparent); } diff --git a/src/composables/useDataGridEditor.ts b/src/composables/useDataGridEditor.ts index 6ef2c81ed..caf6a8438 100644 --- a/src/composables/useDataGridEditor.ts +++ b/src/composables/useDataGridEditor.ts @@ -98,16 +98,9 @@ export function useDataGridEditor(options: UseDataGridEditorOptions) { canEditExistingRows = computed(() => true), onExecuteSql, customSave, - sql, - searchText, - whereFilterInput, - orderByInput, rowStatusFilter, initialEditColumn, getRowItem, - pageSize, - currentPage, - emit, } = options; const editingCell = ref<{ rowId: number; col: number } | null>(null); @@ -559,15 +552,6 @@ export function useDataGridEditor(options: UseDataGridEditorOptions) { deletedRows.value.clear(); exitTransaction(); isSaving.value = false; - emit( - "reload", - sql.value, - searchText.value, - whereFilterInput.value.trim() || undefined, - orderByInput.value.trim() || undefined, - pageSize.value, - (currentPage.value - 1) * pageSize.value, - ); return; } @@ -641,20 +625,19 @@ export function useDataGridEditor(options: UseDataGridEditorOptions) { } catch (e) { console.warn("[DBX] failed to record data grid history", e); } + for (const [sourceIndex, changes] of dirtyRows.value) { + const row = result.value.rows[sourceIndex]; + if (row) { + for (const [colIdx, value] of changes) { + row[colIdx] = value; + } + } + } dirtyRows.value.clear(); newRows.value = []; deletedRows.value.clear(); exitTransaction(); isSaving.value = false; - emit( - "reload", - sql.value, - searchText.value, - whereFilterInput.value.trim() || undefined, - orderByInput.value.trim() || undefined, - pageSize.value, - (currentPage.value - 1) * pageSize.value, - ); } function discardChanges() {