diff --git a/frontend/src/components/DeviceMockup.tsx b/frontend/src/components/DeviceMockup.tsx index 7b85b3b..9d17dc5 100644 --- a/frontend/src/components/DeviceMockup.tsx +++ b/frontend/src/components/DeviceMockup.tsx @@ -36,6 +36,10 @@ const isL009 = (b?: string | null): boolean => const isRb4011 = (b?: string | null): boolean => !!b && /RB?\s*4011/i.test(b); +// CRS317-1G-16S+ — белый 1U-свич: 16×SFP+ + 1 GigE (ETH/BOOT). +const isCrs317 = (b?: string | null): boolean => + !!b && /CRS\s*317(?:-?\s*1G)?(?:-?\s*16S)?/i.test(b); + // Найти интерфейс по базовому имени, допуская суффиксы вида `ether1-Uztelecom`, // `ether2_LAN`, `ether3 description` и т.п. Сначала пробуем точное совпадение, потом по префиксу. function findPort(interfaces: InterfaceInfo[], baseName: string): InterfaceInfo | undefined { @@ -69,6 +73,9 @@ export default function DeviceMockup({ boardName, interfaces }: DeviceMockupProp if (isRb4011(boardName)) { return ; } + if (isCrs317(boardName)) { + return ; + } if (isHexS(boardName)) { return ; } @@ -716,6 +723,193 @@ function Rb4011Mockup({ interfaces }: { interfaces: InterfaceInfo[] }) { ); } +// --------- CRS317-1G-16S+ --------- +// Белый 1U-свич: 16 портов SFP+ в 4 группах по 4, над каждым портом пара +// светодиодов ACT и 10G. Справа: CONSOLE (RJ45), ETH/BOOT (Gigabit RJ45 +// для управления = ether1), кнопка RESET и блок статусных LED (USR, +// FAULT, PWR2, PWR1). Имена SFP-портов в RouterOS — sfp-sfpplus1…16. + +function Crs317Mockup({ interfaces }: { interfaces: InterfaceInfo[] }) { + const W = 700, H = 66; + const portW = 28, portH = 26, gap = 3; + const groupGap = 8; + const portsY = 28; + const portsStartX = 78; + + // Управляющий Gigabit-порт ETH/BOOT = ether1. Допускаем альт-имена на случай переименования. + const ethBoot = + findPort(interfaces, 'ether1') || + findPort(interfaces, 'eth1') || + findPort(interfaces, 'boot'); + + // Группа из 4 портов: индексы 0..3, 4..7, 8..11, 12..15. Между группами — groupGap. + const xOf = (i: number) => portsStartX + i * (portW + gap) + Math.floor(i / 4) * groupGap; + + return ( +
+
+ Лицевая панель CRS317-1G-16S+ · подсветка портов в реальном времени +
+
+ + {/* Белый корпус */} + + + {/* Левая декоративная зона: 4 ряда вентиляционных решёток (по числу групп портов) */} + {Array.from({ length: 4 }).map((_, gi) => { + const gx = portsStartX + gi * (4 * (portW + gap) + groupGap) - 4; + return ( + + {Array.from({ length: 16 }).map((__, vi) => ( + + ))} + + ); + })} + + {/* Лейблы ACT / 10G над каждым портом + сами светодиоды */} + {Array.from({ length: 16 }).map((_, i) => { + const x = xOf(i); + const it = findPort(interfaces, `sfp-sfpplus${i + 1}`) + || findPort(interfaces, `sfpplus${i + 1}`); + const actOn = !!it?.running; + return ( + + ACT + 10G + {/* «коробочки» светодиодов */} + + + + ); + })} + + {/* SFP+ слоты (16 шт.) */} + {Array.from({ length: 16 }).map((_, i) => { + const x = xOf(i); + const it = findPort(interfaces, `sfp-sfpplus${i + 1}`) + || findPort(interfaces, `sfpplus${i + 1}`); + const col = portColor(it); + return ( + + {/* Внешний металлический корпус слота */} + + {/* Внутренняя «начинка» — цвет по статусу */} + + {/* Боковые тёмные полоски — стандартный «вид» SFP-клетки */} + + + {/* Подпись «SFP+ i» под портом */} + + SFP+{i + 1} + + + {(it?.name) || `sfp-sfpplus${i + 1}`} · 10 GbE SFP+ + {'\n'}статус: {col.label} + {it?.comment ? `\ncomment: ${it.comment}` : ''} + {it?.mac_address ? `\nmac: ${it.mac_address}` : ''} + + + ); + })} + + {/* Правая колонка: CONSOLE, ETH/BOOT, RESET, статусные LED, лого */} + {(() => { + const rightX = portsStartX + 16 * (portW + gap) + 3 * groupGap + 6; + const consoleY = 18; + const ethY = 38; + return ( + + {/* CONSOLE — RJ45 для serial */} + CONSOLE + + + + + {/* ETH/BOOT — управляющий Gigabit (ether1) */} + ETH/BOOT + {(() => { + const col = portColor(ethBoot); + return ( + + + + + + + + {(ethBoot?.name) || 'ether1'} · ETH/BOOT (Gigabit, management) + {'\n'}статус: {col.label} + {ethBoot?.comment ? `\ncomment: ${ethBoot.comment}` : ''} + {ethBoot?.mac_address ? `\nmac: ${ethBoot.mac_address}` : ''} + + + ); + })()} + + {/* RESET — утопленная кнопка */} + + + RESET + + {/* Блок статусных LED справа */} + {(() => { + const lx = rightX + 50; + const labels = [ + { name: 'USR', color: '#f5d600' }, + { name: 'FAULT', color: '#d04848' }, + { name: 'PWR 2', color: '#22c55e' }, + { name: 'PWR 1', color: '#22c55e' }, + ]; + return ( + + {labels.map((l, idx) => ( + + + {l.name} + + ))} + + ); + })()} + + {/* Лого + название модели — справа сверху, как на корпусе */} + + Cloud Router Switch + + + CRS 317-1G-16S+ + + + MikroTik + + + ); + })()} + +
+ +
+ ); +} + // --------- CHR (Cloud Hosted Router) --------- // Виртуальная машина MikroTik — нет физической панели. // Простой белый прямоугольник: слева лейбл «CHR», справа порты ether* в ряд.