update
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
<script setup>
|
||||
import BausteinPanel from './BausteinPanel.vue'
|
||||
import MermaidView from './MermaidView.vue'
|
||||
import { renderMarkdown } from '../markdown.js'
|
||||
|
||||
const props = defineProps({
|
||||
@@ -88,7 +89,8 @@ const standFarbe = computed(() => {
|
||||
</div>
|
||||
<div class="fokus-body">
|
||||
<div ref="guideEl" class="fokus-col left">
|
||||
<div class="markdown" v-html="renderMarkdown(ansicht === 'kompakt' ? (baustein.kompakt || baustein.md) : baustein.md)"></div>
|
||||
<MermaidView v-if="ansicht === 'grafik'" :code="baustein.grafik || ''" />
|
||||
<div v-else class="markdown" v-html="renderMarkdown(ansicht === 'kompakt' ? (baustein.kompakt || baustein.md) : baustein.md)"></div>
|
||||
</div>
|
||||
<div ref="rightEl" class="fokus-col right">
|
||||
<BausteinPanel
|
||||
|
||||
@@ -74,9 +74,10 @@ const aktSchwer = computed(() => {
|
||||
return schwer.value
|
||||
})
|
||||
const modusRegel = computed(() => {
|
||||
if (zeigeForm.value === 'quiz') return aktSchwer.value ? 'x von 4 · +3/−1' : '1 von 4 · +1/−1'
|
||||
if (zeigeForm.value === 'lueckentext') return aktSchwer.value ? 'frei tippen · +3/−1' : 'Begriff aus 4 · +1/−1'
|
||||
return '+1/+2/+3 · Nachfragen max +1 · schwach −1'
|
||||
const m = imZufall.value ? '−3' : '−1' // Zufallband: Fehler kostet −3
|
||||
if (zeigeForm.value === 'quiz') return aktSchwer.value ? `x von 4 · +3/${m}` : `1 von 4 · +1/${m}`
|
||||
if (zeigeForm.value === 'lueckentext') return aktSchwer.value ? `frei tippen · +3/${m}` : `Begriff aus 4 · +1/${m}`
|
||||
return imZufall.value ? '+1/+2/+3 · Fehler −3' : '+1/+2/+3 · Nachfragen max +1 · schwach −1'
|
||||
})
|
||||
// Ende des aktuellen Bands (nächster Meilenstein).
|
||||
const bandZiel = computed(() => {
|
||||
|
||||
41
frontend/src/components/MermaidView.vue
Normal file
41
frontend/src/components/MermaidView.vue
Normal file
@@ -0,0 +1,41 @@
|
||||
<script setup>
|
||||
import { ref, watch, onMounted } from 'vue'
|
||||
import mermaid from 'mermaid'
|
||||
|
||||
mermaid.initialize({ startOnLoad: false, securityLevel: 'strict', theme: 'neutral' })
|
||||
|
||||
const props = defineProps({ code: { type: String, default: '' } })
|
||||
const svg = ref('')
|
||||
const fehler = ref(false)
|
||||
let n = 0
|
||||
|
||||
// Async rendern; bricht das Mermaid-Parsing (kaputte Syntax) → Fallback statt Absturz.
|
||||
async function render() {
|
||||
const code = (props.code || '').trim()
|
||||
svg.value = ''
|
||||
fehler.value = false
|
||||
if (!code) { fehler.value = true; return }
|
||||
try {
|
||||
const { svg: out } = await mermaid.render(`mmd-${Date.now()}-${n++}`, code)
|
||||
svg.value = out
|
||||
} catch {
|
||||
fehler.value = true
|
||||
}
|
||||
}
|
||||
|
||||
watch(() => props.code, render)
|
||||
onMounted(render)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="mermaid-view">
|
||||
<div v-if="svg" v-html="svg"></div>
|
||||
<p v-else class="mermaid-fallback">Grafik nicht verfügbar — Guide neu bauen.</p>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.mermaid-view { display: flex; justify-content: center; padding: 0.5rem 0; }
|
||||
.mermaid-view :deep(svg) { max-width: 100%; height: auto; }
|
||||
.mermaid-fallback { color: var(--text-muted); font-size: 0.85rem; padding: 1rem 0; }
|
||||
</style>
|
||||
@@ -5,6 +5,7 @@ import { renderMarkdown } from '../markdown.js'
|
||||
import { useChat } from '../composables/useChat.js'
|
||||
import BausteinPanel from './BausteinPanel.vue'
|
||||
import BausteinFokus from './BausteinFokus.vue'
|
||||
import MermaidView from './MermaidView.vue'
|
||||
|
||||
const props = defineProps({
|
||||
previewGuide: { type: Object, default: null },
|
||||
@@ -204,7 +205,8 @@ function extractContext() {
|
||||
<span v-else-if="lernstand[s.title]?.verstanden" class="baustein-done verstanden" title="Vollständig verstanden (10/10)">✓✓ Verstanden</span>
|
||||
<span v-else-if="lernstand[s.title]?.absolviert" class="baustein-done" title="Prüfung bestanden">✓ Absolviert</span>
|
||||
</h3>
|
||||
<div class="section-body markdown" v-html="renderMarkdown(!isOnePager && ansichtModus === 'kompakt' ? (s.kompakt || s.md) : s.md)"></div>
|
||||
<MermaidView v-if="!isOnePager && ansichtModus === 'grafik'" :code="s.grafik || ''" />
|
||||
<div v-else class="section-body markdown" v-html="renderMarkdown(!isOnePager && ansichtModus === 'kompakt' ? (s.kompakt || s.md) : s.md)"></div>
|
||||
<BausteinPanel
|
||||
v-if="!isOnePager"
|
||||
mode="trigger"
|
||||
|
||||
@@ -312,6 +312,14 @@ function saveQuelle() {
|
||||
<rect x="2" y="12.9" width="8" height="1.4" rx="0.7" />
|
||||
</svg>
|
||||
</button>
|
||||
<button :class="{ active: ansichtModus === 'grafik' }" title="Grafik (Diagramm)" @click="emit('setAnsicht', 'grafik')">
|
||||
<svg viewBox="0 0 16 16" width="14" height="14" aria-hidden="true">
|
||||
<circle cx="4" cy="4" r="2" />
|
||||
<circle cx="12" cy="4" r="2" />
|
||||
<circle cx="8" cy="12" r="2" />
|
||||
<path d="M4 6 L8 10 M12 6 L8 10" stroke="currentColor" stroke-width="1.3" fill="none" />
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
<button class="new-topic-toggle" :class="{ active: dlg }" title="Thema erstellen" @click="toggleErstellen">+</button>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user