UNPKG

@logicflow/extension

Version:
534 lines (533 loc) 25.4 kB
"use strict"; var __assign = (this && this.__assign) || function () { __assign = Object.assign || function(t) { for (var s, i = 1, n = arguments.length; i < n; i++) { s = arguments[i]; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; } return t; }; return __assign.apply(this, arguments); }; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __exportStar = (this && this.__exportStar) || function(m, exports) { for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); }; var __rest = (this && this.__rest) || function (s, e) { var t = {}; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) t[p] = s[p]; if (s != null && typeof Object.getOwnPropertySymbols === "function") for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) { if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) t[p[i]] = s[p[i]]; } return t; }; var __read = (this && this.__read) || function (o, n) { var m = typeof Symbol === "function" && o[Symbol.iterator]; if (!m) return o; var i = m.call(o), r, ar = [], e; try { while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value); } catch (error) { e = { error: error }; } finally { try { if (r && !r.done && (m = i["return"])) m.call(i); } finally { if (e) throw e.error; } } return ar; }; var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) { if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) { if (ar || !(i in from)) { if (!ar) ar = Array.prototype.slice.call(from, 0, i); ar[i] = from[i]; } } return to.concat(ar || Array.prototype.slice.call(from)); }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.Group = void 0; /** * @deprecated * 待废弃,2.0 版本将 提供 dynamic-group 支持分组功能,当前 Group 插件设计和实现有比较多的问题,后续不再维护,请及时切换 */ var lodash_es_1 = require("lodash-es"); var core_1 = require("@logicflow/core"); var GroupNode_1 = __importDefault(require("./GroupNode")); var DEFAULT_TOP_Z_INDEX = -1000; var DEFAULT_BOTTOM_Z_INDEX = -10000; var Group = /** @class */ (function () { function Group(_a) { var lf = _a.lf; var _this = this; this.topGroupZIndex = DEFAULT_BOTTOM_Z_INDEX; this.nodeGroupMap = new Map(); this.graphRendered = function (_a) { var data = _a.data; // 如果节点 if (data && data.nodes) { data.nodes.forEach(function (node) { if (node.children) { ; node.children.forEach(function (nodeId) { _this.nodeGroupMap.set(nodeId, node.id); }); } }); // 初始化nodes时进行this.topGroupZIndex的校准更新 _this.checkAndCorrectTopGroupZIndex(data.nodes); } }; this.appendNodeToGroup = function (_a) { var data = _a.data; // 如果这个节点之前已经在group中了,则将其从之前的group中移除 var preGroupId = _this.nodeGroupMap.get(data.id); if (preGroupId) { var preGroup = _this.lf.getNodeModelById(preGroupId); preGroup.removeChild(data.id); _this.nodeGroupMap.delete(data.id); preGroup.setAllowAppendChild(false); } // 然后再判断这个节点是否在某个group中,如果在,则将其添加到对应的group中 var nodeModel = _this.lf.getNodeModelById(data.id); var bounds = nodeModel === null || nodeModel === void 0 ? void 0 : nodeModel.getBounds(); if (bounds && nodeModel) { var group = _this.getGroup(bounds, data); // https://github.com/didi/LogicFlow/issues/1261 // 当使用SelectionSelect框选后触发lf.addNode(Group) // 会触发appendNodeToGroup()的执行 // 由于this.getGroup()会判断node.id !== nodeData.id // 因此当addNode是Group类型时,this.getGroup()会一直返回空 // 导致了下面这段代码无法执行,也就是无法将当前添加的Group添加到this.nodeGroupMap中 // 这导致了折叠分组时触发的foldEdge()无法正确通过getNodeGroup()拿到正确的groupId // 从而导致折叠分组时一直都会创建一个虚拟边 // 而初始化分组时由于正确设置了nodeGroupMap的数据,因此不会产生虚拟边的错误情况 if (nodeModel.isGroup) { // 如果这个节点是分组,那么将其子节点也记录下来 ; data.children.forEach(function (nodeId) { _this.nodeGroupMap.set(nodeId, data.id); }); // 新增node时进行this.topGroupZIndex的校准更新 _this.checkAndCorrectTopGroupZIndex([data]); _this.nodeSelected({ data: data, isSelected: false, isMultiple: false, }); } if (!group) return; var isAllowAppendIn = group.isAllowAppendIn(data); if (!isAllowAppendIn) { _this.lf.emit('group:not-allowed', { group: group.getData(), node: data, }); return; } group.addChild(data.id); _this.nodeGroupMap.set(data.id, group.id); group.setAllowAppendChild(false); } }; this.deleteGroupChild = function (_a) { var data = _a.data; // 如果删除的是分组节点,则同时删除分组的子节点 if (data.children) { ; data.children.forEach(function (nodeId) { _this.nodeGroupMap.delete(nodeId); _this.lf.deleteNode(nodeId); }); } var groupId = _this.nodeGroupMap.get(data.id); if (groupId) { var group = _this.lf.getNodeModelById(groupId); group.removeChild(data.id); _this.nodeGroupMap.delete(data.id); } }; this.setActiveGroup = function (_a) { var data = _a.data; var nodeModel = _this.lf.getNodeModelById(data.id); var bounds = nodeModel === null || nodeModel === void 0 ? void 0 : nodeModel.getBounds(); if (nodeModel && bounds) { var newGroup = _this.getGroup(bounds, data); if (_this.activeGroup) { _this.activeGroup.setAllowAppendChild(false); } if (!newGroup || (nodeModel.isGroup && newGroup.id === data.id)) return; var isAllowAppendIn = newGroup.isAllowAppendIn(data); if (!isAllowAppendIn) { return; } _this.activeGroup = newGroup; _this.activeGroup.setAllowAppendChild(true); } }; this.findNodeAndChildMaxZIndex = function (nodeModel) { var maxZIndex = DEFAULT_BOTTOM_Z_INDEX; if (nodeModel.isGroup) { maxZIndex = Math.max(maxZIndex, nodeModel.zIndex); } if (nodeModel.children) { ; nodeModel.children.forEach(function (nodeId) { if (typeof nodeId === 'object') { // 正常情况下, GroupNodeModel.children是一个id数组,这里只是做个兼容 // @ts-ignore nodeId = nodeId.id; } var child = _this.lf.getNodeModelById(nodeId); if (child === null || child === void 0 ? void 0 : child.isGroup) { var childMaxZIndex = _this.findNodeAndChildMaxZIndex(child); maxZIndex = Math.max(childMaxZIndex, maxZIndex); } }); } return maxZIndex; }; this.checkAndCorrectTopGroupZIndex = function (nodes) { // 初始化时/增加新节点时,找出新增nodes的最大zIndex var maxZIndex = DEFAULT_BOTTOM_Z_INDEX; nodes.forEach(function (node) { var nodeModel = _this.lf.getNodeModelById(node.id); if (nodeModel) { var currentNodeMaxZIndex = _this.findNodeAndChildMaxZIndex(nodeModel); if (currentNodeMaxZIndex > maxZIndex) { maxZIndex = currentNodeMaxZIndex; } } }); if (_this.topGroupZIndex >= maxZIndex) { // 一般是初始化时/增加新节点时发生,因为外部强行设置了一个很大的zIndex // 删除节点不会影响目前最高zIndex的赋值 return; } // 新增nodes中如果存在zIndex比this.topGroupZIndex大 // 说明this.topGroupZIndex已经失去意义,代表不了目前最高zIndex的group,需要重新校准 // https://github.com/didi/LogicFlow/issues/1535 // 当外部直接设置多个BaseNode.zIndex=1时 // 当点击某一个node时,由于这个this.topGroupZIndex是从-10000开始计算的,this.topGroupZIndex+1也就是-9999 // 这就造成当前点击的node的zIndex远远比其它node的zIndex小,因此造成zIndex错乱问题 var allGroupNodes = _this.lf.graphModel.nodes.filter(function (node) { return node.isGroup; }); var max = _this.topGroupZIndex; for (var i = 0; i < allGroupNodes.length; i++) { var groupNode = allGroupNodes[i]; if (groupNode.zIndex > max) { max = groupNode.zIndex; } } _this.topGroupZIndex = max; }; /** * 1. 分组节点默认在普通节点下面。 * 2. 分组节点被选中后,会将分组节点以及其内部的其他分组节点放到其余分组节点的上面。 * 3. 分组节点取消选中后,不会将分组节点重置为原来的高度。 * 4. 由于LogicFlow核心目标是支持用户手动绘制流程图,所以不考虑一张流程图超过1000个分组节点的情况。 */ this.nodeSelected = function (_a) { var data = _a.data, isMultiple = _a.isMultiple, isSelected = _a.isSelected; var nodeModel = _this.lf.getNodeModelById(data.id); _this.toFrontGroup(nodeModel); // 重置所有的group zIndex,防止group节点zIndex增长为正。 if (_this.topGroupZIndex > DEFAULT_TOP_Z_INDEX) { _this.topGroupZIndex = DEFAULT_BOTTOM_Z_INDEX; var allGroups = _this.lf.graphModel.nodes .filter(function (node) { return node.isGroup; }) .sort(function (a, b) { return a.zIndex - b.zIndex; }); var preZIndex = 0; for (var i = 0; i < allGroups.length; i++) { var group = allGroups[i]; if (group.zIndex !== preZIndex) { _this.topGroupZIndex++; preZIndex = group.zIndex; } group.setZIndex(_this.topGroupZIndex); } } // FIX #1004 // 如果节点被多选, // 这个节点是分组,则将分组的所有子节点取消选中 // 这个节点是分组的子节点,且其所属分组节点已选,则取消选中 if (isMultiple && isSelected) { if (nodeModel === null || nodeModel === void 0 ? void 0 : nodeModel.isGroup) { ; nodeModel.children.forEach(function (child) { var childModel = _this.lf.graphModel.getElement(child); childModel === null || childModel === void 0 ? void 0 : childModel.setSelected(false); }); } else { var groupId = _this.nodeGroupMap.get(data.id); if (groupId) { var groupModel = _this.lf.getNodeModelById(groupId); (groupModel === null || groupModel === void 0 ? void 0 : groupModel.isSelected) && (nodeModel === null || nodeModel === void 0 ? void 0 : nodeModel.setSelected(false)); } } } }; this.toFrontGroup = function (model) { if (!model || !model.isGroup) { return; } _this.topGroupZIndex++; model.setZIndex(_this.topGroupZIndex); if (model.children) { ; model.children.forEach(function (nodeId) { var node = _this.lf.getNodeModelById(nodeId); _this.toFrontGroup(node); }); } }; lf.register(GroupNode_1.default); this.lf = lf; lf.graphModel.addNodeMoveRules(function (model, deltaX, deltaY) { if (model.isGroup) { // 如果移动的是分组,那么分组的子节点也跟着移动。 var nodeIds = _this.getNodeAllChild(model); lf.graphModel.moveNodes(nodeIds, deltaX, deltaY, true); return true; } var groupModel = lf.getNodeModelById(_this.nodeGroupMap.get(model.id)); if (groupModel && groupModel.isRestrict) { // 如果移动的节点存在分组中,且这个分组禁止子节点移出去。 var _a = model.getBounds(), minX = _a.minX, minY = _a.minY, maxX = _a.maxX, maxY = _a.maxY; return groupModel.isAllowMoveTo({ minX: minX + deltaX, minY: minY + deltaY, maxX: maxX + deltaX, maxY: maxY + deltaY, }); } return true; }); lf.graphModel.group = this; lf.on('node:add,node:drop,node:dnd-add', this.appendNodeToGroup); lf.on('node:delete', this.deleteGroupChild); lf.on('node:dnd-drag,node:drag', this.setActiveGroup); lf.on('node:click', this.nodeSelected); lf.on('graph:rendered', this.graphRendered); // https://github.com/didi/LogicFlow/issues/1346 // 重写 addElements() 方法,在 addElements() 原有基础上增加对 group 内部所有 nodes 和 edges 的复制功能 lf.addElements = function (_a, distance) { var selectedNodes = _a.nodes, selectedEdges = _a.edges; // ============== 变量初始化 ============== var nodeIdMap = {}; var elements = { nodes: [], edges: [], }; var groupInnerEdges = []; // ============== 变量初始化 ============== (0, lodash_es_1.forEach)(selectedNodes, function (node) { var preId = node.id; var children = node.children, rest = __rest(node, ["children"]); var nodeModel = lf.addNode(rest); if (!nodeModel) { return { nodes: [], edges: [], }; } if (preId) nodeIdMap[preId] = nodeModel.id; elements.nodes.push(nodeModel); // group的nodeModel // 递归创建group的nodeModel的children var edgesArray = _this.createAllChildNodes(nodeIdMap, children, nodeModel, distance).edgesArray; groupInnerEdges.push.apply(groupInnerEdges, __spreadArray([], __read(edgesArray), false)); }); groupInnerEdges.forEach(function (edge) { _this.createEdgeModel(edge, nodeIdMap, distance); }); // 构建的时候直接偏移,这里不需要再进行再度偏移 // groupInnerChildren.nodes.forEach(node => this.translateNodeData(node, distance)); // groupInnerChildren.edges.forEach(edge => this. translateEdgeData(edge, distance)); // 最外层的edges继续执行创建edgeModel的流程 // 由于最外层会调用 translateEdgeData(),因此这里不用传入distance进行偏移 (0, lodash_es_1.forEach)(selectedEdges, function (edge) { var edgeModel = _this.createEdgeModel(edge, nodeIdMap, 0); elements.edges.push(edgeModel); }); // 返回elements进行选中效果,即触发element.selectElementById() // shortcut.ts也会对最外层的nodes和edges进行偏移,即translateNodeData() return elements; }; } /** * 创建一个Group类型节点内部的所有子节点的副本 * 并且在遍历所有nodes的过程中顺便拿到所有edges(只在Group范围的edges) */ Group.prototype.createAllChildNodes = function (nodeIdMap, children, current, distance) { var _this = this; var lf = this.lf; var edgesDataArray = []; var edgesNodeModelArray = []; var nodesArray = []; children === null || children === void 0 ? void 0 : children.forEach(function (childId) { var childNodeModel = lf.getNodeModelById(childId); if (childNodeModel) { var x = childNodeModel.x, y = childNodeModel.y, properties = childNodeModel.properties, type = childNodeModel.type, rotate = childNodeModel.rotate, children_1 = childNodeModel.children; var nodeConfig = { x: x + distance, y: y + distance, properties: properties, type: type, rotate: rotate, // 如果不传递type,会自动触发NODE_ADD // 有概率触发appendToGroup }; var eventType = core_1.EventType.NODE_GROUP_COPY || 'node:group-copy-add'; var newChildModel = lf.addNode(nodeConfig, eventType); current.addChild(newChildModel.id); nodeIdMap[childId] = newChildModel.id; nodesArray.push(newChildModel); // 存储children内部节点相关的输入边 childNodeModel.incoming.edges.forEach(function (edge) { edgesNodeModelArray.push(edge); }); // 存储children内部节点相关的输出边 childNodeModel.outgoing.edges.forEach(function (edge) { edgesNodeModelArray.push(edge); }); if (children_1 instanceof Set) { var _a = _this.createAllChildNodes(nodeIdMap, children_1, newChildModel, distance), childNodes = _a.nodesArray, childEdges = _a.edgesArray; nodesArray.push.apply(nodesArray, __spreadArray([], __read(childNodes), false)); edgesDataArray.push.apply(edgesDataArray, __spreadArray([], __read(childEdges), false)); } } }); // 1. 判断每一条边的开始节点和目标节点是否在Group中 var filterEdgesArray = edgesNodeModelArray.filter(function (edge) { return nodeIdMap[edge.sourceNodeId] && nodeIdMap[edge.targetNodeId]; }); // 2. 为每一条group的内部边构建出EdgeData数据 // 从GraphModel.ts的getSelectElements()可以知道EdgeConfig就是EdgeData var filterEdgesDataArray = filterEdgesArray.map(function (item) { return item.getData(); }); return { nodesArray: nodesArray, edgesArray: edgesDataArray.concat(filterEdgesDataArray), // ??? what's this }; }; Group.prototype.createEdgeModel = function (edge, nodeIdMap, distance) { var lf = this.lf; var sourceId = edge.sourceNodeId; var targetId = edge.targetNodeId; if (nodeIdMap[sourceId]) sourceId = nodeIdMap[sourceId]; if (nodeIdMap[targetId]) targetId = nodeIdMap[targetId]; var type = edge.type, startPoint = edge.startPoint, endPoint = edge.endPoint, pointsList = edge.pointsList, text = edge.text; // ====== 仿造shortcut.ts的 translateEdgeData()逻辑 ====== var newStartPoint = { x: ((startPoint === null || startPoint === void 0 ? void 0 : startPoint.x) || 0) + distance, y: ((startPoint === null || startPoint === void 0 ? void 0 : startPoint.y) || 0) + distance, }; var newEndPoint = { x: ((endPoint === null || endPoint === void 0 ? void 0 : endPoint.x) || 0) + distance, y: ((endPoint === null || endPoint === void 0 ? void 0 : endPoint.y) || 0) + distance, }; var newPointsList = []; if (pointsList && pointsList.length > 0) { newPointsList = pointsList.map(function (point) { point.x += distance; point.y += distance; return point; }); } var edgeConfig = { type: type, startPoint: newStartPoint, endPoint: newEndPoint, sourceNodeId: sourceId, targetNodeId: targetId, pointsList: newPointsList, }; if ((0, lodash_es_1.isObject)(text) && !(0, lodash_es_1.isEmpty)(text)) { edgeConfig.text = __assign(__assign({}, text), { x: (text === null || text === void 0 ? void 0 : text.x) + distance, y: (text === null || text === void 0 ? void 0 : text.y) + distance }); } // ====== 仿造shortcut.ts的 translateEdgeData()逻辑 ====== // 简化复制时的参数传入,防止创建出两个edge属于同个group这种情况 return lf.graphModel.addEdge(edgeConfig); }; /** * 获取一个节点内部所有的子节点,包裹分组的子节点 */ Group.prototype.getNodeAllChild = function (model) { var _this = this; var nodeIds = []; if (model.children) { ; model.children.forEach(function (nodeId) { nodeIds.push(nodeId); var nodeModel = _this.lf.getNodeModelById(nodeId); if (nodeModel === null || nodeModel === void 0 ? void 0 : nodeModel.isGroup) { nodeIds = nodeIds.concat(_this.getNodeAllChild(nodeModel)); } }); } return nodeIds; }; /** * 获取自定位置其所属分组 * 当分组重合时,优先返回最上层的分组 */ Group.prototype.getGroup = function (bounds, nodeData) { var nodes = this.lf.graphModel.nodes; var groups = nodes.filter(function (node) { return node.isGroup && node.isInRange(bounds) && node.id !== nodeData.id; }); if (groups.length === 0) return; if (groups.length === 1) return groups[0]; var topGroup = groups[groups.length - 1]; for (var i = groups.length - 2; i >= 0; i--) { if (groups[i].zIndex > topGroup.zIndex) { topGroup = groups[i]; } } return topGroup; }; /** * 获取某个节点所属的groupModel */ Group.prototype.getNodeGroup = function (nodeId) { var groupId = this.nodeGroupMap.get(nodeId); if (groupId) { return this.lf.getNodeModelById(groupId); } }; Group.prototype.render = function () { }; Group.prototype.destroy = function () { }; Group.pluginName = 'group'; return Group; }()); exports.Group = Group; __exportStar(require("./GroupNode"), exports); exports.default = GroupNode_1.default;