import { defineComponent, ref, computed } from 'vue' import { Handle, Position, useVueFlow, NodeProps } from '@vue-flow/core' import styles from './Node.module.css' import { NodeData, ICON_MAP, NodeType } from '../../types' // 节点类型定义 export const NODE_TYPES = { APPLY: 'apply', BRANCH: 'branch', DEPLOY: 'deploy', UPLOAD: 'upload', NOTIFY: 'notify', } export default defineComponent({ name: 'BaseNodeWithAddButton', props: { id: { type: String, required: true }, data: { type: Object, required: true }, selected: { type: Boolean, default: false }, connectable: { type: Boolean, default: true }, nodeClassName: { type: String, default: '' }, icon: { type: String, default: '' }, isClickable: { type: Boolean, default: false }, onClick: { type: Function, default: () => {} }, }, emits: ['add-node'], setup(props, { slots, emit }) { const showMenu = ref(false) const vueFlowInstance = useVueFlow() // 获取节点图标 const nodeIcon = computed(() => { const nodeType = props.data.type as NodeType return props.icon || props.data.icon || ICON_MAP[nodeType] || '📄' }) // 处理添加按钮点击 const handleAddClick = (e: MouseEvent) => { e.stopPropagation() showMenu.value = !showMenu.value } // 处理节点点击 const handleNodeClick = (e: MouseEvent) => { if (props.isClickable) { e.stopPropagation() props.onClick(props.data) } } // 添加新节点 const addNewNode = (type: string) => { // 获取当前节点信息 const currentNode = vueFlowInstance.findNode(props.id) if (!currentNode) return // 创建新节点ID const newNodeId = `${type}-${Date.now()}` // 根据不同类型节点设置不同图标和标签 let nodeLabel = '新节点' switch (type) { case NODE_TYPES.APPLY: nodeLabel = '申请证书' break case NODE_TYPES.BRANCH: nodeLabel = '分支节点' break case NODE_TYPES.DEPLOY: nodeLabel = '部署证书' break case NODE_TYPES.UPLOAD: nodeLabel = '上传证书' break case NODE_TYPES.NOTIFY: nodeLabel = '通知' break } // 计算新节点位置 const nodeHeight = 120 // 节点固定高度 const verticalGap = 150 // 节点之间的垂直间距 const newY = currentNode.position.y + nodeHeight + verticalGap // 创建新节点 const newNode = { id: newNodeId, type: type, position: { x: currentNode.position.x, y: newY, }, data: { id: newNodeId, type: type as NodeType, label: nodeLabel, icon: ICON_MAP[type as NodeType], canMove: false, canDelete: true, canChangeType: true, }, } // 创建连接边 const newEdge = { id: `${props.id}-${newNodeId}`, source: props.id, target: newNodeId, type: 'smoothstep', animated: true, style: { strokeWidth: 2 }, sourceHandle: 'bottom', targetHandle: 'top', } // 添加节点和边 vueFlowInstance.addNodes([newNode]) vueFlowInstance.addEdges([newEdge]) // 关闭菜单 showMenu.value = false // 触发添加节点事件 emit('add-node', { nodeId: newNodeId, nodeType: type }) } // 处理点击外部关闭菜单 const handleOutsideClick = () => { showMenu.value = false } return () => (