'commit'
This commit is contained in:
Binary file not shown.
@@ -99,6 +99,48 @@ body {
|
|||||||
min-width: 0;
|
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 {
|
.right-panel {
|
||||||
flex: 2;
|
flex: 2;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|||||||
@@ -7,7 +7,6 @@
|
|||||||
<link rel="stylesheet" href="css/element-plus.index.css">
|
<link rel="stylesheet" href="css/element-plus.index.css">
|
||||||
<link rel="stylesheet" href="css/app.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">
|
<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/katex.min.js"></script>
|
||||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.16.9/contrib/auto-render.min.js"></script>
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.16.9/contrib/auto-render.min.js"></script>
|
||||||
</head>
|
</head>
|
||||||
|
|||||||
104
static/js/app.js
104
static/js/app.js
@@ -437,11 +437,10 @@ createApp({
|
|||||||
// Computed Properties (Markdown)
|
// Computed Properties (Markdown)
|
||||||
// ==========================================
|
// ==========================================
|
||||||
|
|
||||||
|
/*
|
||||||
marked.use({
|
marked.use({
|
||||||
gfm: true,
|
gfm: true,
|
||||||
breaks: true,
|
breaks: true,
|
||||||
mangle: false,
|
|
||||||
headerIds: false,
|
|
||||||
renderer: {
|
renderer: {
|
||||||
code(code, language) {
|
code(code, language) {
|
||||||
if (language === 'echarts') {
|
if (language === 'echarts') {
|
||||||
@@ -452,6 +451,7 @@ createApp({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
*/
|
||||||
|
|
||||||
const renderedAiText = computed(() => {
|
const renderedAiText = computed(() => {
|
||||||
if (!aiText.value) return "";
|
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(() => {
|
const renderedSummary = computed(() => {
|
||||||
if (!summaryText.value) return '';
|
if (!summaryText.value) return '';
|
||||||
|
|
||||||
|
// 优先使用内置解析器,确保绝对可用
|
||||||
try {
|
try {
|
||||||
return marked.parse(summaryText.value);
|
return simpleMarkdown(summaryText.value);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
console.error("Simple markdown error:", e);
|
||||||
return summaryText.value;
|
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) => {
|
const statusColor = (status) => {
|
||||||
switch(status) {
|
switch(status) {
|
||||||
case 'COMPLETED': return '#10b981';
|
case 'COMPLETED': return '#10b981';
|
||||||
@@ -672,6 +761,15 @@ createApp({
|
|||||||
// Douyin
|
// Douyin
|
||||||
shareText, douyinLoading, douyinRecords,
|
shareText, douyinLoading, douyinRecords,
|
||||||
startParsing, fetchDouyinRecords, deleteRecord, statusColor, statusType, formatDate,
|
startParsing, fetchDouyinRecords, deleteRecord, statusColor, statusType, formatDate,
|
||||||
|
|
||||||
|
// Douyin Summary
|
||||||
|
showSummaryDialog,
|
||||||
|
summaryLoading,
|
||||||
|
summaryText,
|
||||||
|
renderedSummary,
|
||||||
|
openSummaryDialog,
|
||||||
|
handleSummaryClose,
|
||||||
|
fetchDouyinSummary,
|
||||||
// Ad
|
// Ad
|
||||||
showAd, adCountdown, closeAd
|
showAd, adCountdown, closeAd
|
||||||
};
|
};
|
||||||
|
|||||||
31
test_marked.html
Normal file
31
test_marked.html
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/marked/12.0.0/marked.min.js"></script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="output"></div>
|
||||||
|
<div id="error" style="color: red;"></div>
|
||||||
|
<script>
|
||||||
|
try {
|
||||||
|
marked.use({
|
||||||
|
gfm: true,
|
||||||
|
breaks: true,
|
||||||
|
renderer: {
|
||||||
|
code(code, language) {
|
||||||
|
if (language === 'echarts') {
|
||||||
|
return 'ECHARTS';
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
const text = "- **Test Bold**";
|
||||||
|
const html = marked.parse(text);
|
||||||
|
document.getElementById('output').innerHTML = html;
|
||||||
|
} catch (e) {
|
||||||
|
document.getElementById('error').innerText = e.toString();
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
Reference in New Issue
Block a user