fix: PDF-Export verbessert - Seitenraender, kein Abschneiden, klickbare Links
- @page margins 18mm/15mm fuer korrekte Seitenraender - Header kompakt: Titel + Lagebild direkt auf Seite 1 (keine leere Seite) - Citations/Quellenverweise als klickbare unterstrichene Links im PDF - break-inside:avoid statt page-break-inside fuer korrekte Seitenumbrueche - Kartenexport entfernt (nicht sinnvoll als PDF) - Schriftgroessen leicht reduziert fuer bessere Platznutzung
Dieser Commit ist enthalten in:
@@ -2157,10 +2157,15 @@ const App = {
|
||||
const summaryEl = document.getElementById('summary-text');
|
||||
const timestamp = document.getElementById('lagebild-timestamp')?.textContent || '';
|
||||
if (summaryEl && summaryEl.innerHTML.trim()) {
|
||||
// Clone innerHTML and make citation links clickable with full URL visible
|
||||
let summaryHtml = summaryEl.innerHTML;
|
||||
// Ensure citation links are styled for print (underlined, blue)
|
||||
summaryHtml = summaryHtml.replace(/<a\s+href="([^"]*)"[^>]*class="citation"[^>]*>(\[[^\]]+\])<\/a>/g,
|
||||
'<a href="$1" class="citation">$2</a>');
|
||||
sections += '<div class="pdf-section">'
|
||||
+ '<h2>Lagebild</h2>'
|
||||
+ (timestamp ? '<p class="pdf-meta">' + esc(timestamp) + '</p>' : '')
|
||||
+ '<div class="pdf-content">' + summaryEl.innerHTML + '</div>'
|
||||
+ '<div class="pdf-content">' + summaryHtml + '</div>'
|
||||
+ '</div>';
|
||||
}
|
||||
}
|
||||
@@ -2238,30 +2243,6 @@ const App = {
|
||||
}
|
||||
}
|
||||
|
||||
// === Karte ===
|
||||
if (tiles.includes('karte')) {
|
||||
const mapContainer = document.getElementById('map-container');
|
||||
const mapEmpty = document.getElementById('map-empty');
|
||||
if (mapContainer && (!mapEmpty || mapEmpty.style.display === 'none')) {
|
||||
const stats = document.getElementById('map-stats')?.textContent || '';
|
||||
// Try to capture map as canvas image
|
||||
let mapImg = '';
|
||||
try {
|
||||
const leafletPane = mapContainer.querySelector('.leaflet-container');
|
||||
if (leafletPane && typeof leafletPane.toDataURL === 'function') {
|
||||
mapImg = '<img src="' + leafletPane.toDataURL() + '" style="max-width:100%;">';
|
||||
}
|
||||
} catch(e) {}
|
||||
if (!mapImg) {
|
||||
// Leaflet container is not a canvas, so we use a placeholder
|
||||
mapImg = '<div class="pdf-map-placeholder">Die interaktive Karte kann nicht direkt in PDF exportiert werden. Nutzen Sie die Screenshot-Funktion Ihres Browsers (z.B. Strg+Shift+S in Firefox).</div>';
|
||||
}
|
||||
sections += '<div class="pdf-section"><h2>Geografische Verteilung</h2>'
|
||||
+ (stats ? '<p class="pdf-meta">' + esc(stats) + '</p>' : '')
|
||||
+ mapImg + '</div>';
|
||||
}
|
||||
}
|
||||
|
||||
// === Timeline ===
|
||||
if (tiles.includes('timeline')) {
|
||||
const buckets = document.querySelectorAll('#timeline .ht-bucket');
|
||||
@@ -2289,62 +2270,75 @@ const App = {
|
||||
|
||||
if (!sections) { UI.showToast('Keine Inhalte zum Exportieren', 'warning'); return; }
|
||||
|
||||
const printHtml = '<!DOCTYPE html>'
|
||||
+ '\n<html lang="de">'
|
||||
+ '\n<head>'
|
||||
+ '\n<meta charset="utf-8">'
|
||||
+ '\n<title>' + esc(title) + ' \u2014 AegisSight Export</title>'
|
||||
+ '\n<style>'
|
||||
+ '\n@page { margin: 20mm 15mm; size: A4; }'
|
||||
+ '\n* { box-sizing: border-box; margin: 0; padding: 0; }'
|
||||
+ "\nbody { font-family: -apple-system, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif; font-size: 11pt; line-height: 1.5; color: #1a1a1a; background: #fff; }"
|
||||
+ '\n.pdf-header { border-bottom: 2px solid #2c3e50; padding-bottom: 12px; margin-bottom: 24px; }'
|
||||
+ '\n.pdf-header h1 { font-size: 20pt; font-weight: 700; color: #2c3e50; margin-bottom: 4px; }'
|
||||
+ '\n.pdf-header .pdf-subtitle { font-size: 9pt; color: #666; }'
|
||||
+ '\n.pdf-section { margin-bottom: 28px; page-break-inside: avoid; }'
|
||||
+ '\n.pdf-section h2 { font-size: 14pt; font-weight: 600; color: #2c3e50; border-bottom: 1px solid #ddd; padding-bottom: 6px; margin-bottom: 12px; }'
|
||||
+ '\n.pdf-section h4 { font-size: 10pt; font-weight: 600; color: #444; margin: 12px 0 4px; }'
|
||||
+ '\n.pdf-meta { font-size: 9pt; color: #888; margin-bottom: 10px; }'
|
||||
+ '\n.pdf-content { font-size: 11pt; line-height: 1.6; }'
|
||||
+ '\n.pdf-content h3 { font-size: 12pt; font-weight: 600; color: #2c3e50; margin: 14px 0 6px; }'
|
||||
+ '\n.pdf-content strong { font-weight: 600; }'
|
||||
+ '\n.pdf-content ul { margin: 6px 0 6px 20px; }'
|
||||
+ '\n.pdf-content li { margin-bottom: 2px; }'
|
||||
+ '\n.pdf-content a, .pdf-content .citation { color: #2c3e50; font-weight: 600; text-decoration: none; }'
|
||||
+ '\n.pdf-table { width: 100%; border-collapse: collapse; font-size: 10pt; margin-bottom: 16px; }'
|
||||
+ '\n.pdf-table th { background: #f0f0f0; text-align: left; padding: 6px 10px; border: 1px solid #ddd; font-weight: 600; font-size: 9pt; text-transform: uppercase; color: #555; }'
|
||||
+ '\n.pdf-table td { padding: 5px 10px; border: 1px solid #ddd; }'
|
||||
+ '\n.pdf-table tr:nth-child(even) { background: #fafafa; }'
|
||||
+ '\n.pdf-article-list { font-size: 10pt; }'
|
||||
+ '\n.pdf-article-item { padding: 2px 0; }'
|
||||
+ '\n.pdf-article-item a { color: #2c3e50; text-decoration: none; }'
|
||||
+ '\n.pdf-date { color: #888; font-size: 9pt; }'
|
||||
+ '\n.pdf-fc-list { display: flex; flex-direction: column; gap: 12px; }'
|
||||
+ '\n.pdf-fc-item { border: 1px solid #ddd; border-radius: 6px; padding: 10px 14px; page-break-inside: avoid; }'
|
||||
+ '\n.pdf-fc-badge { display: inline-block; font-size: 8pt; font-weight: 700; text-transform: uppercase; letter-spacing: 0.5px; padding: 2px 8px; border-radius: 3px; margin-bottom: 4px; }'
|
||||
+ '\n.pdf-fc-confirmed { background: #d4edda; color: #155724; }'
|
||||
+ '\n.pdf-fc-refuted { background: #f8d7da; color: #721c24; }'
|
||||
+ '\n.pdf-fc-unverified { background: #fff3cd; color: #856404; }'
|
||||
+ '\n.pdf-fc-claim { font-size: 11pt; margin-top: 4px; }'
|
||||
+ '\n.pdf-fc-evidence { margin-top: 6px; font-size: 9pt; }'
|
||||
+ '\n.pdf-fc-ev-link { color: #2c3e50; text-decoration: underline; margin-right: 6px; }'
|
||||
+ '\n.pdf-fc-ev-tag { background: #eee; padding: 1px 6px; border-radius: 3px; margin-right: 4px; }'
|
||||
+ '\n.pdf-map-placeholder { padding: 30px; text-align: center; color: #888; background: #f9f9f9; border: 1px dashed #ccc; border-radius: 6px; font-size: 10pt; }'
|
||||
+ '\n.pdf-timeline h4 { color: #2c3e50; border-bottom: 1px solid #eee; padding-bottom: 3px; margin-top: 10px; }'
|
||||
+ '\n.pdf-tl-item { padding: 2px 0; font-size: 10pt; }'
|
||||
+ '\n.pdf-tl-time { color: #888; font-size: 9pt; min-width: 40px; display: inline-block; }'
|
||||
+ '\n.pdf-tl-source { color: #888; font-size: 9pt; }'
|
||||
+ '\n.pdf-footer { margin-top: 30px; padding-top: 10px; border-top: 1px solid #ddd; font-size: 8pt; color: #999; text-align: center; }'
|
||||
+ '\n</style>'
|
||||
+ '\n</head>'
|
||||
+ '\n<body>'
|
||||
+ '\n<div class="pdf-header">'
|
||||
+ '\n <h1>' + esc(title) + '</h1>'
|
||||
+ '\n <div class="pdf-subtitle">AegisSight Monitor \u2014 Exportiert am ' + esc(now) + '</div>'
|
||||
+ '\n</div>'
|
||||
+ sections
|
||||
+ '\n<div class="pdf-footer">Erstellt mit AegisSight Monitor \u2014 aegis-sight.de</div>'
|
||||
+ '\n</body></html>';
|
||||
const css = `
|
||||
@page { margin: 18mm 15mm 18mm 15mm; size: A4; }
|
||||
* { box-sizing: border-box; margin: 0; padding: 0; }
|
||||
body { font-family: -apple-system, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif; font-size: 11pt; line-height: 1.55; color: #1a1a1a; background: #fff; padding: 0; }
|
||||
a { color: #1a5276; }
|
||||
|
||||
/* Header: compact, inline with content */
|
||||
.pdf-header { border-bottom: 2px solid #2c3e50; padding-bottom: 10px; margin-bottom: 16px; }
|
||||
.pdf-header h1 { font-size: 18pt; font-weight: 700; color: #2c3e50; margin-bottom: 2px; }
|
||||
.pdf-header .pdf-subtitle { font-size: 9pt; color: #666; }
|
||||
|
||||
/* Sections */
|
||||
.pdf-section { margin-bottom: 22px; }
|
||||
.pdf-section h2 { font-size: 13pt; font-weight: 600; color: #2c3e50; border-bottom: 1px solid #ccc; padding-bottom: 4px; margin-bottom: 10px; }
|
||||
.pdf-section h4 { font-size: 10pt; font-weight: 600; color: #444; margin: 10px 0 3px; }
|
||||
.pdf-meta { font-size: 9pt; color: #888; margin-bottom: 8px; }
|
||||
|
||||
/* Lagebild content */
|
||||
.pdf-content { font-size: 10.5pt; line-height: 1.6; }
|
||||
.pdf-content h3 { font-size: 11.5pt; font-weight: 600; color: #2c3e50; margin: 12px 0 5px; }
|
||||
.pdf-content strong { font-weight: 600; }
|
||||
.pdf-content ul { margin: 4px 0 4px 18px; }
|
||||
.pdf-content li { margin-bottom: 2px; }
|
||||
.pdf-content a, .pdf-content .citation { color: #1a5276; font-weight: 600; text-decoration: underline; cursor: pointer; }
|
||||
|
||||
/* Quellen table */
|
||||
.pdf-table { width: 100%; border-collapse: collapse; font-size: 9.5pt; margin-bottom: 14px; }
|
||||
.pdf-table th { background: #f0f0f0; text-align: left; padding: 5px 8px; border: 1px solid #ddd; font-weight: 600; font-size: 8.5pt; text-transform: uppercase; color: #555; }
|
||||
.pdf-table td { padding: 4px 8px; border: 1px solid #ddd; }
|
||||
.pdf-table tr:nth-child(even) { background: #fafafa; }
|
||||
.pdf-article-list { font-size: 9.5pt; }
|
||||
.pdf-article-item { padding: 1px 0; break-inside: avoid; }
|
||||
.pdf-article-item a { color: #1a5276; text-decoration: none; }
|
||||
.pdf-article-item a:hover { text-decoration: underline; }
|
||||
.pdf-date { color: #888; font-size: 8.5pt; }
|
||||
|
||||
/* Faktencheck */
|
||||
.pdf-fc-list { display: flex; flex-direction: column; gap: 10px; }
|
||||
.pdf-fc-item { border: 1px solid #ddd; border-radius: 4px; padding: 8px 12px; break-inside: avoid; }
|
||||
.pdf-fc-badge { display: inline-block; font-size: 7.5pt; font-weight: 700; text-transform: uppercase; letter-spacing: 0.4px; padding: 1px 7px; border-radius: 3px; margin-bottom: 3px; }
|
||||
.pdf-fc-confirmed { background: #d4edda; color: #155724; }
|
||||
.pdf-fc-refuted { background: #f8d7da; color: #721c24; }
|
||||
.pdf-fc-unverified { background: #fff3cd; color: #856404; }
|
||||
.pdf-fc-claim { font-size: 10.5pt; margin-top: 3px; }
|
||||
.pdf-fc-evidence { margin-top: 5px; font-size: 8.5pt; }
|
||||
.pdf-fc-ev-link { color: #1a5276; text-decoration: underline; margin-right: 5px; }
|
||||
.pdf-fc-ev-tag { background: #eee; padding: 1px 5px; border-radius: 3px; margin-right: 3px; }
|
||||
|
||||
/* Timeline */
|
||||
.pdf-timeline h4 { color: #2c3e50; border-bottom: 1px solid #eee; padding-bottom: 2px; margin-top: 8px; }
|
||||
.pdf-tl-item { padding: 1px 0; font-size: 9.5pt; break-inside: avoid; }
|
||||
.pdf-tl-time { color: #888; font-size: 8.5pt; min-width: 36px; display: inline-block; }
|
||||
.pdf-tl-source { color: #888; font-size: 8.5pt; }
|
||||
|
||||
/* Footer */
|
||||
.pdf-footer { margin-top: 24px; padding-top: 8px; border-top: 1px solid #ddd; font-size: 8pt; color: #999; text-align: center; }
|
||||
`;
|
||||
|
||||
const printHtml = '<!DOCTYPE html>\n<html lang="de">\n<head>\n<meta charset="utf-8">\n'
|
||||
+ '<title>' + esc(title) + ' \u2014 AegisSight Export</title>\n'
|
||||
+ '<style>' + css + '</style>\n'
|
||||
+ '</head>\n<body>\n'
|
||||
+ '<div class="pdf-header">\n'
|
||||
+ ' <h1>' + esc(title) + '</h1>\n'
|
||||
+ ' <div class="pdf-subtitle">AegisSight Monitor \u2014 Exportiert am ' + esc(now) + '</div>\n'
|
||||
+ '</div>\n'
|
||||
+ sections + '\n'
|
||||
+ '<div class="pdf-footer">Erstellt mit AegisSight Monitor \u2014 aegis-sight.de</div>\n'
|
||||
+ '</body></html>';
|
||||
|
||||
const printWin = window.open('', '_blank', 'width=800,height=600');
|
||||
if (!printWin) { UI.showToast('Popup blockiert \u2014 bitte Popup-Blocker deaktivieren', 'error'); return; }
|
||||
@@ -2354,7 +2348,6 @@ const App = {
|
||||
setTimeout(function() { try { printWin.focus(); printWin.print(); } catch(e) {} }, 500);
|
||||
},
|
||||
|
||||
|
||||
async exportIncident(format, scope) {
|
||||
this._closeExportDropdown();
|
||||
if (!this.currentIncidentId) return;
|
||||
|
||||
In neuem Issue referenzieren
Einen Benutzer sperren