This commit is contained in:
asp_ly 2024-12-14 13:52:47 +08:00
parent 13297f25dd
commit bc0e595efa
2 changed files with 140 additions and 126 deletions

View File

@ -111,4 +111,53 @@
}
}
}
:global {
.node-selected {
> rect {
stroke: #1890ff;
stroke-width: 2px;
}
> path {
stroke: #1890ff;
stroke-width: 2px;
}
}
.x6-node-selected {
rect {
stroke: #1890ff;
stroke-width: 2px;
}
}
.x6-edge-selected {
path {
stroke: #1890ff;
stroke-width: 2px !important;
}
}
// 右键菜单样式
.x6-context-menu {
background: #fff;
border-radius: 4px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
padding: 4px 0;
min-width: 120px;
&-item {
padding: 5px 16px;
cursor: pointer;
user-select: none;
transition: all 0.3s;
color: rgba(0, 0, 0, 0.85);
font-size: 14px;
&:hover {
background: #f5f5f5;
}
}
}
}
}

View File

@ -49,6 +49,96 @@ const WorkflowDesign: React.FC = () => {
const [nodeDefinitions, setNodeDefinitions] = useState<NodeDefinition[]>([]);
const [isNodeDefinitionsLoaded, setIsNodeDefinitionsLoaded] = useState(false);
// 注册事件处理器
const registerEventHandlers = (graph: Graph) => {
// 显示/隐藏连接桩
graph.on('node:mouseenter', ({node}) => {
const ports = document.querySelectorAll(`[data-cell-id="${node.id}"] .x6-port-body`);
ports.forEach((port) => {
port.setAttribute('style', 'visibility: visible');
});
});
graph.on('node:mouseleave', ({node}) => {
const ports = document.querySelectorAll(`[data-cell-id="${node.id}"] .x6-port-body`);
ports.forEach((port) => {
port.setAttribute('style', 'visibility: hidden');
});
});
// 节点双击事件
graph.on('node:dblclick', ({node}) => {
const nodeType = node.getProp('type');
console.log(nodeType)
// 从节点定义列表中找到对应的定义
const nodeDefinition = nodeDefinitions.find(def => def.type === nodeType);
if (nodeDefinition) {
setSelectedNode(node);
setSelectedNodeDefinition(nodeDefinition);
setConfigModalVisible(true);
}
});
// 添加右键菜单
graph.on('node:contextmenu', ({cell, view, e}) => {
e.preventDefault();
graph.cleanSelection();
graph.select(cell);
const menuItems = [
{
label: '编辑',
onClick: () => {
setSelectedNode(cell);
setSelectedNodeDefinition(nodeDefinitions.find(def => def.type === cell.getProp('type')));
setConfigModalVisible(true);
}
},
{
label: '删除',
onClick: () => {
Modal.confirm({
title: '确认删除',
content: '确定要删除该节点吗?',
onOk: () => {
graph.removeCell(cell);
}
});
}
}
];
const menu = document.createElement('div');
menu.className = 'x6-context-menu';
menu.style.position = 'fixed';
menu.style.left = `${e.clientX}px`;
menu.style.top = `${e.clientY}px`;
menu.style.zIndex = '1000';
menuItems.forEach(item => {
const menuItem = document.createElement('div');
menuItem.className = 'x6-context-menu-item';
menuItem.innerText = item.label;
menuItem.onclick = () => {
item.onClick();
menu.remove();
};
menu.appendChild(menuItem);
});
document.body.appendChild(menu);
const removeMenu = (e: MouseEvent) => {
if (!menu.contains(e.target as Node)) {
menu.remove();
document.removeEventListener('click', removeMenu);
}
};
document.addEventListener('click', removeMenu);
});
};
// 首先加载节点定义列表
useEffect(() => {
const loadNodeDefinitions = async () => {
@ -127,132 +217,7 @@ const WorkflowDesign: React.FC = () => {
);
}
// 添加右键菜单
graph.on('node:contextmenu', ({cell, view, e}) => {
e.preventDefault();
graph.cleanSelection();
graph.select(cell);
const menuItems = [
{
label: '编辑',
onClick: () => {
setSelectedNode(cell);
setSelectedNodeDefinition(nodeDefinitions.find(def => def.type === cell.getProp('type')));
setConfigModalVisible(true);
}
},
{
label: '删除',
onClick: () => {
Modal.confirm({
title: '确认删除',
content: '确定要删除该节点吗?',
onOk: () => {
graph.removeCell(cell);
}
});
}
}
];
const menu = document.createElement('div');
menu.className = 'x6-context-menu';
menu.style.position = 'fixed';
menu.style.left = `${e.clientX}px`;
menu.style.top = `${e.clientY}px`;
menu.style.zIndex = '1000';
menuItems.forEach(item => {
const menuItem = document.createElement('div');
menuItem.className = 'x6-context-menu-item';
menuItem.innerText = item.label;
menuItem.onclick = () => {
item.onClick();
menu.remove();
};
menu.appendChild(menuItem);
});
document.body.appendChild(menu);
const removeMenu = (e: MouseEvent) => {
if (!menu.contains(e.target as Node)) {
menu.remove();
document.removeEventListener('click', removeMenu);
}
};
document.addEventListener('click', removeMenu);
});
// 添加样式
const style = document.createElement('style');
style.textContent = `
.node-selected > rect {
stroke: #1890ff;
stroke-width: 2px;
}
.node-selected > path {
stroke: #1890ff;
stroke-width: 2px;
}
.x6-node-selected rect {
stroke: #1890ff;
stroke-width: 2px;
}
.x6-edge-selected path {
stroke: #1890ff;
stroke-width: 2px !important;
}
.x6-context-menu {
background: #fff;
border-radius: 4px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
padding: 4px 0;
min-width: 120px;
}
.x6-context-menu-item {
padding: 5px 16px;
cursor: pointer;
user-select: none;
transition: all 0.3s;
color: rgba(0, 0, 0, 0.85);
font-size: 14px;
}
.x6-context-menu-item:hover {
background: #f5f5f5;
}
`;
document.head.appendChild(style);
// 显示/隐藏连接桩
graph.on('node:mouseenter', ({node}) => {
const ports = document.querySelectorAll(`[data-cell-id="${node.id}"] .x6-port-body`);
ports.forEach((port) => {
port.setAttribute('style', 'visibility: visible');
});
});
graph.on('node:mouseleave', ({node}) => {
const ports = document.querySelectorAll(`[data-cell-id="${node.id}"] .x6-port-body`);
ports.forEach((port) => {
port.setAttribute('style', 'visibility: hidden');
});
});
// 节点双击事件
graph.on('node:dblclick', ({node}) => {
const nodeType = node.getProp('type');
console.log(nodeType)
// 从节点定义列表中找到对应的定义
const nodeDefinition = nodeDefinitions.find(def => def.type === nodeType);
if (nodeDefinition) {
setSelectedNode(node);
setSelectedNodeDefinition(nodeDefinition);
setConfigModalVisible(true);
}
});
registerEventHandlers(graph);
setGraph(graph);