diff --git a/src/renderer/src/i18n/locales/en-us.json b/src/renderer/src/i18n/locales/en-us.json index 4a06b56c..bcdebb02 100644 --- a/src/renderer/src/i18n/locales/en-us.json +++ b/src/renderer/src/i18n/locales/en-us.json @@ -402,6 +402,7 @@ "citations": "References", "copied": "Copied!", "copy.success": "Copied!", + "copy.failed": "Copy failed", "error.chunk_overlap_too_large": "Chunk overlap cannot be greater than chunk size", "error.dimension_too_large": "Content size is too large", "error.enter.api.host": "Please enter your API host first", diff --git a/src/renderer/src/i18n/locales/ja-jp.json b/src/renderer/src/i18n/locales/ja-jp.json index d075a7ce..115aeb11 100644 --- a/src/renderer/src/i18n/locales/ja-jp.json +++ b/src/renderer/src/i18n/locales/ja-jp.json @@ -402,6 +402,7 @@ "citations": "参考文献", "copied": "コピーしました!", "copy.success": "コピーしました!", + "copy.failed": "コピーに失敗しました", "error.chunk_overlap_too_large": "チャンクの重なりは、チャンクサイズを超えることはできません", "error.dimension_too_large": "内容のサイズが大きすぎます", "error.enter.api.host": "APIホストを入力してください", diff --git a/src/renderer/src/i18n/locales/ru-ru.json b/src/renderer/src/i18n/locales/ru-ru.json index 53e300b4..179540cb 100644 --- a/src/renderer/src/i18n/locales/ru-ru.json +++ b/src/renderer/src/i18n/locales/ru-ru.json @@ -408,6 +408,7 @@ "citations": "Источники", "copied": "Скопировано!", "copy.success": "Скопировано!", + "copy.failed": "Не удалось скопировать", "error.chunk_overlap_too_large": "Перекрытие фрагментов не может быть больше размера фрагмента.", "error.dimension_too_large": "Размер содержимого слишком велик", "error.enter.api.host": "Пожалуйста, введите ваш API хост", diff --git a/src/renderer/src/i18n/locales/zh-cn.json b/src/renderer/src/i18n/locales/zh-cn.json index 6bcf2ff6..90bff49e 100644 --- a/src/renderer/src/i18n/locales/zh-cn.json +++ b/src/renderer/src/i18n/locales/zh-cn.json @@ -402,6 +402,7 @@ "citations": "引用内容", "copied": "已复制", "copy.success": "复制成功", + "copy.failed": "复制失败", "error.chunk_overlap_too_large": "分段重叠不能大于分段大小", "error.dimension_too_large": "内容尺寸过大", "error.enter.api.host": "请输入您的 API 地址", diff --git a/src/renderer/src/i18n/locales/zh-tw.json b/src/renderer/src/i18n/locales/zh-tw.json index 00785547..ca021830 100644 --- a/src/renderer/src/i18n/locales/zh-tw.json +++ b/src/renderer/src/i18n/locales/zh-tw.json @@ -400,8 +400,9 @@ "backup.success": "備份成功", "chat.completion.paused": "聊天完成已暫停", "citations": "參考文獻", - "copied": "已複製", - "copy.success": "複製成功", + "copied": "已複製!", + "copy.success": "已複製!", + "copy.failed": "複製失敗", "error.chunk_overlap_too_large": "分段重疊不能大於分段大小", "error.dimension_too_large": "內容尺寸過大", "error.enter.api.host": "請先輸入您的 API 主機地址", diff --git a/src/renderer/src/pages/home/Markdown/MermaidPopup.tsx b/src/renderer/src/pages/home/Markdown/MermaidPopup.tsx index 7c6b1676..55b3db34 100644 --- a/src/renderer/src/pages/home/Markdown/MermaidPopup.tsx +++ b/src/renderer/src/pages/home/Markdown/MermaidPopup.tsx @@ -51,6 +51,46 @@ const PopupContainer: React.FC = ({ resolve, chart }) => { } } + const handleCopyImage = async () => { + try { + const element = document.getElementById(mermaidId) + if (!element) return + + const svgElement = element.querySelector('svg') + if (!svgElement) return + + const canvas = document.createElement('canvas') + const ctx = canvas.getContext('2d') + const img = new Image() + img.crossOrigin = 'anonymous' + + const viewBox = svgElement.getAttribute('viewBox')?.split(' ').map(Number) || [] + const width = viewBox[2] || svgElement.clientWidth || svgElement.getBoundingClientRect().width + const height = viewBox[3] || svgElement.clientHeight || svgElement.getBoundingClientRect().height + + const svgData = new XMLSerializer().serializeToString(svgElement) + const svgBase64 = `data:image/svg+xml;base64,${btoa(unescape(encodeURIComponent(svgData)))}` + + img.onload = async () => { + const scale = 3 + canvas.width = width * scale + canvas.height = height * scale + + if (ctx) { + ctx.scale(scale, scale) + ctx.drawImage(img, 0, 0, width, height) + const blob = await new Promise((resolve) => canvas.toBlob((b) => resolve(b!), 'image/png')) + await navigator.clipboard.write([new ClipboardItem({ 'image/png': blob })]) + window.message.success(t('message.copy.success')) + } + } + img.src = svgBase64 + } catch (error) { + console.error('Copy failed:', error) + window.message.error(t('message.copy.failed')) + } + } + const handleDownload = async (format: 'svg' | 'png') => { try { const element = document.getElementById(mermaidId) @@ -132,6 +172,7 @@ const PopupContainer: React.FC = ({ resolve, chart }) => { <> +