diff --git a/frontend/src/NetworkConfigManager.jsx b/frontend/src/NetworkConfigManager.jsx index 40afd81..c607e24 100644 --- a/frontend/src/NetworkConfigManager.jsx +++ b/frontend/src/NetworkConfigManager.jsx @@ -5,6 +5,7 @@ import FormModal from './components/FormModal.jsx'; import FormField from './components/FormField.jsx'; import ConfirmModal from './components/ConfirmModal.jsx'; import ServerAutocompleteInput from './components/ServerAutocompleteInput.jsx'; +import PreviewConfigModal from './components/filter/PreviewConfigModal.jsx'; import { countryToFlag } from './utils/serverUtils.js'; import { IconNetwork, @@ -22,7 +23,8 @@ import { IconX, IconCircleFilled, IconLayoutGrid, - IconList + IconList, + IconCode } from '@tabler/icons-react'; /** @@ -125,6 +127,10 @@ function NetworkConfigManager() { const [deleteModalOpen, setDeleteModalOpen] = useState(false); const [itemToDelete, setItemToDelete] = useState(null); const [deleteType, setDeleteType] = useState(''); + + // === MikroTik Code Generation === + const [mikrotikCodeModalOpen, setMikrotikCodeModalOpen] = useState(false); + const [generatedMikrotikCode, setGeneratedMikrotikCode] = useState(''); // === Загрузка данных === useEffect(() => { @@ -462,6 +468,93 @@ function NetworkConfigManager() { } }; + // === Генерация кода MikroTik для рекурсивных маршрутов === + const generateMikrotikRecursiveRoutes = () => { + const recursiveGateways = (config.gateways || []).filter(gw => gw.type === 'recursive'); + + if (recursiveGateways.length === 0) { + return '// Нет рекурсивных gateway для генерации маршрутов\n// Добавьте рекурсивные gateway в настройках'; + } + + let code = '// Конфигурация MikroTik RouterOS для рекурсивных маршрутов\n'; + code += '// Генерируется автоматически\n'; + code += `// Дата: ${new Date().toISOString()}\n\n`; + code += '# Удаление существующих рекурсивных маршрутов (опционально)\n'; + code += '/ip route remove [find comment~"Recursive"]\n\n'; + + // Группируем по серверам для удобства + const gatewaysByServer = {}; + recursiveGateways.forEach(gw => { + const serverId = gw.serverId || '__unassigned__'; + if (!gatewaysByServer[serverId]) { + gatewaysByServer[serverId] = []; + } + gatewaysByServer[serverId].push(gw); + }); + + let validRoutesCount = 0; + + Object.entries(gatewaysByServer).forEach(([serverId, gateways]) => { + const server = getServerInfo(serverId); + const serverName = server?.dns || server?.ip || serverId; + + code += `\n# === Рекурсивные маршруты для сервера: ${serverName} ===\n`; + + gateways.forEach(gw => { + const parentGateway = getParentGateway(gw.parentGatewayId); + + if (!parentGateway) { + code += `\n# Gateway "${gw.name}" - родительский gateway не найден, пропущен\n`; + return; + } + + if (!gw.ip) { + code += `\n# Gateway "${gw.name}" - IP адрес не указан, пропущен\n`; + return; + } + + if (!parentGateway.ip) { + code += `\n# Gateway "${gw.name}" - родительский gateway "${parentGateway.name}" не имеет IP, пропущен\n`; + return; + } + + validRoutesCount++; + + // Создаём маршрут для рекурсивного gateway + // Маршрут к IP рекурсивного gateway направляется через родительский gateway + code += `\n# Рекурсивный gateway: ${gw.name} (IP: ${gw.ip})\n`; + code += `# Родительский gateway: ${parentGateway.name} (IP: ${parentGateway.ip})\n`; + + // Создаём маршрут к IP рекурсивного gateway через родительский + code += `/ip route add dst-address=${gw.ip}/32 gateway=${parentGateway.ip} comment="Recursive: ${gw.name} -> ${parentGateway.name}"\n`; + + // Если у рекурсивного gateway есть описание с указанием на default route + if (gw.description && (gw.description.toLowerCase().includes('default') || gw.description.toLowerCase().includes('0.0.0.0'))) { + code += `# Дополнительный default route через рекурсивный gateway\n`; + code += `/ip route add dst-address=0.0.0.0/0 gateway=${parentGateway.ip} comment="Recursive default: ${gw.name} -> ${parentGateway.name}"\n`; + } + }); + }); + + code += '\n# === Проверка созданных маршрутов ===\n'; + code += '# /ip route print where comment~"Recursive"\n'; + code += `\n# Всего создано маршрутов: ${validRoutesCount}\n`; + + return code; + }; + + // === Обработчик кнопки "Код для MikroTik" === + const handleGenerateMikrotikCode = () => { + const code = generateMikrotikRecursiveRoutes(); + setGeneratedMikrotikCode(code); + setMikrotikCodeModalOpen(true); + }; + + // === Копирование кода MikroTik === + const handleCopyMikrotikCode = async () => { + await copyToClipboard(generatedMikrotikCode); + }; + // === Получение цвета провайдера === const getProviderColor = (provider) => { if (!provider) return 'secondary'; @@ -754,6 +847,16 @@ function NetworkConfigManager() { > +