'commit'
This commit is contained in:
@@ -283,11 +283,20 @@ createApp({
|
||||
const reader = response.body.getReader();
|
||||
const decoder = new TextDecoder();
|
||||
|
||||
let fullText = "";
|
||||
while (true) {
|
||||
const {done, value} = await reader.read();
|
||||
if (done) break;
|
||||
const chunk = decoder.decode(value, {stream: true});
|
||||
aiText.value += chunk;
|
||||
fullText += chunk;
|
||||
|
||||
if (fullText.includes("---CLEAR_PREVIOUS_HINTS---")) {
|
||||
const parts = fullText.split("---CLEAR_PREVIOUS_HINTS---");
|
||||
aiText.value = parts[parts.length - 1];
|
||||
} else {
|
||||
aiText.value = fullText;
|
||||
}
|
||||
|
||||
await Vue.nextTick();
|
||||
if (aiBoxRef.value) {
|
||||
aiBoxRef.value.scrollTop = aiBoxRef.value.scrollHeight;
|
||||
@@ -325,7 +334,7 @@ createApp({
|
||||
});
|
||||
}
|
||||
|
||||
// 降级用的简易 Markdown 解析器
|
||||
// 降级用的简易 Markdown 解析器 (增强版)
|
||||
const simpleMarkdown = (text) => {
|
||||
if (!text) return '';
|
||||
let lines = text.split('\n');
|
||||
@@ -334,6 +343,7 @@ createApp({
|
||||
const parseInline = (str) => {
|
||||
return str
|
||||
.replace(/\*\*(.*?)\*\*/g, '<strong>$1</strong>')
|
||||
.replace(/\*(.*?)\*/g, '<em>$1</em>')
|
||||
.replace(/`(.*?)`/g, '<code style="background:rgba(148, 163, 184, 0.1); padding:2px 4px; border-radius:4px;">$1</code>');
|
||||
};
|
||||
for (let line of lines) {
|
||||
@@ -343,13 +353,28 @@ createApp({
|
||||
html += '<br>';
|
||||
continue;
|
||||
}
|
||||
if (trimmed.startsWith('### ')) {
|
||||
if (trimmed.startsWith('# ')) {
|
||||
if (inList) { html += '</ul>'; inList = false; }
|
||||
html += `<h1>${parseInline(trimmed.substring(2))}</h1>`;
|
||||
} else if (trimmed.startsWith('## ')) {
|
||||
if (inList) { html += '</ul>'; inList = false; }
|
||||
html += `<h2>${parseInline(trimmed.substring(3))}</h2>`;
|
||||
} else 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 (trimmed.startsWith('|') && trimmed.endsWith('|')) {
|
||||
// 简单的表格识别 (仅作示意,复杂表格仍需 marked)
|
||||
if (inList) { html += '</ul>'; inList = false; }
|
||||
let cells = trimmed.split('|').filter(c => c.trim() || c === '');
|
||||
html += '<div style="display:flex; border-bottom:1px solid #334155; padding:4px;">';
|
||||
cells.forEach(c => {
|
||||
html += `<div style="flex:1; padding:4px;">${parseInline(c.trim())}</div>`;
|
||||
});
|
||||
html += '</div>';
|
||||
} else {
|
||||
if (inList) { html += '</ul>'; inList = false; }
|
||||
html += `<p>${parseInline(trimmed)}</p>`;
|
||||
@@ -363,44 +388,45 @@ createApp({
|
||||
const renderMarkdownAndLatex = (text) => {
|
||||
if (!text) return '';
|
||||
|
||||
// 如果包含提示信息且还没被清除,先简单处理显示
|
||||
if (text.includes('正在收集各供应商价格数据') || text.includes('正在进行 AI 深度分析')) {
|
||||
return `<div style="color: #64748b; font-style: italic;">${text.replace(/\n/g, '<br>')}</div>`;
|
||||
}
|
||||
|
||||
try {
|
||||
// 1. 处理 LaTeX (简单替换,先处理 $$ 再处理 $)
|
||||
let processedText = text;
|
||||
|
||||
// 处理块级 LaTeX: $$ ... $$
|
||||
processedText = processedText.replace(/\$\$\s*([\s\S]*?)\s*\$\$/g, (match, formula) => {
|
||||
try {
|
||||
if (typeof katex !== 'undefined') {
|
||||
// 1. 处理 LaTeX (如果 katex 加载成功)
|
||||
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>';
|
||||
}
|
||||
return match;
|
||||
} catch (e) {
|
||||
return match;
|
||||
}
|
||||
});
|
||||
|
||||
// 处理行内 LaTeX: $ ... $
|
||||
processedText = processedText.replace(/\$([^\$\n]+?)\$/g, (match, formula) => {
|
||||
try {
|
||||
if (typeof katex !== 'undefined') {
|
||||
} catch (e) { return match; }
|
||||
});
|
||||
|
||||
// 处理行内 LaTeX: $ ... $
|
||||
processedText = processedText.replace(/\$([^\$\n]+?)\$/g, (match, formula) => {
|
||||
try {
|
||||
return katex.renderToString(formula, { displayMode: false, throwOnError: false });
|
||||
}
|
||||
return match;
|
||||
} catch (e) {
|
||||
return match;
|
||||
}
|
||||
});
|
||||
|
||||
// 2. 使用 marked 解析 Markdown
|
||||
if (typeof marked !== 'undefined') {
|
||||
return marked.parse(processedText);
|
||||
} else {
|
||||
// 降级使用之前的 simpleMarkdown
|
||||
return simpleMarkdown(processedText);
|
||||
} catch (e) { return match; }
|
||||
});
|
||||
}
|
||||
|
||||
// 2. 使用 marked 解析 Markdown (优先使用)
|
||||
if (typeof marked !== 'undefined') {
|
||||
// 兼容不同版本的 marked (UMD 版本中 marked 可能是函数或对象)
|
||||
const parseFn = (typeof marked.parse === 'function') ? marked.parse.bind(marked) : (typeof marked === 'function' ? marked : null);
|
||||
if (parseFn) {
|
||||
return parseFn(processedText);
|
||||
}
|
||||
}
|
||||
|
||||
// 3. 降级使用改进后的 simpleMarkdown
|
||||
return simpleMarkdown(processedText);
|
||||
} catch (e) {
|
||||
console.error('Markdown/LaTeX rendering error:', e);
|
||||
return text;
|
||||
console.error('Markdown rendering error:', e);
|
||||
return simpleMarkdown(text);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user