feat(sidebar): 新增表节点右键复制表名功能

- 左侧表节点右键菜单增加复制表名入口
- 复制真实表名并提供中文剪贴板提示
- 补充表名解析逻辑测试
Refs #460
This commit is contained in:
Syngnat
2026-05-13 20:28:18 +08:00
parent 0bcb8ce6c3
commit 75185f5e66
3 changed files with 37 additions and 2 deletions

View File

@@ -1 +1 @@
d0464f9da25e9356e61652e638c99ffe
d0464f9da25e9356e61652e638c99ffe

View File

@@ -2,7 +2,7 @@ import React from 'react';
import { renderToStaticMarkup } from 'react-dom/server';
import { describe, expect, it, vi } from 'vitest';
import Sidebar from './Sidebar';
import Sidebar, { resolveSidebarTableNameForCopy } from './Sidebar';
const mocks = vi.hoisted(() => ({
noop: vi.fn(),
@@ -80,6 +80,17 @@ vi.mock('../../wailsjs/runtime/runtime', () => ({
}));
describe('Sidebar locate toolbar', () => {
it('resolves the table name used by the sidebar copy action', () => {
expect(resolveSidebarTableNameForCopy({
title: 'users',
dataRef: { tableName: 'public.users' },
})).toBe('public.users');
expect(resolveSidebarTableNameForCopy({
title: 'users',
dataRef: {},
})).toBe('users');
});
it('renders the current table locate action in the sidebar toolbar', () => {
const markup = renderToStaticMarkup(<Sidebar />);
const externalSqlActionIndex = markup.indexOf('data-sidebar-open-external-sql-file-action="true"');

View File

@@ -76,6 +76,10 @@ interface TreeNode {
type?: 'connection' | 'database' | 'table' | 'view' | 'db-trigger' | 'routine' | 'object-group' | 'queries-folder' | 'saved-query' | '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 resolveSidebarTableNameForCopy = (node: Pick<TreeNode, 'title' | 'dataRef'> | null | undefined): string => {
return String(node?.dataRef?.tableName || node?.title || '').trim();
};
type BatchTableExportMode = 'schema' | 'backup' | 'dataOnly';
type BatchObjectType = 'table' | 'view';
type BatchObjectFilterType = 'all' | BatchObjectType;
@@ -2055,6 +2059,20 @@ const Sidebar: React.FC<{ onEditConnection?: (conn: SavedConnection) => void }>
}
};
const handleCopyTableName = async (node: any) => {
const tableName = resolveSidebarTableNameForCopy(node);
if (!tableName) {
message.warning('表名为空,无法复制');
return;
}
try {
await navigator.clipboard.writeText(tableName);
message.success('表名已复制到剪贴板');
} catch (e: any) {
message.error('复制表名失败: ' + (e?.message || String(e)));
}
};
const handleExport = async (node: any, format: string) => {
const { config, dbName, tableName } = node.dataRef;
const hide = message.loading(`正在导出 ${tableName}${format.toUpperCase()}...`, 0);
@@ -4302,6 +4320,12 @@ const Sidebar: React.FC<{ onEditConnection?: (conn: SavedConnection) => void }>
icon: <EditOutlined />,
onClick: () => openDesign(node, 'columns', false)
},
{
key: 'copy-table-name',
label: '复制表名',
icon: <CopyOutlined />,
onClick: () => handleCopyTableName(node)
},
{
key: 'copy-structure',
label: '复制表结构',