feat(flow): 添加节点状态管理和历史实例查看功能

master
钟良源 1 week ago
parent 88b3f90138
commit 5a06269e1d

@ -48,6 +48,7 @@ const InstanceCanvas: React.FC<InstanceCanvasProps> = ({ instanceData, title, on
const [runtimeLogs, setRuntimeLogs] = useState<LogMessage[]>([]);
const [runtimeData, setRuntimeData] = useState<RuntimeData>({});
const [flowData, setFlowData] = useState<any>(null); // 流程数据
const [nodeStatusMap, setNodeStatusMap] = useState<Record<string, string>>({}); // 节点状态映射
const [loading, setLoading] = useState(false); // 加载状态
const resizeBoxRef = useRef<HTMLDivElement>(null);
const flowDataRef = useRef<any>(null); // 使用 ref 来存储 flowData避免重复设置
@ -111,6 +112,8 @@ const InstanceCanvas: React.FC<InstanceCanvasProps> = ({ instanceData, title, on
}
};
console.log('InstanceCanvas - 转换后的 flowData:', newFlowData);
// 只在数据真正变化时才更新
if (!flowDataRef.current) {
flowDataRef.current = newFlowData;
@ -118,7 +121,7 @@ const InstanceCanvas: React.FC<InstanceCanvasProps> = ({ instanceData, title, on
}
}
// 处理运行日志
// 处理运行日志和节点状态
if (res.data.main?.nodeLogs && Array.isArray(res.data.main.nodeLogs) && res.data.main.nodeLogs.length > 0) {
const logs = res.data.main.nodeLogs.map((log: any, index: number) => ({
id: index,
@ -131,6 +134,20 @@ const InstanceCanvas: React.FC<InstanceCanvasProps> = ({ instanceData, title, on
state: log.state
}));
setRuntimeLogs(logs);
// 构建节点状态映射
const statusMap: Record<string, string> = {};
res.data.main.nodeLogs.forEach((log: any) => {
// state: 1=成功(success), 0=运行中(running), -1=失败(failed)
if (log.state === 1) {
statusMap[log.nodeId] = 'success';
} else if (log.state === -1) {
statusMap[log.nodeId] = 'failed';
} else if (log.state === 0) {
statusMap[log.nodeId] = 'running';
}
});
setNodeStatusMap(statusMap);
}
// 处理运行数据input/output
@ -198,6 +215,40 @@ const InstanceCanvas: React.FC<InstanceCanvasProps> = ({ instanceData, title, on
}
}, []);
// 使用 useMemo 创建带有节点状态的 flowData
const flowDataWithStatus = useMemo(() => {
if (!flowData || Object.keys(nodeStatusMap).length === 0) {
return flowData;
}
console.log('InstanceCanvas - 注入状态前的 flowData:', flowData);
console.log('InstanceCanvas - 要注入的状态映射:', nodeStatusMap);
// 深拷贝 flowData 并注入节点状态
const componentsWithStatus = { ...flowData.components };
Object.keys(nodeStatusMap).forEach((nodeId) => {
if (componentsWithStatus[nodeId]) {
componentsWithStatus[nodeId] = {
...componentsWithStatus[nodeId],
status: nodeStatusMap[nodeId],
isStatusVisible: true // 显示状态指示器
};
}
});
const result = {
...flowData,
components: componentsWithStatus,
main: {
...flowData.main,
components: componentsWithStatus
}
};
console.log('InstanceCanvas - 注入状态后的 flowData:', result);
return result;
}, [flowData, nodeStatusMap]);
// 渲染运行日志内容
const renderRuntimeLogs = () => {
return (
@ -339,9 +390,9 @@ const InstanceCanvas: React.FC<InstanceCanvasProps> = ({ instanceData, title, on
<Spin size={40} />
<span style={{ marginTop: '16px', color: 'var(--color-text-3)' }}>...</span>
</div>
) : flowData ? (
) : flowDataWithStatus ? (
<MemoizedFlowEditor
flowData={flowData}
flowData={flowDataWithStatus}
instanceId={instanceData?.id || 'instance-canvas'}
/>
) : (

@ -57,18 +57,28 @@ export const useFlowEditorState = (initialData?: any) => {
? appRuntimeData[currentAppKey].nodeStatusMap
: {};
// 检查 initialData 中是否包含节点状态(用于查看历史实例)
const hasInitialDataStatus = initialData?.components &&
Object.values(initialData.components).some((comp: any) => comp.status);
setNodes(prevNodes =>{
return prevNodes.map(node => ({
...node,
data: {
...node.data,
status: currentNodeStatusMap[node.id] || 'waiting',
isStatusVisible: currentAppIsRunning // 只有在运行时才显示状态指示器
}
}))
return prevNodes.map(node => {
// 优先使用运行时状态,其次使用节点自身的状态(历史实例),最后默认为 waiting
const nodeStatus = currentNodeStatusMap[node.id] || node.data.status || 'waiting';
return {
...node,
data: {
...node.data,
status: nodeStatus,
// 在运行时或有历史状态时显示状态指示器
isStatusVisible: currentAppIsRunning || hasInitialDataStatus || node.data.isStatusVisible
}
};
});
});
}, [appRuntimeData, currentAppKey, currentAppIsRunning, initialData?.id,nodes.length]);
}, [appRuntimeData, currentAppKey, currentAppIsRunning, initialData?.id, initialData?.components, nodes.length]);
const updateCanvasDataMapDebounced = useRef(
debounce((dispatch: Dispatch<any>, canvasDataMap: any, id: string, nodes: Node[], edges: Edge[]) => {

@ -147,6 +147,16 @@ export const convertFlowData = (flowData: any, useDefault = true) => {
node.data.compId = nodeConfig.component.compId;
}
// 保留节点状态信息(用于历史实例查看)
if (nodeConfig.status) {
node.data.status = nodeConfig.status;
console.log(`convertFlowData - 保留节点 ${nodeId} 的状态:`, nodeConfig.status);
}
if (nodeConfig.isStatusVisible !== undefined) {
node.data.isStatusVisible = nodeConfig.isStatusVisible;
console.log(`convertFlowData - 保留节点 ${nodeId} 的状态可见性:`, nodeConfig.isStatusVisible);
}
// 注册循环节点类型
if (nodeType === 'LOOP') {
const nodeMap = Array.from(Object.values(nodeTypeMap).map(key => key));
@ -379,6 +389,8 @@ export const convertFlowData = (flowData: any, useDefault = true) => {
});
}
}
console.log('nodes, edges:', nodes, edges);
return { nodes, edges };
};
@ -675,12 +687,15 @@ const getNodeApiIns = (nodeId: string, nodeConfig: any, currentProjectCompData:
else if (nodeId.includes('end')) {
return [{ name: 'end', desc: '', dataType: '', defaultValue: '' }];
}
else if (nodeConfig.component?.type === 'SUB') {
return [{ name: 'start', desc: '', dataType: '', defaultValue: '' }];
}
else {
const comp = currentProjectCompData.filter(item => {
return (item.id || item?.comp?.id) === nodeConfig?.component?.compId;
});
if (comp && comp.length > 0) {
const apiIns = comp[0].def?.apis || comp[0]?.comp.def?.apis;
const apiIns = comp[0]?.def?.apis || comp[0]?.comp?.def?.apis || [];
return apiIns.map(v => {
return {
...v,
@ -768,6 +783,9 @@ const getNodeApiOuts = (nodeId: string, nodeConfig: any, currentProjectCompData:
else if (nodeId.includes('end')) {
return [];
}
else if (nodeConfig.component?.type === 'SUB') {
return [{ name: 'done', desc: '', dataType: '', defaultValue: '' }];
}
else {
const comp = currentProjectCompData.filter(item => item.id === nodeConfig?.component?.compId);
if (comp && comp.length > 0) {

Loading…
Cancel
Save