This commit is contained in:
dengqichen 2024-12-20 14:04:55 +08:00
parent 091ea4fe7b
commit e76af9b8f5
3 changed files with 122 additions and 129 deletions

View File

@ -23,11 +23,11 @@ import '@antv/x6-plugin-keyboard';
import '@antv/x6-plugin-history'; import '@antv/x6-plugin-history';
import '@antv/x6-plugin-clipboard'; import '@antv/x6-plugin-clipboard';
import '@antv/x6-plugin-transform'; import '@antv/x6-plugin-transform';
import { Selection } from '@antv/x6-plugin-selection'; import {Selection} from '@antv/x6-plugin-selection';
import { MiniMap } from '@antv/x6-plugin-minimap'; import {MiniMap} from '@antv/x6-plugin-minimap';
import { Clipboard } from '@antv/x6-plugin-clipboard'; import {Clipboard} from '@antv/x6-plugin-clipboard';
import { History } from '@antv/x6-plugin-history'; import {History} from '@antv/x6-plugin-history';
import { Transform } from '@antv/x6-plugin-transform'; import {Transform} from '@antv/x6-plugin-transform';
import {getDefinitionDetail, saveDefinition} from '../service'; import {getDefinitionDetail, saveDefinition} from '../service';
import {getNodeDefinitionList} from './service'; import {getNodeDefinitionList} from './service';
import NodePanel from './components/NodePanel'; import NodePanel from './components/NodePanel';
@ -69,12 +69,12 @@ const WorkflowDesign: React.FC = () => {
const container = graphContainerRef.current; const container = graphContainerRef.current;
const containerWidth = container.clientWidth; const containerWidth = container.clientWidth;
const containerHeight = container.clientHeight; const containerHeight = container.clientHeight;
// 计算主画布和小地图的尺寸比例 // 计算主画布和小地图的尺寸比例
const MINIMAP_BASE_WIDTH = 200; const MINIMAP_BASE_WIDTH = 200;
const minimapWidth = MINIMAP_BASE_WIDTH; const minimapWidth = MINIMAP_BASE_WIDTH;
const minimapHeight = Math.round((MINIMAP_BASE_WIDTH * containerHeight) / containerWidth); const minimapHeight = Math.round((MINIMAP_BASE_WIDTH * containerHeight) / containerWidth);
// 计算缩放比例 // 计算缩放比例
const scale = minimapWidth / containerWidth; const scale = minimapWidth / containerWidth;
@ -132,10 +132,10 @@ const WorkflowDesign: React.FC = () => {
}); });
return !exists; return !exists;
}, },
validateMagnet({ magnet }) { validateMagnet({magnet}) {
return magnet.getAttribute('port-group') !== 'top'; return magnet.getAttribute('port-group') !== 'top';
}, },
validateEdge({ edge }) { validateEdge({edge}) {
return true; return true;
} }
}, },
@ -184,7 +184,6 @@ const WorkflowDesign: React.FC = () => {
const history = new History({ const history = new History({
enabled: true, enabled: true,
beforeAddCommand(event: any, args: any) { beforeAddCommand(event: any, args: any) {
console.log('History command added:', event, args);
return true; return true;
}, },
afterExecuteCommand: () => { afterExecuteCommand: () => {
@ -200,7 +199,7 @@ const WorkflowDesign: React.FC = () => {
setForceUpdate(prev => !prev); setForceUpdate(prev => !prev);
}, },
}); });
// 初始化Selection插件 // 初始化Selection插件
const selection = new Selection({ const selection = new Selection({
enabled: true, enabled: true,
@ -216,9 +215,7 @@ const WorkflowDesign: React.FC = () => {
showAnchorSelectionBox: false, showAnchorSelectionBox: false,
pointerEvents: 'auto' pointerEvents: 'auto'
}); });
console.log('Initializing Selection plugin:', selection);
graph.use(selection); graph.use(selection);
graph.use(new MiniMap({ graph.use(new MiniMap({
container: minimapContainerRef.current!, container: minimapContainerRef.current!,
width: minimapWidth, width: minimapWidth,
@ -238,12 +235,7 @@ const WorkflowDesign: React.FC = () => {
async: true, async: true,
frozen: true, frozen: true,
interacting: false, interacting: false,
grid: false, grid: false
getCellView(cell) {
if (cell.isNode()) {
return SimpleNodeView;
}
},
}, },
viewport: { viewport: {
padding: 0, padding: 0,
@ -268,20 +260,14 @@ const WorkflowDesign: React.FC = () => {
(graph as any).history = history; (graph as any).history = history;
// 监听图形变化 // 监听图形变化
graph.on('cell:added', ({ cell }) => { graph.on('cell:added', ({cell}) => {
const canUndo = history.canUndo(); const canUndo = history.canUndo();
const canRedo = history.canRedo(); const canRedo = history.canRedo();
console.log('Cell added:', {
cell,
canUndo,
canRedo,
stackSize: history.stackSize,
});
// 强制更新组件状态 // 强制更新组件状态
setForceUpdate(prev => !prev); setForceUpdate(prev => !prev);
}); });
graph.on('cell:removed', ({ cell }) => { graph.on('cell:removed', ({cell}) => {
const canUndo = history.canUndo(); const canUndo = history.canUndo();
const canRedo = history.canRedo(); const canRedo = history.canRedo();
console.log('Cell removed:', { console.log('Cell removed:', {
@ -293,17 +279,10 @@ const WorkflowDesign: React.FC = () => {
// 强制更新组件状态 // 强制更新组件状态
setForceUpdate(prev => !prev); setForceUpdate(prev => !prev);
}); });
graph.on('cell:changed', ({ cell, options }) => { graph.on('cell:changed', ({cell, options}) => {
const canUndo = history.canUndo(); const canUndo = history.canUndo();
const canRedo = history.canRedo(); const canRedo = history.canRedo();
console.log('Cell changed:', {
cell,
options,
canUndo,
canRedo,
stackSize: history.stackSize,
});
// 强制更新组件状态 // 强制更新组件状态
setForceUpdate(prev => !prev); setForceUpdate(prev => !prev);
}); });
@ -319,9 +298,9 @@ const WorkflowDesign: React.FC = () => {
}); });
// 处理连线重新连接 // 处理连线重新连接
graph.on('edge:moved', ({ edge, terminal, previous }) => { graph.on('edge:moved', ({edge, terminal, previous}) => {
if (!edge || !terminal) return; if (!edge || !terminal) return;
const isSource = terminal.type === 'source'; const isSource = terminal.type === 'source';
const source = isSource ? terminal : edge.getSource(); const source = isSource ? terminal : edge.getSource();
const target = isSource ? edge.getTarget() : terminal; const target = isSource ? edge.getTarget() : terminal;
@ -355,7 +334,7 @@ const WorkflowDesign: React.FC = () => {
}); });
// 处理连线更改 // 处理连线更改
graph.on('edge:change:source edge:change:target', ({ edge, current, previous }) => { graph.on('edge:change:source edge:change:target', ({edge, current, previous}) => {
if (edge && current) { if (edge && current) {
edge.setAttrs({ edge.setAttrs({
line: { line: {
@ -383,13 +362,13 @@ const WorkflowDesign: React.FC = () => {
console.error('History plugin not initialized'); console.error('History plugin not initialized');
return; return;
} }
const beforeState = { const beforeState = {
canUndo: history.canUndo(), canUndo: history.canUndo(),
canRedo: history.canRedo(), canRedo: history.canRedo(),
stackSize: history.stackSize, stackSize: history.stackSize,
}; };
if (history.canUndo()) { if (history.canUndo()) {
history.undo(); history.undo();
const afterState = { const afterState = {
@ -415,13 +394,13 @@ const WorkflowDesign: React.FC = () => {
console.error('History plugin not initialized'); console.error('History plugin not initialized');
return; return;
} }
const beforeState = { const beforeState = {
canUndo: history.canUndo(), canUndo: history.canUndo(),
canRedo: history.canRedo(), canRedo: history.canRedo(),
stackSize: history.stackSize, stackSize: history.stackSize,
}; };
if (history.canRedo()) { if (history.canRedo()) {
history.redo(); history.redo();
const afterState = { const afterState = {
@ -501,13 +480,13 @@ const WorkflowDesign: React.FC = () => {
graph.on('node:mouseenter', ({node}) => { graph.on('node:mouseenter', ({node}) => {
// 保存原始样式 // 保存原始样式
saveNodeOriginalStyle(node); saveNodeOriginalStyle(node);
// 显示连接桩 // 显示连接桩
const ports = document.querySelectorAll(`[data-cell-id="${node.id}"] .x6-port-body`); const ports = document.querySelectorAll(`[data-cell-id="${node.id}"] .x6-port-body`);
ports.forEach((port) => { ports.forEach((port) => {
port.setAttribute('style', 'visibility: visible; fill: #fff; stroke: #85ca6d;'); port.setAttribute('style', 'visibility: visible; fill: #fff; stroke: #85ca6d;');
}); });
// 显示悬停样式 // 显示悬停样式
node.setAttrByPath('body/stroke', hoverStyle.stroke); node.setAttrByPath('body/stroke', hoverStyle.stroke);
node.setAttrByPath('body/strokeWidth', hoverStyle.strokeWidth); node.setAttrByPath('body/strokeWidth', hoverStyle.strokeWidth);
@ -519,7 +498,7 @@ const WorkflowDesign: React.FC = () => {
ports.forEach((port) => { ports.forEach((port) => {
port.setAttribute('style', 'visibility: hidden'); port.setAttribute('style', 'visibility: hidden');
}); });
// 恢复原始样式 // 恢复原始样式
resetNodeStyle(node); resetNodeStyle(node);
}); });
@ -541,15 +520,15 @@ const WorkflowDesign: React.FC = () => {
}); });
// 节点点击事件 // 节点点击事件
graph.on('node:click', ({ node }) => { graph.on('node:click', ({node}) => {
// 获取当前选中的节点 // 获取当前选中的节点
const selectedNode = graph.getSelectedCells()[0]; const selectedNode = graph.getSelectedCells()[0];
// 如果有其他节点被选中,恢复其样式 // 如果有其他节点被选中,恢复其样式
if (selectedNode && selectedNode.isNode() && selectedNode.id !== node.id) { if (selectedNode && selectedNode.isNode() && selectedNode.id !== node.id) {
resetNodeStyle(selectedNode); resetNodeStyle(selectedNode);
} }
// 更新选中状态 // 更新选中状态
graph.resetSelection(); graph.resetSelection();
graph.select(node); graph.select(node);
@ -559,12 +538,12 @@ const WorkflowDesign: React.FC = () => {
graph.on('blank:click', () => { graph.on('blank:click', () => {
// 获取当前选中的节点 // 获取当前选中的节点
const selectedNode = graph.getSelectedCells()[0]; const selectedNode = graph.getSelectedCells()[0];
// 如果有节点被选中,恢复其样式 // 如果有节点被选中,恢复其样式
if (selectedNode && selectedNode.isNode()) { if (selectedNode && selectedNode.isNode()) {
resetNodeStyle(selectedNode); resetNodeStyle(selectedNode);
} }
// 清除选中状态 // 清除选中状态
graph.resetSelection(); graph.resetSelection();
}); });
@ -595,11 +574,11 @@ const WorkflowDesign: React.FC = () => {
const root = createRoot(dropdownContainer); const root = createRoot(dropdownContainer);
let isOpen = true; let isOpen = true;
const closeMenu = () => { const closeMenu = () => {
isOpen = false; isOpen = false;
root.render( root.render(
<Dropdown menu={{ items }} open={false} onOpenChange={(open) => { <Dropdown menu={{items}} open={false} onOpenChange={(open) => {
if (!open) { if (!open) {
setTimeout(() => { setTimeout(() => {
root.unmount(); root.unmount();
@ -607,7 +586,7 @@ const WorkflowDesign: React.FC = () => {
}, 100); }, 100);
} }
}}> }}>
<div /> <div/>
</Dropdown> </Dropdown>
); );
}; };
@ -640,8 +619,8 @@ const WorkflowDesign: React.FC = () => {
]; ];
root.render( root.render(
<Dropdown menu={{ items }} open={isOpen}> <Dropdown menu={{items}} open={isOpen}>
<div /> <div/>
</Dropdown> </Dropdown>
); );
@ -668,11 +647,11 @@ const WorkflowDesign: React.FC = () => {
const root = createRoot(dropdownContainer); const root = createRoot(dropdownContainer);
let isOpen = true; let isOpen = true;
const closeMenu = () => { const closeMenu = () => {
isOpen = false; isOpen = false;
root.render( root.render(
<Dropdown menu={{ items }} open={false} onOpenChange={(open) => { <Dropdown menu={{items}} open={false} onOpenChange={(open) => {
if (!open) { if (!open) {
setTimeout(() => { setTimeout(() => {
root.unmount(); root.unmount();
@ -680,7 +659,7 @@ const WorkflowDesign: React.FC = () => {
}, 100); }, 100);
} }
}}> }}>
<div /> <div/>
</Dropdown> </Dropdown>
); );
}; };
@ -703,8 +682,8 @@ const WorkflowDesign: React.FC = () => {
]; ];
root.render( root.render(
<Dropdown menu={{ items }} open={isOpen}> <Dropdown menu={{items}} open={isOpen}>
<div /> <div/>
</Dropdown> </Dropdown>
); );
@ -718,17 +697,17 @@ const WorkflowDesign: React.FC = () => {
}); });
// 禁用默认的右键菜单 // 禁用默认的右键菜单
graph.on('blank:contextmenu', ({ e }) => { graph.on('blank:contextmenu', ({e}) => {
e.preventDefault(); e.preventDefault();
}); });
// 禁用节点的右键菜单 // 禁用节点的右键菜单
graph.on('node:contextmenu', ({ e }) => { graph.on('node:contextmenu', ({e}) => {
e.preventDefault(); e.preventDefault();
}); });
// 禁用边的右键菜单 // 禁用边的右键菜单
graph.on('edge:contextmenu', ({ e }) => { graph.on('edge:contextmenu', ({e}) => {
e.preventDefault(); e.preventDefault();
}); });
@ -736,20 +715,20 @@ const WorkflowDesign: React.FC = () => {
graph.on('node:mouseenter', ({node}) => { graph.on('node:mouseenter', ({node}) => {
// 保存原始样式 // 保存原始样式
saveNodeOriginalStyle(node); saveNodeOriginalStyle(node);
// 显示连接桩 // 显示连接桩
const ports = document.querySelectorAll(`[data-cell-id="${node.id}"] .x6-port-body`); const ports = document.querySelectorAll(`[data-cell-id="${node.id}"] .x6-port-body`);
ports.forEach((port) => { ports.forEach((port) => {
port.setAttribute('style', 'visibility: visible; fill: #fff; stroke: #85ca6d;'); port.setAttribute('style', 'visibility: visible; fill: #fff; stroke: #85ca6d;');
}); });
// 显示悬停样式 // 显示悬停样式
node.setAttrByPath('body/stroke', hoverStyle.stroke); node.setAttrByPath('body/stroke', hoverStyle.stroke);
node.setAttrByPath('body/strokeWidth', hoverStyle.strokeWidth); node.setAttrByPath('body/strokeWidth', hoverStyle.strokeWidth);
}); });
// 连线开始时的处理 // 连线开始时的处理
graph.on('edge:connected', ({ edge }) => { graph.on('edge:connected', ({edge}) => {
// 设置连线样式 // 设置连线样式
edge.setAttrs({ edge.setAttrs({
line: { line: {
@ -764,7 +743,7 @@ const WorkflowDesign: React.FC = () => {
}); });
// 连线悬停效果 // 连线悬停效果
graph.on('edge:mouseenter', ({ edge }) => { graph.on('edge:mouseenter', ({edge}) => {
edge.setAttrs({ edge.setAttrs({
line: { line: {
stroke: '#52c41a', stroke: '#52c41a',
@ -773,7 +752,7 @@ const WorkflowDesign: React.FC = () => {
}); });
}); });
graph.on('edge:mouseleave', ({ edge }) => { graph.on('edge:mouseleave', ({edge}) => {
edge.setAttrs({ edge.setAttrs({
line: { line: {
stroke: '#5F95FF', stroke: '#5F95FF',
@ -783,7 +762,7 @@ const WorkflowDesign: React.FC = () => {
}); });
// 允许拖动连线中间的点和端点 // 允许拖动连线中间的点和端点
graph.on('edge:selected', ({ edge }) => { graph.on('edge:selected', ({edge}) => {
edge.addTools([ edge.addTools([
{ {
name: 'source-arrowhead', name: 'source-arrowhead',
@ -835,12 +814,12 @@ const WorkflowDesign: React.FC = () => {
}); });
// 连线工具移除 // 连线工具移除
graph.on('edge:unselected', ({ edge }) => { graph.on('edge:unselected', ({edge}) => {
edge.removeTools(); edge.removeTools();
}); });
// 连线移动到其他连接桩时的样式 // 连线移动到其他连接桩时的样式
graph.on('edge:connected', ({ edge }) => { graph.on('edge:connected', ({edge}) => {
edge.setAttrs({ edge.setAttrs({
line: { line: {
stroke: '#5F95FF', stroke: '#5F95FF',
@ -854,7 +833,7 @@ const WorkflowDesign: React.FC = () => {
}); });
// 连线悬停在连接桩上时的样式 // 连线悬停在连接桩上时的样式
graph.on('edge:mouseenter', ({ edge }) => { graph.on('edge:mouseenter', ({edge}) => {
const ports = document.querySelectorAll('.x6-port-body'); const ports = document.querySelectorAll('.x6-port-body');
ports.forEach((port) => { ports.forEach((port) => {
const portGroup = port.getAttribute('port-group'); const portGroup = port.getAttribute('port-group');
@ -864,7 +843,7 @@ const WorkflowDesign: React.FC = () => {
}); });
}); });
graph.on('edge:mouseleave', ({ edge }) => { graph.on('edge:mouseleave', ({edge}) => {
const ports = document.querySelectorAll('.x6-port-body'); const ports = document.querySelectorAll('.x6-port-body');
ports.forEach((port) => { ports.forEach((port) => {
port.setAttribute('style', 'visibility: hidden'); port.setAttribute('style', 'visibility: hidden');
@ -903,7 +882,7 @@ const WorkflowDesign: React.FC = () => {
message.info('剪贴板为空'); message.info('剪贴板为空');
return; return;
} }
const cells = graph.paste({ offset: 32 }); const cells = graph.paste({offset: 32});
graph.cleanSelection(); graph.cleanSelection();
graph.select(cells); graph.select(cells);
message.success('已粘贴'); message.success('已粘贴');
@ -944,7 +923,7 @@ const WorkflowDesign: React.FC = () => {
response.graph?.nodes?.forEach((workflowDefinitionNode: any) => { response.graph?.nodes?.forEach((workflowDefinitionNode: any) => {
const node = addNodeToGraph(false, graphInstance, workflowDefinitionNode, nodeDefinitions); const node = addNodeToGraph(false, graphInstance, workflowDefinitionNode, nodeDefinitions);
// 保存节点配置 // 保存节点配置
node.setProp('config', workflowDefinitionNode.config); node.setProp('workflowDefinitionNode', workflowDefinitionNode);
nodeMap.set(workflowDefinitionNode.id, node); nodeMap.set(workflowDefinitionNode.id, node);
}); });
@ -962,10 +941,10 @@ const WorkflowDesign: React.FC = () => {
// 获取源节点的输出端口一定是out组 // 获取源节点的输出端口一定是out组
const sourcePort = getPortByGroup(sourceNode, 'out'); const sourcePort = getPortByGroup(sourceNode, 'out');
// 获取目标节点的输入端口一定是in组 // 获取目标节点的输入端口一定是in组
const targetPort = getPortByGroup(targetNode, 'in'); const targetPort = getPortByGroup(targetNode, 'in');
if (!sourcePort || !targetPort) { if (!sourcePort || !targetPort) {
console.error('无法找到正确的端口:', edge); console.error('无法找到正确的端口:', edge);
return; return;
@ -1014,7 +993,7 @@ const WorkflowDesign: React.FC = () => {
const newGraph = initGraph(); const newGraph = initGraph();
if (newGraph) { if (newGraph) {
setGraph(newGraph); setGraph(newGraph);
// 在图形初始化完成后加载数据 // 在图形初始化完成后加载数据
if (id) { if (id) {
loadDefinitionDetail(newGraph, id); loadDefinitionDetail(newGraph, id);
@ -1060,6 +1039,7 @@ const WorkflowDesign: React.FC = () => {
const handleNodeConfigUpdate = (values: any) => { const handleNodeConfigUpdate = (values: any) => {
if (!selectedNode) return; if (!selectedNode) return;
// 更新节点配置 // 更新节点配置
console.log("// 更新节点配置", values);
selectedNode.setProp('config', values); selectedNode.setProp('config', values);
// 更新节点显示名称 // 更新节点显示名称
if (values.name) { if (values.name) {
@ -1094,17 +1074,18 @@ const WorkflowDesign: React.FC = () => {
type: nodeType, type: nodeType,
name: node.attr('label/text'), name: node.attr('label/text'),
graph: { graph: {
shape: nodeDefinition?.graphConfig.uiSchema.shape, // shape: nodeDefinition?.graphConfig.uiSchema.shape,
size: { // size: {
width: node.size().width, // width: node.size().width,
height: node.size().height // height: node.size().height
}, // },
style: nodeDefinition?.graphConfig.uiSchema.style, // style: nodeDefinition?.graphConfig.uiSchema.style,
ports: nodeDefinition?.graphConfig.uiSchema.ports, // ports: nodeDefinition?.graphConfig.uiSchema.ports,
position: { // position: {
x: position.x, // x: position.x,
y: position.y // y: position.y
} // }
uiVariables: nodeDefinition.uiVariables
}, },
config: node.getProp('config') || {} config: node.getProp('config') || {}
}; };
@ -1162,7 +1143,7 @@ const WorkflowDesign: React.FC = () => {
<Tooltip title="返回"> <Tooltip title="返回">
<Button <Button
className="back-button" className="back-button"
icon={<ArrowLeftOutlined />} icon={<ArrowLeftOutlined/>}
onClick={() => navigate('/workflow/definition')} onClick={() => navigate('/workflow/definition')}
/> />
</Tooltip> </Tooltip>
@ -1173,7 +1154,7 @@ const WorkflowDesign: React.FC = () => {
<Space.Compact> <Space.Compact>
<Tooltip title="撤销"> <Tooltip title="撤销">
<Button <Button
icon={<UndoOutlined />} icon={<UndoOutlined/>}
onClick={handleUndo} onClick={handleUndo}
disabled={!(graph as any)?.history?.canUndo()} disabled={!(graph as any)?.history?.canUndo()}
> >
@ -1182,7 +1163,7 @@ const WorkflowDesign: React.FC = () => {
</Tooltip> </Tooltip>
<Tooltip title="重做"> <Tooltip title="重做">
<Button <Button
icon={<RedoOutlined />} icon={<RedoOutlined/>}
onClick={handleRedo} onClick={handleRedo}
disabled={!(graph as any)?.history?.canRedo()} disabled={!(graph as any)?.history?.canRedo()}
> >
@ -1193,19 +1174,19 @@ const WorkflowDesign: React.FC = () => {
<Space.Compact> <Space.Compact>
<Tooltip title="剪切"> <Tooltip title="剪切">
<Button <Button
icon={<ScissorOutlined />} icon={<ScissorOutlined/>}
onClick={handleCut} onClick={handleCut}
/> />
</Tooltip> </Tooltip>
<Tooltip title="复制"> <Tooltip title="复制">
<Button <Button
icon={<CopyOutlined />} icon={<CopyOutlined/>}
onClick={handleCopy} onClick={handleCopy}
/> />
</Tooltip> </Tooltip>
<Tooltip title="粘贴"> <Tooltip title="粘贴">
<Button <Button
icon={<SnippetsOutlined />} icon={<SnippetsOutlined/>}
onClick={handlePaste} onClick={handlePaste}
/> />
</Tooltip> </Tooltip>
@ -1213,7 +1194,7 @@ const WorkflowDesign: React.FC = () => {
<Space.Compact> <Space.Compact>
<Tooltip title="放大"> <Tooltip title="放大">
<Button <Button
icon={<ZoomInOutlined />} icon={<ZoomInOutlined/>}
onClick={handleZoomIn} onClick={handleZoomIn}
disabled={scale >= 2} disabled={scale >= 2}
> >
@ -1222,7 +1203,7 @@ const WorkflowDesign: React.FC = () => {
</Tooltip> </Tooltip>
<Tooltip title="缩小"> <Tooltip title="缩小">
<Button <Button
icon={<ZoomOutOutlined />} icon={<ZoomOutOutlined/>}
onClick={handleZoomOut} onClick={handleZoomOut}
disabled={scale <= 0.2} disabled={scale <= 0.2}
> >
@ -1233,25 +1214,25 @@ const WorkflowDesign: React.FC = () => {
<Space.Compact> <Space.Compact>
<Tooltip title="全选"> <Tooltip title="全选">
<Button <Button
icon={<SelectOutlined />} icon={<SelectOutlined/>}
onClick={() => { onClick={() => {
if (!graph) return; if (!graph) return;
// 添加小延时确保图形已完全初始化 // 添加小延时确保图形已完全初始化
setTimeout(() => { setTimeout(() => {
const cells = graph.getCells(); const cells = graph.getCells();
console.log('All cells:', cells); console.log('All cells:', cells);
if (cells.length === 0) { if (cells.length === 0) {
message.info('当前没有可选择的元素'); message.info('当前没有可选择的元素');
return; return;
} }
// 打印当前选择状态 // 打印当前选择状态
console.log('Current selection before reset:', graph.getSelectedCells()); console.log('Current selection before reset:', graph.getSelectedCells());
graph.resetSelection(); graph.resetSelection();
console.log('Selection after reset:', graph.getSelectedCells()); console.log('Selection after reset:', graph.getSelectedCells());
// 尝试选择所有单元格 // 尝试选择所有单元格
try { try {
graph.select(cells); graph.select(cells);
@ -1259,7 +1240,7 @@ const WorkflowDesign: React.FC = () => {
} catch (error) { } catch (error) {
console.error('Error selecting cells:', error); console.error('Error selecting cells:', error);
} }
// 检查Selection插件是否正确初始化 // 检查Selection插件是否正确初始化
const selection = graph.getPlugin('selection'); const selection = graph.getPlugin('selection');
console.log('Selection plugin:', selection); console.log('Selection plugin:', selection);
@ -1269,7 +1250,7 @@ const WorkflowDesign: React.FC = () => {
</Tooltip> </Tooltip>
<Tooltip title="删除"> <Tooltip title="删除">
<Button <Button
icon={<DeleteOutlined />} icon={<DeleteOutlined/>}
onClick={() => { onClick={() => {
if (!graph) return; if (!graph) return;
const cells = graph.getSelectedCells(); const cells = graph.getSelectedCells();
@ -1291,7 +1272,7 @@ const WorkflowDesign: React.FC = () => {
<Tooltip title="保存"> <Tooltip title="保存">
<Button <Button
type="primary" type="primary"
icon={<SaveOutlined />} icon={<SaveOutlined/>}
onClick={handleSaveWorkflow} onClick={handleSaveWorkflow}
> >
@ -1309,13 +1290,13 @@ const WorkflowDesign: React.FC = () => {
</div> </div>
<div className="main-area"> <div className="main-area">
<div className="workflow-container"> <div className="workflow-container">
<div <div
ref={graphContainerRef} ref={graphContainerRef}
className="workflow-canvas" className="workflow-canvas"
onDrop={handleDrop} onDrop={handleDrop}
onDragOver={handleDragOver} onDragOver={handleDragOver}
/> />
<div ref={minimapContainerRef} className="minimap-container" /> <div ref={minimapContainerRef} className="minimap-container"/>
</div> </div>
</div> </div>
</div> </div>

View File

@ -108,6 +108,7 @@ const validateAllNodesConfig = (graph: Graph): ValidationResult => {
for (const node of nodes) { for (const node of nodes) {
const nodeDefinition = node.getProp('nodeDefinition'); const nodeDefinition = node.getProp('nodeDefinition');
console.log(nodeDefinition)
const result = validateNodeConfig(node, nodeDefinition); const result = validateNodeConfig(node, nodeDefinition);
if (!result.valid) { if (!result.valid) {
return result; return result;

View File

@ -1,27 +1,38 @@
import { BaseResponse, BaseQuery } from '@/types/base'; import {BaseResponse, BaseQuery} from '@/types/base';
export interface WorkflowDefinition extends BaseResponse { export interface WorkflowDefinition extends BaseResponse {
id: number; id: number;
name: string; name: string;
key: string; key: string;
description?: string; description?: string;
flowVersion?: number; flowVersion?: number;
status?: string; status?: string;
category: string; category: string;
triggers: string[]; triggers: string[];
graph: { graph: {
nodes: any[]; nodes: WorkflowDefinitionNode[];
edges: any[]; edges: any[];
}; };
formConfig: { formConfig: {
formItems: any[]; formItems: any[];
}; };
}
export interface WorkflowDefinitionNode {
id: number;
code: string;
type: string;
name: string;
uiVariables: JSON;
panelVariables: JSON;
localVariables: JSON;
formVariables: JSON;
} }
export interface WorkflowDefinitionQuery extends BaseQuery { export interface WorkflowDefinitionQuery extends BaseQuery {
name?: string; name?: string;
key?: string; key?: string;
status?: string; status?: string;
} }
/** /**