fix: optimize query cell detail panel layout

* fix: improve cell detail editor layout

* test: update cell detail drawer default

---------

Co-authored-by: staff <staff@qimaos-MacBook-Pro.local>
This commit is contained in:
zipgandstaff authored and GitHub committed 2026-06-24 19:15:51 +08:00
1 parent 902419a3b9
commit 96aada2631
4 files changed
+34 -28

No files matched your search

+25 -21
View File
@@ -7817,7 +7817,7 @@ const gridContextMenuItems = computed<ContextMenuItem[]>(() => {
</div>
<TabsContent value="details" class="m-0 min-h-0 flex-1 flex flex-col">
<div data-native-clipboard class="flex-1 min-h-0 overflow-auto p-3 text-xs space-y-3">
<div data-native-clipboard class="flex-1 min-h-0 overflow-auto p-3 text-xs" :class="isEditingDetail ? 'flex flex-col gap-3' : 'space-y-3'">
<div v-if="cellDetailPanelIsBottom" class="grid grid-cols-[minmax(180px,1.6fr)_repeat(4,minmax(74px,0.55fr))_minmax(160px,1fr)] gap-3 rounded border bg-muted/20 p-2">
<div class="min-w-0 space-y-1">
<div class="text-muted-foreground">{{ t("grid.columnName") }}</div>
@@ -7882,23 +7882,23 @@ const gridContextMenuItems = computed<ContextMenuItem[]>(() => {
</div>
</div>
</template>
<div class="space-y-1" :class="cellDetailPanelIsBottom ? 'min-h-0' : ''">
<div class="flex items-center justify-between gap-2">
<div class="space-y-1" :class="[{ 'min-h-0 flex flex-col': cellDetailPanelIsBottom || isEditingDetail }, isEditingDetail ? 'flex-1' : '']">
<div class="flex min-h-5 items-center justify-between gap-2">
<div class="text-muted-foreground">{{ t("grid.cellValue") }}</div>
<div v-if="!isEditingDetail" class="flex items-center gap-1">
<Button v-if="activeCellDetail.formattedJson" :variant="sideDetailJsonView ? 'secondary' : 'ghost'" size="sm" class="h-6 gap-1 px-2 text-xs" :title="t('grid.formattedJson')" @click="sideDetailJsonView = !sideDetailJsonView">
<Button v-if="activeCellDetail.formattedJson" :variant="sideDetailJsonView ? 'secondary' : 'ghost'" size="sm" class="h-5 gap-1 px-1.5 text-xs" :title="t('grid.formattedJson')" @click="sideDetailJsonView = !sideDetailJsonView">
<Code2 class="h-3 w-3" />
{{ t("grid.formattedJson") }}
</Button>
<Button v-if="activeCellDetail.isEditable" variant="ghost" size="icon" class="h-6 w-6" :title="t('grid.editValue')" @click="startDetailEdit">
<Button v-if="activeCellDetail.isEditable" variant="ghost" size="icon" class="h-5 w-5" :title="t('grid.editValue')" @click="startDetailEdit">
<Pencil class="h-3 w-3" />
</Button>
<Button variant="ghost" size="icon" class="h-6 w-6" :title="t('grid.copyValue')" @click="copyDetailCurrentValue">
<Button variant="ghost" size="icon" class="h-5 w-5" :title="t('grid.copyValue')" @click="copyDetailCurrentValue">
<Copy class="h-3 w-3" />
</Button>
<DropdownMenu v-if="canDownloadDetailBinaryValue(activeCellDetail)">
<DropdownMenuTrigger as-child>
<Button variant="ghost" size="icon" class="h-6 w-6" :title="t('grid.downloadBinaryValue')">
<Button variant="ghost" size="icon" class="h-5 w-5" :title="t('grid.downloadBinaryValue')">
<Download class="h-3 w-3" />
</Button>
</DropdownMenuTrigger>
@@ -7911,7 +7911,7 @@ const gridContextMenuItems = computed<ContextMenuItem[]>(() => {
<!-- Skip hex fallback from backend (unsupported geometry types like TIN/Triangle) -->
<Popover v-if="isGeometryColumnType(activeCellDetail.type) && activeCellDetail.value !== null && !isEditingDetail && !isHexGeometry(activeCellDetail.value as string)" v-model:open="sideGeometryPreviewOpen">
<PopoverTrigger as-child>
<Button variant="ghost" size="icon" class="h-6 w-6" :title="t('grid.geometryPreview')">
<Button variant="ghost" size="icon" class="h-5 w-5" :title="t('grid.geometryPreview')">
<Eye class="h-3 w-3" />
</Button>
</PopoverTrigger>
@@ -7928,15 +7928,9 @@ const gridContextMenuItems = computed<ContextMenuItem[]>(() => {
</a>
</div>
<template v-if="isEditingDetail">
<TemporalCellEditor v-if="detailTemporalEditorKind" v-model="detailEditValue" :kind="detailTemporalEditorKind" variant="inline" :commit-on-close="false" @cancel="cancelDetailEdit" @commit="commitDetailEdit" />
<div v-else ref="detailsEditorContainer" data-cell-detail-editor-root class="w-full rounded border overflow-hidden" :class="cellDetailPanelIsBottom ? 'h-28' : 'h-40'" />
<div class="flex gap-1 mt-1">
<Button size="sm" class="h-6 text-xs" @click="commitDetailEdit">
{{ t("dangerDialog.confirm") }}
</Button>
<Button variant="outline" size="sm" class="h-6 text-xs" @click="cancelDetailEdit">
{{ t("dangerDialog.cancel") }}
</Button>
<div class="min-h-0 flex-1">
<TemporalCellEditor v-if="detailTemporalEditorKind" v-model="detailEditValue" :kind="detailTemporalEditorKind" variant="inline" :commit-on-close="false" @cancel="cancelDetailEdit" @commit="commitDetailEdit" />
<div v-else ref="detailsEditorContainer" data-cell-detail-editor-root class="min-h-0 h-full w-full rounded border overflow-hidden" />
</div>
</template>
<pre v-else class="overflow-auto rounded border bg-muted/20 p-2 font-mono text-xs whitespace-pre-wrap break-words cursor-pointer hover:border-primary/50" :class="{ 'cursor-text': activeCellDetail.isEditable }" @dblclick="startDetailEdit">{{
@@ -7952,10 +7946,20 @@ const gridContextMenuItems = computed<ContextMenuItem[]>(() => {
</div>
</div>
<div class="border-t p-2 grid gap-1" :class="cellDetailPanelIsBottom ? 'grid-cols-[repeat(3,max-content)] justify-end' : 'grid-cols-1'">
<Button v-if="activeCellDetail.isEditable && activeCellDetail.value !== null" variant="ghost" size="sm" class="h-7 justify-start text-xs" @click="setDetailNull"> <X class="w-3 h-3 mr-2" /> {{ t("grid.setNull") }} </Button>
<Button variant="ghost" size="sm" class="h-7 justify-start text-xs" @click="copyDetailColumnName"> <Copy class="w-3 h-3 mr-2" /> {{ t("grid.copyColumnName") }} </Button>
<Button variant="ghost" size="sm" class="h-7 justify-start text-xs" :disabled="!canCopyPreparedDetailSqlCondition()" @click="copyDetailSqlCondition"> <Code2 class="w-3 h-3 mr-2" /> {{ t("grid.copySqlCondition") }} </Button>
<div class="border-t p-1.5 flex gap-1" :class="cellDetailPanelIsBottom ? 'items-center' : 'flex-col'">
<div v-if="isEditingDetail" class="flex shrink-0 gap-1" :class="cellDetailPanelIsBottom ? 'mr-auto' : ''">
<Button size="sm" class="h-6 text-xs" @click="commitDetailEdit">
{{ t("dangerDialog.confirm") }}
</Button>
<Button variant="outline" size="sm" class="h-6 text-xs" @click="cancelDetailEdit">
{{ t("dangerDialog.cancel") }}
</Button>
</div>
<div class="flex gap-1" :class="cellDetailPanelIsBottom ? 'ml-auto shrink-0 justify-end' : 'flex-col'">
<Button v-if="activeCellDetail.isEditable && activeCellDetail.value !== null" variant="ghost" size="sm" class="h-6 justify-start text-xs" @click="setDetailNull"> <X class="w-3 h-3 mr-2" /> {{ t("grid.setNull") }} </Button>
<Button variant="ghost" size="sm" class="h-6 justify-start text-xs" @click="copyDetailColumnName"> <Copy class="w-3 h-3 mr-2" /> {{ t("grid.copyColumnName") }} </Button>
<Button variant="ghost" size="sm" class="h-6 justify-start text-xs" :disabled="!canCopyPreparedDetailSqlCondition()" @click="copyDetailSqlCondition"> <Code2 class="w-3 h-3 mr-2" /> {{ t("grid.copySqlCondition") }} </Button>
</div>
</div>
</TabsContent>
@@ -135,6 +135,8 @@ const { t } = useI18n();
const queryStore = useQueryStore();
const connectionStore = useConnectionStore();
const { toast } = useToast();
const DEFAULT_QUERY_RESULTS_PANE_SIZE = 68;
const DEFAULT_QUERY_EDITOR_PANE_SIZE = 100 - DEFAULT_QUERY_RESULTS_PANE_SIZE;
onMounted(() => {
const preload = () => preloadDataGridComponent();
@@ -537,7 +539,7 @@ defineExpose({ focusSearch, refreshData, handleModRTarget, requestQueryEditorExe
<!-- Query mode: editor + results -->
<template v-if="activeTab.mode === 'query'">
<Splitpanes horizontal class="query-output-splitpanes flex-1 min-h-0 overflow-hidden">
<Pane class="min-h-0" :size="resultsPaneOpen ? 40 : 100" :min-size="resultsPaneOpen ? 15 : 100">
<Pane class="min-h-0" :size="resultsPaneOpen ? DEFAULT_QUERY_EDITOR_PANE_SIZE : 100" :min-size="resultsPaneOpen ? 15 : 100">
<div class="h-full flex flex-col relative">
<QueryEditor
ref="queryEditorRef"
@@ -574,7 +576,7 @@ defineExpose({ focusSearch, refreshData, handleModRTarget, requestQueryEditorExe
</Button>
</div>
</Pane>
<Pane v-if="resultsPaneOpen" class="min-h-0" :size="60" :min-size="20">
<Pane v-if="resultsPaneOpen" class="min-h-0" :size="DEFAULT_QUERY_RESULTS_PANE_SIZE" :min-size="20">
<div class="h-full flex flex-col">
<div v-if="hasQueryOutput" class="flex h-10 shrink-0 items-center gap-1 border-b bg-muted/20 px-2">
<div class="flex shrink-0 items-center gap-1">