feat: Umsetzungsgrad in Ketten-Detail anzeigen
- Backend: KI-Umsetzungsbewertung (Score, Bewertung, Begründung, Kernpunkt, Details) im Ketten-Detail-Response - Frontend: Umsetzungsgrad zwischen Ampel und Timeline im Explorer Panel 2 - Prozent-Kreis (grün/amber/rot) + Bewertungstext + Kernpunkt-Status - Begründung + Details als Fließtext
This commit is contained in:
parent
2d2e335ac3
commit
726f5c06ad
@ -123,6 +123,7 @@ class KetteDetail(BaseModel):
|
||||
graph: dict | None = None
|
||||
strang: str | None = None
|
||||
ampel: dict | None = None
|
||||
umsetzung: dict | None = None
|
||||
|
||||
|
||||
class PaginatedVorlagen(BaseModel):
|
||||
|
||||
@ -191,6 +191,33 @@ def get_kette(kette_id: int, conn=Depends(_db)):
|
||||
# Graph/Perlenschnur data
|
||||
graph = get_kette_graph(conn, kette_id)
|
||||
|
||||
# Umsetzungsbewertung (neueste KI-Bewertung für Ursprungsvorlage)
|
||||
umsetzung = None
|
||||
if row["ursprung_id"]:
|
||||
ub_row = conn.execute(
|
||||
"""SELECT score, begruendung, anmerkungen, erstellt_at, prompt_version
|
||||
FROM ki_bewertungen
|
||||
WHERE vorlage_id = ? AND typ = 'umsetzung_match'
|
||||
ORDER BY id DESC LIMIT 1""",
|
||||
(row["ursprung_id"],),
|
||||
).fetchone()
|
||||
if ub_row:
|
||||
import json as _json
|
||||
details = {}
|
||||
if ub_row["anmerkungen"]:
|
||||
try:
|
||||
details = _json.loads(ub_row["anmerkungen"])
|
||||
except Exception:
|
||||
pass
|
||||
umsetzung = {
|
||||
"score": ub_row["score"],
|
||||
"bewertung": details.get("bewertung", ""),
|
||||
"begruendung": ub_row["begruendung"],
|
||||
"kernpunkt_erfuellt": details.get("kernpunkt_erfuellt"),
|
||||
"details": details.get("details", ""),
|
||||
"erstellt_at": ub_row["erstellt_at"],
|
||||
}
|
||||
|
||||
strang = row["strang"]
|
||||
ampel_data = get_ampel(strang or "", row["status"] or "")
|
||||
|
||||
@ -216,4 +243,5 @@ def get_kette(kette_id: int, conn=Depends(_db)):
|
||||
graph=graph,
|
||||
strang=strang,
|
||||
ampel=ampel_data,
|
||||
umsetzung=umsetzung,
|
||||
)
|
||||
|
||||
@ -338,6 +338,35 @@
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<!-- Umsetzungsgrad -->
|
||||
{#if selectedKette.umsetzung}
|
||||
{@const u = selectedKette.umsetzung}
|
||||
<div class="px-4 pb-3 border-b border-gray-100">
|
||||
<div class="flex items-center gap-2 mb-1.5">
|
||||
<div class="w-10 h-10 rounded-full flex items-center justify-center text-sm font-bold
|
||||
{u.score >= 0.7 ? 'bg-green-200 text-green-800' : u.score >= 0.4 ? 'bg-amber-200 text-amber-800' : 'bg-red-200 text-red-800'}">
|
||||
{Math.round((u.score || 0) * 100)}%
|
||||
</div>
|
||||
<div>
|
||||
<div class="text-xs font-semibold {u.score >= 0.7 ? 'text-green-800' : u.score >= 0.4 ? 'text-amber-800' : 'text-red-800'}">
|
||||
{u.bewertung || (u.score >= 0.7 ? 'Umgesetzt' : u.score >= 0.4 ? 'Teilweise' : 'Kaum umgesetzt')}
|
||||
</div>
|
||||
{#if u.kernpunkt_erfuellt !== null && u.kernpunkt_erfuellt !== undefined}
|
||||
<div class="text-[10px] text-gray-500">
|
||||
Kernpunkt: {u.kernpunkt_erfuellt ? '✅ erfüllt' : '❌ nicht erfüllt'}
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
{#if u.begruendung}
|
||||
<p class="text-[11px] text-gray-600 leading-snug">{u.begruendung}</p>
|
||||
{/if}
|
||||
{#if u.details}
|
||||
<p class="text-[10px] text-gray-500 mt-1 leading-snug">{u.details}</p>
|
||||
{/if}
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<!-- Timeline -->
|
||||
<div class="p-3">
|
||||
<div class="text-xs font-medium text-gray-500 uppercase mb-3">Ketten-Glieder</div>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user