|
@@ -1,4 +1,4 @@
|
|
|
-<template>
|
|
|
|
|
|
|
+<template>
|
|
|
<div class="h-full w-full" ref="workflowWrapperRef" @drop="onDrop">
|
|
<div class="h-full w-full" ref="workflowWrapperRef" @drop="onDrop">
|
|
|
<Workflow
|
|
<Workflow
|
|
|
ref="workflowRef"
|
|
ref="workflowRef"
|
|
@@ -29,10 +29,17 @@
|
|
|
/>
|
|
/>
|
|
|
</Workflow>
|
|
</Workflow>
|
|
|
</div>
|
|
</div>
|
|
|
- <RunWorkflow v-model:visible="runVisible" :workflow="workflow" />
|
|
|
|
|
|
|
+ <RunWorkflow
|
|
|
|
|
+ v-model:visible="runVisible"
|
|
|
|
|
+ :workflow="workflow"
|
|
|
|
|
+ :close-on-run="closeRunWorkflowOnSubmit"
|
|
|
|
|
+ :input-only="runWorkflowInputOnly"
|
|
|
|
|
+ @run-started="handleWorkflowRunStarted"
|
|
|
|
|
+ />
|
|
|
<Setter
|
|
<Setter
|
|
|
:id="nodeID"
|
|
:id="nodeID"
|
|
|
:workflow="workflow"
|
|
:workflow="workflow"
|
|
|
|
|
+ :active-tab="setterActiveTab"
|
|
|
@update:node:data="handleUpdateNode"
|
|
@update:node:data="handleUpdateNode"
|
|
|
@run-node="handleRunNode"
|
|
@run-node="handleRunNode"
|
|
|
v-model:visible="setterVisible"
|
|
v-model:visible="setterVisible"
|
|
@@ -102,8 +109,11 @@ const workflowRef = ref<InstanceType<typeof Workflow>>()
|
|
|
const showNodeLibary = ref(false)
|
|
const showNodeLibary = ref(false)
|
|
|
const libaryRefferenceRef = ref<HTMLElement>()
|
|
const libaryRefferenceRef = ref<HTMLElement>()
|
|
|
const runVisible = ref(false)
|
|
const runVisible = ref(false)
|
|
|
|
|
+const closeRunWorkflowOnSubmit = ref(false)
|
|
|
|
|
+const runWorkflowInputOnly = ref(false)
|
|
|
const setterVisible = ref(false)
|
|
const setterVisible = ref(false)
|
|
|
const nodeID = ref('')
|
|
const nodeID = ref('')
|
|
|
|
|
+const setterActiveTab = ref<'setting' | 'last-run'>('setting')
|
|
|
const pendingSetterInit = new Set<string>()
|
|
const pendingSetterInit = new Set<string>()
|
|
|
const displayNodeExecutionStatus = ref<Record<string, CanvasExecutionStatus>>({})
|
|
const displayNodeExecutionStatus = ref<Record<string, CanvasExecutionStatus>>({})
|
|
|
const peddingHandlePayload = ref<{
|
|
const peddingHandlePayload = ref<{
|
|
@@ -300,9 +310,10 @@ const normalizeConnectionEndpoints = (connection: Connection) => {
|
|
|
return normalizeEdgeEndpoints(connection, props.workflow?.nodes || [])
|
|
return normalizeEdgeEndpoints(connection, props.workflow?.nodes || [])
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-// 节点仍处于临时创建阶段时,跳过持久化更新。
|
|
|
|
|
-const isPendingCreate = (node: any) => {
|
|
|
|
|
- return !!(node as any)?.__pendingCreate
|
|
|
|
|
|
|
+const openSetter = (id: string, tab: 'setting' | 'last-run' = 'setting') => {
|
|
|
|
|
+ nodeID.value = id
|
|
|
|
|
+ setterActiveTab.value = tab
|
|
|
|
|
+ setterVisible.value = true
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// 从节点级操作入口直接运行指定节点。
|
|
// 从节点级操作入口直接运行指定节点。
|
|
@@ -312,17 +323,34 @@ const handleRunNode = async (id: string) => {
|
|
|
return
|
|
return
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ const targetNode = props.workflow?.nodes?.find((node) => node.id === id)
|
|
|
|
|
+ const nodeType = (targetNode as any)?.nodeType || (targetNode as any)?.data?.nodeType
|
|
|
|
|
+
|
|
|
|
|
+ if (nodeType === 'start') {
|
|
|
|
|
+ closeRunWorkflowOnSubmit.value = true
|
|
|
|
|
+ runWorkflowInputOnly.value = true
|
|
|
|
|
+ runVisible.value = false
|
|
|
|
|
+ await nextTick()
|
|
|
|
|
+ runVisible.value = true
|
|
|
|
|
+ return
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ closeRunWorkflowOnSubmit.value = false
|
|
|
|
|
+ runWorkflowInputOnly.value = false
|
|
|
|
|
+
|
|
|
try {
|
|
try {
|
|
|
const response = await agent.postAgentDoExecute({
|
|
const response = await agent.postAgentDoExecute({
|
|
|
appAgentId: props.workflow.id,
|
|
appAgentId: props.workflow.id,
|
|
|
start_node_id: id,
|
|
start_node_id: id,
|
|
|
is_debugger: true,
|
|
is_debugger: true,
|
|
|
responseType: 'ws',
|
|
responseType: 'ws',
|
|
|
|
|
+ // 如果是start用户输入则传入数据
|
|
|
params: {}
|
|
params: {}
|
|
|
})
|
|
})
|
|
|
const agentRunnerKey = response?.result
|
|
const agentRunnerKey = response?.result
|
|
|
if (agentRunnerKey) {
|
|
if (agentRunnerKey) {
|
|
|
runnerStore.startRunner(agentRunnerKey)
|
|
runnerStore.startRunner(agentRunnerKey)
|
|
|
|
|
+ openSetter(id, 'last-run')
|
|
|
}
|
|
}
|
|
|
} catch (error) {
|
|
} catch (error) {
|
|
|
console.error('postDoTestNodeRunner error', error)
|
|
console.error('postDoTestNodeRunner error', error)
|
|
@@ -344,6 +372,8 @@ const handleRunAgent = () => {
|
|
|
return
|
|
return
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ closeRunWorkflowOnSubmit.value = false
|
|
|
|
|
+ runWorkflowInputOnly.value = false
|
|
|
runVisible.value = true
|
|
runVisible.value = true
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -444,9 +474,15 @@ const handleNodeCreate = (value: { type: string; position?: XYPosition } | strin
|
|
|
|
|
|
|
|
// 双击节点时打开对应的配置面板。
|
|
// 双击节点时打开对应的配置面板。
|
|
|
const handleNodeClick = (id: string, _position: XYPosition) => {
|
|
const handleNodeClick = (id: string, _position: XYPosition) => {
|
|
|
- nodeID.value = id
|
|
|
|
|
- pendingSetterInit.add(id)
|
|
|
|
|
- setterVisible.value = true
|
|
|
|
|
|
|
+ openSetter(id, 'setting')
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+const handleWorkflowRunStarted = (id: string) => {
|
|
|
|
|
+ if (!closeRunWorkflowOnSubmit.value) {
|
|
|
|
|
+ return
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ openSetter(id, 'last-run')
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// 将拖拽落点转换成统一的节点创建流程。
|
|
// 将拖拽落点转换成统一的节点创建流程。
|
|
@@ -492,7 +528,7 @@ const onCreateConnection = async (connection: Connection) => {
|
|
|
const handleUpdateNodesPosition = (events: { id: string; position: XYPosition }[]) => {
|
|
const handleUpdateNodesPosition = (events: { id: string; position: XYPosition }[]) => {
|
|
|
events?.forEach(({ id, position }) => {
|
|
events?.forEach(({ id, position }) => {
|
|
|
const node = props.workflow?.nodes.find((item) => item.id === id)
|
|
const node = props.workflow?.nodes.find((item) => item.id === id)
|
|
|
- if (node && !isPendingCreate(node)) {
|
|
|
|
|
|
|
+ if (node) {
|
|
|
if (node.position?.x === position.x && node.position?.y === position.y) {
|
|
if (node.position?.x === position.x && node.position?.y === position.y) {
|
|
|
return
|
|
return
|
|
|
}
|
|
}
|
|
@@ -522,20 +558,27 @@ const handleSelectNode = (id: string) => {
|
|
|
|
|
|
|
|
// 持久化配置面板提交的节点数据变更。
|
|
// 持久化配置面板提交的节点数据变更。
|
|
|
const handleUpdateNode = (node: IWorkflowNode) => {
|
|
const handleUpdateNode = (node: IWorkflowNode) => {
|
|
|
- if (node && !isPendingCreate(node)) {
|
|
|
|
|
- if (pendingSetterInit.has(node.id)) {
|
|
|
|
|
- pendingSetterInit.delete(node.id)
|
|
|
|
|
- return
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
|
|
+ if (node) {
|
|
|
if (node.nodeType === 'if-else') {
|
|
if (node.nodeType === 'if-else') {
|
|
|
const cases = node.data?.cases || []
|
|
const cases = node.data?.cases || []
|
|
|
const offsetHeight = (cases.length > 1 ? cases.length - 1 : 0) * 32
|
|
const offsetHeight = (cases.length > 1 ? cases.length - 1 : 0) * 32
|
|
|
node.height = 96 + offsetHeight
|
|
node.height = 96 + offsetHeight
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ const workflowNode = props.workflow?.nodes.find((item) => item.id === node.id)
|
|
|
|
|
+ const syncedNode = workflowNode || node
|
|
|
|
|
+
|
|
|
|
|
+ if (workflowNode) {
|
|
|
|
|
+ const mergedData = {
|
|
|
|
|
+ ...(workflowNode.data || {}),
|
|
|
|
|
+ ...(node.data || {})
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ Object.assign(workflowNode, node)
|
|
|
|
|
+ workflowNode.data = mergedData
|
|
|
|
|
+ }
|
|
|
agent
|
|
agent
|
|
|
- .postAgentDoUpdateAgentNode(buildUpdateNodePayload(node))
|
|
|
|
|
|
|
+ .postAgentDoUpdateAgentNode(buildUpdateNodePayload(syncedNode))
|
|
|
.then((response) => {
|
|
.then((response) => {
|
|
|
handleApiResult(response, undefined, '更新节点失败')
|
|
handleApiResult(response, undefined, '更新节点失败')
|
|
|
})
|
|
})
|
|
@@ -548,7 +591,7 @@ const handleUpdateNode = (node: IWorkflowNode) => {
|
|
|
// 持久化画布自身抛出的轻量节点属性更新。
|
|
// 持久化画布自身抛出的轻量节点属性更新。
|
|
|
const handleUpdateNodeProps = (id: string, attrs: Record<string, unknown>) => {
|
|
const handleUpdateNodeProps = (id: string, attrs: Record<string, unknown>) => {
|
|
|
const node = props.workflow?.nodes.find((item) => item.id === id)
|
|
const node = props.workflow?.nodes.find((item) => item.id === id)
|
|
|
- if (node && !isPendingCreate(node)) {
|
|
|
|
|
|
|
+ if (node) {
|
|
|
const keys = Object.keys(attrs || {})
|
|
const keys = Object.keys(attrs || {})
|
|
|
const meaningfulKeys = keys.filter((key) => !['selected', 'dragging'].includes(key))
|
|
const meaningfulKeys = keys.filter((key) => !['selected', 'dragging'].includes(key))
|
|
|
if (meaningfulKeys.length === 0) {
|
|
if (meaningfulKeys.length === 0) {
|