|
|
@@ -34,7 +34,7 @@
|
|
|
|
|
|
<div class="detail-divider"></div>
|
|
|
|
|
|
- <div class="detail-text" v-html="renderMath(item.highlighted_text || item.text || '')"></div>
|
|
|
+ <div class="detail-text" v-html="renderMarkdown(item.highlighted_text || item.text || '')"></div>
|
|
|
</div>
|
|
|
</div>
|
|
|
</template>
|
|
|
@@ -44,6 +44,14 @@ import { ref } from 'vue'
|
|
|
import { useRouter, useRoute } from 'vue-router'
|
|
|
import { ArrowLeft, Calendar, Document } from '@element-plus/icons-vue'
|
|
|
import katex from 'katex'
|
|
|
+import MarkdownIt from 'markdown-it'
|
|
|
+
|
|
|
+const md = new MarkdownIt({
|
|
|
+ html: true, // 保留 <em> 高亮标签
|
|
|
+ breaks: true, // 换行符转 <br>
|
|
|
+ linkify: false,
|
|
|
+ typographer: false,
|
|
|
+})
|
|
|
|
|
|
const router = useRouter()
|
|
|
const route = useRoute()
|
|
|
@@ -62,23 +70,26 @@ function formatDate(dateStr: string): string {
|
|
|
return dateStr.split(' ')[0]
|
|
|
}
|
|
|
|
|
|
-function renderMath(text: string): string {
|
|
|
+function renderMarkdown(text: string): string {
|
|
|
if (!text) return ''
|
|
|
- let result = text.replace(/\$\$([\s\S]*?)\$\$/g, (_, math) => {
|
|
|
+ // 先渲染 Markdown(## 标题、列表等),再处理 KaTeX 公式
|
|
|
+ let html = md.render(text)
|
|
|
+ // KaTeX 公式渲染
|
|
|
+ html = html.replace(/\$\$([\s\S]*?)\$\$/g, (_, math) => {
|
|
|
try {
|
|
|
return katex.renderToString(math, { throwOnError: false, displayMode: true })
|
|
|
} catch {
|
|
|
return `<span class="katex-error">${_}</span>`
|
|
|
}
|
|
|
})
|
|
|
- result = result.replace(/\$([\s\S]*?)\$/g, (_, math) => {
|
|
|
+ html = html.replace(/\$([\s\S]*?)\$/g, (_, math) => {
|
|
|
try {
|
|
|
return katex.renderToString(math, { throwOnError: false, displayMode: false })
|
|
|
} catch {
|
|
|
return `<span class="katex-error">${_}</span>`
|
|
|
}
|
|
|
})
|
|
|
- return result
|
|
|
+ return html
|
|
|
}
|
|
|
</script>
|
|
|
|
|
|
@@ -182,6 +193,87 @@ function renderMath(text: string): string {
|
|
|
line-height: 2;
|
|
|
}
|
|
|
|
|
|
+/* Markdown 渲染样式 */
|
|
|
+.detail-text :deep(h1),
|
|
|
+.detail-text :deep(h2),
|
|
|
+.detail-text :deep(h3),
|
|
|
+.detail-text :deep(h4),
|
|
|
+.detail-text :deep(h5),
|
|
|
+.detail-text :deep(h6) {
|
|
|
+ color: #1a1a1a;
|
|
|
+ font-weight: 600;
|
|
|
+ margin: 1.5em 0 0.6em;
|
|
|
+ line-height: 1.5;
|
|
|
+}
|
|
|
+.detail-text :deep(h1) { font-size: 1.5em; }
|
|
|
+.detail-text :deep(h2) { font-size: 1.3em; }
|
|
|
+.detail-text :deep(h3) { font-size: 1.15em; }
|
|
|
+.detail-text :deep(h4),
|
|
|
+.detail-text :deep(h5),
|
|
|
+.detail-text :deep(h6) { font-size: 1em; }
|
|
|
+
|
|
|
+.detail-text :deep(p) {
|
|
|
+ margin: 0.6em 0;
|
|
|
+}
|
|
|
+
|
|
|
+.detail-text :deep(ul),
|
|
|
+.detail-text :deep(ol) {
|
|
|
+ padding-left: 1.8em;
|
|
|
+ margin: 0.6em 0;
|
|
|
+}
|
|
|
+.detail-text :deep(li) {
|
|
|
+ margin: 0.3em 0;
|
|
|
+}
|
|
|
+
|
|
|
+.detail-text :deep(pre) {
|
|
|
+ background: #f6f8fa;
|
|
|
+ border-radius: 6px;
|
|
|
+ padding: 12px 16px;
|
|
|
+ overflow-x: auto;
|
|
|
+ margin: 1em 0;
|
|
|
+}
|
|
|
+.detail-text :deep(code) {
|
|
|
+ font-family: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, monospace;
|
|
|
+ font-size: 0.9em;
|
|
|
+}
|
|
|
+.detail-text :deep(p code),
|
|
|
+.detail-text :deep(li code) {
|
|
|
+ background: #f0f0f0;
|
|
|
+ padding: 2px 6px;
|
|
|
+ border-radius: 3px;
|
|
|
+ color: #d63384;
|
|
|
+}
|
|
|
+
|
|
|
+.detail-text :deep(blockquote) {
|
|
|
+ border-left: 4px solid #e8e8e8;
|
|
|
+ padding-left: 16px;
|
|
|
+ margin: 1em 0;
|
|
|
+ color: #666;
|
|
|
+}
|
|
|
+
|
|
|
+.detail-text :deep(table) {
|
|
|
+ border-collapse: collapse;
|
|
|
+ width: 100%;
|
|
|
+ margin: 1em 0;
|
|
|
+}
|
|
|
+.detail-text :deep(th),
|
|
|
+.detail-text :deep(td) {
|
|
|
+ border: 1px solid #e8e8e8;
|
|
|
+ padding: 8px 12px;
|
|
|
+ text-align: left;
|
|
|
+}
|
|
|
+.detail-text :deep(th) {
|
|
|
+ background: #f6f8fa;
|
|
|
+ font-weight: 600;
|
|
|
+}
|
|
|
+
|
|
|
+.detail-text :deep(hr) {
|
|
|
+ border: none;
|
|
|
+ border-top: 1px solid #e8e8e8;
|
|
|
+ margin: 1.5em 0;
|
|
|
+}
|
|
|
+
|
|
|
+/* 高亮保持 */
|
|
|
.detail-text :deep(em) {
|
|
|
color: #f5a623;
|
|
|
font-style: normal;
|