修复驱动管理与侧边栏展开的前台显示问题

* 修复标签页切换和侧边栏展开滚动

* chore: rerun ci

---------

Co-authored-by: staff <staff@qimaos-MacBook-Pro.local>
This commit is contained in:
zipg
2026-06-24 14:08:58 +08:00
committed by GitHub
co-authored by staff
parent 886c11f8e6
commit 1cd3406e94
4 changed files with 4 additions and 89 deletions
+1
View File
@@ -339,6 +339,7 @@ watch(
);
}
if (id) newQueryContextSource.value = "tab";
if (id && showDriverStore.value) showDriverStore.value = false;
selectedSql.value = "";
activeOutputView.value = "result";
if (id) queryStore.reloadEvictedTab(id);
@@ -13,7 +13,7 @@ import { usesTreeSchemaMode } from "@/lib/databaseFeatureSupport";
import { connectionUsesDatabaseObjectTreeMode, effectiveDatabaseTypeForConnection } from "@/lib/jdbcDialect";
import { activeTabSidebarTarget, findSidebarNodeForActiveTab, findSidebarNodeForTarget, findNodePathForTarget, scrollTopForSidebarNode, shouldScrollActiveSidebarSelection, type ActiveTabSidebarTarget } from "@/lib/sidebarActiveTabTarget";
import { findLoadedTableTargetForCandidate, queryContextTargetFromCandidate, queryCursorTableCandidate, type QueryCursorTableCandidate } from "@/lib/queryCursorTableTarget";
import { SIDEBAR_TREE_ROW_HEIGHT, SIDEBAR_TREE_PRERENDER_COUNT, SIDEBAR_TREE_SCROLL_BUFFER, flattenTree, scrollTopForExpandedTreeNode, shouldAutoScrollExpandedTreeNode, shouldVirtualizeFlatTree, type FlatTreeNode } from "@/composables/useFlatTree";
import { SIDEBAR_TREE_ROW_HEIGHT, SIDEBAR_TREE_PRERENDER_COUNT, SIDEBAR_TREE_SCROLL_BUFFER, flattenTree, shouldVirtualizeFlatTree, type FlatTreeNode } from "@/composables/useFlatTree";
import { sidebarTreeContextKey } from "@/lib/sidebarTreeContext";
import TreeItem from "./TreeItem.vue";
import { RecycleScroller } from "vue-virtual-scroller";
@@ -451,29 +451,6 @@ function onSearchToggle(node: TreeNode) {
searchCollapsedIds.value = next;
}
async function onNodeToggled(node: TreeNode, wasExpanded: boolean) {
if (wasExpanded || !node.isExpanded) return;
if (!shouldAutoScrollExpandedTreeNode(node.type)) return;
await nextTick();
const expandedIndex = flatNodes.value.findIndex((item) => item.id === node.id);
const insertedRowCount = flattenTree([node]).length - 1;
const scroller = treeScrollerRef.value?.$el as HTMLElement | undefined;
if (!scroller || expandedIndex < 0 || insertedRowCount <= 0) return;
const nextScrollTop = scrollTopForExpandedTreeNode({
expandedIndex,
insertedRowCount,
currentScrollTop: scroller.scrollTop,
viewportHeight: scroller.clientHeight,
});
if (nextScrollTop !== scroller.scrollTop) {
scroller.scrollTop = nextScrollTop;
}
}
function currentTreeScroller(): HTMLElement | null {
return ((useVirtualTree.value ? treeScrollerRef.value?.$el : plainTreeScrollerRef.value) as HTMLElement | undefined) ?? null;
}
@@ -630,16 +607,7 @@ defineExpose({ focusSearch, createNewGroup });
flow-mode
>
<template #default="{ item }">
<TreeItem
:node="item.node"
:depth="item.depth"
:drag-disabled="isFiltering"
:pending-rename="pendingRenameGroupId === item.node.id"
:highlighted="highlightedNodeId === item.node.id"
@node-toggled="onNodeToggled"
@search-toggle="onSearchToggle"
@rename-started="pendingRenameGroupId = null"
/>
<TreeItem :node="item.node" :depth="item.depth" :drag-disabled="isFiltering" :pending-rename="pendingRenameGroupId === item.node.id" :highlighted="highlightedNodeId === item.node.id" @search-toggle="onSearchToggle" @rename-started="pendingRenameGroupId = null" />
</template>
</RecycleScroller>
<div v-else-if="flatNodes.length > 0" ref="plainTreeScrollerRef" class="sidebar-tree min-h-0 flex-1 overflow-y-auto" :class="sidebarTreeOverflowClass" @click="clearSidebarSelection">
@@ -651,7 +619,6 @@ defineExpose({ focusSearch, createNewGroup });
:drag-disabled="isFiltering"
:pending-rename="pendingRenameGroupId === item.node.id"
:highlighted="highlightedNodeId === item.id"
@node-toggled="onNodeToggled"
@search-toggle="onSearchToggle"
@rename-started="pendingRenameGroupId = null"
/>
@@ -29,25 +29,3 @@ export function flattenTree(nodes: TreeNode[]): FlatTreeNode[] {
export function shouldVirtualizeFlatTree(count: number): boolean {
return count > 0;
}
export function shouldAutoScrollExpandedTreeNode(type: TreeNodeType): boolean {
return type !== "connection" && type !== "connection-group";
}
export function scrollTopForExpandedTreeNode(options: { expandedIndex: number; insertedRowCount: number; currentScrollTop: number; viewportHeight: number; rowHeight?: number }): number {
const rowHeight = options.rowHeight ?? SIDEBAR_TREE_ROW_HEIGHT;
if (options.expandedIndex < 0 || options.insertedRowCount <= 0 || options.viewportHeight <= 0) {
return options.currentScrollTop;
}
const visibleRowCapacity = Math.max(1, Math.floor(options.viewportHeight / rowHeight) - 1);
const rowsToReveal = Math.min(options.insertedRowCount, visibleRowCapacity);
const expandedContentBottom = (options.expandedIndex + 1 + rowsToReveal) * rowHeight;
const viewportBottom = options.currentScrollTop + options.viewportHeight;
if (expandedContentBottom <= viewportBottom) {
return options.currentScrollTop;
}
return Math.max(0, expandedContentBottom - options.viewportHeight);
}
+1 -32
View File
@@ -1,6 +1,6 @@
import { strict as assert } from "node:assert";
import { test } from "vitest";
import { SIDEBAR_TREE_ROW_HEIGHT, SIDEBAR_TREE_PRERENDER_COUNT, SIDEBAR_TREE_SCROLL_BUFFER, flattenTree, scrollTopForExpandedTreeNode, shouldAutoScrollExpandedTreeNode, shouldVirtualizeFlatTree } from "../../apps/desktop/src/composables/useFlatTree.ts";
import { SIDEBAR_TREE_ROW_HEIGHT, SIDEBAR_TREE_PRERENDER_COUNT, SIDEBAR_TREE_SCROLL_BUFFER, flattenTree, shouldVirtualizeFlatTree } from "../../apps/desktop/src/composables/useFlatTree.ts";
import type { TreeNode } from "../../apps/desktop/src/types/database.ts";
test("flattenTree preserves depth and node type for virtualized sidebar rows", () => {
@@ -51,34 +51,3 @@ test("sidebar virtual tree keeps enough buffered rows for fast scrolling", () =>
test("sidebar virtual tree prerenders enough rows for the first frame", () => {
assert.ok(SIDEBAR_TREE_PRERENDER_COUNT >= 40);
});
test("sidebar keeps root connection expansion from changing scroll position", () => {
assert.equal(shouldAutoScrollExpandedTreeNode("connection"), false);
assert.equal(shouldAutoScrollExpandedTreeNode("connection-group"), false);
assert.equal(shouldAutoScrollExpandedTreeNode("database"), true);
assert.equal(shouldAutoScrollExpandedTreeNode("group-columns"), true);
});
test("expanded sidebar nodes scroll enough to reveal inserted rows", () => {
assert.equal(
scrollTopForExpandedTreeNode({
expandedIndex: 20,
insertedRowCount: 2,
currentScrollTop: 15 * SIDEBAR_TREE_ROW_HEIGHT,
viewportHeight: 6 * SIDEBAR_TREE_ROW_HEIGHT,
}),
17 * SIDEBAR_TREE_ROW_HEIGHT,
);
});
test("expanded sidebar nodes keep scroll position when children are already visible", () => {
assert.equal(
scrollTopForExpandedTreeNode({
expandedIndex: 4,
insertedRowCount: 2,
currentScrollTop: 0,
viewportHeight: 8 * SIDEBAR_TREE_ROW_HEIGHT,
}),
0,
);
});