diff --git a/frontend/src/FilterManager.jsx b/frontend/src/FilterManager.jsx index 80c56cd..07f337f 100644 --- a/frontend/src/FilterManager.jsx +++ b/frontend/src/FilterManager.jsx @@ -482,12 +482,12 @@ function GatewayAutocomplete({ label, value, onChange, gateways = [], required =
- {gw.name} - {gw.ip && ({gw.ip})} + {gw.name} + {gw.comment && ({gw.comment})} {gw.serverDns && — {gw.serverDns}}
- {[gw.country, gw.comment].filter(Boolean).join(' · ') || 'Шлюз'} + {[gw.country].filter(Boolean).join(' · ') || 'Шлюз'}
{gw.primary && Основной} @@ -508,9 +508,12 @@ function GatewayAutocomplete({ label, value, onChange, gateways = [], required = {selectedGateway.country ? countryToFlag(selectedGateway.country) : }
-
{selectedGateway.name}
+
+ {selectedGateway.name} + {selectedGateway.comment && ({selectedGateway.comment})} +
- {[selectedGateway.ip, selectedGateway.serverDns, selectedGateway.comment].filter(Boolean).join(' · ')} + {[selectedGateway.serverDns].filter(Boolean).join(' · ')}
{selectedGateway.primary && Основной} diff --git a/frontend/src/NetworkConfigManager.jsx b/frontend/src/NetworkConfigManager.jsx index 24cba21..eab144e 100644 --- a/frontend/src/NetworkConfigManager.jsx +++ b/frontend/src/NetworkConfigManager.jsx @@ -329,13 +329,39 @@ function NetworkConfigManager() { }; const handleSaveGateway = (gatewayData) => { + // Валидация: IP адрес обязателен + if (!gatewayData.ip || !gatewayData.ip.trim()) { + notify.error('IP адрес обязателен'); + return; + } + if (gatewayModalMode === 'add') { + // Проверка на дубликат IP + const existingGateway = config.gateways.find(g => g.ip === gatewayData.ip.trim()); + if (existingGateway) { + notify.error(`Gateway с IP ${gatewayData.ip} уже существует`); + return; + } setConfig(prev => ({ ...prev, gateways: [...prev.gateways, gatewayData], })); notify.success('Gateway добавлен'); } else { + // При редактировании ищем по ID, но проверяем, не занят ли новый IP другим gateway + const currentGateway = config.gateways.find(g => g.id === gatewayData.id); + if (!currentGateway) { + notify.error('Gateway не найден'); + return; + } + + // Если IP изменился, проверяем, не занят ли он другим gateway + if (gatewayData.ip.trim() !== currentGateway.ip && + config.gateways.some(g => g.id !== gatewayData.id && g.ip === gatewayData.ip.trim())) { + notify.error(`Gateway с IP ${gatewayData.ip} уже существует`); + return; + } + setConfig(prev => ({ ...prev, gateways: prev.gateways.map(g => g.id === gatewayData.id ? gatewayData : g), @@ -701,7 +727,7 @@ function NetworkConfigManager() {
- {provider || '—'} + {gateway.description || provider || '—'}
@@ -756,11 +782,6 @@ function NetworkConfigManager() {
)} - {gateway.description && ( -
- {gateway.description} -
- )} @@ -1096,9 +1117,8 @@ function NetworkConfigManager() { - - + @@ -1124,7 +1144,24 @@ function NetworkConfigManager() { - {gateway.ip || '—'} +
+
+ {gateway.ip || '—'} + {gateway.ip && ( + + )} +
+ {gateway.description && ( +
{gateway.description}
+ )} +
-
ИмяТип IP адресТип Провайдер Сервер Страна @@ -1140,20 +1177,6 @@ function NetworkConfigManager() { )} - - {gateway.ip || '—'} - {gateway.ip && ( - - )} - - {provider ? ( @@ -1442,22 +1465,22 @@ function NetworkConfigManager() { onChange={(val) => setEditingGateway({ ...editingGateway, ip: val })} placeholder="94.142.140.1" required - disabled={gatewayModalMode === 'edit'} /> - {gatewayModalMode === 'edit' && ( -
- IP адрес нельзя изменить после создания -
- )} +
+ IP адрес является главным идентификатором gateway +
setEditingGateway({ ...editingGateway, description: val })} - placeholder="Основной выход через Cloudflare" + placeholder="SWE-IHOR или Основной выход через Cloudflare" /> +
+ Название gateway для удобства (отображается в фильтрах) +
g.id !== editingGateway.id && g.type === 'direct' && g.ip) .map(g => ( ))}