From da5708b5bc49f72f1bf420c01d82c01fbd183a59 Mon Sep 17 00:00:00 2001 From: Syngnat Date: Wed, 11 Feb 2026 10:12:03 +0800 Subject: [PATCH] =?UTF-8?q?=F0=9F=94=A7=20fix(frontend-data-grid):=20?= =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E5=B0=8F=E5=B1=8F=E5=B8=83=E5=B1=80=E6=88=AA?= =?UTF-8?q?=E6=96=AD=E5=B9=B6=E6=A0=B9=E6=B2=BBMySQL=E6=8E=92=E5=BA=8F?= =?UTF-8?q?=E5=86=85=E5=AD=98=E6=BA=A2=E5=87=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/package.json.md5 | 2 +- frontend/src/App.tsx | 6 +- frontend/src/components/DataGrid.tsx | 127 +++++++++++++++++-------- frontend/src/components/DataViewer.tsx | 77 ++++++++++----- frontend/src/components/TabManager.tsx | 5 + frontend/src/utils/sql.ts | 35 +++++++ 6 files changed, 184 insertions(+), 68 deletions(-) diff --git a/frontend/package.json.md5 b/frontend/package.json.md5 index a7661c0..0f8f4fe 100755 --- a/frontend/package.json.md5 +++ b/frontend/package.json.md5 @@ -1 +1 @@ -d0f9366af59a6367ad3c7e2d4185ead4 \ No newline at end of file +5b8157374dae5f9340e31b2d0bd2c00e \ No newline at end of file diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index 2563846..c684af1 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -705,7 +705,7 @@ function App() { - + - -
+ +
{isLogPanelOpen && ( diff --git a/frontend/src/components/DataGrid.tsx b/frontend/src/components/DataGrid.tsx index 6bf7aaa..47604c9 100644 --- a/frontend/src/components/DataGrid.tsx +++ b/frontend/src/components/DataGrid.tsx @@ -9,7 +9,7 @@ import ImportPreviewModal from './ImportPreviewModal'; import { useStore } from '../store'; import { v4 as uuidv4 } from 'uuid'; import 'react-resizable/css/styles.css'; -import { buildOrderBySQL, buildWhereSQL, escapeLiteral, quoteIdentPart, quoteQualifiedIdent, type FilterCondition } from '../utils/sql'; +import { buildOrderBySQL, buildWhereSQL, escapeLiteral, quoteIdentPart, quoteQualifiedIdent, withSortBufferTuningSQL, type FilterCondition } from '../utils/sql'; import { isMacLikePlatform, normalizeOpacityForPlatform } from '../utils/appearance'; // --- Error Boundary --- @@ -496,6 +496,7 @@ interface DataGridProps { onSort?: (field: string, order: string) => void; onPageChange?: (page: number, size: number) => void; pagination?: { current: number, pageSize: number, total: number, totalKnown?: boolean }; + sortInfoExternal?: { columnKey: string, order: string } | null; // Filtering showFilter?: boolean; onToggleFilter?: () => void; @@ -514,7 +515,7 @@ type GridViewMode = 'table' | 'json' | 'text'; const DataGrid: React.FC = ({ data, columnNames, loading, tableName, dbName, connectionId, pkColumns = [], readOnly = false, - onReload, onSort, onPageChange, pagination, showFilter, onToggleFilter, onApplyFilter + onReload, onSort, onPageChange, pagination, sortInfoExternal, showFilter, onToggleFilter, onApplyFilter }) => { const connections = useStore(state => state.connections); const addSqlLog = useStore(state => state.addSqlLog); @@ -661,6 +662,21 @@ const DataGrid: React.FC = ({ const [sortInfo, setSortInfo] = useState<{ columnKey: string, order: string } | null>(null); const [columnWidths, setColumnWidths] = useState>({}); + useEffect(() => { + const nextOrder = sortInfoExternal?.order === 'ascend' || sortInfoExternal?.order === 'descend' + ? sortInfoExternal.order + : ''; + const nextColumn = nextOrder ? String(sortInfoExternal?.columnKey || '') : ''; + const currColumn = String(sortInfo?.columnKey || ''); + const currOrder = sortInfo?.order === 'ascend' || sortInfo?.order === 'descend' ? sortInfo.order : ''; + if (nextColumn === currColumn && nextOrder === currOrder) return; + if (!nextColumn || !nextOrder) { + setSortInfo(null); + } else { + setSortInfo({ columnKey: nextColumn, order: nextOrder }); + } + }, [sortInfoExternal, sortInfo]); + const closeCellEditor = useCallback(() => { setCellEditorOpen(false); setCellEditorMeta(null); @@ -1113,9 +1129,16 @@ const DataGrid: React.FC = ({ const handleTableChange = (pag: any, filtersArg: any, sorter: any) => { if (isResizingRef.current) return; // Block sort if resizing if (sorter.field) { + const field = String(sorter.field); const order = sorter.order as string; - setSortInfo({ columnKey: sorter.field as string, order }); - if (onSort) onSort(sorter.field, order); + const normalizedOrder = order === 'ascend' || order === 'descend' ? order : ''; + if (!normalizedOrder) { + setSortInfo(null); + if (onSort) onSort('', ''); + return; + } + setSortInfo({ columnKey: field, order: normalizedOrder }); + if (onSort) onSort(field, normalizedOrder); } else { setSortInfo(null); if (onSort) onSort('', ''); @@ -1820,6 +1843,11 @@ const DataGrid: React.FC = ({ const whereSQL = buildWhereSQL(dbType, filterConditions); let sql = `SELECT * FROM ${quoteQualifiedIdent(dbType, tableName)} ${whereSQL}`; sql += buildOrderBySQL(dbType, sortInfo, pkColumns); + const normalizedType = String(dbType || '').trim().toLowerCase(); + const hasExplicitSort = !!sortInfo?.columnKey && (sortInfo?.order === 'ascend' || sortInfo?.order === 'descend'); + if (hasExplicitSort && (normalizedType === 'mysql' || normalizedType === 'mariadb')) { + sql = withSortBufferTuningSQL(normalizedType, sql, 32 * 1024 * 1024); + } const offset = (pagination.current - 1) * pagination.pageSize; sql += ` LIMIT ${pagination.pageSize} OFFSET ${offset}`; return sql; @@ -2034,9 +2062,9 @@ const DataGrid: React.FC = ({ }, [viewMode, totalWidth, mergedDisplayData.length, recalculateTableMetrics]); return ( -
- {/* Toolbar */} -
+
+ {/* Toolbar */} +
{onReload &&
{/* Filter Panel */} {showFilter && ( @@ -2448,8 +2478,8 @@ const DataGrid: React.FC = ({ />
- ) : ( -
+ ) : ( +
)}
-
+
{currentTextRow ? columnNames.map((col) => (
@@ -2672,8 +2702,21 @@ const DataGrid: React.FC = ({
)} -