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 = ``;
- 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"
/>