UNPKG

@flowgram.ai/document

Version:

automation flow engine

1,636 lines (1,619 loc) 102 kB
"use strict"; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __hasOwnProp = Object.prototype.hasOwnProperty; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); var __decorateClass = (decorators, target, key, kind) => { var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target; for (var i = decorators.length - 1, decorator; i >= 0; i--) if (decorator = decorators[i]) result = (kind ? decorator(target, key, result) : decorator(result)) || result; if (kind && result) __defProp(target, key, result); return result; }; var __decorateParam = (index, decorator) => (target, key) => decorator(target, key, index); // src/index.ts var index_exports = {}; __export(index_exports, { ConstantKeys: () => ConstantKeys, DEFAULT_FLOW_NODE_META: () => DEFAULT_FLOW_NODE_META, DEFAULT_SIZE: () => DEFAULT_SIZE, DEFAULT_SPACING: () => DEFAULT_SPACING, DRAGGING_TYPE: () => DRAGGING_TYPE, DefaultSpacingKey: () => DefaultSpacingKey, FLOW_DEFAULT_HIDDEN_TYPES: () => FLOW_DEFAULT_HIDDEN_TYPES, FlowDocument: () => FlowDocument, FlowDocumentConfig: () => FlowDocumentConfig, FlowDocumentConfigDefaultData: () => FlowDocumentConfigDefaultData, FlowDocumentConfigEnum: () => FlowDocumentConfigEnum, FlowDocumentContainerModule: () => FlowDocumentContainerModule, FlowDocumentContribution: () => FlowDocumentContribution, FlowDocumentOptions: () => FlowDocumentOptions, FlowDocumentOptionsDefault: () => FlowDocumentOptionsDefault, FlowDocumentProvider: () => FlowDocumentProvider, FlowDocumentTransformerEntity: () => FlowDocumentTransformerEntity, FlowDragService: () => FlowDragService, FlowGroupController: () => FlowGroupController, FlowGroupService: () => FlowGroupService, FlowLayout: () => FlowLayout, FlowLayoutContribution: () => FlowLayoutContribution, FlowLayoutDefault: () => FlowLayoutDefault, FlowNodeBaseType: () => FlowNodeBaseType, FlowNodeEntity: () => FlowNodeEntity, FlowNodeRegistry: () => FlowNodeRegistry, FlowNodeRenderData: () => FlowNodeRenderData, FlowNodeSplitType: () => FlowNodeSplitType, FlowNodeTransformData: () => FlowNodeTransformData, FlowNodeTransitionData: () => FlowNodeTransitionData, FlowOperationBaseService: () => FlowOperationBaseService, FlowOperationBaseServiceImpl: () => FlowOperationBaseServiceImpl, FlowRendererStateEntity: () => FlowRendererStateEntity, FlowTransitionLabelEnum: () => FlowTransitionLabelEnum, FlowTransitionLineEnum: () => FlowTransitionLineEnum, FlowVirtualTree: () => FlowVirtualTree, LABEL_SIDE_TYPE: () => LABEL_SIDE_TYPE, OperationType: () => OperationType, drawLineToBottom: () => drawLineToBottom, drawLineToNext: () => drawLineToNext, getDefaultSpacing: () => getDefaultSpacing }); module.exports = __toCommonJS(index_exports); // src/typings/flow.ts var FlowNodeBaseType = /* @__PURE__ */ ((FlowNodeBaseType2) => { FlowNodeBaseType2["START"] = "start"; FlowNodeBaseType2["DEFAULT"] = "default"; FlowNodeBaseType2["ROOT"] = "root"; FlowNodeBaseType2["EMPTY"] = "empty"; FlowNodeBaseType2["INLINE_BLOCKS"] = "inlineBlocks"; FlowNodeBaseType2["BLOCK_ICON"] = "blockIcon"; FlowNodeBaseType2["BLOCK"] = "block"; FlowNodeBaseType2["BLOCK_ORDER_ICON"] = "blockOrderIcon"; FlowNodeBaseType2["GROUP"] = "group"; FlowNodeBaseType2["END"] = "end"; FlowNodeBaseType2["BREAK"] = "break"; FlowNodeBaseType2["CONDITION"] = "condition"; FlowNodeBaseType2["SUB_CANVAS"] = "subCanvas"; FlowNodeBaseType2["MULTI_INPUTS"] = "multiInputs"; FlowNodeBaseType2["MULTI_OUTPUTS"] = "multiOutputs"; FlowNodeBaseType2["INPUT"] = "input"; FlowNodeBaseType2["OUTPUT"] = "output"; FlowNodeBaseType2["SLOT"] = "slot"; FlowNodeBaseType2["SLOT_BLOCK"] = "slotBlock"; return FlowNodeBaseType2; })(FlowNodeBaseType || {}); var FlowNodeSplitType = /* @__PURE__ */ ((FlowNodeSplitType2) => { FlowNodeSplitType2["SIMPLE_SPLIT"] = "simpleSplit"; FlowNodeSplitType2["DYNAMIC_SPLIT"] = "dynamicSplit"; FlowNodeSplitType2["STATIC_SPLIT"] = "staticSplit"; return FlowNodeSplitType2; })(FlowNodeSplitType || {}); var FlowDocumentConfigEnum = /* @__PURE__ */ ((FlowDocumentConfigEnum2) => { FlowDocumentConfigEnum2["END_NODES_REFINE_BRANCH"] = "END_NODES_REFINE_BRANCH"; return FlowDocumentConfigEnum2; })(FlowDocumentConfigEnum || {}); var FLOW_DEFAULT_HIDDEN_TYPES = [ "root" /* ROOT */, "inlineBlocks" /* INLINE_BLOCKS */, "block" /* BLOCK */ ]; // src/typings/flow-layout.ts var FlowLayout = Symbol("FlowLayout"); var FlowLayoutContribution = Symbol("FlowLayoutContribution"); var FlowLayoutDefault = /* @__PURE__ */ ((FlowLayoutDefault2) => { FlowLayoutDefault2["VERTICAL_FIXED_LAYOUT"] = "vertical-fixed-layout"; FlowLayoutDefault2["HORIZONTAL_FIXED_LAYOUT"] = "horizontal-fixed-layout"; return FlowLayoutDefault2; })(FlowLayoutDefault || {}); ((FlowLayoutDefault2) => { function isVertical(layout) { return layout.name === "vertical-fixed-layout" /* VERTICAL_FIXED_LAYOUT */; } FlowLayoutDefault2.isVertical = isVertical; })(FlowLayoutDefault || (FlowLayoutDefault = {})); // src/typings/flow-transition.ts var FlowTransitionLineEnum = /* @__PURE__ */ ((FlowTransitionLineEnum2) => { FlowTransitionLineEnum2[FlowTransitionLineEnum2["STRAIGHT_LINE"] = 0] = "STRAIGHT_LINE"; FlowTransitionLineEnum2[FlowTransitionLineEnum2["DIVERGE_LINE"] = 1] = "DIVERGE_LINE"; FlowTransitionLineEnum2[FlowTransitionLineEnum2["MERGE_LINE"] = 2] = "MERGE_LINE"; FlowTransitionLineEnum2[FlowTransitionLineEnum2["ROUNDED_LINE"] = 3] = "ROUNDED_LINE"; FlowTransitionLineEnum2[FlowTransitionLineEnum2["CUSTOM_LINE"] = 4] = "CUSTOM_LINE"; FlowTransitionLineEnum2[FlowTransitionLineEnum2["DRAGGING_LINE"] = 5] = "DRAGGING_LINE"; return FlowTransitionLineEnum2; })(FlowTransitionLineEnum || {}); var FlowTransitionLabelEnum = /* @__PURE__ */ ((FlowTransitionLabelEnum2) => { FlowTransitionLabelEnum2[FlowTransitionLabelEnum2["ADDER_LABEL"] = 0] = "ADDER_LABEL"; FlowTransitionLabelEnum2[FlowTransitionLabelEnum2["TEXT_LABEL"] = 1] = "TEXT_LABEL"; FlowTransitionLabelEnum2[FlowTransitionLabelEnum2["COLLAPSE_LABEL"] = 2] = "COLLAPSE_LABEL"; FlowTransitionLabelEnum2[FlowTransitionLabelEnum2["COLLAPSE_ADDER_LABEL"] = 3] = "COLLAPSE_ADDER_LABEL"; FlowTransitionLabelEnum2[FlowTransitionLabelEnum2["CUSTOM_LABEL"] = 4] = "CUSTOM_LABEL"; FlowTransitionLabelEnum2[FlowTransitionLabelEnum2["BRANCH_DRAGGING_LABEL"] = 5] = "BRANCH_DRAGGING_LABEL"; return FlowTransitionLabelEnum2; })(FlowTransitionLabelEnum || {}); // src/typings/flow-node-register.ts var DefaultSpacingKey = { /** * 普通节点间距。垂直 / 水平 */ NODE_SPACING: "SPACING", /** * 分支节点间距 */ BRANCH_SPACING: "BRANCH_SPACING", /** * 圆弧线条拐角 radius */ ROUNDED_LINE_RADIUS: "ROUNDED_LINE_RADIUS", /** * 圆弧线条 x radius */ ROUNDED_LINE_X_RADIUS: "ROUNDED_LINE_X_RADIUS", /** * 圆弧线条 y radius */ ROUNDED_LINE_Y_RADIUS: "ROUNDED_LINE_Y_RADIUS", /** * dynamicSplit block list 下部留白间距,因为有两个拐弯,所以翻一倍 */ INLINE_BLOCKS_PADDING_BOTTOM: "INLINE_BLOCKS_PADDING_BOTTOM", /** * 复合节点距离上个节点的距离 * 条件分支菱形下边和分支的距离 */ COLLAPSED_SPACING: "COLLAPSED_SPACING", /** * width of hover area */ HOVER_AREA_WIDTH: "HOVER_AREA_WIDTH" }; var DEFAULT_SPACING = { NULL: 0, [DefaultSpacingKey.NODE_SPACING]: 32, // 普通节点间距。垂直 / 水平 [DefaultSpacingKey.BRANCH_SPACING]: 20, // 分支节点间距 /** * @deprecated use 'BRANCH_SPACING' instead */ MARGIN_RIGHT: 20, // 分支节点右边间距 INLINE_BLOCK_PADDING_BOTTOM: 16, // block 底部留白 INLINE_BLOCKS_PADDING_TOP: 30, // block list 上部留白间距 // JS 浮点数有误差,1046.6 -1006.6 = 39.9999999,会导致 间距/20 < 2 导致布局计算问题,因此需要额外增加 0.1 像素 [DefaultSpacingKey.INLINE_BLOCKS_PADDING_BOTTOM]: 40.1, // block lit 下部留白间距,因为有两个拐弯,所以翻一倍 MIN_INLINE_BLOCK_SPACING: 200, // 分支间最小边距 (垂直布局) MIN_INLINE_BLOCK_SPACING_HORIZONTAL: 80, // 分支间最小边距 (水平布局) [DefaultSpacingKey.COLLAPSED_SPACING]: 12, // 复合节点距离上个节点的距离 [DefaultSpacingKey.ROUNDED_LINE_RADIUS]: 16, // 圆弧线条拐角 radius [DefaultSpacingKey.ROUNDED_LINE_X_RADIUS]: 16, // 圆弧线条 x radius [DefaultSpacingKey.ROUNDED_LINE_Y_RADIUS]: 20, // 圆弧线条 y radius [DefaultSpacingKey.HOVER_AREA_WIDTH]: 20 // width of hover area }; var DRAGGING_TYPE = /* @__PURE__ */ ((DRAGGING_TYPE2) => { DRAGGING_TYPE2["NODE"] = "node"; DRAGGING_TYPE2["BRANCH"] = "branch"; return DRAGGING_TYPE2; })(DRAGGING_TYPE || {}); var LABEL_SIDE_TYPE = /* @__PURE__ */ ((LABEL_SIDE_TYPE2) => { LABEL_SIDE_TYPE2["PRE_BRANCH"] = "pre_branch"; LABEL_SIDE_TYPE2["NORMAL_BRANCH"] = "normal_branch"; return LABEL_SIDE_TYPE2; })(LABEL_SIDE_TYPE || {}); var DEFAULT_SIZE = { width: 280, height: 60 }; var DEFAULT_FLOW_NODE_META = (nodeType, document) => { const hidden = FLOW_DEFAULT_HIDDEN_TYPES.includes(nodeType); return { isStart: nodeType === "start", hidden, defaultExpanded: document.options.allNodesDefaultExpanded, size: DEFAULT_SIZE, origin: document.layout.getDefaultNodeOrigin(), isInlineBlocks: nodeType === "inlineBlocks" /* INLINE_BLOCKS */, // miniSize: { width: 200, height: 40 }, spacing: DEFAULT_SPACING.SPACING, inlineSpacingPre: 0, inlineSpacingAfter: 0, expandable: true, draggable: true, selectable: true, renderKey: "", minInlineBlockSpacing: () => { const isVertical = FlowLayoutDefault.isVertical(document.layout); return isVertical ? DEFAULT_SPACING.MIN_INLINE_BLOCK_SPACING : DEFAULT_SPACING.MIN_INLINE_BLOCK_SPACING_HORIZONTAL; } }; }; var FlowNodeRegistry; ((FlowNodeRegistry4) => { function mergeChildRegistries(r1 = [], r2 = []) { if (r1.length === 0 || r2.length === 0) { return [...r1, ...r2]; } const r1Filter = r1.map((r1Current) => { const r2Current = r2.find((n) => n.type === r1Current.type); if (r2Current) { return merge(r1Current, r2Current, r1Current.type); } return r1Current; }); const r2Filter = r2.filter((n) => !r1.some((r) => r.type === n.type)); return [...r1Filter, ...r2Filter]; } FlowNodeRegistry4.mergeChildRegistries = mergeChildRegistries; function merge(registry1, registry2, finalType) { const extendKeys = registry1.__extends__ ? registry1.__extends__.slice() : []; if (registry1.type !== registry2.type) { extendKeys.unshift(registry1.type); } return { ...registry1, ...registry2, extendChildRegistries: mergeChildRegistries( registry1.extendChildRegistries, registry2.extendChildRegistries ), meta: { ...registry1.meta, ...registry2.meta }, extend: void 0, type: finalType, __extends__: extendKeys }; } FlowNodeRegistry4.merge = merge; function extend(registry, extendRegistries) { if (!extendRegistries.length) return registry; return extendRegistries.reduce((res, ext) => merge(res, ext, registry.type), registry); } FlowNodeRegistry4.extend = extend; })(FlowNodeRegistry || (FlowNodeRegistry = {})); // src/typings/flow-operation.ts var OperationType = /* @__PURE__ */ ((OperationType2) => { OperationType2["addFromNode"] = "addFromNode"; OperationType2["deleteFromNode"] = "deleteFromNode"; OperationType2["addBlock"] = "addBlock"; OperationType2["deleteBlock"] = "deleteBlock"; OperationType2["createGroup"] = "createGroup"; OperationType2["ungroup"] = "ungroup"; OperationType2["moveNodes"] = "moveNodes"; OperationType2["moveBlock"] = "moveBlock"; OperationType2["moveChildNodes"] = "moveChildNodes"; OperationType2["addNodes"] = "addNodes"; OperationType2["deleteNodes"] = "deleteNodes"; OperationType2["addChildNode"] = "addChildNode"; OperationType2["deleteChildNode"] = "deleteChildNode"; OperationType2["addNode"] = "addNode"; OperationType2["deleteNode"] = "deleteNode"; return OperationType2; })(OperationType || {}); var FlowOperationBaseService = Symbol("FlowOperationBaseService"); // src/entities/flow-node-entity.ts var import_core4 = require("@flowgram.ai/core"); // src/datas/flow-node-transform-data.ts var import_utils2 = require("@flowgram.ai/utils"); var import_core2 = require("@flowgram.ai/core"); // src/datas/flow-node-render-data.ts var import_utils = require("@flowgram.ai/utils"); var import_core = require("@flowgram.ai/core"); var _FlowNodeRenderData = class _FlowNodeRenderData extends import_core.EntityData { constructor(entity) { super(entity); this.onExtInfoChangeEmitter = new import_utils.Emitter(); this.onExtInfoChange = this.onExtInfoChangeEmitter.event; this.toDispose.push( import_utils.Disposable.create(() => { if (this._node) this._node.remove(); }) ); } get key() { return this.entity.id; } getDefaultData() { const { addable, expandable, defaultExpanded } = this.entity.getNodeMeta(); return { addable, expandable, expanded: defaultExpanded || false, activated: false, hovered: false, dragging: false, stackIndex: 0 }; } updateExtInfo(info, fullUpdate) { const oldInfo = this.data.extInfo; const newInfo = fullUpdate ? info : { ...oldInfo, ...info }; if (import_utils.Compare.isChanged(oldInfo, newInfo)) { this.update({ extInfo: newInfo }); this.onExtInfoChangeEmitter.fire({ oldInfo, newInfo }); } } getExtInfo() { return this.data.extInfo; } get addable() { return this.data.addable; } get expandable() { return this.data.expandable; } get draggable() { const { draggable } = this.entity.getNodeMeta(); if (typeof draggable === "function") { return draggable(this.entity); } return draggable; } get expanded() { return this.data.expanded; } set expanded(expanded) { if (this.expandable && this.data.expanded !== expanded) { this.data.expanded = expanded; this.fireChange(); } } toggleExpand() { this.expanded = !this.expanded; } toggleMouseEnter(silent = false) { this.entity.document.renderState.setNodeHovered(this.entity); if (silent) return; const transform = this.entity.getData(FlowNodeTransformData); if (transform.renderState.hidden) { return; } if (this.mouseLeaveTimeout) { clearTimeout(this.mouseLeaveTimeout); this.mouseLeaveTimeout = void 0; } transform.renderState.hovered = true; if (this.entity.isFirst && this.entity.parent?.id !== "root") { transform.parent.renderState.activated = true; } else { transform.renderState.activated = true; } } toggleMouseLeave(silent = false) { this.entity.document.renderState.setNodeHovered(void 0); if (silent) return; const transform = this.entity.getData(FlowNodeTransformData); this.mouseLeaveTimeout = setTimeout(() => { transform.renderState.hovered = false; if (this.entity.isFirst && this.entity.parent?.id !== "root") { transform.parent.renderState.activated = false; } transform.renderState.activated = false; }, 200); } get hidden() { return this.entity.hidden; } set hovered(hovered) { this.data.hovered = hovered; this.fireChange(); } get hovered() { return this.data.hovered; } get dragging() { return this.data.dragging; } set dragging(dragging) { if (this.data.dragging !== dragging) { this.data.dragging = dragging; this.fireChange(); } } set activated(activated) { if (this.entity.flowNodeType === "blockIcon" /* BLOCK_ICON */ && this.entity.parent) { this.entity.parent.getData(_FlowNodeRenderData).activated = activated; return; } if (this.data.activated !== activated) { this.data.activated = activated; this.fireChange(); } } get activated() { const { entity } = this; if (entity.parent && entity.parent.getData(_FlowNodeRenderData).activated) { return true; } return this.data.activated; } get stackIndex() { return this.data.stackIndex; } set stackIndex(index) { this.data.stackIndex = index; } get lineActivated() { const { activated } = this; if (!activated) return false; return Boolean( this.entity.parent?.getData(_FlowNodeRenderData)?.activated || this.entity.isInlineBlock || this.entity.next?.getData(_FlowNodeRenderData).activated ); } get node() { if (this._node) return this._node; this._node = import_utils.domUtils.createDivWithClass("gedit-flow-activity-node"); this._node.dataset.testid = "sdk.workflow.canvas.node"; this._node.dataset.nodeId = this.entity.id; return this._node; } dispose() { super.dispose(); this.onExtInfoChangeEmitter.dispose(); } }; _FlowNodeRenderData.type = "FlowNodeRenderData"; var FlowNodeRenderData = _FlowNodeRenderData; // src/datas/flow-node-transform-data.ts var _FlowNodeTransformData = class _FlowNodeTransformData extends import_core2.EntityData { constructor(entity) { super(entity); this.localDirty = true; const { origin } = this.entity.getNodeMeta(); this.transform = this.entity.addData(import_core2.TransformData); this.transform.changeLocked = true; this.transform.update({ origin: { ...origin } }); this.transform.changeLocked = false; this.renderState = this.entity.addData(FlowNodeRenderData); this.bindChange(this.transform); this.toDispose.push( import_utils2.Disposable.create(() => { const { next, parent } = this; if (next) next.localDirty = true; if (parent) parent.localDirty = true; }) ); } get origin() { return this.transform.origin; } get key() { return this.entity.id; } getDefaultData() { const { size, hidden } = this.entity.getNodeMeta(); return { size: !hidden ? { ...size } : { width: 0, height: 0 } }; } /** * 获取节点是否展开 */ get collapsed() { return this.entity.collapsed; } set collapsed(collapsed) { this.entity.collapsed = collapsed; this.localDirty = true; if (this.firstChild) this.firstChild.localDirty = true; this.fireChange(); } /** * 获取节点的大小 */ get size() { return this.entity.memoGlobal("size", () => { if (this.isContainer) return this.transform.localSize; return this.data.size; }); } get position() { const { position } = this.transform; return { x: position.x, y: position.y }; } set position(position) { this.transform.update({ position }); } set size(size) { const { width, height } = this.data.size; if (this.isContainer) return; if (size.width !== width || size.height !== height) { this._data.size = { ...size }; this.localDirty = true; this.fireChange(); } } get inputPoint() { return this.entity.memoGlobal("inputPoint", () => { const { getInputPoint } = this.entity.getNodeRegistry(); return getInputPoint ? getInputPoint(this, this.entity.document.layout) : this.defaultInputPoint; }); } get defaultInputPoint() { return this.entity.memoGlobal( "defaultInputPoint", () => this.entity.document.layout.getDefaultInputPoint(this.entity) ); } get defaultOutputPoint() { return this.entity.memoGlobal( "defaultOutputPoint", () => this.entity.document.layout.getDefaultOutputPoint(this.entity) ); } get outputPoint() { return this.entity.memoGlobal("outputPoint", () => { const { getOutputPoint } = this.entity.getNodeRegistry(); return getOutputPoint ? getOutputPoint(this, this.entity.document.layout) : this.defaultOutputPoint; }); } /** * 原点的最左偏移 */ get originDeltaX() { return this.entity.memoLocal("originDeltaX", () => { const { children } = this; const { getOriginDeltaX } = this.entity.getNodeRegistry(); if (getOriginDeltaX) return getOriginDeltaX(this, this.entity.document.layout); if (children.length === 0) { return -this.size.width * this.origin.x; } if (children.length === 1) return children[0].originDeltaX; if (this.entity.isInlineBlocks && children.length > 1) { return children[0].originDeltaX + this.transform.position.x; } return children.reduce((res, child) => { const deltaX = child.originDeltaX; return res === void 0 || deltaX < res ? deltaX : res; }, void 0); }); } /** * 原点 y 轴偏移 */ get originDeltaY() { return this.entity.memoLocal("originDeltaY", () => { const { children } = this; const { getOriginDeltaY } = this.entity.getNodeRegistry(); if (getOriginDeltaY) return getOriginDeltaY(this, this.entity.document.layout); if (children.length === 0) { return -this.size.height * this.origin.y; } if (children.length === 1) return children[0].originDeltaY; if (this.entity.isInlineBlocks && children.length > 1) { return children[0].originDeltaY + this.transform.position.y; } return children.reduce((res, child) => { const deltaY = child.originDeltaY; return res === void 0 || deltaY < res ? deltaY : res; }, void 0); }); } /** * 绝对坐标 bbox, 不包含自身的 spacing(marginBottom), 但是包含 inlineSpacing 和 子节点的 spacing */ get bounds() { return this.entity.memoGlobal("bounds", () => { const { transform } = this; if (this.isContainer) { const childrenRects = transform.children.map( (c) => c.entity.getData(_FlowNodeTransformData).boundsWithPadding ); return import_utils2.Rectangle.enlarge(childrenRects).withPadding(this.padding); } return transform.bounds; }); } get boundsWithPadding() { return this.entity.memoGlobal("boundsWithPadding", () => { const { transform } = this; if (this.isContainer) { const childrenRects = transform.children.map( (c) => c.entity.getData(_FlowNodeTransformData).boundsWithPadding ); return import_utils2.Rectangle.enlarge(childrenRects).withPadding(this.padding); } return transform.bounds.clone().withPadding(this.padding); }); } get isContainer() { return this.transform.isContainer; } /** * 相对坐标 bbox, 这里的 localBounds 会加入 padding 一起算 */ get localBounds() { return this.entity.memoLocal("localBounds", () => { const { transform } = this; if (this.isContainer) { const childrenRects = transform.children.map( (c) => c.entity.getData(_FlowNodeTransformData).localBounds ); const childrenBounds = import_utils2.Rectangle.enlarge(childrenRects).withPadding(this.padding); return import_core2.Bounds.applyMatrix(childrenBounds, transform.localTransform); } return transform.localBounds.clone().withPadding(this.padding); }); } get padding() { return this.entity.document.layout.getPadding(this.entity); } setParentTransform(transform) { if (this.transform.parent !== transform?.transform) { this.localDirty = true; } this.transform.setParent(transform?.transform); } get spacing() { const { spacing } = this.entity.getNodeMeta(); return typeof spacing === "function" ? spacing(this) : spacing; } get inlineSpacingPre() { const { inlineSpacingPre } = this.entity.getNodeMeta(); return typeof inlineSpacingPre === "function" ? inlineSpacingPre(this) : inlineSpacingPre; } get inlineSpacingAfter() { const { inlineSpacingAfter } = this.entity.getNodeMeta(); return typeof inlineSpacingAfter === "function" ? inlineSpacingAfter(this) : inlineSpacingAfter; } get minInlineBlockSpacing() { const { minInlineBlockSpacing } = this.entity.getNodeMeta(); return typeof minInlineBlockSpacing === "function" ? minInlineBlockSpacing(this) : minInlineBlockSpacing; } get children() { return this.entity.children.map( (child) => child.getData(_FlowNodeTransformData) ); } /** * 上一个节点的 transform 数据 */ get pre() { return this.entity.pre?.getData(_FlowNodeTransformData); } get originParent() { return this.entity.originParent?.getData(_FlowNodeTransformData); } get isFirst() { return this.entity.isFirst; } get isLast() { return this.entity.isLast; } get lastChild() { return this.entity.lastChild?.getData(_FlowNodeTransformData); } get firstChild() { return this.entity.firstChild?.getData(_FlowNodeTransformData); } /** * 下一个节点的 transform 数据 */ get next() { return this.entity.next?.getData(_FlowNodeTransformData); } /** * parent 节点的 transform 数据 */ get parent() { return this.entity.parent?.getData(_FlowNodeTransformData); } }; _FlowNodeTransformData.type = "FlowNodeTransformData"; var FlowNodeTransformData = _FlowNodeTransformData; // src/datas/flow-node-transition-data.ts var import_utils3 = require("@flowgram.ai/utils"); var import_core3 = require("@flowgram.ai/core"); var drawLineToNext = (transition) => { const { transform } = transition; const currentOutput = transform.outputPoint; if (transform.next) { return [ { type: 0 /* STRAIGHT_LINE */, from: currentOutput, to: transform.next.inputPoint } ]; } return []; }; var drawLineToBottom = (transition) => { const { transform } = transition; const currentOutput = transform.outputPoint; const isParentRoot = transform.parent?.entity.flowNodeType === "root" /* ROOT */; const parentOutput = transform.parent?.outputPoint; if (!isParentRoot && !transform.next && parentOutput && !new import_utils3.Point().copyFrom(currentOutput).equals(parentOutput) && !transition.isNodeEnd) { return [ { type: 0 /* STRAIGHT_LINE */, from: currentOutput, to: parentOutput } ]; } return []; }; var FlowNodeTransitionData = class extends import_core3.EntityData { getDefaultData() { return {}; } formatLines(lines) { if (this.entity.document.options?.formatNodeLines) { return this.entity.document.options?.formatNodeLines?.(this.entity, lines); } return lines; } formatLabels(labels) { if (this.entity.document.options.formatNodeLabels) { return this.entity.document.options?.formatNodeLabels?.(this.entity, labels); } return labels; } get lines() { return this.entity.memoGlobal("lines", () => { const { getChildLines } = this.entity.parent?.getNodeRegistry() || {}; if (getChildLines) { return this.formatLines(getChildLines(this, this.entity.document.layout)); } const { getLines } = this.entity.getNodeRegistry(); if (getLines) { return this.formatLines(getLines(this, this.entity.document.layout)); } if (this.transform.entity.isInlineBlock) { return []; } return this.formatLines([...drawLineToNext(this), ...drawLineToBottom(this)]); }); } get labels() { return this.entity.memoGlobal("labels", () => { const { getChildLabels } = this.entity.parent?.getNodeRegistry() || {}; if (getChildLabels) { return this.formatLabels(getChildLabels(this, this.entity.document.layout)); } const { getLabels } = this.entity.getNodeRegistry(); if (getLabels) { return this.formatLabels(getLabels(this, this.entity.document.layout)); } if (this.transform.entity.isInlineBlock) { return []; } const currentOutput = this.transform.outputPoint; if (this.transform.next) { return this.formatLabels([ { offset: import_utils3.Point.getMiddlePoint(currentOutput, this.transform.next.inputPoint), type: 0 /* ADDER_LABEL */ } ]); } const parentOutput = this.transform.parent?.outputPoint; if (parentOutput && !new import_utils3.Point().copyFrom(currentOutput).equals(parentOutput) && !this.isNodeEnd) { return this.formatLabels([ { offset: parentOutput, type: 0 /* ADDER_LABEL */ } ]); } return []; }); } constructor(entity) { super(entity); this.transform = this.entity.addData(FlowNodeTransformData); this.renderData = this.entity.addData(FlowNodeRenderData); this.bindChange(this.transform); this.bindChange(this.renderData); } get collapsed() { return this.entity.collapsed; } get isNodeEnd() { return this.entity.isNodeEnd; } }; FlowNodeTransitionData.type = "FlowNodeTransitionData"; // src/entities/flow-node-entity.ts var FlowNodeEntity = class extends import_core4.Entity { constructor(conf) { super(conf); this._memoLocalCache = /* @__PURE__ */ new Map(); this._memoGlobalCache = /* @__PURE__ */ new Map(); this.flowNodeType = "unknown"; // 流程类型 /** * 是否隐藏 */ this._hidden = false; this.index = -1; this.document = conf.document; this.flowNodeType = conf.flowNodeType; this.originParent = conf.originParent; this.metaFromJSON = conf.meta; this.onDispose(() => { this.document.originTree.getChildren(this).slice().forEach((child) => { child.dispose(); }); this.document.originTree.remove(this, false); this.originParent = void 0; }); } initData(initConf) { if (initConf.originParent !== this.originParent) { this.originParent = initConf.originParent; this._registerCache = void 0; } if (initConf.parent) { initConf.parent.addChild(this, initConf.index); } if (initConf.meta !== this.metaFromJSON) { this._metaCache = void 0; this.metaFromJSON = initConf.meta; } this._hidden = !!(this.getNodeMeta().hidden || initConf.hidden); } get isStart() { return this.getNodeMeta().isStart; } get isFirst() { return !this.pre; } get isLast() { return !this.next; } /** * 子节点采用水平布局 */ get isInlineBlocks() { const originIsInlineBlocks = this.getNodeMeta().isInlineBlocks; return typeof originIsInlineBlocks === "function" ? originIsInlineBlocks(this) : originIsInlineBlocks; } /** * 水平节点 */ get isInlineBlock() { const parent = this.document.renderTree.getParent(this); return !!(parent && parent.isInlineBlocks); } /** * 节点结束标记 * - 当前节点是结束节点 * - 当前节点最后一个节点包含结束标记 * - 当前节点为 inlineBlock,每一个 block 包含结束标记 * * 由子元素确定,因此使用 memoLocal */ get isNodeEnd() { return this.memoLocal("isNodeEnd", () => { if (this.getNodeMeta().isNodeEnd) { return true; } if (this.isInlineBlocks && this.collapsedChildren.length) { return this.collapsedChildren.every((child) => child.isNodeEnd); } if (this.lastCollapsedChild) { return this.lastCollapsedChild.isNodeEnd; } return false; }); } /** * 添加 子节点 * * @param child 插入节点 */ addChild(child, index) { if (child.parent === this) return; this.document.originTree.addChild(this, child, index); } get hasChild() { return this.children.length > 0; } get pre() { return this.document.renderTree.getPre(this); } get next() { return this.document.renderTree.getNext(this); } get parent() { return this.document.renderTree.getParent(this); } getNodeRegistry() { if (this._registerCache) return this._registerCache; this._registerCache = this.document.getNodeRegistry(this.flowNodeType, this.originParent); return this._registerCache; } /** * @deprecated * use getNodeRegistry instead */ getNodeRegister() { return this.getNodeRegistry(); } getNodeMeta() { if (this._metaCache) return this._metaCache; if (this.metaFromJSON) { this._metaCache = { ...this.getNodeRegistry().meta, ...this.metaFromJSON }; } else { this._metaCache = this.getNodeRegistry().meta; } return this._metaCache; } /** * 获取所有子节点,包含 child 及其所有兄弟节点 */ get allChildren() { const children = []; for (const child of this.children) { children.push(child); children.push(...child.allChildren); } return children; } /** * 获取所有收起的子节点,包含 child 及其所有兄弟节点 */ get allCollapsedChildren() { const children = []; for (const child of this.collapsedChildren) { children.push(child); children.push(...child.allCollapsedChildren); } return children; } /** * * Get child blocks * * use `blocks` instead * @deprecated */ get collapsedChildren() { return this.document.renderTree.getCollapsedChildren(this); } /** * Get child blocks */ get blocks() { return this.collapsedChildren; } /** * Get last block */ get lastBlock() { return this.lastCollapsedChild; } /** * use `lastBlock` instead */ get lastCollapsedChild() { const { collapsedChildren } = this; return collapsedChildren[collapsedChildren.length - 1]; } /** * 获取子节点,如果子节点收起来,则会返回 空数组 */ get children() { return this.document.renderTree.getChildren(this); } get lastChild() { const { children } = this; return children[children.length - 1]; } get firstChild() { return this.children[0]; } memoLocal(key, fn) { if (this._memoLocalCache.has(key)) { return this._memoLocalCache.get(key); } const data = fn(); this._memoLocalCache.set(key, data); return data; } memoGlobal(key, fn) { if (this._memoGlobalCache.has(key)) { return this._memoGlobalCache.get(key); } const data = fn(); this._memoGlobalCache.set(key, data); return data; } clearMemoGlobal() { this._memoGlobalCache.clear(); } clearMemoLocal() { this._memoLocalCache.clear(); } get childrenLength() { return this.children.length; } get collapsed() { if (this.document.renderTree.isCollapsed(this)) return true; return !!this.parent?.collapsed; } set collapsed(collapsed) { this.document.renderTree.setCollapsed(this, collapsed); this.clearMemoGlobal(); this.clearMemoLocal(); } get hidden() { return this._hidden; } // 展开该节点 openInsideCollapsed() { this.document.renderTree.openNodeInsideCollapsed(this); } /** * 可以重载 */ getJSONData() { return this.getExtInfo(); } /** * 生成 JSON * @param newId */ toJSON() { return this.document.toNodeJSON(this); } get isVertical() { return this.document.layout.name === "vertical-fixed-layout" /* VERTICAL_FIXED_LAYOUT */; } /** * 修改节点扩展信息 * @param info */ updateExtInfo(extInfo, fullUpdate) { this.getData(FlowNodeRenderData).updateExtInfo(extInfo, fullUpdate); } /** * 获取节点扩展信息 */ getExtInfo() { return this.getData(FlowNodeRenderData).getExtInfo(); } get onExtInfoChange() { return this.renderData.onExtInfoChange; } /** * 获取渲染数据 */ get renderData() { return this.getData(FlowNodeRenderData); } /** * 获取位置大小数据 */ get transform() { return this.getData(FlowNodeTransformData); } /** * 获取节点的位置及大小矩形 */ get bounds() { return this.transform.bounds; } /** * Check node extend type */ isExtend(parentType) { return this.document.isExtend(this.flowNodeType, parentType); } /** * Check node type * @param parentType */ isTypeOrExtendType(parentType) { return this.document.isTypeOrExtendType(this.flowNodeType, parentType); } }; FlowNodeEntity.type = "FlowNodeEntity"; ((FlowNodeEntity2) => { function is(obj) { return obj instanceof FlowNodeEntity2; } FlowNodeEntity2.is = is; })(FlowNodeEntity || (FlowNodeEntity = {})); // src/entities/flow-document-transformer-entity.ts var import_utils4 = require("@flowgram.ai/utils"); var import_core5 = require("@flowgram.ai/core"); var FlowDocumentTransformerEntity = class extends import_core5.ConfigEntity { constructor(conf) { super(conf); this.onRefreshEmitter = new import_utils4.Emitter(); this.lastTransformVersion = -1; this.lastTreeVersion = -1; this.onRefresh = this.onRefreshEmitter.event; this.document = conf.document; this.toDispose.push( this.document.originTree.onTreeChange(() => { this.config.treeVersion += 1; this.fireChange(); }) ); this.toDispose.push(this.onRefreshEmitter); } getDefaultConfig() { return { loading: true, treeVersion: 0 }; } get loading() { return this.config.loading; } set loading(loading) { if (this.config.loading !== loading) { this.config.loading = loading; this.fireChange(); } } /** * 更新矩阵结构 (这个只有在树结构变化时候才会触发,如:添加节点、删除节点、改变位置节点) */ updateTransformsTree() { this.document.renderTree.traverse((node, depth, index) => { const transform = node.getData(FlowNodeTransformData); if (transform.collapsed) { transform.transform.clearChildren(); } if (node.parent) { transform.setParentTransform(node.parent.getData(FlowNodeTransformData)); } node.index = index; }); } clear() { this.lastTreeVersion = -1; this.lastTransformVersion = -1; } isTreeDirty() { const transformVersion = this.entityManager.getEntityDataVersion(FlowNodeTransformData); const isTreeVersionChanged = this.lastTreeVersion !== this.config.treeVersion; const isTransformVersionChanged = this.lastTransformVersion !== transformVersion; return isTreeVersionChanged || isTransformVersionChanged; } /** * 刷新节点的相对偏移 */ refresh() { const transformVersion = this.entityManager.getEntityDataVersion(FlowNodeTransformData); const isTreeVersionChanged = this.lastTreeVersion !== this.config.treeVersion; const isTransformVersionChanged = this.lastTransformVersion !== transformVersion; this.entityManager.changeEntityLocked = true; if (isTreeVersionChanged) { this.document.renderTree.updateRenderStruct(); this.updateTransformsTree(); this.lastTreeVersion = this.config.treeVersion; } if (isTreeVersionChanged || isTransformVersionChanged) { this.document.layout.update(); this.lastTransformVersion = this.entityManager.getEntityDataVersion(FlowNodeTransformData); this.lastTreeVersion = this.config.treeVersion; this.onRefreshEmitter.fire(); } this.entityManager.changeEntityLocked = false; } }; FlowDocumentTransformerEntity.type = "FlowDocumentTransformerEntity"; // src/entities/flow-renderer-state-entity.ts var import_lodash_es = require("lodash-es"); var import_core6 = require("@flowgram.ai/core"); var FlowRendererStateEntity = class extends import_core6.ConfigEntity { getDefaultConfig() { return {}; } constructor(conf) { super(conf); } getNodeHovered() { return this.config.nodeHoveredId ? this.entityManager.getEntityById(this.config.nodeHoveredId) : void 0; } setNodeHovered(node) { this.updateConfig({ nodeHoveredId: node?.id }); } get dragging() { return this.config.dragging; } setDragging(dragging) { this.updateConfig({ dragging }); } get isBranch() { return this.config.isBranch; } setIsBranch(isBranch) { this.updateConfig({ isBranch }); } getDragLabelSide() { return this.config.dragLabelSide; } setDragLabelSide(dragLabelSide) { this.updateConfig({ dragLabelSide }); } getNodeDroppingId() { return this.config.nodeDroppingId; } setNodeDroppingId(nodeDroppingId) { this.updateConfig({ nodeDroppingId }); } getDragStartEntity() { const { nodeDragStartId } = this.config; return this.entityManager.getEntityById(nodeDragStartId); } setDragStartEntity(node) { this.updateConfig({ nodeDragStartId: node?.id }); } // 拖拽多个节点时 getDragEntities() { const { nodeDragIds } = this.config; return (nodeDragIds || []).map((_id) => this.entityManager.getEntityById(_id)); } // 设置拖拽的节点 setDragEntities(nodes) { this.updateConfig({ nodeDragIds: nodes.map((_node) => _node.id), nodeDragIdsWithChildren: nodes.map((_node) => [_node.id, ..._node.allCollapsedChildren.map((_n) => _n.id)]).flat() }); } onNodeHoveredChange(fn, debounceTime = 100) { return this.onConfigChanged((0, import_lodash_es.debounce)(() => fn(this.getNodeHovered()), debounceTime)); } }; FlowRendererStateEntity.type = "FlowRendererStateEntity"; // src/flow-document.ts var import_lodash_es2 = require("lodash-es"); var import_inversify2 = require("inversify"); var import_utils7 = require("@flowgram.ai/utils"); var import_core7 = require("@flowgram.ai/core"); // src/flow-virtual-tree.ts var import_utils5 = require("@flowgram.ai/utils"); var FlowVirtualTree = class _FlowVirtualTree { constructor(root) { this.root = root; this.onTreeChangeEmitter = new import_utils5.Emitter(); /** * tree 结构变化时候触发 */ this.onTreeChange = this.onTreeChangeEmitter.event; this.map = /* @__PURE__ */ new Map(); } dispose() { this.map.clear(); this.onTreeChangeEmitter.dispose(); } getInfo(node) { let res = this.map.get(node); if (!res) { res = { children: [] }; this.map.set(node, res); } return res; } clear() { this.map.clear(); } cloneMap() { const newMap = /* @__PURE__ */ new Map(); for (const [key, value] of this.map) { newMap.set(key, { ...value, children: value.children.slice() }); } return newMap; } clone() { const newTree = new _FlowVirtualTree(this.root); newTree.map = this.cloneMap(); return newTree; } remove(node, withChildren = true) { this.removeParent(node); if (withChildren) { this._removeChildren(node); } this.map.delete(node); this.fireTreeChange(); } addChild(parent, child, index) { const parentInfo = this.getInfo(parent); const childInfo = this.getInfo(child); if (childInfo.parent) { if (childInfo.parent === parent) return child; if (childInfo.parent !== parent) { this.removeParent(child); } } const len = parentInfo.children.length; const idx = typeof index === "undefined" ? len - 1 : index - 1; const lastChild = parentInfo.children[idx]; const nextChild = parentInfo.children[idx + 1]; if (lastChild) this.getInfo(lastChild).next = child; if (nextChild) this.getInfo(nextChild).pre = child; childInfo.pre = lastChild; childInfo.next = nextChild; parentInfo.children.splice(idx + 1, 0, child); childInfo.parent = parent; this.fireTreeChange(); return child; } moveChilds(parent, childs, index) { const parentInfo = this.getInfo(parent); const len = parentInfo.children.length; let childIndex = index ?? len; childs.forEach((child) => { const childInfo = this.getInfo(child); if (childInfo.parent) { this.removeParent(child); } }); childs.forEach((child) => { const childInfo = this.getInfo(child); let lastChild = parentInfo.children[childIndex - 1]; let nextChild = parentInfo.children[childIndex]; if (lastChild) this.getInfo(lastChild).next = child; if (nextChild) this.getInfo(nextChild).pre = child; childInfo.pre = lastChild; childInfo.next = nextChild; parentInfo.children.splice(childIndex, 0, child); childInfo.parent = parent; childIndex++; }); this.fireTreeChange(); return childs; } getById(id) { for (const node of this.map.keys()) { if (node.id === id) return node; } } /** * 插入节点到后边 * @param before * @param after */ insertAfter(before, after) { const beforeInfo = this.getInfo(before); const afterInfo = this.getInfo(after); this.removeParent(after); if (beforeInfo.parent) { const parentInfo = this.getInfo(beforeInfo.parent); parentInfo.children.splice(parentInfo.children.indexOf(before) + 1, 0, after); const { next } = beforeInfo; if (next) { this.getInfo(next).pre = after; } afterInfo.next = next; beforeInfo.next = after; afterInfo.pre = before; afterInfo.parent = beforeInfo.parent; } this.fireTreeChange(); } removeParent(node) { const info = this.getInfo(node); if (!info.parent) return; const parentInfo = this.getInfo(info.parent); const index = parentInfo.children.indexOf(node); parentInfo.children.splice(index, 1); const { pre, next } = info; if (pre) this.getInfo(pre).next = next; if (next) this.getInfo(next).pre = pre; this.fireTreeChange(); } _removeChildren(node) { const children = this.getChildren(node); if (children.length > 0) { children.forEach((child) => { this._removeChildren(child); this.map.delete(child); }); } } getParent(node) { return this.getInfo(node).parent; } getPre(node) { return this.getInfo(node).pre; } getNext(node) { return this.getInfo(node).next; } getChildren(node) { return this.getInfo(node).children; } traverse(fn, node = this.root, depth = 0, index = 0) { const breaked = fn(node, depth, index); if (breaked) return true; const info = this.getInfo(node); const shouldBreak = info.children.find((child, i) => this.traverse(fn, child, depth + 1, i)); if (shouldBreak) return true; } /** * 通知文档树结构更新 */ fireTreeChange() { this.onTreeChangeEmitter.fire(); } get size() { return this.map.size; } toString(showType) { const ret = []; this.traverse((node, depth) => { if (depth === 0) { ret.push(node.id); } else { ret.push( `|${new Array(depth).fill("--").join("")} ${showType ? `${node.flowNodeType}(${node.id})` : node.id}` ); } }); return `${ret.join("\n")}`; } }; // src/flow-render-tree.ts var FlowRenderTree = class extends FlowVirtualTree { constructor(root, originTree, document) { super(root); this.root = root; /** * 折叠的节点 * @protected */ this.nodesCollapsed = /* @__PURE__ */ new Set(); this.originTree = originTree; this.onTreeChange = this.originTree.onTreeChange; this.document = document; } isCollapsed(node) { return this.nodesCollapsed.has(node); } get collapsedNodeList() { return Array.from(this.nodesCollapsed); } /** * 折叠元素 * @param node * @param collapsed */ setCollapsed(node, collapsed) { if (collapsed) { this.nodesCollapsed.add(node); } else { this.nodesCollapsed.delete(node); } this.originTree.fireTreeChange(); } /** * */ openNodeInsideCollapsed(node) { let curr = this.originTree.getInfo(node)?.parent; while (curr) { if (this.nodesCollapsed.has(curr)) { this.nodesCollapsed.delete(curr); } const { parent } = this.originTree.getInfo(curr) || {}; curr = parent; } this.originTree.fireTreeChange(); } /** * 更新结束节点等位置信息,分支里如果全是结束节点则要做相应的偏移 */ updateRenderStruct() { this.map = this.originTree.cloneMap(); if (this.document.config.get("END_NODES_REFINE_BRANCH" /* END_NODES_REFINE_BRANCH */)) { this.refineBranch(this.root); } this.hideCollapsed(); } /** * 隐藏收起节点 */ hideCollapsed() { this.nodesCollapsed.forEach((collapsedNode) => { const collapsedNodeInfo = this.getInfo(collapsedNode); if (!collapsedNodeInfo) { this.nodesCollapsed.delete(collapsedNode); return; } const iconChild = collapsedNodeInfo.children.find( (_child) => _child.flowNodeType === "blockIcon" /* BLOCK_ICON */ || _child.flowNodeType === "blockOrderIcon" /* BLOCK_ORDER_ICON */ ); if (iconChild) { const iconInfo = this.getInfo(iconChild); iconInfo.next = void 0; iconInfo.pre = void 0; collapsedNodeInfo.children = [iconChild]; return; } collapsedNodeInfo.children = []; }); } // 节点是否为结束节点 isNodeEnd(node) { if (node.getNodeMeta().isNodeEnd) { return true; } const { children } = this.getInfo(node); if (children.length > 0 && node.isInlineBlocks) { return children.every((child) => this.isNodeEnd(child)); } if (node.isInlineBlock) { return this.isNodeEnd(children[children.length - 1]); } return false; } /** * 优化精简分支线 * - 结束节点拉直分支线 */ refineBranch(block) { let curr = this.getInfo(block).children[0]; while (curr) { if (curr.flowNodeType === "dynamicSplit" /* DYNAMIC_SPLIT */ || curr.flowNodeType === "staticSplit" /* STATIC_SPLIT */) { const { next, children: branchChildren } = this.getInfo(curr); const { children } = this.getInfo(branchChildren[1]); const passBlocks = (children || []).filter((child) => !this.isNodeEnd(child)); const shouldDragAllNextNodes = passBlocks.length === 1; if (shouldDragAllNextNodes && next) { this.dragNextNodesToBlock(passBlocks[0], next); } children?.forEach((child) => { this.refineBranch(child); }); if (shouldDragAllNextNodes) { break; } } curr = curr.next; } } // 结束节点拽分支,将后续节点拽到对应分支内 dr