♻️ refactor(sidebar): 继续抽离 resolveV2ObjectGroupTitle 等 2 个工具函数

- 新增 SidebarNodeLike 结构化类型,替代 Pick<TreeNode, ...> 解除对 Sidebar 内部类型的依赖
- 迁出 resolveV2ObjectGroupTitle(对象分组标题本地化)与 resolveSidebarTableNameForCopy(节点表名提取)
- Sidebar.tsx 从 10243 减至 10235 行
This commit is contained in:
Syngnat
2026-06-19 14:15:35 +08:00
parent 87bd16c4ba
commit a4d94624cd
2 changed files with 48 additions and 14 deletions

View File

@@ -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<TreeNode, 'type' | 'dataRef'> | 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<TreeNode, 'title' | 'dataRef'> | null | undefined): string => {
return String(node?.dataRef?.tableName || node?.dataRef?.viewName || node?.dataRef?.eventName || node?.title || '').trim();
};
// resolveSidebarTableNameForCopy 已迁移到 ./sidebar/sidebarHelpers
type SidebarTableSortPreference = 'name' | 'frequency';

View File

@@ -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<SidebarNodeLike, 'type' | 'dataRef'> | 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<SidebarNodeLike, 'title' | 'dataRef'> | null | undefined,
): string => {
return String(node?.dataRef?.tableName || node?.dataRef?.viewName || node?.dataRef?.eventName || node?.title || '').trim();
};