From ed63994e1cdd74ba8c31c7b71151d26f780291d7 Mon Sep 17 00:00:00 2001 From: Hermes Agent Date: Mon, 13 Jul 2026 22:43:48 +0200 Subject: [PATCH] fix: Word-Upload-Feld wiederhergestellt + beide Formate parallel MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Excel (.xlsx) für Fakten/Wertung/Pro/Kontra/Tags - Word (.docx) für Artikeltext (Spielerklärung) - Beide optional — Text aus Word wird zwischen Infobox und Fazit eingefügt - Formular zeigt beide Upload-Zonen nebeneinander --- article_server.py | 84 ++++++++++++++++++++++++++++++++++------------- 1 file changed, 61 insertions(+), 23 deletions(-) diff --git a/article_server.py b/article_server.py index 61807aa..40c4051 100644 --- a/article_server.py +++ b/article_server.py @@ -1903,11 +1903,21 @@ textarea{{min-height:100px;resize:vertical}}

Review Builder

Word-Datei + Bilder hochladen. Inhalte werden automatisch zugeordnet.

-

1. Excel-Datei hochladen

-
-
Bewertungs-Excel hier ablegen oder klicken (.xlsx)
+

1. Dateien hochladen

+
+
+
+
Excel mit Fakten
(.xlsx)
-
    +
      +
      +
      +
      +
      Word mit Artikeltext
      (.docx)
      + +
        +
        +

        2. Bilder hochladen

        Bilder hier ablegen oder klicken
        @@ -1944,8 +1954,9 @@ textarea{{min-height:100px;resize:vertical}}
        """ @@ -1995,24 +2012,36 @@ document.getElementById('publishBtn').addEventListener('click',function(){{submi boundary = boundary[1:-1] parts = _parse_multipart(raw, boundary) excel_data = parts.get("excel") + word_data = parts.get("word") image_datas = [v for k, v in parts.items() if k.startswith("images_")] - meta = {k: v for k, v in parts.items() if k not in ("excel",) and not k.startswith("images_")} - if not excel_data: - self._json_reply(400, {"ok": False, "error": "Keine Excel-Datei"}) - return - try: - import openpyxl - wb = openpyxl.load_workbook(io.BytesIO(excel_data), data_only=True) - ws = wb["EINGABE"] - xl = {} - for row in ws.iter_rows(min_row=1, values_only=True): - key = str(row[0]).strip() if row[0] else "" - val = str(row[1]).strip() if row[1] else "" - if key and val: - xl[key] = val - except Exception as e: - self._json_reply(400, {"ok": False, "error": f"Excel-Fehler: {e}"}) - return + meta = {k: v for k, v in parts.items() if k not in ("excel", "word") and not k.startswith("images_")} + + # Excel parsen (Fakten, Wertung, Pro/Kontra, Tags) + xl = {} + if excel_data: + try: + import openpyxl + wb = openpyxl.load_workbook(io.BytesIO(excel_data), data_only=True) + ws = wb["EINGABE"] + for row in ws.iter_rows(min_row=1, values_only=True): + key = str(row[0]).strip() if row[0] else "" + val = str(row[1]).strip() if row[1] else "" + if key and val: + xl[key] = val + except Exception as e: + self._json_reply(400, {"ok": False, "error": f"Excel-Fehler: {e}"}) + return + + # Word parsen (Artikeltext) + word_text = "" + if word_data: + try: + from docx import Document + doc = Document(io.BytesIO(word_data)) + word_text = "\n".join(p.text for p in doc.paragraphs if p.text.strip()) + except Exception as e: + self._json_reply(400, {"ok": False, "error": f"Word-Fehler: {e}"}) + return spielname = xl.get("Spieltitel", meta.get("spielname", "Unbekannt")).strip() zusatz = xl.get("Zusatztitel", "").strip() @@ -2148,6 +2177,14 @@ document.getElementById('publishBtn').addEventListener('click',function(){{submi tags_str = ", ".join(tags) if tags else f"{spielname}, Brettspiel, Review, Bewertung, {autor_name}" title_full = f"{spielname} {zusatz}".strip() + # Artikeltext aus Word (zwischen Infobox und Fazit) + artikel_html = "" + if word_text: + if "<" not in word_text[:100]: + artikel_html = f"

        {word_text.replace(chr(10)+chr(10), '

        ')}

        " + else: + artikel_html = word_text + body = f"""

        {spielname} — {komplex or 'Brettspiel'} von {autoren or verlag or 'unbekannt'}


         

        @@ -2155,6 +2192,7 @@ document.getElementById('publishBtn').addEventListener('click',function(){{submi {fakten_html} {disc_html} {mech_html} +{artikel_html} {pro_html} {kontra_html}

        Meine Meinung