From a4d94624cd3369ee15c00bd6662c4755e9083a61 Mon Sep 17 00:00:00 2001 From: Syngnat Date: Fri, 19 Jun 2026 14:15:35 +0800 Subject: [PATCH] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20refactor(sidebar):=20?= =?UTF-8?q?=E7=BB=A7=E7=BB=AD=E6=8A=BD=E7=A6=BB=20resolveV2ObjectGroupTitl?= =?UTF-8?q?e=20=E7=AD=89=202=20=E4=B8=AA=E5=B7=A5=E5=85=B7=E5=87=BD?= =?UTF-8?q?=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增 SidebarNodeLike 结构化类型,替代 Pick 解除对 Sidebar 内部类型的依赖 - 迁出 resolveV2ObjectGroupTitle(对象分组标题本地化)与 resolveSidebarTableNameForCopy(节点表名提取) - Sidebar.tsx 从 10243 减至 10235 行 --- frontend/src/components/Sidebar.tsx | 20 +++------ .../src/components/sidebar/sidebarHelpers.ts | 42 +++++++++++++++++++ 2 files changed, 48 insertions(+), 14 deletions(-) diff --git a/frontend/src/components/Sidebar.tsx b/frontend/src/components/Sidebar.tsx index d164996..2c6dde9 100644 --- a/frontend/src/components/Sidebar.tsx +++ b/frontend/src/components/Sidebar.tsx @@ -6,6 +6,8 @@ import { shouldClearSidebarActiveContextOnEmptySelect, getV2RailConnectionGroupBadgeText, isV2SidebarObjectNode, + resolveV2ObjectGroupTitle, + resolveSidebarTableNameForCopy, type V2ExplorerFilter, } from './sidebar/sidebarHelpers'; // 重新导出,保持外部测试文件的 `from './Sidebar'` 兼容 @@ -16,6 +18,8 @@ export { shouldClearSidebarActiveContextOnEmptySelect, getV2RailConnectionGroupBadgeText, isV2SidebarObjectNode, + resolveV2ObjectGroupTitle, + resolveSidebarTableNameForCopy, } from './sidebar/sidebarHelpers'; import React, { useEffect, useState, useMemo, useRef, useCallback, useDeferredValue } from 'react'; import { createPortal } from 'react-dom'; @@ -193,17 +197,7 @@ interface TreeNode { type?: 'connection' | 'database' | 'table' | 'view' | 'materialized-view' | 'db-trigger' | 'db-event' | 'routine' | 'object-group' | 'v2-table-section' | 'queries-folder' | 'saved-query' | 'all-saved-queries' | 'saved-query-group' | 'unmatched-saved-queries' | 'external-sql-root' | 'external-sql-directory' | 'external-sql-folder' | 'external-sql-file' | 'folder-columns' | 'folder-indexes' | 'folder-fks' | 'folder-triggers' | 'redis-db' | 'tag' | 'jvm-mode' | 'jvm-resource' | 'jvm-diagnostic' | 'jvm-monitoring'; } -export const resolveV2ObjectGroupTitle = (node: Pick | null | undefined): string | null => { - if (node?.type !== 'object-group') return null; - const groupKey = String(node?.dataRef?.groupKey || ''); - if (groupKey === 'tables') return t('sidebar.v2_table_group_menu.title'); - if (groupKey === 'views') return t('sidebar.object_group.views'); - if (groupKey === 'routines') return t('sidebar.object_group.routines'); - if (groupKey === 'triggers') return t('sidebar.object_group.triggers'); - if (groupKey === 'events') return t('sidebar.object_group.events'); - if (groupKey === 'materializedViews') return t('sidebar.object_group.materialized_views'); - return null; -}; +// resolveV2ObjectGroupTitle 已迁移到 ./sidebar/sidebarHelpers export type SQLFileExecutionStatus = 'running' | 'done' | 'cancelled' | 'error'; @@ -308,9 +302,7 @@ export const shouldLoadSidebarNodeOnExpand = ( || node.type === 'jvm-resource'; }; -export const resolveSidebarTableNameForCopy = (node: Pick | null | undefined): string => { - return String(node?.dataRef?.tableName || node?.dataRef?.viewName || node?.dataRef?.eventName || node?.title || '').trim(); -}; +// resolveSidebarTableNameForCopy 已迁移到 ./sidebar/sidebarHelpers type SidebarTableSortPreference = 'name' | 'frequency'; diff --git a/frontend/src/components/sidebar/sidebarHelpers.ts b/frontend/src/components/sidebar/sidebarHelpers.ts index e326adb..966e782 100644 --- a/frontend/src/components/sidebar/sidebarHelpers.ts +++ b/frontend/src/components/sidebar/sidebarHelpers.ts @@ -98,3 +98,45 @@ export const isV2SidebarObjectNode = ( || node?.type === 'db-event' || node?.type === 'routine'; }; + +// === 第二期:依赖 i18n 但不依赖 TreeNode 内部类型的工具函数 === + +/** + * SidebarNodeLike 是 TreeNode 的结构化子集,用于工具函数签名。 + * 让 sidebarHelpers 不依赖 Sidebar.tsx 内部的 TreeNode 定义,避免循环依赖。 + */ +export interface SidebarNodeLike { + type?: string; + dataRef?: any; + title?: string; + children?: SidebarNodeLike[]; + isLeaf?: boolean; +} + +/** + * resolveV2ObjectGroupTitle 解析 V2 资源管理器中"对象分组"节点的本地化标题。 + * 仅对 type === 'object-group' 的节点有效,其他返回 null。 + */ +export const resolveV2ObjectGroupTitle = ( + node: Pick | null | undefined, +): string | null => { + if (node?.type !== 'object-group') return null; + const groupKey = String(node?.dataRef?.groupKey || ''); + if (groupKey === 'tables') return t('sidebar.v2_table_group_menu.title'); + if (groupKey === 'views') return t('sidebar.object_group.views'); + if (groupKey === 'routines') return t('sidebar.object_group.routines'); + if (groupKey === 'triggers') return t('sidebar.object_group.triggers'); + if (groupKey === 'events') return t('sidebar.object_group.events'); + if (groupKey === 'materializedViews') return t('sidebar.object_group.materialized_views'); + return null; +}; + +/** + * resolveSidebarTableNameForCopy 从节点提取用于复制的表名。 + * 优先级:dataRef.tableName > dataRef.viewName > dataRef.eventName > title。 + */ +export const resolveSidebarTableNameForCopy = ( + node: Pick | null | undefined, +): string => { + return String(node?.dataRef?.tableName || node?.dataRef?.viewName || node?.dataRef?.eventName || node?.title || '').trim(); +};