This commit is contained in:
HuangHai
2026-01-21 10:10:30 +08:00
parent 0f4435b51c
commit 9f483c0643
2 changed files with 117 additions and 103 deletions

View File

@@ -164,39 +164,53 @@
<script src="js/element-plus.zh-cn.min.js"></script>
<script src="js/axios.min.js"></script>
<!-- Markdown & LaTeX Support -->
<link rel="stylesheet" href="https://unpkg.com/github-markdown-css@5.5.1/github-markdown-dark.css">
<link rel="stylesheet" href="https://unpkg.com/katex@0.16.9/dist/katex.min.css">
<script src="https://unpkg.com/katex@0.16.9/dist/katex.min.js"></script>
<script src="https://unpkg.com/marked@12.0.0/lib/marked.umd.js"></script>
<link rel="stylesheet" href="https://gcore.jsdelivr.net/npm/github-markdown-css@5.5.1/github-markdown-dark.css">
<link rel="stylesheet" href="https://gcore.jsdelivr.net/npm/katex@0.16.9/dist/katex.min.css">
<script src="https://gcore.jsdelivr.net/npm/katex@0.16.9/dist/katex.min.js"></script>
<script src="https://gcore.jsdelivr.net/npm/marked/marked.min.js"></script>
<style>
/* 适配对话框中的 Markdown 样式 */
.markdown-body {
box-sizing: border-box;
min-width: 200px;
max-width: 980px;
margin: 0 auto;
padding: 15px;
background-color: transparent !important;
padding: 24px;
background-color: #0f172a !important;
color: #cbd5e1 !important;
font-size: 16px;
line-height: 1.6;
}
/* 深度覆盖:确保列表和加粗在任何情况下都可见 */
.markdown-body ul {
list-style-type: disc !important;
padding-left: 2em !important;
margin-top: 0.5em !important;
margin-bottom: 0.5em !important;
}
.markdown-body li {
display: list-item !important;
margin-bottom: 0.25em !important;
}
.markdown-body strong {
font-weight: bold !important;
color: #f1f5f9 !important;
}
.markdown-body p {
margin-bottom: 1em !important;
}
.el-dialog {
background-color: #1e293b !important;
border: 1px solid #334155;
border-radius: 12px;
}
.el-dialog__title {
color: #f1f5f9 !important;
}
.el-dialog__body {
color: #cbd5e1 !important;
}
.cursor-blink {
color: #3b82f6;
font-weight: bold;
animation: blink 1s step-end infinite;
}
@keyframes blink {
from, to { opacity: 1; }
50% { opacity: 0; }
background-color: #0f172a !important;
padding: 0 !important;
}
</style>
<script src="js/douyin.js"></script>

View File

@@ -1,5 +1,75 @@
const { createApp, ref, computed, onMounted } = Vue;
// 1. 全局渲染器 - 纯手写的高鲁棒性解析器,不再依赖 marked
const globalRenderMarkdown = (text) => {
if (!text) return '';
// 0. 预处理:去除 AI 可能返回的代码块标记
let cleanText = text.trim();
// 去除开头的 ```markdown 或 ```
cleanText = cleanText.replace(/^```(markdown)?\s*/i, '');
// 去除结尾的 ```
cleanText = cleanText.replace(/```\s*$/, '');
// 1. 预处理:按行分割
const lines = cleanText.split('\n');
let html = '';
let inList = false;
for (let i = 0; i < lines.length; i++) {
let line = lines[i];
// 关键:去除行首尾空白,解决缩进导致的解析失败
let trimmed = line.trim();
// 空行处理
if (!trimmed) {
if (inList) { html += '</ul>\n'; inList = false; }
continue; // 忽略空行,或者可以加 <br>
}
// 2. 内联格式处理(加粗、代码、链接)
// 加粗 **text** -> <strong>text</strong>
trimmed = trimmed.replace(/\*\*(.*?)\*\*/g, '<strong>$1</strong>');
// 代码 `text` -> <code>text</code>
trimmed = trimmed.replace(/`([^`]+)`/g, '<code>$1</code>');
// 3. 块级元素处理
// 标题 ### Title
if (trimmed.startsWith('###')) {
if (inList) { html += '</ul>\n'; inList = false; }
html += `<h3>${trimmed.replace(/^###\s*/, '')}</h3>`;
}
else if (trimmed.startsWith('##')) {
if (inList) { html += '</ul>\n'; inList = false; }
html += `<h2>${trimmed.replace(/^##\s*/, '')}</h2>`;
}
else if (trimmed.startsWith('#')) {
if (inList) { html += '</ul>\n'; inList = false; }
html += `<h1>${trimmed.replace(/^#\s*/, '')}</h1>`;
}
// 列表 - Item 或 * Item
else if (trimmed.startsWith('- ') || trimmed.startsWith('* ')) {
if (!inList) { html += '<ul>\n'; inList = true; }
html += `<li>${trimmed.substring(2)}</li>`;
}
// 数字列表 1. Item
else if (/^\d+\.\s/.test(trimmed)) {
// 简单起见,数字列表也用 ul或者你可以维护一个 ordered list 状态
if (!inList) { html += '<ul>\n'; inList = true; }
html += `<li>${trimmed.replace(/^\d+\.\s/, '')}</li>`;
}
// 普通段落
else {
if (inList) { html += '</ul>\n'; inList = false; }
html += `<p>${trimmed}</p>`;
}
}
if (inList) { html += '</ul>\n'; }
return html;
};
createApp({
setup() {
const apiBase = ref(window.location.origin || "http://localhost:8000");
@@ -15,96 +85,26 @@ createApp({
const summaryLoading = ref(false);
const summaryText = ref('');
// 降级用的简易 Markdown 解析
const simpleMarkdown = (text) => {
if (!text) return '';
let lines = text.split('\n');
let html = '';
let inList = false;
const parseInline = (str) => {
return str
.replace(/\*\*(.*?)\*\*/g, '<strong>$1</strong>')
.replace(/`(.*?)`/g, '<code style="background:rgba(148, 163, 184, 0.1); padding:2px 4px; border-radius:4px;">$1</code>');
};
for (let line of lines) {
let trimmed = line.trim();
if (!trimmed) {
if (inList) { html += '</ul>'; inList = false; }
html += '<br>';
continue;
}
if (trimmed.startsWith('### ')) {
if (inList) { html += '</ul>'; inList = false; }
html += `<h3>${parseInline(trimmed.substring(4))}</h3>`;
} else if (trimmed.startsWith('- ') || /^\d+\./.test(trimmed)) {
if (!inList) { html += '<ul>'; inList = true; }
let content = trimmed.replace(/^(- |\d+\. )/, '');
html += `<li>${parseInline(content)}</li>`;
} else {
if (inList) { html += '</ul>'; inList = false; }
html += `<p>${parseInline(trimmed)}</p>`;
}
}
if (inList) html += '</ul>';
return html;
};
// Configure Marked
if (typeof marked !== 'undefined') {
marked.use({
gfm: true,
breaks: true
});
}
// 增强的 Markdown & LaTeX 解析器
const renderMarkdownAndLatex = (text) => {
if (!text) return '';
try {
let processedText = text;
// 1. 处理 LaTeX
if (typeof katex !== 'undefined') {
// 处理块级 LaTeX: $$ ... $$
processedText = processedText.replace(/\$\$\s*([\s\S]*?)\s*\$\$/g, (match, formula) => {
try {
return '<div class="katex-block">' + katex.renderToString(formula, { displayMode: true, throwOnError: false }) + '</div>';
} catch (e) { return match; }
});
// 处理行内 LaTeX: $ ... $
processedText = processedText.replace(/\$([^\$\n]+?)\$/g, (match, formula) => {
try {
return katex.renderToString(formula, { displayMode: false, throwOnError: false });
} catch (e) { return match; }
});
}
// 2. 使用 marked 解析 Markdown
if (typeof marked !== 'undefined') {
// marked v12+ 使用 marked.parse
return marked.parse(processedText);
} else {
// 降级使用 simpleMarkdown
return simpleMarkdown(processedText);
}
} catch (e) {
console.error('Markdown rendering error:', e);
// 最后的兜底:如果 marked 报错,尝试用 simpleMarkdown
try {
return simpleMarkdown(text);
} catch (e2) {
return text;
}
}
};
// 使用全局渲染
const renderedSummary = computed(() => {
if (!summaryText.value) return '';
return renderMarkdownAndLatex(summaryText.value);
const html = globalRenderMarkdown(summaryText.value);
return html;
});
// 这里的配置仍然保留,作为双重保险
if (typeof marked !== 'undefined') {
const m = (typeof marked.marked === 'function') ? marked.marked : marked;
if (m.setOptions) {
m.setOptions({
gfm: true,
breaks: true,
mangle: false,
headerIds: false
});
}
}
// Methods
const startParsing = async () => {
if (!shareText.value.trim()) return;