feat(orchestration): 添加应用编排功能
- 在 ideContainer 中引入 ProjectContainer 组件 - 新增 flowEditor 目录及其相关组件 - 实现基本的流程编辑器功能,包括节点拖拽、连接等 - 添加自定义节点类型 TextUpdaterNodeproduction
parent
cceac6bec2
commit
b7586b95b8
@ -0,0 +1,94 @@
|
|||||||
|
import React, { useState, useCallback } from 'react';
|
||||||
|
import {
|
||||||
|
ReactFlow,
|
||||||
|
applyNodeChanges,
|
||||||
|
applyEdgeChanges,
|
||||||
|
addEdge,
|
||||||
|
Background,
|
||||||
|
Controls,
|
||||||
|
Node,
|
||||||
|
Edge
|
||||||
|
} from '@xyflow/react';
|
||||||
|
import '@xyflow/react/dist/style.css';
|
||||||
|
import TextUpdaterNode from './node/textUpdateNode/TextUpdaterNode';
|
||||||
|
|
||||||
|
const nodeTypes = {
|
||||||
|
textUpdater: TextUpdaterNode
|
||||||
|
};
|
||||||
|
|
||||||
|
const initialNodes: Node[] = [
|
||||||
|
{
|
||||||
|
id: 'n1',
|
||||||
|
position: { x: 0, y: 0 },
|
||||||
|
data: { label: 'Node 1' },
|
||||||
|
type: 'input'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'node-1',
|
||||||
|
type: 'textUpdater',
|
||||||
|
position: { x: 150, y: 0 },
|
||||||
|
data: { value: 123 }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'n2',
|
||||||
|
position: { x: 100, y: 100 },
|
||||||
|
data: { label: 'Custom Node' }
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
const initialEdges: Edge[] = [
|
||||||
|
{
|
||||||
|
id: 'n1-n2',
|
||||||
|
source: 'n1',
|
||||||
|
target: 'n2'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'n1-node-1',
|
||||||
|
source: 'n1',
|
||||||
|
target: 'node-1',
|
||||||
|
targetHandle: 'a'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'n2-node-1',
|
||||||
|
source: 'n2',
|
||||||
|
target: 'node-1',
|
||||||
|
targetHandle: 'a1'
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
const FlowEditor: React.FC = () => {
|
||||||
|
const [nodes, setNodes] = useState<Node[]>(initialNodes);
|
||||||
|
const [edges, setEdges] = useState<Edge[]>(initialEdges);
|
||||||
|
|
||||||
|
const onNodesChange = useCallback(
|
||||||
|
(changes: any) => setNodes((nodesSnapshot) => applyNodeChanges(changes, nodesSnapshot)),
|
||||||
|
[]
|
||||||
|
);
|
||||||
|
const onEdgesChange = useCallback(
|
||||||
|
(changes: any) => setEdges((edgesSnapshot) => applyEdgeChanges(changes, edgesSnapshot)),
|
||||||
|
[]
|
||||||
|
);
|
||||||
|
const onConnect = useCallback(
|
||||||
|
(params: any) => setEdges((edgesSnapshot) => addEdge(params, edgesSnapshot)),
|
||||||
|
[]
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div style={{ width: '90vw', height: '91vh' }}>
|
||||||
|
<ReactFlow
|
||||||
|
nodes={nodes}
|
||||||
|
edges={edges}
|
||||||
|
nodeTypes={nodeTypes}
|
||||||
|
onNodesChange={onNodesChange}
|
||||||
|
onEdgesChange={onEdgesChange}
|
||||||
|
onConnect={onConnect}
|
||||||
|
fitView
|
||||||
|
>
|
||||||
|
<Background />
|
||||||
|
<Controls />
|
||||||
|
</ReactFlow>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default React.memo(FlowEditor);
|
||||||
@ -0,0 +1,14 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { Handle, Position } from '@xyflow/react';
|
||||||
|
|
||||||
|
const CustomNode = ({ data }) => {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<div style={{ padding: '10px 20px' }}>
|
||||||
|
{data.label}
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default CustomNode;
|
||||||
@ -0,0 +1,8 @@
|
|||||||
|
.text-updater-node {
|
||||||
|
//width: 150px;
|
||||||
|
//height: 80px;
|
||||||
|
padding: 20px;
|
||||||
|
border-radius: 15px;
|
||||||
|
border: 1px solid #cccccc;
|
||||||
|
background-color: #fff;
|
||||||
|
}
|
||||||
@ -0,0 +1,30 @@
|
|||||||
|
import React, { useCallback } from 'react';
|
||||||
|
import style from './TextUpdaterNode.module.less';
|
||||||
|
import { Handle, NodeProps, Position } from '@xyflow/react';
|
||||||
|
|
||||||
|
interface TextUpdaterNodeData {
|
||||||
|
data?: string;
|
||||||
|
id?: string;
|
||||||
|
}
|
||||||
|
const TextUpdaterNode: React.FC<NodeProps> = (props) => {
|
||||||
|
const onChange = useCallback((evt: React.ChangeEvent<HTMLInputElement>) => {
|
||||||
|
console.log(evt.target.value);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={style['text-updater-node']}>
|
||||||
|
<div>
|
||||||
|
<label htmlFor="text">Text:</label>
|
||||||
|
<input id="text" name="text" onChange={onChange} className="nodrag" />
|
||||||
|
</div>
|
||||||
|
<Handle type="target" position={Position.Left} id="a" />
|
||||||
|
<Handle type="target" position={Position.Bottom} id="a1" />
|
||||||
|
<Handle type="target" position={Position.Top} id="a2" />
|
||||||
|
<Handle type="source" position={Position.Right} id="b" />
|
||||||
|
<Handle type="source" position={Position.Right} style={{ top: 10 }} id="b1" />
|
||||||
|
<Handle type="source" position={Position.Right} style={{ top: 20 }} id="b2" />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default TextUpdaterNode;
|
||||||
@ -0,0 +1,10 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import FlowEditor from '@/pages/flowEditor/index';
|
||||||
|
|
||||||
|
const ProjectContainer = () => {
|
||||||
|
return (
|
||||||
|
<FlowEditor />
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ProjectContainer;
|
||||||
Loading…
Reference in New Issue