mirror of
https://github.com/Syngnat/GoNavi.git
synced 2026-05-24 09:50:04 +08:00
feat: 新增 HTML 导出功能 (#164)
- 后端:在 writeRowsToFile 中新增 html 分支 - 后端:实现 writeRowsToHTML 函数,生成包含内嵌 CSS 的独立 HTML 文件 - 后端:实现 formatExportHTMLCell 函数,进行 HTML 转义和换行处理 - 后端:新增测试用例验证 XSS 转义、样式存在、换行处理、空值显示 - 前端:在 DataGrid 所有导出菜单中新增 HTML 选项(右键菜单、工具栏、单元格菜单) - 前端:在 Sidebar 表节点右键菜单中新增 HTML 选项 - 样式:响应式表格设计,支持斑马纹、悬停效果、表头吸顶 - 安全:所有用户数据经过 HTML 转义,防止 XSS 攻击
This commit is contained in:
@@ -537,6 +537,7 @@ const ContextMenuRow = React.memo(({ children, record, ...props }: any) => {
|
||||
{ key: 'exp-xlsx', label: 'Excel', onClick: () => handleExportSelected('xlsx', record) },
|
||||
{ key: 'exp-json', label: 'JSON', onClick: () => handleExportSelected('json', record) },
|
||||
{ key: 'exp-md', label: 'Markdown', onClick: () => handleExportSelected('md', record) },
|
||||
{ key: 'exp-html', label: 'HTML', onClick: () => handleExportSelected('html', record) },
|
||||
]
|
||||
}
|
||||
];
|
||||
@@ -2588,6 +2589,7 @@ const DataGrid: React.FC<DataGridProps> = ({
|
||||
{ key: 'filtered-xlsx', label: 'Excel (XLSX)', onClick: () => handleExportFilteredAll('xlsx') },
|
||||
{ key: 'filtered-json', label: 'JSON', onClick: () => handleExportFilteredAll('json') },
|
||||
{ key: 'filtered-md', label: 'Markdown', onClick: () => handleExportFilteredAll('md') },
|
||||
{ key: 'filtered-html', label: 'HTML', onClick: () => handleExportFilteredAll('html') },
|
||||
]},
|
||||
{ type: 'divider' },
|
||||
{ type: 'group', label: '全表', children: [
|
||||
@@ -2595,12 +2597,14 @@ const DataGrid: React.FC<DataGridProps> = ({
|
||||
{ key: 'table-xlsx', label: 'Excel (XLSX)', onClick: () => handleExport('xlsx') },
|
||||
{ key: 'table-json', label: 'JSON', onClick: () => handleExport('json') },
|
||||
{ key: 'table-md', label: 'Markdown', onClick: () => handleExport('md') },
|
||||
{ key: 'table-html', label: 'HTML', onClick: () => handleExport('html') },
|
||||
]},
|
||||
] : [
|
||||
{ key: 'csv', label: 'CSV', onClick: () => handleExport('csv') },
|
||||
{ key: 'xlsx', label: 'Excel (XLSX)', onClick: () => handleExport('xlsx') },
|
||||
{ key: 'json', label: 'JSON', onClick: () => handleExport('json') },
|
||||
{ key: 'md', label: 'Markdown', onClick: () => handleExport('md') },
|
||||
{ key: 'html', label: 'HTML', onClick: () => handleExport('html') },
|
||||
];
|
||||
|
||||
const columnInfoSettingContent = (
|
||||
@@ -3572,6 +3576,21 @@ const DataGrid: React.FC<DataGridProps> = ({
|
||||
>
|
||||
导出为 JSON
|
||||
</div>
|
||||
<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={() => {
|
||||
if (cellContextMenu.record) handleExportSelected('html', cellContextMenu.record);
|
||||
setCellContextMenu(prev => ({ ...prev, visible: false }));
|
||||
}}
|
||||
>
|
||||
导出为 HTML
|
||||
</div>
|
||||
</div>,
|
||||
document.body
|
||||
)}
|
||||
|
||||
@@ -2806,6 +2806,7 @@ const Sidebar: React.FC<{ onEditConnection?: (conn: SavedConnection) => void }>
|
||||
{ key: 'export-xlsx', label: '导出 Excel (XLSX)', onClick: () => handleExport(node, 'xlsx') },
|
||||
{ key: 'export-json', label: '导出 JSON', onClick: () => handleExport(node, 'json') },
|
||||
{ key: 'export-md', label: '导出 Markdown', onClick: () => handleExport(node, 'md') },
|
||||
{ key: 'export-html', label: '导出 HTML', onClick: () => handleExport(node, 'html') },
|
||||
]
|
||||
}
|
||||
];
|
||||
|
||||
Reference in New Issue
Block a user