|
|
@@ -81,7 +81,7 @@
|
|
|
<Setter
|
|
|
:id="nodeID"
|
|
|
:workflow="workflow!"
|
|
|
- @update:node:data="handleUpdateNodeData"
|
|
|
+ @update:node:data="handleUpdateNode"
|
|
|
@run-node="handleRunNode"
|
|
|
v-model:visible="setterVisible"
|
|
|
/>
|
|
|
@@ -186,11 +186,96 @@ const mapNodeExecutionStatus = (status?: string): CanvasExecutionStatus => {
|
|
|
return 'idle'
|
|
|
}
|
|
|
|
|
|
+const MIN_NODE_RUNNING_EFFECT_MS = 500
|
|
|
+const displayNodeExecutionStatus = ref<Record<string, CanvasExecutionStatus>>({})
|
|
|
+const runningStatusStartedAt = new Map<string, number>()
|
|
|
+const pendingNodeStatusTimers = new Map<string, number>()
|
|
|
+
|
|
|
+const clearPendingNodeStatusTimer = (nodeId: string) => {
|
|
|
+ const timer = pendingNodeStatusTimers.get(nodeId)
|
|
|
+ if (timer) {
|
|
|
+ window.clearTimeout(timer)
|
|
|
+ pendingNodeStatusTimers.delete(nodeId)
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+const applyDisplayedNodeStatus = (nodeId: string, status: CanvasExecutionStatus) => {
|
|
|
+ if (status === 'idle') {
|
|
|
+ delete displayNodeExecutionStatus.value[nodeId]
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ displayNodeExecutionStatus.value[nodeId] = status
|
|
|
+}
|
|
|
+
|
|
|
+const syncDisplayedNodeStatus = (nodeId: string, nextStatus: CanvasExecutionStatus) => {
|
|
|
+ const currentStatus = displayNodeExecutionStatus.value[nodeId] || 'idle'
|
|
|
+
|
|
|
+ if (nextStatus === 'running') {
|
|
|
+ clearPendingNodeStatusTimer(nodeId)
|
|
|
+ runningStatusStartedAt.set(nodeId, Date.now())
|
|
|
+ applyDisplayedNodeStatus(nodeId, 'running')
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ const runningStartedAt = runningStatusStartedAt.get(nodeId)
|
|
|
+ const shouldKeepRunning =
|
|
|
+ currentStatus === 'running' &&
|
|
|
+ typeof runningStartedAt === 'number' &&
|
|
|
+ Date.now() - runningStartedAt < MIN_NODE_RUNNING_EFFECT_MS
|
|
|
+
|
|
|
+ if (shouldKeepRunning) {
|
|
|
+ clearPendingNodeStatusTimer(nodeId)
|
|
|
+ const delay = MIN_NODE_RUNNING_EFFECT_MS - (Date.now() - runningStartedAt)
|
|
|
+ const timer = window.setTimeout(() => {
|
|
|
+ applyDisplayedNodeStatus(nodeId, nextStatus)
|
|
|
+ runningStatusStartedAt.delete(nodeId)
|
|
|
+ pendingNodeStatusTimers.delete(nodeId)
|
|
|
+ }, delay)
|
|
|
+ pendingNodeStatusTimers.set(nodeId, timer)
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ clearPendingNodeStatusTimer(nodeId)
|
|
|
+ applyDisplayedNodeStatus(nodeId, nextStatus)
|
|
|
+ runningStatusStartedAt.delete(nodeId)
|
|
|
+}
|
|
|
+
|
|
|
+const resetDisplayedNodeStatuses = () => {
|
|
|
+ pendingNodeStatusTimers.forEach((timer) => window.clearTimeout(timer))
|
|
|
+ pendingNodeStatusTimers.clear()
|
|
|
+ runningStatusStartedAt.clear()
|
|
|
+ displayNodeExecutionStatus.value = {}
|
|
|
+}
|
|
|
+
|
|
|
+watch(
|
|
|
+ () => runnerStore.currentRunnerKey,
|
|
|
+ () => {
|
|
|
+ resetDisplayedNodeStatuses()
|
|
|
+ }
|
|
|
+)
|
|
|
+
|
|
|
+watch(
|
|
|
+ () => runnerStore.nodes.map((item) => ({ nodeId: item.nodeId, status: item.status })),
|
|
|
+ (nodeStates) => {
|
|
|
+ const activeNodeIds = new Set(nodeStates.map((item) => item.nodeId))
|
|
|
+
|
|
|
+ nodeStates.forEach((item) => {
|
|
|
+ syncDisplayedNodeStatus(item.nodeId, mapNodeExecutionStatus(item.status))
|
|
|
+ })
|
|
|
+
|
|
|
+ Object.keys(displayNodeExecutionStatus.value).forEach((nodeId) => {
|
|
|
+ if (!activeNodeIds.has(nodeId)) {
|
|
|
+ syncDisplayedNodeStatus(nodeId, 'idle')
|
|
|
+ }
|
|
|
+ })
|
|
|
+ },
|
|
|
+ { immediate: true, deep: true }
|
|
|
+)
|
|
|
+
|
|
|
const workflowWithExecutionState = computed<IWorkflow>(() => {
|
|
|
const baseWorkflow = workflow.value
|
|
|
- const runnerNodeStatusMap = new Map(
|
|
|
- runnerStore.nodes.map((item) => [item.nodeId, mapNodeExecutionStatus(item.status)])
|
|
|
- )
|
|
|
+ const runnerNodeStatusMap = new Map(Object.entries(displayNodeExecutionStatus.value))
|
|
|
|
|
|
return {
|
|
|
...baseWorkflow,
|
|
|
@@ -603,9 +688,9 @@ const handleNodeCreate = (value: { type: string; position?: XYPosition } | strin
|
|
|
if (handle.handleId?.includes('_')) {
|
|
|
newNodeParam.nodeHandleId = handle.handleId
|
|
|
}
|
|
|
- if (handle.handleId?.endsWith('-else')) {
|
|
|
- newNodeParam.nodeHandleId = handle.nodeId
|
|
|
- }
|
|
|
+ // if (handle.handleId?.endsWith('-else')) {
|
|
|
+ // newNodeParam.nodeHandleId = handle.nodeId
|
|
|
+ // }
|
|
|
}
|
|
|
|
|
|
if (!newNodeParam.position) {
|
|
|
@@ -692,9 +777,9 @@ const onCreateConnection = async (connection: Connection) => {
|
|
|
}
|
|
|
|
|
|
// 如果是source条件节点else的sourceHandle模式就是当前节点id
|
|
|
- if (sourceHandle && sourceHandle.endsWith('-else')) {
|
|
|
- params.sourceHandle = source
|
|
|
- }
|
|
|
+ // if (sourceHandle && sourceHandle.endsWith('-else')) {
|
|
|
+ // params.sourceHandle = source
|
|
|
+ // }
|
|
|
|
|
|
if (!workflow.value?.edges.some((edge) => edge.source === source && edge.target === target)) {
|
|
|
const response = await agent.postAgentDoNewEdge(params)
|
|
|
@@ -746,7 +831,7 @@ const handleSelectNode = (id: string) => {
|
|
|
/**
|
|
|
* 修改节点数据
|
|
|
*/
|
|
|
-const hangleUpdateNodeData = (node: IWorkflowNode) => {
|
|
|
+const handleUpdateNode = (node: IWorkflowNode) => {
|
|
|
if (node && !isPendingCreate(node)) {
|
|
|
if (pendingSetterInit.has(id)) {
|
|
|
pendingSetterInit.delete(id)
|
|
|
@@ -881,6 +966,7 @@ const onHideNodeLibary = () => {
|
|
|
onBeforeUnmount(() => {
|
|
|
if (saveAgentTimer.value) window.clearTimeout(saveAgentTimer.value)
|
|
|
if (saveVarsTimer.value) window.clearTimeout(saveVarsTimer.value)
|
|
|
+ resetDisplayedNodeStatuses()
|
|
|
layout?.setMainStyle({})
|
|
|
})
|
|
|
</script>
|