diff --git a/frontend/src/NetworkConfigManager.jsx b/frontend/src/NetworkConfigManager.jsx
index 0775a6d..9a90bac 100644
--- a/frontend/src/NetworkConfigManager.jsx
+++ b/frontend/src/NetworkConfigManager.jsx
@@ -2202,8 +2202,125 @@ function NetworkConfigManager() {
setGeneratedMikrotikCode(filteredBlocks);
setMikrotikCodeModalOpen(true);
+ } else if (type === 'gateway') {
+ // Получаем все gateways для этого сервера
+ const serverGateways = (config.gateways || []).filter(gw => gw.serverId === serverId);
+
+ if (serverGateways.length === 0) {
+ notify.error('Нет gateways для этого сервера');
+ setLoading(false);
+ return;
+ }
+
+ // Генерируем код для рекурсивных маршрутов этого сервера
+ const recursiveGateways = serverGateways.filter(gw => gw.type === 'recursive');
+
+ if (recursiveGateways.length === 0) {
+ notify.error('Нет рекурсивных gateways для генерации кода');
+ setLoading(false);
+ return;
+ }
+
+ const blocks = [];
+ const server = getServerInfo(serverId);
+ const serverName = server?.dns || server?.ip || serverId;
+
+ // Генерируем код для каждого рекурсивного gateway
+ recursiveGateways.forEach(gw => {
+ if (!gw.ip) return;
+
+ // Поддержка старого формата (parentGatewayId) и нового (parentGateways)
+ const parentGatewaysList = gw.parentGateways && Array.isArray(gw.parentGateways) && gw.parentGateways.length > 0
+ ? gw.parentGateways
+ : (gw.parentGatewayId ? [{ id: gw.parentGatewayId, distance: undefined }] : []);
+
+ if (parentGatewaysList.length === 0) return;
+
+ let code = `# Рекурсивный маршрут для gateway: ${gw.ip}\n`;
+ if (server?.provider) {
+ code += `# Провайдер: ${server.provider}\n`;
+ }
+ if (server?.country) {
+ code += `# Страна: ${server.country}\n`;
+ }
+ code += '\n';
+
+ let validRoutesCount = 0;
+
+ parentGatewaysList.forEach((parentRef) => {
+ const parent = getParentGateway(parentRef.id);
+
+ if (!parent) {
+ code += `# Родительский gateway/интерфейс "${parentRef.id}" не найден, пропущен\n`;
+ return;
+ }
+
+ // Определяем IP родителя в зависимости от типа
+ const parentIp = parent.parentType === 'interface' ? parent.remoteIp : parent.ip;
+
+ if (!parentIp) {
+ const parentType = parent.parentType === 'interface' ? 'интерфейс' : 'gateway';
+ code += `# Родительский ${parentType} не имеет IP, пропущен\n`;
+ return;
+ }
+
+ validRoutesCount++;
+
+ // Создаём маршрут для рекурсивного gateway
+ const parentLabel = parent.parentType === 'interface'
+ ? `интерфейс ${parent.name || parent.interfaceType || 'interface'} (${parent.remoteIp})`
+ : `gateway ${parent.ip}`;
+
+ const distanceSuffix = parentRef.distance !== undefined && parentRef.distance !== null ? ` (distance: ${parentRef.distance})` : '';
+ code += `# Рекурсивный gateway: ${gw.ip}${distanceSuffix}\n`;
+ code += `# Родительский: ${parentLabel}\n`;
+
+ // Формируем gateway: для интерфейсов добавляем имя через %, для gateway - только IP
+ const gatewayValue = parent.parentType === 'interface'
+ ? `${parentIp}%${parent.name || parent.interfaceType || 'interface'}`
+ : parentIp;
+
+ // Создаём маршрут к IP рекурсивного gateway через родительский
+ const comment = gw.description
+ ? `Recursive: ${gw.description} -> ${parentIp}${distanceSuffix}`
+ : `Recursive: ${gw.ip} -> ${parentIp}${distanceSuffix}`;
+
+ const distanceParam = parentRef.distance !== undefined && parentRef.distance !== null ? ` distance=${parentRef.distance}` : '';
+ code += `/ip route add dst-address=${gw.ip}/32 gateway=${gatewayValue}${distanceParam} comment="${comment}"\n`;
+
+ // Если у рекурсивного gateway есть описание с указанием на default route
+ if (gw.description && (gw.description.toLowerCase().includes('default') || gw.description.toLowerCase().includes('0.0.0.0'))) {
+ code += `# Дополнительный default route через рекурсивный gateway${distanceSuffix}\n`;
+ const defaultComment = gw.description ? `Recursive: ${gw.description} (default)${distanceSuffix}` : `Recursive: ${gw.ip} (default)${distanceSuffix}`;
+ code += `/ip route add dst-address=0.0.0.0/0 gateway=${gatewayValue}${distanceParam} comment="${defaultComment}"\n`;
+ }
+ code += '\n';
+ });
+
+ code += '# Проверка созданных маршрутов:\n';
+ code += '# /ip route print where comment~"Recursive"\n';
+ code += `# Всего создано маршрутов: ${validRoutesCount}\n`;
+
+ if (validRoutesCount > 0) {
+ blocks.push({
+ type: 'recursive-routes',
+ serverName,
+ server,
+ code
+ });
+ }
+ });
+
+ if (blocks.length === 0) {
+ notify.error('Не удалось сгенерировать код для gateways этого сервера');
+ setLoading(false);
+ return;
+ }
+
+ setGeneratedMikrotikCode(blocks);
+ setMikrotikCodeModalOpen(true);
} else {
- notify.error('Генерация кода для gateways по серверу пока не реализована');
+ notify.error('Неизвестный тип элемента');
}
} catch (error) {
console.error('Error generating MikroTik code for server:', error);
@@ -2638,14 +2755,14 @@ function NetworkConfigManager() {
{items.length} {type === 'gateway' ? (items.length === 1 ? 'gateway' : 'gateways') : (items.length === 1 ? 'интерфейс' : 'интерфейсов')}
- {type === 'interface' && !isUnassigned && items.length > 0 && (
+ {!isUnassigned && items.length > 0 && (