拖拽实现
This commit is contained in:
parent
0713c2c83e
commit
4b37225a50
@ -3,11 +3,12 @@ import {useNavigate, useParams} from 'react-router-dom';
|
|||||||
import {Button, Card, Layout, message, Space, Spin} from 'antd';
|
import {Button, Card, Layout, message, Space, Spin} from 'antd';
|
||||||
import {ArrowLeftOutlined, SaveOutlined} from '@ant-design/icons';
|
import {ArrowLeftOutlined, SaveOutlined} from '@ant-design/icons';
|
||||||
import {getDefinition, updateDefinition} from '../../service';
|
import {getDefinition, updateDefinition} from '../../service';
|
||||||
import {NodeType, WorkflowDefinition, WorkflowStatus} from '../../../Workflow/types';
|
import {WorkflowDefinition, WorkflowStatus} from '../../../Workflow/types';
|
||||||
import {Graph} from '@antv/x6';
|
import {Graph} from '@antv/x6';
|
||||||
import '@antv/x6-react-shape';
|
import '@antv/x6-react-shape';
|
||||||
import './index.module.less';
|
import './index.module.less';
|
||||||
import NodePanel from './components/NodePanel';
|
import NodePanel from './components/NodePanel';
|
||||||
|
import { NodeType } from './service';
|
||||||
|
|
||||||
const {Sider, Content} = Layout;
|
const {Sider, Content} = Layout;
|
||||||
|
|
||||||
@ -18,6 +19,7 @@ const FlowDesigner: React.FC = () => {
|
|||||||
const [detail, setDetail] = useState<WorkflowDefinition>();
|
const [detail, setDetail] = useState<WorkflowDefinition>();
|
||||||
const containerRef = useRef<HTMLDivElement>(null);
|
const containerRef = useRef<HTMLDivElement>(null);
|
||||||
const graphRef = useRef<Graph>();
|
const graphRef = useRef<Graph>();
|
||||||
|
const draggedNodeRef = useRef<NodeType>();
|
||||||
|
|
||||||
// 初始化图形
|
// 初始化图形
|
||||||
const initGraph = () => {
|
const initGraph = () => {
|
||||||
@ -102,27 +104,11 @@ const FlowDesigner: React.FC = () => {
|
|||||||
vertexAddable: true,
|
vertexAddable: true,
|
||||||
vertexDeletable: true,
|
vertexDeletable: true,
|
||||||
},
|
},
|
||||||
scroller: {
|
translating: {
|
||||||
enabled: true,
|
restrict: true,
|
||||||
pannable: true,
|
|
||||||
pageVisible: false,
|
|
||||||
pageBreak: false,
|
|
||||||
},
|
},
|
||||||
history: {
|
background: {
|
||||||
enabled: true,
|
color: '#F8F9FA',
|
||||||
},
|
|
||||||
clipboard: {
|
|
||||||
enabled: true,
|
|
||||||
},
|
|
||||||
keyboard: {
|
|
||||||
enabled: true,
|
|
||||||
},
|
|
||||||
selecting: {
|
|
||||||
enabled: true,
|
|
||||||
multiple: true,
|
|
||||||
rubberband: true,
|
|
||||||
movable: true,
|
|
||||||
showNodeSelectionBox: true,
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -137,6 +123,115 @@ const FlowDesigner: React.FC = () => {
|
|||||||
message.error('加载流程图数据失败');
|
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) {
|
if (detail && containerRef.current) {
|
||||||
initGraph();
|
initGraph();
|
||||||
}
|
}
|
||||||
|
// 清理事件监听
|
||||||
|
return () => {
|
||||||
|
if (containerRef.current) {
|
||||||
|
containerRef.current.removeEventListener('dragover', handleDragOver);
|
||||||
|
containerRef.current.removeEventListener('drop', handleDrop);
|
||||||
|
}
|
||||||
|
};
|
||||||
}, [detail, containerRef.current]);
|
}, [detail, containerRef.current]);
|
||||||
|
|
||||||
// 处理节点拖拽开始
|
// 处理节点拖拽开始
|
||||||
const handleNodeDragStart = (nodeType: NodeType) => {
|
const handleNodeDragStart = (nodeType: NodeType) => {
|
||||||
// TODO: 实现节点拖拽创建
|
draggedNodeRef.current = nodeType;
|
||||||
console.log('Node drag start:', nodeType);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
if (loading) {
|
if (loading) {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user