diff --git a/frontend/src/NetworkConfigManager.jsx b/frontend/src/NetworkConfigManager.jsx index 7d3fba6..0775a6d 100644 --- a/frontend/src/NetworkConfigManager.jsx +++ b/frontend/src/NetworkConfigManager.jsx @@ -232,13 +232,30 @@ function NetworkConfigManager() { const [mikrotikCodeModalOpen, setMikrotikCodeModalOpen] = useState(false); const [generatedMikrotikCode, setGeneratedMikrotikCode] = useState([]); + // === Глобальные настройки PTR зоны === + const [globalPtrZoneReplaceFrom, setGlobalPtrZoneReplaceFrom] = useState(''); + const [globalPtrZoneReplaceTo, setGlobalPtrZoneReplaceTo] = useState(''); + // === Загрузка данных === useEffect(() => { fetchConfig(); fetchServers(); fetchIpsecPasswords(); + fetchUiSettings(); }, []); + const fetchUiSettings = async () => { + try { + const response = await api.get('/ui-settings'); + const data = response.data || {}; + setGlobalPtrZoneReplaceFrom(String(data?.ptrZoneReplaceFrom || '')); + setGlobalPtrZoneReplaceTo(String(data?.ptrZoneReplaceTo || '')); + } catch (error) { + // Мягко игнорируем ошибку, используем значения по умолчанию + console.warn('Не удалось загрузить глобальные настройки PTR зоны:', error); + } + }; + const fetchConfig = async () => { setLoading(true); try { @@ -1494,14 +1511,20 @@ function NetworkConfigManager() { }; // Функция для генерации PTR зоны с учетом замены + // Приоритет: настройки интерфейса > глобальные настройки const generatePtrZone = (serverDns, iface) => { if (!serverDns) return '—'; - // Если указана замена PTR зоны, применяем её + // Сначала проверяем настройки интерфейса if (iface?.ptrZoneReplaceFrom && iface?.ptrZoneReplaceTo) { return serverDns.replace(iface.ptrZoneReplaceFrom, iface.ptrZoneReplaceTo); } + // Если настройки интерфейса не заданы, используем глобальные настройки + if (globalPtrZoneReplaceFrom && globalPtrZoneReplaceTo) { + return serverDns.replace(globalPtrZoneReplaceFrom, globalPtrZoneReplaceTo); + } + return serverDns; }; @@ -1560,7 +1583,7 @@ function NetworkConfigManager() { } return a.type.localeCompare(b.type); }); - }, [config.tunnelInterfaces, servers]); + }, [config.tunnelInterfaces, servers, globalPtrZoneReplaceFrom, globalPtrZoneReplaceTo]); // === Фильтрация реестра IP === const filteredIpRegistry = useMemo(() => { @@ -4254,10 +4277,24 @@ function NetworkConfigManager() { ) : null; })()} - {/* Поля для замены PTR зоны */} + {/* Поля для замены PTR зоны (опционально, переопределяют глобальные настройки) */}

-
Настройка PTR зоны
+
Настройка PTR зоны (опционально)
+
+
+ {globalPtrZoneReplaceFrom && globalPtrZoneReplaceTo ? ( + <> + Глобальные настройки: "{globalPtrZoneReplaceFrom}" → "{globalPtrZoneReplaceTo}"
+ Оставьте поля пустыми, чтобы использовать глобальные настройки, или укажите свои значения для переопределения. + + ) : ( + <> + Глобальные настройки PTR зоны не заданы. Укажите значения здесь или в разделе "Настройки интерфейса". + + )} +
+
setEditingInterface({ ...editingInterface, ptrZoneReplaceFrom: val })} - placeholder="rt.shx" + placeholder={globalPtrZoneReplaceFrom || "rt.shx"} />
- Часть DNS домена, которую нужно заменить (например, "rt.shx") + Часть DNS домена, которую нужно заменить (например, "rt.shx"). Оставьте пустым для использования глобальных настроек.
@@ -4277,13 +4314,13 @@ function NetworkConfigManager() { name="ptrZoneReplaceTo" value={editingInterface.ptrZoneReplaceTo || ''} onChange={(val) => setEditingInterface({ ...editingInterface, ptrZoneReplaceTo: val })} - placeholder="shrt" + placeholder={globalPtrZoneReplaceTo || "shrt"} />
- На что заменить (например, "shrt"). Результат: DNS "selectel.msk.rt.shx.su" → PTR "selectel.msk.shrt.su" + На что заменить (например, "shrt"). Оставьте пустым для использования глобальных настроек.
- {editingInterface.serverId && editingInterface.ptrZoneReplaceFrom && editingInterface.ptrZoneReplaceTo && (() => { + {editingInterface.serverId && (editingInterface.ptrZoneReplaceFrom && editingInterface.ptrZoneReplaceTo || globalPtrZoneReplaceFrom && globalPtrZoneReplaceTo) && (() => { const server = getServerInfo(editingInterface.serverId); const originalDns = server?.dns || ''; const ptrZone = generatePtrZone(originalDns, editingInterface); @@ -4298,6 +4335,15 @@ function NetworkConfigManager() {
PTR зона: {ptrZone}
+ {editingInterface.ptrZoneReplaceFrom && editingInterface.ptrZoneReplaceTo ? ( +
+ Используются настройки интерфейса +
+ ) : ( +
+ Используются глобальные настройки +
+ )}
diff --git a/frontend/src/components/SettingsModal.jsx b/frontend/src/components/SettingsModal.jsx index c4fbd0d..fb4240a 100644 --- a/frontend/src/components/SettingsModal.jsx +++ b/frontend/src/components/SettingsModal.jsx @@ -17,6 +17,8 @@ export default function SettingsModal({ open, onClose }) { const [dohServer, setDohServer] = useState(''); const [wsUrl, setWsUrl] = useState(''); const [baseAS, setBaseAS] = useState('65001'); + const [ptrZoneReplaceFrom, setPtrZoneReplaceFrom] = useState(''); + const [ptrZoneReplaceTo, setPtrZoneReplaceTo] = useState(''); useEffect(() => { if (!open) return; @@ -31,6 +33,8 @@ export default function SettingsModal({ open, onClose }) { setDohServer(String(data?.dohServer || '')); setWsUrl(String(data?.wsUpdateUrl || '')); setBaseAS(String(data?.baseAS || '65001')); + setPtrZoneReplaceFrom(String(data?.ptrZoneReplaceFrom || '')); + setPtrZoneReplaceTo(String(data?.ptrZoneReplaceTo || '')); const e = res?.headers?.etag || res?.headers?.ETag || ''; setEtag(e ? String(e) : ''); } catch (e) { @@ -90,7 +94,9 @@ export default function SettingsModal({ open, onClose }) { settings: { dohServer: String(dohServer || '').trim(), wsUpdateUrl: String(wsUrl || '').trim(), - baseAS: String(baseAS || '65001').trim() + baseAS: String(baseAS || '65001').trim(), + ptrZoneReplaceFrom: String(ptrZoneReplaceFrom || '').trim(), + ptrZoneReplaceTo: String(ptrZoneReplaceTo || '').trim() }, etag }; @@ -186,6 +192,36 @@ export default function SettingsModal({ open, onClose }) { helpText="AS по умолчанию для community (например, 65001). Используется при поиске и нормализации community." disabled={loading || saving} /> + +
+
Настройка PTR зоны
+
+
+ +
+
+ +
+
+