From b6e519dfaa5e4ab39830454d5ea4ee160be33035 Mon Sep 17 00:00:00 2001 From: t8y2 <1156263951@qq.com> Date: Tue, 19 May 2026 16:39:19 +0800 Subject: [PATCH] feat(grid): use temporal inputs for date cells --- apps/desktop/src/components/grid/DataGrid.vue | 48 ++++++++++++++- .../desktop/src/lib/dataGridTemporalEditor.ts | 60 +++++++++++++++++++ .../app-tests/dataGridTemporalEditor.test.ts | 33 ++++++++++ 3 files changed, 140 insertions(+), 1 deletion(-) create mode 100644 apps/desktop/src/lib/dataGridTemporalEditor.ts create mode 100644 packages/app-tests/dataGridTemporalEditor.test.ts diff --git a/apps/desktop/src/components/grid/DataGrid.vue b/apps/desktop/src/components/grid/DataGrid.vue index 33b7ba0618..b134b6240e 100644 --- a/apps/desktop/src/components/grid/DataGrid.vue +++ b/apps/desktop/src/components/grid/DataGrid.vue @@ -104,6 +104,12 @@ import { type ColumnFormatterConfig, type DateTimeFormatterUnit, } from "@/lib/columnFormatter"; +import { + formatTemporalInputValue, + parseTemporalInputValue, + temporalCellEditorKind, + type TemporalCellEditorKind, +} from "@/lib/dataGridTemporalEditor"; import { isCancelSearchShortcut, isFocusSearchShortcut } from "@/lib/keyboardShortcuts"; import { dataGridHeaderContentWidth, scrollbarGutterWidth } from "@/lib/dataGridScrollGutter"; import { dataGridSaveActionMode, dataGridSaveToolbarState } from "@/lib/dataGridSaveUi"; @@ -1386,6 +1392,43 @@ function canEditCellItem(item: RowItem | undefined, columnIndex: number): boolea return true; } +function tableColumnForGridColumn(columnIndex: number): ColumnInfo | undefined { + const columnName = props.sourceColumns?.[columnIndex] ?? props.result.columns[columnIndex]; + if (!columnName) return undefined; + return props.tableMeta?.columns.find((column) => column.name.toLowerCase() === columnName.toLowerCase()); +} + +function temporalEditorKindForColumn(columnIndex: number): TemporalCellEditorKind | undefined { + return temporalCellEditorKind(tableColumnForGridColumn(columnIndex)?.data_type, props.databaseType); +} + +function cellEditInputType(columnIndex: number): string { + const kind = temporalEditorKindForColumn(columnIndex); + if (kind === "date") return "date"; + if (kind === "time") return "time"; + if (kind === "datetime") return "datetime-local"; + return "text"; +} + +function cellEditInputStep(columnIndex: number): string | undefined { + return temporalEditorKindForColumn(columnIndex) ? "1" : undefined; +} + +function cellEditInputValue(columnIndex: number): string { + const kind = temporalEditorKindForColumn(columnIndex); + return kind ? formatTemporalInputValue(editValue.value, kind) : editValue.value; +} + +function onCellEditInput(columnIndex: number, event: Event) { + const target = event.target as HTMLInputElement; + const kind = temporalEditorKindForColumn(columnIndex); + if (!kind) { + editValue.value = target.value; + return; + } + editValue.value = parseTemporalInputValue(target.value, kind) ?? "NULL"; +} + function canDeleteRowItem(item: RowItem | undefined): boolean { return !!props.editable && !!item && !item.isDeleted && (item.isNew || canEditExistingRows.value); } @@ -3500,11 +3543,14 @@ defineExpose({ >