diff --git a/src/data/mesh2.ts b/src/data/mesh2.ts index 5138df0..097338c 100644 --- a/src/data/mesh2.ts +++ b/src/data/mesh2.ts @@ -13,7 +13,7 @@ export const meshNodes: MonitoredEntity[] = [ type: 'network', online: true, telemetry: { latency: 1.2, uplink: 940, clients: 38, cpu: 17 }, - meta: { ip: '10.200.0.1', model: 'x86 / AmneziaWG', role: 'Центральный хаб mesh2', uplink: 'GPON 1 Гбит' }, + meta: { ip: '10.200.0.1', model: 'x86 / AmneziaWG', role: 'Центральный хаб mesh2', uplink: 'GPON 1 Гбит', photo: 'https://cloud-static.wirenboard.com/preview/wb7.jpeg' }, lat: 44.072, lon: 43.05, updatedAt: now, @@ -25,7 +25,7 @@ export const meshNodes: MonitoredEntity[] = [ type: 'network', online: true, telemetry: { latency: 3.4, uplink: 310, clients: 12, cpu: 22 }, - meta: { ip: '10.200.1.2', model: 'Keenetic Hopper SE', role: 'Спица · склад', uplink: 'AWG → хаб' }, + meta: { ip: '10.200.1.2', model: 'Keenetic Hopper SE', role: 'Спица · склад', uplink: 'AWG → хаб', photo: 'https://cloud-static.wirenboard.com/preview/wb8.jpeg' }, lat: 44.064, lon: 43.058, updatedAt: now, @@ -37,7 +37,7 @@ export const meshNodes: MonitoredEntity[] = [ type: 'network', online: true, telemetry: { latency: 5.1, uplink: 95, clients: 7, cpu: 19 }, - meta: { ip: '10.200.2.2', model: 'Keenetic Hero 4G', role: 'Спица · ферма (LTE-бэкап)', uplink: 'AWG → хаб' }, + meta: { ip: '10.200.2.2', model: 'Keenetic Hero 4G', role: 'Спица · ферма (LTE-бэкап)', uplink: 'AWG → хаб', photo: 'https://cloud-static.wirenboard.com/preview/wb6.jpg' }, lat: 44.081, lon: 43.041, updatedAt: now, @@ -49,7 +49,7 @@ export const meshNodes: MonitoredEntity[] = [ type: 'network', online: true, telemetry: { latency: 8.7, uplink: 60, clients: 4, cpu: 31 }, - meta: { ip: '10.200.3.2', model: 'Mikrotik hAP ac3', role: 'Спица · полевой узел', uplink: 'Радиомост 5 ГГц' }, + meta: { ip: '10.200.3.2', model: 'Mikrotik hAP ac3', role: 'Спица · полевой узел', uplink: 'Радиомост 5 ГГц', photo: 'https://cloud-static.wirenboard.com/preview/wb7.jpeg' }, lat: 44.09, lon: 43.07, updatedAt: now, @@ -61,7 +61,7 @@ export const meshNodes: MonitoredEntity[] = [ type: 'network', online: true, telemetry: { latency: 6.0, uplink: 8, clients: 1, cpu: 0 }, - meta: { ip: '10.200.1.51', model: 'Hikvision DS-2CD', role: 'IP-камера (RTSP)', uplink: 'PoE → Keenetic Склад' }, + meta: { ip: '10.200.1.51', model: 'Hikvision DS-2CD', role: 'IP-камера (RTSP)', uplink: 'PoE → Keenetic Склад', photo: 'https://cloud-static.wirenboard.com/preview/wb8.jpeg' }, lat: 44.066, lon: 43.06, updatedAt: now, @@ -73,7 +73,7 @@ export const meshNodes: MonitoredEntity[] = [ type: 'network', online: false, telemetry: { latency: 0, uplink: 0, clients: 0, cpu: 0 }, - meta: { ip: '10.200.2.40', model: 'Wiren Board / Modbus-TCP', role: 'Солнечный контроллер', uplink: 'нет связи 14 мин' }, + meta: { ip: '10.200.2.40', model: 'Wiren Board / Modbus-TCP', role: 'Солнечный контроллер', uplink: 'нет связи 14 мин', photo: 'https://cloud-static.wirenboard.com/preview/wb6.jpg' }, lat: 44.083, lon: 43.045, updatedAt: ago(14), diff --git a/src/modules/network/NetworkModule.tsx b/src/modules/network/NetworkModule.tsx index 58f7a50..a60b46a 100644 --- a/src/modules/network/NetworkModule.tsx +++ b/src/modules/network/NetworkModule.tsx @@ -24,17 +24,21 @@ function linkStyle(n: MonitoredEntity): { style: 'solid' | 'dash' | 'flow'; colo function photoOf(n: MonitoredEntity) { const camera = /камера/i.test(n.name); const kind = camera ? 'Снимок камеры' : 'Фото прибора'; + // Снимок-заглушка, похожая на реальное фото прибора (self-contained SVG, рисуется всегда). + const leds = [0, 1, 2, 3].map((i) => ``).join(''); const svg = ` - - - - - - ${kind} - ${n.name} - 06:00 · сегодня + + + ${camera ? "" : "" + leds} + ${kind} + + LIVE + ${n.name} + снимок 06:00 · сегодня `; - return { url: `data:image/svg+xml;utf8,${encodeURIComponent(svg)}`, kind }; + const fallback = `data:image/svg+xml;utf8,${encodeURIComponent(svg)}`; + // Реальное изображение (same-origin/MinIO) — из meta.photo; иначе снимок-заглушка. + return { url: n.meta?.photo || fallback, fallback, kind, real: !!n.meta?.photo }; } export function NetworkModule() { @@ -145,6 +149,7 @@ export function NetworkModule() { src={photoOf(n).url} alt={photoOf(n).kind} loading="lazy" + onError={(e) => { const el = e.currentTarget; const fb = photoOf(n).fallback; if (el.src !== fb) el.src = fb; }} className="h-32 w-full rounded-lg border border-border object-cover" />