diff --git a/frontend/src/NetworkConfigManager.jsx b/frontend/src/NetworkConfigManager.jsx index a36d5c9..4bafa7c 100644 --- a/frontend/src/NetworkConfigManager.jsx +++ b/frontend/src/NetworkConfigManager.jsx @@ -583,6 +583,7 @@ function NetworkConfigManager() { ip: ip, description: gw.description || '', country: gw.country || '', + serverId: templateServerId, // Сохраняем serverId для фильтрации parentGateways: gw.parentGateways ? [...gw.parentGateways] : [], }; }); @@ -595,11 +596,14 @@ function NetworkConfigManager() { const updatedGateways = templateGateways.map((gw, index) => { const originalTemplate = selectedTemplate.gateways[index]; + // Обновляем serverId для всех gateways при изменении сервера + const updatedGateway = { ...gw, serverId: templateServerId }; + // Для прямых gateways используем IP сервера if (gw.type === 'direct' && templateServerId) { const server = getServerInfo(templateServerId); if (server && server.ip) { - return { ...gw, ip: server.ip }; + return { ...updatedGateway, ip: server.ip }; } } // Для рекурсивных gateways генерируем из базового IP @@ -614,14 +618,14 @@ function NetworkConfigManager() { // Если IP пустой или последний октет совпадает с шаблоном, обновляем if (!gw.ip || (currentIpParts.length === 4 && templateIpParts.length === 4 && currentIpParts[3] === templateIpParts[3])) { - return { ...gw, ip: templateIp }; + return { ...updatedGateway, ip: templateIp }; } } } - return gw; + return updatedGateway; }); // Обновляем только если есть изменения - const hasChanges = updatedGateways.some((gw, i) => gw.ip !== templateGateways[i]?.ip); + const hasChanges = updatedGateways.some((gw, i) => gw.ip !== templateGateways[i]?.ip || gw.serverId !== templateGateways[i]?.serverId); if (hasChanges) { setTemplateGateways(updatedGateways); } @@ -3886,6 +3890,7 @@ function NetworkConfigManager() { }} gateways={config.gateways} interfaces={config.tunnelInterfaces} + serverId={editingGateway.serverId} excludeGatewayId={editingGateway.id} placeholder="Выберите родительский gateway или интерфейс..." /> @@ -5318,6 +5323,7 @@ function NetworkConfigManager() { gateways={config.gateways} interfaces={config.tunnelInterfaces} templateGateways={templateGateways} + serverId={templateServerId} excludeGatewayId={gw.id} placeholder="Выберите родительский gateway или интерфейс..." /> diff --git a/frontend/src/components/GatewayAutocompleteInput.jsx b/frontend/src/components/GatewayAutocompleteInput.jsx index 2f51ab4..371b1aa 100644 --- a/frontend/src/components/GatewayAutocompleteInput.jsx +++ b/frontend/src/components/GatewayAutocompleteInput.jsx @@ -11,6 +11,7 @@ function GatewayAutocompleteInput({ gateways = [], interfaces = [], templateGateways = [], // Gateways из шаблона, которые еще не созданы + serverId = null, // ID сервера для фильтрации интерфейсов и gateways excludeGatewayId = null, // ID gateway, который нужно исключить (текущий редактируемый) placeholder = '', className = 'form-control', @@ -27,8 +28,15 @@ function GatewayAutocompleteInput({ const items = []; // Добавляем прямые gateway из шаблона (которые еще не созданы) + // Фильтруем по serverId, если указан templateGateways - .filter(g => g.id !== excludeGatewayId && g.type === 'direct' && g.ip) + .filter(g => { + if (g.id === excludeGatewayId) return false; + if (g.type !== 'direct' || !g.ip) return false; + // Если указан serverId, фильтруем по нему + if (serverId && g.serverId !== serverId) return false; + return true; + }) .forEach(g => { items.push({ type: 'gateway', @@ -43,8 +51,15 @@ function GatewayAutocompleteInput({ }); // Добавляем прямые gateway (уже созданные) + // Фильтруем по serverId, если указан gateways - .filter(g => g.id !== excludeGatewayId && g.type === 'direct' && g.ip) + .filter(g => { + if (g.id === excludeGatewayId) return false; + if (g.type !== 'direct' || !g.ip) return false; + // Если указан serverId, фильтруем по нему + if (serverId && g.serverId !== serverId) return false; + return true; + }) .forEach(g => { items.push({ type: 'gateway', @@ -59,8 +74,17 @@ function GatewayAutocompleteInput({ }); // Добавляем интерфейсы + // Фильтруем по serverId, если указан (интерфейс должен принадлежать серверу) interfaces - .filter(i => i.remoteIp) + .filter(i => { + if (!i.remoteIp) return false; + // Если указан serverId, фильтруем интерфейсы, которые принадлежат этому серверу + if (serverId) { + // Интерфейс принадлежит серверу, если serverId === i.serverId или serverId === i.serverId2 + return i.serverId === serverId || i.serverId2 === serverId; + } + return true; + }) .forEach(i => { items.push({ type: 'interface', @@ -75,7 +99,7 @@ function GatewayAutocompleteInput({ }); return items; - }, [gateways, interfaces, templateGateways, excludeGatewayId]); + }, [gateways, interfaces, templateGateways, excludeGatewayId, serverId]); const suggestions = useMemo(() => { const q = String(value || '').toLowerCase();