|
@@ -48,12 +48,13 @@
|
|
|
v-model:visible="setterVisible"
|
|
v-model:visible="setterVisible"
|
|
|
/>
|
|
/>
|
|
|
<el-popover
|
|
<el-popover
|
|
|
|
|
+ v-if="libaryRefferenceRef"
|
|
|
:visible="showNodeLibary"
|
|
:visible="showNodeLibary"
|
|
|
- width="360px"
|
|
|
|
|
- virtual-triggering
|
|
|
|
|
:show-arrow="false"
|
|
:show-arrow="false"
|
|
|
:append-to="workflowWrapperRef"
|
|
:append-to="workflowWrapperRef"
|
|
|
:virtual-ref="libaryRefferenceRef"
|
|
:virtual-ref="libaryRefferenceRef"
|
|
|
|
|
+ width="360px"
|
|
|
|
|
+ virtual-triggering
|
|
|
>
|
|
>
|
|
|
<NodeLibary @add-node="handleNodeCreate" @mouseleave="onHideNodeLibary" />
|
|
<NodeLibary @add-node="handleNodeCreate" @mouseleave="onHideNodeLibary" />
|
|
|
</el-popover>
|
|
</el-popover>
|
|
@@ -111,6 +112,7 @@ const workflowWrapperRef = ref<HTMLElement>()
|
|
|
const workflowRef = ref<InstanceType<typeof Workflow>>()
|
|
const workflowRef = ref<InstanceType<typeof Workflow>>()
|
|
|
const showNodeLibary = ref(false)
|
|
const showNodeLibary = ref(false)
|
|
|
const libaryRefferenceRef = ref<HTMLElement>()
|
|
const libaryRefferenceRef = ref<HTMLElement>()
|
|
|
|
|
+const nodeLibaryPopoverAnchorRef = ref<HTMLElement>()
|
|
|
const runVisible = ref(false)
|
|
const runVisible = ref(false)
|
|
|
const closeRunWorkflowOnSubmit = ref(false)
|
|
const closeRunWorkflowOnSubmit = ref(false)
|
|
|
const runWorkflowInputOnly = ref(false)
|
|
const runWorkflowInputOnly = ref(false)
|
|
@@ -120,6 +122,7 @@ const setterVisible = ref(false)
|
|
|
const nodeID = ref('')
|
|
const nodeID = ref('')
|
|
|
const setterActiveTab = ref<'setting' | 'last-run'>('setting')
|
|
const setterActiveTab = ref<'setting' | 'last-run'>('setting')
|
|
|
const displayNodeExecutionStatus = ref<Record<string, CanvasExecutionStatus>>({})
|
|
const displayNodeExecutionStatus = ref<Record<string, CanvasExecutionStatus>>({})
|
|
|
|
|
+const shouldAutoCenterAfterInit = ref(true)
|
|
|
const peddingHandlePayload = ref<{
|
|
const peddingHandlePayload = ref<{
|
|
|
by?: 'node' | 'edge'
|
|
by?: 'node' | 'edge'
|
|
|
handle?: ConnectStartEvent
|
|
handle?: ConnectStartEvent
|
|
@@ -132,6 +135,31 @@ const peddingHandlePayload = ref<{
|
|
|
const runningStatusStartedAt = new Map<string, number>()
|
|
const runningStatusStartedAt = new Map<string, number>()
|
|
|
const pendingNodeStatusTimers = new Map<string, number>()
|
|
const pendingNodeStatusTimers = new Map<string, number>()
|
|
|
|
|
|
|
|
|
|
+const removeNodeLibaryPopoverAnchor = () => {
|
|
|
|
|
+ nodeLibaryPopoverAnchorRef.value?.remove()
|
|
|
|
|
+ nodeLibaryPopoverAnchorRef.value = undefined
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+const createNodeLibaryPopoverAnchor = (event?: MouseEvent) => {
|
|
|
|
|
+ removeNodeLibaryPopoverAnchor()
|
|
|
|
|
+
|
|
|
|
|
+ if (!event) {
|
|
|
|
|
+ return undefined
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ const anchor = document.createElement('div')
|
|
|
|
|
+ anchor.style.position = 'fixed'
|
|
|
|
|
+ anchor.style.left = `${event.clientX}px`
|
|
|
|
|
+ anchor.style.top = `${event.clientY}px`
|
|
|
|
|
+ anchor.style.width = '1px'
|
|
|
|
|
+ anchor.style.height = '1px'
|
|
|
|
|
+ anchor.style.pointerEvents = 'none'
|
|
|
|
|
+ document.body.appendChild(anchor)
|
|
|
|
|
+ nodeLibaryPopoverAnchorRef.value = anchor
|
|
|
|
|
+
|
|
|
|
|
+ return anchor
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
// 在为节点安排新的状态切换前,先清理旧的延时任务。
|
|
// 在为节点安排新的状态切换前,先清理旧的延时任务。
|
|
|
const clearPendingNodeStatusTimer = (nodeId: string) => {
|
|
const clearPendingNodeStatusTimer = (nodeId: string) => {
|
|
|
const timer = pendingNodeStatusTimers.get(nodeId)
|
|
const timer = pendingNodeStatusTimers.get(nodeId)
|
|
@@ -336,6 +364,27 @@ const openSetter = (id: string, tab: 'setting' | 'last-run' = 'setting') => {
|
|
|
setterVisible.value = true
|
|
setterVisible.value = true
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+const centerWorkflowIntoView = async () => {
|
|
|
|
|
+ const vueFlow = workflowRef.value?.getVueFlow()
|
|
|
|
|
+ if (!vueFlow || !props.workflow?.nodes?.length) {
|
|
|
|
|
+ return false
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ await nextTick()
|
|
|
|
|
+
|
|
|
|
|
+ await new Promise<void>((resolve) => {
|
|
|
|
|
+ window.requestAnimationFrame(() => resolve())
|
|
|
|
|
+ })
|
|
|
|
|
+
|
|
|
|
|
+ await vueFlow.fitView({
|
|
|
|
|
+ padding: 0.2,
|
|
|
|
|
+ duration: 240,
|
|
|
|
|
+ maxZoom: 1
|
|
|
|
|
+ })
|
|
|
|
|
+
|
|
|
|
|
+ return true
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
const openRunWorkflow = async (
|
|
const openRunWorkflow = async (
|
|
|
nodeId: string,
|
|
nodeId: string,
|
|
|
initialTab: 'input' | 'trigger' | 'result' | 'detail' | 'trace',
|
|
initialTab: 'input' | 'trigger' | 'result' | 'detail' | 'trace',
|
|
@@ -442,6 +491,21 @@ const handleRunAgent = (id?: string) => {
|
|
|
handleRunNode(targetNode.id)
|
|
handleRunNode(targetNode.id)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+watch(
|
|
|
|
|
+ () => props.workflow?.nodes,
|
|
|
|
|
+ async (nodes) => {
|
|
|
|
|
+ if (!shouldAutoCenterAfterInit.value || !nodes?.length) {
|
|
|
|
|
+ return
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ const centered = await centerWorkflowIntoView()
|
|
|
|
|
+ if (centered) {
|
|
|
|
|
+ shouldAutoCenterAfterInit.value = false
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
|
|
+ { flush: 'post' }
|
|
|
|
|
+)
|
|
|
|
|
+
|
|
|
/**
|
|
/**
|
|
|
* 创建新节点
|
|
* 创建新节点
|
|
|
*/
|
|
*/
|
|
@@ -736,17 +800,20 @@ const onConnectionOpenNodeLibary = async (payload: {
|
|
|
parentId?: string
|
|
parentId?: string
|
|
|
}) => {
|
|
}) => {
|
|
|
await nextTick()
|
|
await nextTick()
|
|
|
- const { handle } = payload
|
|
|
|
|
- libaryRefferenceRef.value = handle.event?.target as HTMLElement
|
|
|
|
|
|
|
+ libaryRefferenceRef.value = createNodeLibaryPopoverAnchor(payload.event)
|
|
|
showNodeLibary.value = true
|
|
showNodeLibary.value = true
|
|
|
peddingHandlePayload.value = payload
|
|
peddingHandlePayload.value = payload
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// 关闭节点库弹层时,清理相关的临时状态。
|
|
// 关闭节点库弹层时,清理相关的临时状态。
|
|
|
const onHideNodeLibary = () => {
|
|
const onHideNodeLibary = () => {
|
|
|
- peddingHandlePayload.value = undefined
|
|
|
|
|
- libaryRefferenceRef.value = undefined
|
|
|
|
|
showNodeLibary.value = false
|
|
showNodeLibary.value = false
|
|
|
|
|
+
|
|
|
|
|
+ setTimeout(() => {
|
|
|
|
|
+ peddingHandlePayload.value = undefined
|
|
|
|
|
+ libaryRefferenceRef.value = undefined
|
|
|
|
|
+ removeNodeLibaryPopoverAnchor()
|
|
|
|
|
+ }, 500)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// 根据边上加号按钮的位置打开节点库弹层。
|
|
// 根据边上加号按钮的位置打开节点库弹层。
|
|
@@ -773,6 +840,7 @@ const handleClickConectionAdd = (connection: Connection & { id: string }, parent
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
onBeforeUnmount(() => {
|
|
onBeforeUnmount(() => {
|
|
|
|
|
+ removeNodeLibaryPopoverAnchor()
|
|
|
resetDisplayedNodeStatuses()
|
|
resetDisplayedNodeStatuses()
|
|
|
})
|
|
})
|
|
|
</script>
|
|
</script>
|