Neue Features: - 3-Panel Dateimanager (Ordnerbaum, Dateiliste, Vorschau) - Separates Vorschau-Fenster für zweiten Monitor - Resize-Handles für flexible Panel-Größen (horizontal & vertikal) - Vorschau-Panel ausblendbar wenn externes Fenster aktiv - Natürliche Sortierung (Sonderzeichen → Zahlen → Buchstaben) - PDF-Vorschau mit Fit-to-Page - Email-Attachment Abruf erweitert Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
712 lines
39 KiB
HTML
712 lines
39 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="de">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>Dateiverwaltung</title>
|
|
<link rel="stylesheet" href="/static/css/style.css">
|
|
</head>
|
|
<body>
|
|
<div id="app">
|
|
<!-- Header -->
|
|
<header class="header">
|
|
<div class="header-left">
|
|
<h1>Dateiverwaltung</h1>
|
|
</div>
|
|
<div class="header-right">
|
|
<a href="/browser" target="_blank" class="btn btn-sm btn-primary" title="Dateimanager in neuem Fenster öffnen">📂 Dateimanager</a>
|
|
<select id="theme-select" class="theme-select" onchange="wechsleTheme(this.value)">
|
|
<option value="auto">🎨 Auto</option>
|
|
<option value="dark">🌙 Dark</option>
|
|
<option value="breeze-dark">🌙 Breeze Dark</option>
|
|
<option value="breeze-light">☀️ Breeze Light</option>
|
|
</select>
|
|
<button class="btn btn-sm" onclick="zeigeStatistik()">📊 Statistik</button>
|
|
<button class="btn btn-sm btn-danger" onclick="dbZuruecksetzen()">🗑 DB Reset</button>
|
|
<span id="status-indicator"></span>
|
|
</div>
|
|
</header>
|
|
|
|
<!-- Main Content -->
|
|
<div class="main-container">
|
|
<!-- Bereich 1: Mail-Abruf -->
|
|
<section class="bereich">
|
|
<div class="bereich-header">
|
|
<h2>📧 Mail-Abruf</h2>
|
|
<p class="bereich-desc">Attachments aus Postfächern in Ordner speichern</p>
|
|
</div>
|
|
|
|
<div class="bereich-content">
|
|
<!-- Postfächer Liste -->
|
|
<div class="card">
|
|
<div class="card-header">
|
|
<h3>Postfächer</h3>
|
|
<button class="btn btn-sm btn-primary" onclick="zeigePostfachModal()">+ Hinzufügen</button>
|
|
</div>
|
|
<div class="card-body">
|
|
<div id="postfaecher-liste">
|
|
<p class="empty-state">Keine Postfächer konfiguriert</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Abruf starten -->
|
|
<div class="action-bar">
|
|
<button class="btn btn-success btn-large" onclick="allePostfaecherAbrufen()">
|
|
▶ Alle Postfächer abrufen
|
|
</button>
|
|
</div>
|
|
|
|
<!-- Letzter Abruf Log -->
|
|
<div class="card">
|
|
<div class="card-header">
|
|
<h3>Letzter Abruf</h3>
|
|
</div>
|
|
<div class="card-body">
|
|
<div id="abruf-log" class="log-output">
|
|
<p class="empty-state">Noch kein Abruf durchgeführt</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<!-- Bereich 2: Datei-Sortierung -->
|
|
<section class="bereich">
|
|
<div class="bereich-header">
|
|
<h2>📁 Datei-Sortierung</h2>
|
|
<p class="bereich-desc">Dateien nach Regeln umbenennen und verschieben</p>
|
|
</div>
|
|
|
|
<div class="bereich-content">
|
|
<!-- Quell-Ordner -->
|
|
<div class="card">
|
|
<div class="card-header">
|
|
<h3>Quell-Ordner</h3>
|
|
<button class="btn btn-sm btn-primary" onclick="zeigeOrdnerModal()">+ Hinzufügen</button>
|
|
</div>
|
|
<div class="card-body">
|
|
<div id="ordner-liste">
|
|
<p class="empty-state">Keine Ordner konfiguriert</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Schnell-Regeln (Typ-basiert für Grob-Sortierung) -->
|
|
<div class="card">
|
|
<div class="card-header">
|
|
<h3>Schnell-Regeln (Grob-Sortierung)</h3>
|
|
<div>
|
|
<button class="btn btn-sm btn-primary" onclick="zeigeSchnellRegelModal()">+ Schnell-Regel</button>
|
|
</div>
|
|
</div>
|
|
<div class="card-body">
|
|
<p class="card-hint">Sortiert automatisch nach Dateityp/Eigenschaften. Wird <strong>vor</strong> den Fein-Regeln angewendet.</p>
|
|
<div id="schnell-regeln-liste">
|
|
<p class="empty-state">Keine Schnell-Regeln definiert</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Regeln (Fein-Sortierung) -->
|
|
<div class="card">
|
|
<div class="card-header">
|
|
<h3>Fein-Regeln (nach Inhalt)</h3>
|
|
<div>
|
|
<button class="btn btn-sm" onclick="zeigeRegelHilfe()">❓ Hilfe</button>
|
|
<button class="btn btn-sm btn-primary" onclick="zeigeRegelModal()">+ Hinzufügen</button>
|
|
</div>
|
|
</div>
|
|
<div class="card-body">
|
|
<p class="card-hint">Sortiert nach Textinhalt (Keywords, Regex). Höhere Priorität = wird später geprüft.</p>
|
|
<div id="regeln-liste">
|
|
<p class="empty-state">Keine Regeln definiert</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- OCR-Backup Einstellung -->
|
|
<div class="card">
|
|
<div class="card-header">
|
|
<h3>OCR-Einstellungen</h3>
|
|
</div>
|
|
<div class="card-body">
|
|
<div class="form-group">
|
|
<label>
|
|
<input type="checkbox" id="ocr-backup-aktiv" onchange="toggleOcrBackup()">
|
|
Backup vor OCR-Einbettung erstellen
|
|
</label>
|
|
<small>Originale werden gesichert bevor Text eingebettet wird</small>
|
|
</div>
|
|
<div id="ocr-backup-ordner-gruppe" class="form-group hidden">
|
|
<label>Backup-Ordner</label>
|
|
<div class="input-with-btn">
|
|
<input type="text" id="ocr-backup-ordner" placeholder="/mnt/backup/pdf-originale">
|
|
<button class="btn" type="button" onclick="oeffneBrowserFuerOcrBackup()">📁</button>
|
|
</div>
|
|
<small>PDFs werden hierhin kopiert bevor OCR-Text eingebettet wird</small>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Sortierung starten/stoppen -->
|
|
<div class="action-bar">
|
|
<div class="action-buttons">
|
|
<button id="sortierung-start-btn" class="btn btn-success btn-large" onclick="sortierungStarten(false)">
|
|
▶ Sortierung starten
|
|
</button>
|
|
<button id="sortierung-test-btn" class="btn btn-large" onclick="sortierungStarten(true)" title="Analysiert Dateien ohne sie zu verschieben">
|
|
🔍 Testlauf (nur Vorschau)
|
|
</button>
|
|
<button id="sortierung-stopp-btn" class="btn btn-danger btn-large hidden" onclick="sortierungStoppen()">
|
|
◼ Sortierung stoppen
|
|
</button>
|
|
</div>
|
|
<small class="action-hint">Testlauf zeigt was passieren würde, ohne Dateien zu verschieben</small>
|
|
</div>
|
|
|
|
<!-- Sortierungs-Log -->
|
|
<div class="card">
|
|
<div class="card-header">
|
|
<h3>Verarbeitete Dateien</h3>
|
|
</div>
|
|
<div class="card-body">
|
|
<div id="sortierung-log" class="log-output">
|
|
<p class="empty-state">Noch keine Dateien verarbeitet</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
</div>
|
|
|
|
<!-- Modal: Postfach hinzufügen -->
|
|
<div id="postfach-modal" class="modal hidden">
|
|
<div class="modal-content">
|
|
<div class="modal-header">
|
|
<h3>Postfach hinzufügen</h3>
|
|
<button class="modal-close" onclick="schliesseModal('postfach-modal')">×</button>
|
|
</div>
|
|
<div class="modal-body">
|
|
<div class="form-group">
|
|
<label>Name</label>
|
|
<input type="text" id="pf-name" placeholder="z.B. Firma Rechnungen">
|
|
</div>
|
|
<div class="form-row">
|
|
<div class="form-group">
|
|
<label>IMAP Server</label>
|
|
<input type="text" id="pf-server" placeholder="imap.example.com">
|
|
</div>
|
|
<div class="form-group">
|
|
<label>Port</label>
|
|
<input type="number" id="pf-port" value="993">
|
|
</div>
|
|
</div>
|
|
<div class="form-group">
|
|
<label>E-Mail</label>
|
|
<input type="email" id="pf-email" placeholder="mail@example.com">
|
|
</div>
|
|
<div class="form-group">
|
|
<label>Passwort</label>
|
|
<input type="password" id="pf-passwort">
|
|
</div>
|
|
<div class="form-row">
|
|
<div class="form-group">
|
|
<label>IMAP-Ordner</label>
|
|
<input type="text" id="pf-ordner" value="INBOX">
|
|
</div>
|
|
<div class="form-group">
|
|
<label>Alle Ordner durchsuchen</label>
|
|
<select id="pf-alle-ordner">
|
|
<option value="false">Nein (nur angegebenen Ordner)</option>
|
|
<option value="true">Ja (alle Ordner)</option>
|
|
</select>
|
|
</div>
|
|
</div>
|
|
<div class="form-group">
|
|
<label>Welche Mails durchsuchen</label>
|
|
<select id="pf-nur-ungelesen">
|
|
<option value="false" selected>Alle Mails</option>
|
|
<option value="true">Nur ungelesene Mails</option>
|
|
</select>
|
|
</div>
|
|
<div class="form-group">
|
|
<label>Mails ab Datum (optional)</label>
|
|
<input type="date" id="pf-ab-datum">
|
|
<small>Nur Mails ab diesem Datum abrufen (leer = alle)</small>
|
|
</div>
|
|
<div class="form-group">
|
|
<label>Ziel-Ordner</label>
|
|
<div class="input-with-btn">
|
|
<input type="text" id="pf-ziel" value="/srv/http/dateiverwaltung/data/inbox/">
|
|
<button class="btn" type="button" onclick="oeffneBrowser('pf-ziel')">📁</button>
|
|
</div>
|
|
<small>Hier landen die Attachments</small>
|
|
</div>
|
|
<div class="form-group">
|
|
<label>Erlaubte Dateitypen</label>
|
|
<div class="checkbox-group" id="pf-typen-gruppe">
|
|
<label class="checkbox-item"><input type="checkbox" value=".pdf" checked> PDF</label>
|
|
<label class="checkbox-item"><input type="checkbox" value=".jpg"> JPG</label>
|
|
<label class="checkbox-item"><input type="checkbox" value=".jpeg"> JPEG</label>
|
|
<label class="checkbox-item"><input type="checkbox" value=".png"> PNG</label>
|
|
<label class="checkbox-item"><input type="checkbox" value=".gif"> GIF</label>
|
|
<label class="checkbox-item"><input type="checkbox" value=".tiff"> TIFF</label>
|
|
<label class="checkbox-item"><input type="checkbox" value=".doc"> DOC</label>
|
|
<label class="checkbox-item"><input type="checkbox" value=".docx"> DOCX</label>
|
|
<label class="checkbox-item"><input type="checkbox" value=".xls"> XLS</label>
|
|
<label class="checkbox-item"><input type="checkbox" value=".xlsx"> XLSX</label>
|
|
<label class="checkbox-item"><input type="checkbox" value=".csv"> CSV</label>
|
|
<label class="checkbox-item"><input type="checkbox" value=".txt"> TXT</label>
|
|
<label class="checkbox-item"><input type="checkbox" value=".zip"> ZIP</label>
|
|
<label class="checkbox-item"><input type="checkbox" value=".xml"> XML</label>
|
|
</div>
|
|
</div>
|
|
<div class="form-group">
|
|
<label>Max. Größe (MB)</label>
|
|
<input type="number" id="pf-max-groesse" value="25" style="width: 100px;">
|
|
</div>
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button class="btn" onclick="schliesseModal('postfach-modal')">Abbrechen</button>
|
|
<button class="btn btn-primary" onclick="speicherePostfach()">Speichern</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Modal: Ordner hinzufügen -->
|
|
<div id="ordner-modal" class="modal hidden">
|
|
<div class="modal-content">
|
|
<div class="modal-header">
|
|
<h3>Quell-Ordner hinzufügen</h3>
|
|
<button class="modal-close" onclick="schliesseModal('ordner-modal')">×</button>
|
|
</div>
|
|
<div class="modal-body">
|
|
<div class="form-group">
|
|
<label>Name</label>
|
|
<input type="text" id="ord-name" placeholder="z.B. Firma Inbox">
|
|
</div>
|
|
<div class="form-group">
|
|
<label>Quell-Pfad (wo liegen die Dateien?)</label>
|
|
<div class="input-with-btn">
|
|
<input type="text" id="ord-pfad" value="/srv/http/dateiverwaltung/data/inbox/">
|
|
<button class="btn" type="button" onclick="oeffneBrowser('ord-pfad')">📁</button>
|
|
</div>
|
|
</div>
|
|
<div class="form-group">
|
|
<label>Ziel-Ordner (wohin nach Sortierung?)</label>
|
|
<div class="input-with-btn">
|
|
<input type="text" id="ord-ziel" value="/srv/http/dateiverwaltung/data/archiv/">
|
|
<button class="btn" type="button" onclick="oeffneBrowser('ord-ziel')">📁</button>
|
|
</div>
|
|
</div>
|
|
<div class="form-group">
|
|
<label>Dateitypen</label>
|
|
<div class="checkbox-group" id="ord-typen-gruppe">
|
|
<label class="checkbox-item"><input type="checkbox" value=".pdf" checked> PDF</label>
|
|
<label class="checkbox-item"><input type="checkbox" value=".jpg" checked> JPG</label>
|
|
<label class="checkbox-item"><input type="checkbox" value=".jpeg" checked> JPEG</label>
|
|
<label class="checkbox-item"><input type="checkbox" value=".png" checked> PNG</label>
|
|
<label class="checkbox-item"><input type="checkbox" value=".gif"> GIF</label>
|
|
<label class="checkbox-item"><input type="checkbox" value=".tiff" checked> TIFF</label>
|
|
<label class="checkbox-item"><input type="checkbox" value=".bmp"> BMP</label>
|
|
<label class="checkbox-item"><input type="checkbox" value=".doc"> DOC</label>
|
|
<label class="checkbox-item"><input type="checkbox" value=".docx"> DOCX</label>
|
|
<label class="checkbox-item"><input type="checkbox" value=".xls"> XLS</label>
|
|
<label class="checkbox-item"><input type="checkbox" value=".xlsx"> XLSX</label>
|
|
<label class="checkbox-item"><input type="checkbox" value=".csv"> CSV</label>
|
|
<label class="checkbox-item"><input type="checkbox" value=".txt"> TXT</label>
|
|
<label class="checkbox-item"><input type="checkbox" value=".xml"> XML</label>
|
|
</div>
|
|
</div>
|
|
<div class="form-group">
|
|
<label>Unterordner einschließen</label>
|
|
<select id="ord-rekursiv">
|
|
<option value="true" selected>Ja (rekursiv)</option>
|
|
<option value="false">Nein (nur dieser Ordner)</option>
|
|
</select>
|
|
</div>
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button class="btn" onclick="schliesseModal('ordner-modal')">Abbrechen</button>
|
|
<button class="btn btn-primary" onclick="speichereOrdner()">Speichern</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Modal: Regel hinzufügen -->
|
|
<div id="regel-modal" class="modal hidden">
|
|
<div class="modal-content modal-large">
|
|
<div class="modal-header">
|
|
<h3 id="regel-modal-title">Regel hinzufügen</h3>
|
|
<button class="modal-close" onclick="schliesseModal('regel-modal')">×</button>
|
|
</div>
|
|
<div class="modal-body">
|
|
<div class="form-row">
|
|
<div class="form-group">
|
|
<label>Name</label>
|
|
<input type="text" id="regel-name" placeholder="z.B. Sonepar Rechnung">
|
|
</div>
|
|
<div class="form-group">
|
|
<label>Priorität (niedriger = wichtiger)</label>
|
|
<input type="number" id="regel-prioritaet" value="100">
|
|
</div>
|
|
</div>
|
|
|
|
<div class="form-group">
|
|
<label>Erkennungsmuster (JSON)</label>
|
|
<textarea id="regel-muster" class="code-input" rows="4">{
|
|
"text_match_any": ["sonepar"],
|
|
"text_match": ["rechnung"]
|
|
}</textarea>
|
|
<small>text_match_any: mindestens eins | text_match: alle müssen passen</small>
|
|
</div>
|
|
|
|
<div class="form-group">
|
|
<label>Feld-Extraktion (JSON)</label>
|
|
<textarea id="regel-extraktion" class="code-input" rows="6">{
|
|
"datum": {"regex": "(\\d{2}[./]\\d{2}[./]\\d{4})", "format": "%d.%m.%Y"},
|
|
"rechnungsnummer": {"regex": "Rechnungsnummer[:\\s]*(\\d+)"},
|
|
"betrag": {"regex": "Gesamtbetrag[:\\s]*([\\d.,]+)", "typ": "betrag"},
|
|
"ersteller": {"wert": "Sonepar"}
|
|
}</textarea>
|
|
</div>
|
|
|
|
<div class="form-group">
|
|
<label>Dateiname-Schema</label>
|
|
<input type="text" id="regel-schema"
|
|
value="{datum} - Rechnung - {ersteller} - {rechnungsnummer} - {betrag} EUR.pdf">
|
|
</div>
|
|
|
|
<div class="form-group">
|
|
<label>Ziel-Unterordner (optional)</label>
|
|
<div class="input-with-btn">
|
|
<input type="text" id="regel-unterordner" placeholder="sonepar">
|
|
<button class="btn" type="button" onclick="oeffneBrowserFuerRegel()">📁</button>
|
|
</div>
|
|
<small>Wird an den Ziel-Ordner des Quell-Ordners angehängt</small>
|
|
</div>
|
|
|
|
<!-- Tester -->
|
|
<div class="form-group">
|
|
<label>Regel testen</label>
|
|
<textarea id="regel-test-text" rows="3" placeholder="Text zum Testen einfügen..."></textarea>
|
|
<button class="btn btn-sm" onclick="testeRegel()">Testen</button>
|
|
<div id="regel-test-ergebnis" class="test-result hidden"></div>
|
|
</div>
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button class="btn" onclick="schliesseModal('regel-modal')">Abbrechen</button>
|
|
<button class="btn btn-primary" onclick="speichereRegel()">Speichern</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Modal: Verzeichnis-Browser -->
|
|
<div id="browser-modal" class="modal hidden">
|
|
<div class="modal-content">
|
|
<div class="modal-header">
|
|
<h3>Verzeichnis wählen</h3>
|
|
<button class="modal-close" onclick="schliesseModal('browser-modal')">×</button>
|
|
</div>
|
|
<div class="modal-body">
|
|
<div class="file-browser">
|
|
<div class="file-browser-path">
|
|
<span id="browser-current-path">/</span>
|
|
</div>
|
|
<ul class="file-browser-list" id="browser-list"></ul>
|
|
</div>
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button class="btn" onclick="schliesseModal('browser-modal')">Abbrechen</button>
|
|
<button class="btn btn-primary" onclick="browserAuswahl()">Auswählen</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Modal: Regel-Hilfe / Text-Analyse -->
|
|
<div id="hilfe-modal" class="modal hidden">
|
|
<div class="modal-content modal-large">
|
|
<div class="modal-header">
|
|
<h3>Regel-Hilfe & Text-Analyse</h3>
|
|
<button class="modal-close" onclick="schliesseModal('hilfe-modal')">×</button>
|
|
</div>
|
|
<div class="modal-body">
|
|
<div class="hilfe-section">
|
|
<h4>📋 Text einfügen zur Analyse</h4>
|
|
<p>Füge hier den Text eines Dokuments ein (z.B. aus einer PDF). Ich analysiere ihn und schlage eine Regel vor.</p>
|
|
<textarea id="hilfe-text" rows="10" placeholder="Text hier einfügen oder hochladen... Beispiel: Kopiere den Text aus einer Rechnung hier rein..."></textarea>
|
|
<div class="btn-group">
|
|
<button class="btn btn-primary" onclick="analysiereText()">Text analysieren</button>
|
|
<label class="btn btn-file">
|
|
PDF hochladen
|
|
<input type="file" id="hilfe-upload" accept=".pdf,.txt" onchange="ladeHilfeDatei(this)" hidden>
|
|
</label>
|
|
<button class="btn" onclick="zeigePdfBrowser()">PDF aus Ordner</button>
|
|
</div>
|
|
</div>
|
|
|
|
<div id="hilfe-ergebnis" class="hilfe-section hidden">
|
|
<h4>✨ Analyse-Ergebnis</h4>
|
|
<div id="hilfe-analyse"></div>
|
|
|
|
<h4 style="margin-top: 1rem;">🔧 Felder anpassen</h4>
|
|
<p>Passe die Regex-Muster an wenn die automatische Erkennung falsch ist:</p>
|
|
|
|
<div class="regex-editor">
|
|
<div class="regex-row">
|
|
<label>Firma/Ersteller:</label>
|
|
<input type="text" id="hilfe-firma" placeholder="z.B. Meine Firma GmbH">
|
|
<small>Fester Wert (kein Regex)</small>
|
|
</div>
|
|
<div class="regex-row">
|
|
<label>Datum Regex:</label>
|
|
<div class="regex-input-group">
|
|
<input type="text" id="hilfe-datum-regex" placeholder="z.B. Rechnungsdatum[:\s]*(\d{2}\.\d{2}\.\d{4})">
|
|
<select id="hilfe-datum-preset" onchange="setzeRegexPreset('datum')">
|
|
<option value="">-- Vorlage --</option>
|
|
<option value="(\d{2}\.\d{2}\.\d{4})">DD.MM.YYYY</option>
|
|
<option value="Rechnungsdatum[:\s]*(\d{2}\.\d{2}\.\d{4})">Rechnungsdatum: DD.MM.YYYY</option>
|
|
<option value="Datum[:\s]*(\d{2}\.\d{2}\.\d{4})">Datum: DD.MM.YYYY</option>
|
|
<option value="(\d{4}-\d{2}-\d{2})">YYYY-MM-DD</option>
|
|
</select>
|
|
</div>
|
|
<small>Gruppe 1 = Datum</small>
|
|
</div>
|
|
<div class="regex-row">
|
|
<label>Betrag Regex:</label>
|
|
<div class="regex-input-group">
|
|
<input type="text" id="hilfe-betrag-regex" placeholder="z.B. Gesamtbetrag[:\s]*([\d.,]+)">
|
|
<select id="hilfe-betrag-preset" onchange="setzeRegexPreset('betrag')">
|
|
<option value="">-- Vorlage --</option>
|
|
<option value="Gesamtbetrag[:\s]*([\d.,]+)">Gesamtbetrag: X,XX</option>
|
|
<option value="Summe[:\s]*([\d.,]+)">Summe: X,XX</option>
|
|
<option value="Rechnungsbetrag[:\s]*([\d.,]+)">Rechnungsbetrag: X,XX</option>
|
|
<option value="Total[:\s]*([\d.,]+)">Total: X,XX</option>
|
|
<option value="Brutto[:\s]*([\d.,]+)">Brutto: X,XX</option>
|
|
<option value="Netto[:\s]*([\d.,]+)">Netto: X,XX</option>
|
|
<option value="EUR\s*([\d.,]+)(?!.*EUR\s*[\d.,]+)">Letzter EUR-Betrag</option>
|
|
</select>
|
|
</div>
|
|
<small>Gruppe 1 = Betrag (fur Gesamtsumme)</small>
|
|
</div>
|
|
<div class="regex-row">
|
|
<label>Nummer Regex:</label>
|
|
<div class="regex-input-group">
|
|
<input type="text" id="hilfe-nummer-regex" placeholder="z.B. Rechnungsnummer[:\s]*(\w+)">
|
|
<select id="hilfe-nummer-preset" onchange="setzeRegexPreset('nummer')">
|
|
<option value="">-- Vorlage --</option>
|
|
<option value="Rechnungsnummer[:\s]*(\S+)">Rechnungsnummer: XXX</option>
|
|
<option value="Rechnung\s*(?:Nr\.?|Nummer)?[:\s]*(\S+)">Rechnung Nr. XXX</option>
|
|
<option value="Belegnummer[:\s]*(\S+)">Belegnummer: XXX</option>
|
|
<option value="Bestellnummer[:\s]*(\S+)">Bestellnummer: XXX</option>
|
|
<option value="Dokumentnummer[:\s]*(\S+)">Dokumentnummer: XXX</option>
|
|
</select>
|
|
</div>
|
|
<small>Gruppe 1 = Rechnungs-/Belegnummer</small>
|
|
</div>
|
|
<div class="regex-row">
|
|
<label>Keywords (Erkennung):</label>
|
|
<input type="text" id="hilfe-keywords" placeholder="z.B. rechnung, meinefirma">
|
|
<small>Komma-getrennt - alle müssen im Text vorkommen</small>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="btn-group">
|
|
<button class="btn" onclick="testeMitRegex()">🔄 Mit Regex testen</button>
|
|
<button class="btn btn-primary" onclick="erstelleRegelAusHilfe()">✓ Regel erstellen</button>
|
|
</div>
|
|
|
|
<div id="hilfe-regel-vorschau" class="regel-vorschau hidden">
|
|
<h5>Generierte Regel:</h5>
|
|
<pre id="hilfe-regel-json"></pre>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="hilfe-section">
|
|
<h4>Regex-Cheatsheet</h4>
|
|
<div class="doku-box regex-cheatsheet">
|
|
<div class="cheatsheet-grid">
|
|
<div class="cheatsheet-section">
|
|
<h5>Grundlagen</h5>
|
|
<table class="cheatsheet-table">
|
|
<tr><td><code>\d</code></td><td>Eine Ziffer (0-9)</td></tr>
|
|
<tr><td><code>\d+</code></td><td>Eine oder mehr Ziffern</td></tr>
|
|
<tr><td><code>\s</code></td><td>Leerzeichen/Tab</td></tr>
|
|
<tr><td><code>\S+</code></td><td>Nicht-Leerzeichen (Wort)</td></tr>
|
|
<tr><td><code>.*</code></td><td>Beliebige Zeichen</td></tr>
|
|
<tr><td><code>[:\s]*</code></td><td>Doppelpunkt und/oder Leerzeichen</td></tr>
|
|
<tr><td><code>(xxx)</code></td><td>Gruppe - wird extrahiert!</td></tr>
|
|
</table>
|
|
</div>
|
|
<div class="cheatsheet-section">
|
|
<h5>Datum-Muster</h5>
|
|
<table class="cheatsheet-table">
|
|
<tr><td><code>(\d{2}\.\d{2}\.\d{4})</code></td><td>31.12.2024</td></tr>
|
|
<tr><td><code>(\d{4}-\d{2}-\d{2})</code></td><td>2024-12-31</td></tr>
|
|
<tr><td><code>Datum[:\s]*(\d{2}\.\d{2}\.\d{4})</code></td><td>Datum: 31.12.2024</td></tr>
|
|
</table>
|
|
</div>
|
|
<div class="cheatsheet-section">
|
|
<h5>Betrag-Muster</h5>
|
|
<table class="cheatsheet-table">
|
|
<tr><td><code>([\d.,]+)</code></td><td>Beliebige Zahl</td></tr>
|
|
<tr><td><code>(\d+,\d{2})</code></td><td>123,45</td></tr>
|
|
<tr><td><code>EUR\s*([\d.,]+)</code></td><td>EUR 123,45</td></tr>
|
|
<tr><td><code>Summe[:\s]*([\d.,]+)</code></td><td>Summe: 123,45</td></tr>
|
|
</table>
|
|
</div>
|
|
<div class="cheatsheet-section">
|
|
<h5>Nummer-Muster</h5>
|
|
<table class="cheatsheet-table">
|
|
<tr><td><code>(\S+)</code></td><td>Ein Wort/Nummer</td></tr>
|
|
<tr><td><code>(\d+)</code></td><td>Nur Ziffern</td></tr>
|
|
<tr><td><code>([A-Z0-9-]+)</code></td><td>Grossbuchst./Ziffern</td></tr>
|
|
<tr><td><code>Nr\.?\s*(\S+)</code></td><td>Nr. 12345</td></tr>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
<div class="cheatsheet-tip">
|
|
<strong>Tipp:</strong> Die <code>(Klammern)</code> bestimmen was extrahiert wird.
|
|
Alles davor dient nur zum Finden der richtigen Stelle im Text.
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="hilfe-section">
|
|
<h4>Regel-Dokumentation</h4>
|
|
<div class="doku-box">
|
|
<h5>Erkennungsmuster (muster)</h5>
|
|
<pre>{
|
|
"text_match_any": ["sonepar", "wuerth"], // Mindestens eins muss vorkommen
|
|
"text_match": ["rechnung"], // Alle müssen vorkommen
|
|
"keywords": "sonepar, rechnung" // Einfache Variante
|
|
}</pre>
|
|
|
|
<h5>Feld-Extraktion (extraktion)</h5>
|
|
<pre>{
|
|
"datum": {
|
|
"regex": "(\\d{2}[./]\\d{2}[./]\\d{4})",
|
|
"format": "%d.%m.%Y"
|
|
},
|
|
"rechnungsnummer": {
|
|
"regex": "Rechnungsnummer[:\\s]*(\\d+)"
|
|
},
|
|
"betrag": {
|
|
"regex": "Gesamtbetrag[:\\s]*([\\d.,]+)",
|
|
"typ": "betrag"
|
|
},
|
|
"ersteller": {
|
|
"wert": "Sonepar" // Fester Wert
|
|
}
|
|
}</pre>
|
|
|
|
<h5>Dateiname-Schema</h5>
|
|
<pre>Verfügbare Platzhalter:
|
|
{datum} -> 2024-01-15
|
|
{jahr} -> 2024
|
|
{monat} -> 01
|
|
{tag} -> 15
|
|
{ersteller} -> Sonepar
|
|
{firma} -> Sonepar
|
|
{rechnungsnummer}-> 12345
|
|
{betrag} -> 123,45
|
|
{original} -> Original-Dateiname
|
|
|
|
Beispiel:
|
|
{datum} - Rechnung - {ersteller} - {rechnungsnummer} - {betrag} EUR.pdf</pre>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button class="btn" onclick="schliesseModal('hilfe-modal')">Schließen</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Modal: Statistik -->
|
|
<div id="statistik-modal" class="modal hidden">
|
|
<div class="modal-content">
|
|
<div class="modal-header">
|
|
<h3>📊 Datenbank-Statistik</h3>
|
|
<button class="modal-close" onclick="schliesseModal('statistik-modal')">×</button>
|
|
</div>
|
|
<div class="modal-body">
|
|
<div id="statistik-inhalt">Wird geladen...</div>
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button class="btn" onclick="schliesseModal('statistik-modal')">Schließen</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Modal: Schnell-Regel hinzufügen -->
|
|
<div id="schnell-regel-modal" class="modal hidden">
|
|
<div class="modal-content">
|
|
<div class="modal-header">
|
|
<h3>Schnell-Regel hinzufügen</h3>
|
|
<button class="modal-close" onclick="schliesseModal('schnell-regel-modal')">×</button>
|
|
</div>
|
|
<div class="modal-body">
|
|
<p class="modal-hint">Schnell-Regeln sortieren nach Dateityp und Eigenschaften (z.B. alle Bilder in einen Ordner).</p>
|
|
|
|
<div class="form-group">
|
|
<label>Regel-Typ auswählen</label>
|
|
<select id="schnell-regel-typ" onchange="schnellRegelTypGeaendert()">
|
|
<option value="">-- Bitte wählen --</option>
|
|
</select>
|
|
</div>
|
|
|
|
<div id="schnell-regel-details" class="hidden">
|
|
<div class="info-box">
|
|
<strong id="schnell-regel-name"></strong>
|
|
<p id="schnell-regel-beschreibung"></p>
|
|
<small>Erkennung: <code id="schnell-regel-muster"></code></small>
|
|
</div>
|
|
|
|
<div class="form-group">
|
|
<label>Ziel-Unterordner</label>
|
|
<input type="text" id="schnell-regel-unterordner" placeholder="z.B. bilder">
|
|
<small>Dateien werden in diesen Unterordner des Zielordners verschoben</small>
|
|
</div>
|
|
|
|
<div class="form-group">
|
|
<label>Priorität (niedriger = wichtiger)</label>
|
|
<input type="number" id="schnell-regel-prioritaet" value="10">
|
|
<small>Regeln mit niedriger Priorität werden zuerst geprüft</small>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button class="btn" onclick="schliesseModal('schnell-regel-modal')">Abbrechen</button>
|
|
<button class="btn btn-primary" id="schnell-regel-speichern-btn" onclick="speichereSchnellRegel()" disabled>Speichern</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Modal: PDF-Browser -->
|
|
<div id="pdf-browser-modal" class="modal hidden">
|
|
<div class="modal-content">
|
|
<div class="modal-header">
|
|
<h3>PDF aus Quell-Ordner auswählen</h3>
|
|
<button class="modal-close" onclick="schliesseModal('pdf-browser-modal')">×</button>
|
|
</div>
|
|
<div class="modal-body">
|
|
<div id="pdf-browser-liste">Lade...</div>
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button class="btn" onclick="schliesseModal('pdf-browser-modal')">Abbrechen</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Loading Overlay -->
|
|
<div id="loading-overlay" class="loading-overlay hidden">
|
|
<div class="spinner"></div>
|
|
<div class="loading-text" id="loading-text">Wird geladen...</div>
|
|
</div>
|
|
</div>
|
|
|
|
<script src="/static/js/app.js"></script>
|
|
</body>
|
|
</html>
|