🐛 fix(connection): 修复连接颜色重启丢失并同步标签页展示

- 恢复连接清洗流程中的图标类型与颜色字段
- 标签页增加连接色标识,便于区分多连接会话
- 抽取连接视觉解析并补充回归测试
Refs #334
This commit is contained in:
Syngnat
2026-04-26 19:33:12 +08:00
parent 2b340f3136
commit 55829bce86
6 changed files with 158 additions and 3 deletions

View File

@@ -0,0 +1,46 @@
import { describe, expect, it } from 'vitest';
import type { SavedConnection } from '../types';
import {
resolveConnectionAccentColor,
resolveConnectionIconType,
} from './connectionVisual';
const baseConnection: SavedConnection = {
id: 'conn-1',
name: 'Orders',
config: {
id: 'conn-1',
type: 'mysql',
host: 'db.local',
port: 3306,
user: 'root',
},
};
describe('connectionVisual', () => {
it('uses custom icon metadata as the connection visual identity', () => {
const connection: SavedConnection = {
...baseConnection,
iconType: 'postgres',
iconColor: '#2f855a',
};
expect(resolveConnectionIconType(connection)).toBe('postgres');
expect(resolveConnectionAccentColor(connection)).toBe('#2f855a');
});
it('falls back to the data source default color when custom color is blank', () => {
expect(resolveConnectionIconType(baseConnection)).toBe('mysql');
expect(resolveConnectionAccentColor(baseConnection)).toBe('#00758F');
});
it('ignores invalid custom colors instead of rendering unsafe CSS values', () => {
const connection: SavedConnection = {
...baseConnection,
iconColor: 'url(javascript:alert(1))',
};
expect(resolveConnectionAccentColor(connection)).toBe('#00758F');
});
});

View File

@@ -0,0 +1,40 @@
import type { SavedConnection } from '../types';
import { getDbDefaultColor } from '../components/DatabaseIcons';
const HEX_COLOR_PATTERN = /^#(?:[0-9a-f]{3}|[0-9a-f]{6})$/i;
const toTrimmedString = (value: unknown): string => {
if (typeof value === 'string') {
return value.trim();
}
if (typeof value === 'number' || typeof value === 'boolean') {
return String(value).trim();
}
return '';
};
export const normalizeConnectionIconColor = (value: unknown): string => {
const color = toTrimmedString(value);
return HEX_COLOR_PATTERN.test(color) ? color : '';
};
export const resolveConnectionIconType = (
connection?: Pick<SavedConnection, 'iconType' | 'config'> | null,
): string => {
const iconType = toTrimmedString(connection?.iconType).toLowerCase();
if (iconType) {
return iconType;
}
const configType = toTrimmedString(connection?.config?.type).toLowerCase();
return configType || 'custom';
};
export const resolveConnectionAccentColor = (
connection?: Pick<SavedConnection, 'iconColor' | 'iconType' | 'config'> | null,
): string => {
const iconColor = normalizeConnectionIconColor(connection?.iconColor);
if (iconColor) {
return iconColor;
}
return getDbDefaultColor(resolveConnectionIconType(connection));
};