update
This commit is contained in:
@@ -94,12 +94,12 @@ export async function chatBaustein({ topic, baustein, section, messages, provide
|
||||
export async function pruefeBaustein({
|
||||
topic, baustein, section, provider,
|
||||
aktion = 'frage', frage = '', letzte_bewertung = '', score_vor_frage = 0, streak = 0,
|
||||
tier2 = false, tier3 = false, messages = [],
|
||||
tier2 = false, tier3 = false, messages = [], gruendlich = false,
|
||||
}) {
|
||||
const res = await fetch(`${BASE}/bausteine/pruefung`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ topic, baustein, section, aktion, frage, letzte_bewertung, score_vor_frage, streak, tier2, tier3, messages, provider }),
|
||||
body: JSON.stringify({ topic, baustein, section, aktion, frage, letzte_bewertung, score_vor_frage, streak, tier2, tier3, messages, provider, gruendlich }),
|
||||
})
|
||||
return jsonOrThrow(res)
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<script setup>
|
||||
import { computed, nextTick, ref } from 'vue'
|
||||
import { computed, nextTick, onMounted, onUnmounted, ref } from 'vue'
|
||||
import { chatBaustein, createVertiefung, fetchVertiefung, pruefeBaustein } from '../api.js'
|
||||
import { renderMarkdown } from '../markdown.js'
|
||||
import { useChat, istUnten } from '../composables/useChat.js'
|
||||
@@ -245,15 +245,17 @@ function antwortPayload() {
|
||||
}
|
||||
|
||||
// Hintergrund: voller Bewerter+Kritiker. Persistiert serverseitig; korrigiert die Anzeige bei Abweichung.
|
||||
async function verdictPruefen() {
|
||||
// gruendlich=true: starkes Modell (role guide), manuell ausgelöst → sichtbarer Ladezustand.
|
||||
async function verdictPruefen(gruendlich = false) {
|
||||
const meine = ++pruefenRun
|
||||
const ziel = letzteFeedbackMsg
|
||||
const warAbsolviert = st.value.absolviert
|
||||
const warVerstanden = st.value.verstanden
|
||||
if (gruendlich) pruefLoading.value = true
|
||||
try {
|
||||
const res = await pruefeBaustein({
|
||||
topic: props.topic, baustein: props.baustein, section: props.section,
|
||||
provider: props.provider, messages: pruefDialog(), ...antwortPayload(), aktion: 'antwort_pruefen',
|
||||
provider: props.provider, messages: pruefDialog(), ...antwortPayload(), aktion: 'antwort_pruefen', gruendlich,
|
||||
})
|
||||
if (meine !== pruefenRun) return // eine neuere Bewertung läuft → diese verwerfen
|
||||
// Streak driftfrei aus streakVorFrage neu setzen; Reset nur am Deckel der
|
||||
@@ -275,6 +277,8 @@ async function verdictPruefen() {
|
||||
}
|
||||
} catch {
|
||||
if (meine === pruefenRun && ziel) ziel.geprueft = true
|
||||
} finally {
|
||||
if (gruendlich && meine === pruefenRun) pruefLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
@@ -286,9 +290,39 @@ function antwortAbgeben() {
|
||||
pruefSenden(antwortPayload(), bewerten)
|
||||
}
|
||||
|
||||
function neuBewerten() {
|
||||
// „Gründlich prüfen": dieselbe Antwort, aber vom starken Modell (role guide) verbindlich neu bewerten.
|
||||
function gruendlichPruefen() {
|
||||
if (pruefLoading.value) return
|
||||
pruefSenden(antwortPayload(), bewerten)
|
||||
verdictPruefen(true)
|
||||
}
|
||||
|
||||
// Abbruch wie im Chat: Run-Counter hochzählen → laufendes Ergebnis (pruefSenden
|
||||
// und verdictPruefen) wird verworfen, Buttons sofort frei. Agent läuft serverseitig aus.
|
||||
function pruefAbbrechen() {
|
||||
if (!pruefLoading.value) return
|
||||
pruefRun++
|
||||
pruefenRun++
|
||||
pruefLoading.value = false
|
||||
pruefMessages.value.push({ role: 'assistant', kind: 'fehler', content: 'Abgebrochen.' })
|
||||
}
|
||||
|
||||
// ESC bricht ab — window-Listener, da nach Button-Klick der Fokus das Panel verlässt.
|
||||
function onWindowKey(e) {
|
||||
if (e.key === 'Escape' && pruefLoading.value) { e.preventDefault(); pruefAbbrechen() }
|
||||
}
|
||||
onMounted(() => window.addEventListener('keydown', onWindowKey))
|
||||
onUnmounted(() => window.removeEventListener('keydown', onWindowKey))
|
||||
|
||||
// ALT+1 Nachfragen/Nachhaken · ALT+2 primär (Antwort abgeben / Nächste Frage) · ALT+3 Gründlich prüfen.
|
||||
function onPruefKey(e) {
|
||||
if (!e.altKey || e.repeat) return
|
||||
if (e.key === '1') { e.preventDefault(); nachfragen() }
|
||||
else if (e.key === '2') {
|
||||
e.preventDefault()
|
||||
pruefPhase.value === 'frage_offen' ? antwortAbgeben() : naechsteFrageZeigen()
|
||||
} else if (e.key === '3' && pruefPhase.value === 'bewertet') {
|
||||
e.preventDefault(); gruendlichPruefen()
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -357,7 +391,7 @@ function neuBewerten() {
|
||||
</div>
|
||||
|
||||
<!-- Prüfung: gesteuerter Dialog -->
|
||||
<div v-else>
|
||||
<div v-else @keydown="onPruefKey">
|
||||
<p class="bp-hint">
|
||||
<template v-if="st.gemeistert">✓✓✓ Gemeistert ({{ MEISTERN }}/{{ MEISTERN }}) — Max. Du kannst dich weiter prüfen, ohne Punkte.</template>
|
||||
<template v-else-if="st.verstanden && tier3">Meisterpfad: {{ st.gute_antworten }}/{{ MEISTERN }}. Richtig = +1, falsch = −2 (nicht unter {{ MAX }}). Bei {{ MEISTERN }} gemeistert.</template>
|
||||
@@ -379,7 +413,8 @@ function neuBewerten() {
|
||||
|
||||
<!-- Phase idle: Frage anfordern -->
|
||||
<div v-if="pruefPhase === 'idle'" class="bp-actions">
|
||||
<button class="bp-action primary" :disabled="pruefLoading" @click="frageAnfordern">Frage anfordern</button>
|
||||
<button v-if="pruefLoading" class="bp-action cancel" @click="pruefAbbrechen">Abbrechen</button>
|
||||
<button v-else class="bp-action primary" @click="frageAnfordern">Frage anfordern</button>
|
||||
</div>
|
||||
|
||||
<!-- Phase frage_offen / bewertet: Textfeld + Aktionen -->
|
||||
@@ -393,14 +428,15 @@ function neuBewerten() {
|
||||
></textarea>
|
||||
</div>
|
||||
<div class="bp-actions">
|
||||
<template v-if="pruefPhase === 'frage_offen'">
|
||||
<button class="bp-action" :disabled="pruefLoading || !pruefInput.trim()" @click="nachfragen">Nachfragen</button>
|
||||
<button class="bp-action primary" :disabled="pruefLoading || !pruefInput.trim()" @click="antwortAbgeben">Antwort abgeben</button>
|
||||
<button v-if="pruefLoading" class="bp-action cancel" @click="pruefAbbrechen">Abbrechen</button>
|
||||
<template v-else-if="pruefPhase === 'frage_offen'">
|
||||
<button class="bp-action" :disabled="!pruefInput.trim()" @click="nachfragen">Nachfragen</button>
|
||||
<button class="bp-action primary" :disabled="!pruefInput.trim()" @click="antwortAbgeben">Antwort abgeben</button>
|
||||
</template>
|
||||
<template v-else>
|
||||
<button class="bp-action" :disabled="pruefLoading || !pruefInput.trim()" @click="nachfragen">Nachhaken</button>
|
||||
<button class="bp-action" :disabled="pruefLoading" @click="neuBewerten">Neu bewerten</button>
|
||||
<button class="bp-action primary" :disabled="pruefLoading" @click="naechsteFrageZeigen">Nächste Frage</button>
|
||||
<button class="bp-action" :disabled="!pruefInput.trim()" @click="nachfragen">Nachhaken</button>
|
||||
<button class="bp-action" @click="gruendlichPruefen">Gründlich prüfen</button>
|
||||
<button class="bp-action primary" @click="naechsteFrageZeigen">Nächste Frage</button>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
@@ -463,6 +499,7 @@ function neuBewerten() {
|
||||
.bp-action:disabled { opacity: 0.5; cursor: default; }
|
||||
.bp-action.primary { background: var(--accent); border-color: var(--accent); color: var(--on-accent); }
|
||||
.bp-action.primary:hover { background: var(--accent-hover); border-color: var(--accent-hover); }
|
||||
.bp-action.cancel { background: var(--danger); border-color: var(--danger); color: var(--on-accent); }
|
||||
|
||||
.bp-actions { display: flex; flex-wrap: wrap; gap: 0.4rem; margin-top: 0.5rem; }
|
||||
.bp-actions .bp-action { margin-top: 0; }
|
||||
|
||||
Reference in New Issue
Block a user