1
This commit is contained in:
parent
13297f25dd
commit
bc0e595efa
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -49,6 +49,96 @@ const WorkflowDesign: React.FC = () => {
|
|||||||
const [nodeDefinitions, setNodeDefinitions] = useState<NodeDefinition[]>([]);
|
const [nodeDefinitions, setNodeDefinitions] = useState<NodeDefinition[]>([]);
|
||||||
const [isNodeDefinitionsLoaded, setIsNodeDefinitionsLoaded] = useState(false);
|
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(() => {
|
useEffect(() => {
|
||||||
const loadNodeDefinitions = async () => {
|
const loadNodeDefinitions = async () => {
|
||||||
@ -127,132 +217,7 @@ const WorkflowDesign: React.FC = () => {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 添加右键菜单
|
registerEventHandlers(graph);
|
||||||
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);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
setGraph(graph);
|
setGraph(graph);
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user