🐛 fix(TableOverview/DataGrid): 修复表概览重复打开Tab及隐藏列修改失效

- Tab去重:表概览 buildTableStatusSQL 对 postgres/kingbase/vastbase/highgo/sqlserver 返回 schema.table 格式表名,与侧边栏一致
- Tab ID统一:移除 openTable 中多余的 table- 前缀,使 Tab ID 格式匹配
- 语义去重:addTab 新增 connectionId+dbName+tableName 语义匹配作为安全网
- 数据修复:handleCommit 和 applyRowEditor 将 displayColumnNames 改为 columnNames,确保隐藏列修改被正确提交
- refs #264
- refs #265
This commit is contained in:
Syngnat
2026-03-20 10:33:51 +08:00
parent 8950081a6c
commit 0f717706b0
3 changed files with 26 additions and 9 deletions

View File

@@ -3011,7 +3011,7 @@ const DataGrid: React.FC<DataGridProps> = ({
const baseRawMap = rowEditorBaseRawRef.current || {};
const patch: Record<string, any> = {};
displayColumnNames.forEach((col) => {
columnNames.forEach((col) => {
const nextVal = values[col];
const baseVal = baseRawMap[col];
if (!isCellValueEqualForDiff(baseVal, nextVal)) patch[col] = nextVal;
@@ -3025,7 +3025,7 @@ const DataGrid: React.FC<DataGridProps> = ({
});
closeRowEditor();
}, [rowEditorRowKey, rowEditorForm, addedRows, displayColumnNames, rowKeyStr, closeRowEditor]);
}, [rowEditorRowKey, rowEditorForm, addedRows, columnNames, rowKeyStr, closeRowEditor]);
const enableVirtual = viewMode === 'table';
@@ -3207,7 +3207,7 @@ const DataGrid: React.FC<DataGridProps> = ({
if (!hasRowKey) {
values = { ...(newRow as any) };
} else {
displayColumnNames.forEach((col) => {
columnNames.forEach((col) => {
const nextVal = (newRow as any)?.[col];
const prevVal = (originalRow as any)?.[col];
if (!isCellValueEqualForDiff(prevVal, nextVal)) values[col] = nextVal;

View File

@@ -57,11 +57,12 @@ const buildTableStatusSQL = (dialect: string, dbName: string, schemaName?: strin
return `SHOW TABLE STATUS FROM \`${dbName.replace(/`/g, '``')}\``;
case 'postgres':
case 'kingbase':
case 'vastbase': {
case 'vastbase':
case 'highgo': {
const schema = schemaName || 'public';
return `
SELECT
c.relname AS table_name,
n.nspname || '.' || c.relname AS table_name,
obj_description(c.oid, 'pg_class') AS table_comment,
c.reltuples::bigint AS table_rows,
pg_total_relation_size(c.oid) AS data_length,
@@ -76,18 +77,19 @@ ORDER BY c.relname`;
const safeDB = `[${dbName.replace(/]/g, ']]')}]`;
return `
SELECT
t.name AS table_name,
s.name + '.' + t.name AS table_name,
ep.value AS table_comment,
SUM(p.rows) AS table_rows,
SUM(a.total_pages) * 8 * 1024 AS data_length,
SUM(a.used_pages) * 8 * 1024 AS index_length
FROM ${safeDB}.sys.tables t
JOIN ${safeDB}.sys.schemas s ON t.schema_id = s.schema_id
LEFT JOIN ${safeDB}.sys.extended_properties ep ON ep.major_id = t.object_id AND ep.minor_id = 0 AND ep.name = 'MS_Description'
LEFT JOIN ${safeDB}.sys.partitions p ON t.object_id = p.object_id AND p.index_id IN (0, 1)
LEFT JOIN ${safeDB}.sys.allocation_units a ON p.partition_id = a.container_id
WHERE t.type = 'U'
GROUP BY t.name, ep.value
ORDER BY t.name`;
GROUP BY s.name, t.name, ep.value
ORDER BY s.name, t.name`;
}
case 'clickhouse':
return `SELECT name AS table_name, comment AS table_comment, total_rows AS table_rows, total_bytes AS data_length, 0 AS index_length FROM system.tables WHERE database = '${escapeLiteral(dbName)}' AND engine NOT IN ('View', 'MaterializedView') ORDER BY name`;
@@ -194,7 +196,7 @@ const TableOverview: React.FC<TableOverviewProps> = ({ tab }) => {
const openTable = useCallback((tableName: string) => {
if (!connection) return;
addTab({
id: `${connection.id}-${tab.dbName}-table-${tableName}`,
id: `${connection.id}-${tab.dbName}-${tableName}`,
title: tableName,
type: 'table',
connectionId: connection.id,

View File

@@ -721,6 +721,21 @@ export const useStore = create<AppState>()(
newTabs[index] = { ...newTabs[index], ...tab };
return { tabs: newTabs, activeTabId: tab.id };
}
// 语义去重:对 table/design 类型按 connectionId+dbName+tableName 匹配已有 Tab
if ((tab.type === 'table' || tab.type === 'design') && tab.tableName && tab.connectionId && tab.dbName) {
const semanticIndex = state.tabs.findIndex(t =>
t.type === tab.type &&
t.connectionId === tab.connectionId &&
t.dbName === tab.dbName &&
t.tableName === tab.tableName
);
if (semanticIndex !== -1) {
const existingTab = state.tabs[semanticIndex];
const newTabs = [...state.tabs];
newTabs[semanticIndex] = { ...existingTab, ...tab, id: existingTab.id };
return { tabs: newTabs, activeTabId: existingTab.id };
}
}
return { tabs: [...state.tabs, tab], activeTabId: tab.id };
}),