This commit is contained in:
HuangHai
2026-01-21 07:29:31 +08:00
parent 21fb8b39d8
commit 9efe1d3872
5 changed files with 174 additions and 4 deletions

View File

@@ -99,6 +99,48 @@ body {
min-width: 0;
}
/* Markdown Styles */
.markdown-body {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif;
font-size: 16px;
line-height: 1.6;
word-wrap: break-word;
color: #334155; /* Slate 700 */
}
.markdown-body h1,
.markdown-body h2,
.markdown-body h3 {
margin-top: 24px;
margin-bottom: 16px;
font-weight: 600;
line-height: 1.25;
color: #0f172a; /* Slate 900 */
}
.markdown-body ul,
.markdown-body ol {
padding-left: 2em;
margin-top: 0;
margin-bottom: 16px;
}
.markdown-body li {
margin: 0.25em 0;
}
.markdown-body strong {
font-weight: 600;
color: #0f172a;
}
.markdown-body blockquote {
padding: 0 1em;
color: #64748b;
border-left: 0.25em solid #cbd5e1;
margin: 0 0 16px 0;
}
.right-panel {
flex: 2;
display: flex;

View File

@@ -7,7 +7,6 @@
<link rel="stylesheet" href="css/element-plus.index.css">
<link rel="stylesheet" href="css/app.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.16.9/katex.min.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/marked/12.0.0/marked.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.16.9/katex.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.16.9/contrib/auto-render.min.js"></script>
</head>

View File

@@ -437,11 +437,10 @@ createApp({
// Computed Properties (Markdown)
// ==========================================
/*
marked.use({
gfm: true,
breaks: true,
mangle: false,
headerIds: false,
renderer: {
code(code, language) {
if (language === 'echarts') {
@@ -452,6 +451,7 @@ createApp({
}
}
});
*/
const renderedAiText = computed(() => {
if (!aiText.value) return "";
@@ -473,11 +473,57 @@ createApp({
}
});
// 内置简易 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>') // Bold
.replace(/`(.*?)`/g, '<code style="background:#f1f5f9; padding:2px 4px; border-radius:4px;">$1</code>'); // Code
};
for (let line of lines) {
let trimmed = line.trim();
// 忽略空行
if (!trimmed) {
continue;
}
// 标题处理 (###)
if (trimmed.startsWith('### ')) {
if (inList) { html += '</ul>'; inList = false; }
html += `<h3 style="margin-top:16px; margin-bottom:8px; font-weight:bold; font-size:1.1em;">${parseInline(trimmed.substring(4))}</h3>`;
}
// 列表项处理 (- 或 1.)
else if (trimmed.startsWith('- ') || /^\d+\./.test(trimmed)) {
if (!inList) { html += '<ul style="padding-left:20px; margin:0;">'; inList = true; }
let content = trimmed.replace(/^(- |\d+\. )/, '');
html += `<li style="margin-bottom:4px;">${parseInline(content)}</li>`;
}
// 普通段落
else {
if (inList) { html += '</ul>'; inList = false; }
html += `<p style="margin-bottom:8px;">${parseInline(trimmed)}</p>`;
}
}
if (inList) html += '</ul>';
return html;
};
const renderedSummary = computed(() => {
if (!summaryText.value) return '';
// 优先使用内置解析器,确保绝对可用
try {
return marked.parse(summaryText.value);
return simpleMarkdown(summaryText.value);
} catch (e) {
console.error("Simple markdown error:", e);
return summaryText.value;
}
});
@@ -586,6 +632,49 @@ createApp({
}
};
const openSummaryDialog = () => {
showSummaryDialog.value = true;
// Optionally auto-start if empty
if (!summaryText.value) {
fetchDouyinSummary();
}
};
const handleSummaryClose = () => {
showSummaryDialog.value = false;
};
const fetchDouyinSummary = async () => {
if (summaryLoading.value) return;
summaryText.value = "";
summaryLoading.value = true;
try {
// Pass empty IDs to summarize all/latest
const response = await fetch(apiBase.value + "/api/douyin/summary", {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({ids: []})
});
if (!response.body) return;
const reader = response.body.getReader();
const decoder = new TextDecoder();
while (true) {
const {done, value} = await reader.read();
if (done) break;
const chunk = decoder.decode(value, {stream: true});
summaryText.value += chunk;
// Auto scroll? The user can scroll the dialog.
}
} catch (e) {
console.error(e);
summaryText.value += "\n(总结过程出错: " + e.message + ")";
} finally {
summaryLoading.value = false;
}
};
const statusColor = (status) => {
switch(status) {
case 'COMPLETED': return '#10b981';
@@ -672,6 +761,15 @@ createApp({
// Douyin
shareText, douyinLoading, douyinRecords,
startParsing, fetchDouyinRecords, deleteRecord, statusColor, statusType, formatDate,
// Douyin Summary
showSummaryDialog,
summaryLoading,
summaryText,
renderedSummary,
openSummaryDialog,
handleSummaryClose,
fetchDouyinSummary,
// Ad
showAd, adCountdown, closeAd
};