feat: add copy function for mermaid diagram
This commit is contained in:
parent
9cb127f14e
commit
7d048872e1
@ -402,6 +402,7 @@
|
|||||||
"citations": "References",
|
"citations": "References",
|
||||||
"copied": "Copied!",
|
"copied": "Copied!",
|
||||||
"copy.success": "Copied!",
|
"copy.success": "Copied!",
|
||||||
|
"copy.failed": "Copy failed",
|
||||||
"error.chunk_overlap_too_large": "Chunk overlap cannot be greater than chunk size",
|
"error.chunk_overlap_too_large": "Chunk overlap cannot be greater than chunk size",
|
||||||
"error.dimension_too_large": "Content size is too large",
|
"error.dimension_too_large": "Content size is too large",
|
||||||
"error.enter.api.host": "Please enter your API host first",
|
"error.enter.api.host": "Please enter your API host first",
|
||||||
|
|||||||
@ -402,6 +402,7 @@
|
|||||||
"citations": "参考文献",
|
"citations": "参考文献",
|
||||||
"copied": "コピーしました!",
|
"copied": "コピーしました!",
|
||||||
"copy.success": "コピーしました!",
|
"copy.success": "コピーしました!",
|
||||||
|
"copy.failed": "コピーに失敗しました",
|
||||||
"error.chunk_overlap_too_large": "チャンクの重なりは、チャンクサイズを超えることはできません",
|
"error.chunk_overlap_too_large": "チャンクの重なりは、チャンクサイズを超えることはできません",
|
||||||
"error.dimension_too_large": "内容のサイズが大きすぎます",
|
"error.dimension_too_large": "内容のサイズが大きすぎます",
|
||||||
"error.enter.api.host": "APIホストを入力してください",
|
"error.enter.api.host": "APIホストを入力してください",
|
||||||
|
|||||||
@ -408,6 +408,7 @@
|
|||||||
"citations": "Источники",
|
"citations": "Источники",
|
||||||
"copied": "Скопировано!",
|
"copied": "Скопировано!",
|
||||||
"copy.success": "Скопировано!",
|
"copy.success": "Скопировано!",
|
||||||
|
"copy.failed": "Не удалось скопировать",
|
||||||
"error.chunk_overlap_too_large": "Перекрытие фрагментов не может быть больше размера фрагмента.",
|
"error.chunk_overlap_too_large": "Перекрытие фрагментов не может быть больше размера фрагмента.",
|
||||||
"error.dimension_too_large": "Размер содержимого слишком велик",
|
"error.dimension_too_large": "Размер содержимого слишком велик",
|
||||||
"error.enter.api.host": "Пожалуйста, введите ваш API хост",
|
"error.enter.api.host": "Пожалуйста, введите ваш API хост",
|
||||||
|
|||||||
@ -402,6 +402,7 @@
|
|||||||
"citations": "引用内容",
|
"citations": "引用内容",
|
||||||
"copied": "已复制",
|
"copied": "已复制",
|
||||||
"copy.success": "复制成功",
|
"copy.success": "复制成功",
|
||||||
|
"copy.failed": "复制失败",
|
||||||
"error.chunk_overlap_too_large": "分段重叠不能大于分段大小",
|
"error.chunk_overlap_too_large": "分段重叠不能大于分段大小",
|
||||||
"error.dimension_too_large": "内容尺寸过大",
|
"error.dimension_too_large": "内容尺寸过大",
|
||||||
"error.enter.api.host": "请输入您的 API 地址",
|
"error.enter.api.host": "请输入您的 API 地址",
|
||||||
|
|||||||
@ -400,8 +400,9 @@
|
|||||||
"backup.success": "備份成功",
|
"backup.success": "備份成功",
|
||||||
"chat.completion.paused": "聊天完成已暫停",
|
"chat.completion.paused": "聊天完成已暫停",
|
||||||
"citations": "參考文獻",
|
"citations": "參考文獻",
|
||||||
"copied": "已複製",
|
"copied": "已複製!",
|
||||||
"copy.success": "複製成功",
|
"copy.success": "已複製!",
|
||||||
|
"copy.failed": "複製失敗",
|
||||||
"error.chunk_overlap_too_large": "分段重疊不能大於分段大小",
|
"error.chunk_overlap_too_large": "分段重疊不能大於分段大小",
|
||||||
"error.dimension_too_large": "內容尺寸過大",
|
"error.dimension_too_large": "內容尺寸過大",
|
||||||
"error.enter.api.host": "請先輸入您的 API 主機地址",
|
"error.enter.api.host": "請先輸入您的 API 主機地址",
|
||||||
|
|||||||
@ -51,6 +51,46 @@ const PopupContainer: React.FC<Props> = ({ 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<Blob>((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') => {
|
const handleDownload = async (format: 'svg' | 'png') => {
|
||||||
try {
|
try {
|
||||||
const element = document.getElementById(mermaidId)
|
const element = document.getElementById(mermaidId)
|
||||||
@ -132,6 +172,7 @@ const PopupContainer: React.FC<Props> = ({ resolve, chart }) => {
|
|||||||
<>
|
<>
|
||||||
<Button onClick={() => handleZoom(0.1)}>{t('mermaid.resize.zoom-in')}</Button>
|
<Button onClick={() => handleZoom(0.1)}>{t('mermaid.resize.zoom-in')}</Button>
|
||||||
<Button onClick={() => handleZoom(-0.1)}>{t('mermaid.resize.zoom-out')}</Button>
|
<Button onClick={() => handleZoom(-0.1)}>{t('mermaid.resize.zoom-out')}</Button>
|
||||||
|
<Button onClick={() => handleCopyImage()}>{t('common.copy')}</Button>
|
||||||
<Button onClick={() => handleDownload('svg')}>{t('mermaid.download.svg')}</Button>
|
<Button onClick={() => handleDownload('svg')}>{t('mermaid.download.svg')}</Button>
|
||||||
<Button onClick={() => handleDownload('png')}>{t('mermaid.download.png')}</Button>
|
<Button onClick={() => handleDownload('png')}>{t('mermaid.download.png')}</Button>
|
||||||
</>
|
</>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user