62e12686e3
- 新增 MarkdownRenderer.vue 组件,基于 marked 解析 GFM
- 学习残片/报告历史列表:纯文本 {{ }} 替换为 MarkdownRenderer
- ReviewDetail.vue content-body:p 标签逐行渲染替换为 MarkdownRenderer
- 结束会话总结框:增加「编辑/预览」切换,预览模式实时渲染 markdown
- 学习预期展示也改为 MarkdownRenderer
134 lines
2.3 KiB
Vue
134 lines
2.3 KiB
Vue
<script setup lang="ts">
|
|
import { computed } from "vue";
|
|
import { marked } from "marked";
|
|
|
|
const props = withDefaults(defineProps<{
|
|
content: string;
|
|
}>(), {
|
|
content: "",
|
|
});
|
|
|
|
const rendered = computed(() => {
|
|
if (!props.content) return "";
|
|
return marked.parse(props.content, { breaks: true, gfm: true });
|
|
});
|
|
</script>
|
|
|
|
<template>
|
|
<div class="markdown-body" v-html="rendered"></div>
|
|
</template>
|
|
|
|
<style scoped>
|
|
.markdown-body {
|
|
line-height: 1.8;
|
|
color: #333;
|
|
word-break: break-word;
|
|
}
|
|
|
|
.markdown-body :deep(h1),
|
|
.markdown-body :deep(h2),
|
|
.markdown-body :deep(h3),
|
|
.markdown-body :deep(h4) {
|
|
margin: 0.75em 0 0.5em;
|
|
color: var(--green-900, #1b5e20);
|
|
font-weight: 600;
|
|
}
|
|
|
|
.markdown-body :deep(h1) { font-size: 1.4em; }
|
|
.markdown-body :deep(h2) { font-size: 1.25em; }
|
|
.markdown-body :deep(h3) { font-size: 1.1em; }
|
|
|
|
.markdown-body :deep(p) {
|
|
margin: 0.4em 0;
|
|
line-height: 1.8;
|
|
}
|
|
|
|
.markdown-body :deep(ul),
|
|
.markdown-body :deep(ol) {
|
|
margin: 0.4em 0;
|
|
padding-left: 1.5em;
|
|
}
|
|
|
|
.markdown-body :deep(li) {
|
|
margin: 0.2em 0;
|
|
line-height: 1.7;
|
|
}
|
|
|
|
.markdown-body :deep(code) {
|
|
background: #f0f4f0;
|
|
padding: 0.15em 0.4em;
|
|
border-radius: 3px;
|
|
font-size: 0.9em;
|
|
color: #c62828;
|
|
}
|
|
|
|
.markdown-body :deep(pre) {
|
|
background: #f5f7f5;
|
|
padding: 12px 16px;
|
|
border-radius: 6px;
|
|
overflow-x: auto;
|
|
border: 1px solid #e0e8e0;
|
|
margin: 0.6em 0;
|
|
}
|
|
|
|
.markdown-body :deep(pre code) {
|
|
background: none;
|
|
padding: 0;
|
|
color: #333;
|
|
font-size: 0.85em;
|
|
}
|
|
|
|
.markdown-body :deep(blockquote) {
|
|
margin: 0.5em 0;
|
|
padding: 0.5em 1em;
|
|
border-left: 3px solid var(--green-600, #2f8f68);
|
|
background: #f1f8e9;
|
|
color: #555;
|
|
}
|
|
|
|
.markdown-body :deep(a) {
|
|
color: var(--green-600, #2f8f68);
|
|
text-decoration: underline;
|
|
}
|
|
|
|
.markdown-body :deep(a:hover) {
|
|
color: var(--green-900, #1b5e20);
|
|
}
|
|
|
|
.markdown-body :deep(strong) {
|
|
font-weight: 600;
|
|
color: #222;
|
|
}
|
|
|
|
.markdown-body :deep(hr) {
|
|
border: none;
|
|
border-top: 1px solid #e0e8e0;
|
|
margin: 1em 0;
|
|
}
|
|
|
|
.markdown-body :deep(table) {
|
|
border-collapse: collapse;
|
|
width: 100%;
|
|
margin: 0.6em 0;
|
|
font-size: 0.9em;
|
|
}
|
|
|
|
.markdown-body :deep(th),
|
|
.markdown-body :deep(td) {
|
|
border: 1px solid #d0d8d0;
|
|
padding: 6px 10px;
|
|
text-align: left;
|
|
}
|
|
|
|
.markdown-body :deep(th) {
|
|
background: #e8f5e9;
|
|
font-weight: 600;
|
|
}
|
|
|
|
.markdown-body :deep(img) {
|
|
max-width: 100%;
|
|
border-radius: 4px;
|
|
margin: 0.5em 0;
|
|
}
|
|
</style>
|