feat(jvm/connection): 优化诊断工作台与连接配置体验

- JVM 诊断工作台改为会话优先布局,未建会话前隐藏命令输入

- 优化命令模板、实时输出、审计历史和能力检查卡片展示

- 连接配置表单引入按数据源分组的卡片化布局

- 补充连接配置布局和 JVM 诊断工作台回归测试
This commit is contained in:
Syngnat
2026-04-26 17:18:10 +08:00
parent df4fcab90b
commit 5bbeb7f373
8 changed files with 2593 additions and 1119 deletions

View File

@@ -15,6 +15,249 @@ type ConnectionTestFailureFeedback = {
shouldToast: boolean;
};
export type ConnectionConfigSectionKey =
| 'identity'
| 'uri'
| 'target'
| 'fileTarget'
| 'connectionMode'
| 'mongoDiscovery'
| 'replica'
| 'service'
| 'mongoPolicy'
| 'credentials'
| 'databaseScope'
| 'customDriver'
| 'customDsn'
| 'jvmRuntime';
export type ConnectionConfigLayoutKind =
| 'mysql-compatible'
| 'mongodb'
| 'redis'
| 'postgres-compatible'
| 'oracle'
| 'file'
| 'custom'
| 'jvm'
| 'generic-sql';
export type ConnectionConfigLayout = {
kind: ConnectionConfigLayoutKind;
sections: ConnectionConfigSectionKey[];
};
type ConnectionConfigSectionCopy = {
title: string;
description: string;
};
const mysqlCompatibleTypes = new Set([
'mysql',
'mariadb',
'doris',
'diros',
'sphinx',
]);
const postgresCompatibleTypes = new Set([
'postgres',
'kingbase',
'highgo',
'vastbase',
]);
const fileDatabaseTypes = new Set(['sqlite', 'duckdb']);
const CONNECTION_CONFIG_SECTION_COPY: Record<
ConnectionConfigSectionKey,
ConnectionConfigSectionCopy
> = {
identity: {
title: '基础身份',
description: '连接名称和连接树中展示的基础信息。',
},
uri: {
title: '连接 URI',
description: '适合复制粘贴完整连接串,也可以和下方参数互相生成、解析。',
},
target: {
title: '目标地址',
description: '数据库服务的主机、端口或网关入口,是连通性测试的主目标。',
},
fileTarget: {
title: '数据库文件',
description: 'SQLite / DuckDB 使用本地数据库文件路径,不需要端口和网络隧道。',
},
connectionMode: {
title: '连接模式',
description: '选择单机、主从、副本集或集群等拓扑模式。',
},
mongoDiscovery: {
title: 'MongoDB 寻址',
description: '选择标准 host:port 或 mongodb+srv DNS 发现方式。',
},
replica: {
title: '多节点配置',
description: '补充从库、种子节点、副本集成员或独立认证信息。',
},
service: {
title: '数据库服务',
description: '默认数据库、Oracle Service Name 等服务级定位参数。',
},
mongoPolicy: {
title: 'MongoDB 策略',
description: '认证库、读偏好等 MongoDB 专属策略。',
},
credentials: {
title: '认证凭据',
description: '用户名、密码和密文保留策略;留空会按已保存密文规则处理。',
},
databaseScope: {
title: '数据库范围',
description: '连接成功后可限制连接树展示的数据库或 Redis DB。',
},
customDriver: {
title: '自定义驱动',
description: '指定驱动名称,用于匹配已安装或可动态导入的数据库驱动。',
},
customDsn: {
title: '连接字符串',
description: '直接填写驱动要求的 DSN适合非内置数据源或特殊参数。',
},
jvmRuntime: {
title: 'JVM 运行时',
description: 'JVM 目标、接入模式、JMX、Endpoint、Agent 与诊断增强。',
},
};
export const getConnectionConfigSectionCopy = (
key: ConnectionConfigSectionKey,
): ConnectionConfigSectionCopy => CONNECTION_CONFIG_SECTION_COPY[key];
export const getConnectionConfigLayoutKindLabel = (
kind: ConnectionConfigLayoutKind,
): string => {
switch (kind) {
case 'mysql-compatible':
return 'MySQL 兼容';
case 'mongodb':
return '文档数据库';
case 'redis':
return '键值数据库';
case 'postgres-compatible':
return 'PostgreSQL 兼容';
case 'oracle':
return 'Oracle 服务';
case 'file':
return '文件型数据库';
case 'custom':
return '自定义连接';
case 'jvm':
return 'JVM 运行时';
case 'generic-sql':
default:
return '标准 SQL';
}
};
export const resolveConnectionConfigLayout = (
rawType: string,
): ConnectionConfigLayout => {
const type = String(rawType || '').trim().toLowerCase();
if (type === 'jvm') {
return {
kind: 'jvm',
sections: ['identity', 'jvmRuntime'],
};
}
if (type === 'custom') {
return {
kind: 'custom',
sections: ['identity', 'customDriver', 'customDsn'],
};
}
if (fileDatabaseTypes.has(type)) {
return {
kind: 'file',
sections: ['identity', 'uri', 'fileTarget'],
};
}
if (mysqlCompatibleTypes.has(type)) {
return {
kind: 'mysql-compatible',
sections: [
'identity',
'uri',
'target',
'connectionMode',
'replica',
'credentials',
'databaseScope',
],
};
}
if (type === 'mongodb') {
return {
kind: 'mongodb',
sections: [
'identity',
'uri',
'target',
'connectionMode',
'mongoDiscovery',
'replica',
'mongoPolicy',
'credentials',
'databaseScope',
],
};
}
if (type === 'redis') {
return {
kind: 'redis',
sections: [
'identity',
'uri',
'target',
'connectionMode',
'credentials',
'databaseScope',
],
};
}
if (postgresCompatibleTypes.has(type)) {
return {
kind: 'postgres-compatible',
sections: [
'identity',
'uri',
'target',
'service',
'credentials',
'databaseScope',
],
};
}
if (type === 'oracle') {
return {
kind: 'oracle',
sections: [
'identity',
'uri',
'target',
'service',
'credentials',
'databaseScope',
],
};
}
return {
kind: 'generic-sql',
sections: ['identity', 'uri', 'target', 'credentials', 'databaseScope'],
};
};
const normalizeText = (value: unknown, fallback = ''): string => {
const text = String(value ?? '').trim();
if (!text || text === 'undefined' || text === 'null') {