maxkb/ui/src/workflow/common/teleport.ts
2025-06-03 16:09:09 +08:00

81 lines
2.3 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { BaseEdgeModel, BaseNodeModel, GraphModel } from '@logicflow/core'
import { defineComponent, h, reactive, isVue3, Teleport, markRaw, Fragment } from 'vue-demi'
let active = false
const items = reactive<{ [key: string]: any }>({})
export function connect(
id: string,
component: any,
container: HTMLDivElement,
node: BaseNodeModel | BaseEdgeModel,
graph: GraphModel,
get_props?: any
) {
if (!get_props) {
get_props = (node: BaseNodeModel | BaseEdgeModel, graph: GraphModel) => {
return { nodeModel: node, graph }
}
}
if (active) {
items[id] = markRaw(
defineComponent({
render: () => h(Teleport, { to: container } as any, [h(component, get_props(node, graph))]),
provide: () => ({
getNode: () => node,
getGraph: () => graph
})
})
)
}
}
export function disconnect(id: string) {
if (active) {
delete items[id]
}
}
export function isActive() {
return active
}
export function getTeleport(): any {
if (!isVue3) {
throw new Error('teleport is only available in Vue3')
}
active = true
return defineComponent({
props: {
flowId: {
type: String,
required: true
}
},
setup(props) {
return () => {
const children: Record<string, any>[] = []
Object.keys(items).forEach((id) => {
// https://github.com/didi/LogicFlow/issues/1768
// 多个不同的VueNodeView都会connect注册到items中因此items存储了可能有多个flowId流程图的数据
// 当使用多个LogicFlow时会创建多个flowId + 同时使用KeepAlive
// 每一次items改变会触发不同flowId持有的setup()执行由于每次setup()执行就是遍历items因此存在多次重复渲染元素的问题
// 即items[0]会在Page1的setup()执行items[0]也会在Page2的setup()执行从而生成两个items[0]
// 比对当前界面显示的flowId只更新items[当前页面flowId:nodeId]的数据
// 比如items[0]属于Page1的数据那么Page2无论active=true/false都无法执行items[0]
if (id.startsWith(props.flowId)) {
children.push(items[id])
}
})
return h(
Fragment,
{},
children.map((item) => h(item))
)
}
}
})
}