Stadionzeitung, Veranstaltungen, News-Artikel, Lightbox und Anzeigen-Verteilung
Stadionzeitung: Live-Seiten (Tabellen, Ergebnisse, Vorschau, Termine, News, Kontakt, Historie, Sportheim, Partner, Momente, Impressum), automatisches Cover, Swipe-Viewer mit Vollbildmodus und die Druckfassung als Falt-Heft. Anzeigen kommen jetzt aus dem Bestand und werden gleichmäßig verteilt, nie mehr als zwei hintereinander (vorher vier Blöcke à fünf). Die Doppelseiten-Regel rechnet das Skript selbst, statt sie von Hand zu prüfen. Veranstaltungen: Bereich /veranstaltungen mit Detailseite pro Fest, Lebenszyklus über das Datum (Ankündigung vor dem Fest, Rückblick danach), Galerie mit Lightbox. veranstaltungen.json ist dritte Termin-Quelle, damit ein Fest nie doppelt gepflegt wird. News-Artikel als dritte dynamische Prefix-Route, gemeinsamer detail-head. Behobene Fehler: - Wappen-Kontexte setzten Zeilen-Layout auf .crest statt auf die Zeile; das Wappen wurde zum Grid, Vereinsname und Tore rutschten darunter zusammen (Ergebnis-Rückblick, Vorschau, Cover). - --header-h (60px) unterschätzt die Kopfleiste um 32px (Logo 72px + 20px Versatz): neues abgeleitetes --header-space, sonst klebten Zurück-Links unter dem Logo. - base_url in der Produktions-Config ohne www, während .htaccess auf www umleitet; preflight prüft das jetzt. - .lightbox brauchte display:none mit (0,2,0), sonst lag das Overlay offen. Neue Werkzeuge: bin/anzeige-add.php (Anzeigen-Bestand), bin/veranstaltung-bilder.php (Plakate und Galerien, Alt-Texte folgen der Quelldatei), bin/qr.php (Druck-QR mit Warnung, wenn base_url nicht auf die echte Domain zeigt). Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NzeVVgMCrzCDJAKeLEdKr7
This commit is contained in:
98
app/components/stadionzeitung-druck.php
Normal file
98
app/components/stadionzeitung-druck.php
Normal file
@@ -0,0 +1,98 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* Druckfassung einer Stadionzeitung-Ausgabe (Route ?druck=1, siehe
|
||||
* app/pages/stadionzeitung-ausgabe.php) — die Seiten in BROSCHÜREN-Reihenfolge
|
||||
* statt Lesereihenfolge: das Heft wird als A4 quer beidseitig gedruckt, die
|
||||
* Blätter werden gestapelt und mittig gefaltet. Damit dabei vorn das Cover
|
||||
* und innen die richtige Abfolge liegt, trägt Blatt 1 vorne [letzte Seite |
|
||||
* Seite 1], hinten [Seite 2 | vorletzte Seite] usw. — die klassische
|
||||
* Sattelheftungs-Montage. Deshalb liegt die Montage HIER im PHP (die
|
||||
* DOM-Reihenfolge selbst ist die Druckreihenfolge), nicht in Druck-CSS:
|
||||
* CSS kann Seiten nicht über Blattgrenzen hinweg umsortieren.
|
||||
*
|
||||
* Die Seitenzahl wird dafür auf ein Vielfaches von 4 gebracht: fehlende
|
||||
* Seiten füllt eine weiße Leerseite VOR der Rückseite auf (die Rückseite
|
||||
* bleibt immer außen). Die Regel fürs Heft bleibt trotzdem: Lücken beim
|
||||
* Erzeugen gemeinsam sauber lösen, Leerseiten sind der Notnagel.
|
||||
*
|
||||
* Auf dem Bildschirm zeigt die Route eine Blatt-Vorschau (jedes Blatt als
|
||||
* A4-quer-Fläche mit Beschriftung „Blatt 1 · Vorderseite") plus
|
||||
* Druck-Anleitung; assets/js/stadionzeitung-druck.js liefert den
|
||||
* „Jetzt drucken"-Button (progressive enhancement — ohne JS druckt der
|
||||
* Browser-Dialog dieselbe Ansicht).
|
||||
*
|
||||
* Props: $issue Eintrag aus data/stadionzeitung.json
|
||||
*/
|
||||
$issue = $issue ?? [];
|
||||
$pages = $issue['images'] ?? [];
|
||||
if ($pages === []) {
|
||||
return;
|
||||
}
|
||||
|
||||
$hasLive = false;
|
||||
foreach ($pages as $entry) {
|
||||
if (($entry['type'] ?? 'image') === 'live') {
|
||||
$hasLive = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
$liveData = $hasLive ? stadionzeitung_live_data($issue) : [];
|
||||
|
||||
// Auf Vielfaches von 4 auffüllen — Leerseiten direkt vor der letzten Seite,
|
||||
// damit die gelieferte Rückseite die äußere Rückseite des Hefts bleibt.
|
||||
$fill = (4 - count($pages) % 4) % 4;
|
||||
if ($fill > 0) {
|
||||
array_splice($pages, count($pages) - 1, 0, array_fill(0, $fill, ['type' => 'leer']));
|
||||
}
|
||||
$n = count($pages);
|
||||
|
||||
// Sattelheftung: Blatt k (0-basiert) trägt vorne [n-1-2k | 2k] und hinten
|
||||
// [2k+1 | n-2-2k] (0-basierte Seitenindizes). Beim beidseitigen Druck an der
|
||||
// KURZEN Kante spiegeln, sonst steht jede Rückseite kopf.
|
||||
$sides = [];
|
||||
for ($k = 0; $k < intdiv($n, 4); $k++) {
|
||||
$sides[] = ['label' => 'Blatt ' . ($k + 1) . ' · Vorderseite', 'pages' => [$n - 1 - 2 * $k, 2 * $k]];
|
||||
$sides[] = ['label' => 'Blatt ' . ($k + 1) . ' · Rückseite', 'pages' => [2 * $k + 1, $n - 2 - 2 * $k]];
|
||||
}
|
||||
?>
|
||||
<section class="stadionzeitung-druck">
|
||||
<ol class="stadionzeitung-druck__blaetter">
|
||||
<?php foreach ($sides as $side): ?>
|
||||
<li class="stadionzeitung-druck__blatt">
|
||||
<p class="stadionzeitung-druck__blatt-label" aria-hidden="true"><?= e($side['label']) ?></p>
|
||||
<div class="stadionzeitung-druck__flaeche">
|
||||
<?php foreach ($side['pages'] as $pageIndex): ?>
|
||||
<div class="stadionzeitung-druck__slot">
|
||||
<?php component('stadionzeitung-seite', [
|
||||
'entry' => $pages[$pageIndex],
|
||||
'issue' => $issue,
|
||||
'data' => $liveData,
|
||||
// In der Druckfassung wird JEDE Seite sofort geladen:
|
||||
// lazy geladene Bilder, die nie im Sichtfeld waren,
|
||||
// druckt Chrome sonst als leere Flächen.
|
||||
'eager' => true,
|
||||
]); ?>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
</li>
|
||||
<?php endforeach; ?>
|
||||
</ol>
|
||||
<?php /* Anleitung + Druck-Button bewusst UNTER den Blättern (Wunsch Felix,
|
||||
29.07.2026): erst die Vorschau komplett durchsehen, ganz unten
|
||||
drucken. */ ?>
|
||||
<div class="stadionzeitung-druck__hilfe">
|
||||
<h2 class="stadionzeitung-druck__hilfe-title">Drucken</h2>
|
||||
<p>
|
||||
<?= intdiv($n, 4) ?> Blätter A4 quer<?= $fill > 0 ? ', mit ' . $fill . ' weißen Füllseiten auf ' . $n . ' Seiten aufgefüllt' : ' (' . $n . ' Seiten)' ?>.
|
||||
Beidseitig drucken und dabei <strong>an der kurzen Kante spiegeln</strong>,
|
||||
danach alle Blätter aufeinanderlegen und mittig falten — fertig ist das Heft.
|
||||
</p>
|
||||
<button class="btn stadionzeitung-druck__print-btn" type="button" data-druck-print hidden>
|
||||
<?= icon('printer') ?> Jetzt drucken
|
||||
</button>
|
||||
</div>
|
||||
</section>
|
||||
Reference in New Issue
Block a user