diff --git a/frontend/src/NetworkConfigManager.jsx b/frontend/src/NetworkConfigManager.jsx index 39cb9ad..9865e06 100644 --- a/frontend/src/NetworkConfigManager.jsx +++ b/frontend/src/NetworkConfigManager.jsx @@ -547,9 +547,17 @@ function NetworkConfigManager() { setSelectedTemplate(template); // Инициализируем gateways из шаблона const initializedGateways = template.gateways.map((gw, index) => { - // Генерируем IP из шаблона, если есть базовый IP - let ip = gw.ipTemplate || ''; - if (templateBaseIp && gw.ipTemplate) { + let ip = ''; + + // Для прямых gateways используем IP сервера (если выбран сервер) + if (gw.type === 'direct' && templateServerId) { + const server = getServerInfo(templateServerId); + if (server && server.ip) { + ip = server.ip; + } + } + // Для рекурсивных gateways генерируем из базового IP + else if (gw.type === 'recursive' && templateBaseIp && templateBaseIp.trim().split('.').length >= 3 && gw.ipTemplate) { ip = gw.ipTemplate.replace('{baseIp}', templateBaseIp.trim()); } @@ -565,12 +573,21 @@ function NetworkConfigManager() { setTemplateGateways(initializedGateways); }; - // Обновление IP адресов при изменении базового IP + // Обновление IP адресов при изменении базового IP или сервера useEffect(() => { - if (selectedTemplate && templateBaseIp && templateBaseIp.trim().split('.').length >= 3 && templateGateways.length > 0) { + if (selectedTemplate && templateGateways.length > 0) { const updatedGateways = templateGateways.map((gw, index) => { const originalTemplate = selectedTemplate.gateways[index]; - if (originalTemplate && originalTemplate.ipTemplate) { + + // Для прямых gateways используем IP сервера + if (gw.type === 'direct' && templateServerId) { + const server = getServerInfo(templateServerId); + if (server && server.ip) { + return { ...gw, ip: server.ip }; + } + } + // Для рекурсивных gateways генерируем из базового IP + else if (gw.type === 'recursive' && templateBaseIp && templateBaseIp.trim().split('.').length >= 3 && originalTemplate && originalTemplate.ipTemplate) { const templateIp = originalTemplate.ipTemplate.replace('{baseIp}', templateBaseIp.trim()); // Обновляем IP только если он соответствует шаблону (последний октет совпадает) или пустой const currentIpParts = gw.ip ? gw.ip.split('.') : []; @@ -591,7 +608,7 @@ function NetworkConfigManager() { } } // eslint-disable-next-line react-hooks/exhaustive-deps - }, [templateBaseIp, selectedTemplate?.id]); + }, [templateBaseIp, templateServerId, selectedTemplate?.id]); const handleCreateGatewaysFromTemplate = () => { if (!selectedTemplate) { @@ -618,13 +635,22 @@ function NetworkConfigManager() { const newGateways = []; const usedIps = new Set(config.gateways.map(g => g.ip)); + + // Создаем маппинг между ID из шаблона и реальными ID после создания + const templateIdToRealId = new Map(); templateGateways.forEach((gwTemplate, index) => { - // Используем IP из редактируемого gateway (уже сгенерированный из шаблона) let ip = gwTemplate.ip || ''; - // Если IP пустой, пытаемся сгенерировать из шаблона - if (!ip && selectedTemplate.gateways[index]?.ipTemplate) { + // Для прямых gateways используем IP сервера + if (gwTemplate.type === 'direct' && templateServerId) { + const server = getServerInfo(templateServerId); + if (server && server.ip) { + ip = server.ip; + } + } + // Для рекурсивных gateways генерируем из базового IP + else if (gwTemplate.type === 'recursive' && !ip && selectedTemplate.gateways[index]?.ipTemplate) { ip = selectedTemplate.gateways[index].ipTemplate.replace('{baseIp}', templateBaseIp.trim()); } @@ -642,15 +668,24 @@ function NetworkConfigManager() { return; } + const newGatewayId = `gw-${Date.now()}-${index}-${Math.random().toString(16).slice(2, 6)}`; + + // Сохраняем маппинг ID + templateIdToRealId.set(gwTemplate.id, newGatewayId); + const newGateway = { - id: `gw-${Date.now()}-${index}-${Math.random().toString(16).slice(2, 6)}`, + id: newGatewayId, ip: ip, description: gwTemplate.description || '', serverId: templateServerId, country: gwTemplate.country || '', type: gwTemplate.type, parentGateways: gwTemplate.type === 'recursive' - ? (gwTemplate.parentGateways || []).filter(p => p && p.id) + ? (gwTemplate.parentGateways || []).filter(p => p && p.id).map(p => { + // Преобразуем ID родительского gateway из шаблона в реальный ID + const realParentId = templateIdToRealId.get(p.id) || p.id; + return { ...p, id: realParentId }; + }) : [], }; @@ -2569,9 +2604,21 @@ function NetworkConfigManager() { }; // === Получение родительского gateway или интерфейса === - const getParentGateway = (parentId) => { + const getParentGateway = (parentId, templateGatewaysList = null) => { if (!parentId) return null; + // Если передан список templateGateways, сначала ищем там + if (templateGatewaysList) { + const templateGateway = templateGatewaysList.find(g => g.id === parentId); + if (templateGateway) { + return { + parentType: 'gateway', + ...templateGateway, + ip: templateGateway.ip + }; + } + } + // Сначала ищем в gateway const gateway = config.gateways?.find(g => g.id === parentId); if (gateway) { @@ -2598,7 +2645,8 @@ function NetworkConfigManager() { // Если не найден ни gateway, ни интерфейс - логируем для отладки console.warn('Parent gateway/interface not found:', parentId, { availableGateways: config.gateways?.map(g => g.id), - availableInterfaces: config.tunnelInterfaces?.map(i => i.id) + availableInterfaces: config.tunnelInterfaces?.map(i => i.id), + templateGateways: templateGatewaysList?.map(g => g.id) }); return null; @@ -5051,15 +5099,21 @@ function NetworkConfigManager() {
{s.label}
{s.description && ({s.description})}
+ {s.isTemplate && Шаблон}