Jelajahi Sumber

AI工作流新增退格删除节点

lk 1 hari lalu
induk
melakukan
fb95a80617
1 mengubah file dengan 115 tambahan dan 39 penghapusan
  1. 115 39
      src/views/his/aiWorkflow/design.vue

+ 115 - 39
src/views/his/aiWorkflow/design.vue

@@ -57,10 +57,13 @@
       <div
         class="canvas-container"
         ref="canvasContainer"
+        tabindex="0" 
         @drop="onDrop"
         @dragover.prevent
         @click="onCanvasClick"
         @mousedown="onCanvasMouseDown"
+        @keydown.delete="handleDelete"
+        @keydown.backspace="handleDelete"
       >
         <svg class="canvas-svg" ref="canvasSvg" :width="canvasSize.width" :height="canvasSize.height"
           :class="{ 'dragging-canvas': isDraggingCanvas }">
@@ -166,7 +169,7 @@
         
         <!-- 节点属性 -->
         <el-form v-if="selectedNode" label-width="80px" size="small">
-          <el-form-item label="节点名称">
+          <el-form-item label="节点内容">
             <el-input v-model="selectedNode.nodeName" />
           </el-form-item>
           <el-form-item label="节点类型">
@@ -270,14 +273,113 @@ export default {
     }
   },
   mounted() {
+    // 确保容器可获取焦点
+    this.$nextTick(() => {
+      this.$refs.canvasContainer.focus()  // 这里应该是 canvasContainer 不是 container
+    })
+    
+    // 添加全局键盘事件监听
+    // window.addEventListener('keydown', this.handleGlobalKeydown)
     document.addEventListener('mousemove', this.onMouseMove)
     document.addEventListener('mouseup', this.onMouseUp)
   },
   beforeDestroy() {
+    // window.removeEventListener('keydown', this.handleGlobalKeydown)
     document.removeEventListener('mousemove', this.onMouseMove)
     document.removeEventListener('mouseup', this.onMouseUp)
   },
   methods: {
+    // 聚焦画布容器
+    focusCanvasContainer() {
+      this.$refs.canvasContainer.focus()
+    },
+    
+    // 点击画布时聚焦
+    onCanvasClick() {
+      this.clearSelection()
+      this.focusCanvasContainer()
+    },
+    
+    // 点击节点时聚焦
+    selectNode(node) {
+      this.selectedNode = node
+      this.selectedEdge = null
+      this.focusCanvasContainer()
+    },
+    
+    // 点击连线时聚焦
+    selectEdge(edge) {
+      this.selectedEdge = edge
+      this.selectedNode = null
+      this.focusCanvasContainer()
+    },
+    
+    // 局部键盘事件
+    handleDelete(event) {
+      event.preventDefault() // 阻止默认行为(如浏览器后退)
+      this.deleteSelected()
+    },
+    
+    // 全局键盘事件
+    // handleGlobalKeydown(event) {
+    //   // 检查是否按下了退格键或删除键
+    //   if ((event.key === 'Backspace' || event.key === 'Delete') && !this.isInputFocused()) {
+    //     event.preventDefault()
+    //     this.deleteSelected()
+    //   }
+    // },
+    
+    // 删除选中项的逻辑
+    deleteSelected() {
+      if (this.selectedNode) {
+        this.deleteSelectedNode()
+      } else if (this.selectedEdge) {
+        this.deleteSelectedEdge()
+      }
+    },
+    
+    // 删除选中节点
+    deleteSelectedNode() {
+      if (!this.selectedNode) return
+      // 确认对话框
+      this.$confirm('是否确认删除该节点?', '警告', {
+        confirmButtonText: '确定',
+        cancelButtonText: '取消',
+        type: 'warning'
+      }).then(() => {
+        const key = this.selectedNode.nodeKey
+        this.nodes = this.nodes.filter(n => n.nodeKey !== key)
+        // 同时删除与该节点相关的连线
+        this.edges = this.edges.filter(e => 
+          e.sourceNodeKey !== key && e.targetNodeKey !== key)
+        this.selectedNode = null
+      }).catch(() => {})
+    },
+    
+    // 删除选中连线
+    deleteSelectedEdge() {
+      if (!this.selectedEdge) return
+      
+      this.$confirm('是否确认删除该连线?', '警告', {
+        confirmButtonText: '确定',
+        cancelButtonText: '取消',
+        type: 'warning'
+      }).then(() => {
+        this.edges = this.edges.filter(e => e.edgeKey !== this.selectedEdge.edgeKey)
+        this.selectedEdge = null
+      }).catch(() => {})
+    },
+    
+    // 检查是否有输入框获得焦点
+    isInputFocused() {
+      const activeElement = document.activeElement
+      // 注意:节点名称输入框也需要排除
+      const isEditable = ['INPUT', 'TEXTAREA', 'SELECT'].includes(activeElement.tagName)
+      // 额外检查是否是节点名称输入框
+      const isNodeInput = activeElement.classList && activeElement.classList.contains('node-name-input')
+      return isEditable || isNodeInput
+    },
+    
     /** 加载节点类型 */
     loadNodeTypes() {
       getNodeTypes().then(res => {
@@ -342,6 +444,7 @@ export default {
     fitView() {
       this.scale = 1
       this.canvasOffset = { x: 0, y: 0 }
+      this.focusCanvasContainer()
     },
     /** 生成唯一Key */
     generateKey() {
@@ -373,13 +476,11 @@ export default {
       }
       this.nodes.push(newNode)
       this.selectNode(newNode)
+      this.focusCanvasContainer()
       // 检测并扩展画布
       this.checkAndExpandCanvas(newNode)
     },
-    /** 点击画布 */
-    onCanvasClick() {
-      this.clearSelection()
-    },
+    
     /** 画布鼠标按下 */
     onCanvasMouseDown(e) {
       // 只响应左键且点击在空白区域
@@ -395,16 +496,7 @@ export default {
         e.preventDefault()
       }
     },
-    /** 选中节点 */
-    selectNode(node) {
-      this.selectedNode = node
-      this.selectedEdge = null
-    },
-    /** 选中连线 */
-    selectEdge(edge) {
-      this.selectedEdge = edge
-      this.selectedNode = null
-    },
+    
     /** 清除选中 */
     clearSelection() {
       this.selectedNode = null
@@ -421,6 +513,7 @@ export default {
         x: (e.clientX - rect.left + scrollLeft - this.canvasOffset.x) / this.scale - node.posX,
         y: (e.clientY - rect.top + scrollTop - this.canvasOffset.y) / this.scale - node.posY
       }
+      this.selectNode(node)
     },
     /** 鼠标移动 */
     onMouseMove(e) {
@@ -480,6 +573,7 @@ export default {
       // 停止拖动画布
       if (this.isDraggingCanvas) {
         this.isDraggingCanvas = false
+        this.focusCanvasContainer()
         return
       }
       // 停止连线
@@ -505,6 +599,7 @@ export default {
         x: anchorPos.x,
         y: anchorPos.y
       }
+      this.selectNode(node)
     },
     /** 获取锚点位置 */
     getAnchorPos(node, anchor) {
@@ -601,32 +696,13 @@ export default {
       const t = this.nodeTypes.find(n => n.typeCode === typeCode)
       return t ? t.typeName : typeCode
     },
-    /** 删除节点 */
+    /** 删除节点(按钮触发) */
     deleteNode() {
-      if (!this.selectedNode) return
-      this.$confirm('是否确认删除该节点?', '警告', {
-        confirmButtonText: '确定',
-        cancelButtonText: '取消',
-        type: 'warning'
-      }).then(() => {
-        const key = this.selectedNode.nodeKey
-        this.nodes = this.nodes.filter(n => n.nodeKey !== key)
-        this.edges = this.edges.filter(e => 
-          e.sourceNodeKey !== key && e.targetNodeKey !== key)
-        this.selectedNode = null
-      }).catch(() => {})
+      this.deleteSelectedNode()
     },
-    /** 删除连线 */
+    /** 删除连线(按钮触发) */
     deleteEdge() {
-      if (!this.selectedEdge) return
-      this.$confirm('是否确认删除该连线?', '警告', {
-        confirmButtonText: '确定',
-        cancelButtonText: '取消',
-        type: 'warning'
-      }).then(() => {
-        this.edges = this.edges.filter(e => e.edgeKey !== this.selectedEdge.edgeKey)
-        this.selectedEdge = null
-      }).catch(() => {})
+      this.deleteSelectedEdge()
     },
     /** 保存工作流 */
     handleSave() {
@@ -662,4 +738,4 @@ export default {
 
 <style lang="scss" scoped>
 @import './design.scss';
-</style>
+</style>