🐛 fix(workbench): 统一最近连接与资源树图标

- 最近连接复用资源树的数据库图标类型与强调色解析
- 保留自定义图标和颜色并按连接类型回退默认视觉
- 新增渲染回归测试覆盖 MySQL 与自定义 PostgreSQL 图标
This commit is contained in:
Syngnat
2026-08-07 10:05:53 +08:00
parent 79af082908
commit 2f24c9667c
2 changed files with 64 additions and 13 deletions

View File

@@ -1,9 +1,12 @@
import React from 'react';
import { renderToStaticMarkup } from 'react-dom/server';
import { describe, expect, it } from 'vitest';
import {
buildPinnedTableShortcuts,
buildRecentConnectionShortcuts,
buildRecentSQLFileShortcuts,
RecentConnectionShortcutItem,
} from './TabManager';
import type { ExternalSQLDirectory, SavedConnection } from '../types';
@@ -20,6 +23,38 @@ const connection = (id: string, type: string): SavedConnection => ({
});
describe('recent workbench shortcuts', () => {
it('renders recent connections with the same database identity as the sidebar tree', () => {
const mysqlConnection = connection('mysql-1', 'mysql');
const customizedConnection: SavedConnection = {
...connection('customized-1', 'mysql'),
iconType: 'postgres',
iconColor: '#2f855a',
};
const [mysqlShortcut, customizedShortcut] = buildRecentConnectionShortcuts([
mysqlConnection,
customizedConnection,
], [
{ connectionId: 'mysql-1', dbName: 'orders', openedAt: 2 },
{ connectionId: 'customized-1', dbName: 'reporting', openedAt: 1 },
]);
const mysqlMarkup = renderToStaticMarkup(React.createElement(RecentConnectionShortcutItem, {
shortcut: mysqlShortcut,
onOpen: () => undefined,
}));
const customizedMarkup = renderToStaticMarkup(React.createElement(RecentConnectionShortcutItem, {
shortcut: customizedShortcut,
onOpen: () => undefined,
}));
expect(mysqlMarkup).toContain('data-db-icon-frame="true"');
expect(mysqlMarkup).toContain('/db-icons/mysql.svg');
expect(customizedMarkup).toContain('/db-icons/postgres.svg');
expect(customizedMarkup).toContain('#2f855a');
expect(mysqlMarkup).not.toContain('anticon-database');
expect(customizedMarkup).not.toContain('anticon-database');
});
it('only offers connections that can open the SQL query editor', () => {
const shortcuts = buildRecentConnectionShortcuts([
connection('redis-1', 'redis'),

View File

@@ -54,6 +54,8 @@ import { useWorkbenchTabs } from '../hooks/useWorkbenchTabs';
import { resolveConnectionEnvironmentPresentation } from '../utils/connectionEnvironment';
import { createSidebarResizeAwareFrameScheduler } from '../utils/sidebarResizeLifecycle';
import { QUERY_TAB_RENAME_REQUEST_EVENT } from '../utils/queryTabTitle';
import { getDbIcon } from './DatabaseIcons';
import { resolveConnectionAccentColor, resolveConnectionIconType } from '../utils/connectionVisual';
const getTabKindLabel = (tab: TabData): string => {
if (tab.type === 'query') return t('tab_manager.kind_badge.query');
@@ -117,7 +119,7 @@ export const resolveV2WorkbenchTabWidth = (availableWidth: number, tabCount: num
);
};
type RecentConnectionShortcut = {
export type RecentConnectionShortcut = {
connection: SavedConnection;
dbName?: string;
};
@@ -172,6 +174,28 @@ export const buildRecentConnectionShortcuts = (
return result;
};
export const RecentConnectionShortcutItem: React.FC<{
shortcut: RecentConnectionShortcut;
onOpen: (shortcut: RecentConnectionShortcut) => void;
}> = ({ shortcut, onOpen }) => (
<button
type="button"
className="gn-v2-empty-recent-item"
onClick={() => onOpen(shortcut)}
>
{getDbIcon(
resolveConnectionIconType(shortcut.connection),
resolveConnectionAccentColor(shortcut.connection),
22,
)}
<span>
<strong title={shortcut.connection.name}>{shortcut.connection.name}</strong>
<small>{shortcut.dbName || t('tab_manager.empty.recent.connection.default_database')}</small>
</span>
<RightOutlined className="gn-v2-empty-recent-arrow" />
</button>
);
export const buildPinnedTableShortcuts = (
connections: SavedConnection[],
pinnedTableKeys: string[],
@@ -1573,19 +1597,11 @@ const TabManager: React.FC<TabManagerProps> = React.memo<TabManagerProps>(({ onF
{recentConnectionShortcuts.length > 0 ? (
<div className="gn-v2-empty-recent-list">
{recentConnectionShortcuts.map((shortcut) => (
<button
<RecentConnectionShortcutItem
key={`${shortcut.connection.id}::${shortcut.dbName || ''}`}
type="button"
className="gn-v2-empty-recent-item"
onClick={() => handleOpenRecentConnection(shortcut)}
>
<DatabaseOutlined />
<span>
<strong title={shortcut.connection.name}>{shortcut.connection.name}</strong>
<small>{shortcut.dbName || t('tab_manager.empty.recent.connection.default_database')}</small>
</span>
<RightOutlined className="gn-v2-empty-recent-arrow" />
</button>
shortcut={shortcut}
onOpen={handleOpenRecentConnection}
/>
))}
</div>
) : (