feat(nacos): 新增 Nacos 数据源管理能力

- 支持 Nacos 连接测试及多命名空间资源树
- 提供配置搜索、发布、删除、历史回滚和变更监听
- 增加 Beta 发布、配置导入导出与批量操作
- 支持服务发现、实例管理、只读保护和多语言界面
- 补充 Wails 接口绑定及前后端回归测试

Refs #756
This commit is contained in:
Syngnat
2026-07-28 15:55:47 +08:00
parent ce9f5cffb9
commit cef273f228
46 changed files with 10466 additions and 16 deletions

View File

@@ -42,6 +42,7 @@ const layoutKindEntries = [
['timeseries', 'timeseries'],
['custom', 'custom'],
['jvm', 'jvm'],
['nacos', 'nacos'],
['generic-sql', 'genericSql'],
] as const;

View File

@@ -47,6 +47,7 @@ export type ConnectionConfigLayoutKind =
| 'timeseries'
| 'custom'
| 'jvm'
| 'nacos'
| 'generic-sql';
export type ConnectionConfigLayout = {
@@ -136,6 +137,8 @@ export const getConnectionConfigLayoutKindLabel = (
return t('connection.modal.layoutKind.custom');
case 'jvm':
return t('connection.modal.layoutKind.jvm');
case 'nacos':
return t('connection.modal.layoutKind.nacos');
case 'generic-sql':
default:
return t('connection.modal.layoutKind.genericSql');
@@ -208,6 +211,17 @@ export const resolveConnectionConfigLayout = (
],
};
}
if (type === 'nacos') {
return {
kind: 'nacos',
sections: [
'identity',
'uri',
'target',
'credentials',
],
};
}
if (type === 'elasticsearch') {
return {
kind: 'search',

View File

@@ -21,6 +21,7 @@ export const singleHostUriSchemesByType: Record<string, string[]> = {
rocketmq: ["rocketmq", "rmq"],
mqtt: ["mqtt", "mqtts", "tcp", "ssl", "tls"],
rabbitmq: ["rabbitmq", "http", "https"],
nacos: ["http", "https", "nacos"],
};
const normalizeConnectionType = (type: string) =>
@@ -76,6 +77,7 @@ const sslSupportedTypes = new Set([
"mqtt",
"kafka",
"rabbitmq",
"nacos",
]);
export const supportsSSLForType = (type: string) =>
@@ -186,4 +188,5 @@ export const supportsConnectionParamsForType = (type: string) =>
type === "rocketmq" ||
type === "mqtt" ||
type === "kafka" ||
type === "rabbitmq";
type === "rabbitmq" ||
type === "nacos";

View File

@@ -95,6 +95,13 @@ export const CONNECTION_TYPE_GROUPS: ConnectionTypeCatalogGroup[] = [
{ key: 'rabbitmq', name: 'RabbitMQ' },
],
},
{
labelKey: 'connection_modal.step1.group.config_center',
label: 'Config centers',
items: [
{ key: 'nacos', name: 'Nacos' },
],
},
{
labelKey: 'connection_modal.step1.group.other',
label: 'Other',
@@ -177,6 +184,8 @@ export const getConnectionTypeDefaultPort = (type: string): number => {
return 9092;
case 'rabbitmq':
return 15672;
case 'nacos':
return 8848;
case 'highgo':
return 5866;
case 'mariadb':
@@ -238,6 +247,12 @@ export const getConnectionTypeHint = (
return 'Broker / Topic / Consumer Group';
case 'rabbitmq':
return 'Management API / Virtual Host / Queue';
case 'nacos':
return translateCatalogCopy(
translate,
'connection_modal.step1.hint.nacos',
'Browse and publish configs across namespaces',
);
case 'oceanbase':
return translateCatalogCopy(translate, 'connection_modal.step1.hint.oceanBase', 'MySQL / Oracle tenant');
case 'goldendb':

View File

@@ -280,6 +280,9 @@ const isRedisTab = (tab: TabData): boolean => {
return tab.type === 'redis-keys' || tab.type === 'redis-command' || tab.type === 'redis-monitor';
};
const isNacosTab = (tab: TabData): boolean =>
tab.type === 'nacos-config' || tab.type === 'nacos-services';
const buildRedisBaseTitle = (tab: TabData, translate: TabDisplayTranslate = defaultTranslate): string => {
const dbLabel = `db${tab.redisDB ?? 0}`;
if (tab.type === 'redis-command') return translate('sidebar.tab.redis_command', { database: dbLabel });
@@ -637,6 +640,13 @@ export const buildTabDisplayTitle = (
return identity ? `[${identity}] ${buildRedisBaseTitle(tab, translate)}` : buildRedisBaseTitle(tab, translate);
}
if (isNacosTab(tab)) {
const nsTitle = String(tab.nacosNamespaceName || tab.nacosNamespaceId || tab.title || 'public').trim();
const kind = tab.type === 'nacos-services' ? 'services' : 'config';
const full = `${nsTitle} · ${kind}`;
return connectionName ? `[${connectionName}] ${full}` : full;
}
const baseTitle = buildCompactObjectTabTitle(tab, translate);
if (
tab.type !== 'table' &&