Răsfoiți Sursa

【代码评审】AI:code review 思维导图的逻辑

YunaiV 8 luni în urmă
părinte
comite
1fe40b61a0

+ 3 - 0
build/vite/optimize.ts

@@ -29,6 +29,9 @@ const include = [
   '@wangeditor/editor-for-vue',
   '@microsoft/fetch-event-source',
   'markdown-it',
+  'markmap-view',
+  'markmap-lib',
+  'markmap-toolbar',
   'highlight.js',
   'element-plus',
   'element-plus/es',

+ 0 - 1
package.json

@@ -53,7 +53,6 @@
     "jsencrypt": "^3.3.2",
     "lodash-es": "^4.17.21",
     "markdown-it": "^14.1.0",
-    "marked": "^12.0.2",
     "markmap-common": "^0.16.0",
     "markmap-lib": "^0.16.1",
     "markmap-toolbar": "^0.17.0",

Fișier diff suprimat deoarece este prea mare
+ 725 - 23
pnpm-lock.yaml


+ 0 - 1
src/api/ai/mindmap/index.ts

@@ -5,7 +5,6 @@ import { config } from '@/config/axios/config'
 export interface AiMindMapGenerateReqVO {
   prompt: string
 }
-//
 
 export const AiMindMapApi = {
   generateMindMap: ({

+ 11 - 8
src/views/ai/mindmap/index/components/Left.vue

@@ -20,13 +20,14 @@
           type="primary"
           :loading="isGenerating"
           @click="emits('submit', formData)"
-          >智能生成思维导图</el-button
         >
+          智能生成思维导图
+        </el-button>
       </div>
       <div class="mt-[30px]">
         <el-text tag="b">使用已有内容生成?</el-text>
         <el-input
-          v-model="existPrompt"
+          v-model="generatedContent"
           maxlength="1024"
           rows="5"
           class="w-100% mt-15px"
@@ -38,17 +39,18 @@
         <el-button
           class="!w-full mt-[15px]"
           type="primary"
-          @click="emits('directGenerate', existPrompt)"
+          @click="emits('directGenerate', generatedContent)"
           :disabled="isGenerating"
-          >直接生成</el-button
         >
+          直接生成
+        </el-button>
       </div>
     </div>
   </div>
 </template>
 
 <script setup lang="ts">
-import { MindmapExitExample } from '@/views/ai/utils/constants'
+import { MindMapContentExample } from '@/views/ai/utils/constants'
 
 const emits = defineEmits(['submit', 'directGenerate'])
 defineProps<{
@@ -59,11 +61,12 @@ const formData = reactive({
   prompt: ''
 })
 
-const existPrompt = ref(MindmapExitExample) // 已有的内容
+const generatedContent = ref(MindMapContentExample) // 已有的内容
 
 defineExpose({
-  setExistPrompt(e: string){ // 设置已有的内容,在生成结束的时候将结果赋值给该值
-    existPrompt.value = e
+  setGeneratedContent(newContent: string) {
+    // 设置已有的内容,在生成结束的时候将结果赋值给该值
+    generatedContent.value = newContent
   }
 })
 </script>

+ 23 - 17
src/views/ai/mindmap/index/components/Right.vue

@@ -1,7 +1,7 @@
 <template>
   <el-card class="my-card h-full flex-grow">
-    <template #header
-      ><h3 class="m-0 px-7 shrink-0 flex items-center justify-between">
+    <template #header>
+      <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">
@@ -10,13 +10,13 @@
           </template>
           下载图片
         </el-button>
-      </h3></template
-    >
+      </h3>
+    </template>
 
     <div ref="contentRef" class="hide-scroll-bar h-full box-border">
-      <!--展示markdown的容器,最终生成的是html字符串,直接用v-html嵌入-->
+      <!--展示 markdown 的容器,最终生成的是 html 字符串,直接用 v-html 嵌入-->
       <div v-if="isGenerating" ref="mdContainerRef" class="wh-full overflow-y-auto">
-        <div  class="flex flex-col items-center justify-center" v-html="html"></div>
+        <div class="flex flex-col items-center justify-center" v-html="html"></div>
       </div>
 
       <div ref="mindmapRef" class="wh-full">
@@ -34,24 +34,25 @@ import { Toolbar } from 'markmap-toolbar'
 import markdownit from 'markdown-it'
 
 const md = markdownit()
+const message = useMessage() // 消息弹窗
+
+// TODO @hhero:mindmap 改成 mindMap 更精准哈
 const props = defineProps<{
-  mindmapResult: string // 生成结果
+  mindmapResult: string // 生成结果 TODO @hhero 改成 generatedContent 会不会好点
   isEnd: boolean // 是否结束
   isGenerating: boolean // 是否正在生成
-  isStart: boolean // 开始状态,开始时需要清除html
+  isStart: boolean // 开始状态,开始时需要清除 html
 }>()
 const contentRef = ref<HTMLDivElement>() // 右侧出来header以下的区域
-const mdContainerRef = ref<HTMLDivElement>() // markdown的容器,用来滚动到底下的
+const mdContainerRef = ref<HTMLDivElement>() // markdown 的容器,用来滚动到底下的
 const mindmapRef = ref<HTMLDivElement>() // 思维导图的容器
-const svgRef = ref<SVGElement>() // 思维导图的渲染svg
+const svgRef = ref<SVGElement>() // 思维导图的渲染 svg
 const toolBarRef = ref<HTMLDivElement>() // 思维导图右下角的工具栏,缩放等
 const html = ref('') // 生成过程中的文本
-const contentAreaHeight = ref(0) // 生成区域的高度,出去header部分
+const contentAreaHeight = ref(0) // 生成区域的高度,出去 header 部分
 let markMap: Markmap | null = null
 const transformer = new Transformer()
 
-const message = useMessage()
-
 onMounted(() => {
   contentAreaHeight.value = contentRef.value?.clientHeight || 0 // 获取区域高度
   /** 初始化思维导图 **/
@@ -66,11 +67,11 @@ onMounted(() => {
 })
 
 watch(props, ({ mindmapResult, isGenerating, isEnd, isStart }) => {
-  // 开始生成的时候清空一下markdown的内容
+  // 开始生成的时候清空一下 markdown 的内容
   if (isStart) {
     html.value = ''
   }
-  // 生成内容的时候使用markdown来渲染
+  // 生成内容的时候使用 markdown 来渲染
   if (isGenerating) {
     html.value = md.render(mindmapResult)
   }
@@ -79,6 +80,7 @@ watch(props, ({ mindmapResult, isGenerating, isEnd, isStart }) => {
   }
 })
 
+/** 更新思维导图的展示 */
 const update = () => {
   try {
     const { root } = transformer.transform(processContent(props.mindmapResult))
@@ -89,7 +91,8 @@ const update = () => {
   }
 }
 
-const processContent = (text) => {
+/** 处理内容 */
+const processContent = (text: string) => {
   const arr: string[] = []
   const lines = text.split('\n')
   for (let line of lines) {
@@ -101,6 +104,9 @@ const processContent = (text) => {
   }
   return arr.join('\n')
 }
+
+/** 下载图片 */
+// TODO @hhhero:可以抽到 download 这个里面,src/utils/download.ts 么?复用 image 方法?
 // download SVG to png file
 const downloadImage = () => {
   const svgElement = mindmapRef.value
@@ -121,7 +127,7 @@ const downloadImage = () => {
   image.onload = function () {
     context?.drawImage(image, 0, 0)
     const a = document.createElement('a')
-    a.download = 'ruoyi-mindmap.png'
+    a.download = 'mindmap.png'
     a.href = canvas.toDataURL(`image/png`)
     a.click()
   }

+ 18 - 8
src/views/ai/mindmap/index/index.vue

@@ -1,7 +1,12 @@
 <template>
   <div class="absolute top-0 left-0 right-0 bottom-0 flex">
     <!--表单区域-->
-    <Left ref="leftRef" @submit="submit" @direct-generate="directGenerate" :is-generating="isGenerating" />
+    <Left
+      ref="leftRef"
+      @submit="submit"
+      @direct-generate="directGenerate"
+      :is-generating="isGenerating"
+    />
     <!--右边生成思维导图区域-->
     <Right
       ref="rightRef"
@@ -17,10 +22,10 @@
 import Left from './components/Left.vue'
 import Right from './components/Right.vue'
 import { AiMindMapApi, AiMindMapGenerateReqVO } from '@/api/ai/mindmap'
-import { MindmapExitExample } from '@/views/ai/utils/constants'
+import { MindMapContentExample } from '@/views/ai/utils/constants'
 
 defineOptions({
-  name: 'AIMindMap'
+  name: 'AiMindMap'
 })
 const ctrl = ref<AbortController>() // 请求控制
 const isGenerating = ref(false) // 是否正在生成思维导图
@@ -33,21 +38,21 @@ const mindmapResult = ref('') // 生成思维导图结果
 const leftRef = ref<InstanceType<typeof Left>>() // 左边组件
 const rightRef = ref<InstanceType<typeof Right>>() // 右边组件
 
-onMounted(() => {
-  mindmapResult.value = MindmapExitExample
-})
 /** 使用已有内容直接生成 **/
 const directGenerate = (existPrompt: string) => {
   isEnd.value = false // 先设置为false再设置为true,让子组建的watch能够监听到
   mindmapResult.value = existPrompt
   isEnd.value = true
 }
+
 /** 停止 stream 生成 */
 const stopStream = () => {
   isGenerating.value = false
   isStart.value = false
   ctrl.value?.abort()
 }
+
+/** 提交生成 */
 const submit = (data: AiMindMapGenerateReqVO) => {
   isGenerating.value = true
   isStart.value = true
@@ -56,7 +61,7 @@ const submit = (data: AiMindMapGenerateReqVO) => {
   mindmapResult.value = '' // 清空生成数据
   AiMindMapApi.generateMindMap({
     data,
-    onMessage:async (res) => {
+    onMessage: async (res) => {
       const { code, data, msg } = JSON.parse(res.data)
       if (code !== 0) {
         message.alert(`生成思维导图异常! ${msg}`)
@@ -69,7 +74,7 @@ const submit = (data: AiMindMapGenerateReqVO) => {
     },
     onClose() {
       isEnd.value = true
-      leftRef.value?.setExistPrompt(mindmapResult.value)
+      leftRef.value?.setGeneratedContent(mindmapResult.value)
       stopStream()
     },
     onError(err) {
@@ -79,4 +84,9 @@ const submit = (data: AiMindMapGenerateReqVO) => {
     ctrl: ctrl.value
   })
 }
+
+/** 初始化 */
+onMounted(() => {
+  mindmapResult.value = MindMapContentExample
+})
 </script>

+ 6 - 2
src/views/ai/utils/constants.ts

@@ -67,10 +67,11 @@ export enum AiWriteTypeEnum {
 // 表格展示对照map
 export const AiWriteTypeTableRender = {
   [AiWriteTypeEnum.WRITING]: '撰写',
-  [AiWriteTypeEnum.REPLY]: '回复',
+  [AiWriteTypeEnum.REPLY]: '回复'
 }
 
 // ========== 【图片 UI】相关的枚举 ==========
+
 export const ImageHotWords = [
   '中国旗袍',
   '古装美女',
@@ -414,8 +415,11 @@ export const WriteExample = {
     data: '您的请假申请已收悉,经核实和考虑,暂时无法批准您的请假申请。\n\n如有特殊情况或紧急事务,请及时与我联系。\n\n祝工作顺利。\n\n谢谢。'
   }
 }
+
+// ========== 【思维导图 UI】相关的枚举 ==========
+
 /** 思维导图已有内容生成示例 **/
-export const MindmapExitExample = `# Java 技术栈
+export const MindMapContentExample = `# Java 技术栈
 
 ## 核心技术
 ### Java SE

Unele fișiere nu au fost afișate deoarece prea multe fișiere au fost modificate în acest diff