feat(flowEditor): 添加等待节点编辑器

- 实现了等待节点的编辑器组件,包括小时、分钟、秒的选择
- 添加了节点别名和描述的编辑功能
- 优化了节点 footer 的显示逻辑,支持自定义内容- 修复了与门和或门节点不可编辑的问题
master
钟良源 5 months ago
parent d92beca5c1
commit 75aaa9a02e

@ -176,12 +176,21 @@ const renderRegularNodeHandles = (dataIns: any[], dataOuts: any[], apiIns: any[]
); );
}; };
// 通过duration计算时分秒
const formatDuration = (duration: number) => {
const hours = Math.floor(duration / 3600);
const minutes = Math.floor((duration % 3600) / 60);
const seconds = Math.floor(duration % 60);
return `${hours}小时${minutes}分钟${seconds}`;
};
const NodeContent = ({ data }: { data: NodeContentData }) => { const NodeContent = ({ data }: { data: NodeContentData }) => {
const apiIns = data.parameters?.apiIns || []; const apiIns = data.parameters?.apiIns || [];
const apiOuts = data.parameters?.apiOuts || []; const apiOuts = data.parameters?.apiOuts || [];
const dataIns = data.parameters?.dataIns || []; const dataIns = data.parameters?.dataIns || [];
const dataOuts = data.parameters?.dataOuts || []; const dataOuts = data.parameters?.dataOuts || [];
const showFooter = data.showFooter || false; const showFooter = data?.component?.customDef || false;
const footerData = (showFooter && JSON.parse(data.component?.customDef)) || {};
// 判断节点类型 // 判断节点类型
const isStartNode = data.type === 'start'; const isStartNode = data.type === 'start';
@ -216,7 +225,7 @@ const NodeContent = ({ data }: { data: NodeContentData }) => {
{/*footer栏*/} {/*footer栏*/}
{showFooter && ( {showFooter && (
<div className={styles['node-footer']}> <div className={styles['node-footer']}>
footer {formatDuration(footerData.duration)}
</div> </div>
)} )}

@ -161,6 +161,8 @@ const FlowEditor: React.FC = () => {
// 节点双击处理 // 节点双击处理
const onNodeDoubleClick = useCallback( const onNodeDoubleClick = useCallback(
(event: React.MouseEvent, node: Node) => { (event: React.MouseEvent, node: Node) => {
// 与门和或门不可编辑
if (['AND', 'OR'].includes(node.type)) return;
setEditingNode(node); setEditingNode(node);
setIsEditModalOpen(true); setIsEditModalOpen(true);
}, },

@ -50,5 +50,6 @@
padding: 5px 20px; padding: 5px 20px;
border-top: 1px solid rgba(204, 204, 204, 0.18); border-top: 1px solid rgba(204, 204, 204, 0.18);
min-height: 20px; min-height: 20px;
text-align: center;
} }
} }

@ -66,7 +66,7 @@ const LocalNodeEditor: React.FC<NodeEditorProps> = ({
onChange={(value) => updateNodeData('title', value)} onChange={(value) => updateNodeData('title', value)}
/> />
</Form.Item> </Form.Item>
<Form.Item label="描述"> <Form.Item label="节点描述">
<Input.TextArea <Input.TextArea
value={nodeData.description || ''} value={nodeData.description || ''}
onChange={(value) => updateNodeData('description', value)} onChange={(value) => updateNodeData('description', value)}

@ -1,22 +1,118 @@
import React from 'react'; import React, { useEffect, useState } from 'react';
import { NodeEditorProps } from '@/pages/flowEditor/nodeEditors'; import { NodeEditorProps } from '@/pages/flowEditor/nodeEditors';
import { Typography } from '@arco-design/web-react'; import { Form, Input, Select } from '@arco-design/web-react';
import { IconUnorderedList } from '@arco-design/web-react/icon';
import ParamsTable from './ParamsTable'; const { Option } = Select;
interface DurationType {
hour: number;
minute: number;
second: number;
time: number;
}
const WaitEditor: React.FC<NodeEditorProps> = ({ nodeData, updateNodeData }) => { const WaitEditor: React.FC<NodeEditorProps> = ({ nodeData, updateNodeData }) => {
console.log('nodeData:', nodeData);
const hourOptions = Array.from({ length: 23 }, (_, i) => i);
const minuteOptions = Array.from({ length: 59 }, (_, i) => i);
const secondOptions = Array.from({ length: 59 }, (_, i) => i);
const [duration, setDuration] = useState<DurationType>({
hour: 0,
minute: 0,
second: 0,
time: 0
});
useEffect(() => {
if (nodeData.component.customDef) {
const duration = JSON.parse(nodeData.component.customDef).duration;
setDuration({
hour: Math.floor(duration / 3600),
minute: Math.floor((duration % 3600) / 60),
second: Math.floor(duration % 60),
time: duration
});
}
}, [nodeData]);
const handleChangeDuration = (newDuration: DurationType) => {
const time = (newDuration.hour || 0) * 60 * 60 + (newDuration.minute || 0) * 60 + (newDuration.second || 0);
setDuration({
...newDuration,
time
});
updateNodeData('component', {
customDef: JSON.stringify({ duration: time }),
type: 'WAIT'
});
};
return ( return (
<> <>
<Typography.Title heading={5}><IconUnorderedList style={{ marginRight: 5 }} /></Typography.Title> <Form.Item label="节点别名">
<ParamsTable <Input
initialData={nodeData.parameters.dataIns || []} value={nodeData.title || ''}
onUpdateData={(data) => { onChange={(value) => updateNodeData('alias', value)}
updateNodeData('parameters', {
...nodeData.parameters,
dataIns: data
});
}}
/> />
</Form.Item>
<Form.Item label="节点描述">
<Input.TextArea
value={nodeData.description || ''}
onChange={(value) => updateNodeData('description', value)}
/>
</Form.Item>
<Form.Item label="等待时间">
<div
style={{ display: 'flex', alignItems: 'center' }}
>
<Select
placeholder="小时"
value={duration.hour || undefined}
onChange={(value) => {
const newDuration = { ...duration, hour: value };
handleChangeDuration(newDuration);
}}
>
{hourOptions.map((option) => (
<Option key={option} value={option}>
{option}
</Option>
))}
</Select>
<div style={{ margin: '0 10px' }}></div>
<Select
placeholder="分钟"
value={duration.minute || undefined}
onChange={(value) => {
const newDuration = { ...duration, minute: value };
handleChangeDuration(newDuration);
}}
>
{minuteOptions.map((option) => (
<Option key={option} value={option}>
{option}
</Option>
))}
</Select>
<div style={{ margin: '0 10px' }}></div>
<Select
placeholder="秒"
value={duration.second || undefined}
onChange={(value) => {
const newDuration = { ...duration, second: value };
handleChangeDuration(newDuration);
}}
>
{secondOptions.map((option) => (
<Option key={option} value={option}>
{option}
</Option>
))}
</Select>
<div style={{ margin: '0 10px' }}></div>
</div>
</Form.Item>
</> </>
); );
}; };

Loading…
Cancel
Save