diff --git a/frontend/src/components/Sidebar.tsx b/frontend/src/components/Sidebar.tsx
index 95944ed..778f871 100644
--- a/frontend/src/components/Sidebar.tsx
+++ b/frontend/src/components/Sidebar.tsx
@@ -53,6 +53,8 @@ const Sidebar: React.FC<{ onEditConnection?: (conn: SavedConnection) => void }>
const addTab = useStore(state => state.addTab);
const setActiveContext = useStore(state => state.setActiveContext);
const removeConnection = useStore(state => state.removeConnection);
+ const closeTabsByConnection = useStore(state => state.closeTabsByConnection);
+ const closeTabsByDatabase = useStore(state => state.closeTabsByDatabase);
const theme = useStore(state => state.theme);
const appearance = useStore(state => state.appearance);
const tableAccessCount = useStore(state => state.tableAccessCount);
@@ -1592,6 +1594,7 @@ const Sidebar: React.FC<{ onEditConnection?: (conn: SavedConnection) => void }>
const res = await DropDatabase(config as any, dbName);
if (res.success) {
message.success("数据库删除成功");
+ closeTabsByDatabase(conn.id, dbName);
setExpandedKeys(prev => prev.filter(k => !k.toString().startsWith(`${conn.id}-${dbName}`)));
setLoadedKeys(prev => prev.filter(k => !k.toString().startsWith(`${conn.id}-${dbName}`)));
await loadDatabases(getConnectionNodeRef(conn));
@@ -2095,6 +2098,7 @@ const Sidebar: React.FC<{ onEditConnection?: (conn: SavedConnection) => void }>
setExpandedKeys(prev => prev.filter(k => k !== node.key && !k.toString().startsWith(`${node.key}-`)));
setLoadedKeys(prev => prev.filter(k => k !== node.key && !k.toString().startsWith(`${node.key}-`)));
setTreeData(origin => updateTreeData(origin, node.key, undefined));
+ closeTabsByConnection(String(node.key));
message.success("已断开连接");
}
},
@@ -2107,7 +2111,10 @@ const Sidebar: React.FC<{ onEditConnection?: (conn: SavedConnection) => void }>
Modal.confirm({
title: '确认删除',
content: `确定要删除连接 "${node.title}" 吗?`,
- onOk: () => removeConnection(node.key)
+ onOk: () => {
+ closeTabsByConnection(String(node.key));
+ removeConnection(node.key);
+ }
});
}
}
@@ -2177,6 +2184,7 @@ const Sidebar: React.FC<{ onEditConnection?: (conn: SavedConnection) => void }>
setLoadedKeys(prev => prev.filter(k => k !== node.key && !k.toString().startsWith(`${node.key}-`)));
// Clear children (undefined to trigger reload)
setTreeData(origin => updateTreeData(origin, node.key, undefined));
+ closeTabsByConnection(String(node.key));
message.success("已断开连接");
}
},
@@ -2189,7 +2197,10 @@ const Sidebar: React.FC<{ onEditConnection?: (conn: SavedConnection) => void }>
Modal.confirm({
title: '确认删除',
content: `确定要删除连接 "${node.title}" 吗?`,
- onOk: () => removeConnection(node.key)
+ onOk: () => {
+ closeTabsByConnection(String(node.key));
+ removeConnection(node.key);
+ }
});
}
}
@@ -2276,6 +2287,8 @@ const Sidebar: React.FC<{ onEditConnection?: (conn: SavedConnection) => void }>
label: '关闭数据库',
icon: ,
onClick: () => {
+ const dbConnId = String(node.dataRef?.id || '');
+ const dbName = String(node.dataRef?.dbName || node.title || '').trim();
setConnectionStates(prev => {
const next = { ...prev };
delete next[node.key];
@@ -2284,6 +2297,10 @@ const Sidebar: React.FC<{ onEditConnection?: (conn: SavedConnection) => void }>
setExpandedKeys(prev => prev.filter(k => k !== node.key && !k.toString().startsWith(`${node.key}-`)));
setLoadedKeys(prev => prev.filter(k => k !== node.key && !k.toString().startsWith(`${node.key}-`)));
setTreeData(origin => updateTreeData(origin, node.key, undefined));
+ if (dbConnId && dbName) {
+ closeTabsByDatabase(dbConnId, dbName);
+ }
+ message.success("已关闭数据库");
}
},
{
diff --git a/frontend/src/store.ts b/frontend/src/store.ts
index 9d96935..161dfca 100644
--- a/frontend/src/store.ts
+++ b/frontend/src/store.ts
@@ -269,6 +269,8 @@ interface AppState {
closeOtherTabs: (id: string) => void;
closeTabsToLeft: (id: string) => void;
closeTabsToRight: (id: string) => void;
+ closeTabsByConnection: (connectionId: string) => void;
+ closeTabsByDatabase: (connectionId: string, dbName: string) => void;
closeAllTabs: () => void;
setActiveTab: (id: string) => void;
setActiveContext: (context: { connectionId: string; dbName: string } | null) => void;
@@ -428,6 +430,45 @@ export const useStore = create()(
return { tabs: newTabs, activeTabId: activeStillExists ? state.activeTabId : id };
}),
+ closeTabsByConnection: (connectionId) => set((state) => {
+ const targetConnectionId = String(connectionId || '').trim();
+ if (!targetConnectionId) return state;
+ const newTabs = state.tabs.filter(t => String(t.connectionId || '').trim() !== targetConnectionId);
+ const activeStillExists = state.activeTabId ? newTabs.some(t => t.id === state.activeTabId) : false;
+ const nextActiveTabId = activeStillExists
+ ? state.activeTabId
+ : (newTabs.length > 0 ? newTabs[newTabs.length - 1].id : null);
+ const nextActiveContext = state.activeContext?.connectionId === targetConnectionId ? null : state.activeContext;
+ return {
+ tabs: newTabs,
+ activeTabId: nextActiveTabId,
+ activeContext: nextActiveContext,
+ };
+ }),
+
+ closeTabsByDatabase: (connectionId, dbName) => set((state) => {
+ const targetConnectionId = String(connectionId || '').trim();
+ const targetDbName = String(dbName || '').trim();
+ if (!targetConnectionId || !targetDbName) return state;
+ const newTabs = state.tabs.filter((tab) => {
+ const sameConnection = String(tab.connectionId || '').trim() === targetConnectionId;
+ const sameDb = String(tab.dbName || '').trim() === targetDbName;
+ return !(sameConnection && sameDb);
+ });
+ const activeStillExists = state.activeTabId ? newTabs.some(t => t.id === state.activeTabId) : false;
+ const nextActiveTabId = activeStillExists
+ ? state.activeTabId
+ : (newTabs.length > 0 ? newTabs[newTabs.length - 1].id : null);
+ const sameActiveContext = state.activeContext
+ && state.activeContext.connectionId === targetConnectionId
+ && state.activeContext.dbName === targetDbName;
+ return {
+ tabs: newTabs,
+ activeTabId: nextActiveTabId,
+ activeContext: sameActiveContext ? null : state.activeContext,
+ };
+ }),
+
closeAllTabs: () => set(() => ({ tabs: [], activeTabId: null })),
setActiveTab: (id) => set({ activeTabId: id }),