fix(sidebar): 保持表列表滚动显示
This commit is contained in:
1 parent
cab0e79dad
commit
e4c1d6639b
6 files changed
+166
-74
No files matched your search
@@ -5,7 +5,14 @@ import { Search, X, ListFilter, Check, FolderPlus } from "lucide-vue-next";
|
||||
import { useConnectionStore } from "@/stores/connectionStore";
|
||||
import type { TreeNode } from "@/types/database";
|
||||
import { matchSidebarLabel } from "@/lib/sidebarSearch";
|
||||
import { flattenTree, 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 TreeItem from "./TreeItem.vue";
|
||||
import DatabaseIcon from "@/components/icons/DatabaseIcon.vue";
|
||||
import { RecycleScroller } from "vue-virtual-scroller";
|
||||
@@ -242,7 +249,9 @@ function onSearchToggle(node: TreeNode) {
|
||||
v-if="flatNodes.length > 0 && useVirtualTree"
|
||||
class="min-h-0 flex-1 overflow-y-auto"
|
||||
:items="flatNodes"
|
||||
:item-size="28"
|
||||
:item-size="SIDEBAR_TREE_ROW_HEIGHT"
|
||||
:buffer="SIDEBAR_TREE_SCROLL_BUFFER"
|
||||
:prerender="SIDEBAR_TREE_PRERENDER_COUNT"
|
||||
key-field="id"
|
||||
type-field="type"
|
||||
flow-mode
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
import type { TreeNode, TreeNodeType } from "@/types/database";
|
||||
|
||||
export const SIDEBAR_TREE_ROW_HEIGHT = 28;
|
||||
export const SIDEBAR_TREE_SCROLL_BUFFER = SIDEBAR_TREE_ROW_HEIGHT * 48;
|
||||
export const SIDEBAR_TREE_PRERENDER_COUNT = 48;
|
||||
|
||||
export interface FlatTreeNode {
|
||||
node: TreeNode;
|
||||
depth: number;
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
import type { TableInfo, TreeNode } from "@/types/database";
|
||||
|
||||
export function buildTableTreeNodes({
|
||||
nodeId,
|
||||
connectionId,
|
||||
database,
|
||||
schema,
|
||||
tables,
|
||||
}: {
|
||||
nodeId: string;
|
||||
connectionId: string;
|
||||
database: string;
|
||||
schema?: string;
|
||||
tables: TableInfo[];
|
||||
}): TreeNode[] {
|
||||
return tables.map((table) => ({
|
||||
id: `${nodeId}:${table.name}`,
|
||||
label: table.name,
|
||||
type: table.table_type === "VIEW" ? "view" : "table",
|
||||
connectionId,
|
||||
database,
|
||||
schema,
|
||||
isExpanded: false,
|
||||
children: [],
|
||||
}));
|
||||
}
|
||||
|
||||
export function expandCachedObjectBrowserNodes(nodes: TreeNode[]): TreeNode[] {
|
||||
return nodes.flatMap((node) => {
|
||||
if (node.type === "object-browser") return node.hiddenChildren ?? [];
|
||||
|
||||
if (!node.children) return [node];
|
||||
|
||||
return [
|
||||
{
|
||||
...node,
|
||||
children: expandCachedObjectBrowserNodes(node.children),
|
||||
},
|
||||
];
|
||||
});
|
||||
}
|
||||
@@ -23,10 +23,10 @@ import { isTauriRuntime } from "@/lib/tauriRuntime";
|
||||
import { isSchemaAware, TREE_SCHEMA_TYPES } from "@/lib/databaseCapabilities";
|
||||
import { buildDatabaseTreeNodes } from "@/lib/databaseTree";
|
||||
import { buildSqlServerDatabaseTreeNodes, SQLSERVER_DEFAULT_SCHEMA } from "@/lib/sqlServerTree";
|
||||
import { buildTableTreeNodes, expandCachedObjectBrowserNodes } from "@/lib/tableTree";
|
||||
import { useSavedSqlStore } from "@/stores/savedSqlStore";
|
||||
|
||||
const PINNED_TREE_NODES_STORAGE_KEY = "dbx-pinned-tree-nodes";
|
||||
const SIDEBAR_TABLE_NODE_LIMIT = 15;
|
||||
type ImportSource = "dbx" | "navicat" | "dbeaver";
|
||||
|
||||
interface LoadTreeOptions {
|
||||
@@ -280,9 +280,12 @@ export const useConnectionStore = defineStore("connection", () => {
|
||||
async function loadPersistedTreeChildren(node: TreeNode, cacheKey: string): Promise<boolean> {
|
||||
const children = await api.loadSchemaCache<TreeNode[]>(cacheKey).catch(() => null);
|
||||
if (!children) return false;
|
||||
const normalizedChildren = expandCachedObjectBrowserNodes(children);
|
||||
setChildren(
|
||||
node,
|
||||
node.type === "connection" && node.connectionId ? withSavedSqlRoot(node.connectionId, children, node) : children,
|
||||
node.type === "connection" && node.connectionId
|
||||
? withSavedSqlRoot(node.connectionId, normalizedChildren, node)
|
||||
: normalizedChildren,
|
||||
);
|
||||
node.isExpanded = true;
|
||||
return true;
|
||||
@@ -292,24 +295,6 @@ export const useConnectionStore = defineStore("connection", () => {
|
||||
await api.saveSchemaCache(cacheKey, children).catch(() => undefined);
|
||||
}
|
||||
|
||||
function buildObjectBrowserNode(
|
||||
nodeId: string,
|
||||
connectionId: string,
|
||||
database: string,
|
||||
schema: string | undefined,
|
||||
objectCount: number,
|
||||
): TreeNode {
|
||||
return {
|
||||
id: `${nodeId}:__object_browser`,
|
||||
label: "tree.objectBrowser",
|
||||
type: "object-browser",
|
||||
connectionId,
|
||||
database,
|
||||
schema,
|
||||
objectCount,
|
||||
};
|
||||
}
|
||||
|
||||
function useCachedChildren(node: TreeNode, options?: LoadTreeOptions): boolean {
|
||||
if (options?.force || !loadedTreeNodeChildrenIds.value.has(node.id)) return false;
|
||||
node.isExpanded = true;
|
||||
@@ -683,34 +668,7 @@ export const useConnectionStore = defineStore("connection", () => {
|
||||
api.listSchemas(connectionId, database),
|
||||
api.listTables(connectionId, database, SQLSERVER_DEFAULT_SCHEMA),
|
||||
]);
|
||||
let children = buildSqlServerDatabaseTreeNodes(connectionId, database, schemas, defaultSchemaTables);
|
||||
if (defaultSchemaTables.length > SIDEBAR_TABLE_NODE_LIMIT) {
|
||||
const previewTables = buildSqlServerDatabaseTreeNodes(
|
||||
connectionId,
|
||||
database,
|
||||
[],
|
||||
defaultSchemaTables.slice(0, SIDEBAR_TABLE_NODE_LIMIT),
|
||||
);
|
||||
const browserNode = buildObjectBrowserNode(
|
||||
`${nodeId}:${SQLSERVER_DEFAULT_SCHEMA}`,
|
||||
connectionId,
|
||||
database,
|
||||
SQLSERVER_DEFAULT_SCHEMA,
|
||||
defaultSchemaTables.length,
|
||||
);
|
||||
const hiddenTables = defaultSchemaTables.slice(SIDEBAR_TABLE_NODE_LIMIT);
|
||||
browserNode.hiddenChildren = hiddenTables.map((t) => ({
|
||||
id: `${nodeId}:${SQLSERVER_DEFAULT_SCHEMA}:${t.name}`,
|
||||
label: t.name,
|
||||
type: (t.table_type === "VIEW" ? "view" : "table") as "view" | "table",
|
||||
connectionId,
|
||||
database,
|
||||
schema: SQLSERVER_DEFAULT_SCHEMA,
|
||||
isExpanded: false,
|
||||
children: [],
|
||||
}));
|
||||
children = [...previewTables, browserNode, ...children.filter((child) => child.type === "schema")];
|
||||
}
|
||||
const children = buildSqlServerDatabaseTreeNodes(connectionId, database, schemas, defaultSchemaTables);
|
||||
setChildren(node, children);
|
||||
await savePersistedTreeChildren(cacheKey, children);
|
||||
node.isExpanded = true;
|
||||
@@ -734,32 +692,13 @@ export const useConnectionStore = defineStore("connection", () => {
|
||||
const tables = await api.listTables(connectionId, database, querySchema);
|
||||
const config = getConfig(connectionId);
|
||||
const effectiveSchema = schema || (config?.db_type && isSchemaAware(config.db_type) ? database : undefined);
|
||||
const visibleTables = tables.slice(0, SIDEBAR_TABLE_NODE_LIMIT);
|
||||
const children: TreeNode[] = visibleTables.map((t) => ({
|
||||
id: `${nodeId}:${t.name}`,
|
||||
label: t.name,
|
||||
type: (t.table_type === "VIEW" ? "view" : "table") as "view" | "table",
|
||||
const children = buildTableTreeNodes({
|
||||
nodeId,
|
||||
connectionId,
|
||||
database,
|
||||
schema: effectiveSchema,
|
||||
isExpanded: false,
|
||||
children: [],
|
||||
}));
|
||||
if (tables.length > SIDEBAR_TABLE_NODE_LIMIT) {
|
||||
const hiddenTables = tables.slice(SIDEBAR_TABLE_NODE_LIMIT);
|
||||
const browserNode = buildObjectBrowserNode(nodeId, connectionId, database, effectiveSchema, tables.length);
|
||||
browserNode.hiddenChildren = hiddenTables.map((t) => ({
|
||||
id: `${nodeId}:${t.name}`,
|
||||
label: t.name,
|
||||
type: (t.table_type === "VIEW" ? "view" : "table") as "view" | "table",
|
||||
connectionId,
|
||||
database,
|
||||
schema: effectiveSchema,
|
||||
isExpanded: false,
|
||||
children: [],
|
||||
}));
|
||||
children.push(browserNode);
|
||||
}
|
||||
tables,
|
||||
});
|
||||
setChildren(node, children);
|
||||
await savePersistedTreeChildren(cacheKey, children);
|
||||
node.isExpanded = true;
|
||||
|
||||
Reference in new issue
Block a user