feat(data-grid): 支持右键复制字段名称

- 新增单元格右键菜单“复制字段名称”
- 将表格复制成功提示改为中文
- 补充字段名称解析回归测试
This commit is contained in:
Syngnat
2026-05-10 20:55:16 +08:00
parent 7dc9da0fd0
commit 2d9d5f0e98
2 changed files with 35 additions and 2 deletions

View File

@@ -2,7 +2,7 @@ import React from 'react';
import { renderToStaticMarkup } from 'react-dom/server';
import { describe, expect, it, vi } from 'vitest';
import DataGrid, { formatCellDisplayText } from './DataGrid';
import DataGrid, { formatCellDisplayText, resolveContextMenuFieldName } from './DataGrid';
vi.mock('../store', () => ({
useStore: (selector: (state: any) => any) => selector({
@@ -87,6 +87,11 @@ describe('DataGrid layout', () => {
expect(formatCellDisplayText('2026-05-10T09:12:33.456+08:00')).toBe('2026-05-10 09:12:33.456');
});
it('resolves the field name copied from the cell context menu', () => {
expect(resolveContextMenuFieldName('created_at', '创建时间')).toBe('created_at');
expect(resolveContextMenuFieldName('', 'fallback_name')).toBe('fallback_name');
});
it('renders a DDL action for table data pages only', () => {
const tableMarkup = renderToStaticMarkup(
<DataGrid

View File

@@ -163,6 +163,10 @@ const splitCellKey = (cellKey: string): { rowKey: string; colName: string } | nu
colName: cellKey.slice(sepIndex + CELL_KEY_SEP.length),
};
};
export const resolveContextMenuFieldName = (dataIndex: string, title?: string): string => {
const name = String(dataIndex || title || '').trim();
return name;
};
const trimSimpleCache = (cache: Map<string, string>, limit: number) => {
if (cache.size < limit) return;
@@ -4274,9 +4278,19 @@ const DataGrid: React.FC<DataGridProps> = ({
const copyToClipboard = useCallback((text: string) => {
navigator.clipboard.writeText(text).catch(console.error);
void message.success("Copied to clipboard");
void message.success("已复制到剪贴板");
}, []);
const handleCopyContextMenuFieldName = useCallback(() => {
const fieldName = resolveContextMenuFieldName(cellContextMenu.dataIndex, cellContextMenu.title);
if (!fieldName) {
void message.info('未识别到字段名称');
return;
}
copyToClipboard(fieldName);
setCellContextMenu(prev => ({ ...prev, visible: false }));
}, [cellContextMenu.dataIndex, cellContextMenu.title, copyToClipboard]);
const getClipboardRows = useCallback(() => (
pickRowsForClipboard({
rows: mergedDisplayData as Array<Record<string, unknown>>,
@@ -6534,6 +6548,20 @@ const DataGrid: React.FC<DataGridProps> = ({
}}
onClick={(e) => e.stopPropagation()}
>
<div
style={{
padding: '8px 12px',
cursor: 'pointer',
transition: 'background 0.2s',
}}
onMouseEnter={(e) => e.currentTarget.style.background = darkMode ? '#303030' : '#f5f5f5'}
onMouseLeave={(e) => e.currentTarget.style.background = 'transparent'}
onClick={handleCopyContextMenuFieldName}
>
<CopyOutlined style={{ marginRight: 8 }} />
</div>
<div style={{ height: 1, background: darkMode ? '#303030' : '#f0f0f0', margin: '4px 0' }} />
{canModifyData && (
<>
<div