From e295922209fb87c6dcd68ea1560fd16c3e6d808c Mon Sep 17 00:00:00 2001
From: dongyukun <1208714201@qq.com>
Date: 星期五, 27 六月 2025 09:36:51 +0800
Subject: [PATCH] Merge remote-tracking branch 'origin/feature/ai'

---
 src/views/ai/mindmap/index/components/Right.vue |   60 ++++++++++++++++++++++++++----------------------------------
 1 files changed, 26 insertions(+), 34 deletions(-)

diff --git a/src/views/ai/mindmap/index/components/Right.vue b/src/views/ai/mindmap/index/components/Right.vue
index 0550650..b1d04de 100644
--- a/src/views/ai/mindmap/index/components/Right.vue
+++ b/src/views/ai/mindmap/index/components/Right.vue
@@ -4,7 +4,7 @@
       <h3 class="m-0 px-7 shrink-0 flex items-center justify-between">
         <span>思维导图预览</span>
         <!-- 展示在右上角 -->
-        <el-button type="primary" v-show="isEnd" @click="downloadImage" size="small">
+        <el-button v-show="isEnd" size="small" type="primary" @click="downloadImage">
           <template #icon>
             <Icon icon="ph:copy-bold" />
           </template>
@@ -19,33 +19,33 @@
         <div class="flex flex-col items-center justify-center" v-html="html"></div>
       </div>
 
-      <div ref="mindmapRef" class="wh-full">
-        <svg ref="svgRef" class="w-full" :style="{ height: `${contentAreaHeight}px` }" />
+      <div ref="mindMapRef" class="wh-full">
+        <svg ref="svgRef" :style="{ height: `${contentAreaHeight}px` }" class="w-full" />
         <div ref="toolBarRef" class="absolute bottom-[10px] right-5"></div>
       </div>
     </div>
   </el-card>
 </template>
 
-<script setup lang="ts">
+<script lang="ts" setup>
 import { Markmap } from 'markmap-view'
 import { Transformer } from 'markmap-lib'
 import { Toolbar } from 'markmap-toolbar'
 import markdownit from 'markdown-it'
+import download from '@/utils/download'
 
 const md = markdownit()
 const message = useMessage() // 消息弹窗
 
-// TODO @hhero:mindmap 改成 mindMap 更精准哈
 const props = defineProps<{
-  mindmapResult: string // 生成结果 TODO @hhero 改成 generatedContent 会不会好点
+  generatedContent: string // 生成结果
   isEnd: boolean // 是否结束
   isGenerating: boolean // 是否正在生成
   isStart: boolean // 开始状态,开始时需要清除 html
 }>()
-const contentRef = ref<HTMLDivElement>() // 右侧出来header以下的区域
+const contentRef = ref<HTMLDivElement>() // 右侧出来 header 以下的区域
 const mdContainerRef = ref<HTMLDivElement>() // markdown 的容器,用来滚动到底下的
-const mindmapRef = ref<HTMLDivElement>() // 思维导图的容器
+const mindMapRef = ref<HTMLDivElement>() // 思维导图的容器
 const svgRef = ref<SVGElement>() // 思维导图的渲染 svg
 const toolBarRef = ref<HTMLDivElement>() // 思维导图右下角的工具栏,缩放等
 const html = ref('') // 生成过程中的文本
@@ -66,15 +66,16 @@
   }
 })
 
-watch(props, ({ mindmapResult, isGenerating, isEnd, isStart }) => {
+watch(props, ({ generatedContent, isGenerating, isEnd, isStart }) => {
   // 开始生成的时候清空一下 markdown 的内容
   if (isStart) {
     html.value = ''
   }
   // 生成内容的时候使用 markdown 来渲染
   if (isGenerating) {
-    html.value = md.render(mindmapResult)
+    html.value = md.render(generatedContent)
   }
+  // 生成结束时更新思维导图
   if (isEnd) {
     update()
   }
@@ -83,7 +84,7 @@
 /** 更新思维导图的展示 */
 const update = () => {
   try {
-    const { root } = transformer.transform(processContent(props.mindmapResult))
+    const { root } = transformer.transform(processContent(props.generatedContent))
     markMap?.setData(root)
     markMap?.fit()
   } catch (e) {
@@ -105,32 +106,19 @@
   return arr.join('\n')
 }
 
-/** 下载图片 */
-// TODO @hhhero:可以抽到 download 这个里面,src/utils/download.ts 么?复用 image 方法?
-// download SVG to png file
+/** 下载图片:download SVG to png file */
 const downloadImage = () => {
-  const svgElement = mindmapRef.value
+  const svgElement = mindMapRef.value
   // 将 SVG 渲染到图片对象
   const serializer = new XMLSerializer()
-  const source =
-    '<?xml version="1.0" standalone="no"?>\r\n' + serializer.serializeToString(svgRef.value!)
-  const image = new Image()
-  image.src = 'data:image/svg+xml;charset=utf-8,' + encodeURIComponent(source)
-
-  // 将图片对象渲染
-  const canvas = document.createElement('canvas')
-  canvas.width = svgElement?.offsetWidth || 0
-  canvas.height = svgElement?.offsetHeight || 0
-  let context = canvas.getContext('2d')
-  context?.clearRect(0, 0, canvas.width, canvas.height)
-
-  image.onload = function () {
-    context?.drawImage(image, 0, 0)
-    const a = document.createElement('a')
-    a.download = 'mindmap.png'
-    a.href = canvas.toDataURL(`image/png`)
-    a.click()
-  }
+  const source = `<?xml version="1.0" standalone="no"?>\r\n${serializer.serializeToString(svgRef.value!)}`
+  const base64Url = `data:image/svg+xml;charset=utf-8,${encodeURIComponent(source)}`
+  download.image({
+    url: base64Url,
+    canvasWidth: svgElement?.offsetWidth,
+    canvasHeight: svgElement?.offsetHeight,
+    drawWithImageSize: false
+  })
 }
 
 defineExpose({
@@ -149,6 +137,7 @@
     height: 0;
   }
 }
+
 .my-card {
   display: flex;
   flex-direction: column;
@@ -161,13 +150,16 @@
     @extend .hide-scroll-bar;
   }
 }
+
 // markmap的tool样式覆盖
 :deep(.markmap) {
   width: 100%;
 }
+
 :deep(.mm-toolbar-brand) {
   display: none;
 }
+
 :deep(.mm-toolbar) {
   display: flex;
   flex-direction: row;

--
Gitblit v1.9.3