feat: 优化思维导图编辑和显示功能

- 修复编辑模式下表格渲染问题,使用新的节点结构逻辑
- 实现Markdown到HTML转换,支持表格和图片正确显示
- 添加generateTopicFromMarkdown函数,自动生成节点简短标题
- 优化保存逻辑,同时更新HTML、Markdown和topic字段
- 修复思维导图生成过程中的页面空白问题,优先使用增量更新
- 应用自定义紫色主题,统一线条和节点配色方案
- 简化控制台输出,只保留关键调试信息
This commit is contained in:
lixinran 2025-10-15 17:07:31 +08:00
parent 68b0ba1ccf
commit 318974511c
3 changed files with 376 additions and 145 deletions

Binary file not shown.

View File

@ -209,6 +209,18 @@ import '../lib/mind-elixir/dist/style.css';
import { renderMarkdownToHTML } from '../utils/markdownRenderer.js'; import { renderMarkdownToHTML } from '../utils/markdownRenderer.js';
import Vditor from 'vditor'; import Vditor from 'vditor';
import 'vditor/dist/index.css'; import 'vditor/dist/index.css';
import { marked } from 'marked';
// marked
marked.setOptions({
breaks: true, //
gfm: true, // GitHubMarkdown
tables: true, //
pedantic: false, //
sanitize: false, // HTML
smartLists: true, //
smartypants: false //
});
// 使VditorMarkdown // 使VditorMarkdown
const renderMarkdownWithVditor = async (markdown) => { const renderMarkdownWithVditor = async (markdown) => {
@ -445,41 +457,233 @@ const closeImagePreview = () => {
imagePreviewError.value = ''; imagePreviewError.value = '';
}; };
// HTMLMarkdown /**
const convertHTMLToMarkdown = (html) => { * 从Markdown内容生成简短标题
* 用于节点显示
*/
const generateTopicFromMarkdown = (markdown) => {
if (!markdown || typeof markdown !== 'string') {
return '';
}
try {
// Markdown
let text = markdown
//
.replace(/^#{1,6}\s+/gm, '')
//
.replace(/\*\*(.*?)\*\*/g, '$1')
.replace(/\*(.*?)\*/g, '$1')
//
.replace(/```[\s\S]*?```/g, '')
.replace(/`([^`]*)`/g, '$1')
//
.replace(/\[([^\]]+)\]\([^)]+\)/g, '$1')
//
.replace(/!\[([^\]]*)\]\([^)]+\)/g, '')
//
.replace(/^\|.*\|$/gm, '')
.replace(/^[-|:\s]+$/gm, '')
//
.replace(/^[-*+]\s+/gm, '')
.replace(/^\d+\.\s+/gm, '')
//
.replace(/^>\s*/gm, '')
//
.replace(/\n+/g, ' ')
.replace(/\s+/g, ' ')
.trim();
// 50
if (text.length > 50) {
text = text.substring(0, 50) + '...';
}
return text || '无标题';
} catch (error) {
console.error('❌ 生成标题失败:', error);
return '无标题';
}
};
/**
* Markdown转HTML转换函数
* 支持表格图片等复杂内容的转换
*/
const convertMarkdownToHTML = (markdown) => {
if (!markdown || typeof markdown !== 'string') {
return '';
}
try {
let html = markdown;
// -
// Markdown
html = html.replace(/\|(.+)\|\n\|[-\s|]+\|\n((?:\|.+\|\n?)*)/g, (match, header, rows) => {
const headers = header.split('|').map(h => h.trim()).filter(h => h);
const rowLines = rows.trim().split('\n').filter(line => line.trim());
let tableHTML = '<table class="markdown-table" style="border-collapse: collapse; width: 100%; margin: 1em 0;">\n';
//
if (headers.length > 0) {
tableHTML += '<thead><tr>';
headers.forEach(header => {
tableHTML += `<th style="border: 1px solid #ddd; padding: 8px; background: #f5f5f5; font-weight: bold;">${header}</th>`;
});
tableHTML += '</tr></thead>\n';
}
//
if (rowLines.length > 0) {
tableHTML += '<tbody>';
rowLines.forEach(row => {
const cells = row.split('|').map(c => c.trim()).filter(c => c);
if (cells.length > 0) {
tableHTML += '<tr>';
cells.forEach(cell => {
tableHTML += `<td style="border: 1px solid #ddd; padding: 8px;">${cell}</td>`;
});
tableHTML += '</tr>';
}
});
tableHTML += '</tbody>';
}
tableHTML += '</table>';
return tableHTML;
});
//
if (!html.includes('<table')) {
//
html = html.replace(/^([^:]+)[:]\s*(.+)$/gm, '<div style="display: flex; margin: 0.5em 0; border-bottom: 1px solid #eee; padding: 0.5em 0;"><div style="font-weight: bold; min-width: 120px;">$1:</div><div style="flex: 1;">$2</div></div>');
}
//
html = html.replace(/!\[([^\]]*)\]\(([^)]+)\)/g, '<img src="$2" alt="$1" style="max-width: 100%; height: auto; margin: 1em 0; border-radius: 4px;" />');
//
html = html.replace(/^### (.*$)/gim, '<h3>$1</h3>');
html = html.replace(/^## (.*$)/gim, '<h2>$1</h2>');
html = html.replace(/^# (.*$)/gim, '<h1>$1</h1>');
//
html = html.replace(/\*\*(.*?)\*\*/g, '<strong>$1</strong>');
//
html = html.replace(/\*(.*?)\*/g, '<em>$1</em>');
//
html = html.replace(/```([^`]*)```/g, '<pre style="background: #f5f5f5; padding: 1em; border-radius: 4px; overflow-x: auto;"><code>$1</code></pre>');
//
html = html.replace(/`([^`]*)`/g, '<code style="background: #f5f5f5; padding: 0.2em 0.4em; border-radius: 3px; font-family: monospace;">$1</code>');
//
html = html.replace(/\[([^\]]+)\]\(([^)]+)\)/g, '<a href="$2" style="color: #1a73e8; text-decoration: none;">$1</a>');
//
html = html.replace(/^- (.*$)/gim, '<li>$1</li>');
html = html.replace(/(<li>.*<\/li>)/s, '<ul style="margin: 1em 0; padding-left: 2em;">$1</ul>');
//
html = html.replace(/\n\n/g, '</p><p>');
html = html.replace(/\n/g, '<br>');
//
if (!html.startsWith('<')) {
html = '<p>' + html + '</p>';
}
return html;
} catch (error) {
console.error('❌ Markdown转HTML转换失败:', error);
return markdown; // 退Markdown
}
};
/**
* 改进的HTML转Markdown转换函数
* 支持表格图片等复杂内容的转换
*/
const convertHTMLToMarkdownImproved = (html) => {
if (!html || typeof html !== 'string') { if (!html || typeof html !== 'string') {
return ''; return '';
} }
try { try {
console.log('🔄 开始转换HTML到Markdown:', html.substring(0, 100) + '...'); // 使Vditorhtml2md
// 使Vditorhtml2md
if (typeof Vditor?.html2md === 'function') { if (typeof Vditor?.html2md === 'function') {
const markdown = Vditor.html2md(html); console.log('✅ 使用Vditor.html2md转换HTML');
console.log('✅ 使用Vditor.html2md转换成功:', markdown.substring(0, 100) + '...'); return Vditor.html2md(html);
return markdown;
} }
// 退 console.log('⚠️ Vditor.html2md不可用使用改进的转换逻辑');
console.log('⚠️ Vditor.html2md不可用使用简单转换逻辑');
let markdown = html // DOM
// - const tempDiv = document.createElement('div');
.replace(/<table[^>]*>/gi, '\n') tempDiv.innerHTML = html;
.replace(/<\/table>/gi, '\n')
.replace(/<thead[^>]*>/gi, '') let markdown = '';
.replace(/<\/thead>/gi, '')
.replace(/<tbody[^>]*>/gi, '') //
.replace(/<\/tbody>/gi, '') const tables = tempDiv.querySelectorAll('table');
.replace(/<tr[^>]*>/gi, '') tables.forEach((table, tableIndex) => {
.replace(/<\/tr>/gi, ' |\n') console.log(`📊 处理表格 ${tableIndex + 1}`);
.replace(/<th[^>]*>/gi, '| ')
.replace(/<\/th>/gi, ' ') //
.replace(/<td[^>]*>/gi, '| ') const thead = table.querySelector('thead');
.replace(/<\/td>/gi, ' ') if (thead) {
// const headerRow = thead.querySelector('tr');
.replace(/<img[^>]*src="([^"]+)"[^>]*alt="([^"]*)"[^>]*>/gi, '![$2]($1)') if (headerRow) {
.replace(/<img[^>]*src="([^"]+)"[^>]*>/gi, '![]($1)') const headers = Array.from(headerRow.querySelectorAll('th, td')).map(cell =>
(cell.textContent || '').trim().replace(/\|/g, '\\|')
);
markdown += '| ' + headers.join(' | ') + ' |\n';
markdown += '| ' + headers.map(() => '---').join(' | ') + ' |\n';
}
}
//
const tbody = table.querySelector('tbody') || table;
const rows = tbody.querySelectorAll('tr');
rows.forEach(row => {
// thead
if (thead && thead.contains(row)) return;
const cells = Array.from(row.querySelectorAll('td, th')).map(cell =>
(cell.textContent || '').trim().replace(/\|/g, '\\|')
);
if (cells.length > 0) {
markdown += '| ' + cells.join(' | ') + ' |\n';
}
});
markdown += '\n';
});
//
const images = tempDiv.querySelectorAll('img');
images.forEach(img => {
const src = img.src || img.getAttribute('src') || '';
const alt = img.alt || img.getAttribute('alt') || '';
if (src) {
markdown += `![${alt}](${src})\n\n`;
}
});
//
const processedDiv = tempDiv.cloneNode(true);
processedDiv.querySelectorAll('table, img').forEach(el => el.remove());
//
let remainingContent = processedDiv.innerHTML;
// HTMLMarkdown
remainingContent = remainingContent
// //
.replace(/<br\s*\/?>/gi, '\n') .replace(/<br\s*\/?>/gi, '\n')
.replace(/<\/p>/gi, '\n\n') .replace(/<\/p>/gi, '\n\n')
@ -494,48 +698,32 @@ const convertHTMLToMarkdown = (html) => {
.replace(/<\/ul>/gi, '\n') .replace(/<\/ul>/gi, '\n')
.replace(/<li[^>]*>/gi, '- ') .replace(/<li[^>]*>/gi, '- ')
.replace(/<\/li>/gi, '\n') .replace(/<\/li>/gi, '\n')
//
.replace(/<h1[^>]*>(.*?)<\/h1>/gi, '# $1\n\n')
.replace(/<h2[^>]*>(.*?)<\/h2>/gi, '## $1\n\n')
.replace(/<h3[^>]*>(.*?)<\/h3>/gi, '### $1\n\n')
.replace(/<h4[^>]*>(.*?)<\/h4>/gi, '#### $1\n\n')
.replace(/<h5[^>]*>(.*?)<\/h5>/gi, '##### $1\n\n')
.replace(/<h6[^>]*>(.*?)<\/h6>/gi, '###### $1\n\n')
//
.replace(/<a[^>]*href="([^"]*)"[^>]*>(.*?)<\/a>/gi, '[$2]($1)')
//
.replace(/<code[^>]*>(.*?)<\/code>/gi, '`$1`')
.replace(/<pre[^>]*>(.*?)<\/pre>/gi, '```\n$1\n```\n\n')
// //
.replace(/<[^>]+>/g, '') .replace(/<[^>]+>/g, '')
// //
.replace(/\n{3,}/g, '\n\n') .replace(/\n{3,}/g, '\n\n')
.trim(); .trim();
// - 线 markdown += remainingContent;
const lines = markdown.split('\n');
const processedLines = [];
let inTable = false;
for (let i = 0; i < lines.length; i++) { console.log('✅ HTML转Markdown转换完成:', markdown.substring(0, 200) + '...');
const line = lines[i];
if (line.includes('|') && line.trim().length > 0) {
if (!inTable) {
inTable = true;
processedLines.push(line);
// 线
const headerCells = line.split('|').filter(cell => cell.trim());
if (headerCells.length > 0) {
const separator = '| ' + headerCells.map(() => '---').join(' | ') + ' |';
processedLines.push(separator);
}
} else {
processedLines.push(line);
}
} else {
if (inTable) {
inTable = false;
}
processedLines.push(line);
}
}
markdown = processedLines.join('\n');
console.log('✅ 简单转换逻辑完成:', markdown.substring(0, 100) + '...');
return markdown; return markdown;
} catch (error) { } catch (error) {
console.error('❌ HTML转Markdown失败:', error); console.error('❌ HTML转Markdown转换失败:', error);
return html; // HTML return html; // 退HTML
} }
}; };
@ -565,15 +753,55 @@ const openRichTextEditor = (nodeObj, nodeElement) => {
allKeys: Object.keys(nodeObj) allKeys: Object.keys(nodeObj)
}); });
// HTMLMarkdown // 使
let htmlContent = '';
// 使dangerouslySetInnerHTMLWYSIWYG
if (nodeObj.dangerouslySetInnerHTML) { if (nodeObj.dangerouslySetInnerHTML) {
editorContent.value = convertHTMLToMarkdown(nodeObj.dangerouslySetInnerHTML); htmlContent = nodeObj.dangerouslySetInnerHTML;
console.log('📝 转换后的Markdown内容:', editorContent.value); console.log('📝 使用dangerouslySetInnerHTML内容:', htmlContent.substring(0, 200) + '...');
} else if (nodeObj.topic) {
editorContent.value = nodeObj.topic;
} else {
editorContent.value = '';
} }
// 使markdown
else if (nodeObj.markdown) {
console.log('📝 使用markdown内容转换为HTML:', nodeObj.markdown.substring(0, 200) + '...');
try {
htmlContent = marked.parse(nodeObj.markdown);
// dangerouslySetInnerHTML
nodeObj.dangerouslySetInnerHTML = htmlContent;
} catch (error) {
console.error('❌ Markdown转HTML失败:', error);
htmlContent = nodeObj.markdown;
}
}
// 退datatopic
else {
const markdownContent = nodeObj.data || nodeObj.topic || '';
console.log('📝 使用兼容模式从data/topic获取内容:', markdownContent.substring(0, 200) + '...');
// Markdown
const hasMarkdownContent = markdownContent.includes('|') && markdownContent.includes('-') || //
markdownContent.includes('![') || //
markdownContent.includes('#') || //
markdownContent.includes('**') || //
markdownContent.includes('`'); //
if (hasMarkdownContent) {
try {
htmlContent = marked.parse(markdownContent);
//
nodeObj.markdown = markdownContent;
nodeObj.dangerouslySetInnerHTML = htmlContent;
} catch (error) {
console.error('❌ Markdown转HTML失败:', error);
htmlContent = markdownContent;
}
} else {
htmlContent = markdownContent;
}
}
editorContent.value = htmlContent;
console.log('🎯 WYSIWYG模式HTML内容:', htmlContent.substring(0, 200) + '...');
// MindElixir // MindElixir
if (nodeObj.image && !editorContent.value.includes('![')) { if (nodeObj.image && !editorContent.value.includes('![')) {
@ -622,13 +850,6 @@ const initVditor = async () => {
return; return;
} }
console.log('🎯 开始初始化Vditor编辑器...');
console.log('🔍 vditorContainer元素:', vditorContainer.value);
console.log('🔍 容器可见性:', vditorContainer.value.offsetParent !== null);
console.log('🔍 容器尺寸:', {
width: vditorContainer.value.offsetWidth,
height: vditorContainer.value.offsetHeight
});
try { try {
// //
@ -638,7 +859,7 @@ const initVditor = async () => {
vditorInstance = new Vditor(vditorContainer.value, { vditorInstance = new Vditor(vditorContainer.value, {
height: 400, height: 400,
placeholder: '请输入节点内容...', placeholder: '请输入节点内容...',
mode: 'wysiwyg', // mode: 'wysiwyg', // 使HTML
theme: 'classic', theme: 'classic',
toolbarConfig: { toolbarConfig: {
pin: true // pin: true //
@ -691,17 +912,12 @@ const initVditor = async () => {
} }
}, },
after: () => { after: () => {
console.log('✅ Vditor编辑器初始化完成');
// //
setTimeout(() => { setTimeout(() => {
// VditorMarkdown/HTML // VditorMarkdown/HTML
if (editorContent.value && editorContent.value.trim()) { if (editorContent.value && editorContent.value.trim()) {
vditorInstance.setValue(editorContent.value); vditorInstance.setValue(editorContent.value);
console.log('✅ 内容已设置到WYSIWYG编辑器:', editorContent.value.substring(0, 100) + '...');
console.log('✅ 编辑器当前模式: wysiwyg (所见即所得模式)');
} else { } else {
console.warn('⚠️ editorContent.value为空设置空内容');
vditorInstance.setValue(''); vditorInstance.setValue('');
} }
@ -714,34 +930,18 @@ const initVditor = async () => {
// Markdown // Markdown
const markdownContent = vditorInstance.getValue(); const markdownContent = vditorInstance.getValue();
editorContent.value = markdownContent; editorContent.value = markdownContent;
console.log('📝 编辑器内容变化(Markdown):', markdownContent.substring(0, 50) + '...');
}); });
} else {
console.warn('⚠️ Vditor实例没有on方法');
} }
// //
setTimeout(() => { setTimeout(() => {
const toolbar = document.querySelector('.vditor-toolbar'); const toolbar = document.querySelector('.vditor-toolbar');
const editor = document.querySelector('.vditor-wysiwyg'); const editor = document.querySelector('.vditor-wysiwyg');
console.log('🔍 Vditor工具栏:', toolbar);
console.log('🔍 Vditor编辑器区域:', editor);
if (!toolbar || !editor) {
console.error('❌ Vditor组件没有正确渲染');
console.error('工具栏状态:', toolbar ? '存在' : '不存在');
console.error('编辑器状态:', editor ? '存在' : '不存在');
} else {
console.log('✅ Vditor组件渲染成功');
console.log('工具栏按钮数量:', toolbar.querySelectorAll('button').length);
console.log('工具栏高度:', toolbar.offsetHeight);
}
}, 100); }, 100);
}, 100); }, 100);
} }
}); });
console.log('✅ Vditor编辑器创建成功');
} catch (error) { } catch (error) {
console.error('❌ Vditor编辑器初始化失败:', error); console.error('❌ Vditor编辑器初始化失败:', error);
console.error('错误详情:', error.stack); console.error('错误详情:', error.stack);
@ -820,14 +1020,13 @@ const saveRichTextChanges = async () => {
} }
// 使VditorAPI // 使VditorAPI
const markdownContent = vditorInstance ? vditorInstance.getValue() : editorContent.value; const htmlContent = vditorInstance ? vditorInstance.getValue() : editorContent.value;
const htmlContent = vditorInstance ? vditorInstance.getHTML() : editorContent.value; const markdownContent = vditorInstance ? vditorInstance.getMarkdown() : '';
const contentToSave = markdownContent.trim() || '';
console.log('📝 获取到的Markdown内容:', contentToSave.substring(0, 100) + '...');
console.log('📝 获取到的HTML内容:', htmlContent.substring(0, 100) + '...'); console.log('📝 获取到的HTML内容:', htmlContent.substring(0, 100) + '...');
console.log('📝 获取到的Markdown内容:', markdownContent.substring(0, 100) + '...');
// // - 使
const titleChanged = editorTitle.value !== (currentNode.value.title || ''); const titleChanged = editorTitle.value !== (currentNode.value.title || '');
console.log('🔍 标题变化检查:', { console.log('🔍 标题变化检查:', {
editorTitle: editorTitle.value, editorTitle: editorTitle.value,
@ -835,10 +1034,11 @@ const saveRichTextChanges = async () => {
titleChanged: titleChanged titleChanged: titleChanged
}); });
// // -
currentNode.value.topic = contentToSave; // Markdown currentNode.value.dangerouslySetInnerHTML = htmlContent; // HTML
currentNode.value.markdown = markdownContent || htmlContent; // Markdown
currentNode.value.topic = generateTopicFromMarkdown(markdownContent || htmlContent); //
currentNode.value.title = editorTitle.value; // currentNode.value.title = editorTitle.value; //
currentNode.value.dangerouslySetInnerHTML = htmlContent; // HTML
// DOM // DOM
if (currentNodeElement.value) { if (currentNodeElement.value) {
@ -864,7 +1064,9 @@ const saveRichTextChanges = async () => {
newTitle: editorTitle.value, // 使 newTitle: editorTitle.value, // 使
newDes: currentNode.value.data?.des || "", newDes: currentNode.value.data?.des || "",
newParentId: currentNode.value.parentId || currentNode.value.parent?.id, newParentId: currentNode.value.parentId || currentNode.value.parent?.id,
newDangerouslySetInnerHTML: htmlContent || "" // newDangerouslySetInnerHTML: htmlContent || "", // HTML
newMarkdown: markdownContent || htmlContent, // Markdown
newTopic: currentNode.value.topic //
}; };
console.log("🔍 直接发送到后端的更新数据:", updateData); console.log("🔍 直接发送到后端的更新数据:", updateData);
@ -3656,24 +3858,18 @@ const openCustomEditModal = (nodeObj, nodeElement) => {
// Vditor // Vditor
nextTick(() => { nextTick(() => {
setTimeout(() => { setTimeout(() => {
console.log('🔄 准备初始化Vditor容器状态:', vditorContainer.value);
// //
if (vditorContainer.value && vditorContainer.value.offsetParent !== null) { if (vditorContainer.value && vditorContainer.value.offsetParent !== null) {
console.log('✅ 容器已可见开始初始化Vditor');
initVditor(); initVditor();
} else { } else {
console.warn('⚠️ 容器未准备好,延迟初始化');
// //
let attempts = 0; let attempts = 0;
const maxAttempts = 10; const maxAttempts = 10;
const checkContainer = () => { const checkContainer = () => {
attempts++; attempts++;
if (vditorContainer.value && vditorContainer.value.offsetParent !== null) { if (vditorContainer.value && vditorContainer.value.offsetParent !== null) {
console.log('✅ 容器在第', attempts, '次尝试后可见');
initVditor(); initVditor();
} else if (attempts < maxAttempts) { } else if (attempts < maxAttempts) {
console.log('🔄 第', attempts, '次检查,容器仍未准备好,继续等待...');
setTimeout(checkContainer, 100); setTimeout(checkContainer, 100);
} else { } else {
console.error('❌ 容器在', maxAttempts, '次尝试后仍未准备好'); console.error('❌ 容器在', maxAttempts, '次尝试后仍未准备好');
@ -4785,6 +4981,7 @@ const updateMindMapRealtime = async (data, title, eventDetail = null) => {
infinite: true, infinite: true,
maxScale: 5, maxScale: 5,
minScale: 0.1, minScale: 0.1,
theme: customTheme, // 使
markdown: (text, nodeObj) => { markdown: (text, nodeObj) => {
// markdown // markdown
if (text.includes('|') || text.includes('**') || text.includes('`') || text.includes('#') || text.includes('$') || text.includes('![')) { if (text.includes('|') || text.includes('**') || text.includes('`') || text.includes('#') || text.includes('$') || text.includes('![')) {
@ -4869,8 +5066,44 @@ const updateMindMapRealtime = async (data, title, eventDetail = null) => {
} }
} else { } else {
// // 使
console.log('🔄 执行完整更新'); console.log('🔄 尝试增量更新替代完整更新');
//
if (mindElixir.value && mindElixir.value.data && mindElixir.value.data.nodeData) {
console.log('✅ 使用增量更新,避免页面空白');
//
if (mindElixir.value.data.nodeData && data.topic) {
const rootNode = Object.values(mindElixir.value.data.nodeData)[0];
if (rootNode && rootNode.topic !== data.topic) {
rootNode.topic = data.topic;
// DOM
const rootElement = mindmapEl.value.querySelector(`[data-id="${rootNode.id}"]`);
if (rootElement) {
const textElement = rootElement.querySelector('.topic-text');
if (textElement) {
textElement.textContent = data.topic;
}
}
}
}
//
if (data.children && data.children.length > 0) {
updateNodesIncremental(data.children, mindElixir.value.data.nodeData);
}
//
if (currentPosition) {
setTimeout(() => {
restorePosition(currentPosition);
console.log('📍 优化增量更新后恢复位置');
}, 50);
}
} else {
//
console.log('⚠️ 无法增量更新,执行完整更新');
const currentId = String(currentMindmapId.value || ''); const currentId = String(currentMindmapId.value || '');
const tempId = currentId && currentId.startsWith('temp-') const tempId = currentId && currentId.startsWith('temp-')
@ -4901,6 +5134,7 @@ const updateMindMapRealtime = async (data, title, eventDetail = null) => {
}, 100); }, 100);
} }
} }
}
} catch (error) { } catch (error) {
console.error('❌ 更新思维导图数据失败:', error); console.error('❌ 更新思维导图数据失败:', error);

View File

@ -53,13 +53,10 @@ renderer.image = function(href, title, text) {
// 处理图片URL确保能正确显示 // 处理图片URL确保能正确显示
let processedUrl = hrefStr; let processedUrl = hrefStr;
// 暂时禁用代理URL转换直接使用原始URL
// 这样可以避免代理服务配置问题导致的图片显示异常
if (hrefStr.includes('cdn-mineru.openxlab.org.cn')) { if (hrefStr.includes('cdn-mineru.openxlab.org.cn')) {
// 直接使用原始URL不进行代理转换 // 将外部CDN URL转换为代理URL
processedUrl = hrefStr; const urlPath = hrefStr.replace('https://cdn-mineru.openxlab.org.cn', '');
console.log('🖼️ 使用原始CDN URL:', processedUrl); processedUrl = `/proxy-image${urlPath}`;
} }
// 生成图片HTML // 生成图片HTML