feat(flowEditor): 添加默认节点

- 开始节点和结束节点
master
钟良源 5 months ago
parent 80627b2c32
commit b784cb158b

@ -36,14 +36,14 @@ const initialNodes: Node[] = [
}, },
{ {
id: 'end-node', id: 'end-node',
position: { x: 300, y: 200 }, position: { x: 1000, y: 0 },
data: { label: '结束' }, data: { label: '结束' },
type: 'end' type: 'end'
}, },
{ {
id: 'node-1', id: 'node-1',
type: 'textUpdater', type: 'textUpdater',
position: { x: 150, y: 0 }, position: { x: 400, y: 0 },
data: { value: 123 } data: { value: 123 }
} }
]; ];
@ -111,14 +111,14 @@ const FlowEditor: React.FC = () => {
const position = reactFlowInstance.screenToFlowPosition({ const position = reactFlowInstance.screenToFlowPosition({
x: event.clientX, x: event.clientX,
y: event.clientY, y: event.clientY
}); });
const newNode = { const newNode = {
id: `${type}-${Date.now()}`, id: `${type}-${Date.now()}`,
type, type,
position, position,
data: { label: `${type} node` }, data: { label: `${type} node` }
}; };
setNodes((nds) => nds.concat(newNode)); setNodes((nds) => nds.concat(newNode));

@ -1,22 +1,96 @@
import React from 'react'; import React from 'react';
import { Handle, Position } from '@xyflow/react'; import { Handle, Position } from '@xyflow/react';
import styles from '@/pages/flowEditor/node/style/base.module.less';
interface EndNodeData {
title?: string;
parameters?: {
inputs?: any[];
outputs?: any[];
};
showFooter?: boolean;
[key: string]: any;
}
const EndNode = ({ data }: { data: EndNodeData }) => {
const title = data.title || '结束';
const inputs = data.parameters?.inputs || [];
const outputs = data.parameters?.outputs || [];
const showFooter = data.showFooter || false;
const EndNode = ({ data }: { data: any }) => {
return ( return (
<div style={{ <div className={styles['node-container']}>
padding: '10px 20px', <div className={styles['node-header']} style={{ backgroundColor: '#c05144' }}>
backgroundColor: '#ff4d4f', {title}
borderRadius: '5px', </div>
color: 'white',
fontWeight: 'bold' <div className={styles['node-content']}>
}}> {inputs.length > 0 && (
<div></div> <div className={styles['node-inputs']}>
{inputs.map((input, index) => (
<div key={`input-${index}`} className={styles['node-input-label']}>
{input.name || `输入${index + 1}`}
</div>
))}
</div>
)}
{outputs.length > 0 && (
<div className={styles['node-outputs']}>
{outputs.map((output, index) => (
<div key={`output-${index}`} style={{ fontSize: '12px', padding: '2px 0' }}>
{output.name || `输出${index + 1}`}
</div>
))}
</div>
)}
</div>
{showFooter && (
<div className={styles['node-footer']}>
footer
</div>
)}
{/* Dynamic handles based on parameters */}
<Handle <Handle
type="target" type="target"
position={Position.Left} position={Position.Left}
id="end-target" id="end-target"
style={{ background: '#555' }} style={{
background: '#555',
top: '40px'
}}
/> />
{/* Add additional handles based on parameters */}
{inputs.map((_, index) => (
<Handle
key={`input-handle-${index}`}
type="target"
position={Position.Left}
id={`input-${index}`}
style={{
background: '#555',
top: `${60 + index * 20}px`
}}
/>
))}
{outputs.map((_, index) => (
<Handle
key={`output-handle-${index}`}
type="source"
position={Position.Right}
id={`output-${index}`}
style={{
background: '#555',
// top: `${80 + inputs.length * 20 + index * 20}px`
top: `${60 + index * 20}px`
}}
/>
))}
</div> </div>
); );
}; };

@ -1,22 +1,96 @@
import React from 'react'; import React from 'react';
import { Handle, Position } from '@xyflow/react'; import { Handle, Position } from '@xyflow/react';
import styles from '@/pages/flowEditor/node/style/base.module.less';
const StartNode = ({ data }: { data: any }) => { interface StartNodeData {
title?: string;
parameters?: {
inputs?: any[];
outputs?: any[];
};
showFooter?: boolean;
[key: string]: any;
}
const StartNode = ({ data }: { data: StartNodeData }) => {
const title = data.title || '开始';
const inputs = data.parameters?.inputs || [];
const outputs = data.parameters?.outputs || [];
const showFooter = data.showFooter || false;
return ( return (
<div style={{ <div className={styles['node-container']}>
padding: '10px 20px', <div className={styles['node-header']} style={{ backgroundColor: '#29b971' }}>
backgroundColor: '#52c41a', {title}
borderRadius: '5px', </div>
color: 'white',
fontWeight: 'bold' <div className={styles['node-content']}>
}}>
<div></div> {inputs.length > 0 && (
<div className={styles['node-inputs']}>
{inputs.map((input, index) => (
<div key={`input-${index}`} className={styles['node-input-label']}>
{input.name || `输入${index + 1}`}
</div>
))}
</div>
)}
{outputs.length > 0 && (
<div className={styles['node-outputs']}>
{outputs.map((output, index) => (
<div key={`output-${index}`} style={{ fontSize: '12px', padding: '2px 0' }}>
{output.name || `输出${index + 1}`}
</div>
))}
</div>
)}
</div>
{showFooter && (
<div className={styles['node-footer']}>
footer
</div>
)}
{/* Dynamic handles based on parameters */}
<Handle <Handle
type="source" type="source"
position={Position.Right} position={Position.Right}
id="start-source" id="start-source"
style={{ background: '#555' }} style={{
background: '#555',
top: '40px'
}}
/> />
{/* Add additional handles based on parameters */}
{inputs.map((_, index) => (
<Handle
key={`input-handle-${index}`}
type="target"
position={Position.Left}
id={`input-${index}`}
style={{
background: '#555',
top: `${60 + index * 20}px`
}}
/>
))}
{outputs.map((_, index) => (
<Handle
key={`output-handle-${index}`}
type="source"
position={Position.Right}
id={`output-${index}`}
style={{
background: '#555',
// top: `${80 + inputs.length * 20 + index * 20}px`
top: `${60 + index * 20}px`
}}
/>
))}
</div> </div>
); );
}; };

@ -0,0 +1,47 @@
.node-container {
border-radius: 10px;
overflow: hidden;
color: white;
min-width: 150px;
font-size: 14px;
.node-header {
padding: 5px 15px;
border-bottom: 1px solid rgba(255, 255, 255, 0.2);
}
.node-content {
display: flex;
background-color: #ffffff;
color: #000000;
padding: 15px 5px;
min-height: 10px;
.node-inputs,
.node-outputs {
flex: 1;
.node-input-label {
font-size: 12px;
padding: 2px 0;
}
}
.node-inputs {
margin-bottom: 5px;
margin-right: 30px;
}
.node-outputs {
text-align: right;
}
}
.node-footer {
background-color: #ffffff;
color: #000000;
padding: 5px 20px;
border-top: 1px solid rgba(204, 204, 204, 0.18);
min-height: 20px;
}
}
Loading…
Cancel
Save