diff --git a/frontend/src/pages/Workflow/Definition/Designer/index.tsx b/frontend/src/pages/Workflow/Definition/Designer/index.tsx index 82d5087a..eb58df34 100644 --- a/frontend/src/pages/Workflow/Definition/Designer/index.tsx +++ b/frontend/src/pages/Workflow/Definition/Designer/index.tsx @@ -3,11 +3,12 @@ import {useNavigate, useParams} from 'react-router-dom'; import {Button, Card, Layout, message, Space, Spin} from 'antd'; import {ArrowLeftOutlined, SaveOutlined} from '@ant-design/icons'; import {getDefinition, updateDefinition} from '../../service'; -import {NodeType, WorkflowDefinition, WorkflowStatus} from '../../../Workflow/types'; +import {WorkflowDefinition, WorkflowStatus} from '../../../Workflow/types'; import {Graph} from '@antv/x6'; import '@antv/x6-react-shape'; import './index.module.less'; import NodePanel from './components/NodePanel'; +import { NodeType } from './service'; const {Sider, Content} = Layout; @@ -18,6 +19,7 @@ const FlowDesigner: React.FC = () => { const [detail, setDetail] = useState(); const containerRef = useRef(null); const graphRef = useRef(); + const draggedNodeRef = useRef(); // 初始化图形 const initGraph = () => { @@ -102,27 +104,11 @@ const FlowDesigner: React.FC = () => { vertexAddable: true, vertexDeletable: true, }, - scroller: { - enabled: true, - pannable: true, - pageVisible: false, - pageBreak: false, + translating: { + restrict: true, }, - history: { - enabled: true, - }, - clipboard: { - enabled: true, - }, - keyboard: { - enabled: true, - }, - selecting: { - enabled: true, - multiple: true, - rubberband: true, - movable: true, - showNodeSelectionBox: true, + background: { + color: '#F8F9FA', }, }); @@ -137,6 +123,115 @@ const FlowDesigner: React.FC = () => { message.error('加载流程图数据失败'); } } + + // 监听画布拖拽事件 + containerRef.current.addEventListener('dragover', handleDragOver); + containerRef.current.addEventListener('drop', handleDrop); + }; + + // 处理拖拽移动 + const handleDragOver = (e: DragEvent) => { + e.preventDefault(); + e.dataTransfer!.dropEffect = 'copy'; + }; + + // 处理拖拽放置 + const handleDrop = (e: DragEvent) => { + e.preventDefault(); + const nodeType = draggedNodeRef.current; + if (!nodeType || !graphRef.current || !containerRef.current) return; + + // 获取画布相对位置 + const rect = containerRef.current.getBoundingClientRect(); + const point = { + x: e.clientX - rect.left, + y: e.clientY - rect.top, + }; + + // 获取画布缩放和平移信息 + const matrix = graphRef.current.matrix(); + const scale = matrix.a; + const offsetX = matrix.e; + const offsetY = matrix.f; + + // 计算实际位置(考虑缩放和平移) + const position = { + x: (point.x - offsetX) / scale, + y: (point.y - offsetY) / scale, + }; + + // 创建节点 + const node = graphRef.current.addNode({ + x: position.x - 90, // 节点宽度的一半,使节点中心对准鼠标 + y: position.y - 20, // 节点高度的一半,使节点中心对准鼠标 + width: 180, + height: 40, + label: nodeType.name, + attrs: { + body: { + fill: '#fff', + stroke: nodeType.color, + strokeWidth: 1, + rx: 4, + ry: 4, + }, + label: { + fill: '#333', + fontSize: 14, + refX: 0.5, + refY: 0.5, + textAnchor: 'middle', + textVerticalAnchor: 'middle', + }, + }, + ports: { + groups: { + in: { + position: 'left', + attrs: { + circle: { + r: 4, + magnet: true, + stroke: '#5F95FF', + strokeWidth: 1, + fill: '#fff', + }, + }, + }, + out: { + position: 'right', + attrs: { + circle: { + r: 4, + magnet: true, + stroke: '#5F95FF', + strokeWidth: 1, + fill: '#fff', + }, + }, + }, + }, + items: [ + { + id: 'port-in', + group: 'in', + }, + { + id: 'port-out', + group: 'out', + }, + ], + }, + data: { + type: nodeType.code, + config: {}, + }, + }); + + // 选中新创建的节点 + const cells = graphRef.current.getSelectedCells(); + cells.forEach(cell => cell.unselect()); + node.select(); }; // 获取详情 @@ -185,12 +280,18 @@ const FlowDesigner: React.FC = () => { if (detail && containerRef.current) { initGraph(); } + // 清理事件监听 + return () => { + if (containerRef.current) { + containerRef.current.removeEventListener('dragover', handleDragOver); + containerRef.current.removeEventListener('drop', handleDrop); + } + }; }, [detail, containerRef.current]); // 处理节点拖拽开始 const handleNodeDragStart = (nodeType: NodeType) => { - // TODO: 实现节点拖拽创建 - console.log('Node drag start:', nodeType); + draggedNodeRef.current = nodeType; }; if (loading) {