1
This commit is contained in:
parent
f55b21d5ab
commit
45264109d0
@ -3,6 +3,7 @@ import { useParams, useNavigate } from 'react-router-dom';
|
||||
import { Button, Space, Card, Row, Col, message, Modal } from 'antd';
|
||||
import { ArrowLeftOutlined, SaveOutlined, PlayCircleOutlined } from '@ant-design/icons';
|
||||
import { Graph, Cell } from '@antv/x6';
|
||||
import '@antv/x6-plugin-snapline';
|
||||
import { getDefinitionDetail, saveDefinition } from '../service';
|
||||
import { getNodeDefinitionList } from './service';
|
||||
import NodePanel from './components/NodePanel';
|
||||
@ -119,9 +120,9 @@ const WorkflowDesign: React.FC = () => {
|
||||
};
|
||||
}, [graphContainerRef, id, nodeDefinitions, isNodeDefinitionsLoaded]);
|
||||
|
||||
const loadDefinitionDetail = async (graphInstance: Graph, definitionId: number) => {
|
||||
const loadDefinitionDetail = async (graphInstance: Graph, definitionId: string) => {
|
||||
try {
|
||||
const response = await getDefinitionDetail(definitionId);
|
||||
const response = await getDefinitionDetail(Number(definitionId));
|
||||
setTitle(`工作流设计 - ${response.name}`);
|
||||
setDefinitionData(response);
|
||||
|
||||
@ -131,8 +132,6 @@ const WorkflowDesign: React.FC = () => {
|
||||
|
||||
// 创建节点
|
||||
response.graph?.nodes?.forEach((workflowDefinitionNode: any) => {
|
||||
console.log('Creating node with data:', workflowDefinitionNode); // 添加日志
|
||||
|
||||
const node = addNodeToGraph(false, graphInstance, workflowDefinitionNode, nodeDefinitions);
|
||||
// 保存节点配置
|
||||
node.setProp('config', workflowDefinitionNode.config);
|
||||
@ -155,8 +154,8 @@ const WorkflowDesign: React.FC = () => {
|
||||
}
|
||||
});
|
||||
|
||||
// 应用自动布局
|
||||
applyAutoLayout(graphInstance);
|
||||
// 传入节点数据,只在没有位置信息时应用自动布局
|
||||
applyAutoLayout(graphInstance, response.graph?.nodes || []);
|
||||
} catch (error) {
|
||||
console.error('加载工作流定义失败:', error);
|
||||
message.error('加载工作流定义失败');
|
||||
@ -217,6 +216,7 @@ const WorkflowDesign: React.FC = () => {
|
||||
const nodes = graph.getNodes().map(node => {
|
||||
const nodeDefinition = node.getProp('nodeDefinition');
|
||||
const nodeType = node.getProp('type');
|
||||
const position = node.getPosition();
|
||||
|
||||
return {
|
||||
id: node.id,
|
||||
@ -230,7 +230,11 @@ const WorkflowDesign: React.FC = () => {
|
||||
height: node.size().height
|
||||
},
|
||||
style: nodeDefinition?.graphConfig.uiSchema.style,
|
||||
ports: nodeDefinition?.graphConfig.uiSchema.ports
|
||||
ports: nodeDefinition?.graphConfig.uiSchema.ports,
|
||||
position: {
|
||||
x: position.x,
|
||||
y: position.y
|
||||
}
|
||||
},
|
||||
config: node.getProp('config') || {}
|
||||
};
|
||||
|
||||
@ -1,11 +1,40 @@
|
||||
import { Graph } from '@antv/x6';
|
||||
import dagre from 'dagre';
|
||||
|
||||
interface NodeData {
|
||||
graph: {
|
||||
position?: {
|
||||
x: number;
|
||||
y: number;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查是否所有节点都有位置信息
|
||||
* @param nodes 节点列表
|
||||
* @returns 是否所有节点都有位置信息
|
||||
*/
|
||||
const hasAllNodesPosition = (nodes: NodeData[]) => {
|
||||
return nodes.every(node => {
|
||||
const graphData = node.graph;
|
||||
return graphData && graphData.position &&
|
||||
typeof graphData.position.x === 'number' &&
|
||||
typeof graphData.position.y === 'number';
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 应用自动布局
|
||||
* @param graph 图形实例
|
||||
* @param nodes 节点数据列表
|
||||
*/
|
||||
export const applyAutoLayout = (graph: Graph) => {
|
||||
export const applyAutoLayout = (graph: Graph, nodes: NodeData[] = []) => {
|
||||
// 如果所有节点都有位置信息,则不应用自动布局
|
||||
if (nodes.length > 0 && hasAllNodesPosition(nodes)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const g = new dagre.graphlib.Graph();
|
||||
g.setGraph({
|
||||
rankdir: 'LR',
|
||||
@ -18,8 +47,8 @@ export const applyAutoLayout = (graph: Graph) => {
|
||||
g.setDefaultEdgeLabel(() => ({}));
|
||||
|
||||
// 添加节点
|
||||
const nodes = graph.getNodes();
|
||||
nodes.forEach(node => {
|
||||
const graphNodes = graph.getNodes();
|
||||
graphNodes.forEach(node => {
|
||||
g.setNode(node.id, {
|
||||
width: node.getSize().width,
|
||||
height: node.getSize().height,
|
||||
@ -36,7 +65,7 @@ export const applyAutoLayout = (graph: Graph) => {
|
||||
dagre.layout(g);
|
||||
|
||||
// 应用布局结果
|
||||
nodes.forEach(node => {
|
||||
graphNodes.forEach(node => {
|
||||
const nodeWithPosition = g.node(node.id);
|
||||
node.position(
|
||||
nodeWithPosition.x - nodeWithPosition.width / 2,
|
||||
|
||||
@ -3,20 +3,23 @@ import {convertPortConfig} from '../constants';
|
||||
|
||||
/**
|
||||
* 添加节点到图形
|
||||
* @param isNew 是否为新节点
|
||||
* @param graph X6 Graph实例
|
||||
* @param node 节点数据
|
||||
* @param position 节点位置(可选)
|
||||
* @param workflowDefinitionNode 工作流节点定义
|
||||
* @param workflowNodeDefinitionList 工作流节点定义列表
|
||||
* @param position 新节点的位置(可选)
|
||||
* @returns 创建的节点实例
|
||||
*/
|
||||
export const addNodeToGraph = (
|
||||
isNew: Boolean,
|
||||
isNew: boolean,
|
||||
graph: Graph,
|
||||
workflowDefinitionNode: any,
|
||||
workflowNodeDefinitionList: any,
|
||||
position?: { x: number, y: number }
|
||||
position?: { x: number; y: number }
|
||||
) => {
|
||||
let nodeDefinition = workflowNodeDefinitionList.find(def => def.type === workflowDefinitionNode.type);
|
||||
let uiGraph = isNew ? nodeDefinition.graphConfig.uiSchema : workflowDefinitionNode.graph;
|
||||
|
||||
// 根据形状类型设置正确的 shape
|
||||
let shape = 'rect'; // 默认使用矩形
|
||||
if (uiGraph.shape === 'circle') {
|
||||
@ -24,8 +27,9 @@ export const addNodeToGraph = (
|
||||
} else if (uiGraph.shape === 'diamond') {
|
||||
shape = 'polygon';
|
||||
}
|
||||
// 创建节点
|
||||
return graph.addNode({
|
||||
|
||||
// 创建节点配置
|
||||
const nodeConfig = {
|
||||
inherit: 'rect',
|
||||
width: uiGraph.size.width,
|
||||
height: uiGraph.size.height,
|
||||
@ -40,14 +44,26 @@ export const addNodeToGraph = (
|
||||
text: isNew ? nodeDefinition.name : workflowDefinitionNode.name
|
||||
},
|
||||
},
|
||||
shape, // 使用映射后的形状
|
||||
...(position && {x: position.x, y: position.y}),
|
||||
// 如果是已保存的节点,使用其ID和位置
|
||||
...(uiGraph.id && {id: uiGraph.id}),
|
||||
...(uiGraph.graph?.position && {position: uiGraph.graph.position}),
|
||||
shape,
|
||||
type: isNew ? nodeDefinition.type : workflowDefinitionNode.type,
|
||||
code: uiGraph.code,
|
||||
ports: convertPortConfig(uiGraph.ports),
|
||||
nodeDefinition: nodeDefinition
|
||||
});
|
||||
};
|
||||
|
||||
// 设置节点位置
|
||||
if (isNew && position) {
|
||||
// 新节点:使用传入的position
|
||||
Object.assign(nodeConfig, { x: position.x, y: position.y });
|
||||
} else if (!isNew && workflowDefinitionNode.graph?.position) {
|
||||
// 已有节点:使用后端返回的position
|
||||
Object.assign(nodeConfig, { position: workflowDefinitionNode.graph.position });
|
||||
}
|
||||
|
||||
// 设置节点ID(如果有)
|
||||
if (uiGraph.id) {
|
||||
Object.assign(nodeConfig, { id: uiGraph.id });
|
||||
}
|
||||
|
||||
return graph.addNode(nodeConfig);
|
||||
};
|
||||
Loading…
Reference in New Issue
Block a user