feat(grid): preserve selection highlight after data refresh
This commit is contained in:
3 files changed
+639
No files matched your search
@@ -172,6 +172,7 @@ import { buildDataGridColumnLookupItems, dataGridColumnCommentFor, filterDataGri
|
||||
import { uniqueDataGridColumnOrderKeys } from "@/lib/dataGrid/dataGridColumnOrder";
|
||||
import { dataGridColumnLayoutScopeKey, TABLE_DATA_GRID_COLUMN_ORDER_CHANGED_EVENT, tableDataGridColumnOrderScopeKey } from "@/lib/dataGrid/dataGridColumnLayoutStorage";
|
||||
import { summarizeSelection } from "@/lib/dataGrid/gridSelection";
|
||||
import { captureDataGridSelection, reactivatesCellSelectionAfterRestore, restoreDataGridSelection, type PersistedDataGridSelection } from "@/lib/dataGrid/dataGridSelectionPersistence";
|
||||
import { dataGridFrameCoversRow, dataGridSelectionEdgeMask, dataGridSelectionFrameKindAtCell, dataGridSelectionUsesOuterFrame, resolveDataGridSelectionFrames } from "@/lib/dataGrid/dataGridSelectionFrames";
|
||||
import {
|
||||
createDataGridCellContextMenuItems,
|
||||
@@ -414,6 +415,7 @@ if (isDebugLoggingEnabled()) {
|
||||
const transposeRowIndex = ref<number | null>(null);
|
||||
const showTranspose = ref(false);
|
||||
const preserveTransposeOnNextResult = ref(false);
|
||||
let preservedSelectionOnNextResult: { selection: PersistedDataGridSelection; sourceResult: QueryResult } | null = null;
|
||||
|
||||
watch(
|
||||
() => props.result,
|
||||
@@ -2646,6 +2648,7 @@ watch(
|
||||
// and the completion was triggered by a refresh/rollback.
|
||||
if (!loading && prevLoading && isRefreshingData.value) {
|
||||
isRefreshingData.value = false;
|
||||
if (preservedSelectionOnNextResult?.sourceResult === props.result) preservedSelectionOnNextResult = null;
|
||||
const total = paginationTotalRowCount.value;
|
||||
if (!total || total <= 0) return;
|
||||
const lastPageNum = Math.max(1, Math.ceil(total / pageSize.value));
|
||||
@@ -3386,6 +3389,8 @@ async function onToolbarRefresh() {
|
||||
if (infiniteScrollEnabled.value) {
|
||||
resetInfiniteScrollState();
|
||||
}
|
||||
const selection = captureCurrentSelectionForRefresh();
|
||||
preservedSelectionOnNextResult = selection ? { selection, sourceResult: props.result } : null;
|
||||
preserveTransposeOnNextResult.value = showTranspose.value;
|
||||
isRefreshingData.value = true;
|
||||
beginDataGridNativeSelectionBlock(dataGridNativeSelectionBlockOwner);
|
||||
@@ -3848,6 +3853,7 @@ const {
|
||||
isSelectingAll,
|
||||
isSelectingCells,
|
||||
selectedRange,
|
||||
selectionAnchor,
|
||||
selectedCells,
|
||||
selectedCellKeys,
|
||||
selectedCellMatrix,
|
||||
@@ -3877,6 +3883,64 @@ const {
|
||||
isRowSelected,
|
||||
} = selection;
|
||||
|
||||
function captureCurrentSelectionForRefresh(): PersistedDataGridSelection | null {
|
||||
return captureDataGridSelection({
|
||||
columns: props.result.columns,
|
||||
sourceColumns: props.sourceColumns,
|
||||
rows: props.result.rows,
|
||||
primaryKeys: props.tableMeta?.primaryKeys ?? [],
|
||||
visibleColumnIndexes: visibleColumnIndexes.value,
|
||||
displayItems: displayItems.value,
|
||||
selectedRowIds: selectedRowIds.value,
|
||||
selectedColumnIndexes: selectedColumnIndexes.value,
|
||||
selectedCellKeys: selectedCellKeys.value,
|
||||
selectionAnchor: selectionAnchor.value,
|
||||
selectionFocus: selectionFocus.value,
|
||||
selectingAll: isSelectingAll.value,
|
||||
lastClickedRowIndex: selection.lastClickedRowIndex.value,
|
||||
});
|
||||
}
|
||||
|
||||
function restoreSelectionAfterRefresh(snapshot: PersistedDataGridSelection) {
|
||||
const restored = restoreDataGridSelection({
|
||||
snapshot,
|
||||
columns: props.result.columns,
|
||||
sourceColumns: props.sourceColumns,
|
||||
rows: props.result.rows,
|
||||
visibleColumnIndexes: visibleColumnIndexes.value,
|
||||
displayItems: displayItems.value,
|
||||
});
|
||||
if (!restored) return;
|
||||
|
||||
if (restored.kind === "rows") {
|
||||
selectedRowIds.value = new Set(restored.rowIds);
|
||||
selection.lastClickedRowIndex.value = restored.anchorRowIndex;
|
||||
} else if (restored.kind === "columns") {
|
||||
selectedColumnIndexes.value = new Set(restored.columnIndexes);
|
||||
} else if (restored.kind === "range") {
|
||||
selectionAnchor.value = restored.anchor;
|
||||
selectionFocus.value = restored.focus;
|
||||
isSelectingAll.value = restored.selectingAll;
|
||||
} else {
|
||||
selectedCellKeys.value = restored.cellKeys;
|
||||
}
|
||||
|
||||
// 恢复 range/离散单元格选区后重新激活 cell-selection 拖拽状态机:refresh watcher
|
||||
// 在 restore 前调的 clearCellSelection 已把 isSelectingCells 置 false,而它仅在
|
||||
// beginCellSelection(鼠标按下)时才重新置 true。不在此补偿,则恢复的高亮虽能显示,
|
||||
// 但 extendCellSelection/handleSelectionPointerMove 的 isSelectingCells 守卫会挡住
|
||||
// 拖拽扩展,用户必须重新点一次单元格。行选/列选是独立状态机,不应激活。
|
||||
if (reactivatesCellSelectionAfterRestore(restored)) {
|
||||
isSelectingCells.value = true;
|
||||
}
|
||||
|
||||
if (restored.kind === "columns") return;
|
||||
nextTick(() => {
|
||||
if (restored.kind === "range") scrollCellIntoView(restored.scrollRowIndex, restored.focus.colIndex);
|
||||
else scrollGridRowIntoView(restored.scrollRowIndex);
|
||||
});
|
||||
}
|
||||
|
||||
const multiRowCount = computed(() => {
|
||||
if (hasRowSelection.value) return selectedRowCount.value;
|
||||
const range = selectedRange.value;
|
||||
@@ -7494,6 +7558,8 @@ watch(isTransposeMode, (active) => {
|
||||
watch(
|
||||
() => props.result,
|
||||
(result, previousResult) => {
|
||||
const selectionSnapshot = preservedSelectionOnNextResult?.selection;
|
||||
preservedSelectionOnNextResult = null;
|
||||
const shouldPreserveTranspose = preserveTransposeOnNextResult.value;
|
||||
preserveTransposeOnNextResult.value = false;
|
||||
if (isDataGridPrefixAppend(previousResult, result)) return;
|
||||
@@ -7512,6 +7578,7 @@ watch(
|
||||
closeTranspose(false);
|
||||
}
|
||||
exitTransaction();
|
||||
if (selectionSnapshot) restoreSelectionAfterRefresh(selectionSnapshot);
|
||||
},
|
||||
);
|
||||
|
||||
|
||||
Reference in new issue
Block a user