From a159dcfc83a2d34be09f1a9daa54e20ad918a123 Mon Sep 17 00:00:00 2001 From: t8y2 <1156263951@qq.com> Date: Thu, 21 May 2026 23:15:44 +0800 Subject: [PATCH] feat(grid): optimize transpose view toggle --- .../editor/EditorSettingsDialog.vue | 4 +- apps/desktop/src/components/grid/DataGrid.vue | 70 +++++++++++---- apps/desktop/src/i18n/locales/en.ts | 2 + apps/desktop/src/i18n/locales/es.ts | 2 + apps/desktop/src/i18n/locales/zh-CN.ts | 2 + apps/desktop/src/lib/dataGridTranspose.ts | 52 +++++++++++ apps/desktop/src/lib/keyboardShortcuts.ts | 4 + apps/desktop/src/lib/shortcutRegistry.ts | 9 +- packages/app-tests/dataGridTranspose.test.ts | 90 +++++++++++++++++++ .../app-tests/dataGridTransposeSource.test.ts | 12 +++ packages/app-tests/keyboardShortcuts.test.ts | 7 ++ .../app-tests/settingsDialogLayout.test.ts | 3 + packages/app-tests/settingsStore.test.ts | 1 + 13 files changed, 237 insertions(+), 21 deletions(-) create mode 100644 packages/app-tests/dataGridTransposeSource.test.ts diff --git a/apps/desktop/src/components/editor/EditorSettingsDialog.vue b/apps/desktop/src/components/editor/EditorSettingsDialog.vue index 8237c7378a..20ef3d188f 100644 --- a/apps/desktop/src/components/editor/EditorSettingsDialog.vue +++ b/apps/desktop/src/components/editor/EditorSettingsDialog.vue @@ -647,7 +647,7 @@ watch(
diff --git a/apps/desktop/src/components/grid/DataGrid.vue b/apps/desktop/src/components/grid/DataGrid.vue index 9d3e6f7369..3002a79bb5 100644 --- a/apps/desktop/src/components/grid/DataGrid.vue +++ b/apps/desktop/src/components/grid/DataGrid.vue @@ -90,8 +90,9 @@ import { } from "@/lib/tableEditing"; import { formatGridSqlLiteral } from "@/lib/dataGridSql"; import { - buildTransposeRows, + buildVisibleTransposeRows, nextContextTransposeState, + nextKeyboardTransposeState, nextTransposeState, transposeFieldWidth, transposeScrollLeftForRecord, @@ -118,7 +119,7 @@ import { type DateTimeFormatterUnit, } from "@/lib/columnFormatter"; import { temporalCellEditorKind, type TemporalCellEditorKind } from "@/lib/dataGridTemporalEditor"; -import { isCancelSearchShortcut, isFocusSearchShortcut } from "@/lib/keyboardShortcuts"; +import { isCancelSearchShortcut, isFocusSearchShortcut, isToggleTransposeShortcut } from "@/lib/keyboardShortcuts"; import { dataGridHeaderContentWidth, scrollbarGutterWidth } from "@/lib/dataGridScrollGutter"; import { dataGridSaveActionMode, dataGridSaveToolbarState } from "@/lib/dataGridSaveUi"; import { appendColumnValueFilterCondition, buildColumnValueFilterCondition } from "@/lib/dataGridColumnFilter"; @@ -2258,6 +2259,33 @@ function scrollCellIntoView(rowIndex: number, colIndex: number) { }); } +function currentTransposeRequestedRowIndex(): number { + const position = currentSelectedCellPosition(); + if (position) return position.rowIndex; + if (transposeRowIndex.value !== null) return transposeRowIndex.value; + return 0; +} + +function toggleKeyboardTranspose(): boolean { + if (displayItems.value.length === 0) return false; + const next = nextKeyboardTransposeState({ + showTranspose: showTranspose.value, + transposeRowIndex: transposeRowIndex.value, + requestedRowIndex: currentTransposeRequestedRowIndex(), + rowIds: displayItems.value.map((item) => item.id), + selectedRowIds: selectedRowIds.value, + selectedRange: selectedRange.value, + }); + showTranspose.value = next.showTranspose; + transposeRowIndex.value = next.transposeRowIndex; + if (next.showTranspose) { + closeCellDetails(); + nextTick(updateTransposeViewport); + if (next.transposeRowIndex !== null) scrollTransposeRecordIntoView(next.transposeRowIndex); + } + return true; +} + function moveSelectedCell(rowDelta: number, colDelta: number): boolean { const position = currentSelectedCellPosition(); if (!position || editingCell.value || displayItems.value.length === 0 || visibleColumnIndexes.value.length === 0) @@ -2293,6 +2321,10 @@ async function onGridKeydown(event: KeyboardEvent) { return; } if (eventTargetAllowsNativeClipboard(event)) return; + if (isToggleTransposeShortcut(event, settingsStore.editorSettings.shortcuts) && toggleKeyboardTranspose()) { + event.preventDefault(); + return; + } if (event.key === "ArrowLeft" && moveTransposeRecordSelection(-1)) { event.preventDefault(); return; @@ -2375,15 +2407,6 @@ const transposePinnedWidth = computed( () => transposePinnedWidthOverride.value ?? transposeFieldWidth(visibleColumns.value), ); -const transposeRows = computed(() => { - return buildTransposeRows({ - columns: visibleColumns.value, - records: displayItems.value.map((item) => visibleColumnIndexes.value.map((columnIndex) => item.data[columnIndex])), - typeByColumn: columnTypeMap.value, - displayValue: (value, _column, index) => formatCell(value, visibleColumnIndexes.value[index]), - }); -}); -const isTransposeMode = computed(() => showTranspose.value && transposeRows.value.length > 0); const transposeRecordWindow = computed(() => visibleTransposeRecordWindow({ totalRecords: displayItems.value.length, @@ -2398,6 +2421,17 @@ const visibleTransposeRecordIndexes = computed(() => { const window = transposeRecordWindow.value; return Array.from({ length: window.end - window.start }, (_, offset) => window.start + offset); }); +const transposeRows = computed(() => { + return buildVisibleTransposeRows({ + columns: visibleColumns.value, + records: displayItems.value.map((item) => item.data), + recordIndexes: visibleTransposeRecordIndexes.value, + valueIndexes: visibleColumnIndexes.value, + typeByColumn: columnTypeMap.value, + displayValue: (value, _column, index) => formatCell(value, visibleColumnIndexes.value[index]), + }); +}); +const isTransposeMode = computed(() => showTranspose.value && transposeRows.value.length > 0); const transposeTotalWidth = computed( () => transposePinnedWidth.value + displayItems.value.length * transposeRecordWidth.value, ); @@ -3344,18 +3378,18 @@ defineExpose({