Verbindungsübersicht mit Raumtopologie und PNG-Export erweitert

closes #31
This commit is contained in:
bigserver
2026-04-09 08:36:28 +02:00
parent 55bbd45562
commit f8c55e4fea
3 changed files with 634 additions and 105 deletions

View File

@@ -64,6 +64,8 @@ foreach ($floors as $floor) {
$editorFloor = ($floorId > 0 && isset($floorMap[$floorId])) ? $floorMap[$floorId] : null;
$editorPatchPanels = [];
$editorOutlets = [];
$editorRooms = [];
$editorLinks = [];
if ($editorFloor) {
foreach ($patchPanels as $panel) {
@@ -97,6 +99,101 @@ if ($editorFloor) {
'comment' => (string)($outlet['comment'] ?? '')
];
}
foreach ($sql->get(
"SELECT id, name, number, x, y, width, height, polygon_points
FROM rooms
WHERE floor_id = ?
ORDER BY name",
"i",
[$floorId]
) as $room) {
$editorRooms[] = [
'id' => (int)($room['id'] ?? 0),
'name' => (string)($room['name'] ?? ''),
'number' => (string)($room['number'] ?? ''),
'x' => (int)($room['x'] ?? 0),
'y' => (int)($room['y'] ?? 0),
'width' => (int)($room['width'] ?? 0),
'height' => (int)($room['height'] ?? 0),
'polygon_points' => (string)($room['polygon_points'] ?? ''),
];
}
$outletIdByPort = [];
foreach ($sql->get(
"SELECT nop.id AS port_id, nop.outlet_id
FROM network_outlet_ports nop
JOIN network_outlets o ON o.id = nop.outlet_id
JOIN rooms r ON r.id = o.room_id
WHERE r.floor_id = ?",
"i",
[$floorId]
) as $row) {
$portId = (int)($row['port_id'] ?? 0);
$outletId = (int)($row['outlet_id'] ?? 0);
if ($portId > 0 && $outletId > 0) {
$outletIdByPort[$portId] = $outletId;
}
}
$patchPanelIdByPort = [];
foreach ($sql->get(
"SELECT fpp.id AS port_id, fpp.patchpanel_id
FROM floor_patchpanel_ports fpp
JOIN floor_patchpanels fp ON fp.id = fpp.patchpanel_id
WHERE fp.floor_id = ?",
"i",
[$floorId]
) as $row) {
$portId = (int)($row['port_id'] ?? 0);
$patchPanelId = (int)($row['patchpanel_id'] ?? 0);
if ($portId > 0 && $patchPanelId > 0) {
$patchPanelIdByPort[$portId] = $patchPanelId;
}
}
$resolveNodeKey = static function (string $endpointType, int $endpointId) use ($outletIdByPort, $patchPanelIdByPort): ?string {
if ($endpointId <= 0) {
return null;
}
$type = strtolower(trim($endpointType));
if ($type === 'outlet' || $type === 'network_outlet_ports') {
$outletId = (int)($outletIdByPort[$endpointId] ?? 0);
return $outletId > 0 ? ('outlet:' . $outletId) : null;
}
if ($type === 'patchpanel' || $type === 'floor_patchpanel_ports') {
$patchPanelId = (int)($patchPanelIdByPort[$endpointId] ?? 0);
return $patchPanelId > 0 ? ('patchpanel:' . $patchPanelId) : null;
}
return null;
};
$linksByKey = [];
foreach ($sql->get(
"SELECT id, port_a_type, port_a_id, port_b_type, port_b_id
FROM connections",
"",
[]
) as $row) {
$fromKey = $resolveNodeKey((string)($row['port_a_type'] ?? ''), (int)($row['port_a_id'] ?? 0));
$toKey = $resolveNodeKey((string)($row['port_b_type'] ?? ''), (int)($row['port_b_id'] ?? 0));
if ($fromKey === null || $toKey === null || $fromKey === $toKey) {
continue;
}
$edgeKey = ($fromKey < $toKey) ? ($fromKey . '|' . $toKey) : ($toKey . '|' . $fromKey);
if (!isset($linksByKey[$edgeKey])) {
$linksByKey[$edgeKey] = [
'from_key' => $fromKey,
'to_key' => $toKey,
'count' => 0,
'sample_connection_id' => (int)($row['id'] ?? 0)
];
}
$linksByKey[$edgeKey]['count']++;
}
$editorLinks = array_values($linksByKey);
}
?>
@@ -133,9 +230,12 @@ if ($editorFloor) {
</form>
<section class="infra-plan">
<div class="infra-plan-header">
<div class="infra-plan-header">
<h2>Stockwerkskarte</h2>
<div class="infra-plan-tools">
<button type="button" class="button button-small" data-infra-toggle="rooms">Räume</button>
<button type="button" class="button button-small" data-infra-toggle="connections">Kabel</button>
<button type="button" class="button button-small" data-infra-download="png">PNG</button>
<button type="button" class="button button-small" data-infra-zoom="in">+</button>
<button type="button" class="button button-small" data-infra-zoom="out">-</button>
<button type="button" class="button button-small" data-infra-zoom="reset">Reset</button>
@@ -155,13 +255,15 @@ if ($editorFloor) {
<div id="infra-floor-canvas"
class="infra-floor-canvas"
data-patchpanels="<?php echo htmlspecialchars(json_encode($editorPatchPanels, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), ENT_QUOTES, 'UTF-8'); ?>"
data-outlets="<?php echo htmlspecialchars(json_encode($editorOutlets, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), ENT_QUOTES, 'UTF-8'); ?>">
data-outlets="<?php echo htmlspecialchars(json_encode($editorOutlets, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), ENT_QUOTES, 'UTF-8'); ?>"
data-rooms="<?php echo htmlspecialchars(json_encode($editorRooms, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), ENT_QUOTES, 'UTF-8'); ?>"
data-links="<?php echo htmlspecialchars(json_encode($editorLinks, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), ENT_QUOTES, 'UTF-8'); ?>">
<div class="infra-floor-scene" id="infra-floor-scene">
<img src="<?php echo htmlspecialchars((string)$editorFloor['svg_url']); ?>" class="infra-floor-svg" alt="Stockwerksplan">
<svg id="infra-floor-overlay" class="infra-floor-overlay" viewBox="0 0 1 1" preserveAspectRatio="xMidYMid meet" aria-hidden="true"></svg>
</div>
</div>
<p class="floor-plan-hint">Blau: Patchpanel | Grün: Wandbuchse. Hover zeigt Name, Raum und Ports (Browser-Tooltip).</p>
<p class="floor-plan-hint">Blau: Patchpanel | Grün: Wandbuchse. Knoten sind greifbar und verschiebbar. Räume und Kabel lassen sich ein-/ausblenden.</p>
<?php endif; ?>
</section>