@flowgram.ai/free-layout-core 0.2.10 → 0.2.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/esm/index.js +106 -34
- package/dist/esm/index.js.map +1 -1
- package/dist/index.d.mts +12 -2
- package/dist/index.d.ts +12 -2
- package/dist/index.js +99 -33
- package/dist/index.js.map +1 -1
- package/dist/typings/index.d.mts +1 -1
- package/dist/typings/index.d.ts +1 -1
- package/dist/typings/workflow-drag.d.mts +1 -1
- package/dist/typings/workflow-drag.d.ts +1 -1
- package/dist/typings/workflow-json.d.mts +1 -1
- package/dist/typings/workflow-json.d.ts +1 -1
- package/dist/typings/workflow-line.d.mts +1 -1
- package/dist/typings/workflow-line.d.ts +1 -1
- package/dist/typings/workflow-node.d.mts +1 -1
- package/dist/typings/workflow-node.d.ts +1 -1
- package/dist/typings/workflow-registry.d.mts +1 -1
- package/dist/typings/workflow-registry.d.ts +1 -1
- package/dist/{workflow-line-entity-BGD6_sdy.d.mts → workflow-line-entity-B34FWw9W.d.mts} +9 -2
- package/dist/{workflow-line-entity-OFVYg40b.d.ts → workflow-line-entity-B4Mfa03B.d.ts} +9 -2
- package/package.json +9 -9
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/workflow-commands.ts","../src/hooks/index.ts","../src/hooks/use-node-render.tsx","../src/service/workflow-select-service.ts","../src/utils/index.ts","../src/utils/nanoid.ts","../src/utils/compose.ts","../src/utils/fit-view.ts","../src/utils/get-anti-overlap-position.ts","../src/utils/statics.ts","../src/entities/workflow-node-entity.ts","../src/entities/workflow-line-entity.ts","../src/entity-datas/workflow-node-ports-data.ts","../src/entities/workflow-port-entity.ts","../src/entity-datas/workflow-node-lines-data.ts","../src/entity-datas/workflow-line-render-data.ts","../src/service/workflow-hover-service.ts","../src/service/workflow-drag-service.ts","../src/workflow-lines-manager.ts","../src/workflow-document-option.ts","../src/utils/flow-node-form-data.ts","../src/typings/workflow-json.ts","../src/typings/workflow-line.ts","../src/typings/workflow-operation.ts","../src/typings/index.ts","../src/workflow-document.ts","../src/layout/free-layout.ts","../src/service/workflow-reset-layout-service.ts","../src/utils/layout-to-positions.ts","../src/service/workflow-operation-base-service.ts","../src/hooks/use-playground-readonly-state.ts","../src/hooks/use-current-dom-node.ts","../src/hooks/use-current-entity.ts","../src/hooks/use-workflow-document.ts","../src/constants.ts","../src/workflow-document-container-module.ts","../src/workflow-document-contribution.ts","../src/utils/get-url-params.ts","../src/utils/simple-line.ts"],"sourcesContent":["export * from './workflow-commands';\nexport * from './hooks';\nexport * from './utils';\nexport * from './typings';\nexport * from './entities';\nexport * from './constants';\nexport * from './entity-datas';\nexport * from './service';\nexport * from './workflow-document';\nexport * from './workflow-document-container-module';\nexport * from './workflow-lines-manager';\nexport * from './workflow-document-option';\nexport * from './utils/simple-line';\n","export enum WorkflowCommands {\n DELETE_NODES = 'DELETE_NODES',\n COPY_NODES = 'COPY_NODES',\n PASTE_NODES = 'PASTE_NODES',\n ZOOM_IN = 'ZOOM_IN',\n ZOOM_OUT = 'ZOOM_OUT',\n UNDO = 'UNDO',\n REDO = 'REDO',\n}\n","export {\n useConfigEntity,\n useService,\n usePlayground,\n useListenEvents,\n usePlaygroundContainer,\n usePlaygroundContext,\n useEntities,\n useEntityFromContext,\n useEntityDataFromContext,\n useRefresh,\n usePlaygroundLatest,\n} from '@flowgram.ai/core';\nexport * from './typings';\nexport * from './use-node-render';\nexport * from './use-current-dom-node';\nexport * from './use-current-entity';\nexport * from './use-workflow-document';\nexport * from './use-playground-readonly-state';\n","import type React from 'react';\nimport { useCallback, useEffect, useRef, useState, useContext, useMemo } from 'react';\n\nimport { useObserve } from '@flowgram.ai/reactive';\nimport { getNodeForm } from '@flowgram.ai/node';\nimport { FlowNodeRenderData } from '@flowgram.ai/document';\nimport { PlaygroundEntityContext, useListenEvents, useService } from '@flowgram.ai/core';\n\nimport { WorkflowDragService, WorkflowSelectService } from '../service';\nimport { WorkflowNodePortsData } from '../entity-datas';\nimport { type WorkflowNodeEntity } from '../entities';\nimport { usePlaygroundReadonlyState } from './use-playground-readonly-state';\nimport { type NodeRenderReturnType } from './typings';\n\nfunction checkTargetDraggable(el: any): boolean {\n return (\n el &&\n el.tagName !== 'INPUT' &&\n el.tagName !== 'TEXTAREA' &&\n !el.closest('.flow-canvas-not-draggable')\n );\n}\nexport function useNodeRender(nodeFromProps?: WorkflowNodeEntity): NodeRenderReturnType {\n const node = nodeFromProps || useContext<WorkflowNodeEntity>(PlaygroundEntityContext);\n const renderData = node.getData(FlowNodeRenderData)!;\n const portsData = node.getData(WorkflowNodePortsData)!;\n const readonly = usePlaygroundReadonlyState();\n const dragService = useService<WorkflowDragService>(WorkflowDragService);\n const selectionService = useService<WorkflowSelectService>(WorkflowSelectService);\n const isDragging = useRef(false);\n const nodeRef = useRef<HTMLDivElement | null>(null);\n const [linkingNodeId, setLinkingNodeId] = useState('');\n\n useEffect(() => {\n const disposable = dragService.onDragLineEventChange(({ type, onDragNodeId }) => {\n if (type === 'onDrag') {\n setLinkingNodeId(onDragNodeId || '');\n } else {\n setLinkingNodeId('');\n }\n });\n\n return () => {\n disposable.dispose();\n };\n }, []);\n\n const startDrag = useCallback(\n (e: React.MouseEvent) => {\n e.preventDefault();\n if (!selectionService.isSelected(node.id)) {\n selectNode(e);\n }\n // 输入框不能拖拽\n if (!checkTargetDraggable(e.target) || !checkTargetDraggable(document.activeElement)) {\n return;\n }\n isDragging.current = true;\n // 拖拽选中的节点\n dragService.startDragSelectedNodes(e)?.finally(() =>\n setTimeout(() => {\n isDragging.current = false;\n })\n );\n },\n [dragService, node]\n );\n /**\n * 单选节点\n */\n const selectNode = useCallback(\n (e: React.MouseEvent) => {\n // 触发了拖拽就不要再触发单选\n if (isDragging.current) {\n return;\n }\n // 追加选择\n if (e.shiftKey) {\n selectionService.toggleSelect(node);\n } else {\n selectionService.selectNode(node);\n }\n if (e.target) {\n (e.target as HTMLDivElement).focus();\n }\n },\n [node]\n );\n const deleteNode = useCallback(() => node.dispose(), [node]);\n // 监听端口变化\n useListenEvents(portsData.onDataChange);\n\n /**\n * - 下面的 firefox 为了修复一个 bug:https://meego.feishu.cn/bot_bot/issue/detail/3001017843\n * - firefox 下 draggable 属性会影响节点 input 内容 focus:https://jsfiddle.net/Aydar/ztsvbyep/3/\n * - 该 bug 在 firefox 浏览器上存在了很久,需要作兼容:https://bugzilla.mozilla.org/show_bug.cgi?id=739071\n */\n const isFirefox = navigator?.userAgent?.includes?.('Firefox');\n const onFocus = useCallback(() => {\n if (isFirefox) {\n nodeRef.current?.setAttribute('draggable', 'false');\n }\n }, []);\n const onBlur = useCallback(() => {\n if (isFirefox) {\n nodeRef.current?.setAttribute('draggable', 'true');\n }\n }, []);\n const getExtInfo = useCallback(() => node.getExtInfo() as any, [node]);\n const updateExtInfo = useCallback(\n (data: any) => {\n node.updateExtInfo(data);\n },\n [node]\n );\n const form = useMemo(() => getNodeForm(node), [node]);\n // Listen FormState change\n const formState = useObserve<any>(form?.state);\n const toggleExpand = useCallback(() => {\n renderData.toggleExpand();\n }, [renderData]);\n\n return {\n node,\n selected: selectionService.isSelected(node.id),\n activated: selectionService.isActivated(node.id),\n expanded: renderData.expanded,\n startDrag,\n ports: portsData.allPorts,\n deleteNode,\n selectNode,\n readonly,\n linkingNodeId,\n nodeRef,\n onFocus,\n onBlur,\n getExtInfo,\n updateExtInfo,\n toggleExpand,\n get form() {\n if (!form) return undefined;\n return {\n ...form,\n get values() {\n return form.values!;\n },\n get state() {\n return formState;\n },\n };\n },\n };\n}\n","import { inject, injectable } from 'inversify';\nimport {\n type Entity,\n Playground,\n SelectionService,\n TransformData,\n type PlaygroundConfigRevealOpts,\n} from '@flowgram.ai/core';\nimport { type Event, Rectangle, SizeSchema } from '@flowgram.ai/utils';\n\nimport { delay } from '../utils';\nimport { WorkflowNodeEntity } from '../entities';\nimport { type WorkfloEntityHoverable } from './workflow-hover-service';\n\n@injectable()\nexport class WorkflowSelectService {\n @inject(SelectionService) protected selectionService: SelectionService;\n\n @inject(Playground) protected playground: Playground;\n\n get onSelectionChanged(): Event<void> {\n return this.selectionService.onSelectionChanged;\n }\n\n get selection(): Entity[] {\n return this.selectionService.selection;\n }\n\n set selection(entities: Entity[]) {\n this.selectionService.selection = entities;\n }\n\n /**\n * 当前激活的节点只能有一个\n */\n get activatedNode(): WorkflowNodeEntity | undefined {\n const { selectedNodes } = this;\n if (selectedNodes.length !== 1) {\n return undefined;\n }\n return selectedNodes[0];\n }\n\n isSelected(id: string): boolean {\n return this.selectionService.selection.some(s => s.id === id);\n }\n\n isActivated(id: string): boolean {\n return this.activatedNode?.id === id;\n }\n\n /**\n * 选中的节点\n */\n get selectedNodes(): WorkflowNodeEntity[] {\n return this.selectionService.selection.filter(\n n => n instanceof WorkflowNodeEntity,\n ) as WorkflowNodeEntity[];\n }\n\n /**\n * 选中\n * @param node\n */\n selectNode(node: WorkflowNodeEntity): void {\n this.selectionService.selection = [node];\n }\n\n toggleSelect(node: WorkflowNodeEntity): void {\n if (this.selectionService.selection.includes(node)) {\n this.selectionService.selection = this.selectionService.selection.filter(n => n !== node);\n } else {\n this.selectionService.selection = this.selectionService.selection.concat(node);\n }\n }\n\n select(node: WorkfloEntityHoverable): void {\n this.selectionService.selection = [node];\n }\n\n clear(): void {\n this.selectionService.selection = [];\n }\n\n /**\n * 选中并滚动到节点\n * @param node\n */\n async selectNodeAndScrollToView(node: WorkflowNodeEntity, fitView?: boolean): Promise<void> {\n this.selectNodeAndFocus(node);\n const DELAY_TIME = 30;\n // 等待节点渲染完成(一般用于刚添加的节点)\n await delay(DELAY_TIME);\n\n const scrollConfig: PlaygroundConfigRevealOpts = {\n entities: [node],\n };\n\n if (fitView) {\n const bounds = Rectangle.enlarge([node.getData<TransformData>(TransformData).bounds]).pad(\n 30,\n 30,\n ); // 留出 30 像素的边界\n\n const viewport = this.playground.config.getViewport(false);\n\n const zoom = SizeSchema.fixSize(bounds, viewport);\n\n scrollConfig.zoom = zoom;\n scrollConfig.scrollToCenter = true;\n scrollConfig.easing = true;\n }\n\n return this.playground.config.scrollToView(scrollConfig);\n }\n\n selectNodeAndFocus(node: WorkflowNodeEntity): void {\n // 新添加的节点需要被选中\n this.select(node);\n // 拖进来需要让画布聚焦, 才能使用快捷键删除\n this.playground.node.focus();\n }\n}\n","import { bindConfigEntity } from '@flowgram.ai/core';\nexport { delay } from '@flowgram.ai/utils';\n\n/**\n * 让 entity 可以注入到类中\n *\n * @example\n * ```\n * class SomeClass {\n * @inject(PlaygroundConfigEntity) playgroundConfig: PlaygroundConfigEntity\n * }\n * ```\n * @param bind\n * @param entityRegistry\n */\nexport { bindConfigEntity };\n\nexport * from './nanoid';\nexport * from './compose';\nexport * from './fit-view';\nexport * from './get-anti-overlap-position';\nexport * from './statics';\n","import { nanoid as nanoidOrigin } from 'nanoid';\n\nexport function nanoid(n?: number): string {\n return nanoidOrigin(n);\n}\n","export { compose, composeAsync } from '@flowgram.ai/utils';\n","import { type PlaygroundConfigEntity, TransformData } from '@flowgram.ai/core';\nimport { Rectangle } from '@flowgram.ai/utils';\n\nimport { type WorkflowDocument } from '../workflow-document';\n\nexport const fitView = (\n doc: WorkflowDocument,\n playgroundConfig: PlaygroundConfigEntity,\n easing = true,\n) => {\n const bounds = Rectangle.enlarge(\n doc.getAllNodes().map(node => node.getData<TransformData>(TransformData).bounds),\n );\n // 留出 30 像素的边界\n return playgroundConfig.fitView(bounds, easing, 30);\n};\n","import { TransformData } from '@flowgram.ai/core';\nimport { type IPoint } from '@flowgram.ai/utils';\n\nimport { type WorkflowDocument } from '../workflow-document';\nimport { WorkflowNodeEntity } from '../entities';\n\n/**\n * 获取没有碰撞的位置\n * 距离很小时,xy 各偏移 30\n * @param position\n */\nexport function getAntiOverlapPosition(\n doc: WorkflowDocument,\n position: IPoint,\n containerNode?: WorkflowNodeEntity,\n): IPoint {\n let { x, y } = position;\n const nodes = containerNode ? containerNode.collapsedChildren : doc.getAllNodes();\n const positions = nodes\n .map(n => {\n const transform = n.getData<TransformData>(TransformData)!;\n return { x: transform.position.x, y: transform.position.y };\n })\n .sort((a, b) => a.y - b.y);\n const minDistance = 3;\n for (const pos of positions) {\n const { x: posX, y: posY } = pos;\n if (y - posY < -minDistance) {\n break;\n }\n const deltaX = Math.abs(x - posX);\n const deltaY = Math.abs(y - posY);\n if (deltaX <= minDistance && deltaY <= minDistance) {\n x += 30;\n y += 30;\n }\n }\n return { x, y };\n}\n","import { Rectangle } from '@flowgram.ai/utils';\n\nimport { type WorkflowNodeEntity } from '../entities/workflow-node-entity';\nexport type WorkflowPortType = 'input' | 'output';\n\nexport const getPortEntityId = (\n node: WorkflowNodeEntity,\n portType: WorkflowPortType,\n portID: string | number = '',\n): string => `port_${portType}_${node.id}_${portID}`;\n\nexport const WORKFLOW_LINE_ENTITY = 'WorkflowLineEntity';\n\nexport function domReactToBounds(react: DOMRect): Rectangle {\n return new Rectangle(react.x, react.y, react.width, react.height);\n}\n","import { FlowNodeEntity } from '@flowgram.ai/document';\n\nexport type WorkflowNodeEntity = FlowNodeEntity;\nexport const WorkflowNodeEntity = FlowNodeEntity;\n","import { isEqual } from 'lodash-es';\nimport { domUtils, type IPoint, Rectangle } from '@flowgram.ai/utils';\nimport { Entity, type EntityOpts } from '@flowgram.ai/core';\n\nimport { type WorkflowLinesManager } from '../workflow-lines-manager';\nimport { type WorkflowDocument } from '../workflow-document';\nimport { WORKFLOW_LINE_ENTITY } from '../utils/statics';\nimport { LineRenderType, type LinePosition } from '../typings/workflow-line';\nimport { type WorkflowEdgeJSON } from '../typings';\nimport { WorkflowNodePortsData } from '../entity-datas/workflow-node-ports-data';\nimport { WorkflowLineRenderData } from '../entity-datas';\nimport { type WorkflowPortEntity } from './workflow-port-entity';\nimport { type WorkflowNodeEntity } from './workflow-node-entity';\n\nexport const LINE_HOVER_DISTANCE = 8; // 线条 hover 的最小检测距离\nexport const POINT_RADIUS = 10;\n\nexport interface WorkflowLinePortInfo {\n from: string; // 前置节点 id\n to?: string; // 后置节点 id\n fromPort?: string | number; // 连线的 port 位置\n toPort?: string | number; // 连线的 port 位置\n}\n\nexport interface WorkflowLineEntityOpts extends EntityOpts, WorkflowLinePortInfo {\n document: WorkflowDocument;\n linesManager: WorkflowLinesManager;\n drawingTo?: IPoint;\n}\n\nexport interface WorkflowLineInfo extends WorkflowLinePortInfo {\n drawingTo?: IPoint; // 正在画中的元素\n isDefaultLine?: boolean; // 是否为默认的线\n highlightColor?: string; // 高亮显示\n}\n\n/**\n * 线条\n */\nexport class WorkflowLineEntity extends Entity<WorkflowLineEntityOpts> {\n static type = WORKFLOW_LINE_ENTITY;\n\n /**\n * 转成线条 id\n * @param info\n */\n static portInfoToLineId(info: WorkflowLinePortInfo): string {\n const { from, to, fromPort, toPort } = info;\n return `${from}_${fromPort || ''}-${to || ''}_${toPort || ''}`;\n }\n\n readonly document: WorkflowDocument;\n\n readonly linesManager: WorkflowLinesManager;\n\n private _from: WorkflowNodeEntity;\n\n private _to?: WorkflowNodeEntity;\n\n private _processing = false;\n\n private _hasError = false;\n\n /**\n * 线条数据\n */\n info: WorkflowLineInfo = {\n from: '',\n };\n\n readonly isDrawing: boolean;\n\n /**\n * 线条 Portal 挂载的 div\n */\n private _node?: HTMLDivElement;\n\n constructor(opts: WorkflowLineEntityOpts) {\n super(opts);\n this.document = opts.document;\n this.linesManager = opts.linesManager;\n // 初始化\n this.initInfo({\n from: opts.from,\n to: opts.to,\n drawingTo: opts.drawingTo,\n fromPort: opts.fromPort,\n toPort: opts.toPort,\n });\n if (opts.drawingTo) {\n this.isDrawing = true;\n }\n // this.onDispose(() => {\n // this._infoDispose.dispose();\n // });\n }\n\n /**\n * 获取线条的前置节点\n */\n get from(): WorkflowNodeEntity {\n return this._from;\n }\n\n /**\n * 获取线条的后置节点\n */\n get to(): WorkflowNodeEntity | undefined {\n return this._to;\n }\n\n get isHidden(): boolean {\n return this.highlightColor === this.linesManager.lineColor.hidden;\n }\n\n get inContainer(): boolean {\n const nodeInContainer = (node?: WorkflowNodeEntity) =>\n !!node?.parent && node.parent.flowNodeType !== 'root';\n return nodeInContainer(this.from) || nodeInContainer(this.to);\n }\n\n /**\n * 获取是否 testrun processing\n */\n get processing(): boolean {\n return this._processing;\n }\n\n /**\n * 设置 testrun processing 状态\n */\n set processing(status: boolean) {\n if (this._processing !== status) {\n this._processing = status;\n this.fireChange();\n }\n }\n\n // 获取连线是否为错误态\n get hasError() {\n return this._hasError;\n }\n\n // 设置连线的错误态\n set hasError(hasError: boolean) {\n if (this._hasError !== hasError) {\n this._hasError = hasError;\n this.fireChange();\n }\n if (this._node) {\n this._node.dataset.hasError = this.hasError ? 'true' : 'false';\n }\n }\n\n /**\n * 设置线条的后置节点\n */\n setToPort(toPort?: WorkflowPortEntity) {\n // 只有绘制中的线条才允许设置 port, 主要用于吸附到点\n if (!this.isDrawing) {\n throw new Error('[setToPort] only support drawing line.');\n }\n if (this.toPort === toPort) {\n return;\n }\n if (\n toPort &&\n toPort.portType === 'input' &&\n this.linesManager.canAddLine(this.fromPort, toPort, true)\n ) {\n const { node, portID } = toPort;\n this._to = node;\n this.info.drawingTo = undefined;\n this.info.isDefaultLine = false;\n this.info.to = node.id;\n this.info.toPort = portID;\n } else {\n this._to = undefined;\n this.info.to = undefined;\n this.info.toPort = '';\n }\n this.fireChange();\n }\n\n /**\n * 设置线条画线时的目标位置\n */\n set drawingTo(pos: IPoint | undefined) {\n const oldDrawingTo = this.info.drawingTo;\n if (!pos) {\n this.info.drawingTo = undefined;\n this.fireChange();\n return;\n }\n if (!oldDrawingTo || pos.x !== oldDrawingTo.x || pos.y !== oldDrawingTo.y) {\n this.info.to = undefined;\n this.info.isDefaultLine = false;\n this.info.drawingTo = pos;\n this.fireChange();\n }\n }\n\n /**\n * 获取线条正在画线的位置\n */\n get drawingTo(): IPoint | undefined {\n return this.info.drawingTo;\n }\n\n get highlightColor(): string {\n return this.info.highlightColor || '';\n }\n\n set highlightColor(color) {\n if (this.info.highlightColor !== color) {\n this.info.highlightColor = color;\n this.fireChange();\n }\n }\n\n /**\n * 获取线条的边框位置大小\n */\n get bounds(): Rectangle {\n return this.getData(WorkflowLineRenderData).bounds;\n }\n\n /**\n * 获取点和线最接近的距离\n */\n getHoverDist(pos: IPoint): number {\n return this.getData(WorkflowLineRenderData).calcDistance(pos);\n }\n\n get fromPort(): WorkflowPortEntity {\n return this.from\n .getData(WorkflowNodePortsData)\n .getPortEntityByKey('output', this.info.fromPort);\n }\n\n get toPort(): WorkflowPortEntity | undefined {\n if (!this.to) {\n return undefined;\n }\n return this.to.getData(WorkflowNodePortsData).getPortEntityByKey('input', this.info.toPort);\n }\n\n /**\n * 获取线条真实的输入输出节点坐标\n */\n get position(): LinePosition {\n return this.getData(WorkflowLineRenderData).position;\n }\n\n /** 是否反转箭头 */\n get reverse(): boolean {\n return this.linesManager.isReverseLine(this);\n }\n\n /** 是否隐藏箭头 */\n get hideArrow(): boolean {\n return this.linesManager.isHideArrowLine(this);\n }\n\n /** 是否流动 */\n get flowing(): boolean {\n return this.linesManager.isFlowingLine(this);\n }\n\n /** 是否禁用 */\n get disabled(): boolean {\n return this.linesManager.isDisabledLine(this);\n }\n\n /** 是否竖向 */\n get vertical(): boolean {\n return this.linesManager.isVerticalLine(this);\n }\n\n /** 获取线条渲染器类型 */\n get renderType(): LineRenderType | undefined {\n return this.linesManager.setLineRenderType(this);\n }\n\n /** 获取线条样式 */\n get className(): string | undefined {\n return this.linesManager.setLineClassName(this) ?? '';\n }\n\n get color(): string | undefined {\n return this.linesManager.getLineColor(this);\n }\n\n /**\n * 初始化线条\n * @param info 线条信息\n */\n protected initInfo(info: WorkflowLineInfo): void {\n if (!isEqual(info, this.info)) {\n this.info = info;\n this._from = this.document.getNode(info.from)!;\n this._to = info.to ? this.document.getNode(info.to) : undefined;\n this.fireChange();\n }\n }\n\n // 校验连线是否为错误态\n validate() {\n const { fromPort, toPort } = this;\n this.validateSelf();\n fromPort?.validate();\n toPort?.validate();\n }\n\n validateSelf() {\n const { fromPort, toPort } = this;\n\n if (fromPort) {\n this.hasError = this.linesManager.isErrorLine(fromPort, toPort);\n }\n }\n\n is(line: WorkflowLineEntity | WorkflowLinePortInfo): boolean {\n if (line instanceof WorkflowLineEntity) {\n return this === line;\n }\n return WorkflowLineEntity.portInfoToLineId(line as WorkflowLinePortInfo) === this.id;\n }\n\n canRemove(newLineInfo?: Required<WorkflowLinePortInfo>): boolean {\n return this.linesManager.canRemove(this, newLineInfo);\n }\n\n get node(): HTMLDivElement {\n if (this._node) return this._node;\n this._node = domUtils.createDivWithClass('gedit-flow-activity-line');\n this._node.dataset.testid = 'sdk.workflow.canvas.line';\n this._node.dataset.lineId = this.id;\n this._node.dataset.fromNodeId = this.from.id;\n this._node.dataset.fromPortId = this.fromPort?.id ?? '';\n this._node.dataset.toNodeId = this.to?.id ?? '';\n this._node.dataset.toPortId = this.toPort?.id ?? '';\n this._node.dataset.hasError = this.hasError ? 'true' : 'false';\n return this._node;\n }\n\n toJSON(): WorkflowEdgeJSON {\n const json = {\n sourceNodeID: this.info.from,\n targetNodeID: this.info.to!,\n sourcePortID: this.info.fromPort,\n targetPortID: this.info.toPort,\n };\n if (!json.sourcePortID) {\n delete json.sourcePortID;\n }\n if (!json.targetPortID) {\n delete json.targetPortID;\n }\n return json;\n }\n\n /** 触发线条渲染 */\n fireRender(): void {\n this.fireChange();\n }\n}\n","import { isEqual } from 'lodash-es';\nimport { FlowNodeRenderData } from '@flowgram.ai/document';\nimport { EntityData, SizeData } from '@flowgram.ai/core';\nimport { type IPoint } from '@flowgram.ai/utils';\n\nimport { type WorkflowPortType, getPortEntityId } from '../utils/statics';\nimport { type WorkflowNodeMeta } from '../typings';\nimport { WorkflowPortEntity } from '../entities/workflow-port-entity';\nimport { type WorkflowNodeEntity, type WorkflowPort, type WorkflowPorts } from '../entities';\n\n/**\n * 节点的点位信息\n * portsData 只监听点位的数目和类型,不监听点位的 position 变化\n */\nexport class WorkflowNodePortsData extends EntityData {\n public static readonly type = 'WorkflowNodePortsData';\n\n public readonly entity: WorkflowNodeEntity;\n\n /** 静态的 ports 数据 */\n protected _staticPorts: WorkflowPorts = [];\n\n /** 存储 port 实体的 id,用于判断 port 是否存在 */\n protected _portIDSet = new Set<string>();\n\n /** 上一次的 ports 数据,用于判断 ports 是否发生变化 */\n protected _prePorts: WorkflowPorts;\n\n constructor(entity: WorkflowNodeEntity) {\n super(entity);\n this.entity = entity;\n const meta = entity.getNodeMeta<WorkflowNodeMeta>();\n // 动态模式默认为空, 非动态模式默认左右两个点位\n const defaultPorts: WorkflowPorts = meta.useDynamicPort\n ? []\n : [{ type: 'input' }, { type: 'output' }];\n this._staticPorts = meta.defaultPorts?.slice() || defaultPorts;\n this.updatePorts(this._staticPorts);\n if (meta.useDynamicPort) {\n this.toDispose.push(\n // 只需要监听节点的大小,因为算的是相对位置\n entity.getData!(SizeData)!.onDataChange(() => {\n // 有可能节点被销毁了\n if (entity.getData!(SizeData).width && entity.getData!(SizeData).height) {\n this.updateDynamicPorts();\n }\n }),\n );\n }\n this.onDispose(() => {\n this.allPorts.forEach(port => port.dispose());\n });\n }\n\n public getDefaultData(): any {\n return {};\n }\n\n /**\n * 更新静态的 ports 数据\n */\n public updateStaticPorts(ports: WorkflowPorts): void {\n const meta = this.entity.getNodeMeta<WorkflowNodeMeta>();\n this._staticPorts = ports;\n if (meta.useDynamicPort) {\n this.updateDynamicPorts();\n } else {\n this.updatePorts(this._staticPorts);\n }\n }\n\n /**\n * 动态计算点位,通过 dom 的 data-port-key\n */\n public updateDynamicPorts(): void {\n const domNode = this.entity.getData(FlowNodeRenderData)!.node;\n const elements = domNode.querySelectorAll<HTMLDivElement>('[data-port-id]');\n const staticPorts: WorkflowPorts = this._staticPorts;\n const dynamicPorts: WorkflowPorts = [];\n if (elements.length > 0) {\n dynamicPorts.push(\n ...Array.from(elements).map(element => ({\n portID: element.getAttribute('data-port-id')!,\n type: element.getAttribute('data-port-type')! as WorkflowPortType,\n targetElement: element,\n })),\n );\n }\n this.updatePorts(staticPorts.concat(dynamicPorts));\n }\n\n /**\n * 根据 key 获取 port 实体\n */\n public getPortEntityByKey(\n portType: WorkflowPortType,\n portKey?: string | number,\n ): WorkflowPortEntity {\n const entity = this.getOrCreatePortEntity({\n type: portType,\n portID: portKey,\n });\n return entity;\n }\n\n /**\n * 更新 ports 数据\n */\n public updatePorts(ports: WorkflowPorts): void {\n if (!isEqual(this._prePorts, ports)) {\n const portKeys = ports.map(port => this.getPortId(port.type, port.portID));\n this._portIDSet.forEach(portId => {\n if (!portKeys.includes(portId)) {\n this.getPortEntity(portId)?.dispose();\n }\n });\n ports.forEach(port => this.updatePortEntity(port));\n this._prePorts = ports;\n this.fireChange();\n }\n\n // Note: 为什么调用 port.validate 不够,需要调用 line.validate\n // 原因:假设有这样的连线:dynamic port → end 节点。\n // line.validate 时,line.fromPort 可能为 undefined(未创建实体),导致 end 节点上的 port 未正确校验\n // 所以需要在所有 port entities 准备完成后,通过再次调用 line.validate 来触发连线另一端的 port 更新\n this.allPorts.forEach(port => {\n port.allLines.forEach(line => {\n line.validate();\n });\n port.validate();\n });\n }\n\n /**\n * 获取所有 port entities\n */\n public get allPorts(): WorkflowPortEntity[] {\n return Array.from(this._portIDSet)\n .map(portId => this.getPortEntity(portId)!)\n .filter(Boolean); // dispose 时,会获取不到 port\n }\n\n /**\n * 获取输入点位\n */\n public get inputPorts(): WorkflowPortEntity[] {\n return this.allPorts.filter(port => port.portType === 'input');\n }\n\n /**\n * 获取输出点位\n */\n public get outputPorts(): WorkflowPortEntity[] {\n return this.allPorts.filter(port => port.portType === 'output');\n }\n\n /**\n * 获取输入点位置\n */\n public get inputPoints(): IPoint[] {\n return this.inputPorts.map(port => port.point);\n }\n\n /**\n * 获取输出点位置\n */\n public get outputPoints(): IPoint[] {\n return this.inputPorts.map(port => port.point);\n }\n\n /**\n * 根据 key 获取 输入点位置\n */\n public getInputPoint(key?: string | number): IPoint {\n return this.getPortEntityByKey('input', key).point;\n }\n\n /**\n * 根据 key 获取输出点位置\n */\n public getOutputPoint(key?: string | number): IPoint {\n return this.getPortEntityByKey('output', key).point;\n }\n\n /**\n * 获取 port 实体\n */\n protected getPortEntity(portId: string): WorkflowPortEntity | undefined {\n if (!this._portIDSet.has(portId)) {\n // 如果不是自身创建的 port,则返回 undefined\n return undefined;\n }\n return this.entity.entityManager.getEntityById<WorkflowPortEntity>(portId)!;\n }\n\n /**\n * 拼接 port 实体的 id\n */\n protected getPortId(portType: WorkflowPortType, portKey: string | number = ''): string {\n return getPortEntityId(this.entity, portType, portKey);\n }\n\n /**\n * 创建 port 实体\n */\n protected createPortEntity(portInfo: WorkflowPort): WorkflowPortEntity {\n const id = this.getPortId(portInfo.type, portInfo.portID);\n let portEntity = this.entity.entityManager.getEntityById<WorkflowPortEntity>(id);\n if (!portEntity) {\n portEntity = this.entity.entityManager.createEntity<WorkflowPortEntity>(WorkflowPortEntity, {\n id,\n node: this.entity,\n ...portInfo,\n });\n }\n portEntity.onDispose(() => {\n this._portIDSet.delete(id);\n });\n this._portIDSet.add(id);\n return portEntity;\n }\n\n /**\n * 获取或创建 port 实体\n */\n protected getOrCreatePortEntity(portInfo: WorkflowPort): WorkflowPortEntity {\n const id = this.getPortId(portInfo.type, portInfo.portID);\n return this.getPortEntity(id) ?? this.createPortEntity(portInfo);\n }\n\n /**\n * 更新 port 实体\n */\n protected updatePortEntity(portInfo: WorkflowPort): WorkflowPortEntity {\n const portEntity = this.getOrCreatePortEntity(portInfo);\n if (portInfo.targetElement) {\n portEntity.updateTargetElement(portInfo.targetElement);\n }\n return portEntity;\n }\n}\n","import { type IPoint, Rectangle, Emitter } from '@flowgram.ai/utils';\nimport { FlowNodeTransformData } from '@flowgram.ai/document';\nimport {\n Entity,\n type EntityOpts,\n PlaygroundConfigEntity,\n TransformData,\n type EntityRegistry,\n} from '@flowgram.ai/core';\n\nimport { type WorkflowDocument } from '../workflow-document';\nimport {\n type WorkflowPortType,\n getPortEntityId,\n WORKFLOW_LINE_ENTITY,\n domReactToBounds,\n} from '../utils/statics';\nimport { type WorkflowNodeMeta } from '../typings';\nimport { type WorkflowNodeEntity } from './workflow-node-entity';\nimport { type WorkflowLineEntity } from './workflow-line-entity';\n\n// port 的宽度\nexport const PORT_SIZE = 24;\n\nexport interface WorkflowPort {\n /**\n * 没有代表 默认连接点,默认 input 类型 为最左边中心,output 类型为最右边中心\n */\n portID?: string | number;\n /**\n * 禁用端口\n */\n disabled?: boolean;\n /**\n * 将点位渲染到该父节点上\n */\n targetElement?: HTMLElement;\n /**\n * 输入或者输出点\n */\n type: WorkflowPortType;\n}\n\nexport type WorkflowPorts = WorkflowPort[];\n\nexport interface WorkflowPortEntityOpts extends EntityOpts, WorkflowPort {\n /**\n * port 属于哪个节点\n */\n node: WorkflowNodeEntity;\n}\n\n/**\n * Port 抽象的 Entity\n */\nexport class WorkflowPortEntity extends Entity<WorkflowPortEntityOpts> {\n static type = 'WorkflowPortEntity';\n\n readonly node: WorkflowNodeEntity;\n\n targetElement?: HTMLElement;\n\n readonly portID: string | number = '';\n\n readonly _disabled: boolean = false;\n\n private _hasError = false;\n\n protected readonly _onErrorChangedEmitter = new Emitter<void>();\n\n onErrorChanged = this._onErrorChangedEmitter.event;\n\n /**\n * port 类型\n */\n portType: WorkflowPortType;\n\n static getPortEntityId(\n node: WorkflowNodeEntity,\n portType: WorkflowPortType,\n portID: string | number = ''\n ): string {\n return getPortEntityId(node, portType, portID);\n }\n\n // relativePosition\n constructor(opts: WorkflowPortEntityOpts) {\n super(opts);\n this.portID = opts.portID || '';\n this.portType = opts.type;\n this._disabled = opts.disabled ?? false;\n this.node = opts.node;\n this.updateTargetElement(opts.targetElement);\n this.toDispose.push(this.node.getData(TransformData)!.onDataChange(() => this.fireChange()));\n this.toDispose.push(this.node.onDispose(this.dispose.bind(this)));\n }\n\n // 获取连线是否为错误态\n get hasError() {\n return this._hasError;\n }\n\n // 设置连线的错误态,外部应使用 validate 进行更新\n set hasError(hasError: boolean) {\n this._hasError = hasError;\n this._onErrorChangedEmitter.fire();\n }\n\n validate() {\n // 一个端口可能连接很多线,需要保证所有的连线都不包含错误\n const anyLineHasError = this.allLines.some((line) => {\n // 忽略已销毁和被隐藏的线\n if (line.disposed || line.isHidden) {\n return false;\n }\n\n // 保证 hasError 最新\n line.validateSelf();\n\n return line.hasError;\n });\n // 如果没有连线错误,需校验端口自身错误\n const isPortHasError = (this.node.document as WorkflowDocument).isErrorPort(this);\n this.hasError = anyLineHasError || isPortHasError;\n }\n\n isErrorPort() {\n return (this.node.document as WorkflowDocument).isErrorPort(this);\n }\n\n get point(): IPoint {\n const { targetElement } = this;\n const { bounds } = this.node.getData(FlowNodeTransformData)!;\n if (targetElement) {\n const pos = domReactToBounds(targetElement.getBoundingClientRect()).center;\n return this.entityManager\n .getEntity<PlaygroundConfigEntity>(PlaygroundConfigEntity)!\n .getPosFromMouseEvent({\n clientX: pos.x,\n clientY: pos.y,\n });\n }\n if (this.portType === 'input') {\n // 默认为左边重点\n return bounds.leftCenter;\n }\n return bounds.rightCenter;\n }\n\n /**\n * 点的区域\n */\n get bounds(): Rectangle {\n const { point } = this;\n const halfSize = PORT_SIZE / 2;\n return new Rectangle(point.x - halfSize, point.y - halfSize, PORT_SIZE, PORT_SIZE);\n }\n\n isHovered(x: number, y: number): boolean {\n return this.bounds.contains(x, y);\n }\n\n /**\n * 相对节点左上角的位置\n */\n get relativePosition(): IPoint {\n const { point } = this;\n const { bounds } = this.node.getData(FlowNodeTransformData)!;\n return {\n x: point.x - bounds.x,\n y: point.y - bounds.y,\n };\n }\n\n updateTargetElement(el?: HTMLElement): void {\n if (el !== this.targetElement) {\n this.targetElement = el;\n this.fireChange();\n }\n }\n\n /**\n * 是否被禁用\n */\n get disabled(): boolean {\n const document = this.node.document as WorkflowDocument;\n if (typeof document.options.isDisabledPort === 'function') {\n return document.options.isDisabledPort(this);\n }\n if (this._disabled) {\n return true;\n }\n const meta = this.node.getNodeMeta<WorkflowNodeMeta>();\n if (this.portType === 'input') {\n return !!meta.inputDisable;\n }\n return !!meta.outputDisable;\n }\n\n /**\n * 当前点位上连接的线条\n * @deprecated use `availableLines` instead\n */\n get lines(): WorkflowLineEntity[] {\n return this.allLines.filter((line) => !line.isDrawing);\n }\n\n /**\n * 当前有效的线条,不包含正在画的线条和隐藏的线条(这个出现在线条重连会先把原来的线条隐藏)\n */\n get availableLines(): WorkflowLineEntity[] {\n return this.allLines.filter((line) => !line.isDrawing && !line.isHidden);\n }\n\n /**\n * 当前点位上连接的线条(包含 isDrawing === true 的线条)\n */\n get allLines() {\n const lines: WorkflowLineEntity[] = [];\n // TODO: 后续 sdk 支持 getEntitiesByType 单独根据 type 获取功能后修改\n // eslint-disable-next-line @typescript-eslint/consistent-type-assertions\n const allLines = this.entityManager.getEntities<WorkflowLineEntity>({\n type: WORKFLOW_LINE_ENTITY,\n } as EntityRegistry);\n allLines.forEach((line) => {\n // 不包含 drawing 的线条\n if (line.toPort === this || line.fromPort === this) {\n lines.push(line);\n }\n });\n return lines;\n }\n\n dispose(): void {\n // 点位被删除,对应的线条也要删除\n this.lines.forEach((l) => l.dispose());\n super.dispose();\n }\n}\n","import { Disposable } from '@flowgram.ai/utils';\nimport { EntityData } from '@flowgram.ai/core';\n\nimport { type WorkflowLineEntity, type WorkflowNodeEntity } from '../entities';\n\nexport interface WorkflowNodeLines {\n inputLines: WorkflowLineEntity[];\n outputLines: WorkflowLineEntity[];\n}\n\n/**\n * 节点的关联的线条\n */\nexport class WorkflowNodeLinesData extends EntityData<WorkflowNodeLines> {\n static type = 'WorkflowNodeLinesData';\n\n entity: WorkflowNodeEntity;\n\n getDefaultData(): WorkflowNodeLines {\n return {\n inputLines: [],\n outputLines: [],\n };\n }\n\n constructor(entity: WorkflowNodeEntity) {\n super(entity);\n this.entity = entity;\n this.entity.preDispose.push(\n Disposable.create(() => {\n this.inputLines.slice().forEach((line) => line.dispose());\n this.outputLines.slice().forEach((line) => line.dispose());\n })\n );\n }\n\n /**\n * 输入线条\n */\n get inputLines(): WorkflowLineEntity[] {\n return this.data.inputLines;\n }\n\n /**\n * 输出线条\n */\n get outputLines(): WorkflowLineEntity[] {\n return this.data.outputLines;\n }\n\n /**\n * 输入节点\n */\n get inputNodes(): WorkflowNodeEntity[] {\n return this.inputLines.map((l) => l.from!).filter(Boolean);\n }\n\n /**\n * 所有输入节点\n */\n get allInputNodes(): WorkflowNodeEntity[] {\n const nodeSet: Set<WorkflowNodeEntity> = new Set();\n\n const handleNode = (node: WorkflowNodeEntity): void => {\n if (nodeSet.has(node)) {\n return;\n }\n\n nodeSet.add(node);\n\n const { inputNodes } = node.getData<WorkflowNodeLinesData>(WorkflowNodeLinesData)!;\n if (!inputNodes || !inputNodes.length) {\n return;\n }\n\n inputNodes.forEach((inputNode: WorkflowNodeEntity) => {\n // 如果 outputNode 和当前 node 是父子节点,则不向下遍历\n if (inputNode?.parent === node || node?.parent === inputNode) {\n return;\n }\n handleNode(inputNode);\n });\n };\n\n handleNode(this.entity);\n nodeSet.delete(this.entity);\n\n return Array.from(nodeSet);\n }\n\n /**\n * 输出节点\n */\n get outputNodes(): WorkflowNodeEntity[] {\n return this.outputLines.map((l) => l.to!).filter(Boolean);\n }\n\n /**\n * 输入输出节点\n */\n get allOutputNodes(): WorkflowNodeEntity[] {\n const nodeSet: Set<WorkflowNodeEntity> = new Set();\n\n const handleNode = (node: WorkflowNodeEntity): void => {\n if (nodeSet.has(node)) {\n return;\n }\n\n nodeSet.add(node);\n\n const { outputNodes } = node.getData<WorkflowNodeLinesData>(WorkflowNodeLinesData)!;\n if (!outputNodes || !outputNodes.length) {\n return;\n }\n\n outputNodes.forEach((outputNode: WorkflowNodeEntity) => {\n // 如果 outputNode 和当前 node 是父子节点,则不向下遍历\n if (outputNode?.parent === node || node?.parent === outputNode) {\n return;\n }\n handleNode(outputNode);\n });\n };\n\n handleNode(this.entity);\n nodeSet.delete(this.entity);\n\n return Array.from(nodeSet);\n }\n\n addLine(line: WorkflowLineEntity): void {\n if (line.from === this.entity) {\n this.outputLines.push(line);\n } else {\n this.inputLines.push(line);\n }\n this.fireChange();\n }\n\n removeLine(line: WorkflowLineEntity): void {\n const { inputLines, outputLines } = this;\n const inputIndex = inputLines.indexOf(line);\n const outputIndex = outputLines.indexOf(line);\n if (inputIndex !== -1) {\n inputLines.splice(inputIndex, 1);\n this.fireChange();\n }\n if (outputIndex !== -1) {\n outputLines.splice(outputIndex, 1);\n this.fireChange();\n }\n }\n}\n","import { IPoint, Rectangle } from '@flowgram.ai/utils';\nimport { EntityData } from '@flowgram.ai/core';\n\nimport {\n LinePosition,\n LineRenderType,\n WorkflowLineRenderContribution,\n WorkflowLineRenderContributionFactory,\n} from '../typings';\nimport { WorkflowLineEntity } from '../entities';\nimport { WorkflowNodePortsData } from './workflow-node-ports-data';\n\nexport interface WorkflowLineRenderDataSchema {\n version: string;\n contributions: Map<LineRenderType, WorkflowLineRenderContribution>;\n position: LinePosition;\n}\n\nexport class WorkflowLineRenderData extends EntityData<WorkflowLineRenderDataSchema> {\n static type = 'WorkflowLineRenderData';\n\n declare entity: WorkflowLineEntity;\n\n constructor(entity: WorkflowLineEntity) {\n super(entity);\n this.syncContributions();\n }\n\n public getDefaultData(): WorkflowLineRenderDataSchema {\n return {\n version: '',\n contributions: new Map(),\n position: {\n from: { x: 0, y: 0 },\n to: { x: 0, y: 0 },\n },\n };\n }\n\n public get renderVersion(): string {\n return this.data.version;\n }\n\n public get position(): LinePosition {\n return this.data.position;\n }\n\n public get path(): string {\n return this.currentLine?.path ?? '';\n }\n\n public calcDistance(pos: IPoint): number {\n return this.currentLine?.calcDistance(pos) ?? Number.MAX_SAFE_INTEGER;\n }\n\n public get bounds(): Rectangle {\n return this.currentLine?.bounds ?? new Rectangle();\n }\n\n /**\n * 更新数据\n * WARNING: 这个方法,必须在 requestAnimationFrame / useLayoutEffect 中调用,否则会引起浏览器强制重排\n */\n public update(): void {\n this.syncContributions();\n const oldVersion = this.data.version;\n this.updatePosition();\n const newVersion = this.data.version;\n if (oldVersion === newVersion) {\n return;\n }\n this.data.version = newVersion;\n this.currentLine?.update({\n fromPos: this.data.position.from,\n toPos: this.data.position.to,\n });\n }\n\n private get lineType(): LineRenderType {\n return this.entity.renderType ?? this.entity.linesManager.lineType;\n }\n\n /**\n * 更新版本\n * WARNING: 这个方法,必须在 requestAnimationFrame / useLayoutEffect 中调用,否则会引起浏览器强制重排\n */\n private updatePosition(): void {\n this.data.position.from = this.entity.from\n .getData(WorkflowNodePortsData)!\n .getOutputPoint(this.entity.info.fromPort);\n\n this.data.position.to = this.entity.info.drawingTo ??\n this.entity.to?.getData(WorkflowNodePortsData)?.getInputPoint(this.entity.info.toPort) ?? {\n x: this.data.position.from.x,\n y: this.data.position.from.y,\n };\n\n this.data.version = [\n this.lineType,\n this.data.position.from.x,\n this.data.position.from.y,\n this.data.position.to.x,\n this.data.position.to.y,\n ].join('-');\n }\n\n private get currentLine(): WorkflowLineRenderContribution | undefined {\n return this.data.contributions.get(this.lineType);\n }\n\n private syncContributions(): void {\n if (this.entity.linesManager.contributionFactories.length === this.data.contributions.size) {\n return;\n }\n this.entity.linesManager.contributionFactories.forEach((factory) => {\n this.registerContribution(factory);\n });\n }\n\n private registerContribution(contributionFactory: WorkflowLineRenderContributionFactory): void {\n if (this.data.contributions.has(contributionFactory.type)) {\n return;\n }\n const contribution = new contributionFactory(this.entity);\n this.data.contributions.set(contributionFactory.type, contribution);\n }\n}\n","import { inject, injectable } from 'inversify';\nimport { Emitter, type IPoint } from '@flowgram.ai/utils';\nimport { EntityManager } from '@flowgram.ai/core';\n\nimport {\n type WorkflowLineEntity,\n type WorkflowNodeEntity,\n type WorkflowPortEntity,\n} from '../entities';\n\n/**\n * 可 Hover 的节点 类型\n */\nexport type WorkflowEntityHoverable = WorkflowNodeEntity | WorkflowLineEntity | WorkflowPortEntity;\n\n/** @deprecated */\nexport type WorkfloEntityHoverable = WorkflowEntityHoverable;\n/**\n * hover 状态管理\n */\n@injectable()\nexport class WorkflowHoverService {\n @inject(EntityManager) protected entityManager: EntityManager;\n\n protected onHoveredChangeEmitter = new Emitter<string>();\n\n readonly onHoveredChange = this.onHoveredChangeEmitter.event;\n\n // 当前鼠标 hover 位置\n hoveredPos: IPoint = { x: 0, y: 0 };\n\n /**\n * 当前 hovered 的 节点或者线条或者点\n * 1: nodeId / lineId (节点 / 线条)\n * 2: nodeId:portKey (节点连接点)\n */\n hoveredKey = '';\n\n /**\n * 更新 hover 的内容\n * @param hoveredKey hovered key\n */\n updateHoveredKey(hoveredKey: string): void {\n if (this.hoveredKey !== hoveredKey) {\n this.hoveredKey = hoveredKey;\n this.onHoveredChangeEmitter.fire(hoveredKey);\n }\n }\n\n /**\n * 清空 hover 内容\n */\n clearHovered(): void {\n this.updateHoveredKey('');\n }\n\n /**\n * 判断是否 hover\n * @param nodeId hoveredKey\n * @returns 是否 hover\n */\n isHovered(nodeId: string): boolean {\n return nodeId === this.hoveredKey;\n }\n\n isSomeHovered(): boolean {\n return !!this.hoveredKey;\n }\n\n /**\n * 获取被 hover 的节点或线条\n */\n get hoveredNode(): WorkfloEntityHoverable | undefined {\n return this.entityManager.getEntityById(this.hoveredKey);\n }\n}\n","import type React from 'react';\n\nimport { nanoid } from 'nanoid';\nimport { inject, injectable, postConstruct } from 'inversify';\nimport {\n domUtils,\n type IPoint,\n PromiseDeferred,\n Emitter,\n type PositionSchema,\n DisposableCollection,\n Rectangle,\n delay,\n Disposable,\n} from '@flowgram.ai/utils';\nimport {\n FlowNodeTransformData,\n FlowNodeType,\n FlowOperationBaseService,\n type FlowNodeEntity,\n} from '@flowgram.ai/document';\nimport { FlowNodeBaseType } from '@flowgram.ai/document';\nimport {\n CommandService,\n PlaygroundConfigEntity,\n PlaygroundDrag,\n type PlaygroundDragEvent,\n TransformData,\n} from '@flowgram.ai/core';\n\nimport { WorkflowLinesManager } from '../workflow-lines-manager';\nimport { WorkflowDocumentOptions } from '../workflow-document-option';\nimport { WorkflowDocument } from '../workflow-document';\nimport { LineEventProps, NodesDragEvent, OnDragLineEnd } from '../typings/workflow-drag';\nimport { type WorkflowNodeJSON, type WorkflowNodeMeta } from '../typings';\nimport { WorkflowNodePortsData } from '../entity-datas';\nimport {\n type WorkflowLineEntity,\n type WorkflowLinePortInfo,\n type WorkflowNodeEntity,\n type WorkflowPortEntity,\n} from '../entities';\nimport { WorkflowSelectService } from './workflow-select-service';\nimport { WorkflowHoverService } from './workflow-hover-service';\n\nconst DRAG_TIMEOUT = 100;\nconst DRAG_MIN_DELTA = 5;\nfunction checkDragSuccess(\n time: number,\n e: PlaygroundDragEvent,\n originLine?: WorkflowLineEntity\n): boolean {\n if (\n !originLine ||\n time > DRAG_TIMEOUT ||\n Math.abs(e.endPos.x - e.startPos.x) >= DRAG_MIN_DELTA ||\n Math.abs(e.endPos.y - e.startPos.y) >= DRAG_MIN_DELTA\n ) {\n return true;\n }\n return false;\n}\n\n@injectable()\nexport class WorkflowDragService {\n @inject(PlaygroundConfigEntity)\n protected playgroundConfig: PlaygroundConfigEntity;\n\n @inject(WorkflowHoverService) protected hoverService: WorkflowHoverService;\n\n @inject(WorkflowDocument) protected document: WorkflowDocument;\n\n @inject(WorkflowLinesManager) protected linesManager: WorkflowLinesManager;\n\n @inject(CommandService) protected commandService: CommandService;\n\n @inject(WorkflowSelectService) protected selectService: WorkflowSelectService;\n\n @inject(FlowOperationBaseService)\n protected operationService: FlowOperationBaseService;\n\n @inject(WorkflowDocumentOptions)\n readonly options: WorkflowDocumentOptions;\n\n private _onDragLineEventEmitter = new Emitter<LineEventProps>();\n\n readonly onDragLineEventChange = this._onDragLineEventEmitter.event;\n\n isDragging = false;\n\n private _nodesDragEmitter = new Emitter<NodesDragEvent>();\n\n readonly onNodesDrag = this._nodesDragEmitter.event;\n\n protected _toDispose = new DisposableCollection();\n\n private _droppableTransforms: FlowNodeTransformData[] = [];\n\n private _dropNode?: FlowNodeEntity;\n\n private posAdjusters: Set<\n (params: { selectedNodes: WorkflowNodeEntity[]; position: IPoint }) => IPoint\n > = new Set();\n\n private _onDragLineEndCallbacks: Map<string, OnDragLineEnd> = new Map();\n\n @postConstruct()\n init() {\n this._toDispose.pushAll([this._onDragLineEventEmitter, this._nodesDragEmitter]);\n if (this.options.onDragLineEnd) {\n this._toDispose.push(this.onDragLineEnd(this.options.onDragLineEnd));\n }\n }\n\n dispose() {\n this._toDispose.dispose();\n }\n\n /**\n * 拖拽选中节点\n * @param triggerEvent\n */\n async startDragSelectedNodes(triggerEvent: MouseEvent | React.MouseEvent): Promise<boolean> {\n let { selectedNodes } = this.selectService;\n if (\n selectedNodes.length === 0 ||\n this.playgroundConfig.readonly ||\n this.playgroundConfig.disabled ||\n this.isDragging\n ) {\n return Promise.resolve(false);\n }\n this.isDragging = true;\n const sameParent = this.childrenOfContainer(selectedNodes);\n if (sameParent && sameParent.flowNodeType !== FlowNodeBaseType.ROOT) {\n selectedNodes = [sameParent];\n }\n // 节点整体开始位置\n let startPosition = this.getNodesPosition(selectedNodes);\n // 单个节点开始位置\n let startPositions = selectedNodes.map((node) => {\n const transform = node.getData(TransformData);\n return { x: transform.position.x, y: transform.position.y };\n });\n let dragSuccess = false;\n const startTime = Date.now();\n const dragger = new PlaygroundDrag({\n onDragStart: (dragEvent) => {\n this._nodesDragEmitter.fire({\n type: 'onDragStart',\n nodes: selectedNodes,\n startPositions,\n dragEvent,\n triggerEvent,\n dragger,\n });\n },\n onDrag: (dragEvent) => {\n if (!dragSuccess && checkDragSuccess(Date.now() - startTime, dragEvent)) {\n dragSuccess = true;\n }\n\n // 计算拖拽偏移量\n const offset: IPoint = this.getDragPosOffset({\n event: dragEvent,\n selectedNodes,\n startPosition,\n });\n\n const positions: PositionSchema[] = [];\n\n selectedNodes.forEach((node, index) => {\n const transform = node.getData(TransformData);\n const nodeStartPosition = startPositions[index];\n const newPosition = {\n x: nodeStartPosition.x + offset.x,\n y: nodeStartPosition.y + offset.y,\n };\n transform.update({\n position: newPosition,\n });\n this.document.layout.updateAffectedTransform(node);\n positions.push(newPosition);\n });\n\n this._nodesDragEmitter.fire({\n type: 'onDragging',\n nodes: selectedNodes,\n startPositions,\n positions,\n dragEvent,\n triggerEvent,\n dragger,\n });\n },\n onDragEnd: (dragEvent) => {\n this.isDragging = false;\n this._nodesDragEmitter.fire({\n type: 'onDragEnd',\n nodes: selectedNodes,\n startPositions,\n dragEvent,\n triggerEvent,\n dragger,\n });\n },\n });\n return dragger\n .start(triggerEvent.clientX, triggerEvent.clientY, this.playgroundConfig)\n ?.then(() => dragSuccess);\n }\n\n /**\n * 通过拖入卡片添加\n * @param type\n * @param event\n * @param data 节点数据\n */\n async dropCard(\n type: string,\n event: { clientX: number; clientY: number },\n data?: Partial<WorkflowNodeJSON>,\n parent?: WorkflowNodeEntity\n ): Promise<WorkflowNodeEntity | undefined> {\n const mousePos = this.playgroundConfig.getPosFromMouseEvent(event);\n if (!this.playgroundConfig.getViewport().contains(mousePos.x, mousePos.y)) {\n // 鼠标范围不在画布之内\n return;\n }\n const position = this.adjustSubNodePosition(type, parent, mousePos);\n\n const node: WorkflowNodeEntity = await this.document.createWorkflowNodeByType(\n type,\n position,\n data,\n parent?.id\n );\n return node;\n }\n\n /**\n * 拖拽卡片到画布\n * 返回创建结果\n * @param type\n * @param event\n */\n async startDragCard(\n type: string,\n event: React.MouseEvent,\n data: Partial<WorkflowNodeJSON>,\n cloneNode?: (e: PlaygroundDragEvent) => HTMLDivElement // 创建拖拽的dom\n ): Promise<WorkflowNodeEntity | undefined> {\n let domNode: HTMLDivElement;\n let startPos: IPoint = { x: 0, y: 0 };\n const deferred = new PromiseDeferred<WorkflowNodeEntity | undefined>();\n const dragger = new PlaygroundDrag({\n onDragStart: (e) => {\n const targetNode = event.currentTarget as HTMLDivElement;\n domNode = cloneNode ? cloneNode(e) : (targetNode.cloneNode(true) as HTMLDivElement);\n const bounds = targetNode.getBoundingClientRect();\n startPos = { x: bounds.left, y: bounds.top };\n domUtils.setStyle(domNode, {\n zIndex: 1000,\n position: 'absolute',\n left: startPos.x,\n top: startPos.y,\n boxShadow: '0 6px 8px 0 rgba(28, 31, 35, .2)',\n });\n document.body.appendChild(domNode);\n this.updateDroppableTransforms();\n },\n onDrag: (e) => {\n const deltaX = e.endPos.x - e.startPos.x;\n const deltaY = e.endPos.y - e.startPos.y;\n const left = startPos.x + deltaX;\n const right = startPos.y + deltaY;\n domNode.style.left = `${left}px`;\n domNode.style.top = `${right}px`;\n // 节点类型拖拽碰撞检测\n const { x, y } = this.playgroundConfig.getPosFromMouseEvent(e);\n const draggingRect = new Rectangle(x, y, 170, 90);\n const collisionTransform = this._droppableTransforms.find((transform) => {\n const { bounds, entity } = transform;\n const padding = this.document.layout.getPadding(entity);\n const transformRect = new Rectangle(\n bounds.x + padding.left + padding.right,\n bounds.y,\n bounds.width,\n bounds.height\n );\n // 检测两个正方形是否相互碰撞\n return Rectangle.intersects(draggingRect, transformRect);\n });\n this.updateDropNode(collisionTransform?.entity);\n },\n onDragEnd: async (e) => {\n const dropNode = this._dropNode;\n const { allowDrop } = this.canDropToNode({\n dragNodeType: type,\n dropNode,\n });\n const dragNode = allowDrop ? await this.dropCard(type, e, data, dropNode) : undefined;\n this.clearDrop();\n if (dragNode) {\n domNode.remove();\n deferred.resolve(dragNode);\n } else {\n domNode.style.transition = 'all ease .2s';\n domNode.style.left = `${startPos.x}px`;\n domNode.style.top = `${startPos.y}px`;\n const TIMEOUT = 200;\n await delay(TIMEOUT);\n domNode.remove();\n deferred.resolve();\n }\n },\n });\n await dragger.start(event.clientX, event.clientY);\n return deferred.promise;\n }\n\n /**\n * 如果存在容器节点,且传入鼠标坐标,需要用容器的坐标减去传入的鼠标坐标\n */\n public adjustSubNodePosition(\n subNodeType?: string,\n containerNode?: WorkflowNodeEntity,\n mousePos?: IPoint,\n resetEmptyPos: boolean = true\n ): IPoint {\n if (!mousePos) {\n return { x: 0, y: 0 };\n }\n if (!subNodeType || !containerNode || containerNode.flowNodeType === FlowNodeBaseType.ROOT) {\n return mousePos;\n }\n const isParentEmpty = !containerNode.children || containerNode.children.length === 0;\n const parentPadding = this.document.layout.getPadding(containerNode);\n const parentTransform = containerNode.getData<TransformData>(TransformData);\n if (isParentEmpty && resetEmptyPos) {\n // 确保空容器节点不偏移\n return {\n x: 0,\n y: parentPadding.top,\n };\n } else {\n return {\n x: mousePos.x - parentTransform.position.x,\n y: mousePos.y - parentTransform.position.y,\n };\n }\n }\n\n /**\n * 注册位置调整\n */\n public registerPosAdjuster(\n adjuster: (params: { selectedNodes: WorkflowNodeEntity[]; position: IPoint }) => IPoint\n ) {\n this.posAdjusters.add(adjuster);\n return {\n dispose: () => this.posAdjusters.delete(adjuster),\n };\n }\n\n /**\n * 判断是否可以放置节点\n */\n public canDropToNode(params: { dragNodeType?: FlowNodeType; dropNode?: WorkflowNodeEntity }): {\n allowDrop: boolean;\n message?: string;\n dropNode?: WorkflowNodeEntity;\n } {\n const { dragNodeType, dropNode } = params;\n if (!dragNodeType) {\n return {\n allowDrop: false,\n message: 'Please select a node to drop',\n };\n }\n return {\n allowDrop: true,\n dropNode,\n };\n }\n\n /**\n * 获取拖拽偏移\n */\n private getDragPosOffset(params: {\n event: PlaygroundDragEvent;\n selectedNodes: WorkflowNodeEntity[];\n startPosition: IPoint;\n }) {\n const { event, selectedNodes, startPosition } = params;\n const { finalScale } = this.playgroundConfig;\n const mouseOffset: IPoint = {\n x: (event.endPos.x - event.startPos.x) / finalScale,\n y: (event.endPos.y - event.startPos.y) / finalScale,\n };\n const wholePosition: IPoint = {\n x: startPosition.x + mouseOffset.x,\n y: startPosition.y + mouseOffset.y,\n };\n const adjustedOffsets: IPoint[] = Array.from(this.posAdjusters.values()).map((adjuster) =>\n adjuster({\n selectedNodes,\n position: wholePosition,\n })\n );\n const offset: IPoint = adjustedOffsets.reduce(\n (offset, adjustOffset) => ({\n x: offset.x + adjustOffset.x,\n y: offset.y + adjustOffset.y,\n }),\n mouseOffset\n );\n return offset;\n }\n\n private updateDroppableTransforms() {\n this._droppableTransforms = this.document\n .getRenderDatas(FlowNodeTransformData, false)\n .filter((transform) => {\n const { entity } = transform;\n if (entity.originParent) {\n return this.nodeSelectable(entity) && this.nodeSelectable(entity.originParent);\n }\n return this.nodeSelectable(entity);\n })\n .filter((transform) => this.isContainer(transform.entity));\n }\n\n /** 是否容器节点 */\n private isContainer(node?: WorkflowNodeEntity): boolean {\n return node?.getNodeMeta<WorkflowNodeMeta>().isContainer ?? false;\n }\n\n /**\n * 获取节点整体位置\n */\n private getNodesPosition(nodes: WorkflowNodeEntity[]): IPoint {\n const selectedBounds = Rectangle.enlarge(\n nodes.map((n) => n.getData(FlowNodeTransformData)!.bounds)\n );\n const position: IPoint = {\n x: selectedBounds.x,\n y: selectedBounds.y,\n };\n return position;\n }\n\n private nodeSelectable(node: FlowNodeEntity) {\n const selectable = node.getNodeMeta().selectable;\n if (typeof selectable === 'function') {\n return selectable(node);\n } else {\n return selectable;\n }\n }\n\n private updateDropNode(node?: FlowNodeEntity) {\n if (this._dropNode) {\n if (this._dropNode.id === node?.id) {\n return;\n }\n this.selectService.clear();\n }\n if (node) {\n this.selectService.selectNode(node);\n }\n this._dropNode = node;\n }\n\n private clearDrop() {\n if (this._dropNode) {\n this.selectService.clear();\n }\n this._dropNode = undefined;\n this._droppableTransforms = [];\n }\n\n private setLineColor(line: WorkflowLineEntity, color: string) {\n line.highlightColor = color;\n this.hoverService.clearHovered();\n }\n\n private handleDragOnNode(\n toNode: WorkflowNodeEntity,\n fromPort: WorkflowPortEntity,\n line: WorkflowLineEntity,\n toPort?: WorkflowPortEntity,\n originLine?: WorkflowLineEntity\n ): {\n hasError: boolean;\n } {\n if (\n toPort &&\n (originLine?.toPort === toPort ||\n (toPort.portType === 'input' && this.linesManager.canAddLine(fromPort, toPort, true)))\n ) {\n // 同一条线条则不用在判断 canAddLine\n this.hoverService.updateHoveredKey(toPort.id);\n line.setToPort(toPort);\n this._onDragLineEventEmitter.fire({\n type: 'onDrag',\n onDragNodeId: toNode.id,\n });\n return {\n hasError: false,\n };\n } else if (this.isContainer(toNode)) {\n // 在容器内进行连线的情况,需忽略\n return {\n hasError: false,\n };\n } else {\n this.setLineColor(line, this.linesManager.lineColor.error);\n return {\n hasError: true,\n };\n }\n }\n\n private childrenOfContainer(nodes: WorkflowNodeEntity[]): WorkflowNodeEntity | undefined {\n if (nodes.length === 0) {\n return;\n }\n const sourceContainer = nodes[0]?.parent;\n if (!sourceContainer || sourceContainer.collapsedChildren.length !== nodes.length) {\n return;\n }\n const valid = nodes.every((node) => node?.parent === sourceContainer);\n if (!valid) {\n return;\n }\n return sourceContainer;\n }\n\n /**\n * 绘制线条\n * @param opts\n * @param event\n */\n async startDrawingLine(\n fromPort: WorkflowPortEntity,\n event: { clientX: number; clientY: number },\n originLine?: WorkflowLineEntity\n ): Promise<{\n dragSuccess?: boolean; // 是否拖拽成功,不成功则为选择节点\n newLine?: WorkflowLineEntity; // 新的线条\n }> {\n const isFromInActivePort = !originLine && fromPort.isErrorPort() && fromPort.disabled;\n if (\n originLine?.disabled ||\n isFromInActivePort ||\n this.playgroundConfig.readonly ||\n this.playgroundConfig.disabled\n ) {\n return { dragSuccess: false, newLine: undefined };\n }\n\n this.selectService.clear();\n const config = this.playgroundConfig;\n const deferred = new PromiseDeferred<{\n dragSuccess?: boolean;\n newLine?: WorkflowLineEntity; // 新的线条\n }>();\n const preCursor = config.cursor;\n let line: WorkflowLineEntity | undefined,\n toPort: WorkflowPortEntity | undefined,\n toNode: WorkflowNodeEntity | undefined,\n lineErrorReset = false;\n const startTime = Date.now();\n let dragSuccess = false;\n const dragger = new PlaygroundDrag({\n onDrag: (e) => {\n if (!line && checkDragSuccess(Date.now() - startTime, e, originLine)) {\n // 隐藏原来的线条\n if (originLine) {\n originLine.highlightColor = this.linesManager.lineColor.hidden;\n }\n dragSuccess = true;\n // 创建临时的线条\n line = this.linesManager.createLine({\n from: fromPort.node.id,\n fromPort: fromPort.portID,\n drawingTo: config.getPosFromMouseEvent(event),\n });\n if (!line) {\n return;\n }\n config.updateCursor('grab');\n line.highlightColor = this.linesManager.lineColor.drawing;\n this.hoverService.updateHoveredKey('');\n }\n if (!line) {\n return;\n }\n\n lineErrorReset = false;\n\n const dragPos = config.getPosFromMouseEvent(e);\n\n // 默认 toNode 获取\n toNode = this.linesManager.getNodeFromMousePos(dragPos);\n // 默认 toPort 获取\n toPort = this.linesManager.getPortFromMousePos(dragPos);\n\n if (!toPort) {\n line.setToPort(undefined);\n } else if (!this.linesManager.canAddLine(fromPort, toPort, true)) {\n line.highlightColor = this.linesManager.lineColor.error;\n lineErrorReset = true;\n line.setToPort(undefined);\n } else {\n line.setToPort(toPort);\n }\n\n this._onDragLineEventEmitter.fire({\n type: 'onDrag',\n });\n\n this.setLineColor(line, this.linesManager.lineColor.drawing);\n if (toNode && !this.isContainer(toNode)) {\n // 如果鼠标 hover 在 node 中的时候,默认连线到这个 node 的初始位置\n const portsData = toNode.getData(WorkflowNodePortsData)!;\n const { inputPorts } = portsData;\n if (inputPorts.length === 1) {\n toPort = inputPorts[0];\n }\n const { hasError } = this.handleDragOnNode(toNode, fromPort, line, toPort, originLine);\n lineErrorReset = hasError;\n }\n\n if (line.toPort) {\n line.drawingTo = { x: line.toPort.point.x, y: line.toPort.point.y };\n } else {\n line.drawingTo = { x: dragPos.x, y: dragPos.y };\n }\n\n // 触发原 toPort 的校验\n originLine?.validate();\n line.validate();\n },\n // eslint-disable-next-line complexity\n onDragEnd: async (e) => {\n const dragPos = config.getPosFromMouseEvent(e);\n const onDragLineEndCallbacks = Array.from(this._onDragLineEndCallbacks.values());\n config.updateCursor(preCursor);\n await Promise.all(\n onDragLineEndCallbacks.map((callback) =>\n callback({\n fromPort,\n toPort,\n mousePos: dragPos,\n line,\n originLine,\n event: e,\n })\n )\n );\n line?.dispose();\n this._onDragLineEventEmitter.fire({\n type: 'onDragEnd',\n });\n // 清除选中状态\n if (originLine) {\n originLine.highlightColor = '';\n }\n const end = () => {\n originLine?.validate();\n deferred.resolve({ dragSuccess });\n };\n if (dragSuccess) {\n // Step 1: check same line\n if (originLine && originLine.toPort === toPort) {\n // 线条没变化则直接返回,不做处理\n return end();\n }\n // 非 input 节点不能连接\n if (toPort && toPort.portType !== 'input') {\n return end();\n }\n const newLineInfo: Required<WorkflowLinePortInfo> | undefined = toPort\n ? {\n from: fromPort.node.id,\n fromPort: fromPort.portID,\n to: toPort.node.id,\n toPort: toPort.portID,\n }\n : undefined;\n // Step2: 检测 reset\n const isReset = originLine && toPort;\n if (\n isReset &&\n !this.linesManager.canReset(\n originLine.fromPort,\n originLine.toPort as WorkflowPortEntity,\n toPort as WorkflowPortEntity\n )\n ) {\n return end();\n }\n // Step 3: delete line\n if (\n originLine &&\n (!this.linesManager.canRemove(originLine, newLineInfo, false) || lineErrorReset)\n ) {\n // 线条无法删除则返回,不再触发 canAddLine\n return end();\n } else {\n originLine?.dispose();\n }\n // Step 4: add line\n if (!toPort || !this.linesManager.canAddLine(fromPort, toPort, false)) {\n // 无法添加成功\n return end();\n }\n const newLine = this.linesManager.createLine(newLineInfo as WorkflowLinePortInfo);\n if (!newLine) {\n end();\n }\n deferred.resolve({\n dragSuccess,\n newLine,\n });\n } else {\n end();\n }\n },\n });\n await dragger.start(event.clientX, event.clientY, config);\n return deferred.promise;\n }\n\n /**\n * 重新连接线条\n * @param line\n * @param e\n */\n async resetLine(line: WorkflowLineEntity, e: MouseEvent): Promise<void> {\n const { fromPort } = line;\n const { dragSuccess } = await this.startDrawingLine(fromPort, e, line);\n if (!dragSuccess) {\n // 没有拖拽成功则表示为选中节点\n this.selectService.select(line);\n }\n }\n\n /** 线条拖拽结束 */\n public onDragLineEnd(callback: OnDragLineEnd): Disposable {\n const id = nanoid();\n this._onDragLineEndCallbacks.set(id, callback);\n return {\n dispose: () => {\n this._onDragLineEndCallbacks.delete(id);\n },\n };\n }\n}\n","import { last } from 'lodash-es';\nimport { inject, injectable } from 'inversify';\nimport { DisposableCollection, Emitter, type IPoint } from '@flowgram.ai/utils';\nimport { FlowNodeRenderData, FlowNodeTransformData } from '@flowgram.ai/document';\nimport { EntityManager, PlaygroundConfigEntity, TransformData } from '@flowgram.ai/core';\n\nimport { WorkflowDocumentOptions } from './workflow-document-option';\nimport { type WorkflowDocument } from './workflow-document';\nimport {\n LineColor,\n LineColors,\n LineRenderType,\n LineType,\n type WorkflowLineRenderContributionFactory,\n} from './typings/workflow-line';\nimport {\n type WorkflowContentChangeEvent,\n WorkflowContentChangeType,\n type WorkflowEdgeJSON,\n} from './typings';\nimport { WorkflowHoverService, WorkflowSelectService } from './service';\nimport { WorkflowNodeLinesData } from './entity-datas/workflow-node-lines-data';\nimport { WorkflowLineRenderData } from './entity-datas';\nimport {\n LINE_HOVER_DISTANCE,\n WorkflowLineEntity,\n type WorkflowLinePortInfo,\n type WorkflowNodeEntity,\n WorkflowPortEntity,\n} from './entities';\n\n/**\n * 线条管理\n */\n@injectable()\nexport class WorkflowLinesManager {\n protected document: WorkflowDocument;\n\n protected toDispose = new DisposableCollection();\n // 线条类型\n\n protected _lineType: LineRenderType = LineType.BEZIER;\n\n protected onAvailableLinesChangeEmitter = new Emitter<WorkflowContentChangeEvent>();\n\n protected onForceUpdateEmitter = new Emitter<void>();\n\n @inject(WorkflowHoverService) hoverService: WorkflowHoverService;\n\n @inject(WorkflowSelectService) selectService: WorkflowSelectService;\n\n @inject(EntityManager) protected readonly entityManager: EntityManager;\n\n @inject(WorkflowDocumentOptions)\n readonly options: WorkflowDocumentOptions;\n\n /**\n * 有效的线条被添加或者删除时候触发,未连上的线条不算\n */\n readonly onAvailableLinesChange = this.onAvailableLinesChangeEmitter.event;\n\n /**\n * 强制渲染 lines\n */\n readonly onForceUpdate = this.onForceUpdateEmitter.event;\n\n readonly contributionFactories: WorkflowLineRenderContributionFactory[] = [];\n\n init(doc: WorkflowDocument): void {\n this.document = doc;\n }\n\n forceUpdate() {\n this.onForceUpdateEmitter.fire();\n }\n\n get lineType() {\n return this._lineType;\n }\n\n get lineColor(): LineColor {\n const color: LineColor = {\n default: LineColors.DEFUALT,\n error: LineColors.ERROR,\n hidden: LineColors.HIDDEN,\n drawing: LineColors.DRAWING,\n hovered: LineColors.HOVER,\n selected: LineColors.SELECTED,\n flowing: LineColors.FLOWING,\n };\n if (this.options.lineColor) {\n Object.assign(color, this.options.lineColor);\n }\n return color;\n }\n\n switchLineType(newType?: LineRenderType): LineRenderType {\n if (newType === undefined) {\n if (this._lineType === LineType.BEZIER) {\n newType = LineType.LINE_CHART;\n } else {\n newType = LineType.BEZIER;\n }\n }\n if (newType !== this._lineType) {\n this._lineType = newType;\n // 更新线条数据\n this.getAllLines().forEach((line) => {\n line.getData(WorkflowLineRenderData).update();\n });\n window.requestAnimationFrame(() => {\n // 触发线条重渲染\n this.entityManager.fireEntityChanged(WorkflowLineEntity.type);\n });\n }\n return this._lineType;\n }\n\n getAllLines(): WorkflowLineEntity[] {\n return this.entityManager.getEntities(WorkflowLineEntity);\n }\n\n hasLine(portInfo: WorkflowLinePortInfo): boolean {\n return !!this.entityManager.getEntityById<WorkflowLineEntity>(\n WorkflowLineEntity.portInfoToLineId(portInfo)\n );\n }\n\n getLine(portInfo: WorkflowLinePortInfo): WorkflowLineEntity | undefined {\n return this.entityManager.getEntityById<WorkflowLineEntity>(\n WorkflowLineEntity.portInfoToLineId(portInfo)\n );\n }\n\n replaceLine(\n oldPortInfo: WorkflowLinePortInfo,\n newPortInfo: WorkflowLinePortInfo\n ): WorkflowLineEntity {\n const oldLine = this.getLine(oldPortInfo);\n if (oldLine) {\n oldLine.dispose();\n }\n return this.createLine(newPortInfo)!;\n }\n\n createLine(\n options: {\n drawingTo?: IPoint; // 无连接的线条\n key?: string; // 自定义 key\n } & WorkflowLinePortInfo\n ): WorkflowLineEntity | undefined {\n const { from, to, drawingTo, fromPort, toPort } = options;\n const available = Boolean(from && to);\n const key = options.key || WorkflowLineEntity.portInfoToLineId(options);\n let line = this.entityManager.getEntityById<WorkflowLineEntity>(key)!;\n if (line) {\n // 如果之前有线条,则先把颜色去掉\n line.highlightColor = '';\n line.validate();\n return line;\n }\n\n const fromNode = this.entityManager\n .getEntityById<WorkflowNodeEntity>(from)\n ?.getData<WorkflowNodeLinesData>(WorkflowNodeLinesData);\n const toNode = to\n ? this.entityManager\n .getEntityById<WorkflowNodeEntity>(to)!\n .getData<WorkflowNodeLinesData>(WorkflowNodeLinesData)!\n : undefined;\n\n if (!fromNode) {\n // 非法情况\n return;\n }\n\n this.isDrawing = Boolean(drawingTo);\n line = this.entityManager.createEntity<WorkflowLineEntity>(WorkflowLineEntity, {\n id: key,\n document: this.document,\n linesManager: this,\n from,\n fromPort,\n toPort,\n to,\n drawingTo,\n });\n\n this.registerData(line);\n\n fromNode.addLine(line);\n toNode?.addLine(line);\n line.onDispose(() => {\n if (drawingTo) {\n this.isDrawing = false;\n }\n fromNode.removeLine(line);\n toNode?.removeLine(line);\n // 连线销毁时检验 连线错误态 & 端口错误态\n line.validate();\n });\n line.onDispose(() => {\n if (available) {\n this.onAvailableLinesChangeEmitter.fire({\n type: WorkflowContentChangeType.DELETE_LINE,\n toJSON: () => line.toJSON(),\n entity: line,\n });\n }\n });\n // 是否为有效的线条\n if (available) {\n this.onAvailableLinesChangeEmitter.fire({\n type: WorkflowContentChangeType.ADD_LINE,\n toJSON: () => line.toJSON(),\n entity: line,\n });\n }\n // 创建时检验 连线错误态 & 端口错误态\n line.validate();\n return line;\n }\n\n /**\n * 获取线条中距离鼠标位置最近的线条和距离\n * @param mousePos 鼠标位置\n * @param minDistance 最小检测距离\n * @returns 距离鼠标位置最近的线条 以及距离\n */\n getCloseInLineFromMousePos(\n mousePos: IPoint,\n minDistance: number = LINE_HOVER_DISTANCE\n ): WorkflowLineEntity | undefined {\n let targetLine: WorkflowLineEntity | undefined, targetLineDist: number | undefined;\n this.getAllLines().forEach((line) => {\n const dist = line.getHoverDist(mousePos);\n\n if (dist <= minDistance && (!targetLineDist || targetLineDist >= dist)) {\n targetLineDist = dist;\n targetLine = line;\n }\n });\n return targetLine;\n }\n\n /**\n * 是否在调整线条\n */\n isDrawing = false;\n\n dispose(): void {\n this.toDispose.dispose();\n }\n\n get disposed(): boolean {\n return this.toDispose.disposed;\n }\n\n isErrorLine(fromPort: WorkflowPortEntity, toPort?: WorkflowPortEntity) {\n if (this.options.isErrorLine) {\n return this.options.isErrorLine(fromPort, toPort, this);\n }\n\n return false;\n }\n\n isReverseLine(line: WorkflowLineEntity): boolean {\n if (this.options.isReverseLine) {\n return this.options.isReverseLine(line);\n }\n\n return false;\n }\n\n isHideArrowLine(line: WorkflowLineEntity): boolean {\n if (this.options.isHideArrowLine) {\n return this.options.isHideArrowLine(line);\n }\n\n return false;\n }\n\n isFlowingLine(line: WorkflowLineEntity): boolean {\n if (this.options.isFlowingLine) {\n return this.options.isFlowingLine(line);\n }\n\n return false;\n }\n\n isDisabledLine(line: WorkflowLineEntity): boolean {\n if (this.options.isDisabledLine) {\n return this.options.isDisabledLine(line);\n }\n return false;\n }\n\n isVerticalLine(line: WorkflowLineEntity): boolean {\n if (this.options.isVerticalLine) {\n return this.options.isVerticalLine(line);\n }\n\n return false;\n }\n\n setLineRenderType(line: WorkflowLineEntity): LineRenderType | undefined {\n if (this.options.setLineRenderType) {\n return this.options.setLineRenderType(line);\n }\n return undefined;\n }\n\n setLineClassName(line: WorkflowLineEntity): string | undefined {\n if (this.options.setLineClassName) {\n return this.options.setLineClassName(line);\n }\n return undefined;\n }\n\n getLineColor(line: WorkflowLineEntity): string | undefined {\n // 隐藏的优先级比 hasError 高\n if (line.isHidden) {\n return this.lineColor.hidden;\n }\n if (line.hasError) {\n return this.lineColor.error;\n }\n if (line.highlightColor) {\n return line.highlightColor;\n }\n if (line.drawingTo) {\n return this.lineColor.drawing;\n }\n if (this.hoverService.isHovered(line.id)) {\n return this.lineColor.hovered;\n }\n if (this.selectService.isSelected(line.id)) {\n return this.lineColor.selected;\n }\n // 检查是否为流动线条\n if (this.isFlowingLine(line)) {\n return this.lineColor.flowing;\n }\n return this.lineColor.default;\n }\n\n canAddLine(fromPort: WorkflowPortEntity, toPort: WorkflowPortEntity, silent?: boolean): boolean {\n if (\n fromPort === toPort ||\n fromPort.node === toPort.node ||\n fromPort.portType !== 'output' ||\n toPort.portType !== 'input' ||\n toPort.disabled\n ) {\n return false;\n }\n if (this.options.canAddLine) {\n return this.options.canAddLine(fromPort, toPort, this, silent);\n }\n // 默认不能连接自己\n return fromPort.node !== toPort.node;\n }\n\n toJSON(): WorkflowEdgeJSON[] {\n return this.getAllLines()\n .filter((l) => !l.isDrawing)\n .map((l) => l.toJSON());\n }\n\n getPortById(portId: string): WorkflowPortEntity | undefined {\n return this.entityManager.getEntityById<WorkflowPortEntity>(portId);\n }\n\n canRemove(\n line: WorkflowLineEntity,\n newLineInfo?: Required<WorkflowLinePortInfo>,\n silent?: boolean\n ): boolean {\n if (\n this.options &&\n this.options.canDeleteLine &&\n !this.options.canDeleteLine(line, newLineInfo, silent)\n ) {\n return false;\n }\n return true;\n }\n\n canReset(\n fromPort: WorkflowPortEntity,\n oldToPort: WorkflowPortEntity,\n newToPort: WorkflowPortEntity\n ): boolean {\n if (\n this.options &&\n this.options.canResetLine &&\n !this.options.canResetLine(fromPort, oldToPort, newToPort, this)\n ) {\n return false;\n }\n return true;\n }\n\n /**\n * 根据鼠标位置找到 port\n * @param pos\n */\n getPortFromMousePos(pos: IPoint): WorkflowPortEntity | undefined {\n const allPorts = this.entityManager\n .getEntities<WorkflowPortEntity>(WorkflowPortEntity)\n .filter((port) => port.node.flowNodeType !== 'root');\n const targetPort = allPorts.find((port) => port.isHovered(pos.x, pos.y));\n if (targetPort) {\n // 后创建的要先校验\n const targetNode = this.document\n .getAllNodes()\n .slice()\n .reverse()\n .filter((node) => targetPort.node?.parent?.id !== node.id)\n .find((node) => node.getData(TransformData)!.contains(pos.x, pos.y));\n // 点位可能会被节点覆盖\n if (targetNode && targetNode !== targetPort.node) {\n return;\n }\n }\n return targetPort;\n }\n\n /**\n * 根据鼠标位置找到 node\n * @param pos - 鼠标位置\n */\n getNodeFromMousePos(pos: IPoint): WorkflowNodeEntity | undefined {\n const allNodes = this.document\n .getAllNodes()\n .sort((a, b) => this.getNodeIndex(a) - this.getNodeIndex(b));\n // 先挑选出 bounds 区域符合的 node\n const containNodes: WorkflowNodeEntity[] = [];\n const { selection } = this.selectService;\n const zoom =\n this.entityManager.getEntity<PlaygroundConfigEntity>(PlaygroundConfigEntity)?.config?.zoom ||\n 1;\n allNodes.forEach((node) => {\n const { bounds } = node.getData<FlowNodeTransformData>(FlowNodeTransformData);\n // 交互要求,节点边缘 4px 的时候就生效连线逻辑\n if (\n bounds\n .clone()\n .pad(4 / zoom)\n .contains(pos.x, pos.y)\n ) {\n containNodes.push(node);\n }\n });\n // 当有元素被选中的时候选中元素在顶层\n if (selection?.length) {\n const filteredNodes = containNodes.filter((node) =>\n selection.some((_node) => node.id === _node.id)\n );\n if (filteredNodes?.length) {\n return last(filteredNodes);\n }\n }\n // 默认取最顶层的\n return last(containNodes);\n }\n\n registerContribution(factory: WorkflowLineRenderContributionFactory): this {\n this.contributionFactories.push(factory);\n return this;\n }\n\n private registerData(line: WorkflowLineEntity) {\n line.addData(WorkflowLineRenderData);\n }\n\n private getNodeIndex(node: WorkflowNodeEntity): number {\n const nodeRenderData = node.getData(FlowNodeRenderData);\n return nodeRenderData.stackIndex;\n }\n}\n","import { FlowNodeErrorData } from '@flowgram.ai/form-core';\nimport { FlowDocumentOptions, FlowNodeTransformData } from '@flowgram.ai/document';\nimport { TransformData } from '@flowgram.ai/core';\n\nimport { type WorkflowLinesManager } from './workflow-lines-manager';\nimport { initFormDataFromJSON, toFormJSON } from './utils/flow-node-form-data';\nimport {\n LineColor,\n LineRenderType,\n onDragLineEndParams,\n WorkflowNodeJSON,\n WorkflowNodeMeta,\n} from './typings';\nimport {\n type WorkflowLineEntity,\n type WorkflowLinePortInfo,\n type WorkflowNodeEntity,\n type WorkflowPortEntity,\n} from './entities';\n\nexport const WorkflowDocumentOptions = Symbol('WorkflowDocumentOptions');\n\n/**\n * 线条配置\n */\nexport interface WorkflowDocumentOptions extends FlowDocumentOptions {\n cursors?: {\n grab?: string;\n grabbing?: string;\n };\n /** 线条颜色 */\n lineColor?: Partial<LineColor>;\n /** 是否显示错误线条 */\n isErrorLine?: (\n fromPort: WorkflowPortEntity,\n toPort: WorkflowPortEntity | undefined,\n lines: WorkflowLinesManager\n ) => boolean;\n /** 是否错误端口 */\n isErrorPort?: (port: WorkflowPortEntity) => boolean;\n /** 是否禁用端口 */\n isDisabledPort?: (port: WorkflowPortEntity) => boolean;\n /** 是否反转线条箭头 */\n isReverseLine?: (line: WorkflowLineEntity) => boolean;\n /** 是否隐藏线条箭头 */\n isHideArrowLine?: (line: WorkflowLineEntity) => boolean;\n /** 是否流动线条 */\n isFlowingLine?: (line: WorkflowLineEntity) => boolean;\n /** 是否禁用线条 */\n isDisabledLine?: (line: WorkflowLineEntity) => boolean;\n /** 是否竖向线条 */\n isVerticalLine?: (line: WorkflowLineEntity) => boolean;\n /** 拖拽线条结束 */\n onDragLineEnd?: (params: onDragLineEndParams) => Promise<void>;\n /** 获取线条渲染器 */\n setLineRenderType?: (line: WorkflowLineEntity) => LineRenderType | undefined;\n /** 设置线条样式 */\n setLineClassName?: (line: WorkflowLineEntity) => string | undefined;\n /** 能否添加线条 */\n canAddLine?: (\n fromPort: WorkflowPortEntity,\n toPort: WorkflowPortEntity,\n lines: WorkflowLinesManager,\n silent?: boolean\n ) => boolean;\n /** 能否删除节点 */\n canDeleteNode?: (node: WorkflowNodeEntity, silent?: boolean) => boolean;\n /** 能否删除线条 */\n canDeleteLine?: (\n line: WorkflowLineEntity,\n newLineInfo?: Required<WorkflowLinePortInfo>,\n silent?: boolean\n ) => boolean;\n /**\n * @param fromPort - 开始点\n * @param oldToPort - 旧的连接点\n * @param newToPort - 新的连接点\n * @param lines - 线条管理器\n */\n canResetLine?: (\n fromPort: WorkflowPortEntity,\n oldToPort: WorkflowPortEntity,\n newToPort: WorkflowPortEntity,\n lines: WorkflowLinesManager\n ) => boolean;\n}\n\nexport const WorkflowDocumentOptionsDefault: WorkflowDocumentOptions = {\n cursors: {\n grab: 'url(\"data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjAiIGhlaWdodD0iMjEiIHZpZXdCb3g9IjAgMCAyMCAyMSIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik0xMC40ODczIDIuNjIzNzhDOS45MDczMSAyLjYyMzc4IDkuNDM3MTMgMy4wOTM5NiA5LjQzNzEzIDMuNjczOTZWNS4xNDM3NkM5LjM5NDI4IDQuNDAyNzQgOC43Nzk3OCAzLjgxNTA0IDguMDI4MDIgMy44MTUwNEM3LjI0ODQ4IDMuODE1MDQgNi42MTY1MyA0LjQ0Njk5IDYuNjE2NTMgNS4yMjY1M1YxMS44Mjg5TDUuNjc0MTggMTEuMDA0OUM1LjE1NDg3IDEwLjU1MDkgNC40MDk1IDEwLjQ2MzYgMy43OTkzOCAxMC43ODU1TDMuNjk2OTQgMTAuODM5NkMzLjA2MjE3IDExLjE3NDUgMi45MjI2IDEyLjAyMjggMy40MTY2MiAxMi41NDM0TDcuMzM5NTkgMTYuNjc3NVYxNy4zMjU5QzcuMzM5NTkgMTcuNzg2MiA3LjcxMjY5IDE4LjE1OTMgOC4xNzI5MiAxOC4xNTkzSDEzLjgwODRDMTQuMjY4NyAxOC4xNTkzIDE0LjY0MTcgMTcuNzg2MiAxNC42NDE3IDE3LjMyNTlWMTYuNzkzNUMxNS44MDk0IDE1LjY0ODUgMTYuNDY3MyAxNC4wODE5IDE2LjQ2NzMgMTIuNDQ2NVYxMS40OTY3TDE2LjQ2NzEgNi42MzY4NUMxNi40NjcxIDUuOTU2MyAxNS45MTU0IDUuNDA0NjEgMTUuMjM0OCA1LjQwNDYxQzE0LjU1NDMgNS40MDQ2MSAxNC4wMDI2IDUuOTU2MyAxNC4wMDI2IDYuNjM2ODVMMTQuMDAyMSA1LjA0NzI4QzE0LjAwMjEgNC4zNjY3MyAxMy40NTA0IDMuODE1MDQgMTIuNzY5OCAzLjgxNTA0QzEyLjA4OTMgMy44MTUwNCAxMS41Mzc2IDQuMzY2NzMgMTEuNTM3NiA1LjA0NzI4TDExLjUzNzUgMy42NzM5NUMxMS41Mzc1IDMuMDkzOTYgMTEuMDY3MyAyLjYyMzc4IDEwLjQ4NzMgMi42MjM3OFoiIGZpbGw9IndoaXRlIi8+CjxwYXRoIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBkPSJNMTAuNDg3NCAxLjM3NDAyQzExLjM2MTIgMS4zNzQwMiAxMi4xMjExIDEuODYxMTggMTIuNTEwNSAyLjU3ODY4QzEyLjU5NTggMi41Njk4MyAxMi42ODIzIDIuNTY1MjggMTIuNzcgMi41NjUyOEMxMy44Mjc4IDIuNTY1MjggMTQuNzMxMSAzLjIyNzAxIDE1LjA4ODUgNC4xNTkxMUMxNS4xMzcgNC4xNTYyOSAxNS4xODU4IDQuMTU0ODYgMTUuMjM1IDQuMTU0ODZDMTYuNjA1OSA0LjE1NDg2IDE3LjcxNzIgNS4yNjYxOSAxNy43MTcyIDYuNjM3MDlMMTcuNzE3NCAxMi40NDY3QzE3LjcxNzQgMTQuMjM1NSAxNy4wNjQ0IDE1Ljk1NTkgMTUuODkxOSAxNy4yOTA0VjE3LjMyNjJDMTUuODkxOSAxOC40NzY4IDE0Ljk1OTEgMTkuNDA5NSAxMy44MDg1IDE5LjQwOTVIOC4xNzMwNkM3LjAyMjQ3IDE5LjQwOTUgNi4wODk3MyAxOC40NzY4IDYuMDg5NzMgMTcuMzI2MlYxNy4xNzY0TDIuNTEwMDMgMTMuNDA0MUMxLjQ0NTk5IDEyLjI4MjggMS43NDY2IDEwLjQ1NTUgMy4xMTM3OSA5LjczNDI0TDMuMjE2MjQgOS42ODAxOUMzLjg5MTY4IDkuMzIzODMgNC42NjE4NSA5LjI1NDAxIDUuMzY2NjYgOS40NTE5OFY1LjIyNjc4QzUuMzY2NjYgMy43NTY4NyA2LjU1ODI2IDIuNTY1MjggOC4wMjgxNiAyLjU2NTI4QzguMTcyOTMgMi41NjUyOCA4LjMxNDk5IDIuNTc2ODQgOC40NTM0NyAyLjU5OTA3QzguODM5NDMgMS44NzA0MiA5LjYwNTQ2IDEuMzc0MDIgMTAuNDg3NCAxLjM3NDAyWk0xMi40NDc2IDMuODU3ODdWOS40NzY0NkMxMi40NDc2IDkuNzI4NTIgMTIuMjQzMyA5LjkzMjg1IDExLjk5MTMgOS45MzI4NUMxMS43MzkyIDkuOTMyODUgMTEuNTM0OSA5LjcyODUyIDExLjUzNDkgOS40NzY0NlYzLjc5NjU1QzExLjUzNDkgMy43Nzk1NiAxMS41MzU4IDMuNzYyNzcgMTEuNTM3NiAzLjc0NjI2VjMuNjc0MkMxMS41Mzc2IDMuNDMyODIgMTEuNDU2MiAzLjIxMDQ2IDExLjMxOTMgMy4wMzMwOUMxMS4xMjcyIDIuNzg0MjggMTAuODI2MSAyLjYyNDAyIDEwLjQ4NzQgMi42MjQwMkMxMC4xMjM4IDIuNjI0MDIgOS44MDMzMiAyLjgwODg2IDkuNjE0ODMgMy4wODk3QzkuNTAyNjkgMy4yNTY3OSA5LjQzNzI2IDMuNDU3ODUgOS40MzcyNiAzLjY3NDJWMy43ODU3M0M5LjQzNzM1IDMuNzg5MzMgOS40MzczOSAzLjc5Mjk0IDkuNDM3MzkgMy43OTY1NVY5LjkwMTdDOS40MzczOSAxMC4xNTM3IDkuMjMzMDYgMTAuMzU4MSA4Ljk4MTAxIDEwLjM1ODFDOC43Mjg5NSAxMC4zNTgxIDguNTI0NjIgMTAuMTUzNyA4LjUyNDYyIDkuOTAxN1YzLjkwNTA3QzguNDE3NzMgMy44NjQ5IDguMzA0NjggMy44MzczMiA4LjE4NzI2IDMuODI0MTVDOC4xMzUwNCAzLjgxODI5IDguMDgxOTUgMy44MTUyOCA4LjAyODE2IDMuODE1MjhDNy4yNDg2MSAzLjgxNTI4IDYuNjE2NjYgNC40NDcyMyA2LjYxNjY2IDUuMjI2NzhWMTEuODI5Mkw1LjY3NDMxIDExLjAwNTJDNS41Nzg2OCAxMC45MjE2IDUuNDc1MzcgMTAuODUwNCA1LjM2NjY2IDEwLjc5MTlDNC44ODUwNiAxMC41MzI5IDQuMjk3MjggMTAuNTIzMSAzLjc5OTUyIDEwLjc4NThMMy42OTcwNyAxMC44Mzk4QzMuMDYyMzEgMTEuMTc0NyAyLjkyMjczIDEyLjAyMzEgMy40MTY3NSAxMi41NDM3TDcuMzM5NzMgMTYuNjc3N1YxNy4zMjYyQzcuMzM5NzMgMTcuNzg2NCA3LjcxMjgyIDE4LjE1OTUgOC4xNzMwNiAxOC4xNTk1SDEzLjgwODVDMTQuMjY4OCAxOC4xNTk1IDE0LjY0MTkgMTcuNzg2NCAxNC42NDE5IDE3LjMyNjJWMTYuNzkzOEMxNS43Mzc5IDE1LjcxOSAxNi4zODQ3IDE0LjI3MjggMTYuNDYgMTIuNzQ3QzE2LjQ2NDEgMTIuNjY0MSAxNi40NjY1IDEyLjU4MDkgMTYuNDY3MiAxMi40OTc1TDE2LjQ2NzQgMTIuNDQ2N0wxNi40NjcyIDYuNjM3MDlDMTYuNDY3MiA1Ljk2MjMgMTUuOTI0OCA1LjQxNDE5IDE1LjI1MjIgNS40MDQ5N0wxNS4yMzUgNS40MDQ4NkMxNS4xMjQ2IDUuNDA0ODYgMTUuMDE3NyA1LjQxOTM2IDE0LjkxNTkgNS40NDY1NlY5LjYwMjI2QzE0LjkxNTkgOS44NTQzMSAxNC43MTE2IDEwLjA1ODYgMTQuNDU5NSAxMC4wNTg2QzE0LjIwNzUgMTAuMDU4NiAxNC4wMDMxIDkuODU0MzEgMTQuMDAzMSA5LjYwMjI2VjYuNjA1MTRDMTQuMDAyOSA2LjYxNTc2IDE0LjAwMjcgNi42MjY0MSAxNC4wMDI3IDYuNjM3MDlWOS4yNzcwNUwxNC4wMDIyIDUuMDQ3NTJDMTQuMDAyMiA0Ljg2OTEzIDEzLjk2NDMgNC42OTk2IDEzLjg5NjEgNC41NDY1M0MxMy43MDY0IDQuMTIwNzIgMTMuMjgyMiAzLjgyMjM1IDEyLjc4NzYgMy44MTU0MUwxMi43NyAzLjgxNTI4QzEyLjY1ODQgMy44MTUyOCAxMi41NTA0IDMuODMwMSAxMi40NDc2IDMuODU3ODdaIiBmaWxsPSIjMUQxQzIzIi8+Cjwvc3ZnPg==\"), auto',\n grabbing:\n 'url(\"data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjAiIGhlaWdodD0iMjEiIHZpZXdCb3g9IjAgMCAyMCAyMSIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik02LjYxODE3IDUuNTk4NzVDNi42MTgxNyA0LjgxOTIgNy4yNTAxMiA0LjE4NzI2IDguMDI5NjcgNC4xODcyNkM4Ljc3ODczIDQuMTg3MjYgOS4zOTE1MiA0Ljc3MDc1IDkuNDM4MjkgNS41MDgwMUM5LjQ1OTkyIDQuOTQ3MSA5LjkyMTQ3IDQuNDk5MDIgMTAuNDg3NyA0LjQ5OTAyQzExLjA2NzcgNC40OTkwMiAxMS41Mzc4IDQuOTY5MiAxMS41Mzc4IDUuNTQ5MTlWOC43NjI0NkwxMS41Mzc5IDYuNzExNUMxMS41Mzc5IDYuMDMwOTUgMTIuMDg5NiA1LjQ3OTI2IDEyLjc3MDIgNS40NzkyNkMxMy40NTA3IDUuNDc5MjYgMTQuMDAyNCA2LjAzMDk1IDE0LjAwMjQgNi43MTE1TDE0LjAwMjQgOC43NjI0NkwxNC4wMDI5IDguMDE5ODNDMTQuMDAyOSA3LjMzOTI5IDE0LjU1NDYgNi43ODc1OSAxNS4yMzUyIDYuNzg3NTlDMTUuOTE1NyA2Ljc4NzU5IDE2LjQ2NzQgNy4zMzkyOCAxNi40Njc0IDguMDE5ODNWMTEuNDk3TDE2LjQ2NzUgMTIuNDQ2N0MxNi40Njc1IDE0LjA4MjEgMTUuODA5NiAxNS42NDg3IDE0LjY0MiAxNi43OTM4VjE3LjMyNjJDMTQuNjQyIDE3Ljc4NjQgMTQuMjY4OSAxOC4xNTk1IDEzLjgwODcgMTguMTU5NUg4LjE3MzE3QzcuNzEyOTMgMTguMTU5NSA3LjMzOTg0IDE3Ljc4NjQgNy4zMzk4NCAxNy4zMjYyVjE1Ljk0MjRMNS4zNDU2MiAxNC43NTM0QzQuNTg5MjQgMTQuMzAyNCA0LjEyNTkxIDEzLjQ4NjcgNC4xMjU4OSAxMi42MDYxTDQuMTI1ODMgOS4yODM4M0M0LjEyNTgyIDguOTU0MjcgNC4zMjAwMyA4LjY1NTY2IDQuNjIxMjkgOC41MjIwNUw2LjYxODE3IDcuNjM2MzRWNS41OTg3NVoiIGZpbGw9IndoaXRlIi8+CjxwYXRoIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBkPSJNMTAuNDg3OCAzLjI0OTAyQzExLjI3OTYgMy4yNDkwMiAxMS45Nzc4IDMuNjQ5MDIgMTIuMzkxNyA0LjI1Nzk2QzEyLjUxNTEgNC4yMzkwNiAxMi42NDE2IDQuMjI5MjYgMTIuNzcwMyA0LjIyOTI2QzEzLjcyMjQgNC4yMjkyNiAxNC41NDkzIDQuNzY1MzEgMTQuOTY1NyA1LjU1MjA3QzE1LjA1NDMgNS41NDI1IDE1LjE0NDIgNS41Mzc1OSAxNS4yMzUzIDUuNTM3NTlDMTYuNjA2MiA1LjUzNzU5IDE3LjcxNzYgNi42NDg5MyAxNy43MTc2IDguMDE5ODNMMTcuNzE3NyAxMi40NDY3QzE3LjcxNzcgMTQuMjM1NSAxNy4wNjQ3IDE1Ljk1NTkgMTUuODkyMSAxNy4yOTA0VjE3LjMyNjJDMTUuODkyMSAxOC40NzY4IDE0Ljk1OTQgMTkuNDA5NSAxMy44MDg4IDE5LjQwOTVIOC4xNzMzMkM3LjAyMjczIDE5LjQwOTUgNi4wODk5OCAxOC40NzY4IDYuMDg5OTggMTcuMzI2MlYxNi42NTI0TDQuNzA1NjMgMTUuODI3QzMuNTcxMDYgMTUuMTUwNSAyLjg3NjA3IDEzLjkyNzEgMi44NzYwNCAxMi42MDYxTDIuODc1OTggOS4yODM4NUMyLjg3NTk2IDguNDU5OTYgMy4zNjE0OSA3LjcxMzQ1IDQuMTE0NjIgNy4zNzk0TDUuMzY4MzIgNi44MjMzM1Y1LjU5ODc1QzUuMzY4MzIgNC4xMjg4NSA2LjU1OTkxIDIuOTM3MjYgOC4wMjk4MiAyLjkzNzI2QzguNjA4MzEgMi45MzcyNiA5LjE0MzU1IDMuMTIxNyA5LjU4MDA1IDMuNDM1MDVDOS44NTg1MyAzLjMxNTMyIDEwLjE2NTQgMy4yNDkwMiAxMC40ODc4IDMuMjQ5MDJaTTEyLjQ0NzkgNS41MjE4NlY5LjQ3NTU3QzEyLjQ0NzkgOS43Mjc2MiAxMi4yNDM2IDkuOTMxOTUgMTEuOTkxNiA5LjkzMTk1QzExLjc1NjggOS45MzE5NSAxMS41NjM0IDkuNzU0NjUgMTEuNTM4IDkuNTI2NjNDMTEuNTM2MSA5LjUwOTg3IDExLjUzNTIgOS40OTI4MyAxMS41MzUyIDkuNDc1NTdWNS40NzE1OEMxMS41MTU0IDUuMjAwODMgMTEuMzkzIDQuOTU4NTggMTEuMjA2NiA0Ljc4MzU4QzExLjAxODggNC42MDcxMSAxMC43NjU5IDQuNDk5MDIgMTAuNDg3OCA0LjQ5OTAyQzEwLjQ3NjYgNC40OTkwMiAxMC40NjU0IDQuNDk5MTkgMTAuNDU0MiA0LjQ5OTU0QzkuOTAzNDcgNC41MTY4NCA5LjQ1OTY0IDQuOTU4MjQgOS40Mzg0NCA1LjUwODAxQzkuNDM4MiA1LjUwNDMgOS40Mzc5NSA1LjUwMDU4IDkuNDM3NjkgNS40OTY4OFY5LjkwMjQzQzkuNDM3NjkgMTAuMTU0NSA5LjIzMzM2IDEwLjM1ODggOC45ODEzMSAxMC4zNTg4QzguNzI5MjUgMTAuMzU4OCA4LjUyNDkyIDEwLjE1NDUgOC41MjQ5MiA5LjkwMjQzVjQuMjc2NTNDOC4zNzA4NiA0LjIxODgyIDguMjA0MDIgNC4xODcyNiA4LjAyOTgyIDQuMTg3MjZDNy4yNTAyNyA0LjE4NzI2IDYuNjE4MzIgNC44MTkyIDYuNjE4MzIgNS41OTg3NUw2LjYxODI3IDkuOTc1OTlDNi42MTgyNyAxMC4yMjggNi40MTM5NCAxMC40MzI0IDYuMTYxODkgMTAuNDMyNEM1LjkwOTgzIDEwLjQzMjQgNS43MDU1IDEwLjIyOCA1LjcwNTUgOS45NzU5OVY4LjA0MTIyTDQuNjIxNDQgOC41MjIwNUM0LjMyMDE4IDguNjU1NjYgNC4xMjU5NyA4Ljk1NDI3IDQuMTI1OTggOS4yODM4M0w0LjEyNjA0IDEyLjYwNjFDNC4xMjYwNiAxMy40ODY3IDQuNTg5MzkgMTQuMzAyNCA1LjM0NTc2IDE0Ljc1MzRMNy4zMzk5OCAxNS45NDI0VjE3LjMyNjJDNy4zMzk5OCAxNy43ODY0IDcuNzEzMDggMTguMTU5NSA4LjE3MzMyIDE4LjE1OTVIMTMuODA4OEMxNC4yNjkgMTguMTU5NSAxNC42NDIxIDE3Ljc4NjQgMTQuNjQyMSAxNy4zMjYyVjE2Ljc5MzhDMTUuNzM4MSAxNS43MTkgMTYuMzg1IDE0LjI3MjggMTYuNDYwMyAxMi43NDdDMTYuNDY0NiAxMi42NiAxNi40NjcgMTIuNTcyOCAxNi40Njc2IDEyLjQ4NTRMMTYuNDY3NyAxMi40NDY3TDE2LjQ2NzYgOC4wMTk4M0MxNi40Njc2IDcuMzQ1MDQgMTUuOTI1MiA2Ljc5NjkzIDE1LjI1MjUgNi43ODc3MUwxNS4yMzUzIDYuNzg3NTlDMTUuMTI1IDYuNzg3NTkgMTUuMDE4IDYuODAyMSAxNC45MTYyIDYuODI5MzFWOS42MDEzNkMxNC45MTYyIDkuODUzNDIgMTQuNzExOSAxMC4wNTc3IDE0LjQ1OTggMTAuMDU3N0MxNC4yMDc4IDEwLjA1NzcgMTQuMDAzNCA5Ljg1MzQxIDE0LjAwMzQgOS42MDEzNlY3Ljk4OTg1QzE0LjAwMzIgNy45OTk4MiAxNC4wMDMxIDguMDA5ODEgMTQuMDAzMSA4LjAxOTgzTDE0LjAwMzQgOS42MDEzNkwxNC4wMDI1IDYuNzExNUMxNC4wMDI1IDYuNDQ5NzQgMTMuOTIwOSA2LjIwNzA1IDEzLjc4MTggNi4wMDc0OEMxMy41NjIgNS42OTI0MiAxMy4xOTg5IDUuNDg0ODMgMTIuNzg3IDUuNDc5MzdMMTIuNzcwMyA1LjQ3OTI2QzEyLjY1ODggNS40NzkyNiAxMi41NTA3IDUuNDk0MDggMTIuNDQ3OSA1LjUyMTg2WiIgZmlsbD0iIzFEMUMyMyIvPgo8L3N2Zz4=\"), auto',\n },\n\n fromNodeJSON(node, json, isFirstCreate) {\n initFormDataFromJSON(node, json, isFirstCreate);\n return;\n },\n toNodeJSON(node: WorkflowNodeEntity): WorkflowNodeJSON {\n const nodeError = node.getData<FlowNodeErrorData>(FlowNodeErrorData)?.getError();\n // 如果节点有错误,这里抛出错误,避免后面的代码执行异常\n if (nodeError) {\n throw nodeError;\n }\n const transform = node.getData<TransformData>(TransformData)!;\n\n let formJSON = toFormJSON(node);\n const metaData: Record<string, unknown> = {};\n\n // 持久化子画布位置\n const nodeMeta = node.getNodeMeta<WorkflowNodeMeta>();\n const subCanvas = nodeMeta.subCanvas?.(node);\n if (subCanvas?.isCanvas === false) {\n const canvasNodeTransform =\n subCanvas.canvasNode.getData<FlowNodeTransformData>(FlowNodeTransformData);\n const { x, y } = canvasNodeTransform.transform.position;\n metaData.canvasPosition = { x, y };\n }\n\n const json: WorkflowNodeJSON = {\n id: node.id,\n type: node.flowNodeType,\n meta: {\n position: { x: transform.position.x, y: transform.position.y },\n ...metaData,\n },\n data: formJSON,\n };\n return json;\n },\n};\n","import { FlowNodeFormData } from '@flowgram.ai/form-core';\nimport { FlowNodeEntity, FlowNodeJSON } from '@flowgram.ai/document';\n\nimport { type WorkflowDocument } from '../workflow-document';\nimport { WorkflowContentChangeType, type WorkflowNodeRegistry } from '../typings';\n\nexport function getFlowNodeFormData(node: FlowNodeEntity) {\n return node.getData(FlowNodeFormData) as FlowNodeFormData;\n}\n\nexport function toFormJSON(node: FlowNodeEntity) {\n const formData = node.getData(FlowNodeFormData) as FlowNodeFormData;\n if (!formData || !(node.getNodeRegistry() as WorkflowNodeRegistry).formMeta) return undefined;\n return formData.toJSON();\n}\n\nexport function initFormDataFromJSON(\n node: FlowNodeEntity,\n json: FlowNodeJSON,\n isFirstCreate: boolean\n) {\n const formData = node.getData(FlowNodeFormData)!;\n const registry = node.getNodeRegistry();\n const { formMeta } = registry;\n\n if (formData && formMeta) {\n if (isFirstCreate) {\n formData.createForm(formMeta, json.data);\n formData.onDataChange(() => {\n (node.document as WorkflowDocument).fireContentChange({\n type: WorkflowContentChangeType.NODE_DATA_CHANGE,\n toJSON: () => formData.toJSON(),\n entity: node,\n });\n });\n } else {\n formData.updateFormValues(json.data);\n }\n }\n}\n","import { type WorkflowLineEntity, type WorkflowNodeEntity } from '../entities';\nimport { type WorkflowNodeJSON } from './workflow-node';\nimport { type WorkflowEdgeJSON } from './workflow-edge';\n\nexport interface WorkflowJSON {\n nodes: WorkflowNodeJSON[];\n edges: WorkflowEdgeJSON[];\n}\n\nexport enum WorkflowContentChangeType {\n /**\n * 添加节点\n */\n ADD_NODE = 'ADD_NODE',\n /**\n * 删除节点\n */\n DELETE_NODE = 'DELETE_NODE',\n /**\n * 移动节点\n */\n MOVE_NODE = 'MOVE_NODE',\n /**\n * 节点数据更新 (表单引擎数据 或者 extInfo 数据)\n */\n NODE_DATA_CHANGE = 'NODE_DATA_CHANGE',\n /**\n * 添加线条\n */\n ADD_LINE = 'ADD_LINE',\n /**\n * 删除线条\n */\n DELETE_LINE = 'DELETE_LINE',\n /**\n * 节点Meta信息变更\n */\n META_CHANGE = 'META_CHANGE',\n}\n\nexport interface WorkflowContentChangeEvent {\n type: WorkflowContentChangeType;\n /**\n * 当前触发的元素的json数据,toJSON 需要主动触发\n */\n toJSON: () => any;\n /*\n * 当前的事件的 entity\n */\n entity: WorkflowNodeEntity | WorkflowLineEntity;\n}\n","import type { Rectangle, IPoint } from '@flowgram.ai/utils';\n\nimport { type WorkflowLineEntity } from '../entities';\n\nexport enum LineType {\n BEZIER, // 贝塞尔曲线\n LINE_CHART, // 折叠线\n}\n\nexport type LineRenderType = LineType | string;\n\nexport interface LinePosition {\n from: IPoint;\n to: IPoint;\n}\n\nexport interface LineColor {\n hidden: string;\n default: string;\n drawing: string;\n hovered: string;\n selected: string;\n error: string;\n flowing: string;\n}\n\nexport enum LineColors {\n HIDDEN = 'var(--g-workflow-line-color-hidden,transparent)', // 隐藏线条\n DEFUALT = 'var(--g-workflow-line-color-default,#4d53e8)',\n DRAWING = 'var(--g-workflow-line-color-drawing, #5DD6E3)', // '#b5bbf8', // '#9197F1',\n HOVER = 'var(--g-workflow-line-color-hover,#37d0ff)',\n SELECTED = 'var(--g-workflow-line-color-selected,#37d0ff)',\n ERROR = 'var(--g-workflow-line-color-error,red)',\n FLOWING = 'var(--g-workflow-line-color-flowing,#4d53e8)', // 流动线条,默认使用主题色\n}\n\nexport interface WorkflowLineRenderContribution {\n entity: WorkflowLineEntity;\n path: string;\n bounds: Rectangle;\n update: (params: { fromPos: IPoint; toPos: IPoint }) => void;\n calcDistance: (pos: IPoint) => number;\n}\n\nexport type WorkflowLineRenderContributionFactory = (new (\n entity: WorkflowLineEntity\n) => WorkflowLineRenderContribution) & {\n type: LineRenderType;\n};\n","import { IPoint, Event } from '@flowgram.ai/utils';\nimport {\n FlowNodeEntity,\n FlowNodeEntityOrId,\n FlowOperationBaseService,\n} from '@flowgram.ai/document';\n\nexport interface NodePostionUpdateEvent {\n node: FlowNodeEntity;\n oldPosition: IPoint;\n newPosition: IPoint;\n}\n\nexport interface WorkflowOperationBaseService extends FlowOperationBaseService {\n /**\n * 节点位置更新事件\n */\n readonly onNodePostionUpdate: Event<NodePostionUpdateEvent>;\n /**\n * 更新节点位置\n * @param nodeOrId\n * @param position\n * @returns\n */\n updateNodePosition(nodeOrId: FlowNodeEntityOrId, position: IPoint): void;\n}\n\nexport const WorkflowOperationBaseService = Symbol('WorkflowOperationBaseService');\n","export * from './workflow-json';\nexport * from './workflow-edge';\nexport * from './workflow-node';\nexport * from './workflow-registry';\nexport * from './workflow-line';\nexport * from './workflow-sub-canvas';\nexport * from './workflow-operation';\nexport * from './workflow-drag';\n\nexport const URLParams = Symbol('');\n\nexport interface URLParams {\n [key: string]: string;\n}\n","import { customAlphabet } from 'nanoid';\nimport { inject, injectable, optional, postConstruct } from 'inversify';\nimport { Emitter, type IPoint } from '@flowgram.ai/utils';\nimport { NodeEngineContext } from '@flowgram.ai/form-core';\nimport {\n AddNodeData,\n FlowDocument,\n FlowNodeBaseType,\n FlowNodeTransformData,\n} from '@flowgram.ai/document';\nimport {\n injectPlaygroundContext,\n PlaygroundConfigEntity,\n PlaygroundContext,\n PositionData,\n TransformData,\n} from '@flowgram.ai/core';\n\nimport { WorkflowLinesManager } from './workflow-lines-manager';\nimport {\n WorkflowDocumentOptions,\n WorkflowDocumentOptionsDefault,\n} from './workflow-document-option';\nimport { getFlowNodeFormData } from './utils/flow-node-form-data';\nimport { delay, fitView, getAntiOverlapPosition } from './utils';\nimport {\n type WorkflowContentChangeEvent,\n WorkflowContentChangeType,\n WorkflowEdgeJSON,\n type WorkflowJSON,\n type WorkflowNodeJSON,\n type WorkflowNodeMeta,\n type WorkflowNodeRegistry,\n WorkflowSubCanvas,\n} from './typings';\nimport { WorkflowSelectService } from './service/workflow-select-service';\nimport { FREE_LAYOUT_KEY, type FreeLayout } from './layout';\nimport { WorkflowNodeLinesData } from './entity-datas';\nimport {\n WorkflowLineEntity,\n WorkflowLinePortInfo,\n WorkflowNodeEntity,\n WorkflowPortEntity,\n} from './entities';\n\nconst nanoid = customAlphabet('1234567890', 5);\n\nexport const WorkflowDocumentProvider = Symbol('WorkflowDocumentProvider');\nexport type WorkflowDocumentProvider = () => WorkflowDocument;\n\n@injectable()\nexport class WorkflowDocument extends FlowDocument {\n private _onContentChangeEmitter = new Emitter<WorkflowContentChangeEvent>();\n\n protected readonly onLoadedEmitter = new Emitter<void>();\n\n readonly onContentChange = this._onContentChangeEmitter.event;\n\n private _onReloadEmitter = new Emitter<WorkflowDocument>();\n\n readonly onReload = this._onReloadEmitter.event;\n\n /**\n * 数据加载完成\n */\n readonly onLoaded = this.onLoadedEmitter.event;\n\n protected _loading = false;\n\n @inject(WorkflowLinesManager) linesManager: WorkflowLinesManager;\n\n @inject(PlaygroundConfigEntity) playgroundConfig: PlaygroundConfigEntity;\n\n @injectPlaygroundContext() playgroundContext: PlaygroundContext;\n\n @inject(WorkflowDocumentOptions)\n options: WorkflowDocumentOptions = {};\n\n @inject(NodeEngineContext) @optional() nodeEngineContext: NodeEngineContext;\n\n @inject(WorkflowSelectService) selectServices: WorkflowSelectService;\n\n get loading(): boolean {\n return this._loading;\n }\n\n async fitView(easing?: boolean): Promise<void> {\n return fitView(this, this.playgroundConfig, easing).then(() => {\n this.linesManager.forceUpdate();\n });\n }\n\n @postConstruct()\n init(): void {\n super.init();\n this.currentLayoutKey = this.options.defaultLayout || FREE_LAYOUT_KEY;\n this.linesManager.init(this);\n this.playgroundConfig.getCursors = () => this.options.cursors;\n this.linesManager.onAvailableLinesChange((e) => this.fireContentChange(e));\n this.playgroundConfig.onReadonlyOrDisabledChange(({ readonly }) => {\n if (this.nodeEngineContext) {\n this.nodeEngineContext.readonly = readonly;\n }\n });\n }\n\n async load(): Promise<void> {\n if (this.disposed) return;\n this._loading = true;\n await super.load();\n this._loading = false;\n this.onLoadedEmitter.fire();\n }\n\n async reload(json: WorkflowJSON, delayTime = 0): Promise<void> {\n if (this.disposed) return;\n this._loading = true;\n this.clear();\n this.fromJSON(json);\n // loading添加delay,避免reload时触发fireContentChange的副作用\n await delay(delayTime);\n this._loading = false;\n this._onReloadEmitter.fire(this);\n }\n\n /**\n * 从数据加载\n * @param json\n */\n fromJSON(json: Partial<WorkflowJSON>, fireRender = true): void {\n if (this.disposed) return;\n const workflowJSON: WorkflowJSON = {\n nodes: json.nodes ?? [],\n edges: json.edges ?? [],\n };\n // 触发画布更新\n this.entityManager.changeEntityLocked = true;\n\n // 逐层渲染\n this.renderJSON(workflowJSON);\n\n this.entityManager.changeEntityLocked = false;\n this.transformer.loading = false;\n // 批量触发画布更新\n if (fireRender) {\n this.fireRender();\n }\n }\n\n /**\n * 清空画布\n */\n clear(): void {\n this.getAllNodes().map((node) => node.dispose()); // 清空节点\n this.linesManager.getAllLines().map((line) => line.dispose()); // 清空线条\n this.getAllPorts().map((port) => port.dispose()); // 清空端口\n this.selectServices.clear(); // 清空选择\n }\n\n /**\n * 创建流程节点\n * @param json\n */\n createWorkflowNode(\n json: WorkflowNodeJSON,\n isClone: boolean = false,\n parentId?: string\n ): WorkflowNodeEntity {\n // 是否是一个已经存在的节点\n const isExistedNode = this.getNode(json.id);\n const parent = this.getNode(parentId ?? this.root.id) ?? this.root;\n const node = this.addNode(\n {\n ...json,\n parent,\n },\n undefined,\n true\n ) as WorkflowNodeEntity;\n\n const registry = node.getNodeRegistry() as WorkflowNodeRegistry;\n const { formMeta } = registry;\n const meta = node.getNodeMeta<WorkflowNodeMeta>();\n const formData = getFlowNodeFormData(node);\n\n const transform = node.getData<FlowNodeTransformData>(FlowNodeTransformData)!;\n const freeLayout = this.layout as FreeLayout;\n if (!isExistedNode) {\n transform.onDataChange(() => {\n // TODO 这个有点难以理解,其实是为了同步size 数据\n freeLayout.syncTransform(node);\n });\n }\n let { position } = meta;\n if (!position) {\n // 获取默认的位置\n position = this.getNodeDefaultPosition(json.type);\n }\n\n // 更新节点位置信息\n node.getData(TransformData)!.update({\n position,\n });\n\n // 初始化表单数据\n if (formMeta && formData && !formData.formModel.initialized) {\n // 如果表单数据在前置步骤(fromJSON)内已定义,则跳过表单初始化逻辑\n formData.createForm(formMeta, json.data);\n\n formData.onDataChange(() => {\n this.fireContentChange({\n type: WorkflowContentChangeType.NODE_DATA_CHANGE,\n toJSON: () => formData.toJSON(),\n entity: node,\n });\n });\n }\n // 位置变更\n const positionData = node.getData<PositionData>(PositionData)!;\n if (!isExistedNode) {\n positionData.onDataChange(() => {\n this.fireContentChange({\n type: WorkflowContentChangeType.MOVE_NODE,\n toJSON: () => positionData.toJSON(),\n entity: node,\n });\n });\n }\n\n const subCanvas = this.getNodeSubCanvas(node);\n\n if (!isExistedNode && !subCanvas?.isCanvas) {\n this.fireContentChange({\n type: WorkflowContentChangeType.ADD_NODE,\n entity: node,\n toJSON: () => this.toNodeJSON(node),\n });\n node.onDispose(() => {\n if (!node.parent || node.parent.flowNodeType === FlowNodeBaseType.ROOT) {\n return;\n }\n const parentTransform = node.parent.getData(FlowNodeTransformData);\n parentTransform.fireChange();\n });\n let lastDeleteNodeData: WorkflowNodeJSON | undefined;\n node.preDispose.onDispose(() => {\n lastDeleteNodeData = this.toNodeJSON(node);\n });\n node.onDispose(() => {\n this.fireContentChange({\n type: WorkflowContentChangeType.DELETE_NODE,\n entity: node,\n toJSON: () => lastDeleteNodeData,\n });\n });\n }\n\n // 若存在子节点,则创建子节点\n if (json.blocks) {\n this.renderJSON(\n { nodes: json.blocks, edges: json.edges ?? [] },\n {\n parent: node,\n isClone,\n }\n );\n }\n // 子画布联动\n if (subCanvas) {\n const canvasTransform = subCanvas.canvasNode.getData<TransformData>(TransformData);\n canvasTransform.update({\n position: subCanvas.parentNode.getNodeMeta()?.canvasPosition,\n });\n if (!isExistedNode) {\n subCanvas.parentNode.onDispose(() => {\n subCanvas.canvasNode.dispose();\n });\n subCanvas.canvasNode.onDispose(() => {\n subCanvas.parentNode.dispose();\n });\n }\n }\n if (!isExistedNode) {\n this.onNodeCreateEmitter.fire({\n node,\n data: json,\n json,\n });\n } else {\n this.onNodeUpdateEmitter.fire({\n node,\n data: json,\n json,\n });\n }\n\n return node;\n }\n\n /**\n * 添加节点,如果节点已经存在则不会重复创建\n * @param data\n * @param addedNodes\n */\n addNode(\n data: AddNodeData,\n addedNodes?: WorkflowNodeEntity[],\n ignoreCreateAndUpdateEvent?: boolean\n ): WorkflowNodeEntity {\n const { id, type = 'block', originParent, parent, meta, hidden, index } = data;\n let node = this.getNode(id);\n let isNew = false;\n const register = this.getNodeRegistry(type, data.originParent);\n // node 类型变化则全部删除重新来\n if (node && node.flowNodeType !== data.type) {\n node.dispose();\n node = undefined;\n }\n if (!node) {\n const { dataRegistries } = register;\n node = this.entityManager.createEntity<WorkflowNodeEntity>(WorkflowNodeEntity, {\n id,\n document: this,\n flowNodeType: type,\n originParent,\n meta,\n });\n const datas = dataRegistries\n ? this.nodeDataRegistries.concat(...dataRegistries)\n : this.nodeDataRegistries;\n node.addInitializeData(datas);\n node.onDispose(() => this.onNodeDisposeEmitter.fire({ node: node! }));\n this.options.fromNodeJSON?.(node, data, true);\n isNew = true;\n } else {\n this.options.fromNodeJSON?.(node, data, false);\n }\n // 初始化数据重制\n node.initData({\n originParent,\n parent,\n meta,\n hidden,\n index,\n });\n addedNodes?.push(node);\n // 自定义创建逻辑\n if (register.onCreate) {\n const extendNodes = register.onCreate(node, data);\n if (extendNodes && addedNodes) {\n addedNodes.push(...extendNodes);\n }\n }\n\n if (!ignoreCreateAndUpdateEvent) {\n if (isNew) {\n this.onNodeCreateEmitter.fire({\n node,\n data,\n json: data,\n });\n } else {\n this.onNodeUpdateEmitter.fire({ node, data, json: data });\n }\n }\n\n return node;\n }\n\n get layout(): FreeLayout {\n const layout = this.layouts.find((layout) => layout.name == this.currentLayoutKey);\n if (!layout) {\n throw new Error(`Unknown flow layout: ${this.currentLayoutKey}`);\n }\n return layout as FreeLayout;\n }\n\n /**\n * 获取默认的 x y 坐标, 默认为当前画布可视区域中心\n * @param type\n * @protected\n */\n getNodeDefaultPosition(type: string | number): IPoint {\n const { size } = this.getNodeRegistry(type).meta || {};\n // 当前可视区域的中心位置\n let position = this.playgroundConfig.getViewport(true).center;\n if (size) {\n position = {\n x: position.x,\n y: position.y - size.height / 2,\n };\n }\n // 去掉叠加的\n return getAntiOverlapPosition(this, position);\n }\n\n /**\n * 通过类型创建节点, 如果没有提供position 则直接放在画布中间\n * @param type\n */\n createWorkflowNodeByType(\n type: string | number,\n position?: IPoint,\n json: Partial<WorkflowNodeJSON> = {},\n parentID?: string\n ): WorkflowNodeEntity {\n let id: string = json.id as string;\n if (id === undefined) {\n // 保证 id 不要重复\n do {\n id = `1${nanoid()}`;\n } while (this.entityManager.getEntityById(id));\n } else {\n if (this.entityManager.getEntityById(id)) {\n throw new Error(`[WorkflowDocument.createWorkflowNodeByType] Node Id \"${id}\" duplicated.`);\n }\n }\n return this.createWorkflowNode(\n {\n ...json,\n id,\n type,\n meta: { position, ...json?.meta }, // TODO title 和 meta 要从注册数据去拿\n data: json?.data,\n blocks: json?.blocks,\n edges: json?.edges,\n },\n false,\n parentID\n );\n }\n\n getAllNodes(): WorkflowNodeEntity[] {\n return this.entityManager\n .getEntities<WorkflowNodeEntity>(WorkflowNodeEntity)\n .filter((n) => n.id !== FlowNodeBaseType.ROOT);\n }\n\n getAllPorts(): WorkflowPortEntity[] {\n return this.entityManager\n .getEntities<WorkflowPortEntity>(WorkflowPortEntity)\n .filter((p) => p.node.id !== FlowNodeBaseType.ROOT);\n }\n\n /**\n * 获取画布中的非游离节点\n * 1. 开始节点\n * 2. 从开始节点出发能走到的节点\n * 3. 结束节点\n * 4. 默认所有子画布内节点为游离节点\n */\n getAssociatedNodes(): WorkflowNodeEntity[] {\n const allNode = this.getAllNodes();\n\n const allLines = this.linesManager\n .getAllLines()\n .filter((line) => line.from && line.to)\n .map((line) => ({\n from: line.from.id,\n to: line.to!.id,\n }));\n\n const startNodeId = allNode.find((node) => node.isStart)!.id;\n const endNodeId = allNode.find((node) => node.isNodeEnd)!.id;\n\n // 子画布内节点无需开始/结束\n const nodeInContainer = allNode\n .filter((node) => node.parent?.getNodeMeta<WorkflowNodeMeta>().isContainer)\n .map((node) => node.id);\n\n const associatedCache = new Set([endNodeId, ...nodeInContainer]);\n const bfs = (nodeId: string) => {\n if (associatedCache.has(nodeId)) {\n return;\n }\n associatedCache.add(nodeId);\n const nextNodes = allLines.reduce((ids, { from, to }) => {\n if (from === nodeId && !associatedCache.has(to)) {\n ids.push(to);\n }\n return ids;\n }, [] as string[]);\n\n nextNodes.forEach(bfs);\n };\n\n bfs(startNodeId);\n\n const associatedNodes = allNode.filter((node) => associatedCache.has(node.id));\n\n return associatedNodes;\n }\n\n /**\n * 触发渲染\n */\n fireRender() {\n this.entityManager.fireEntityChanged(WorkflowNodeEntity.type);\n this.entityManager.fireEntityChanged(WorkflowLineEntity.type);\n this.entityManager.fireEntityChanged(WorkflowPortEntity.type);\n }\n\n fireContentChange(event: WorkflowContentChangeEvent): void {\n if (this._loading || this.disposed || this.entityManager.changeEntityLocked) {\n return;\n }\n this._onContentChangeEmitter.fire(event);\n }\n\n toNodeJSON(node: WorkflowNodeEntity): WorkflowNodeJSON {\n // 如果是子画布,返回其父节点的JSON\n const subCanvas = this.getNodeSubCanvas(node);\n if (subCanvas?.isCanvas === true) {\n return this.toNodeJSON(subCanvas.parentNode);\n }\n\n const json = this.toNodeJSONFromOptions(node);\n const children = this.getNodeChildren(node);\n\n // 计算子节点 JSON\n const blocks = children.map((child) => this.toNodeJSON(child));\n\n // 计算子线条 JSON\n const linesMap = new Map<string, WorkflowEdgeJSON>();\n children.forEach((child) => {\n const childLinesData = child.getData<WorkflowNodeLinesData>(WorkflowNodeLinesData);\n [...childLinesData.inputLines, ...childLinesData.outputLines]\n .filter(Boolean)\n .forEach((line) => {\n const lineJSON = this.toLineJSON(line);\n if (!lineJSON || linesMap.has(line.id)) {\n return;\n }\n linesMap.set(line.id, lineJSON);\n });\n });\n const edges = Array.from(linesMap.values()); // 使用 Map 防止线条重复\n\n // 拼接 JSON\n if (blocks.length > 0) json.blocks = blocks;\n if (edges.length > 0) json.edges = edges;\n\n return json;\n }\n\n /**\n * 节点转换为JSON, 没有format的过程\n * @param node\n * @returns\n */\n private toNodeJSONFromOptions(node: WorkflowNodeEntity): WorkflowNodeJSON {\n if (this.options.toNodeJSON) {\n return this.options.toNodeJSON(node) as WorkflowNodeJSON;\n }\n return WorkflowDocumentOptionsDefault.toNodeJSON!(node) as WorkflowNodeJSON;\n }\n\n copyNode(\n node: WorkflowNodeEntity,\n newNodeId?: string | undefined,\n format?: (json: WorkflowNodeJSON) => WorkflowNodeJSON,\n position?: IPoint\n ): WorkflowNodeEntity {\n let json = this.toNodeJSON(node);\n if (format) {\n json = format(json);\n }\n position = position || {\n x: json.meta!.position!.x + 30,\n y: json.meta!.position!.y + 30,\n };\n return this.createWorkflowNode(\n {\n id: newNodeId || `1${nanoid()}`,\n type: node.flowNodeType,\n meta: {\n ...json.meta,\n position,\n },\n data: json.data,\n blocks: json.blocks,\n edges: json.edges,\n },\n true,\n node.parent?.id\n );\n }\n\n copyNodeFromJSON(\n flowNodeType: string,\n nodeJSON: WorkflowNodeJSON,\n newNodeId?: string | undefined,\n position?: IPoint,\n parentId?: string\n ): WorkflowNodeEntity {\n position = position || {\n x: nodeJSON.meta!.position!.x + 30,\n y: nodeJSON.meta!.position!.y + 30,\n };\n return this.createWorkflowNode(\n {\n id: newNodeId || `1${nanoid()}`,\n type: flowNodeType,\n meta: {\n ...nodeJSON.meta,\n position,\n },\n data: nodeJSON.data,\n blocks: nodeJSON.blocks,\n edges: nodeJSON.edges,\n },\n true,\n parentId\n );\n }\n\n canRemove(node: WorkflowNodeEntity, silent?: boolean): boolean {\n const meta = node.getNodeMeta<WorkflowNodeMeta>();\n if (meta.deleteDisable) {\n return false;\n }\n if (this.options.canDeleteNode && !this.options.canDeleteNode(node, silent)) {\n return false;\n }\n return true;\n }\n\n /**\n * 判断端口是否为错误态\n */\n isErrorPort(port: WorkflowPortEntity) {\n if (typeof this.options.isErrorPort === 'function') {\n return this.options.isErrorPort(port);\n }\n\n return false;\n }\n\n /**\n * 导出数据\n */\n toJSON(): WorkflowJSON {\n const rootJSON = this.toNodeJSON(this.root);\n return {\n nodes: rootJSON.blocks ?? [],\n edges: rootJSON.edges ?? [],\n };\n }\n\n dispose() {\n super.dispose();\n this._onReloadEmitter.dispose();\n }\n\n /**\n * 逐层创建节点和线条\n */\n public renderJSON(\n json: WorkflowJSON,\n options?: {\n parent?: WorkflowNodeEntity;\n isClone?: boolean;\n }\n ): {\n nodes: WorkflowNodeEntity[];\n edges: WorkflowLineEntity[];\n } {\n const { parent = this.root, isClone = false } = options ?? {};\n // 创建节点\n const containerID = this.getNodeSubCanvas(parent)?.canvasNode.id ?? parent.id;\n const nodes = json.nodes.map((nodeJSON: WorkflowNodeJSON) =>\n this.createWorkflowNode(nodeJSON, isClone, containerID)\n );\n // 创建线条\n const edges = json.edges\n .map((edge) => this.createWorkflowLine(edge, containerID))\n .filter(Boolean) as WorkflowLineEntity[];\n return { nodes, edges };\n }\n\n private getNodeSubCanvas(node: WorkflowNodeEntity): WorkflowSubCanvas | undefined {\n if (!node) return;\n const nodeMeta = node.getNodeMeta<WorkflowNodeMeta>();\n const subCanvas = nodeMeta.subCanvas?.(node);\n return subCanvas;\n }\n\n private getNodeChildren(node: WorkflowNodeEntity): WorkflowNodeEntity[] {\n if (!node) return [];\n const subCanvas = this.getNodeSubCanvas(node);\n const childrenWithCanvas = subCanvas\n ? subCanvas.canvasNode.collapsedChildren\n : node.collapsedChildren;\n // 过滤掉子画布的JSON数据\n const children = childrenWithCanvas\n .filter((child) => {\n const childMeta = child.getNodeMeta<WorkflowNodeMeta>();\n return !childMeta.subCanvas?.(node)?.isCanvas;\n })\n .filter(Boolean);\n return children;\n }\n\n private toLineJSON(line: WorkflowLineEntity): WorkflowEdgeJSON | undefined {\n const lineJSON = line.toJSON();\n if (\n !line.from ||\n !line.info.from ||\n !line.fromPort ||\n !line.to ||\n !line.info.to ||\n !line.toPort\n ) {\n return;\n }\n // 父子节点之间连线,需替换子画布为父节点\n const fromSubCanvas = this.getNodeSubCanvas(line.from);\n const toSubCanvas = this.getNodeSubCanvas(line.to);\n if (fromSubCanvas && !fromSubCanvas.isCanvas && toSubCanvas && toSubCanvas.isCanvas) {\n // 忽略子画布与父节点的连线\n return;\n }\n if (line.from === line.to.parent && fromSubCanvas) {\n return {\n ...lineJSON,\n sourceNodeID: fromSubCanvas.parentNode.id,\n };\n }\n if (line.to === line.from.parent && toSubCanvas) {\n return {\n ...lineJSON,\n targetNodeID: toSubCanvas.parentNode.id,\n };\n }\n return lineJSON;\n }\n\n private createWorkflowLine(\n json: WorkflowEdgeJSON,\n parentId?: string\n ): WorkflowLineEntity | undefined {\n const fromNode = this.getNode(json.sourceNodeID);\n const toNode = this.getNode(json.targetNodeID);\n // 脏数据清除\n if (!fromNode || !toNode) {\n return;\n }\n const lineInfo: WorkflowLinePortInfo = {\n from: json.sourceNodeID,\n fromPort: json.sourcePortID,\n to: json.targetNodeID,\n toPort: json.targetPortID,\n };\n if (!parentId) {\n return this.linesManager.createLine(lineInfo);\n }\n // 父子节点之间连线,需替换父节点为子画布\n const canvasNode = this.getNode(parentId);\n if (!canvasNode) {\n return this.linesManager.createLine(lineInfo);\n }\n const parentSubCanvas = this.getNodeSubCanvas(canvasNode);\n if (!parentSubCanvas) {\n return this.linesManager.createLine(lineInfo);\n }\n if (lineInfo.from === parentSubCanvas.parentNode.id) {\n return this.linesManager.createLine({\n ...lineInfo,\n from: parentSubCanvas.canvasNode.id,\n });\n }\n if (lineInfo.to === parentSubCanvas.parentNode.id) {\n return this.linesManager.createLine({\n ...lineInfo,\n to: parentSubCanvas.canvasNode.id,\n });\n }\n return this.linesManager.createLine(lineInfo);\n }\n}\n","import { inject, injectable } from 'inversify';\nimport {\n type IPoint,\n PaddingSchema,\n Rectangle,\n type ScrollSchema,\n SizeSchema,\n} from '@flowgram.ai/utils';\nimport {\n type FlowDocument,\n type FlowLayout,\n type FlowNodeEntity,\n FlowDocumentProvider,\n FlowNodeTransformData,\n} from '@flowgram.ai/document';\nimport { PlaygroundConfigEntity, TransformData } from '@flowgram.ai/core';\n\nexport const FREE_LAYOUT_KEY = 'free-layout';\n/**\n * 自由画布布局\n */\n@injectable()\nexport class FreeLayout implements FlowLayout {\n name = FREE_LAYOUT_KEY;\n\n @inject(PlaygroundConfigEntity) playgroundConfig: PlaygroundConfigEntity;\n\n @inject(FlowDocumentProvider)\n protected documentProvider: FlowDocumentProvider;\n\n get document(): FlowDocument {\n return this.documentProvider();\n }\n\n /**\n * 更新布局\n */\n update(): void {\n if (this.document.root.getData(FlowNodeTransformData)?.localDirty) {\n this.document.root.clearMemoGlobal();\n // this.document.root.getData(FlowNodeTransformData)!.localDirty = false\n }\n // 自由画布同步同步大小, TODO 这个移动到 createWorkflowNode\n // this.document.root.allChildren.forEach(this.syncTransform.bind(this))\n }\n\n syncTransform(node: FlowNodeEntity): void {\n const transform = node.getData<FlowNodeTransformData>(FlowNodeTransformData)!;\n if (!transform.localDirty) {\n return;\n }\n node.clearMemoGlobal();\n node.clearMemoLocal();\n // 同步 size 给原始的 transform\n transform.transform.update({\n size: transform.data.size,\n });\n if (!node.parent) {\n return;\n }\n node.parent.clearMemoGlobal();\n node.parent.clearMemoLocal();\n const parentTransform = node.parent.getData<FlowNodeTransformData>(FlowNodeTransformData);\n parentTransform.transform.fireChange();\n }\n\n /**\n * 更新所有受影响的上下游节点\n */\n updateAffectedTransform(node: FlowNodeEntity): void {\n const transformData = node.transform;\n if (!transformData.localDirty) {\n return;\n }\n const allParents = this.getAllParents(node);\n const allBlocks = this.getAllBlocks(node).reverse();\n const affectedNodes = [...allBlocks, ...allParents];\n affectedNodes.forEach((node) => {\n this.fireChange(node);\n });\n }\n\n /**\n * 获取节点的 padding 数据\n * @param node\n */\n getPadding(node: FlowNodeEntity): PaddingSchema {\n const { padding } = node.getNodeMeta();\n const transform = node.getData<FlowNodeTransformData>(FlowNodeTransformData);\n if (padding) {\n return typeof padding === 'function' ? padding(transform) : padding;\n }\n return PaddingSchema.empty();\n }\n\n /**\n * 默认滚动到 fitview 区域\n * @param contentSize\n */\n getInitScroll(contentSize: SizeSchema): ScrollSchema {\n const bounds = Rectangle.enlarge(\n this.document.getAllNodes().map((node) => node.getData<TransformData>(TransformData).bounds)\n ).pad(30, 30); // 留出 30 像素的边界\n const viewport = this.playgroundConfig.getViewport(false);\n const zoom = SizeSchema.fixSize(bounds, viewport);\n return {\n scrollX: (bounds.x + bounds.width / 2) * zoom - this.playgroundConfig.config.width / 2,\n scrollY: (bounds.y + bounds.height / 2) * zoom - this.playgroundConfig.config.height / 2,\n };\n }\n\n /**\n * 获取默认输入点\n */\n getDefaultInputPoint(node: FlowNodeEntity): IPoint {\n return node.getData<TransformData>(TransformData)!.bounds.leftCenter;\n }\n\n /**\n * 获取默认输出点\n */\n getDefaultOutputPoint(node: FlowNodeEntity): IPoint {\n return node.getData<TransformData>(TransformData)!.bounds.rightCenter;\n }\n\n /**\n * 水平中心点\n */\n getDefaultNodeOrigin(): IPoint {\n return { x: 0.5, y: 0 };\n }\n\n private getAllParents(node: FlowNodeEntity): FlowNodeEntity[] {\n const parents: FlowNodeEntity[] = [];\n let current = node.parent;\n\n while (current) {\n parents.push(current);\n current = current.parent;\n }\n\n return parents;\n }\n\n private getAllBlocks(node: FlowNodeEntity): FlowNodeEntity[] {\n return node.blocks.reduce<FlowNodeEntity[]>(\n (acc, child) => [...acc, ...this.getAllBlocks(child)],\n [node]\n );\n }\n\n private fireChange(node?: FlowNodeEntity): void {\n const transformData = node?.transform;\n if (!node || !transformData?.localDirty) {\n return;\n }\n node.clearMemoGlobal();\n node.clearMemoLocal();\n transformData.transform.fireChange();\n }\n}\n","import { inject, injectable, postConstruct } from 'inversify';\nimport { PlaygroundConfigEntity } from '@flowgram.ai/core';\nimport { EntityManager } from '@flowgram.ai/core';\nimport { DisposableCollection, Emitter, type IPoint } from '@flowgram.ai/utils';\n\nimport { WorkflowDocument } from '../workflow-document';\nimport { layoutToPositions } from '../utils/layout-to-positions';\nimport { fitView } from '../utils';\nimport { WorkflowNodeEntity } from '../entities';\n\nexport type PositionMap = Record<string, IPoint>;\n\n/**\n * 重置布局服务\n */\n@injectable()\nexport class WorkflowResetLayoutService {\n @inject(PlaygroundConfigEntity)\n private _config: PlaygroundConfigEntity;\n\n @inject(WorkflowDocument)\n private _document: WorkflowDocument;\n\n @inject(EntityManager)\n private _entityManager: EntityManager;\n\n private _resetLayoutEmitter = new Emitter<{\n nodeIds: string[];\n positionMap: PositionMap;\n oldPositionMap: PositionMap;\n }>();\n\n /**\n * reset layout事件\n */\n readonly onResetLayout = this._resetLayoutEmitter.event;\n\n private _toDispose = new DisposableCollection();\n\n /**\n * 初始化\n */\n @postConstruct()\n init() {\n this._toDispose.push(this._resetLayoutEmitter);\n }\n\n /**\n * 触发重置布局\n * @param nodeIds 节点id\n * @param positionMap 新布局数据\n * @param oldPositionMap 老布局数据\n */\n fireResetLayout(nodeIds: string[], positionMap: PositionMap, oldPositionMap: PositionMap) {\n this._resetLayoutEmitter.fire({\n nodeIds,\n positionMap,\n oldPositionMap,\n });\n }\n\n /**\n * 根据数据重新布局\n * @param positionMap\n * @returns\n */\n async layoutToPositions(nodeIds: string[], positionMap: PositionMap) {\n const nodes = nodeIds\n .map(id => this._entityManager.getEntityById(id))\n .filter(Boolean) as WorkflowNodeEntity[];\n const positions = await layoutToPositions(nodes, positionMap);\n fitView(this._document, this._config, true);\n return positions;\n }\n\n /**\n * 销毁\n */\n dispose() {\n this._toDispose.dispose();\n }\n}\n","import { type IPoint } from '@flowgram.ai/utils';\nimport { FlowNodeTransformData } from '@flowgram.ai/document';\nimport { TransformData, startTween } from '@flowgram.ai/core';\n\nimport { type WorkflowDocument } from '../workflow-document';\nimport { type WorkflowNodeEntity } from '../entities';\n\n/**\n * Coze 中节点坐标,以卡片顶部中间为原点。\n * autoLayout 计算出来的对齐的坐标以节点正中为原点,需要上移当前节点一般高度。\n * 即: newPosition.y - transform.bounds.height / 2\n * bounds 的原点坐标为左上角。\n */\nexport const layoutToPositions = async (\n nodes: WorkflowNodeEntity[],\n nodePositionMap: Record<string, IPoint>\n): Promise<Record<string, IPoint>> => {\n // 缓存上次位置,用来还原位置\n const newNodePositionMap: Record<string, IPoint> = {};\n nodes.forEach((node) => {\n const transform = node.getData(TransformData);\n const nodeTransform = node.getData(FlowNodeTransformData);\n\n newNodePositionMap[node.id] = {\n x: transform.position.x,\n y: transform.position.y + nodeTransform.bounds.height / 2,\n };\n });\n\n return new Promise((resolve) => {\n startTween({\n from: { d: 0 },\n to: { d: 100 },\n duration: 300,\n onUpdate: (v) => {\n nodes.forEach((node) => {\n const transform = node.getData(TransformData);\n const deltaX = ((nodePositionMap[node.id].x - transform.position.x) * v.d) / 100;\n const deltaY =\n ((nodePositionMap[node.id].y - transform.bounds.height / 2 - transform.position.y) *\n v.d) /\n 100;\n\n transform.update({\n position: {\n x: transform.position.x + deltaX,\n y: transform.position.y + deltaY,\n },\n });\n\n const document = node.document as WorkflowDocument;\n document.layout.updateAffectedTransform(node);\n });\n },\n onComplete: () => {\n resolve(newNodePositionMap);\n },\n });\n });\n};\n","import { inject } from 'inversify';\nimport { IPoint, Emitter } from '@flowgram.ai/utils';\nimport { FlowNodeEntityOrId, FlowOperationBaseServiceImpl } from '@flowgram.ai/document';\nimport { TransformData } from '@flowgram.ai/core';\n\nimport { WorkflowDocument } from '../workflow-document';\nimport {\n NodePostionUpdateEvent,\n WorkflowOperationBaseService,\n} from '../typings/workflow-operation';\n\nexport class WorkflowOperationBaseServiceImpl\n extends FlowOperationBaseServiceImpl\n implements WorkflowOperationBaseService\n{\n @inject(WorkflowDocument)\n protected declare document: WorkflowDocument;\n\n private onNodePostionUpdateEmitter = new Emitter<NodePostionUpdateEvent>();\n\n public readonly onNodePostionUpdate = this.onNodePostionUpdateEmitter.event;\n\n updateNodePosition(nodeOrId: FlowNodeEntityOrId, position: IPoint): void {\n const node = this.toNodeEntity(nodeOrId);\n\n if (!node) {\n return;\n }\n\n const transformData = node.getData(TransformData);\n const oldPosition = {\n x: transformData.position.x,\n y: transformData.position.y,\n };\n transformData.update({\n position,\n });\n\n this.onNodePostionUpdateEmitter.fire({\n node,\n oldPosition,\n newPosition: position,\n });\n }\n}\n","import { useEffect } from 'react';\n\nimport { usePlayground, useRefresh } from '@flowgram.ai/core';\nimport { type Disposable } from '@flowgram.ai/utils';\n\n/**\n * 获取 readonly 状态\n */\nexport function usePlaygroundReadonlyState(listenChange?: boolean): boolean {\n const playground = usePlayground();\n const refresh = useRefresh();\n useEffect(() => {\n let dispose: Disposable | undefined = undefined;\n if (listenChange) {\n dispose = playground.config.onReadonlyOrDisabledChange(() => refresh());\n }\n return () => dispose?.dispose();\n }, [listenChange]);\n return playground.config.readonly;\n}\n","import { FlowNodeRenderData } from '@flowgram.ai/document';\nimport { useEntityFromContext } from '@flowgram.ai/core';\n\nimport { type WorkflowNodeEntity } from '../entities';\n\n/**\n * 获取当前渲染的 dom 节点\n */\nexport function useCurrentDomNode(): HTMLDivElement {\n const entity = useEntityFromContext<WorkflowNodeEntity>();\n const renderData = entity.getData(FlowNodeRenderData)!;\n return renderData.node;\n}\n","import { useEntityFromContext } from '@flowgram.ai/core';\n\nimport { type WorkflowNodeEntity } from '../entities';\n\n/**\n * 获取当前节点\n */\nexport function useCurrentEntity(): WorkflowNodeEntity {\n return useEntityFromContext<WorkflowNodeEntity>();\n}\n","import { useService } from '@flowgram.ai/core';\n\nimport { WorkflowDocument } from '../workflow-document';\n\nexport function useWorkflowDocument(): WorkflowDocument {\n return useService<WorkflowDocument>(WorkflowDocument);\n}\n","export enum EditorCursorState {\n GRAB = 'GRAB',\n SELECT = 'SELECT',\n}\n\nexport enum InteractiveType {\n /** 鼠标优先交互模式 */\n MOUSE = 'MOUSE',\n\n /** 触控板优先交互模式 */\n PAD = 'PAD',\n}\n","import { ContainerModule } from 'inversify';\nimport { bindContributions } from '@flowgram.ai/utils';\nimport { FlowDocument, FlowDocumentContribution } from '@flowgram.ai/document';\n\nimport { WorkflowLinesManager } from './workflow-lines-manager';\nimport {\n WorkflowDocumentOptions,\n WorkflowDocumentOptionsDefault,\n} from './workflow-document-option';\nimport { WorkflowDocumentContribution } from './workflow-document-contribution';\nimport { WorkflowDocument, WorkflowDocumentProvider } from './workflow-document';\nimport { getUrlParams } from './utils/get-url-params';\nimport { URLParams, WorkflowOperationBaseService } from './typings';\nimport {\n WorkflowDragService,\n WorkflowHoverService,\n WorkflowSelectService,\n WorkflowResetLayoutService,\n WorkflowOperationBaseServiceImpl,\n} from './service';\nimport { FreeLayout } from './layout';\n\nexport const WorkflowDocumentContainerModule = new ContainerModule(\n (bind, unbind, isBound, rebind) => {\n bind(WorkflowDocument).toSelf().inSingletonScope();\n bind(WorkflowLinesManager).toSelf().inSingletonScope();\n bind(FreeLayout).toSelf().inSingletonScope();\n bind(WorkflowDragService).toSelf().inSingletonScope();\n bind(WorkflowSelectService).toSelf().inSingletonScope();\n bind(WorkflowHoverService).toSelf().inSingletonScope();\n bind(WorkflowResetLayoutService).toSelf().inSingletonScope();\n bind(WorkflowOperationBaseService).to(WorkflowOperationBaseServiceImpl).inSingletonScope();\n bind(URLParams)\n .toDynamicValue(() => getUrlParams())\n .inSingletonScope();\n bindContributions(bind, WorkflowDocumentContribution, [FlowDocumentContribution]);\n bind(WorkflowDocumentOptions).toConstantValue({\n ...WorkflowDocumentOptionsDefault,\n });\n rebind(FlowDocument).toService(WorkflowDocument);\n bind(WorkflowDocumentProvider)\n .toDynamicValue((ctx) => () => ctx.container.get(WorkflowDocument))\n .inSingletonScope();\n }\n);\n","import { injectable, inject } from 'inversify';\nimport {\n type FlowDocumentContribution,\n FlowNodeRenderData,\n FlowNodeTransformData,\n} from '@flowgram.ai/document';\n\nimport { WorkflowDocument } from './workflow-document';\nimport { FreeLayout } from './layout';\nimport { WorkflowNodeLinesData, WorkflowNodePortsData } from './entity-datas';\n\n@injectable()\nexport class WorkflowDocumentContribution implements FlowDocumentContribution<WorkflowDocument> {\n @inject(FreeLayout) freeLayout: FreeLayout;\n\n registerDocument(document: WorkflowDocument): void {\n // 注册节点数据\n document.registerNodeDatas(\n FlowNodeTransformData,\n FlowNodeRenderData,\n WorkflowNodePortsData,\n WorkflowNodeLinesData,\n );\n document.registerLayout(this.freeLayout);\n }\n}\n","export function getUrlParams(): Record<string, string> {\n return location.search\n .replace(/^\\?/, '')\n .split('&')\n .reduce((res: Record<string, string>, key) => {\n const [k, v] = key.split('=');\n res[k] = v;\n return res;\n }, {} satisfies Record<string, string>);\n}\n","import { IPoint, Point, Rectangle } from '@flowgram.ai/utils';\n\nimport { WorkflowLineRenderContribution } from '../typings';\nimport { POINT_RADIUS, WorkflowLineEntity } from '../entities';\n\nconst LINE_PADDING = 12;\n\nexport interface StraightData {\n points: IPoint[];\n path: string;\n bbox: Rectangle;\n}\n\nexport class WorkflowSimpleLineContribution implements WorkflowLineRenderContribution {\n public static type = 'WorkflowSimpleLineContribution';\n\n public entity: WorkflowLineEntity;\n\n constructor(entity: WorkflowLineEntity) {\n this.entity = entity;\n }\n\n private data?: StraightData;\n\n public get path(): string {\n return this.data?.path ?? '';\n }\n\n public calcDistance(pos: IPoint): number {\n if (!this.data) {\n return Number.MAX_SAFE_INTEGER;\n }\n const [start, end] = this.data.points;\n return Point.getDistance(pos, this.projectPointOnLine(pos, start, end));\n }\n\n public get bounds(): Rectangle {\n if (!this.data) {\n return new Rectangle();\n }\n return this.data.bbox;\n }\n\n public update(params: { fromPos: IPoint; toPos: IPoint }): void {\n const { fromPos, toPos } = params;\n const { vertical } = this.entity;\n\n // 根据方向预先计算源点和目标点的偏移\n const sourceOffset = {\n x: vertical ? 0 : POINT_RADIUS,\n y: vertical ? POINT_RADIUS : 0,\n };\n const targetOffset = {\n x: vertical ? 0 : -POINT_RADIUS,\n y: vertical ? -POINT_RADIUS : 0,\n };\n\n const points = [\n {\n x: fromPos.x + sourceOffset.x,\n y: fromPos.y + sourceOffset.y,\n },\n {\n x: toPos.x + targetOffset.x,\n y: toPos.y + targetOffset.y,\n },\n ];\n\n const bbox = Rectangle.createRectangleWithTwoPoints(points[0], points[1]);\n\n // 调整所有点到 SVG 视口坐标系\n const adjustedPoints = points.map((p) => ({\n x: p.x - bbox.x + LINE_PADDING,\n y: p.y - bbox.y + LINE_PADDING,\n }));\n\n // 生成直线路径\n const path = `M ${adjustedPoints[0].x} ${adjustedPoints[0].y} L ${adjustedPoints[1].x} ${adjustedPoints[1].y}`;\n\n this.data = {\n points,\n path,\n bbox,\n };\n }\n\n private projectPointOnLine(point: IPoint, lineStart: IPoint, lineEnd: IPoint): IPoint {\n const dx = lineEnd.x - lineStart.x;\n const dy = lineEnd.y - lineStart.y;\n\n // 如果是垂直线\n if (dx === 0) {\n return { x: lineStart.x, y: point.y };\n }\n // 如果是水平线\n if (dy === 0) {\n return { x: point.x, y: lineStart.y };\n }\n\n const t = ((point.x - lineStart.x) * dx + (point.y - lineStart.y) * dy) / (dx * dx + dy * dy);\n const clampedT = Math.max(0, Math.min(1, t));\n\n return {\n x: lineStart.x + clampedT * dx,\n y: lineStart.y + clampedT * dy,\n };\n }\n}\n"],"mappings":"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","names":["WorkflowCommands","import_core","import_react","import_document","import_core","import_core","import_utils","import_core","import_utils","nanoidOrigin","import_utils","import_core","import_utils","import_lodash_es","import_utils","import_core","import_document","import_core","import_utils","import_document","import_core","document","import_utils","import_core","import_utils","import_core","fitView","import_inversify","import_utils","import_core","import_nanoid","import_inversify","import_utils","import_document","import_core","import_lodash_es","import_inversify","import_utils","import_document","import_core","import_form_core","import_document","import_core","WorkflowContentChangeType","LineType","LineColors","import_nanoid","import_inversify","import_utils","import_form_core","import_document","import_core","import_inversify","import_utils","import_document","import_core","node","nanoid","layout","offset","import_inversify","import_core","import_utils","import_document","import_core","document","import_inversify","import_utils","import_document","import_core","import_core","import_document","import_core","import_core","import_core","EditorCursorState","InteractiveType","import_inversify","import_utils","import_document","import_inversify","import_document","document","import_utils"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/workflow-commands.ts","../src/hooks/index.ts","../src/hooks/use-node-render.tsx","../src/service/workflow-select-service.ts","../src/utils/index.ts","../src/utils/nanoid.ts","../src/utils/compose.ts","../src/utils/fit-view.ts","../src/utils/get-anti-overlap-position.ts","../src/utils/statics.ts","../src/entities/workflow-node-entity.ts","../src/entities/workflow-line-entity.ts","../src/entity-datas/workflow-node-ports-data.ts","../src/entities/workflow-port-entity.ts","../src/entity-datas/workflow-node-lines-data.ts","../src/entity-datas/workflow-line-render-data.ts","../src/service/workflow-hover-service.ts","../src/service/workflow-drag-service.ts","../src/workflow-lines-manager.ts","../src/workflow-document-option.ts","../src/utils/flow-node-form-data.ts","../src/typings/workflow-json.ts","../src/typings/workflow-line.ts","../src/typings/workflow-operation.ts","../src/typings/index.ts","../src/workflow-document.ts","../src/layout/free-layout.ts","../src/service/workflow-reset-layout-service.ts","../src/utils/layout-to-positions.ts","../src/service/workflow-operation-base-service.ts","../src/hooks/use-playground-readonly-state.ts","../src/hooks/use-current-dom-node.ts","../src/hooks/use-current-entity.ts","../src/hooks/use-workflow-document.ts","../src/constants.ts","../src/workflow-document-container-module.ts","../src/workflow-document-contribution.ts","../src/utils/get-url-params.ts","../src/utils/simple-line.ts"],"sourcesContent":["export * from './workflow-commands';\nexport * from './hooks';\nexport * from './utils';\nexport * from './typings';\nexport * from './entities';\nexport * from './constants';\nexport * from './entity-datas';\nexport * from './service';\nexport * from './workflow-document';\nexport * from './workflow-document-container-module';\nexport * from './workflow-lines-manager';\nexport * from './workflow-document-option';\nexport * from './utils/simple-line';\n","export enum WorkflowCommands {\n DELETE_NODES = 'DELETE_NODES',\n COPY_NODES = 'COPY_NODES',\n PASTE_NODES = 'PASTE_NODES',\n ZOOM_IN = 'ZOOM_IN',\n ZOOM_OUT = 'ZOOM_OUT',\n UNDO = 'UNDO',\n REDO = 'REDO',\n}\n","export {\n useConfigEntity,\n useService,\n usePlayground,\n useListenEvents,\n usePlaygroundContainer,\n usePlaygroundContext,\n useEntities,\n useEntityFromContext,\n useEntityDataFromContext,\n useRefresh,\n usePlaygroundLatest,\n} from '@flowgram.ai/core';\nexport * from './typings';\nexport * from './use-node-render';\nexport * from './use-current-dom-node';\nexport * from './use-current-entity';\nexport * from './use-workflow-document';\nexport * from './use-playground-readonly-state';\n","import type React from 'react';\nimport { useCallback, useEffect, useRef, useState, useContext, useMemo } from 'react';\n\nimport { useObserve } from '@flowgram.ai/reactive';\nimport { getNodeForm } from '@flowgram.ai/node';\nimport { FlowNodeRenderData } from '@flowgram.ai/document';\nimport {\n MouseTouchEvent,\n PlaygroundEntityContext,\n useListenEvents,\n useService,\n} from '@flowgram.ai/core';\n\nimport { WorkflowDragService, WorkflowSelectService } from '../service';\nimport { WorkflowNodePortsData } from '../entity-datas';\nimport { type WorkflowNodeEntity } from '../entities';\nimport { usePlaygroundReadonlyState } from './use-playground-readonly-state';\nimport { type NodeRenderReturnType } from './typings';\n\nfunction checkTargetDraggable(el: any): boolean {\n return (\n el &&\n el.tagName !== 'INPUT' &&\n el.tagName !== 'TEXTAREA' &&\n !el.closest('.flow-canvas-not-draggable')\n );\n}\n\nexport function useNodeRender(nodeFromProps?: WorkflowNodeEntity): NodeRenderReturnType {\n const node = nodeFromProps || useContext<WorkflowNodeEntity>(PlaygroundEntityContext);\n const renderData = node.getData(FlowNodeRenderData)!;\n const portsData = node.getData(WorkflowNodePortsData)!;\n const readonly = usePlaygroundReadonlyState();\n const dragService = useService<WorkflowDragService>(WorkflowDragService);\n const selectionService = useService<WorkflowSelectService>(WorkflowSelectService);\n const isDragging = useRef(false);\n const [formValueVersion, updateFormValueVersion] = useState<number>(0);\n const formValueDependRef = useRef(false);\n formValueDependRef.current = false;\n const nodeRef = useRef<HTMLDivElement | null>(null);\n const [linkingNodeId, setLinkingNodeId] = useState('');\n\n useEffect(() => {\n const disposable = dragService.onDragLineEventChange(({ type, onDragNodeId }) => {\n if (type === 'onDrag') {\n setLinkingNodeId(onDragNodeId || '');\n } else {\n setLinkingNodeId('');\n }\n });\n\n return () => {\n disposable.dispose();\n };\n }, []);\n\n const startDrag = useCallback(\n (e: React.MouseEvent) => {\n MouseTouchEvent.preventDefault(e);\n if (!selectionService.isSelected(node.id)) {\n selectNode(e);\n }\n if (!MouseTouchEvent.isTouchEvent(e as unknown as React.TouchEvent)) {\n // 输入框不能拖拽\n if (!checkTargetDraggable(e.target) || !checkTargetDraggable(document.activeElement)) {\n return;\n }\n }\n isDragging.current = true;\n // 拖拽选中的节点\n dragService.startDragSelectedNodes(e)?.finally(() =>\n setTimeout(() => {\n isDragging.current = false;\n })\n );\n },\n [dragService, node]\n );\n /**\n * 单选节点\n */\n const selectNode = useCallback(\n (e: React.MouseEvent) => {\n // 触发了拖拽就不要再触发单选\n if (isDragging.current) {\n return;\n }\n // 追加选择\n if (e.shiftKey) {\n selectionService.toggleSelect(node);\n } else {\n selectionService.selectNode(node);\n }\n if (e.target) {\n (e.target as HTMLDivElement).focus();\n }\n },\n [node]\n );\n const deleteNode = useCallback(() => node.dispose(), [node]);\n // 监听端口变化\n useListenEvents(portsData.onDataChange);\n\n /**\n * - 下面的 firefox 为了修复一个 bug:https://meego.feishu.cn/bot_bot/issue/detail/3001017843\n * - firefox 下 draggable 属性会影响节点 input 内容 focus:https://jsfiddle.net/Aydar/ztsvbyep/3/\n * - 该 bug 在 firefox 浏览器上存在了很久,需要作兼容:https://bugzilla.mozilla.org/show_bug.cgi?id=739071\n */\n const isFirefox = navigator?.userAgent?.includes?.('Firefox');\n const onFocus = useCallback(() => {\n if (isFirefox) {\n nodeRef.current?.setAttribute('draggable', 'false');\n }\n }, []);\n const onBlur = useCallback(() => {\n if (isFirefox) {\n nodeRef.current?.setAttribute('draggable', 'true');\n }\n }, []);\n const getExtInfo = useCallback(() => node.getExtInfo() as any, [node]);\n const updateExtInfo = useCallback(\n (data: any) => {\n node.updateExtInfo(data);\n },\n [node]\n );\n const form = useMemo(() => getNodeForm(node), [node]);\n // Listen FormState change\n const formState = useObserve<any>(form?.state);\n const toggleExpand = useCallback(() => {\n renderData.toggleExpand();\n }, [renderData]);\n const selected = selectionService.isSelected(node.id);\n const activated = selectionService.isActivated(node.id);\n const expanded = renderData.expanded;\n useEffect(() => {\n const toDispose = form?.onFormValuesChange(() => {\n if (formValueDependRef.current) {\n updateFormValueVersion((v) => v + 1);\n }\n });\n return () => toDispose?.dispose();\n }, [form]);\n\n return useMemo(\n () => ({\n id: node.id,\n type: node.flowNodeType,\n get data() {\n if (form) {\n formValueDependRef.current = true;\n return form.values;\n }\n return getExtInfo();\n },\n updateData(values: any) {\n if (form) {\n form.updateFormValues(values);\n } else {\n updateExtInfo(values);\n }\n },\n node,\n selected,\n activated,\n expanded,\n startDrag,\n get ports() {\n return portsData.allPorts;\n },\n deleteNode,\n selectNode,\n readonly,\n linkingNodeId,\n nodeRef,\n onFocus,\n onBlur,\n getExtInfo,\n updateExtInfo,\n toggleExpand,\n get form() {\n if (!form) return undefined;\n return {\n ...form,\n get values() {\n formValueDependRef.current = true;\n return form.values!;\n },\n get state() {\n return formState;\n },\n };\n },\n }),\n [\n node,\n selected,\n activated,\n expanded,\n startDrag,\n deleteNode,\n selectNode,\n readonly,\n linkingNodeId,\n nodeRef,\n onFocus,\n onBlur,\n getExtInfo,\n updateExtInfo,\n toggleExpand,\n formValueVersion,\n ]\n );\n}\n","import { inject, injectable } from 'inversify';\nimport {\n type Entity,\n Playground,\n SelectionService,\n TransformData,\n type PlaygroundConfigRevealOpts,\n} from '@flowgram.ai/core';\nimport { type Event, Rectangle, SizeSchema } from '@flowgram.ai/utils';\n\nimport { delay } from '../utils';\nimport { WorkflowNodeEntity } from '../entities';\nimport { type WorkfloEntityHoverable } from './workflow-hover-service';\n\n@injectable()\nexport class WorkflowSelectService {\n @inject(SelectionService) protected selectionService: SelectionService;\n\n @inject(Playground) protected playground: Playground;\n\n get onSelectionChanged(): Event<void> {\n return this.selectionService.onSelectionChanged;\n }\n\n get selection(): Entity[] {\n return this.selectionService.selection;\n }\n\n set selection(entities: Entity[]) {\n this.selectionService.selection = entities;\n }\n\n /**\n * 当前激活的节点只能有一个\n */\n get activatedNode(): WorkflowNodeEntity | undefined {\n const { selectedNodes } = this;\n if (selectedNodes.length !== 1) {\n return undefined;\n }\n return selectedNodes[0];\n }\n\n isSelected(id: string): boolean {\n return this.selectionService.selection.some(s => s.id === id);\n }\n\n isActivated(id: string): boolean {\n return this.activatedNode?.id === id;\n }\n\n /**\n * 选中的节点\n */\n get selectedNodes(): WorkflowNodeEntity[] {\n return this.selectionService.selection.filter(\n n => n instanceof WorkflowNodeEntity,\n ) as WorkflowNodeEntity[];\n }\n\n /**\n * 选中\n * @param node\n */\n selectNode(node: WorkflowNodeEntity): void {\n this.selectionService.selection = [node];\n }\n\n toggleSelect(node: WorkflowNodeEntity): void {\n if (this.selectionService.selection.includes(node)) {\n this.selectionService.selection = this.selectionService.selection.filter(n => n !== node);\n } else {\n this.selectionService.selection = this.selectionService.selection.concat(node);\n }\n }\n\n select(node: WorkfloEntityHoverable): void {\n this.selectionService.selection = [node];\n }\n\n clear(): void {\n this.selectionService.selection = [];\n }\n\n /**\n * 选中并滚动到节点\n * @param node\n */\n async selectNodeAndScrollToView(node: WorkflowNodeEntity, fitView?: boolean): Promise<void> {\n this.selectNodeAndFocus(node);\n const DELAY_TIME = 30;\n // 等待节点渲染完成(一般用于刚添加的节点)\n await delay(DELAY_TIME);\n\n const scrollConfig: PlaygroundConfigRevealOpts = {\n entities: [node],\n };\n\n if (fitView) {\n const bounds = Rectangle.enlarge([node.getData<TransformData>(TransformData).bounds]).pad(\n 30,\n 30,\n ); // 留出 30 像素的边界\n\n const viewport = this.playground.config.getViewport(false);\n\n const zoom = SizeSchema.fixSize(bounds, viewport);\n\n scrollConfig.zoom = zoom;\n scrollConfig.scrollToCenter = true;\n scrollConfig.easing = true;\n }\n\n return this.playground.config.scrollToView(scrollConfig);\n }\n\n selectNodeAndFocus(node: WorkflowNodeEntity): void {\n // 新添加的节点需要被选中\n this.select(node);\n // 拖进来需要让画布聚焦, 才能使用快捷键删除\n this.playground.node.focus();\n }\n}\n","import { bindConfigEntity } from '@flowgram.ai/core';\nexport { delay } from '@flowgram.ai/utils';\n\n/**\n * 让 entity 可以注入到类中\n *\n * @example\n * ```\n * class SomeClass {\n * @inject(PlaygroundConfigEntity) playgroundConfig: PlaygroundConfigEntity\n * }\n * ```\n * @param bind\n * @param entityRegistry\n */\nexport { bindConfigEntity };\n\nexport * from './nanoid';\nexport * from './compose';\nexport * from './fit-view';\nexport * from './get-anti-overlap-position';\nexport * from './statics';\n","import { nanoid as nanoidOrigin } from 'nanoid';\n\nexport function nanoid(n?: number): string {\n return nanoidOrigin(n);\n}\n","export { compose, composeAsync } from '@flowgram.ai/utils';\n","import { type PlaygroundConfigEntity, TransformData } from '@flowgram.ai/core';\nimport { Rectangle } from '@flowgram.ai/utils';\n\nimport { type WorkflowDocument } from '../workflow-document';\n\nexport const fitView = (\n doc: WorkflowDocument,\n playgroundConfig: PlaygroundConfigEntity,\n easing = true,\n) => {\n const bounds = Rectangle.enlarge(\n doc.getAllNodes().map(node => node.getData<TransformData>(TransformData).bounds),\n );\n // 留出 30 像素的边界\n return playgroundConfig.fitView(bounds, easing, 30);\n};\n","import { TransformData } from '@flowgram.ai/core';\nimport { type IPoint } from '@flowgram.ai/utils';\n\nimport { type WorkflowDocument } from '../workflow-document';\nimport { WorkflowNodeEntity } from '../entities';\n\n/**\n * 获取没有碰撞的位置\n * 距离很小时,xy 各偏移 30\n * @param position\n */\nexport function getAntiOverlapPosition(\n doc: WorkflowDocument,\n position: IPoint,\n containerNode?: WorkflowNodeEntity,\n): IPoint {\n let { x, y } = position;\n const nodes = containerNode ? containerNode.collapsedChildren : doc.getAllNodes();\n const positions = nodes\n .map(n => {\n const transform = n.getData<TransformData>(TransformData)!;\n return { x: transform.position.x, y: transform.position.y };\n })\n .sort((a, b) => a.y - b.y);\n const minDistance = 3;\n for (const pos of positions) {\n const { x: posX, y: posY } = pos;\n if (y - posY < -minDistance) {\n break;\n }\n const deltaX = Math.abs(x - posX);\n const deltaY = Math.abs(y - posY);\n if (deltaX <= minDistance && deltaY <= minDistance) {\n x += 30;\n y += 30;\n }\n }\n return { x, y };\n}\n","import { Rectangle } from '@flowgram.ai/utils';\n\nimport { type WorkflowNodeEntity } from '../entities/workflow-node-entity';\nexport type WorkflowPortType = 'input' | 'output';\n\nexport const getPortEntityId = (\n node: WorkflowNodeEntity,\n portType: WorkflowPortType,\n portID: string | number = '',\n): string => `port_${portType}_${node.id}_${portID}`;\n\nexport const WORKFLOW_LINE_ENTITY = 'WorkflowLineEntity';\n\nexport function domReactToBounds(react: DOMRect): Rectangle {\n return new Rectangle(react.x, react.y, react.width, react.height);\n}\n","import { FlowNodeEntity } from '@flowgram.ai/document';\n\nexport type WorkflowNodeEntity = FlowNodeEntity;\nexport const WorkflowNodeEntity = FlowNodeEntity;\n","import { isEqual } from 'lodash-es';\nimport { domUtils, type IPoint, Rectangle } from '@flowgram.ai/utils';\nimport { Entity, type EntityOpts } from '@flowgram.ai/core';\n\nimport { type WorkflowLinesManager } from '../workflow-lines-manager';\nimport { type WorkflowDocument } from '../workflow-document';\nimport { WORKFLOW_LINE_ENTITY } from '../utils/statics';\nimport { LineRenderType, type LinePosition } from '../typings/workflow-line';\nimport { type WorkflowEdgeJSON } from '../typings';\nimport { WorkflowNodePortsData } from '../entity-datas/workflow-node-ports-data';\nimport { WorkflowLineRenderData } from '../entity-datas';\nimport { type WorkflowPortEntity } from './workflow-port-entity';\nimport { type WorkflowNodeEntity } from './workflow-node-entity';\n\nexport const LINE_HOVER_DISTANCE = 8; // 线条 hover 的最小检测距离\nexport const POINT_RADIUS = 10;\n\nexport interface WorkflowLinePortInfo {\n from: string; // 前置节点 id\n to?: string; // 后置节点 id\n fromPort?: string | number; // 连线的 port 位置\n toPort?: string | number; // 连线的 port 位置\n}\n\nexport interface WorkflowLineEntityOpts extends EntityOpts, WorkflowLinePortInfo {\n document: WorkflowDocument;\n linesManager: WorkflowLinesManager;\n drawingTo?: IPoint;\n}\n\nexport interface WorkflowLineInfo extends WorkflowLinePortInfo {\n drawingTo?: IPoint; // 正在画中的元素\n isDefaultLine?: boolean; // 是否为默认的线\n highlightColor?: string; // 高亮显示\n}\n\n/**\n * 线条\n */\nexport class WorkflowLineEntity extends Entity<WorkflowLineEntityOpts> {\n static type = WORKFLOW_LINE_ENTITY;\n\n /**\n * 转成线条 id\n * @param info\n */\n static portInfoToLineId(info: WorkflowLinePortInfo): string {\n const { from, to, fromPort, toPort } = info;\n return `${from}_${fromPort || ''}-${to || ''}_${toPort || ''}`;\n }\n\n readonly document: WorkflowDocument;\n\n readonly linesManager: WorkflowLinesManager;\n\n private _from: WorkflowNodeEntity;\n\n private _to?: WorkflowNodeEntity;\n\n private _processing = false;\n\n private _hasError = false;\n\n /**\n * 线条数据\n */\n info: WorkflowLineInfo = {\n from: '',\n };\n\n readonly isDrawing: boolean;\n\n /**\n * 线条 Portal 挂载的 div\n */\n private _node?: HTMLDivElement;\n\n constructor(opts: WorkflowLineEntityOpts) {\n super(opts);\n this.document = opts.document;\n this.linesManager = opts.linesManager;\n // 初始化\n this.initInfo({\n from: opts.from,\n to: opts.to,\n drawingTo: opts.drawingTo,\n fromPort: opts.fromPort,\n toPort: opts.toPort,\n });\n if (opts.drawingTo) {\n this.isDrawing = true;\n }\n // this.onDispose(() => {\n // this._infoDispose.dispose();\n // });\n }\n\n /**\n * 获取线条的前置节点\n */\n get from(): WorkflowNodeEntity {\n return this._from;\n }\n\n /**\n * 获取线条的后置节点\n */\n get to(): WorkflowNodeEntity | undefined {\n return this._to;\n }\n\n get isHidden(): boolean {\n return this.highlightColor === this.linesManager.lineColor.hidden;\n }\n\n get inContainer(): boolean {\n const nodeInContainer = (node?: WorkflowNodeEntity) =>\n !!node?.parent && node.parent.flowNodeType !== 'root';\n return nodeInContainer(this.from) || nodeInContainer(this.to);\n }\n\n /**\n * 获取是否 testrun processing\n */\n get processing(): boolean {\n return this._processing;\n }\n\n /**\n * 设置 testrun processing 状态\n */\n set processing(status: boolean) {\n if (this._processing !== status) {\n this._processing = status;\n this.fireChange();\n }\n }\n\n // 获取连线是否为错误态\n get hasError() {\n return this._hasError;\n }\n\n // 设置连线的错误态\n set hasError(hasError: boolean) {\n if (this._hasError !== hasError) {\n this._hasError = hasError;\n this.fireChange();\n }\n if (this._node) {\n this._node.dataset.hasError = this.hasError ? 'true' : 'false';\n }\n }\n\n /**\n * 设置线条的后置节点\n */\n setToPort(toPort?: WorkflowPortEntity) {\n // 只有绘制中的线条才允许设置 port, 主要用于吸附到点\n if (!this.isDrawing) {\n throw new Error('[setToPort] only support drawing line.');\n }\n if (this.toPort === toPort) {\n return;\n }\n if (\n toPort &&\n toPort.portType === 'input' &&\n this.linesManager.canAddLine(this.fromPort, toPort, true)\n ) {\n const { node, portID } = toPort;\n this._to = node;\n this.info.drawingTo = undefined;\n this.info.isDefaultLine = false;\n this.info.to = node.id;\n this.info.toPort = portID;\n } else {\n this._to = undefined;\n this.info.to = undefined;\n this.info.toPort = '';\n }\n this.fireChange();\n }\n\n /**\n * 设置线条画线时的目标位置\n */\n set drawingTo(pos: IPoint | undefined) {\n const oldDrawingTo = this.info.drawingTo;\n if (!pos) {\n this.info.drawingTo = undefined;\n this.fireChange();\n return;\n }\n if (!oldDrawingTo || pos.x !== oldDrawingTo.x || pos.y !== oldDrawingTo.y) {\n this.info.to = undefined;\n this.info.isDefaultLine = false;\n this.info.drawingTo = pos;\n this.fireChange();\n }\n }\n\n /**\n * 获取线条正在画线的位置\n */\n get drawingTo(): IPoint | undefined {\n return this.info.drawingTo;\n }\n\n get highlightColor(): string {\n return this.info.highlightColor || '';\n }\n\n set highlightColor(color) {\n if (this.info.highlightColor !== color) {\n this.info.highlightColor = color;\n this.fireChange();\n }\n }\n\n /**\n * 获取线条的边框位置大小\n */\n get bounds(): Rectangle {\n return this.getData(WorkflowLineRenderData).bounds;\n }\n\n /**\n * 获取点和线最接近的距离\n */\n getHoverDist(pos: IPoint): number {\n return this.getData(WorkflowLineRenderData).calcDistance(pos);\n }\n\n get fromPort(): WorkflowPortEntity {\n return this.from\n .getData(WorkflowNodePortsData)\n .getPortEntityByKey('output', this.info.fromPort);\n }\n\n get toPort(): WorkflowPortEntity | undefined {\n if (!this.to) {\n return undefined;\n }\n return this.to.getData(WorkflowNodePortsData).getPortEntityByKey('input', this.info.toPort);\n }\n\n /**\n * 获取线条真实的输入输出节点坐标\n */\n get position(): LinePosition {\n return this.getData(WorkflowLineRenderData).position;\n }\n\n /** 是否反转箭头 */\n get reverse(): boolean {\n return this.linesManager.isReverseLine(this);\n }\n\n /** 是否隐藏箭头 */\n get hideArrow(): boolean {\n return this.linesManager.isHideArrowLine(this);\n }\n\n /** 是否流动 */\n get flowing(): boolean {\n return this.linesManager.isFlowingLine(this);\n }\n\n /** 是否禁用 */\n get disabled(): boolean {\n return this.linesManager.isDisabledLine(this);\n }\n\n /** 是否竖向 */\n get vertical(): boolean {\n return this.linesManager.isVerticalLine(this);\n }\n\n /** 获取线条渲染器类型 */\n get renderType(): LineRenderType | undefined {\n return this.linesManager.setLineRenderType(this);\n }\n\n /** 获取线条样式 */\n get className(): string | undefined {\n return this.linesManager.setLineClassName(this) ?? '';\n }\n\n get color(): string | undefined {\n return this.linesManager.getLineColor(this);\n }\n\n /**\n * 初始化线条\n * @param info 线条信息\n */\n protected initInfo(info: WorkflowLineInfo): void {\n if (!isEqual(info, this.info)) {\n this.info = info;\n this._from = this.document.getNode(info.from)!;\n this._to = info.to ? this.document.getNode(info.to) : undefined;\n this.fireChange();\n }\n }\n\n // 校验连线是否为错误态\n validate() {\n const { fromPort, toPort } = this;\n this.validateSelf();\n fromPort?.validate();\n toPort?.validate();\n }\n\n validateSelf() {\n const { fromPort, toPort } = this;\n\n if (fromPort) {\n this.hasError = this.linesManager.isErrorLine(fromPort, toPort);\n }\n }\n\n is(line: WorkflowLineEntity | WorkflowLinePortInfo): boolean {\n if (line instanceof WorkflowLineEntity) {\n return this === line;\n }\n return WorkflowLineEntity.portInfoToLineId(line as WorkflowLinePortInfo) === this.id;\n }\n\n canRemove(newLineInfo?: Required<WorkflowLinePortInfo>): boolean {\n return this.linesManager.canRemove(this, newLineInfo);\n }\n\n get node(): HTMLDivElement {\n if (this._node) return this._node;\n this._node = domUtils.createDivWithClass('gedit-flow-activity-line');\n this._node.dataset.testid = 'sdk.workflow.canvas.line';\n this._node.dataset.lineId = this.id;\n this._node.dataset.fromNodeId = this.from.id;\n this._node.dataset.fromPortId = this.fromPort?.id ?? '';\n this._node.dataset.toNodeId = this.to?.id ?? '';\n this._node.dataset.toPortId = this.toPort?.id ?? '';\n this._node.dataset.hasError = this.hasError ? 'true' : 'false';\n return this._node;\n }\n\n toJSON(): WorkflowEdgeJSON {\n const json = {\n sourceNodeID: this.info.from,\n targetNodeID: this.info.to!,\n sourcePortID: this.info.fromPort,\n targetPortID: this.info.toPort,\n };\n if (!json.sourcePortID) {\n delete json.sourcePortID;\n }\n if (!json.targetPortID) {\n delete json.targetPortID;\n }\n return json;\n }\n\n /** 触发线条渲染 */\n fireRender(): void {\n this.fireChange();\n }\n}\n","import { isEqual } from 'lodash-es';\nimport { FlowNodeRenderData } from '@flowgram.ai/document';\nimport { EntityData, SizeData } from '@flowgram.ai/core';\nimport { type IPoint } from '@flowgram.ai/utils';\n\nimport { type WorkflowPortType, getPortEntityId } from '../utils/statics';\nimport { type WorkflowNodeMeta } from '../typings';\nimport { WorkflowPortEntity } from '../entities/workflow-port-entity';\nimport { type WorkflowNodeEntity, type WorkflowPort, type WorkflowPorts } from '../entities';\n\n/**\n * 节点的点位信息\n * portsData 只监听点位的数目和类型,不监听点位的 position 变化\n */\nexport class WorkflowNodePortsData extends EntityData {\n public static readonly type = 'WorkflowNodePortsData';\n\n public readonly entity: WorkflowNodeEntity;\n\n /** 静态的 ports 数据 */\n protected _staticPorts: WorkflowPorts = [];\n\n /** 存储 port 实体的 id,用于判断 port 是否存在 */\n protected _portIDSet = new Set<string>();\n\n /** 上一次的 ports 数据,用于判断 ports 是否发生变化 */\n protected _prePorts: WorkflowPorts;\n\n constructor(entity: WorkflowNodeEntity) {\n super(entity);\n this.entity = entity;\n const meta = entity.getNodeMeta<WorkflowNodeMeta>();\n // 动态模式默认为空, 非动态模式默认左右两个点位\n const defaultPorts: WorkflowPorts = meta.useDynamicPort\n ? []\n : [{ type: 'input' }, { type: 'output' }];\n this._staticPorts = meta.defaultPorts?.slice() || defaultPorts;\n this.updatePorts(this._staticPorts);\n if (meta.useDynamicPort) {\n this.toDispose.push(\n // 只需要监听节点的大小,因为算的是相对位置\n entity.getData!(SizeData)!.onDataChange(() => {\n // 有可能节点被销毁了\n if (entity.getData!(SizeData).width && entity.getData!(SizeData).height) {\n this.updateDynamicPorts();\n }\n }),\n );\n }\n this.onDispose(() => {\n this.allPorts.forEach(port => port.dispose());\n });\n }\n\n public getDefaultData(): any {\n return {};\n }\n\n /**\n * 更新静态的 ports 数据\n */\n public updateStaticPorts(ports: WorkflowPorts): void {\n const meta = this.entity.getNodeMeta<WorkflowNodeMeta>();\n this._staticPorts = ports;\n if (meta.useDynamicPort) {\n this.updateDynamicPorts();\n } else {\n this.updatePorts(this._staticPorts);\n }\n }\n\n /**\n * 动态计算点位,通过 dom 的 data-port-key\n */\n public updateDynamicPorts(): void {\n const domNode = this.entity.getData(FlowNodeRenderData)!.node;\n const elements = domNode.querySelectorAll<HTMLDivElement>('[data-port-id]');\n const staticPorts: WorkflowPorts = this._staticPorts;\n const dynamicPorts: WorkflowPorts = [];\n if (elements.length > 0) {\n dynamicPorts.push(\n ...Array.from(elements).map(element => ({\n portID: element.getAttribute('data-port-id')!,\n type: element.getAttribute('data-port-type')! as WorkflowPortType,\n targetElement: element,\n })),\n );\n }\n this.updatePorts(staticPorts.concat(dynamicPorts));\n }\n\n /**\n * 根据 key 获取 port 实体\n */\n public getPortEntityByKey(\n portType: WorkflowPortType,\n portKey?: string | number,\n ): WorkflowPortEntity {\n const entity = this.getOrCreatePortEntity({\n type: portType,\n portID: portKey,\n });\n return entity;\n }\n\n /**\n * 更新 ports 数据\n */\n public updatePorts(ports: WorkflowPorts): void {\n if (!isEqual(this._prePorts, ports)) {\n const portKeys = ports.map(port => this.getPortId(port.type, port.portID));\n this._portIDSet.forEach(portId => {\n if (!portKeys.includes(portId)) {\n this.getPortEntity(portId)?.dispose();\n }\n });\n ports.forEach(port => this.updatePortEntity(port));\n this._prePorts = ports;\n this.fireChange();\n }\n\n // Note: 为什么调用 port.validate 不够,需要调用 line.validate\n // 原因:假设有这样的连线:dynamic port → end 节点。\n // line.validate 时,line.fromPort 可能为 undefined(未创建实体),导致 end 节点上的 port 未正确校验\n // 所以需要在所有 port entities 准备完成后,通过再次调用 line.validate 来触发连线另一端的 port 更新\n this.allPorts.forEach(port => {\n port.allLines.forEach(line => {\n line.validate();\n });\n port.validate();\n });\n }\n\n /**\n * 获取所有 port entities\n */\n public get allPorts(): WorkflowPortEntity[] {\n return Array.from(this._portIDSet)\n .map(portId => this.getPortEntity(portId)!)\n .filter(Boolean); // dispose 时,会获取不到 port\n }\n\n /**\n * 获取输入点位\n */\n public get inputPorts(): WorkflowPortEntity[] {\n return this.allPorts.filter(port => port.portType === 'input');\n }\n\n /**\n * 获取输出点位\n */\n public get outputPorts(): WorkflowPortEntity[] {\n return this.allPorts.filter(port => port.portType === 'output');\n }\n\n /**\n * 获取输入点位置\n */\n public get inputPoints(): IPoint[] {\n return this.inputPorts.map(port => port.point);\n }\n\n /**\n * 获取输出点位置\n */\n public get outputPoints(): IPoint[] {\n return this.inputPorts.map(port => port.point);\n }\n\n /**\n * 根据 key 获取 输入点位置\n */\n public getInputPoint(key?: string | number): IPoint {\n return this.getPortEntityByKey('input', key).point;\n }\n\n /**\n * 根据 key 获取输出点位置\n */\n public getOutputPoint(key?: string | number): IPoint {\n return this.getPortEntityByKey('output', key).point;\n }\n\n /**\n * 获取 port 实体\n */\n protected getPortEntity(portId: string): WorkflowPortEntity | undefined {\n if (!this._portIDSet.has(portId)) {\n // 如果不是自身创建的 port,则返回 undefined\n return undefined;\n }\n return this.entity.entityManager.getEntityById<WorkflowPortEntity>(portId)!;\n }\n\n /**\n * 拼接 port 实体的 id\n */\n protected getPortId(portType: WorkflowPortType, portKey: string | number = ''): string {\n return getPortEntityId(this.entity, portType, portKey);\n }\n\n /**\n * 创建 port 实体\n */\n protected createPortEntity(portInfo: WorkflowPort): WorkflowPortEntity {\n const id = this.getPortId(portInfo.type, portInfo.portID);\n let portEntity = this.entity.entityManager.getEntityById<WorkflowPortEntity>(id);\n if (!portEntity) {\n portEntity = this.entity.entityManager.createEntity<WorkflowPortEntity>(WorkflowPortEntity, {\n id,\n node: this.entity,\n ...portInfo,\n });\n }\n portEntity.onDispose(() => {\n this._portIDSet.delete(id);\n });\n this._portIDSet.add(id);\n return portEntity;\n }\n\n /**\n * 获取或创建 port 实体\n */\n protected getOrCreatePortEntity(portInfo: WorkflowPort): WorkflowPortEntity {\n const id = this.getPortId(portInfo.type, portInfo.portID);\n return this.getPortEntity(id) ?? this.createPortEntity(portInfo);\n }\n\n /**\n * 更新 port 实体\n */\n protected updatePortEntity(portInfo: WorkflowPort): WorkflowPortEntity {\n const portEntity = this.getOrCreatePortEntity(portInfo);\n if (portInfo.targetElement) {\n portEntity.updateTargetElement(portInfo.targetElement);\n }\n return portEntity;\n }\n}\n","import { type IPoint, Rectangle, Emitter } from '@flowgram.ai/utils';\nimport { FlowNodeTransformData } from '@flowgram.ai/document';\nimport {\n Entity,\n type EntityOpts,\n PlaygroundConfigEntity,\n TransformData,\n type EntityRegistry,\n} from '@flowgram.ai/core';\n\nimport { type WorkflowDocument } from '../workflow-document';\nimport {\n type WorkflowPortType,\n getPortEntityId,\n WORKFLOW_LINE_ENTITY,\n domReactToBounds,\n} from '../utils/statics';\nimport { type WorkflowNodeMeta } from '../typings';\nimport { type WorkflowNodeEntity } from './workflow-node-entity';\nimport { type WorkflowLineEntity } from './workflow-line-entity';\n\n// port 的宽度\nexport const PORT_SIZE = 24;\n\nexport interface WorkflowPort {\n /**\n * 没有代表 默认连接点,默认 input 类型 为最左边中心,output 类型为最右边中心\n */\n portID?: string | number;\n /**\n * 禁用端口\n */\n disabled?: boolean;\n /**\n * 将点位渲染到该父节点上\n */\n targetElement?: HTMLElement;\n /**\n * 输入或者输出点\n */\n type: WorkflowPortType;\n}\n\nexport type WorkflowPorts = WorkflowPort[];\n\nexport interface WorkflowPortEntityOpts extends EntityOpts, WorkflowPort {\n /**\n * port 属于哪个节点\n */\n node: WorkflowNodeEntity;\n}\n\n/**\n * Port 抽象的 Entity\n */\nexport class WorkflowPortEntity extends Entity<WorkflowPortEntityOpts> {\n static type = 'WorkflowPortEntity';\n\n readonly node: WorkflowNodeEntity;\n\n targetElement?: HTMLElement;\n\n readonly portID: string | number = '';\n\n readonly _disabled: boolean = false;\n\n private _hasError = false;\n\n protected readonly _onErrorChangedEmitter = new Emitter<void>();\n\n onErrorChanged = this._onErrorChangedEmitter.event;\n\n /**\n * port 类型\n */\n portType: WorkflowPortType;\n\n static getPortEntityId(\n node: WorkflowNodeEntity,\n portType: WorkflowPortType,\n portID: string | number = ''\n ): string {\n return getPortEntityId(node, portType, portID);\n }\n\n // relativePosition\n constructor(opts: WorkflowPortEntityOpts) {\n super(opts);\n this.portID = opts.portID || '';\n this.portType = opts.type;\n this._disabled = opts.disabled ?? false;\n this.node = opts.node;\n this.updateTargetElement(opts.targetElement);\n this.toDispose.push(this.node.getData(TransformData)!.onDataChange(() => this.fireChange()));\n this.toDispose.push(this.node.onDispose(this.dispose.bind(this)));\n }\n\n // 获取连线是否为错误态\n get hasError() {\n return this._hasError;\n }\n\n // 设置连线的错误态,外部应使用 validate 进行更新\n set hasError(hasError: boolean) {\n this._hasError = hasError;\n this._onErrorChangedEmitter.fire();\n }\n\n validate() {\n // 一个端口可能连接很多线,需要保证所有的连线都不包含错误\n const anyLineHasError = this.allLines.some((line) => {\n // 忽略已销毁和被隐藏的线\n if (line.disposed || line.isHidden) {\n return false;\n }\n\n // 保证 hasError 最新\n line.validateSelf();\n\n return line.hasError;\n });\n // 如果没有连线错误,需校验端口自身错误\n const isPortHasError = (this.node.document as WorkflowDocument).isErrorPort(this);\n this.hasError = anyLineHasError || isPortHasError;\n }\n\n isErrorPort() {\n return (this.node.document as WorkflowDocument).isErrorPort(this);\n }\n\n get point(): IPoint {\n const { targetElement } = this;\n const { bounds } = this.node.getData(FlowNodeTransformData)!;\n if (targetElement) {\n const pos = domReactToBounds(targetElement.getBoundingClientRect()).center;\n return this.entityManager\n .getEntity<PlaygroundConfigEntity>(PlaygroundConfigEntity)!\n .getPosFromMouseEvent({\n clientX: pos.x,\n clientY: pos.y,\n });\n }\n if (this.portType === 'input') {\n // 默认为左边重点\n return bounds.leftCenter;\n }\n return bounds.rightCenter;\n }\n\n /**\n * 点的区域\n */\n get bounds(): Rectangle {\n const { point } = this;\n const halfSize = PORT_SIZE / 2;\n return new Rectangle(point.x - halfSize, point.y - halfSize, PORT_SIZE, PORT_SIZE);\n }\n\n isHovered(x: number, y: number): boolean {\n return this.bounds.contains(x, y);\n }\n\n /**\n * 相对节点左上角的位置\n */\n get relativePosition(): IPoint {\n const { point } = this;\n const { bounds } = this.node.getData(FlowNodeTransformData)!;\n return {\n x: point.x - bounds.x,\n y: point.y - bounds.y,\n };\n }\n\n updateTargetElement(el?: HTMLElement): void {\n if (el !== this.targetElement) {\n this.targetElement = el;\n this.fireChange();\n }\n }\n\n /**\n * 是否被禁用\n */\n get disabled(): boolean {\n const document = this.node.document as WorkflowDocument;\n if (typeof document.options.isDisabledPort === 'function') {\n return document.options.isDisabledPort(this);\n }\n if (this._disabled) {\n return true;\n }\n const meta = this.node.getNodeMeta<WorkflowNodeMeta>();\n if (this.portType === 'input') {\n return !!meta.inputDisable;\n }\n return !!meta.outputDisable;\n }\n\n /**\n * 当前点位上连接的线条\n * @deprecated use `availableLines` instead\n */\n get lines(): WorkflowLineEntity[] {\n return this.allLines.filter((line) => !line.isDrawing);\n }\n\n /**\n * 当前有效的线条,不包含正在画的线条和隐藏的线条(这个出现在线条重连会先把原来的线条隐藏)\n */\n get availableLines(): WorkflowLineEntity[] {\n return this.allLines.filter((line) => !line.isDrawing && !line.isHidden);\n }\n\n /**\n * 当前点位上连接的线条(包含 isDrawing === true 的线条)\n */\n get allLines() {\n const lines: WorkflowLineEntity[] = [];\n // TODO: 后续 sdk 支持 getEntitiesByType 单独根据 type 获取功能后修改\n // eslint-disable-next-line @typescript-eslint/consistent-type-assertions\n const allLines = this.entityManager.getEntities<WorkflowLineEntity>({\n type: WORKFLOW_LINE_ENTITY,\n } as EntityRegistry);\n allLines.forEach((line) => {\n // 不包含 drawing 的线条\n if (line.toPort === this || line.fromPort === this) {\n lines.push(line);\n }\n });\n return lines;\n }\n\n dispose(): void {\n // 点位被删除,对应的线条也要删除\n this.lines.forEach((l) => l.dispose());\n super.dispose();\n }\n}\n","import { Disposable } from '@flowgram.ai/utils';\nimport { EntityData } from '@flowgram.ai/core';\n\nimport { type WorkflowLineEntity, type WorkflowNodeEntity } from '../entities';\n\nexport interface WorkflowNodeLines {\n inputLines: WorkflowLineEntity[];\n outputLines: WorkflowLineEntity[];\n}\n\n/**\n * 节点的关联的线条\n */\nexport class WorkflowNodeLinesData extends EntityData<WorkflowNodeLines> {\n static type = 'WorkflowNodeLinesData';\n\n entity: WorkflowNodeEntity;\n\n getDefaultData(): WorkflowNodeLines {\n return {\n inputLines: [],\n outputLines: [],\n };\n }\n\n constructor(entity: WorkflowNodeEntity) {\n super(entity);\n this.entity = entity;\n this.entity.preDispose.push(\n Disposable.create(() => {\n this.inputLines.slice().forEach((line) => line.dispose());\n this.outputLines.slice().forEach((line) => line.dispose());\n })\n );\n }\n\n /**\n * 输入线条\n */\n get inputLines(): WorkflowLineEntity[] {\n return this.data.inputLines;\n }\n\n /**\n * 输出线条\n */\n get outputLines(): WorkflowLineEntity[] {\n return this.data.outputLines;\n }\n\n /**\n * 输入节点\n */\n get inputNodes(): WorkflowNodeEntity[] {\n return this.inputLines.map((l) => l.from!).filter(Boolean);\n }\n\n /**\n * 所有输入节点\n */\n get allInputNodes(): WorkflowNodeEntity[] {\n const nodeSet: Set<WorkflowNodeEntity> = new Set();\n\n const handleNode = (node: WorkflowNodeEntity): void => {\n if (nodeSet.has(node)) {\n return;\n }\n\n nodeSet.add(node);\n\n const { inputNodes } = node.getData<WorkflowNodeLinesData>(WorkflowNodeLinesData)!;\n if (!inputNodes || !inputNodes.length) {\n return;\n }\n\n inputNodes.forEach((inputNode: WorkflowNodeEntity) => {\n // 如果 outputNode 和当前 node 是父子节点,则不向下遍历\n if (inputNode?.parent === node || node?.parent === inputNode) {\n return;\n }\n handleNode(inputNode);\n });\n };\n\n handleNode(this.entity);\n nodeSet.delete(this.entity);\n\n return Array.from(nodeSet);\n }\n\n /**\n * 输出节点\n */\n get outputNodes(): WorkflowNodeEntity[] {\n return this.outputLines.map((l) => l.to!).filter(Boolean);\n }\n\n /**\n * 输入输出节点\n */\n get allOutputNodes(): WorkflowNodeEntity[] {\n const nodeSet: Set<WorkflowNodeEntity> = new Set();\n\n const handleNode = (node: WorkflowNodeEntity): void => {\n if (nodeSet.has(node)) {\n return;\n }\n\n nodeSet.add(node);\n\n const { outputNodes } = node.getData<WorkflowNodeLinesData>(WorkflowNodeLinesData)!;\n if (!outputNodes || !outputNodes.length) {\n return;\n }\n\n outputNodes.forEach((outputNode: WorkflowNodeEntity) => {\n // 如果 outputNode 和当前 node 是父子节点,则不向下遍历\n if (outputNode?.parent === node || node?.parent === outputNode) {\n return;\n }\n handleNode(outputNode);\n });\n };\n\n handleNode(this.entity);\n nodeSet.delete(this.entity);\n\n return Array.from(nodeSet);\n }\n\n addLine(line: WorkflowLineEntity): void {\n if (line.from === this.entity) {\n this.outputLines.push(line);\n } else {\n this.inputLines.push(line);\n }\n this.fireChange();\n }\n\n removeLine(line: WorkflowLineEntity): void {\n const { inputLines, outputLines } = this;\n const inputIndex = inputLines.indexOf(line);\n const outputIndex = outputLines.indexOf(line);\n if (inputIndex !== -1) {\n inputLines.splice(inputIndex, 1);\n this.fireChange();\n }\n if (outputIndex !== -1) {\n outputLines.splice(outputIndex, 1);\n this.fireChange();\n }\n }\n}\n","import { IPoint, Rectangle } from '@flowgram.ai/utils';\nimport { EntityData } from '@flowgram.ai/core';\n\nimport {\n LinePosition,\n LineRenderType,\n WorkflowLineRenderContribution,\n WorkflowLineRenderContributionFactory,\n} from '../typings';\nimport { WorkflowLineEntity } from '../entities';\nimport { WorkflowNodePortsData } from './workflow-node-ports-data';\n\nexport interface WorkflowLineRenderDataSchema {\n version: string;\n contributions: Map<LineRenderType, WorkflowLineRenderContribution>;\n position: LinePosition;\n}\n\nexport class WorkflowLineRenderData extends EntityData<WorkflowLineRenderDataSchema> {\n static type = 'WorkflowLineRenderData';\n\n declare entity: WorkflowLineEntity;\n\n constructor(entity: WorkflowLineEntity) {\n super(entity);\n this.syncContributions();\n }\n\n public getDefaultData(): WorkflowLineRenderDataSchema {\n return {\n version: '',\n contributions: new Map(),\n position: {\n from: { x: 0, y: 0 },\n to: { x: 0, y: 0 },\n },\n };\n }\n\n public get renderVersion(): string {\n return this.data.version;\n }\n\n public get position(): LinePosition {\n return this.data.position;\n }\n\n public get path(): string {\n return this.currentLine?.path ?? '';\n }\n\n public calcDistance(pos: IPoint): number {\n return this.currentLine?.calcDistance(pos) ?? Number.MAX_SAFE_INTEGER;\n }\n\n public get bounds(): Rectangle {\n return this.currentLine?.bounds ?? new Rectangle();\n }\n\n /**\n * 更新数据\n * WARNING: 这个方法,必须在 requestAnimationFrame / useLayoutEffect 中调用,否则会引起浏览器强制重排\n */\n public update(): void {\n this.syncContributions();\n const oldVersion = this.data.version;\n this.updatePosition();\n const newVersion = this.data.version;\n if (oldVersion === newVersion) {\n return;\n }\n this.data.version = newVersion;\n this.currentLine?.update({\n fromPos: this.data.position.from,\n toPos: this.data.position.to,\n });\n }\n\n private get lineType(): LineRenderType {\n return this.entity.renderType ?? this.entity.linesManager.lineType;\n }\n\n /**\n * 更新版本\n * WARNING: 这个方法,必须在 requestAnimationFrame / useLayoutEffect 中调用,否则会引起浏览器强制重排\n */\n private updatePosition(): void {\n this.data.position.from = this.entity.from\n .getData(WorkflowNodePortsData)!\n .getOutputPoint(this.entity.info.fromPort);\n\n this.data.position.to = this.entity.info.drawingTo ??\n this.entity.to?.getData(WorkflowNodePortsData)?.getInputPoint(this.entity.info.toPort) ?? {\n x: this.data.position.from.x,\n y: this.data.position.from.y,\n };\n\n this.data.version = [\n this.lineType,\n this.data.position.from.x,\n this.data.position.from.y,\n this.data.position.to.x,\n this.data.position.to.y,\n ].join('-');\n }\n\n private get currentLine(): WorkflowLineRenderContribution | undefined {\n return this.data.contributions.get(this.lineType);\n }\n\n private syncContributions(): void {\n if (this.entity.linesManager.contributionFactories.length === this.data.contributions.size) {\n return;\n }\n this.entity.linesManager.contributionFactories.forEach((factory) => {\n this.registerContribution(factory);\n });\n }\n\n private registerContribution(contributionFactory: WorkflowLineRenderContributionFactory): void {\n if (this.data.contributions.has(contributionFactory.type)) {\n return;\n }\n const contribution = new contributionFactory(this.entity);\n this.data.contributions.set(contributionFactory.type, contribution);\n }\n}\n","import { inject, injectable } from 'inversify';\nimport { Emitter, type PositionSchema } from '@flowgram.ai/utils';\nimport { EntityManager } from '@flowgram.ai/core';\n\nimport {\n type WorkflowLineEntity,\n type WorkflowNodeEntity,\n type WorkflowPortEntity,\n} from '../entities';\n\n/**\n * 可 Hover 的节点 类型\n */\nexport type WorkflowEntityHoverable = WorkflowNodeEntity | WorkflowLineEntity | WorkflowPortEntity;\n\nexport interface HoverPosition {\n position: PositionSchema;\n target?: HTMLElement;\n}\n\n/** @deprecated */\nexport type WorkfloEntityHoverable = WorkflowEntityHoverable;\n/**\n * hover 状态管理\n */\n@injectable()\nexport class WorkflowHoverService {\n @inject(EntityManager) protected entityManager: EntityManager;\n\n protected onHoveredChangeEmitter = new Emitter<string>();\n\n protected onUpdateHoverPositionEmitter = new Emitter<HoverPosition>();\n\n readonly onHoveredChange = this.onHoveredChangeEmitter.event;\n\n readonly onUpdateHoverPosition = this.onUpdateHoverPositionEmitter.event;\n\n // 当前鼠标 hover 位置\n hoveredPos: PositionSchema = { x: 0, y: 0 };\n\n /**\n * 当前 hovered 的 节点或者线条或者点\n * 1: nodeId / lineId (节点 / 线条)\n * 2: nodeId:portKey (节点连接点)\n */\n hoveredKey = '';\n\n /**\n * 更新 hover 的内容\n * @param hoveredKey hovered key\n */\n updateHoveredKey(hoveredKey: string): void {\n if (this.hoveredKey !== hoveredKey) {\n this.hoveredKey = hoveredKey;\n this.onHoveredChangeEmitter.fire(hoveredKey);\n }\n }\n\n updateHoverPosition(position: PositionSchema, target?: HTMLElement): void {\n this.hoveredPos = position;\n this.onUpdateHoverPositionEmitter.fire({\n position,\n target,\n });\n }\n\n /**\n * 清空 hover 内容\n */\n clearHovered(): void {\n this.updateHoveredKey('');\n }\n\n /**\n * 判断是否 hover\n * @param nodeId hoveredKey\n * @returns 是否 hover\n */\n isHovered(nodeId: string): boolean {\n return nodeId === this.hoveredKey;\n }\n\n isSomeHovered(): boolean {\n return !!this.hoveredKey;\n }\n\n /**\n * 获取被 hover 的节点或线条\n */\n get hoveredNode(): WorkfloEntityHoverable | undefined {\n return this.entityManager.getEntityById(this.hoveredKey);\n }\n}\n","import type React from 'react';\n\nimport { nanoid } from 'nanoid';\nimport { inject, injectable, postConstruct } from 'inversify';\nimport {\n domUtils,\n type IPoint,\n PromiseDeferred,\n Emitter,\n type PositionSchema,\n DisposableCollection,\n Rectangle,\n delay,\n Disposable,\n} from '@flowgram.ai/utils';\nimport {\n FlowNodeTransformData,\n FlowNodeType,\n FlowOperationBaseService,\n type FlowNodeEntity,\n} from '@flowgram.ai/document';\nimport { FlowNodeBaseType } from '@flowgram.ai/document';\nimport {\n CommandService,\n MouseTouchEvent,\n PlaygroundConfigEntity,\n PlaygroundDrag,\n type PlaygroundDragEvent,\n TransformData,\n} from '@flowgram.ai/core';\n\nimport { WorkflowLinesManager } from '../workflow-lines-manager';\nimport { WorkflowDocumentOptions } from '../workflow-document-option';\nimport { WorkflowDocument } from '../workflow-document';\nimport { LineEventProps, NodesDragEvent, OnDragLineEnd } from '../typings/workflow-drag';\nimport { type WorkflowNodeJSON, type WorkflowNodeMeta } from '../typings';\nimport { WorkflowNodePortsData } from '../entity-datas';\nimport {\n type WorkflowLineEntity,\n type WorkflowLinePortInfo,\n type WorkflowNodeEntity,\n type WorkflowPortEntity,\n} from '../entities';\nimport { WorkflowSelectService } from './workflow-select-service';\nimport { WorkflowHoverService } from './workflow-hover-service';\n\nconst DRAG_TIMEOUT = 100;\nconst DRAG_MIN_DELTA = 5;\nfunction checkDragSuccess(\n time: number,\n e: PlaygroundDragEvent,\n originLine?: WorkflowLineEntity\n): boolean {\n if (\n !originLine ||\n time > DRAG_TIMEOUT ||\n Math.abs(e.endPos.x - e.startPos.x) >= DRAG_MIN_DELTA ||\n Math.abs(e.endPos.y - e.startPos.y) >= DRAG_MIN_DELTA\n ) {\n return true;\n }\n return false;\n}\n\n@injectable()\nexport class WorkflowDragService {\n @inject(PlaygroundConfigEntity)\n protected playgroundConfig: PlaygroundConfigEntity;\n\n @inject(WorkflowHoverService) protected hoverService: WorkflowHoverService;\n\n @inject(WorkflowDocument) protected document: WorkflowDocument;\n\n @inject(WorkflowLinesManager) protected linesManager: WorkflowLinesManager;\n\n @inject(CommandService) protected commandService: CommandService;\n\n @inject(WorkflowSelectService) protected selectService: WorkflowSelectService;\n\n @inject(FlowOperationBaseService)\n protected operationService: FlowOperationBaseService;\n\n @inject(WorkflowDocumentOptions)\n readonly options: WorkflowDocumentOptions;\n\n private _onDragLineEventEmitter = new Emitter<LineEventProps>();\n\n readonly onDragLineEventChange = this._onDragLineEventEmitter.event;\n\n isDragging = false;\n\n private _nodesDragEmitter = new Emitter<NodesDragEvent>();\n\n readonly onNodesDrag = this._nodesDragEmitter.event;\n\n protected _toDispose = new DisposableCollection();\n\n private _droppableTransforms: FlowNodeTransformData[] = [];\n\n private _dropNode?: FlowNodeEntity;\n\n private posAdjusters: Set<\n (params: { selectedNodes: WorkflowNodeEntity[]; position: IPoint }) => IPoint\n > = new Set();\n\n private _onDragLineEndCallbacks: Map<string, OnDragLineEnd> = new Map();\n\n @postConstruct()\n init() {\n this._toDispose.pushAll([this._onDragLineEventEmitter, this._nodesDragEmitter]);\n if (this.options.onDragLineEnd) {\n this._toDispose.push(this.onDragLineEnd(this.options.onDragLineEnd));\n }\n }\n\n dispose() {\n this._toDispose.dispose();\n }\n\n /**\n * 拖拽选中节点\n * @param triggerEvent\n */\n async startDragSelectedNodes(triggerEvent: MouseEvent | React.MouseEvent): Promise<boolean> {\n let { selectedNodes } = this.selectService;\n if (\n selectedNodes.length === 0 ||\n this.playgroundConfig.readonly ||\n this.playgroundConfig.disabled ||\n this.isDragging\n ) {\n return Promise.resolve(false);\n }\n this.isDragging = true;\n const sameParent = this.childrenOfContainer(selectedNodes);\n if (sameParent && sameParent.flowNodeType !== FlowNodeBaseType.ROOT) {\n selectedNodes = [sameParent];\n }\n // 节点整体开始位置\n let startPosition = this.getNodesPosition(selectedNodes);\n // 单个节点开始位置\n let startPositions = selectedNodes.map((node) => {\n const transform = node.getData(TransformData);\n return { x: transform.position.x, y: transform.position.y };\n });\n let dragSuccess = false;\n const startTime = Date.now();\n const dragger = new PlaygroundDrag({\n onDragStart: (dragEvent) => {\n this._nodesDragEmitter.fire({\n type: 'onDragStart',\n nodes: selectedNodes,\n startPositions,\n dragEvent,\n triggerEvent,\n dragger,\n });\n },\n onDrag: (dragEvent) => {\n if (!dragSuccess && checkDragSuccess(Date.now() - startTime, dragEvent)) {\n dragSuccess = true;\n }\n\n // 计算拖拽偏移量\n const offset: IPoint = this.getDragPosOffset({\n event: dragEvent,\n selectedNodes,\n startPosition,\n });\n\n const positions: PositionSchema[] = [];\n\n selectedNodes.forEach((node, index) => {\n const transform = node.getData(TransformData);\n const nodeStartPosition = startPositions[index];\n const newPosition = {\n x: nodeStartPosition.x + offset.x,\n y: nodeStartPosition.y + offset.y,\n };\n transform.update({\n position: newPosition,\n });\n this.document.layout.updateAffectedTransform(node);\n positions.push(newPosition);\n });\n\n this._nodesDragEmitter.fire({\n type: 'onDragging',\n nodes: selectedNodes,\n startPositions,\n positions,\n dragEvent,\n triggerEvent,\n dragger,\n });\n },\n onDragEnd: (dragEvent) => {\n this.isDragging = false;\n this._nodesDragEmitter.fire({\n type: 'onDragEnd',\n nodes: selectedNodes,\n startPositions,\n dragEvent,\n triggerEvent,\n dragger,\n });\n },\n });\n const { clientX, clientY } = MouseTouchEvent.getEventCoord(triggerEvent);\n return dragger.start(clientX, clientY, this.playgroundConfig)?.then(() => dragSuccess);\n }\n\n /**\n * 通过拖入卡片添加\n * @param type\n * @param event\n * @param data 节点数据\n */\n async dropCard(\n type: string,\n event: { clientX: number; clientY: number },\n data?: Partial<WorkflowNodeJSON>,\n parent?: WorkflowNodeEntity\n ): Promise<WorkflowNodeEntity | undefined> {\n const mousePos = this.playgroundConfig.getPosFromMouseEvent(event);\n if (!this.playgroundConfig.getViewport().contains(mousePos.x, mousePos.y)) {\n // 鼠标范围不在画布之内\n return;\n }\n const position = this.adjustSubNodePosition(type, parent, mousePos);\n\n const node: WorkflowNodeEntity = await this.document.createWorkflowNodeByType(\n type,\n position,\n data,\n parent?.id\n );\n return node;\n }\n\n /**\n * 拖拽卡片到画布\n * 返回创建结果\n * @param type\n * @param event\n */\n async startDragCard(\n type: string,\n event: React.MouseEvent,\n data: Partial<WorkflowNodeJSON>,\n cloneNode?: (e: PlaygroundDragEvent) => HTMLDivElement // 创建拖拽的dom\n ): Promise<WorkflowNodeEntity | undefined> {\n let domNode: HTMLDivElement;\n let startPos: IPoint = { x: 0, y: 0 };\n const deferred = new PromiseDeferred<WorkflowNodeEntity | undefined>();\n const dragger = new PlaygroundDrag({\n onDragStart: (e) => {\n const targetNode = event.currentTarget as HTMLDivElement;\n domNode = cloneNode ? cloneNode(e) : (targetNode.cloneNode(true) as HTMLDivElement);\n const bounds = targetNode.getBoundingClientRect();\n startPos = { x: bounds.left, y: bounds.top };\n domUtils.setStyle(domNode, {\n zIndex: 1000,\n position: 'absolute',\n left: startPos.x,\n top: startPos.y,\n boxShadow: '0 6px 8px 0 rgba(28, 31, 35, .2)',\n });\n document.body.appendChild(domNode);\n this.updateDroppableTransforms();\n },\n onDrag: (e) => {\n const deltaX = e.endPos.x - e.startPos.x;\n const deltaY = e.endPos.y - e.startPos.y;\n const left = startPos.x + deltaX;\n const right = startPos.y + deltaY;\n domNode.style.left = `${left}px`;\n domNode.style.top = `${right}px`;\n // 节点类型拖拽碰撞检测\n const { x, y } = this.playgroundConfig.getPosFromMouseEvent(e);\n const draggingRect = new Rectangle(x, y, 170, 90);\n const collisionTransform = this._droppableTransforms.find((transform) => {\n const { bounds, entity } = transform;\n const padding = this.document.layout.getPadding(entity);\n const transformRect = new Rectangle(\n bounds.x + padding.left + padding.right,\n bounds.y,\n bounds.width,\n bounds.height\n );\n // 检测两个正方形是否相互碰撞\n return Rectangle.intersects(draggingRect, transformRect);\n });\n this.updateDropNode(collisionTransform?.entity);\n },\n onDragEnd: async (e) => {\n const dropNode = this._dropNode;\n const { allowDrop } = this.canDropToNode({\n dragNodeType: type,\n dropNode,\n });\n const dragNode = allowDrop ? await this.dropCard(type, e, data, dropNode) : undefined;\n this.clearDrop();\n if (dragNode) {\n domNode.remove();\n deferred.resolve(dragNode);\n } else {\n domNode.style.transition = 'all ease .2s';\n domNode.style.left = `${startPos.x}px`;\n domNode.style.top = `${startPos.y}px`;\n const TIMEOUT = 200;\n await delay(TIMEOUT);\n domNode.remove();\n deferred.resolve();\n }\n },\n });\n await dragger.start(event.clientX, event.clientY);\n return deferred.promise;\n }\n\n /**\n * 如果存在容器节点,且传入鼠标坐标,需要用容器的坐标减去传入的鼠标坐标\n */\n public adjustSubNodePosition(\n subNodeType?: string,\n containerNode?: WorkflowNodeEntity,\n mousePos?: IPoint,\n resetEmptyPos: boolean = true\n ): IPoint {\n if (!mousePos) {\n return { x: 0, y: 0 };\n }\n if (!subNodeType || !containerNode || containerNode.flowNodeType === FlowNodeBaseType.ROOT) {\n return mousePos;\n }\n const isParentEmpty = !containerNode.children || containerNode.children.length === 0;\n const parentPadding = this.document.layout.getPadding(containerNode);\n const parentTransform = containerNode.getData<TransformData>(TransformData);\n if (isParentEmpty && resetEmptyPos) {\n // 确保空容器节点不偏移\n return {\n x: 0,\n y: parentPadding.top,\n };\n } else {\n return {\n x: mousePos.x - parentTransform.position.x,\n y: mousePos.y - parentTransform.position.y,\n };\n }\n }\n\n /**\n * 注册位置调整\n */\n public registerPosAdjuster(\n adjuster: (params: { selectedNodes: WorkflowNodeEntity[]; position: IPoint }) => IPoint\n ) {\n this.posAdjusters.add(adjuster);\n return {\n dispose: () => this.posAdjusters.delete(adjuster),\n };\n }\n\n /**\n * 判断是否可以放置节点\n */\n public canDropToNode(params: { dragNodeType?: FlowNodeType; dropNode?: WorkflowNodeEntity }): {\n allowDrop: boolean;\n message?: string;\n dropNode?: WorkflowNodeEntity;\n } {\n const { dragNodeType, dropNode } = params;\n if (!dragNodeType) {\n return {\n allowDrop: false,\n message: 'Please select a node to drop',\n };\n }\n return {\n allowDrop: true,\n dropNode,\n };\n }\n\n /**\n * 获取拖拽偏移\n */\n private getDragPosOffset(params: {\n event: PlaygroundDragEvent;\n selectedNodes: WorkflowNodeEntity[];\n startPosition: IPoint;\n }) {\n const { event, selectedNodes, startPosition } = params;\n const { finalScale } = this.playgroundConfig;\n const mouseOffset: IPoint = {\n x: (event.endPos.x - event.startPos.x) / finalScale,\n y: (event.endPos.y - event.startPos.y) / finalScale,\n };\n const wholePosition: IPoint = {\n x: startPosition.x + mouseOffset.x,\n y: startPosition.y + mouseOffset.y,\n };\n const adjustedOffsets: IPoint[] = Array.from(this.posAdjusters.values()).map((adjuster) =>\n adjuster({\n selectedNodes,\n position: wholePosition,\n })\n );\n const offset: IPoint = adjustedOffsets.reduce(\n (offset, adjustOffset) => ({\n x: offset.x + adjustOffset.x,\n y: offset.y + adjustOffset.y,\n }),\n mouseOffset\n );\n return offset;\n }\n\n private updateDroppableTransforms() {\n this._droppableTransforms = this.document\n .getRenderDatas(FlowNodeTransformData, false)\n .filter((transform) => {\n const { entity } = transform;\n if (entity.originParent) {\n return this.nodeSelectable(entity) && this.nodeSelectable(entity.originParent);\n }\n return this.nodeSelectable(entity);\n })\n .filter((transform) => this.isContainer(transform.entity));\n }\n\n /** 是否容器节点 */\n private isContainer(node?: WorkflowNodeEntity): boolean {\n return node?.getNodeMeta<WorkflowNodeMeta>().isContainer ?? false;\n }\n\n /**\n * 获取节点整体位置\n */\n private getNodesPosition(nodes: WorkflowNodeEntity[]): IPoint {\n const selectedBounds = Rectangle.enlarge(\n nodes.map((n) => n.getData(FlowNodeTransformData)!.bounds)\n );\n const position: IPoint = {\n x: selectedBounds.x,\n y: selectedBounds.y,\n };\n return position;\n }\n\n private nodeSelectable(node: FlowNodeEntity) {\n const selectable = node.getNodeMeta().selectable;\n if (typeof selectable === 'function') {\n return selectable(node);\n } else {\n return selectable;\n }\n }\n\n private updateDropNode(node?: FlowNodeEntity) {\n if (this._dropNode) {\n if (this._dropNode.id === node?.id) {\n return;\n }\n this.selectService.clear();\n }\n if (node) {\n this.selectService.selectNode(node);\n }\n this._dropNode = node;\n }\n\n private clearDrop() {\n if (this._dropNode) {\n this.selectService.clear();\n }\n this._dropNode = undefined;\n this._droppableTransforms = [];\n }\n\n private setLineColor(line: WorkflowLineEntity, color: string) {\n line.highlightColor = color;\n this.hoverService.clearHovered();\n }\n\n private handleDragOnNode(\n toNode: WorkflowNodeEntity,\n fromPort: WorkflowPortEntity,\n line: WorkflowLineEntity,\n toPort?: WorkflowPortEntity,\n originLine?: WorkflowLineEntity\n ): {\n hasError: boolean;\n } {\n if (\n toPort &&\n (originLine?.toPort === toPort ||\n (toPort.portType === 'input' && this.linesManager.canAddLine(fromPort, toPort, true)))\n ) {\n // 同一条线条则不用在判断 canAddLine\n this.hoverService.updateHoveredKey(toPort.id);\n line.setToPort(toPort);\n this._onDragLineEventEmitter.fire({\n type: 'onDrag',\n onDragNodeId: toNode.id,\n });\n return {\n hasError: false,\n };\n } else if (this.isContainer(toNode)) {\n // 在容器内进行连线的情况,需忽略\n return {\n hasError: false,\n };\n } else {\n this.setLineColor(line, this.linesManager.lineColor.error);\n return {\n hasError: true,\n };\n }\n }\n\n private childrenOfContainer(nodes: WorkflowNodeEntity[]): WorkflowNodeEntity | undefined {\n if (nodes.length === 0) {\n return;\n }\n const sourceContainer = nodes[0]?.parent;\n if (!sourceContainer || sourceContainer.collapsedChildren.length !== nodes.length) {\n return;\n }\n const valid = nodes.every((node) => node?.parent === sourceContainer);\n if (!valid) {\n return;\n }\n return sourceContainer;\n }\n\n /**\n * 绘制线条\n * @param opts\n * @param event\n */\n async startDrawingLine(\n fromPort: WorkflowPortEntity,\n event: { clientX: number; clientY: number },\n originLine?: WorkflowLineEntity\n ): Promise<{\n dragSuccess?: boolean; // 是否拖拽成功,不成功则为选择节点\n newLine?: WorkflowLineEntity; // 新的线条\n }> {\n const isFromInActivePort = !originLine && fromPort.isErrorPort() && fromPort.disabled;\n if (\n originLine?.disabled ||\n isFromInActivePort ||\n this.playgroundConfig.readonly ||\n this.playgroundConfig.disabled\n ) {\n return { dragSuccess: false, newLine: undefined };\n }\n\n this.selectService.clear();\n const config = this.playgroundConfig;\n const deferred = new PromiseDeferred<{\n dragSuccess?: boolean;\n newLine?: WorkflowLineEntity; // 新的线条\n }>();\n const preCursor = config.cursor;\n let line: WorkflowLineEntity | undefined,\n toPort: WorkflowPortEntity | undefined,\n toNode: WorkflowNodeEntity | undefined,\n lineErrorReset = false;\n const startTime = Date.now();\n let dragSuccess = false;\n const dragger = new PlaygroundDrag({\n onDrag: (e) => {\n if (!line && checkDragSuccess(Date.now() - startTime, e, originLine)) {\n // 隐藏原来的线条\n if (originLine) {\n originLine.highlightColor = this.linesManager.lineColor.hidden;\n }\n dragSuccess = true;\n // 创建临时的线条\n line = this.linesManager.createLine({\n from: fromPort.node.id,\n fromPort: fromPort.portID,\n drawingTo: config.getPosFromMouseEvent(event),\n });\n if (!line) {\n return;\n }\n config.updateCursor('grab');\n line.highlightColor = this.linesManager.lineColor.drawing;\n this.hoverService.updateHoveredKey('');\n }\n if (!line) {\n return;\n }\n\n lineErrorReset = false;\n\n const dragPos = config.getPosFromMouseEvent(e);\n\n // 默认 toNode 获取\n toNode = this.linesManager.getNodeFromMousePos(dragPos);\n // 默认 toPort 获取\n toPort = this.linesManager.getPortFromMousePos(dragPos);\n\n if (!toPort) {\n line.setToPort(undefined);\n } else if (!this.linesManager.canAddLine(fromPort, toPort, true)) {\n line.highlightColor = this.linesManager.lineColor.error;\n lineErrorReset = true;\n line.setToPort(undefined);\n } else {\n line.setToPort(toPort);\n }\n\n this._onDragLineEventEmitter.fire({\n type: 'onDrag',\n });\n\n this.setLineColor(line, this.linesManager.lineColor.drawing);\n if (toNode && !this.isContainer(toNode)) {\n // 如果鼠标 hover 在 node 中的时候,默认连线到这个 node 的初始位置\n const portsData = toNode.getData(WorkflowNodePortsData)!;\n const { inputPorts } = portsData;\n if (inputPorts.length === 1) {\n toPort = inputPorts[0];\n }\n const { hasError } = this.handleDragOnNode(toNode, fromPort, line, toPort, originLine);\n lineErrorReset = hasError;\n }\n\n if (line.toPort) {\n line.drawingTo = { x: line.toPort.point.x, y: line.toPort.point.y };\n } else {\n line.drawingTo = { x: dragPos.x, y: dragPos.y };\n }\n\n // 触发原 toPort 的校验\n originLine?.validate();\n line.validate();\n },\n // eslint-disable-next-line complexity\n onDragEnd: async (e) => {\n const dragPos = config.getPosFromMouseEvent(e);\n const onDragLineEndCallbacks = Array.from(this._onDragLineEndCallbacks.values());\n config.updateCursor(preCursor);\n await Promise.all(\n onDragLineEndCallbacks.map((callback) =>\n callback({\n fromPort,\n toPort,\n mousePos: dragPos,\n line,\n originLine,\n event: e,\n })\n )\n );\n line?.dispose();\n this._onDragLineEventEmitter.fire({\n type: 'onDragEnd',\n });\n // 清除选中状态\n if (originLine) {\n originLine.highlightColor = '';\n }\n const end = () => {\n originLine?.validate();\n deferred.resolve({ dragSuccess });\n };\n if (dragSuccess) {\n // Step 1: check same line\n if (originLine && originLine.toPort === toPort) {\n // 线条没变化则直接返回,不做处理\n return end();\n }\n // 非 input 节点不能连接\n if (toPort && toPort.portType !== 'input') {\n return end();\n }\n const newLineInfo: Required<WorkflowLinePortInfo> | undefined = toPort\n ? {\n from: fromPort.node.id,\n fromPort: fromPort.portID,\n to: toPort.node.id,\n toPort: toPort.portID,\n }\n : undefined;\n // Step2: 检测 reset\n const isReset = originLine && toPort;\n if (\n isReset &&\n !this.linesManager.canReset(\n originLine.fromPort,\n originLine.toPort as WorkflowPortEntity,\n toPort as WorkflowPortEntity\n )\n ) {\n return end();\n }\n // Step 3: delete line\n if (\n originLine &&\n (!this.linesManager.canRemove(originLine, newLineInfo, false) || lineErrorReset)\n ) {\n // 线条无法删除则返回,不再触发 canAddLine\n return end();\n } else {\n originLine?.dispose();\n }\n // Step 4: add line\n if (!toPort || !this.linesManager.canAddLine(fromPort, toPort, false)) {\n // 无法添加成功\n return end();\n }\n const newLine = this.linesManager.createLine(newLineInfo as WorkflowLinePortInfo);\n if (!newLine) {\n end();\n }\n deferred.resolve({\n dragSuccess,\n newLine,\n });\n } else {\n end();\n }\n },\n });\n const { clientX, clientY } = MouseTouchEvent.getEventCoord(event);\n await dragger.start(clientX, clientY, config);\n return deferred.promise;\n }\n\n /**\n * 重新连接线条\n * @param line\n * @param e\n */\n async resetLine(line: WorkflowLineEntity, e: MouseEvent): Promise<void> {\n const { fromPort } = line;\n const { dragSuccess } = await this.startDrawingLine(fromPort, e, line);\n if (!dragSuccess) {\n // 没有拖拽成功则表示为选中节点\n this.selectService.select(line);\n }\n }\n\n /** 线条拖拽结束 */\n public onDragLineEnd(callback: OnDragLineEnd): Disposable {\n const id = nanoid();\n this._onDragLineEndCallbacks.set(id, callback);\n return {\n dispose: () => {\n this._onDragLineEndCallbacks.delete(id);\n },\n };\n }\n}\n","import { last } from 'lodash-es';\nimport { inject, injectable } from 'inversify';\nimport { DisposableCollection, Emitter, type IPoint } from '@flowgram.ai/utils';\nimport { FlowNodeRenderData, FlowNodeTransformData } from '@flowgram.ai/document';\nimport { EntityManager, PlaygroundConfigEntity, TransformData } from '@flowgram.ai/core';\n\nimport { WorkflowDocumentOptions } from './workflow-document-option';\nimport { type WorkflowDocument } from './workflow-document';\nimport {\n LineColor,\n LineColors,\n LineRenderType,\n LineType,\n type WorkflowLineRenderContributionFactory,\n} from './typings/workflow-line';\nimport {\n type WorkflowContentChangeEvent,\n WorkflowContentChangeType,\n type WorkflowEdgeJSON,\n} from './typings';\nimport { WorkflowHoverService, WorkflowSelectService } from './service';\nimport { WorkflowNodeLinesData } from './entity-datas/workflow-node-lines-data';\nimport { WorkflowLineRenderData } from './entity-datas';\nimport {\n LINE_HOVER_DISTANCE,\n WorkflowLineEntity,\n type WorkflowLinePortInfo,\n type WorkflowNodeEntity,\n WorkflowPortEntity,\n} from './entities';\n\n/**\n * 线条管理\n */\n@injectable()\nexport class WorkflowLinesManager {\n protected document: WorkflowDocument;\n\n protected toDispose = new DisposableCollection();\n // 线条类型\n\n protected _lineType: LineRenderType = LineType.BEZIER;\n\n protected onAvailableLinesChangeEmitter = new Emitter<WorkflowContentChangeEvent>();\n\n protected onForceUpdateEmitter = new Emitter<void>();\n\n @inject(WorkflowHoverService) hoverService: WorkflowHoverService;\n\n @inject(WorkflowSelectService) selectService: WorkflowSelectService;\n\n @inject(EntityManager) protected readonly entityManager: EntityManager;\n\n @inject(WorkflowDocumentOptions)\n readonly options: WorkflowDocumentOptions;\n\n /**\n * 有效的线条被添加或者删除时候触发,未连上的线条不算\n */\n readonly onAvailableLinesChange = this.onAvailableLinesChangeEmitter.event;\n\n /**\n * 强制渲染 lines\n */\n readonly onForceUpdate = this.onForceUpdateEmitter.event;\n\n readonly contributionFactories: WorkflowLineRenderContributionFactory[] = [];\n\n init(doc: WorkflowDocument): void {\n this.document = doc;\n }\n\n forceUpdate() {\n this.onForceUpdateEmitter.fire();\n }\n\n get lineType() {\n return this._lineType;\n }\n\n get lineColor(): LineColor {\n const color: LineColor = {\n default: LineColors.DEFUALT,\n error: LineColors.ERROR,\n hidden: LineColors.HIDDEN,\n drawing: LineColors.DRAWING,\n hovered: LineColors.HOVER,\n selected: LineColors.SELECTED,\n flowing: LineColors.FLOWING,\n };\n if (this.options.lineColor) {\n Object.assign(color, this.options.lineColor);\n }\n return color;\n }\n\n switchLineType(newType?: LineRenderType): LineRenderType {\n if (newType === undefined) {\n if (this._lineType === LineType.BEZIER) {\n newType = LineType.LINE_CHART;\n } else {\n newType = LineType.BEZIER;\n }\n }\n if (newType !== this._lineType) {\n this._lineType = newType;\n // 更新线条数据\n this.getAllLines().forEach((line) => {\n line.getData(WorkflowLineRenderData).update();\n });\n window.requestAnimationFrame(() => {\n // 触发线条重渲染\n this.entityManager.fireEntityChanged(WorkflowLineEntity.type);\n });\n }\n return this._lineType;\n }\n\n getAllLines(): WorkflowLineEntity[] {\n return this.entityManager.getEntities(WorkflowLineEntity);\n }\n\n hasLine(portInfo: WorkflowLinePortInfo): boolean {\n return !!this.entityManager.getEntityById<WorkflowLineEntity>(\n WorkflowLineEntity.portInfoToLineId(portInfo)\n );\n }\n\n getLine(portInfo: WorkflowLinePortInfo): WorkflowLineEntity | undefined {\n return this.entityManager.getEntityById<WorkflowLineEntity>(\n WorkflowLineEntity.portInfoToLineId(portInfo)\n );\n }\n\n replaceLine(\n oldPortInfo: WorkflowLinePortInfo,\n newPortInfo: WorkflowLinePortInfo\n ): WorkflowLineEntity {\n const oldLine = this.getLine(oldPortInfo);\n if (oldLine) {\n oldLine.dispose();\n }\n return this.createLine(newPortInfo)!;\n }\n\n createLine(\n options: {\n drawingTo?: IPoint; // 无连接的线条\n key?: string; // 自定义 key\n } & WorkflowLinePortInfo\n ): WorkflowLineEntity | undefined {\n const { from, to, drawingTo, fromPort, toPort } = options;\n const available = Boolean(from && to);\n const key = options.key || WorkflowLineEntity.portInfoToLineId(options);\n let line = this.entityManager.getEntityById<WorkflowLineEntity>(key)!;\n if (line) {\n // 如果之前有线条,则先把颜色去掉\n line.highlightColor = '';\n line.validate();\n return line;\n }\n\n const fromNode = this.entityManager\n .getEntityById<WorkflowNodeEntity>(from)\n ?.getData<WorkflowNodeLinesData>(WorkflowNodeLinesData);\n const toNode = to\n ? this.entityManager\n .getEntityById<WorkflowNodeEntity>(to)!\n .getData<WorkflowNodeLinesData>(WorkflowNodeLinesData)!\n : undefined;\n\n if (!fromNode) {\n // 非法情况\n return;\n }\n\n this.isDrawing = Boolean(drawingTo);\n line = this.entityManager.createEntity<WorkflowLineEntity>(WorkflowLineEntity, {\n id: key,\n document: this.document,\n linesManager: this,\n from,\n fromPort,\n toPort,\n to,\n drawingTo,\n });\n\n this.registerData(line);\n\n fromNode.addLine(line);\n toNode?.addLine(line);\n line.onDispose(() => {\n if (drawingTo) {\n this.isDrawing = false;\n }\n fromNode.removeLine(line);\n toNode?.removeLine(line);\n // 连线销毁时检验 连线错误态 & 端口错误态\n line.validate();\n });\n line.onDispose(() => {\n if (available) {\n this.onAvailableLinesChangeEmitter.fire({\n type: WorkflowContentChangeType.DELETE_LINE,\n toJSON: () => line.toJSON(),\n entity: line,\n });\n }\n });\n // 是否为有效的线条\n if (available) {\n this.onAvailableLinesChangeEmitter.fire({\n type: WorkflowContentChangeType.ADD_LINE,\n toJSON: () => line.toJSON(),\n entity: line,\n });\n }\n // 创建时检验 连线错误态 & 端口错误态\n line.validate();\n return line;\n }\n\n /**\n * 获取线条中距离鼠标位置最近的线条和距离\n * @param mousePos 鼠标位置\n * @param minDistance 最小检测距离\n * @returns 距离鼠标位置最近的线条 以及距离\n */\n getCloseInLineFromMousePos(\n mousePos: IPoint,\n minDistance: number = LINE_HOVER_DISTANCE\n ): WorkflowLineEntity | undefined {\n let targetLine: WorkflowLineEntity | undefined, targetLineDist: number | undefined;\n this.getAllLines().forEach((line) => {\n const dist = line.getHoverDist(mousePos);\n\n if (dist <= minDistance && (!targetLineDist || targetLineDist >= dist)) {\n targetLineDist = dist;\n targetLine = line;\n }\n });\n return targetLine;\n }\n\n /**\n * 是否在调整线条\n */\n isDrawing = false;\n\n dispose(): void {\n this.toDispose.dispose();\n }\n\n get disposed(): boolean {\n return this.toDispose.disposed;\n }\n\n isErrorLine(fromPort: WorkflowPortEntity, toPort?: WorkflowPortEntity) {\n if (this.options.isErrorLine) {\n return this.options.isErrorLine(fromPort, toPort, this);\n }\n\n return false;\n }\n\n isReverseLine(line: WorkflowLineEntity): boolean {\n if (this.options.isReverseLine) {\n return this.options.isReverseLine(line);\n }\n\n return false;\n }\n\n isHideArrowLine(line: WorkflowLineEntity): boolean {\n if (this.options.isHideArrowLine) {\n return this.options.isHideArrowLine(line);\n }\n\n return false;\n }\n\n isFlowingLine(line: WorkflowLineEntity): boolean {\n if (this.options.isFlowingLine) {\n return this.options.isFlowingLine(line);\n }\n\n return false;\n }\n\n isDisabledLine(line: WorkflowLineEntity): boolean {\n if (this.options.isDisabledLine) {\n return this.options.isDisabledLine(line);\n }\n return false;\n }\n\n isVerticalLine(line: WorkflowLineEntity): boolean {\n if (this.options.isVerticalLine) {\n return this.options.isVerticalLine(line);\n }\n\n return false;\n }\n\n setLineRenderType(line: WorkflowLineEntity): LineRenderType | undefined {\n if (this.options.setLineRenderType) {\n return this.options.setLineRenderType(line);\n }\n return undefined;\n }\n\n setLineClassName(line: WorkflowLineEntity): string | undefined {\n if (this.options.setLineClassName) {\n return this.options.setLineClassName(line);\n }\n return undefined;\n }\n\n getLineColor(line: WorkflowLineEntity): string | undefined {\n // 隐藏的优先级比 hasError 高\n if (line.isHidden) {\n return this.lineColor.hidden;\n }\n if (line.hasError) {\n return this.lineColor.error;\n }\n if (line.highlightColor) {\n return line.highlightColor;\n }\n if (line.drawingTo) {\n return this.lineColor.drawing;\n }\n if (this.hoverService.isHovered(line.id)) {\n return this.lineColor.hovered;\n }\n if (this.selectService.isSelected(line.id)) {\n return this.lineColor.selected;\n }\n // 检查是否为流动线条\n if (this.isFlowingLine(line)) {\n return this.lineColor.flowing;\n }\n return this.lineColor.default;\n }\n\n canAddLine(fromPort: WorkflowPortEntity, toPort: WorkflowPortEntity, silent?: boolean): boolean {\n if (\n fromPort === toPort ||\n fromPort.node === toPort.node ||\n fromPort.portType !== 'output' ||\n toPort.portType !== 'input' ||\n toPort.disabled\n ) {\n return false;\n }\n if (this.options.canAddLine) {\n return this.options.canAddLine(fromPort, toPort, this, silent);\n }\n // 默认不能连接自己\n return fromPort.node !== toPort.node;\n }\n\n toJSON(): WorkflowEdgeJSON[] {\n return this.getAllLines()\n .filter((l) => !l.isDrawing)\n .map((l) => l.toJSON());\n }\n\n getPortById(portId: string): WorkflowPortEntity | undefined {\n return this.entityManager.getEntityById<WorkflowPortEntity>(portId);\n }\n\n canRemove(\n line: WorkflowLineEntity,\n newLineInfo?: Required<WorkflowLinePortInfo>,\n silent?: boolean\n ): boolean {\n if (\n this.options &&\n this.options.canDeleteLine &&\n !this.options.canDeleteLine(line, newLineInfo, silent)\n ) {\n return false;\n }\n return true;\n }\n\n canReset(\n fromPort: WorkflowPortEntity,\n oldToPort: WorkflowPortEntity,\n newToPort: WorkflowPortEntity\n ): boolean {\n if (\n this.options &&\n this.options.canResetLine &&\n !this.options.canResetLine(fromPort, oldToPort, newToPort, this)\n ) {\n return false;\n }\n return true;\n }\n\n /**\n * 根据鼠标位置找到 port\n * @param pos\n */\n getPortFromMousePos(pos: IPoint): WorkflowPortEntity | undefined {\n const allPorts = this.entityManager\n .getEntities<WorkflowPortEntity>(WorkflowPortEntity)\n .filter((port) => port.node.flowNodeType !== 'root');\n const targetPort = allPorts.find((port) => port.isHovered(pos.x, pos.y));\n if (targetPort) {\n // 后创建的要先校验\n const targetNode = this.document\n .getAllNodes()\n .slice()\n .reverse()\n .filter((node) => targetPort.node?.parent?.id !== node.id)\n .find((node) => node.getData(TransformData)!.contains(pos.x, pos.y));\n // 点位可能会被节点覆盖\n if (targetNode && targetNode !== targetPort.node) {\n return;\n }\n }\n return targetPort;\n }\n\n /**\n * 根据鼠标位置找到 node\n * @param pos - 鼠标位置\n */\n getNodeFromMousePos(pos: IPoint): WorkflowNodeEntity | undefined {\n const allNodes = this.document\n .getAllNodes()\n .sort((a, b) => this.getNodeIndex(a) - this.getNodeIndex(b));\n // 先挑选出 bounds 区域符合的 node\n const containNodes: WorkflowNodeEntity[] = [];\n const { selection } = this.selectService;\n const zoom =\n this.entityManager.getEntity<PlaygroundConfigEntity>(PlaygroundConfigEntity)?.config?.zoom ||\n 1;\n allNodes.forEach((node) => {\n const { bounds } = node.getData<FlowNodeTransformData>(FlowNodeTransformData);\n // 交互要求,节点边缘 4px 的时候就生效连线逻辑\n if (\n bounds\n .clone()\n .pad(4 / zoom)\n .contains(pos.x, pos.y)\n ) {\n containNodes.push(node);\n }\n });\n // 当有元素被选中的时候选中元素在顶层\n if (selection?.length) {\n const filteredNodes = containNodes.filter((node) =>\n selection.some((_node) => node.id === _node.id)\n );\n if (filteredNodes?.length) {\n return last(filteredNodes);\n }\n }\n // 默认取最顶层的\n return last(containNodes);\n }\n\n registerContribution(factory: WorkflowLineRenderContributionFactory): this {\n this.contributionFactories.push(factory);\n return this;\n }\n\n private registerData(line: WorkflowLineEntity) {\n line.addData(WorkflowLineRenderData);\n }\n\n private getNodeIndex(node: WorkflowNodeEntity): number {\n const nodeRenderData = node.getData(FlowNodeRenderData);\n return nodeRenderData.stackIndex;\n }\n}\n","import { FlowNodeErrorData } from '@flowgram.ai/form-core';\nimport { FlowDocumentOptions, FlowNodeTransformData } from '@flowgram.ai/document';\nimport { TransformData } from '@flowgram.ai/core';\n\nimport { type WorkflowLinesManager } from './workflow-lines-manager';\nimport { initFormDataFromJSON, toFormJSON } from './utils/flow-node-form-data';\nimport {\n LineColor,\n LineRenderType,\n onDragLineEndParams,\n WorkflowNodeJSON,\n WorkflowNodeMeta,\n} from './typings';\nimport {\n type WorkflowLineEntity,\n type WorkflowLinePortInfo,\n type WorkflowNodeEntity,\n type WorkflowPortEntity,\n} from './entities';\n\nexport const WorkflowDocumentOptions = Symbol('WorkflowDocumentOptions');\n\n/**\n * 线条配置\n */\nexport interface WorkflowDocumentOptions extends FlowDocumentOptions {\n cursors?: {\n grab?: string;\n grabbing?: string;\n };\n /** 线条颜色 */\n lineColor?: Partial<LineColor>;\n /** 是否显示错误线条 */\n isErrorLine?: (\n fromPort: WorkflowPortEntity,\n toPort: WorkflowPortEntity | undefined,\n lines: WorkflowLinesManager\n ) => boolean;\n /** 是否错误端口 */\n isErrorPort?: (port: WorkflowPortEntity) => boolean;\n /** 是否禁用端口 */\n isDisabledPort?: (port: WorkflowPortEntity) => boolean;\n /** 是否反转线条箭头 */\n isReverseLine?: (line: WorkflowLineEntity) => boolean;\n /** 是否隐藏线条箭头 */\n isHideArrowLine?: (line: WorkflowLineEntity) => boolean;\n /** 是否流动线条 */\n isFlowingLine?: (line: WorkflowLineEntity) => boolean;\n /** 是否禁用线条 */\n isDisabledLine?: (line: WorkflowLineEntity) => boolean;\n /** 是否竖向线条 */\n isVerticalLine?: (line: WorkflowLineEntity) => boolean;\n /** 拖拽线条结束 */\n onDragLineEnd?: (params: onDragLineEndParams) => Promise<void>;\n /** 获取线条渲染器 */\n setLineRenderType?: (line: WorkflowLineEntity) => LineRenderType | undefined;\n /** 设置线条样式 */\n setLineClassName?: (line: WorkflowLineEntity) => string | undefined;\n /** 能否添加线条 */\n canAddLine?: (\n fromPort: WorkflowPortEntity,\n toPort: WorkflowPortEntity,\n lines: WorkflowLinesManager,\n silent?: boolean\n ) => boolean;\n /** 能否删除节点 */\n canDeleteNode?: (node: WorkflowNodeEntity, silent?: boolean) => boolean;\n /** 能否删除线条 */\n canDeleteLine?: (\n line: WorkflowLineEntity,\n newLineInfo?: Required<WorkflowLinePortInfo>,\n silent?: boolean\n ) => boolean;\n /**\n * @param fromPort - 开始点\n * @param oldToPort - 旧的连接点\n * @param newToPort - 新的连接点\n * @param lines - 线条管理器\n */\n canResetLine?: (\n fromPort: WorkflowPortEntity,\n oldToPort: WorkflowPortEntity,\n newToPort: WorkflowPortEntity,\n lines: WorkflowLinesManager\n ) => boolean;\n}\n\nexport const WorkflowDocumentOptionsDefault: WorkflowDocumentOptions = {\n cursors: {\n grab: 'url(\"data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjAiIGhlaWdodD0iMjEiIHZpZXdCb3g9IjAgMCAyMCAyMSIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik0xMC40ODczIDIuNjIzNzhDOS45MDczMSAyLjYyMzc4IDkuNDM3MTMgMy4wOTM5NiA5LjQzNzEzIDMuNjczOTZWNS4xNDM3NkM5LjM5NDI4IDQuNDAyNzQgOC43Nzk3OCAzLjgxNTA0IDguMDI4MDIgMy44MTUwNEM3LjI0ODQ4IDMuODE1MDQgNi42MTY1MyA0LjQ0Njk5IDYuNjE2NTMgNS4yMjY1M1YxMS44Mjg5TDUuNjc0MTggMTEuMDA0OUM1LjE1NDg3IDEwLjU1MDkgNC40MDk1IDEwLjQ2MzYgMy43OTkzOCAxMC43ODU1TDMuNjk2OTQgMTAuODM5NkMzLjA2MjE3IDExLjE3NDUgMi45MjI2IDEyLjAyMjggMy40MTY2MiAxMi41NDM0TDcuMzM5NTkgMTYuNjc3NVYxNy4zMjU5QzcuMzM5NTkgMTcuNzg2MiA3LjcxMjY5IDE4LjE1OTMgOC4xNzI5MiAxOC4xNTkzSDEzLjgwODRDMTQuMjY4NyAxOC4xNTkzIDE0LjY0MTcgMTcuNzg2MiAxNC42NDE3IDE3LjMyNTlWMTYuNzkzNUMxNS44MDk0IDE1LjY0ODUgMTYuNDY3MyAxNC4wODE5IDE2LjQ2NzMgMTIuNDQ2NVYxMS40OTY3TDE2LjQ2NzEgNi42MzY4NUMxNi40NjcxIDUuOTU2MyAxNS45MTU0IDUuNDA0NjEgMTUuMjM0OCA1LjQwNDYxQzE0LjU1NDMgNS40MDQ2MSAxNC4wMDI2IDUuOTU2MyAxNC4wMDI2IDYuNjM2ODVMMTQuMDAyMSA1LjA0NzI4QzE0LjAwMjEgNC4zNjY3MyAxMy40NTA0IDMuODE1MDQgMTIuNzY5OCAzLjgxNTA0QzEyLjA4OTMgMy44MTUwNCAxMS41Mzc2IDQuMzY2NzMgMTEuNTM3NiA1LjA0NzI4TDExLjUzNzUgMy42NzM5NUMxMS41Mzc1IDMuMDkzOTYgMTEuMDY3MyAyLjYyMzc4IDEwLjQ4NzMgMi42MjM3OFoiIGZpbGw9IndoaXRlIi8+CjxwYXRoIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBkPSJNMTAuNDg3NCAxLjM3NDAyQzExLjM2MTIgMS4zNzQwMiAxMi4xMjExIDEuODYxMTggMTIuNTEwNSAyLjU3ODY4QzEyLjU5NTggMi41Njk4MyAxMi42ODIzIDIuNTY1MjggMTIuNzcgMi41NjUyOEMxMy44Mjc4IDIuNTY1MjggMTQuNzMxMSAzLjIyNzAxIDE1LjA4ODUgNC4xNTkxMUMxNS4xMzcgNC4xNTYyOSAxNS4xODU4IDQuMTU0ODYgMTUuMjM1IDQuMTU0ODZDMTYuNjA1OSA0LjE1NDg2IDE3LjcxNzIgNS4yNjYxOSAxNy43MTcyIDYuNjM3MDlMMTcuNzE3NCAxMi40NDY3QzE3LjcxNzQgMTQuMjM1NSAxNy4wNjQ0IDE1Ljk1NTkgMTUuODkxOSAxNy4yOTA0VjE3LjMyNjJDMTUuODkxOSAxOC40NzY4IDE0Ljk1OTEgMTkuNDA5NSAxMy44MDg1IDE5LjQwOTVIOC4xNzMwNkM3LjAyMjQ3IDE5LjQwOTUgNi4wODk3MyAxOC40NzY4IDYuMDg5NzMgMTcuMzI2MlYxNy4xNzY0TDIuNTEwMDMgMTMuNDA0MUMxLjQ0NTk5IDEyLjI4MjggMS43NDY2IDEwLjQ1NTUgMy4xMTM3OSA5LjczNDI0TDMuMjE2MjQgOS42ODAxOUMzLjg5MTY4IDkuMzIzODMgNC42NjE4NSA5LjI1NDAxIDUuMzY2NjYgOS40NTE5OFY1LjIyNjc4QzUuMzY2NjYgMy43NTY4NyA2LjU1ODI2IDIuNTY1MjggOC4wMjgxNiAyLjU2NTI4QzguMTcyOTMgMi41NjUyOCA4LjMxNDk5IDIuNTc2ODQgOC40NTM0NyAyLjU5OTA3QzguODM5NDMgMS44NzA0MiA5LjYwNTQ2IDEuMzc0MDIgMTAuNDg3NCAxLjM3NDAyWk0xMi40NDc2IDMuODU3ODdWOS40NzY0NkMxMi40NDc2IDkuNzI4NTIgMTIuMjQzMyA5LjkzMjg1IDExLjk5MTMgOS45MzI4NUMxMS43MzkyIDkuOTMyODUgMTEuNTM0OSA5LjcyODUyIDExLjUzNDkgOS40NzY0NlYzLjc5NjU1QzExLjUzNDkgMy43Nzk1NiAxMS41MzU4IDMuNzYyNzcgMTEuNTM3NiAzLjc0NjI2VjMuNjc0MkMxMS41Mzc2IDMuNDMyODIgMTEuNDU2MiAzLjIxMDQ2IDExLjMxOTMgMy4wMzMwOUMxMS4xMjcyIDIuNzg0MjggMTAuODI2MSAyLjYyNDAyIDEwLjQ4NzQgMi42MjQwMkMxMC4xMjM4IDIuNjI0MDIgOS44MDMzMiAyLjgwODg2IDkuNjE0ODMgMy4wODk3QzkuNTAyNjkgMy4yNTY3OSA5LjQzNzI2IDMuNDU3ODUgOS40MzcyNiAzLjY3NDJWMy43ODU3M0M5LjQzNzM1IDMuNzg5MzMgOS40MzczOSAzLjc5Mjk0IDkuNDM3MzkgMy43OTY1NVY5LjkwMTdDOS40MzczOSAxMC4xNTM3IDkuMjMzMDYgMTAuMzU4MSA4Ljk4MTAxIDEwLjM1ODFDOC43Mjg5NSAxMC4zNTgxIDguNTI0NjIgMTAuMTUzNyA4LjUyNDYyIDkuOTAxN1YzLjkwNTA3QzguNDE3NzMgMy44NjQ5IDguMzA0NjggMy44MzczMiA4LjE4NzI2IDMuODI0MTVDOC4xMzUwNCAzLjgxODI5IDguMDgxOTUgMy44MTUyOCA4LjAyODE2IDMuODE1MjhDNy4yNDg2MSAzLjgxNTI4IDYuNjE2NjYgNC40NDcyMyA2LjYxNjY2IDUuMjI2NzhWMTEuODI5Mkw1LjY3NDMxIDExLjAwNTJDNS41Nzg2OCAxMC45MjE2IDUuNDc1MzcgMTAuODUwNCA1LjM2NjY2IDEwLjc5MTlDNC44ODUwNiAxMC41MzI5IDQuMjk3MjggMTAuNTIzMSAzLjc5OTUyIDEwLjc4NThMMy42OTcwNyAxMC44Mzk4QzMuMDYyMzEgMTEuMTc0NyAyLjkyMjczIDEyLjAyMzEgMy40MTY3NSAxMi41NDM3TDcuMzM5NzMgMTYuNjc3N1YxNy4zMjYyQzcuMzM5NzMgMTcuNzg2NCA3LjcxMjgyIDE4LjE1OTUgOC4xNzMwNiAxOC4xNTk1SDEzLjgwODVDMTQuMjY4OCAxOC4xNTk1IDE0LjY0MTkgMTcuNzg2NCAxNC42NDE5IDE3LjMyNjJWMTYuNzkzOEMxNS43Mzc5IDE1LjcxOSAxNi4zODQ3IDE0LjI3MjggMTYuNDYgMTIuNzQ3QzE2LjQ2NDEgMTIuNjY0MSAxNi40NjY1IDEyLjU4MDkgMTYuNDY3MiAxMi40OTc1TDE2LjQ2NzQgMTIuNDQ2N0wxNi40NjcyIDYuNjM3MDlDMTYuNDY3MiA1Ljk2MjMgMTUuOTI0OCA1LjQxNDE5IDE1LjI1MjIgNS40MDQ5N0wxNS4yMzUgNS40MDQ4NkMxNS4xMjQ2IDUuNDA0ODYgMTUuMDE3NyA1LjQxOTM2IDE0LjkxNTkgNS40NDY1NlY5LjYwMjI2QzE0LjkxNTkgOS44NTQzMSAxNC43MTE2IDEwLjA1ODYgMTQuNDU5NSAxMC4wNTg2QzE0LjIwNzUgMTAuMDU4NiAxNC4wMDMxIDkuODU0MzEgMTQuMDAzMSA5LjYwMjI2VjYuNjA1MTRDMTQuMDAyOSA2LjYxNTc2IDE0LjAwMjcgNi42MjY0MSAxNC4wMDI3IDYuNjM3MDlWOS4yNzcwNUwxNC4wMDIyIDUuMDQ3NTJDMTQuMDAyMiA0Ljg2OTEzIDEzLjk2NDMgNC42OTk2IDEzLjg5NjEgNC41NDY1M0MxMy43MDY0IDQuMTIwNzIgMTMuMjgyMiAzLjgyMjM1IDEyLjc4NzYgMy44MTU0MUwxMi43NyAzLjgxNTI4QzEyLjY1ODQgMy44MTUyOCAxMi41NTA0IDMuODMwMSAxMi40NDc2IDMuODU3ODdaIiBmaWxsPSIjMUQxQzIzIi8+Cjwvc3ZnPg==\"), auto',\n grabbing:\n 'url(\"data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjAiIGhlaWdodD0iMjEiIHZpZXdCb3g9IjAgMCAyMCAyMSIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik02LjYxODE3IDUuNTk4NzVDNi42MTgxNyA0LjgxOTIgNy4yNTAxMiA0LjE4NzI2IDguMDI5NjcgNC4xODcyNkM4Ljc3ODczIDQuMTg3MjYgOS4zOTE1MiA0Ljc3MDc1IDkuNDM4MjkgNS41MDgwMUM5LjQ1OTkyIDQuOTQ3MSA5LjkyMTQ3IDQuNDk5MDIgMTAuNDg3NyA0LjQ5OTAyQzExLjA2NzcgNC40OTkwMiAxMS41Mzc4IDQuOTY5MiAxMS41Mzc4IDUuNTQ5MTlWOC43NjI0NkwxMS41Mzc5IDYuNzExNUMxMS41Mzc5IDYuMDMwOTUgMTIuMDg5NiA1LjQ3OTI2IDEyLjc3MDIgNS40NzkyNkMxMy40NTA3IDUuNDc5MjYgMTQuMDAyNCA2LjAzMDk1IDE0LjAwMjQgNi43MTE1TDE0LjAwMjQgOC43NjI0NkwxNC4wMDI5IDguMDE5ODNDMTQuMDAyOSA3LjMzOTI5IDE0LjU1NDYgNi43ODc1OSAxNS4yMzUyIDYuNzg3NTlDMTUuOTE1NyA2Ljc4NzU5IDE2LjQ2NzQgNy4zMzkyOCAxNi40Njc0IDguMDE5ODNWMTEuNDk3TDE2LjQ2NzUgMTIuNDQ2N0MxNi40Njc1IDE0LjA4MjEgMTUuODA5NiAxNS42NDg3IDE0LjY0MiAxNi43OTM4VjE3LjMyNjJDMTQuNjQyIDE3Ljc4NjQgMTQuMjY4OSAxOC4xNTk1IDEzLjgwODcgMTguMTU5NUg4LjE3MzE3QzcuNzEyOTMgMTguMTU5NSA3LjMzOTg0IDE3Ljc4NjQgNy4zMzk4NCAxNy4zMjYyVjE1Ljk0MjRMNS4zNDU2MiAxNC43NTM0QzQuNTg5MjQgMTQuMzAyNCA0LjEyNTkxIDEzLjQ4NjcgNC4xMjU4OSAxMi42MDYxTDQuMTI1ODMgOS4yODM4M0M0LjEyNTgyIDguOTU0MjcgNC4zMjAwMyA4LjY1NTY2IDQuNjIxMjkgOC41MjIwNUw2LjYxODE3IDcuNjM2MzRWNS41OTg3NVoiIGZpbGw9IndoaXRlIi8+CjxwYXRoIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBkPSJNMTAuNDg3OCAzLjI0OTAyQzExLjI3OTYgMy4yNDkwMiAxMS45Nzc4IDMuNjQ5MDIgMTIuMzkxNyA0LjI1Nzk2QzEyLjUxNTEgNC4yMzkwNiAxMi42NDE2IDQuMjI5MjYgMTIuNzcwMyA0LjIyOTI2QzEzLjcyMjQgNC4yMjkyNiAxNC41NDkzIDQuNzY1MzEgMTQuOTY1NyA1LjU1MjA3QzE1LjA1NDMgNS41NDI1IDE1LjE0NDIgNS41Mzc1OSAxNS4yMzUzIDUuNTM3NTlDMTYuNjA2MiA1LjUzNzU5IDE3LjcxNzYgNi42NDg5MyAxNy43MTc2IDguMDE5ODNMMTcuNzE3NyAxMi40NDY3QzE3LjcxNzcgMTQuMjM1NSAxNy4wNjQ3IDE1Ljk1NTkgMTUuODkyMSAxNy4yOTA0VjE3LjMyNjJDMTUuODkyMSAxOC40NzY4IDE0Ljk1OTQgMTkuNDA5NSAxMy44MDg4IDE5LjQwOTVIOC4xNzMzMkM3LjAyMjczIDE5LjQwOTUgNi4wODk5OCAxOC40NzY4IDYuMDg5OTggMTcuMzI2MlYxNi42NTI0TDQuNzA1NjMgMTUuODI3QzMuNTcxMDYgMTUuMTUwNSAyLjg3NjA3IDEzLjkyNzEgMi44NzYwNCAxMi42MDYxTDIuODc1OTggOS4yODM4NUMyLjg3NTk2IDguNDU5OTYgMy4zNjE0OSA3LjcxMzQ1IDQuMTE0NjIgNy4zNzk0TDUuMzY4MzIgNi44MjMzM1Y1LjU5ODc1QzUuMzY4MzIgNC4xMjg4NSA2LjU1OTkxIDIuOTM3MjYgOC4wMjk4MiAyLjkzNzI2QzguNjA4MzEgMi45MzcyNiA5LjE0MzU1IDMuMTIxNyA5LjU4MDA1IDMuNDM1MDVDOS44NTg1MyAzLjMxNTMyIDEwLjE2NTQgMy4yNDkwMiAxMC40ODc4IDMuMjQ5MDJaTTEyLjQ0NzkgNS41MjE4NlY5LjQ3NTU3QzEyLjQ0NzkgOS43Mjc2MiAxMi4yNDM2IDkuOTMxOTUgMTEuOTkxNiA5LjkzMTk1QzExLjc1NjggOS45MzE5NSAxMS41NjM0IDkuNzU0NjUgMTEuNTM4IDkuNTI2NjNDMTEuNTM2MSA5LjUwOTg3IDExLjUzNTIgOS40OTI4MyAxMS41MzUyIDkuNDc1NTdWNS40NzE1OEMxMS41MTU0IDUuMjAwODMgMTEuMzkzIDQuOTU4NTggMTEuMjA2NiA0Ljc4MzU4QzExLjAxODggNC42MDcxMSAxMC43NjU5IDQuNDk5MDIgMTAuNDg3OCA0LjQ5OTAyQzEwLjQ3NjYgNC40OTkwMiAxMC40NjU0IDQuNDk5MTkgMTAuNDU0MiA0LjQ5OTU0QzkuOTAzNDcgNC41MTY4NCA5LjQ1OTY0IDQuOTU4MjQgOS40Mzg0NCA1LjUwODAxQzkuNDM4MiA1LjUwNDMgOS40Mzc5NSA1LjUwMDU4IDkuNDM3NjkgNS40OTY4OFY5LjkwMjQzQzkuNDM3NjkgMTAuMTU0NSA5LjIzMzM2IDEwLjM1ODggOC45ODEzMSAxMC4zNTg4QzguNzI5MjUgMTAuMzU4OCA4LjUyNDkyIDEwLjE1NDUgOC41MjQ5MiA5LjkwMjQzVjQuMjc2NTNDOC4zNzA4NiA0LjIxODgyIDguMjA0MDIgNC4xODcyNiA4LjAyOTgyIDQuMTg3MjZDNy4yNTAyNyA0LjE4NzI2IDYuNjE4MzIgNC44MTkyIDYuNjE4MzIgNS41OTg3NUw2LjYxODI3IDkuOTc1OTlDNi42MTgyNyAxMC4yMjggNi40MTM5NCAxMC40MzI0IDYuMTYxODkgMTAuNDMyNEM1LjkwOTgzIDEwLjQzMjQgNS43MDU1IDEwLjIyOCA1LjcwNTUgOS45NzU5OVY4LjA0MTIyTDQuNjIxNDQgOC41MjIwNUM0LjMyMDE4IDguNjU1NjYgNC4xMjU5NyA4Ljk1NDI3IDQuMTI1OTggOS4yODM4M0w0LjEyNjA0IDEyLjYwNjFDNC4xMjYwNiAxMy40ODY3IDQuNTg5MzkgMTQuMzAyNCA1LjM0NTc2IDE0Ljc1MzRMNy4zMzk5OCAxNS45NDI0VjE3LjMyNjJDNy4zMzk5OCAxNy43ODY0IDcuNzEzMDggMTguMTU5NSA4LjE3MzMyIDE4LjE1OTVIMTMuODA4OEMxNC4yNjkgMTguMTU5NSAxNC42NDIxIDE3Ljc4NjQgMTQuNjQyMSAxNy4zMjYyVjE2Ljc5MzhDMTUuNzM4MSAxNS43MTkgMTYuMzg1IDE0LjI3MjggMTYuNDYwMyAxMi43NDdDMTYuNDY0NiAxMi42NiAxNi40NjcgMTIuNTcyOCAxNi40Njc2IDEyLjQ4NTRMMTYuNDY3NyAxMi40NDY3TDE2LjQ2NzYgOC4wMTk4M0MxNi40Njc2IDcuMzQ1MDQgMTUuOTI1MiA2Ljc5NjkzIDE1LjI1MjUgNi43ODc3MUwxNS4yMzUzIDYuNzg3NTlDMTUuMTI1IDYuNzg3NTkgMTUuMDE4IDYuODAyMSAxNC45MTYyIDYuODI5MzFWOS42MDEzNkMxNC45MTYyIDkuODUzNDIgMTQuNzExOSAxMC4wNTc3IDE0LjQ1OTggMTAuMDU3N0MxNC4yMDc4IDEwLjA1NzcgMTQuMDAzNCA5Ljg1MzQxIDE0LjAwMzQgOS42MDEzNlY3Ljk4OTg1QzE0LjAwMzIgNy45OTk4MiAxNC4wMDMxIDguMDA5ODEgMTQuMDAzMSA4LjAxOTgzTDE0LjAwMzQgOS42MDEzNkwxNC4wMDI1IDYuNzExNUMxNC4wMDI1IDYuNDQ5NzQgMTMuOTIwOSA2LjIwNzA1IDEzLjc4MTggNi4wMDc0OEMxMy41NjIgNS42OTI0MiAxMy4xOTg5IDUuNDg0ODMgMTIuNzg3IDUuNDc5MzdMMTIuNzcwMyA1LjQ3OTI2QzEyLjY1ODggNS40NzkyNiAxMi41NTA3IDUuNDk0MDggMTIuNDQ3OSA1LjUyMTg2WiIgZmlsbD0iIzFEMUMyMyIvPgo8L3N2Zz4=\"), auto',\n },\n\n fromNodeJSON(node, json, isFirstCreate) {\n initFormDataFromJSON(node, json, isFirstCreate);\n return;\n },\n toNodeJSON(node: WorkflowNodeEntity): WorkflowNodeJSON {\n const nodeError = node.getData<FlowNodeErrorData>(FlowNodeErrorData)?.getError();\n // 如果节点有错误,这里抛出错误,避免后面的代码执行异常\n if (nodeError) {\n throw nodeError;\n }\n const transform = node.getData<TransformData>(TransformData)!;\n\n let formJSON = toFormJSON(node);\n const metaData: Record<string, unknown> = {};\n\n // 持久化子画布位置\n const nodeMeta = node.getNodeMeta<WorkflowNodeMeta>();\n const subCanvas = nodeMeta.subCanvas?.(node);\n if (subCanvas?.isCanvas === false) {\n const canvasNodeTransform =\n subCanvas.canvasNode.getData<FlowNodeTransformData>(FlowNodeTransformData);\n const { x, y } = canvasNodeTransform.transform.position;\n metaData.canvasPosition = { x, y };\n }\n\n const json: WorkflowNodeJSON = {\n id: node.id,\n type: node.flowNodeType,\n meta: {\n position: { x: transform.position.x, y: transform.position.y },\n ...metaData,\n },\n data: formJSON,\n };\n return json;\n },\n};\n","import { FlowNodeFormData } from '@flowgram.ai/form-core';\nimport { FlowNodeEntity, FlowNodeJSON } from '@flowgram.ai/document';\n\nimport { type WorkflowDocument } from '../workflow-document';\nimport { WorkflowContentChangeType, type WorkflowNodeRegistry } from '../typings';\n\nexport function getFlowNodeFormData(node: FlowNodeEntity) {\n return node.getData(FlowNodeFormData) as FlowNodeFormData;\n}\n\nexport function toFormJSON(node: FlowNodeEntity) {\n const formData = node.getData(FlowNodeFormData) as FlowNodeFormData;\n if (!formData || !(node.getNodeRegistry() as WorkflowNodeRegistry).formMeta) return undefined;\n return formData.toJSON();\n}\n\nexport function initFormDataFromJSON(\n node: FlowNodeEntity,\n json: FlowNodeJSON,\n isFirstCreate: boolean\n) {\n const formData = node.getData(FlowNodeFormData)!;\n const registry = node.getNodeRegistry();\n const { formMeta } = registry;\n\n if (formData && formMeta) {\n if (isFirstCreate) {\n formData.createForm(formMeta, json.data);\n formData.onDataChange(() => {\n (node.document as WorkflowDocument).fireContentChange({\n type: WorkflowContentChangeType.NODE_DATA_CHANGE,\n toJSON: () => formData.toJSON(),\n entity: node,\n });\n });\n } else {\n formData.updateFormValues(json.data);\n }\n }\n}\n","import { type WorkflowLineEntity, type WorkflowNodeEntity } from '../entities';\nimport { type WorkflowNodeJSON } from './workflow-node';\nimport { type WorkflowEdgeJSON } from './workflow-edge';\n\nexport interface WorkflowJSON {\n nodes: WorkflowNodeJSON[];\n edges: WorkflowEdgeJSON[];\n}\n\nexport enum WorkflowContentChangeType {\n /**\n * 添加节点\n */\n ADD_NODE = 'ADD_NODE',\n /**\n * 删除节点\n */\n DELETE_NODE = 'DELETE_NODE',\n /**\n * 移动节点\n */\n MOVE_NODE = 'MOVE_NODE',\n /**\n * 节点数据更新 (表单引擎数据 或者 extInfo 数据)\n */\n NODE_DATA_CHANGE = 'NODE_DATA_CHANGE',\n /**\n * 添加线条\n */\n ADD_LINE = 'ADD_LINE',\n /**\n * 删除线条\n */\n DELETE_LINE = 'DELETE_LINE',\n /**\n * 节点Meta信息变更\n */\n META_CHANGE = 'META_CHANGE',\n}\n\nexport interface WorkflowContentChangeEvent {\n type: WorkflowContentChangeType;\n /**\n * 当前触发的元素的json数据,toJSON 需要主动触发\n */\n toJSON: () => any;\n /*\n * 当前的事件的 entity\n */\n entity: WorkflowNodeEntity | WorkflowLineEntity;\n}\n","import type { Rectangle, IPoint } from '@flowgram.ai/utils';\n\nimport { type WorkflowLineEntity } from '../entities';\n\nexport enum LineType {\n BEZIER, // 贝塞尔曲线\n LINE_CHART, // 折叠线\n}\n\nexport type LineRenderType = LineType | string;\n\nexport interface LinePosition {\n from: IPoint;\n to: IPoint;\n}\n\nexport interface LineColor {\n hidden: string;\n default: string;\n drawing: string;\n hovered: string;\n selected: string;\n error: string;\n flowing: string;\n}\n\nexport enum LineColors {\n HIDDEN = 'var(--g-workflow-line-color-hidden,transparent)', // 隐藏线条\n DEFUALT = 'var(--g-workflow-line-color-default,#4d53e8)',\n DRAWING = 'var(--g-workflow-line-color-drawing, #5DD6E3)', // '#b5bbf8', // '#9197F1',\n HOVER = 'var(--g-workflow-line-color-hover,#37d0ff)',\n SELECTED = 'var(--g-workflow-line-color-selected,#37d0ff)',\n ERROR = 'var(--g-workflow-line-color-error,red)',\n FLOWING = 'var(--g-workflow-line-color-flowing,#4d53e8)', // 流动线条,默认使用主题色\n}\n\nexport interface WorkflowLineRenderContribution {\n entity: WorkflowLineEntity;\n path: string;\n bounds: Rectangle;\n update: (params: { fromPos: IPoint; toPos: IPoint }) => void;\n calcDistance: (pos: IPoint) => number;\n}\n\nexport type WorkflowLineRenderContributionFactory = (new (\n entity: WorkflowLineEntity\n) => WorkflowLineRenderContribution) & {\n type: LineRenderType;\n};\n","import { IPoint, Event } from '@flowgram.ai/utils';\nimport {\n FlowNodeEntity,\n FlowNodeEntityOrId,\n FlowOperationBaseService,\n} from '@flowgram.ai/document';\n\nexport interface NodePostionUpdateEvent {\n node: FlowNodeEntity;\n oldPosition: IPoint;\n newPosition: IPoint;\n}\n\nexport interface WorkflowOperationBaseService extends FlowOperationBaseService {\n /**\n * 节点位置更新事件\n */\n readonly onNodePostionUpdate: Event<NodePostionUpdateEvent>;\n /**\n * 更新节点位置\n * @param nodeOrId\n * @param position\n * @returns\n */\n updateNodePosition(nodeOrId: FlowNodeEntityOrId, position: IPoint): void;\n}\n\nexport const WorkflowOperationBaseService = Symbol('WorkflowOperationBaseService');\n","export * from './workflow-json';\nexport * from './workflow-edge';\nexport * from './workflow-node';\nexport * from './workflow-registry';\nexport * from './workflow-line';\nexport * from './workflow-sub-canvas';\nexport * from './workflow-operation';\nexport * from './workflow-drag';\n\nexport const URLParams = Symbol('');\n\nexport interface URLParams {\n [key: string]: string;\n}\n","import { customAlphabet } from 'nanoid';\nimport { inject, injectable, optional, postConstruct } from 'inversify';\nimport { Emitter, type IPoint } from '@flowgram.ai/utils';\nimport { NodeEngineContext } from '@flowgram.ai/form-core';\nimport {\n AddNodeData,\n FlowDocument,\n FlowNodeBaseType,\n FlowNodeTransformData,\n} from '@flowgram.ai/document';\nimport {\n injectPlaygroundContext,\n PlaygroundConfigEntity,\n PlaygroundContext,\n PositionData,\n TransformData,\n} from '@flowgram.ai/core';\n\nimport { WorkflowLinesManager } from './workflow-lines-manager';\nimport {\n WorkflowDocumentOptions,\n WorkflowDocumentOptionsDefault,\n} from './workflow-document-option';\nimport { getFlowNodeFormData } from './utils/flow-node-form-data';\nimport { delay, fitView, getAntiOverlapPosition } from './utils';\nimport {\n type WorkflowContentChangeEvent,\n WorkflowContentChangeType,\n WorkflowEdgeJSON,\n type WorkflowJSON,\n type WorkflowNodeJSON,\n type WorkflowNodeMeta,\n type WorkflowNodeRegistry,\n WorkflowSubCanvas,\n} from './typings';\nimport { WorkflowSelectService } from './service/workflow-select-service';\nimport { FREE_LAYOUT_KEY, type FreeLayout } from './layout';\nimport { WorkflowNodeLinesData } from './entity-datas';\nimport {\n WorkflowLineEntity,\n WorkflowLinePortInfo,\n WorkflowNodeEntity,\n WorkflowPortEntity,\n} from './entities';\n\nconst nanoid = customAlphabet('1234567890', 5);\n\nexport const WorkflowDocumentProvider = Symbol('WorkflowDocumentProvider');\nexport type WorkflowDocumentProvider = () => WorkflowDocument;\n\n@injectable()\nexport class WorkflowDocument extends FlowDocument {\n private _onContentChangeEmitter = new Emitter<WorkflowContentChangeEvent>();\n\n protected readonly onLoadedEmitter = new Emitter<void>();\n\n readonly onContentChange = this._onContentChangeEmitter.event;\n\n private _onReloadEmitter = new Emitter<WorkflowDocument>();\n\n readonly onReload = this._onReloadEmitter.event;\n\n /**\n * 数据加载完成\n */\n readonly onLoaded = this.onLoadedEmitter.event;\n\n protected _loading = false;\n\n @inject(WorkflowLinesManager) linesManager: WorkflowLinesManager;\n\n @inject(PlaygroundConfigEntity) playgroundConfig: PlaygroundConfigEntity;\n\n @injectPlaygroundContext() playgroundContext: PlaygroundContext;\n\n @inject(WorkflowDocumentOptions)\n options: WorkflowDocumentOptions = {};\n\n @inject(NodeEngineContext) @optional() nodeEngineContext: NodeEngineContext;\n\n @inject(WorkflowSelectService) selectServices: WorkflowSelectService;\n\n get loading(): boolean {\n return this._loading;\n }\n\n async fitView(easing?: boolean): Promise<void> {\n return fitView(this, this.playgroundConfig, easing).then(() => {\n this.linesManager.forceUpdate();\n });\n }\n\n @postConstruct()\n init(): void {\n super.init();\n this.currentLayoutKey = this.options.defaultLayout || FREE_LAYOUT_KEY;\n this.linesManager.init(this);\n this.playgroundConfig.getCursors = () => this.options.cursors;\n this.linesManager.onAvailableLinesChange((e) => this.fireContentChange(e));\n this.playgroundConfig.onReadonlyOrDisabledChange(({ readonly }) => {\n if (this.nodeEngineContext) {\n this.nodeEngineContext.readonly = readonly;\n }\n });\n }\n\n async load(): Promise<void> {\n if (this.disposed) return;\n this._loading = true;\n await super.load();\n this._loading = false;\n this.onLoadedEmitter.fire();\n }\n\n async reload(json: WorkflowJSON, delayTime = 0): Promise<void> {\n if (this.disposed) return;\n this._loading = true;\n this.clear();\n this.fromJSON(json);\n // loading添加delay,避免reload时触发fireContentChange的副作用\n await delay(delayTime);\n this._loading = false;\n this._onReloadEmitter.fire(this);\n }\n\n /**\n * 从数据加载\n * @param json\n */\n fromJSON(json: Partial<WorkflowJSON>, fireRender = true): void {\n if (this.disposed) return;\n const workflowJSON: WorkflowJSON = {\n nodes: json.nodes ?? [],\n edges: json.edges ?? [],\n };\n // 触发画布更新\n this.entityManager.changeEntityLocked = true;\n\n // 逐层渲染\n this.renderJSON(workflowJSON);\n\n this.entityManager.changeEntityLocked = false;\n this.transformer.loading = false;\n // 批量触发画布更新\n if (fireRender) {\n this.fireRender();\n }\n }\n\n /**\n * 清空画布\n */\n clear(): void {\n this.getAllNodes().map((node) => node.dispose()); // 清空节点\n this.linesManager.getAllLines().map((line) => line.dispose()); // 清空线条\n this.getAllPorts().map((port) => port.dispose()); // 清空端口\n this.selectServices.clear(); // 清空选择\n }\n\n /**\n * 创建流程节点\n * @param json\n */\n createWorkflowNode(\n json: WorkflowNodeJSON,\n isClone: boolean = false,\n parentId?: string\n ): WorkflowNodeEntity {\n // 是否是一个已经存在的节点\n const isExistedNode = this.getNode(json.id);\n const parent = this.getNode(parentId ?? this.root.id) ?? this.root;\n const node = this.addNode(\n {\n ...json,\n parent,\n },\n undefined,\n true\n ) as WorkflowNodeEntity;\n\n const registry = node.getNodeRegistry() as WorkflowNodeRegistry;\n const { formMeta } = registry;\n const meta = node.getNodeMeta<WorkflowNodeMeta>();\n const formData = getFlowNodeFormData(node);\n\n const transform = node.getData<FlowNodeTransformData>(FlowNodeTransformData)!;\n const freeLayout = this.layout as FreeLayout;\n if (!isExistedNode) {\n transform.onDataChange(() => {\n // TODO 这个有点难以理解,其实是为了同步size 数据\n freeLayout.syncTransform(node);\n });\n }\n let { position } = meta;\n if (!position) {\n // 获取默认的位置\n position = this.getNodeDefaultPosition(json.type);\n }\n\n // 更新节点位置信息\n node.getData(TransformData)!.update({\n position,\n });\n\n // 初始化表单数据\n if (formMeta && formData && !formData.formModel.initialized) {\n // 如果表单数据在前置步骤(fromJSON)内已定义,则跳过表单初始化逻辑\n formData.createForm(formMeta, json.data);\n\n formData.onDataChange(() => {\n this.fireContentChange({\n type: WorkflowContentChangeType.NODE_DATA_CHANGE,\n toJSON: () => formData.toJSON(),\n entity: node,\n });\n });\n }\n // 位置变更\n const positionData = node.getData<PositionData>(PositionData)!;\n if (!isExistedNode) {\n positionData.onDataChange(() => {\n this.fireContentChange({\n type: WorkflowContentChangeType.MOVE_NODE,\n toJSON: () => positionData.toJSON(),\n entity: node,\n });\n });\n }\n\n const subCanvas = this.getNodeSubCanvas(node);\n\n if (!isExistedNode && !subCanvas?.isCanvas) {\n this.fireContentChange({\n type: WorkflowContentChangeType.ADD_NODE,\n entity: node,\n toJSON: () => this.toNodeJSON(node),\n });\n node.onDispose(() => {\n if (!node.parent || node.parent.flowNodeType === FlowNodeBaseType.ROOT) {\n return;\n }\n const parentTransform = node.parent.getData(FlowNodeTransformData);\n parentTransform.fireChange();\n });\n let lastDeleteNodeData: WorkflowNodeJSON | undefined;\n node.preDispose.onDispose(() => {\n lastDeleteNodeData = this.toNodeJSON(node);\n });\n node.onDispose(() => {\n this.fireContentChange({\n type: WorkflowContentChangeType.DELETE_NODE,\n entity: node,\n toJSON: () => lastDeleteNodeData,\n });\n });\n }\n\n // 若存在子节点,则创建子节点\n if (json.blocks) {\n this.renderJSON(\n { nodes: json.blocks, edges: json.edges ?? [] },\n {\n parent: node,\n isClone,\n }\n );\n }\n // 子画布联动\n if (subCanvas) {\n const canvasTransform = subCanvas.canvasNode.getData<TransformData>(TransformData);\n canvasTransform.update({\n position: subCanvas.parentNode.getNodeMeta()?.canvasPosition,\n });\n if (!isExistedNode) {\n subCanvas.parentNode.onDispose(() => {\n subCanvas.canvasNode.dispose();\n });\n subCanvas.canvasNode.onDispose(() => {\n subCanvas.parentNode.dispose();\n });\n }\n }\n if (!isExistedNode) {\n this.onNodeCreateEmitter.fire({\n node,\n data: json,\n json,\n });\n } else {\n this.onNodeUpdateEmitter.fire({\n node,\n data: json,\n json,\n });\n }\n\n return node;\n }\n\n /**\n * 添加节点,如果节点已经存在则不会重复创建\n * @param data\n * @param addedNodes\n */\n addNode(\n data: AddNodeData,\n addedNodes?: WorkflowNodeEntity[],\n ignoreCreateAndUpdateEvent?: boolean\n ): WorkflowNodeEntity {\n const { id, type = 'block', originParent, parent, meta, hidden, index } = data;\n let node = this.getNode(id);\n let isNew = false;\n const register = this.getNodeRegistry(type, data.originParent);\n // node 类型变化则全部删除重新来\n if (node && node.flowNodeType !== data.type) {\n node.dispose();\n node = undefined;\n }\n if (!node) {\n const { dataRegistries } = register;\n node = this.entityManager.createEntity<WorkflowNodeEntity>(WorkflowNodeEntity, {\n id,\n document: this,\n flowNodeType: type,\n originParent,\n meta,\n });\n const datas = dataRegistries\n ? this.nodeDataRegistries.concat(...dataRegistries)\n : this.nodeDataRegistries;\n node.addInitializeData(datas);\n node.onDispose(() => this.onNodeDisposeEmitter.fire({ node: node! }));\n this.options.fromNodeJSON?.(node, data, true);\n isNew = true;\n } else {\n this.options.fromNodeJSON?.(node, data, false);\n }\n // 初始化数据重制\n node.initData({\n originParent,\n parent,\n meta,\n hidden,\n index,\n });\n addedNodes?.push(node);\n // 自定义创建逻辑\n if (register.onCreate) {\n const extendNodes = register.onCreate(node, data);\n if (extendNodes && addedNodes) {\n addedNodes.push(...extendNodes);\n }\n }\n\n if (!ignoreCreateAndUpdateEvent) {\n if (isNew) {\n this.onNodeCreateEmitter.fire({\n node,\n data,\n json: data,\n });\n } else {\n this.onNodeUpdateEmitter.fire({ node, data, json: data });\n }\n }\n\n return node;\n }\n\n get layout(): FreeLayout {\n const layout = this.layouts.find((layout) => layout.name == this.currentLayoutKey);\n if (!layout) {\n throw new Error(`Unknown flow layout: ${this.currentLayoutKey}`);\n }\n return layout as FreeLayout;\n }\n\n /**\n * 获取默认的 x y 坐标, 默认为当前画布可视区域中心\n * @param type\n * @protected\n */\n getNodeDefaultPosition(type: string | number): IPoint {\n const { size } = this.getNodeRegistry(type).meta || {};\n // 当前可视区域的中心位置\n let position = this.playgroundConfig.getViewport(true).center;\n if (size) {\n position = {\n x: position.x,\n y: position.y - size.height / 2,\n };\n }\n // 去掉叠加的\n return getAntiOverlapPosition(this, position);\n }\n\n /**\n * 通过类型创建节点, 如果没有提供position 则直接放在画布中间\n * @param type\n */\n createWorkflowNodeByType(\n type: string | number,\n position?: IPoint,\n json: Partial<WorkflowNodeJSON> = {},\n parentID?: string\n ): WorkflowNodeEntity {\n let id: string = json.id as string;\n if (id === undefined) {\n // 保证 id 不要重复\n do {\n id = `1${nanoid()}`;\n } while (this.entityManager.getEntityById(id));\n } else {\n if (this.entityManager.getEntityById(id)) {\n throw new Error(`[WorkflowDocument.createWorkflowNodeByType] Node Id \"${id}\" duplicated.`);\n }\n }\n return this.createWorkflowNode(\n {\n ...json,\n id,\n type,\n meta: { position, ...json?.meta }, // TODO title 和 meta 要从注册数据去拿\n data: json?.data,\n blocks: json?.blocks,\n edges: json?.edges,\n },\n false,\n parentID\n );\n }\n\n getAllNodes(): WorkflowNodeEntity[] {\n return this.entityManager\n .getEntities<WorkflowNodeEntity>(WorkflowNodeEntity)\n .filter((n) => n.id !== FlowNodeBaseType.ROOT);\n }\n\n getAllPorts(): WorkflowPortEntity[] {\n return this.entityManager\n .getEntities<WorkflowPortEntity>(WorkflowPortEntity)\n .filter((p) => p.node.id !== FlowNodeBaseType.ROOT);\n }\n\n /**\n * 获取画布中的非游离节点\n * 1. 开始节点\n * 2. 从开始节点出发能走到的节点\n * 3. 结束节点\n * 4. 默认所有子画布内节点为游离节点\n */\n getAssociatedNodes(): WorkflowNodeEntity[] {\n const allNode = this.getAllNodes();\n\n const allLines = this.linesManager\n .getAllLines()\n .filter((line) => line.from && line.to)\n .map((line) => ({\n from: line.from.id,\n to: line.to!.id,\n }));\n\n const startNodeId = allNode.find((node) => node.isStart)!.id;\n const endNodeId = allNode.find((node) => node.isNodeEnd)!.id;\n\n // 子画布内节点无需开始/结束\n const nodeInContainer = allNode\n .filter((node) => node.parent?.getNodeMeta<WorkflowNodeMeta>().isContainer)\n .map((node) => node.id);\n\n const associatedCache = new Set([endNodeId, ...nodeInContainer]);\n const bfs = (nodeId: string) => {\n if (associatedCache.has(nodeId)) {\n return;\n }\n associatedCache.add(nodeId);\n const nextNodes = allLines.reduce((ids, { from, to }) => {\n if (from === nodeId && !associatedCache.has(to)) {\n ids.push(to);\n }\n return ids;\n }, [] as string[]);\n\n nextNodes.forEach(bfs);\n };\n\n bfs(startNodeId);\n\n const associatedNodes = allNode.filter((node) => associatedCache.has(node.id));\n\n return associatedNodes;\n }\n\n /**\n * 触发渲染\n */\n fireRender() {\n this.entityManager.fireEntityChanged(WorkflowNodeEntity.type);\n this.entityManager.fireEntityChanged(WorkflowLineEntity.type);\n this.entityManager.fireEntityChanged(WorkflowPortEntity.type);\n }\n\n fireContentChange(event: WorkflowContentChangeEvent): void {\n if (this._loading || this.disposed || this.entityManager.changeEntityLocked) {\n return;\n }\n this._onContentChangeEmitter.fire(event);\n }\n\n toNodeJSON(node: WorkflowNodeEntity): WorkflowNodeJSON {\n // 如果是子画布,返回其父节点的JSON\n const subCanvas = this.getNodeSubCanvas(node);\n if (subCanvas?.isCanvas === true) {\n return this.toNodeJSON(subCanvas.parentNode);\n }\n\n const json = this.toNodeJSONFromOptions(node);\n const children = this.getNodeChildren(node);\n\n // 计算子节点 JSON\n const blocks = children.map((child) => this.toNodeJSON(child));\n\n // 计算子线条 JSON\n const linesMap = new Map<string, WorkflowEdgeJSON>();\n children.forEach((child) => {\n const childLinesData = child.getData<WorkflowNodeLinesData>(WorkflowNodeLinesData);\n [...childLinesData.inputLines, ...childLinesData.outputLines]\n .filter(Boolean)\n .forEach((line) => {\n const lineJSON = this.toLineJSON(line);\n if (!lineJSON || linesMap.has(line.id)) {\n return;\n }\n linesMap.set(line.id, lineJSON);\n });\n });\n const edges = Array.from(linesMap.values()); // 使用 Map 防止线条重复\n\n // 拼接 JSON\n if (blocks.length > 0) json.blocks = blocks;\n if (edges.length > 0) json.edges = edges;\n\n return json;\n }\n\n /**\n * 节点转换为JSON, 没有format的过程\n * @param node\n * @returns\n */\n private toNodeJSONFromOptions(node: WorkflowNodeEntity): WorkflowNodeJSON {\n if (this.options.toNodeJSON) {\n return this.options.toNodeJSON(node) as WorkflowNodeJSON;\n }\n return WorkflowDocumentOptionsDefault.toNodeJSON!(node) as WorkflowNodeJSON;\n }\n\n copyNode(\n node: WorkflowNodeEntity,\n newNodeId?: string | undefined,\n format?: (json: WorkflowNodeJSON) => WorkflowNodeJSON,\n position?: IPoint\n ): WorkflowNodeEntity {\n let json = this.toNodeJSON(node);\n if (format) {\n json = format(json);\n }\n position = position || {\n x: json.meta!.position!.x + 30,\n y: json.meta!.position!.y + 30,\n };\n return this.createWorkflowNode(\n {\n id: newNodeId || `1${nanoid()}`,\n type: node.flowNodeType,\n meta: {\n ...json.meta,\n position,\n },\n data: json.data,\n blocks: json.blocks,\n edges: json.edges,\n },\n true,\n node.parent?.id\n );\n }\n\n copyNodeFromJSON(\n flowNodeType: string,\n nodeJSON: WorkflowNodeJSON,\n newNodeId?: string | undefined,\n position?: IPoint,\n parentId?: string\n ): WorkflowNodeEntity {\n position = position || {\n x: nodeJSON.meta!.position!.x + 30,\n y: nodeJSON.meta!.position!.y + 30,\n };\n return this.createWorkflowNode(\n {\n id: newNodeId || `1${nanoid()}`,\n type: flowNodeType,\n meta: {\n ...nodeJSON.meta,\n position,\n },\n data: nodeJSON.data,\n blocks: nodeJSON.blocks,\n edges: nodeJSON.edges,\n },\n true,\n parentId\n );\n }\n\n canRemove(node: WorkflowNodeEntity, silent?: boolean): boolean {\n const meta = node.getNodeMeta<WorkflowNodeMeta>();\n if (meta.deleteDisable) {\n return false;\n }\n if (this.options.canDeleteNode && !this.options.canDeleteNode(node, silent)) {\n return false;\n }\n return true;\n }\n\n /**\n * 判断端口是否为错误态\n */\n isErrorPort(port: WorkflowPortEntity) {\n if (typeof this.options.isErrorPort === 'function') {\n return this.options.isErrorPort(port);\n }\n\n return false;\n }\n\n /**\n * 导出数据\n */\n toJSON(): WorkflowJSON {\n const rootJSON = this.toNodeJSON(this.root);\n return {\n nodes: rootJSON.blocks ?? [],\n edges: rootJSON.edges ?? [],\n };\n }\n\n dispose() {\n super.dispose();\n this._onReloadEmitter.dispose();\n }\n\n /**\n * 逐层创建节点和线条\n */\n public renderJSON(\n json: WorkflowJSON,\n options?: {\n parent?: WorkflowNodeEntity;\n isClone?: boolean;\n }\n ): {\n nodes: WorkflowNodeEntity[];\n edges: WorkflowLineEntity[];\n } {\n const { parent = this.root, isClone = false } = options ?? {};\n // 创建节点\n const containerID = this.getNodeSubCanvas(parent)?.canvasNode.id ?? parent.id;\n const nodes = json.nodes.map((nodeJSON: WorkflowNodeJSON) =>\n this.createWorkflowNode(nodeJSON, isClone, containerID)\n );\n // 创建线条\n const edges = json.edges\n .map((edge) => this.createWorkflowLine(edge, containerID))\n .filter(Boolean) as WorkflowLineEntity[];\n return { nodes, edges };\n }\n\n private getNodeSubCanvas(node: WorkflowNodeEntity): WorkflowSubCanvas | undefined {\n if (!node) return;\n const nodeMeta = node.getNodeMeta<WorkflowNodeMeta>();\n const subCanvas = nodeMeta.subCanvas?.(node);\n return subCanvas;\n }\n\n private getNodeChildren(node: WorkflowNodeEntity): WorkflowNodeEntity[] {\n if (!node) return [];\n const subCanvas = this.getNodeSubCanvas(node);\n const childrenWithCanvas = subCanvas\n ? subCanvas.canvasNode.collapsedChildren\n : node.collapsedChildren;\n // 过滤掉子画布的JSON数据\n const children = childrenWithCanvas\n .filter((child) => {\n const childMeta = child.getNodeMeta<WorkflowNodeMeta>();\n return !childMeta.subCanvas?.(node)?.isCanvas;\n })\n .filter(Boolean);\n return children;\n }\n\n private toLineJSON(line: WorkflowLineEntity): WorkflowEdgeJSON | undefined {\n const lineJSON = line.toJSON();\n if (\n !line.from ||\n !line.info.from ||\n !line.fromPort ||\n !line.to ||\n !line.info.to ||\n !line.toPort\n ) {\n return;\n }\n // 父子节点之间连线,需替换子画布为父节点\n const fromSubCanvas = this.getNodeSubCanvas(line.from);\n const toSubCanvas = this.getNodeSubCanvas(line.to);\n if (fromSubCanvas && !fromSubCanvas.isCanvas && toSubCanvas && toSubCanvas.isCanvas) {\n // 忽略子画布与父节点的连线\n return;\n }\n if (line.from === line.to.parent && fromSubCanvas) {\n return {\n ...lineJSON,\n sourceNodeID: fromSubCanvas.parentNode.id,\n };\n }\n if (line.to === line.from.parent && toSubCanvas) {\n return {\n ...lineJSON,\n targetNodeID: toSubCanvas.parentNode.id,\n };\n }\n return lineJSON;\n }\n\n private createWorkflowLine(\n json: WorkflowEdgeJSON,\n parentId?: string\n ): WorkflowLineEntity | undefined {\n const fromNode = this.getNode(json.sourceNodeID);\n const toNode = this.getNode(json.targetNodeID);\n // 脏数据清除\n if (!fromNode || !toNode) {\n return;\n }\n const lineInfo: WorkflowLinePortInfo = {\n from: json.sourceNodeID,\n fromPort: json.sourcePortID,\n to: json.targetNodeID,\n toPort: json.targetPortID,\n };\n if (!parentId) {\n return this.linesManager.createLine(lineInfo);\n }\n // 父子节点之间连线,需替换父节点为子画布\n const canvasNode = this.getNode(parentId);\n if (!canvasNode) {\n return this.linesManager.createLine(lineInfo);\n }\n const parentSubCanvas = this.getNodeSubCanvas(canvasNode);\n if (!parentSubCanvas) {\n return this.linesManager.createLine(lineInfo);\n }\n if (lineInfo.from === parentSubCanvas.parentNode.id) {\n return this.linesManager.createLine({\n ...lineInfo,\n from: parentSubCanvas.canvasNode.id,\n });\n }\n if (lineInfo.to === parentSubCanvas.parentNode.id) {\n return this.linesManager.createLine({\n ...lineInfo,\n to: parentSubCanvas.canvasNode.id,\n });\n }\n return this.linesManager.createLine(lineInfo);\n }\n}\n","import { inject, injectable } from 'inversify';\nimport {\n type IPoint,\n PaddingSchema,\n Rectangle,\n type ScrollSchema,\n SizeSchema,\n} from '@flowgram.ai/utils';\nimport {\n type FlowDocument,\n type FlowLayout,\n type FlowNodeEntity,\n FlowDocumentProvider,\n FlowNodeTransformData,\n} from '@flowgram.ai/document';\nimport { PlaygroundConfigEntity, TransformData } from '@flowgram.ai/core';\n\nexport const FREE_LAYOUT_KEY = 'free-layout';\n/**\n * 自由画布布局\n */\n@injectable()\nexport class FreeLayout implements FlowLayout {\n name = FREE_LAYOUT_KEY;\n\n @inject(PlaygroundConfigEntity) playgroundConfig: PlaygroundConfigEntity;\n\n @inject(FlowDocumentProvider)\n protected documentProvider: FlowDocumentProvider;\n\n get document(): FlowDocument {\n return this.documentProvider();\n }\n\n /**\n * 更新布局\n */\n update(): void {\n if (this.document.root.getData(FlowNodeTransformData)?.localDirty) {\n this.document.root.clearMemoGlobal();\n // this.document.root.getData(FlowNodeTransformData)!.localDirty = false\n }\n // 自由画布同步同步大小, TODO 这个移动到 createWorkflowNode\n // this.document.root.allChildren.forEach(this.syncTransform.bind(this))\n }\n\n syncTransform(node: FlowNodeEntity): void {\n const transform = node.getData<FlowNodeTransformData>(FlowNodeTransformData)!;\n if (!transform.localDirty) {\n return;\n }\n node.clearMemoGlobal();\n node.clearMemoLocal();\n // 同步 size 给原始的 transform\n transform.transform.update({\n size: transform.data.size,\n });\n if (!node.parent) {\n return;\n }\n node.parent.clearMemoGlobal();\n node.parent.clearMemoLocal();\n const parentTransform = node.parent.getData<FlowNodeTransformData>(FlowNodeTransformData);\n parentTransform.transform.fireChange();\n }\n\n /**\n * 更新所有受影响的上下游节点\n */\n updateAffectedTransform(node: FlowNodeEntity): void {\n const transformData = node.transform;\n if (!transformData.localDirty) {\n return;\n }\n const allParents = this.getAllParents(node);\n const allBlocks = this.getAllBlocks(node).reverse();\n const affectedNodes = [...allBlocks, ...allParents];\n affectedNodes.forEach((node) => {\n this.fireChange(node);\n });\n }\n\n /**\n * 获取节点的 padding 数据\n * @param node\n */\n getPadding(node: FlowNodeEntity): PaddingSchema {\n const { padding } = node.getNodeMeta();\n const transform = node.getData<FlowNodeTransformData>(FlowNodeTransformData);\n if (padding) {\n return typeof padding === 'function' ? padding(transform) : padding;\n }\n return PaddingSchema.empty();\n }\n\n /**\n * 默认滚动到 fitview 区域\n * @param contentSize\n */\n getInitScroll(contentSize: SizeSchema): ScrollSchema {\n const bounds = Rectangle.enlarge(\n this.document.getAllNodes().map((node) => node.getData<TransformData>(TransformData).bounds)\n ).pad(30, 30); // 留出 30 像素的边界\n const viewport = this.playgroundConfig.getViewport(false);\n const zoom = SizeSchema.fixSize(bounds, viewport);\n return {\n scrollX: (bounds.x + bounds.width / 2) * zoom - this.playgroundConfig.config.width / 2,\n scrollY: (bounds.y + bounds.height / 2) * zoom - this.playgroundConfig.config.height / 2,\n };\n }\n\n /**\n * 获取默认输入点\n */\n getDefaultInputPoint(node: FlowNodeEntity): IPoint {\n return node.getData<TransformData>(TransformData)!.bounds.leftCenter;\n }\n\n /**\n * 获取默认输出点\n */\n getDefaultOutputPoint(node: FlowNodeEntity): IPoint {\n return node.getData<TransformData>(TransformData)!.bounds.rightCenter;\n }\n\n /**\n * 水平中心点\n */\n getDefaultNodeOrigin(): IPoint {\n return { x: 0.5, y: 0 };\n }\n\n private getAllParents(node: FlowNodeEntity): FlowNodeEntity[] {\n const parents: FlowNodeEntity[] = [];\n let current = node.parent;\n\n while (current) {\n parents.push(current);\n current = current.parent;\n }\n\n return parents;\n }\n\n private getAllBlocks(node: FlowNodeEntity): FlowNodeEntity[] {\n return node.blocks.reduce<FlowNodeEntity[]>(\n (acc, child) => [...acc, ...this.getAllBlocks(child)],\n [node]\n );\n }\n\n private fireChange(node?: FlowNodeEntity): void {\n const transformData = node?.transform;\n if (!node || !transformData?.localDirty) {\n return;\n }\n node.clearMemoGlobal();\n node.clearMemoLocal();\n transformData.transform.fireChange();\n }\n}\n","import { inject, injectable, postConstruct } from 'inversify';\nimport { PlaygroundConfigEntity } from '@flowgram.ai/core';\nimport { EntityManager } from '@flowgram.ai/core';\nimport { DisposableCollection, Emitter, type IPoint } from '@flowgram.ai/utils';\n\nimport { WorkflowDocument } from '../workflow-document';\nimport { layoutToPositions } from '../utils/layout-to-positions';\nimport { fitView } from '../utils';\nimport { WorkflowNodeEntity } from '../entities';\n\nexport type PositionMap = Record<string, IPoint>;\n\n/**\n * 重置布局服务\n */\n@injectable()\nexport class WorkflowResetLayoutService {\n @inject(PlaygroundConfigEntity)\n private _config: PlaygroundConfigEntity;\n\n @inject(WorkflowDocument)\n private _document: WorkflowDocument;\n\n @inject(EntityManager)\n private _entityManager: EntityManager;\n\n private _resetLayoutEmitter = new Emitter<{\n nodeIds: string[];\n positionMap: PositionMap;\n oldPositionMap: PositionMap;\n }>();\n\n /**\n * reset layout事件\n */\n readonly onResetLayout = this._resetLayoutEmitter.event;\n\n private _toDispose = new DisposableCollection();\n\n /**\n * 初始化\n */\n @postConstruct()\n init() {\n this._toDispose.push(this._resetLayoutEmitter);\n }\n\n /**\n * 触发重置布局\n * @param nodeIds 节点id\n * @param positionMap 新布局数据\n * @param oldPositionMap 老布局数据\n */\n fireResetLayout(nodeIds: string[], positionMap: PositionMap, oldPositionMap: PositionMap) {\n this._resetLayoutEmitter.fire({\n nodeIds,\n positionMap,\n oldPositionMap,\n });\n }\n\n /**\n * 根据数据重新布局\n * @param positionMap\n * @returns\n */\n async layoutToPositions(nodeIds: string[], positionMap: PositionMap) {\n const nodes = nodeIds\n .map(id => this._entityManager.getEntityById(id))\n .filter(Boolean) as WorkflowNodeEntity[];\n const positions = await layoutToPositions(nodes, positionMap);\n fitView(this._document, this._config, true);\n return positions;\n }\n\n /**\n * 销毁\n */\n dispose() {\n this._toDispose.dispose();\n }\n}\n","import { type IPoint } from '@flowgram.ai/utils';\nimport { FlowNodeTransformData } from '@flowgram.ai/document';\nimport { TransformData, startTween } from '@flowgram.ai/core';\n\nimport { type WorkflowDocument } from '../workflow-document';\nimport { type WorkflowNodeEntity } from '../entities';\n\n/**\n * Coze 中节点坐标,以卡片顶部中间为原点。\n * autoLayout 计算出来的对齐的坐标以节点正中为原点,需要上移当前节点一般高度。\n * 即: newPosition.y - transform.bounds.height / 2\n * bounds 的原点坐标为左上角。\n */\nexport const layoutToPositions = async (\n nodes: WorkflowNodeEntity[],\n nodePositionMap: Record<string, IPoint>\n): Promise<Record<string, IPoint>> => {\n // 缓存上次位置,用来还原位置\n const newNodePositionMap: Record<string, IPoint> = {};\n nodes.forEach((node) => {\n const transform = node.getData(TransformData);\n const nodeTransform = node.getData(FlowNodeTransformData);\n\n newNodePositionMap[node.id] = {\n x: transform.position.x,\n y: transform.position.y + nodeTransform.bounds.height / 2,\n };\n });\n\n return new Promise((resolve) => {\n startTween({\n from: { d: 0 },\n to: { d: 100 },\n duration: 300,\n onUpdate: (v) => {\n nodes.forEach((node) => {\n const transform = node.getData(TransformData);\n const deltaX = ((nodePositionMap[node.id].x - transform.position.x) * v.d) / 100;\n const deltaY =\n ((nodePositionMap[node.id].y - transform.bounds.height / 2 - transform.position.y) *\n v.d) /\n 100;\n\n transform.update({\n position: {\n x: transform.position.x + deltaX,\n y: transform.position.y + deltaY,\n },\n });\n\n const document = node.document as WorkflowDocument;\n document.layout.updateAffectedTransform(node);\n });\n },\n onComplete: () => {\n resolve(newNodePositionMap);\n },\n });\n });\n};\n","import { inject } from 'inversify';\nimport { IPoint, Emitter } from '@flowgram.ai/utils';\nimport { FlowNodeEntityOrId, FlowOperationBaseServiceImpl } from '@flowgram.ai/document';\nimport { TransformData } from '@flowgram.ai/core';\n\nimport { WorkflowDocument } from '../workflow-document';\nimport {\n NodePostionUpdateEvent,\n WorkflowOperationBaseService,\n} from '../typings/workflow-operation';\n\nexport class WorkflowOperationBaseServiceImpl\n extends FlowOperationBaseServiceImpl\n implements WorkflowOperationBaseService\n{\n @inject(WorkflowDocument)\n protected declare document: WorkflowDocument;\n\n private onNodePostionUpdateEmitter = new Emitter<NodePostionUpdateEvent>();\n\n public readonly onNodePostionUpdate = this.onNodePostionUpdateEmitter.event;\n\n updateNodePosition(nodeOrId: FlowNodeEntityOrId, position: IPoint): void {\n const node = this.toNodeEntity(nodeOrId);\n\n if (!node) {\n return;\n }\n\n const transformData = node.getData(TransformData);\n const oldPosition = {\n x: transformData.position.x,\n y: transformData.position.y,\n };\n transformData.update({\n position,\n });\n\n this.onNodePostionUpdateEmitter.fire({\n node,\n oldPosition,\n newPosition: position,\n });\n }\n}\n","import { useEffect } from 'react';\n\nimport { usePlayground, useRefresh } from '@flowgram.ai/core';\nimport { type Disposable } from '@flowgram.ai/utils';\n\n/**\n * 获取 readonly 状态\n */\nexport function usePlaygroundReadonlyState(listenChange?: boolean): boolean {\n const playground = usePlayground();\n const refresh = useRefresh();\n useEffect(() => {\n let dispose: Disposable | undefined = undefined;\n if (listenChange) {\n dispose = playground.config.onReadonlyOrDisabledChange(() => refresh());\n }\n return () => dispose?.dispose();\n }, [listenChange]);\n return playground.config.readonly;\n}\n","import { FlowNodeRenderData } from '@flowgram.ai/document';\nimport { useEntityFromContext } from '@flowgram.ai/core';\n\nimport { type WorkflowNodeEntity } from '../entities';\n\n/**\n * 获取当前渲染的 dom 节点\n */\nexport function useCurrentDomNode(): HTMLDivElement {\n const entity = useEntityFromContext<WorkflowNodeEntity>();\n const renderData = entity.getData(FlowNodeRenderData)!;\n return renderData.node;\n}\n","import { useEntityFromContext } from '@flowgram.ai/core';\n\nimport { type WorkflowNodeEntity } from '../entities';\n\n/**\n * 获取当前节点\n */\nexport function useCurrentEntity(): WorkflowNodeEntity {\n return useEntityFromContext<WorkflowNodeEntity>();\n}\n","import { useService } from '@flowgram.ai/core';\n\nimport { WorkflowDocument } from '../workflow-document';\n\nexport function useWorkflowDocument(): WorkflowDocument {\n return useService<WorkflowDocument>(WorkflowDocument);\n}\n","export enum EditorCursorState {\n GRAB = 'GRAB',\n SELECT = 'SELECT',\n}\n\nexport enum InteractiveType {\n /** 鼠标优先交互模式 */\n MOUSE = 'MOUSE',\n\n /** 触控板优先交互模式 */\n PAD = 'PAD',\n}\n","import { ContainerModule } from 'inversify';\nimport { bindContributions } from '@flowgram.ai/utils';\nimport { FlowDocument, FlowDocumentContribution } from '@flowgram.ai/document';\n\nimport { WorkflowLinesManager } from './workflow-lines-manager';\nimport {\n WorkflowDocumentOptions,\n WorkflowDocumentOptionsDefault,\n} from './workflow-document-option';\nimport { WorkflowDocumentContribution } from './workflow-document-contribution';\nimport { WorkflowDocument, WorkflowDocumentProvider } from './workflow-document';\nimport { getUrlParams } from './utils/get-url-params';\nimport { URLParams, WorkflowOperationBaseService } from './typings';\nimport {\n WorkflowDragService,\n WorkflowHoverService,\n WorkflowSelectService,\n WorkflowResetLayoutService,\n WorkflowOperationBaseServiceImpl,\n} from './service';\nimport { FreeLayout } from './layout';\n\nexport const WorkflowDocumentContainerModule = new ContainerModule(\n (bind, unbind, isBound, rebind) => {\n bind(WorkflowDocument).toSelf().inSingletonScope();\n bind(WorkflowLinesManager).toSelf().inSingletonScope();\n bind(FreeLayout).toSelf().inSingletonScope();\n bind(WorkflowDragService).toSelf().inSingletonScope();\n bind(WorkflowSelectService).toSelf().inSingletonScope();\n bind(WorkflowHoverService).toSelf().inSingletonScope();\n bind(WorkflowResetLayoutService).toSelf().inSingletonScope();\n bind(WorkflowOperationBaseService).to(WorkflowOperationBaseServiceImpl).inSingletonScope();\n bind(URLParams)\n .toDynamicValue(() => getUrlParams())\n .inSingletonScope();\n bindContributions(bind, WorkflowDocumentContribution, [FlowDocumentContribution]);\n bind(WorkflowDocumentOptions).toConstantValue({\n ...WorkflowDocumentOptionsDefault,\n });\n rebind(FlowDocument).toService(WorkflowDocument);\n bind(WorkflowDocumentProvider)\n .toDynamicValue((ctx) => () => ctx.container.get(WorkflowDocument))\n .inSingletonScope();\n }\n);\n","import { injectable, inject } from 'inversify';\nimport {\n type FlowDocumentContribution,\n FlowNodeRenderData,\n FlowNodeTransformData,\n} from '@flowgram.ai/document';\n\nimport { WorkflowDocument } from './workflow-document';\nimport { FreeLayout } from './layout';\nimport { WorkflowNodeLinesData, WorkflowNodePortsData } from './entity-datas';\n\n@injectable()\nexport class WorkflowDocumentContribution implements FlowDocumentContribution<WorkflowDocument> {\n @inject(FreeLayout) freeLayout: FreeLayout;\n\n registerDocument(document: WorkflowDocument): void {\n // 注册节点数据\n document.registerNodeDatas(\n FlowNodeTransformData,\n FlowNodeRenderData,\n WorkflowNodePortsData,\n WorkflowNodeLinesData,\n );\n document.registerLayout(this.freeLayout);\n }\n}\n","export function getUrlParams(): Record<string, string> {\n return location.search\n .replace(/^\\?/, '')\n .split('&')\n .reduce((res: Record<string, string>, key) => {\n const [k, v] = key.split('=');\n res[k] = v;\n return res;\n }, {} satisfies Record<string, string>);\n}\n","import { IPoint, Point, Rectangle } from '@flowgram.ai/utils';\n\nimport { WorkflowLineRenderContribution } from '../typings';\nimport { POINT_RADIUS, WorkflowLineEntity } from '../entities';\n\nconst LINE_PADDING = 12;\n\nexport interface StraightData {\n points: IPoint[];\n path: string;\n bbox: Rectangle;\n}\n\nexport class WorkflowSimpleLineContribution implements WorkflowLineRenderContribution {\n public static type = 'WorkflowSimpleLineContribution';\n\n public entity: WorkflowLineEntity;\n\n constructor(entity: WorkflowLineEntity) {\n this.entity = entity;\n }\n\n private data?: StraightData;\n\n public get path(): string {\n return this.data?.path ?? '';\n }\n\n public calcDistance(pos: IPoint): number {\n if (!this.data) {\n return Number.MAX_SAFE_INTEGER;\n }\n const [start, end] = this.data.points;\n return Point.getDistance(pos, this.projectPointOnLine(pos, start, end));\n }\n\n public get bounds(): Rectangle {\n if (!this.data) {\n return new Rectangle();\n }\n return this.data.bbox;\n }\n\n public update(params: { fromPos: IPoint; toPos: IPoint }): void {\n const { fromPos, toPos } = params;\n const { vertical } = this.entity;\n\n // 根据方向预先计算源点和目标点的偏移\n const sourceOffset = {\n x: vertical ? 0 : POINT_RADIUS,\n y: vertical ? POINT_RADIUS : 0,\n };\n const targetOffset = {\n x: vertical ? 0 : -POINT_RADIUS,\n y: vertical ? -POINT_RADIUS : 0,\n };\n\n const points = [\n {\n x: fromPos.x + sourceOffset.x,\n y: fromPos.y + sourceOffset.y,\n },\n {\n x: toPos.x + targetOffset.x,\n y: toPos.y + targetOffset.y,\n },\n ];\n\n const bbox = Rectangle.createRectangleWithTwoPoints(points[0], points[1]);\n\n // 调整所有点到 SVG 视口坐标系\n const adjustedPoints = points.map((p) => ({\n x: p.x - bbox.x + LINE_PADDING,\n y: p.y - bbox.y + LINE_PADDING,\n }));\n\n // 生成直线路径\n const path = `M ${adjustedPoints[0].x} ${adjustedPoints[0].y} L ${adjustedPoints[1].x} ${adjustedPoints[1].y}`;\n\n this.data = {\n points,\n path,\n bbox,\n };\n }\n\n private projectPointOnLine(point: IPoint, lineStart: IPoint, lineEnd: IPoint): IPoint {\n const dx = lineEnd.x - lineStart.x;\n const dy = lineEnd.y - lineStart.y;\n\n // 如果是垂直线\n if (dx === 0) {\n return { x: lineStart.x, y: point.y };\n }\n // 如果是水平线\n if (dy === 0) {\n return { x: point.x, y: lineStart.y };\n }\n\n const t = ((point.x - lineStart.x) * dx + (point.y - lineStart.y) * dy) / (dx * dx + dy * dy);\n const clampedT = Math.max(0, Math.min(1, t));\n\n return {\n x: lineStart.x + clampedT * dx,\n y: lineStart.y + clampedT * dy,\n };\n }\n}\n"],"mappings":"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","names":["WorkflowCommands","import_core","import_react","import_document","import_core","import_core","import_utils","import_core","import_utils","nanoidOrigin","import_utils","import_core","import_utils","import_lodash_es","import_utils","import_core","import_document","import_core","import_utils","import_document","import_core","document","import_utils","import_core","import_utils","import_core","fitView","import_inversify","import_utils","import_core","import_nanoid","import_inversify","import_utils","import_document","import_core","import_lodash_es","import_inversify","import_utils","import_document","import_core","import_form_core","import_document","import_core","WorkflowContentChangeType","LineType","LineColors","import_nanoid","import_inversify","import_utils","import_form_core","import_document","import_core","import_inversify","import_utils","import_document","import_core","node","nanoid","layout","offset","import_inversify","import_core","import_utils","import_document","import_core","document","import_inversify","import_utils","import_document","import_core","import_core","import_document","import_core","import_core","import_core","EditorCursorState","InteractiveType","import_inversify","import_utils","import_document","import_inversify","import_document","document","import_utils"]}
|