feat(frontend): 升级 DataGrid 组件并引入高性能拖拽交互

- 实现基于原生 DOM 事件的零渲染列宽拖拽,彻底解决卡顿与误触排序问题
- 查询编辑器集成 DataGrid,支持 SQL 结果直接编辑与事务提交
- 侧边栏新增上下文感知的 "新建查询" 快捷入口
- 优化 TabManager 渲染逻辑与全局布局,消除不必要的滚动条
This commit is contained in:
杨国锋
2026-02-02 11:32:49 +08:00
parent e0181cc7ac
commit af91c916c3
33 changed files with 2020 additions and 1618 deletions

View File

@@ -7,7 +7,7 @@ import { CSS } from '@dnd-kit/utilities';
import { Resizable } from 'react-resizable';
import { TabData, ColumnDefinition, IndexDefinition, ForeignKeyDefinition, TriggerDefinition } from '../types';
import { useStore } from '../store';
import { DBGetColumns, DBGetIndexes, MySQLQuery, DBGetForeignKeys, DBGetTriggers, DBShowCreateTable } from '../../wailsjs/go/main/App';
import { DBGetColumns, DBGetIndexes, MySQLQuery, DBGetForeignKeys, DBGetTriggers, DBShowCreateTable } from '../../wailsjs/go/app/App';
// Need styles for react-resizable
import 'react-resizable/css/styles.css';
@@ -74,6 +74,11 @@ const ResizableTitle = (props: any) => {
className="react-resizable-handle"
onClick={(e) => {
e.stopPropagation();
e.preventDefault();
}}
onMouseDown={(e) => {
e.stopPropagation();
e.preventDefault(); // Prevent text selection and focus hijacking
}}
style={{
position: 'absolute',
@@ -87,7 +92,7 @@ const ResizableTitle = (props: any) => {
/>
}
onResize={onResize}
draggableOpts={{ enableUserSelectHack: false }}
draggableOpts={{ enableUserSelectHack: true }}
>
<th {...restProps} style={{ ...restProps.style, position: 'relative' }} />
</Resizable>
@@ -263,16 +268,24 @@ const TableDesigner: React.FC<{ tab: TabData }> = ({ tab }) => {
setTableColumns(initialCols);
}, [readOnly]); // Re-create if readOnly changes
const rafRef = React.useRef<number | null>(null);
// Resize Handler
const handleResize = (index: number) => (_: React.SyntheticEvent, { size }: { size: { width: number } }) => {
setTableColumns((columns) => {
const nextColumns = [...columns];
nextColumns[index] = {
...nextColumns[index],
width: size.width,
};
return nextColumns;
});
if (rafRef.current) {
cancelAnimationFrame(rafRef.current);
}
rafRef.current = requestAnimationFrame(() => {
setTableColumns((columns) => {
const nextColumns = [...columns];
nextColumns[index] = {
...nextColumns[index],
width: size.width,
};
return nextColumns;
});
rafRef.current = null;
});
};
const fetchData = async () => {
@@ -587,8 +600,8 @@ const TableDesigner: React.FC<{ tab: TabData }> = ({ tab }) => {
)}
{!readOnly && <Button icon={<SaveOutlined />} type="primary" onClick={generateDDL}></Button>}
{!isNewTable && <Button icon={<ReloadOutlined />} onClick={fetchData}></Button>}
<div style={{ flex: 1 }} />
{!readOnly && <Button icon={<PlusOutlined />} onClick={handleAddColumn}></Button>}
<div style={{ flex: 1 }} />
</div>
<Tabs
activeKey={activeKey}