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() {
- Имя
- Тип
IP адрес
+ Тип
Провайдер
Сервер
Страна
@@ -1124,7 +1144,24 @@ function NetworkConfigManager() {
- {gateway.ip || '—'}
+
+
+ {gateway.ip || '—'}
+ {gateway.ip && (
+ copyToClipboard(gateway.ip)}
+ style={{ width: 20, height: 20 }}
+ title="Копировать IP"
+ >
+
+
+ )}
+
+ {gateway.description && (
+
{gateway.description}
+ )}
+
@@ -1140,20 +1177,6 @@ function NetworkConfigManager() {
)}
-
-
- {gateway.ip || '—'}
- {gateway.ip && (
- copyToClipboard(gateway.ip)}
- style={{ width: 20, height: 20 }}
- >
-
-
- )}
-
-
{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 => (
- Gateway: {g.ip} {g.description ? `(${g.description})` : ''}
+ Gateway: {g.ip} {g.description ? `- ${g.description}` : ''}
))}