| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842 |
- import {
- bpmnSequenceFlow,
- bpmnIncoming,
- bpmnOutgoing,
- bpmnInclusive,
- typeStart,
- typeTask,
- typeSubFlow,
- typeEnd,
- typeTrigger,
- typeEventTrigger,
- typeTimeTrigger,
- typeNoticeTrigger,
- typeWebhookTrigger,
- typeGetData,
- typeAddData,
- typeUpdateData,
- typeDelData,
- typeInterface,
- typeMessage,
- typeLaunchFlow,
- typeSchedule,
- typeProcessing,
- typeGateway,
- typeInclusion,
- typeOutside,
- } from '../config/variableName';
- import { buildBitUUID } from '../utils/uuidUtil';
- import { hasGatewayType, typeConfig } from '../config';
- import { is } from 'bpmn-js/lib/util/ModelUtil';
- import { getExternalLabelMid } from 'bpmn-js/lib/util/LabelUtil';
- export class NodeUtils {
- /**
- * 判断节点类型
- * @param {Node} node - 节点数据
- * @returns Boolean
- */
- static isStartNode(node) {
- return node && node?.type === typeStart;
- }
- static isApproverNode(node) {
- return node && node?.type === typeTask;
- }
- static isProcessingNode(node) {
- return node && node?.type === typeProcessing;
- }
- static isSubFlowNode(node) {
- return node && node?.type === typeSubFlow;
- }
- static isInterflowNode(node) {
- return node && node?.type === typeTask && node?.isInterflow;
- }
- static isConnectNode(node) {
- return node && node?.type === bpmnSequenceFlow;
- }
- static isEndNode(node) {
- return node && node?.type === typeEnd;
- }
- static isTriggerNode(node) {
- return node && node?.type === typeTrigger;
- }
- static isEventTriggerNode(node) {
- return node && node?.type === typeEventTrigger;
- }
- static isTimeTriggerNode(node) {
- return node && node?.type === typeTimeTrigger;
- }
- static isNoticeTriggerNode(node) {
- return node && node?.type === typeNoticeTrigger;
- }
- static isWebhookTriggerNode(node) {
- return node && node?.type === typeWebhookTrigger;
- }
- static isGetDataNode(node) {
- return node && node?.type === typeGetData;
- }
- static isAddDataNode(node) {
- return node && node?.type === typeAddData;
- }
- static isUpdateDataNode(node) {
- return node && node?.type === typeUpdateData;
- }
- static isDeleteDataNode(node) {
- return node && node?.type === typeDelData;
- }
- static isDataInterfaceNode(node) {
- return node && node?.type === typeInterface;
- }
- static isMessageNode(node) {
- return node && node?.type === typeMessage;
- }
- static isLaunchFlowNode(node) {
- return node && node?.type === typeLaunchFlow;
- }
- static isScheduleNode(node) {
- return node && node?.type === typeSchedule;
- }
- static isOutsideNode(node) {
- return node && node?.type === typeOutside;
- }
- /**
- * 获取上节点元素
- * @param element 当前元素
- */
- static getPreNodeList(element) {
- let preList: any[] = [];
- if (!element || !element.incoming || !element.incoming.length) return preList;
- for (let i = 0; i < element.incoming.length; i++) {
- const item = element.incoming[i];
- preList.push(item.source);
- }
- return preList;
- }
- /**
- * 生成条件组名称
- * @param conditions 条件组
- * @param matchLogic and / or
- */
- static getConditionsContent(conditions, matchLogic) {
- let content = '';
- for (let i = 0; i < conditions.length; i++) {
- const e = conditions[i];
- content += conditions.length == 1 ? '' : (i == 0 ? '' : ` ${matchLogic} `) + '( ';
- for (let j = 0; j < e.groups.length; j++) {
- const groups = e.groups[j];
- const logic = j == 0 ? '' : ` ${e.logic} `;
- const text = ` ${groups.fieldName} ${groups.symbolName}${groups.fieldLabel ? groups.fieldLabel : groups.fieldValue || groups.fieldValue === 0 ? groups.fieldValue : ''
- } `;
- content += logic + text;
- }
- content += conditions.length == 1 ? '' : ' )';
- }
- return content;
- }
- /**
- * 自动生成网关
- * @param xml xml
- * @param elementRegistry 节点元素
- */
- static autoCreateGateWay(xml, elementRegistry, jnpfData) {
- let parser = new DOMParser();
- let xmlDoc = parser.parseFromString(xml, 'text/xml');
- let process: any = xmlDoc.querySelector('#Process_1');
- let plane: any = xmlDoc.querySelector('#BPMNPlane_1');
- let divideList: any[] = [];
- let confluenceList: any = [];
- const allList: any[] = elementRegistry.getAll() || [];
- allList.map((item: any) => {
- // 过滤任务节点的网关
- let groupId = item?.businessObject?.$attrs?.customGroupId;
- if (item.incoming?.length > 1 && !groupId) confluenceList.push({ key: item.id, gatewayType: 'inclusion' });
- if (item.outgoing && item.outgoing.length > 1 && !groupId) {
- divideList.push({
- key: item.id,
- gatewayType: jnpfData.data[item.id]?.divideRule || 'inclusion',
- });
- }
- });
- // 新增分流xml标签
- if (divideList?.length) {
- divideList.map((item: any) => {
- let targetElement = xmlDoc.querySelector(`#${item.key}`);
- if (targetElement) {
- let targeChildren: any = targetElement.children;
- let outgoingList: any = [];
- let incomingList: any = [];
- for (var i = 0; i < targeChildren.length; i++) {
- if (targeChildren[i].nodeName === bpmnOutgoing) {
- // 将该值赋值给新生成的分流元素上 删除原来元素上的outgoing 并且生成一条新的outgoing连接到该线条上。
- outgoingList.push(targeChildren[i]);
- } else {
- incomingList.push(targeChildren[i]);
- }
- }
- // 新增一个分流节点 并且连接线到目前的元素上
- let gatewayElement = NodeUtils.createGateway(xmlDoc, item.gatewayType);
- let gatewayId = 'Gateway_' + buildBitUUID();
- let flowId = 'flow_' + buildBitUUID();
- gatewayElement.setAttribute('id', gatewayId);
- let flowElement = xmlDoc.createElement('bpmn2:sequenceFlow');
- flowElement.setAttribute('id', flowId);
- flowElement.setAttribute('sourceRef', item.key);
- flowElement.setAttribute('targetRef', gatewayId);
- let conditionExpression = xmlDoc.createElement('bpmn2:conditionExpression');
- conditionExpression.setAttribute('xsi:type', 'bpmn2:tFormalExpression');
- let testText = xmlDoc.createTextNode('${' + `${flowId}` + '}');
- conditionExpression.appendChild(testText);
- let childElement = xmlDoc.createElement(bpmnIncoming); // 替换为您想要创建的子标签的名称
- let textNode = xmlDoc.createTextNode(flowId);
- childElement.appendChild(textNode);
- gatewayElement.appendChild(childElement);
- if (outgoingList?.length) {
- let set: any = new Set();
- outgoingList.map((item: any) => {
- let outgoingId = item.textContent;
- let outgoingItemElementId = `#${outgoingId}`; // 替换成您要操作的元素的 ID
- let outgoingItemElement: any = xmlDoc.querySelector(outgoingItemElementId);
- outgoingItemElement.setAttribute('sourceRef', gatewayId);
- allList.map((itemElement: any) => {
- if (itemElement.id === outgoingId) set.add(itemElement.source?.id);
- });
- gatewayElement.appendChild(item);
- });
- set.forEach((item: any) => {
- let element: any = xmlDoc.getElementById(item);
- let childElement = xmlDoc.createElement(bpmnOutgoing);
- element.appendChild(childElement);
- let textNode = xmlDoc.createTextNode(flowId);
- childElement.appendChild(textNode);
- });
- }
- flowElement.appendChild(conditionExpression);
- process.appendChild(gatewayElement);
- process.appendChild(flowElement);
- this.handleCreateGatewayBounds(xmlDoc, gatewayId, plane);
- }
- });
- }
- if (confluenceList?.length) {
- confluenceList.map((item: any) => {
- let targetElement = xmlDoc.querySelector(`#${item.key}`);
- if (targetElement) {
- let targeChildren: any = targetElement.children;
- let outgoingList: any = [];
- let incomingList: any = [];
- for (var i = 0; i < targeChildren.length; i++) {
- if (targeChildren[i].nodeName === bpmnOutgoing) {
- // 将该值赋值给新生成的分流元素上 删除原来元素上的outgoing 并且生成一条新的outgoing连接到该线条上。
- outgoingList.push(targeChildren[i]);
- } else {
- incomingList.push(targeChildren[i]);
- }
- }
- // 新增一个分流节点 并且连接线到目前的元素上
- let gatewayElement = NodeUtils.createGateway(xmlDoc, item.gatewayType);
- let gatewayId = 'Gateway_' + buildBitUUID();
- let flowId = 'Flow_' + buildBitUUID();
- gatewayElement.setAttribute('id', gatewayId);
- let flowElement = xmlDoc.createElement('bpmn2:sequenceFlow');
- let conditionExpression = xmlDoc.createElement('bpmn2:conditionExpression');
- conditionExpression.setAttribute('xsi:type', 'bpmn2:tFormalExpression');
- let testText = xmlDoc.createTextNode('${' + `${flowId}` + '}');
- conditionExpression.appendChild(testText);
- flowElement.setAttribute('id', flowId);
- flowElement.setAttribute('sourceRef', gatewayId);
- flowElement.setAttribute('targetRef', item.key);
- let childElement = xmlDoc.createElement(bpmnOutgoing); // 替换为您想要创建的子标签的名称
- let textNode = xmlDoc.createTextNode(flowId);
- childElement.appendChild(textNode);
- gatewayElement.appendChild(childElement);
- if (incomingList && incomingList.length) {
- let set: any = new Set();
- incomingList.map((item: any) => {
- let incomingId = item.textContent;
- let incomingItemElementId = `#${incomingId}`; // 替换成您要操作的元素的 ID
- let incomingItemElement: any = xmlDoc.querySelector(incomingItemElementId);
- incomingItemElement.setAttribute('targetRef', gatewayId);
- allList.map((itemElement: any) => {
- if (itemElement.id === incomingId) set.add(itemElement.target?.id);
- });
- gatewayElement.appendChild(item);
- });
- set.forEach((item: any) => {
- let element: any = xmlDoc.getElementById(item);
- let childElement = xmlDoc.createElement(bpmnIncoming);
- // 新增新的出线线条在元素上
- element.appendChild(childElement);
- let textNode = xmlDoc.createTextNode(flowId);
- childElement.appendChild(textNode);
- });
- }
- flowElement.appendChild(conditionExpression);
- process.appendChild(gatewayElement);
- process.appendChild(flowElement);
- this.handleCreateGatewayBounds(xmlDoc, gatewayId, plane);
- }
- });
- }
- const newXml = new XMLSerializer().serializeToString(xmlDoc);
- return encodeURIComponent(newXml);
- }
- /**
- * 自动删除网关
- * @param flowXml
- * @returns
- */
- static autoDelGateWay(flowXml: string, type: number, nodeMap: any, isPreview: boolean) {
- let parser = new DOMParser();
- let xmlDoc = parser.parseFromString(decodeURIComponent(flowXml), 'text/xml');
- let oldXmlDoc = parser.parseFromString(decodeURIComponent(flowXml), 'text/xml');
- if (type != 1) {
- let process: any = xmlDoc.querySelector('#Process_1');
- let plane: any = xmlDoc.querySelector('#BPMNPlane_1');
- let gatewayList = NodeUtils.getAllGateway(xmlDoc);
- gatewayList.map((item: any) => {
- let incoming = item.getElementsByTagName(bpmnIncoming) || []; // 对于网关的进线线条
- let outgoing = item.getElementsByTagName(bpmnOutgoing) || []; // 对于网关的出线线条
- let sourceElement: any = []; // 当前网关的进线元素
- let targetElement: any = []; // 当前网关的出线元素
- for (let i = 0; i < incoming.length; i++) {
- // 获取进线元素的id
- let flowId = `#${incoming[i].innerText || incoming[i].textContent}`;
- // 然后在全局内找到该线条
- let connectElement: any = xmlDoc.querySelector(flowId);
- // 获取到该线条的进线元素
- let sourceElementId = connectElement.getAttribute('sourceRef');
- sourceElement.push(xmlDoc.querySelector(`#${sourceElementId}`));
- }
- for (let i = 0; i < outgoing.length; i++) {
- let flowId = `#${outgoing[i].innerText || outgoing[i].textContent}`;
- let connectElement: any = xmlDoc.querySelector(flowId);
- let targetElementId = connectElement.getAttribute('targetRef');
- targetElement.push(xmlDoc.querySelector(`#${targetElementId}`));
- }
- // 合流网关(网关有多条进线 一条出线)
- if (sourceElement.length > 1 && targetElement.length === 1) {
- // 获取当前的出线元素
- let targetElementId = targetElement[0]?.id;
- // 删除targetElement旧的进线元素
- const incomingList = NodeUtils.getIncomingConnectByElement(targetElement[0]) || [];
- incomingList.map((targetComingChildren: any) => {
- targetElement[0].removeChild(targetComingChildren);
- });
- // 遍历网关进线线条
- let list: any = [];
- // 迭代器
- for (let i = 0; i < incoming.length; i++) {
- let flowId = incoming[i].innerText || incoming[i].textContent;
- let connectElement: any = xmlDoc.querySelector(`#${flowId}`);
- let connectElementDi: any = xmlDoc.querySelector(`#${flowId}_di`);
- let connectWaypoint = connectElementDi.getElementsByTagName('di:waypoint');
- connectElement.setAttribute('targetRef', targetElementId);
- list.push(incoming[i]);
- let id = item.getAttribute('id');
- if (id.includes('_isSimple')) {
- let outGoingId = outgoing[0].innerText || outgoing[0].textContent;
- let outGoingDi: any = xmlDoc.querySelector(`#${outGoingId}_di`);
- let test: any = new Set();
- let newWayList = this.getGatewayWaypoints(test, outGoingDi, outgoing, oldXmlDoc, connectWaypoint);
- for (let i = 0; i < newWayList?.length; i++) {
- if (!connectWaypoint[i]) {
- let newWaypoint = xmlDoc.createElementNS('http://www.omg.org/spec/DD/20100524/DI', 'di:waypoint');
- newWaypoint.setAttribute('x', newWayList[i].x);
- newWaypoint.setAttribute('y', newWayList[i].y);
- connectElementDi.appendChild(newWaypoint);
- }
- }
- }
- }
- // 给targetElement设置新的进线元素
- list.map((item: any) => {
- targetElement[0]?.appendChild(item);
- });
- // 删除该网关及网关对应的出线元素
- process.removeChild(item);
- let flowId = outgoing[0].innerText || outgoing[0].textContent;
- let connectElement: any = xmlDoc.querySelector(`#${flowId}`);
- let connectElementDi: any = xmlDoc.querySelector(`#${flowId}_di`);
- let itemDi: any = xmlDoc.querySelector(`#${item.getAttribute('id')}_di`);
- process.removeChild(connectElement);
- connectElementDi && plane.removeChild(connectElementDi);
- itemDi && plane.removeChild(itemDi);
- }
- // 分流网关(网关有一条进线 多条出线)
- if (sourceElement.length === 1 && targetElement.length > 1) {
- // 获取当前的进元素
- let sourceElementId = sourceElement[0].id;
- // 删除sourceElement旧的出线元素
- const outgoingList = NodeUtils.getOutgoingConnectByElement(sourceElement[0]) || [];
- outgoingList.map((sourceElementChildren: any) => {
- sourceElement[0].removeChild(sourceElementChildren);
- });
- // 遍历网关出线线条
- let list: any = [];
- for (let i = 0; i < outgoing.length; i++) {
- // 获取进线元素的id
- let flowId = outgoing[i].innerText || outgoing[i].textContent;
- let incomingId = incoming[0].innerText || incoming[0].textContent;
- // 然后在全局内找到该线条 并且设置该线条的出线元素为targetElementId
- let connectElement: any = xmlDoc.querySelector(`#${flowId}`);
- connectElement.setAttribute('sourceRef', sourceElementId);
- // 给sourceElement设置新的出线信息
- list.push(outgoing[i]);
- let id = item.getAttribute('id');
- if (id.includes('_isSimple')) {
- let itemDi: any = xmlDoc.querySelector(`#${flowId}_di`);
- let itemDiWaypoint = itemDi.getElementsByTagName('di:waypoint');
- let incomingDi: any = xmlDoc.querySelector(`#${incomingId}_di`);
- let waypoint: any = incomingDi.getElementsByTagName('di:waypoint');
- let newWayList: any = [];
- for (let i = 0; i < waypoint.length; i++) {
- newWayList.push({
- x: waypoint[i].getAttribute('x'),
- y:
- i === waypoint.length - 1
- ? String(Number(waypoint[i].getAttribute('y')) + typeConfig[bpmnInclusive].renderer.attr.height / 2)
- : waypoint[i].getAttribute('y'),
- });
- }
- for (let i = 0; i < itemDiWaypoint.length; i++) {
- i != 0 && newWayList.push({ x: itemDiWaypoint[i].getAttribute('x'), y: itemDiWaypoint[i].getAttribute('y') });
- }
- for (let i = 0; i < newWayList.length; i++) {
- if (itemDiWaypoint[i]) {
- itemDiWaypoint[i].setAttribute('x', newWayList[i].x);
- itemDiWaypoint[i].setAttribute('y', newWayList[i].y);
- } else {
- let newWaypoint = xmlDoc.createElementNS('http://www.omg.org/spec/DD/20100524/DI', 'di:waypoint');
- newWaypoint.setAttribute('x', newWayList[i].x);
- newWaypoint.setAttribute('y', newWayList[i].y);
- itemDi.appendChild(newWaypoint);
- }
- }
- }
- }
- list.map((item: any) => {
- sourceElement[0].appendChild(item);
- });
- // 删除该网关及网关对应的出线元素
- process.removeChild(item);
- let flowId = incoming[0].innerText || incoming[0].textContent;
- let connectElement: any = xmlDoc.querySelector(`#${flowId}`);
- let connectElementDi: any = xmlDoc.querySelector(`#${flowId}_di`);
- let itemDi: any = xmlDoc.querySelector(`#${item.getAttribute('id')}_di`);
- process.removeChild(connectElement);
- connectElementDi && plane.removeChild(connectElementDi);
- itemDi && plane.removeChild(itemDi);
- }
- });
- // 有颜色的线条颜色标签重新生成
- if (isPreview) {
- let list = process.getElementsByTagName('bpmn2:sequenceFlow');
- let newList: any = [];
- for (let i = 0; i < list.length; i++) {
- let sourceRef = list[i].getAttribute('sourceRef');
- let targetRef = list[i].getAttribute('targetRef');
- if (
- nodeMap &&
- nodeMap.has(sourceRef) &&
- nodeMap.has(targetRef) &&
- nodeMap.get(sourceRef)?.type === '0' &&
- (nodeMap.get(targetRef)?.type === '0' || nodeMap.get(targetRef)?.type === '1')
- ) {
- newList.push(list[i]);
- }
- }
- newList.forEach((node: any) => {
- process.removeChild(node);
- process.appendChild(node);
- });
- }
- }
- return xmlDoc;
- }
- static createGateway(xmlDoc: any, type: 'parallel' | 'inclusion' | 'exclusive' | 'choose') {
- if (type === 'inclusion' || type === 'choose') return xmlDoc.createElement('bpmn2:inclusiveGateway');
- if (type === 'parallel') return xmlDoc.createElement('bpmn2:parallelGateway');
- if (type === 'exclusive') return xmlDoc.createElement('bpmn2:exclusiveGateway');
- }
- static getAllGateway(xmlDoc: any) {
- let gateWayList: any = [];
- let parallelGateways = xmlDoc.getElementsByTagName('bpmn2:parallelGateway');
- let inclusiveGateways = xmlDoc.getElementsByTagName('bpmn2:inclusiveGateway');
- let exclusiveGateways = xmlDoc.getElementsByTagName('bpmn2:exclusiveGateway');
- for (let i = 0; i < parallelGateways.length; i++) {
- gateWayList.push(parallelGateways[i]);
- }
- for (let i = 0; i < inclusiveGateways.length; i++) {
- gateWayList.push(inclusiveGateways[i]);
- }
- for (let i = 0; i < exclusiveGateways.length; i++) {
- gateWayList.push(exclusiveGateways[i]);
- }
- return gateWayList;
- }
- /**
- * 获取element下的进线元素
- * @param element 元素
- * @returns {Array} 进线元素数组
- */
- static getIncomingConnectByElement(element: any) {
- let list: any = [];
- let incomingElements = element?.getElementsByTagName(bpmnIncoming);
- for (let i = 0; i < incomingElements?.length; i++) {
- list.push(incomingElements[i]);
- }
- return list;
- }
- /**
- * 获取element下的出线元素
- * @param element 元素
- * @returns {Array} 出线元素数组
- */
- static getOutgoingConnectByElement(element: any) {
- let list: any = [];
- let outgoingElements = element?.getElementsByTagName(bpmnOutgoing);
- for (let i = 0; i < outgoingElements?.length; i++) {
- list.push(outgoingElements[i]);
- }
- return list;
- }
- static getLastElementList(element: any, allElements: any[]) {
- let lastList: any = [];
- if (element && element.incoming && element.incoming.length) {
- element.incoming.forEach((item: any) => {
- return allElements.forEach((last: any) => {
- // last中的出线若和 item的id相同 则获取到上一个节点的信息
- if (last.outgoing && last.outgoing.length) {
- let nextElement = last.outgoing.find((outgoing: any) => {
- return outgoing.id === item.id;
- });
- if (nextElement) {
- lastList.push(last);
- return element;
- }
- }
- });
- });
- }
- return lastList;
- }
- static getNextElementList = (element: any, allElements: any[]) => {
- let lastList: any = [];
- if (element && element.outgoing && element.outgoing.length) {
- element.outgoing.forEach((item: any) => {
- let list = allElements.forEach((last: any) => {
- // last中的出线若和 item的id相同 则获取到上一个节点的信息
- if (last.incoming && last.incoming.length) {
- let nextElement = last.incoming.find((incoming: any) => {
- return incoming.id === item.id;
- });
- if (nextElement) {
- lastList.push(last);
- return element;
- }
- }
- });
- return list;
- });
- }
- return lastList;
- };
- static getEndlessLoop = (bpmn: any) => {
- // 获取 BPMN 图中的所有元素
- let elementRegistry = bpmn.get('elementRegistry');
- let elements = elementRegistry.getAll();
- // 构建图数据结构
- let graph = {};
- let edgeMap = {}; // 用于存储边信息,key 是源节点,value 是目标节点和连线 id
- elements.forEach(element => {
- if (element.type === 'bpmn:SequenceFlow') {
- const sourceId = element.source.id;
- const targetId = element.target.id;
- const edgeId = element.id;
- if (!graph[sourceId]) graph[sourceId] = [];
- graph[sourceId].push(targetId);
- if (!edgeMap[sourceId]) edgeMap[sourceId] = [];
- edgeMap[sourceId].push({ targetId, edgeId });
- }
- });
- // 使用修改后的 DFS 检测所有环路并找出每个环路的最后一个进入环路的连线
- function findAllCycles(graph, edgeMap) {
- let visited = new Set();
- let stack: any = [];
- let stackSet: any = new Set();
- let cycles: any = [];
- function visit(node, startNode) {
- if (stackSet.has(node)) {
- // 找到环,记录从开始节点到环路的路径上的连线,并选择路径上的最后一条连线作为最后一个进入环路的连线
- let pathEdges: any = [];
- let isCycle = false;
- for (let i = stack.indexOf(startNode); i < stack.length - 1; i++) {
- let source = stack[i];
- let target = stack[i + 1];
- let edge = edgeMap[source].find(edge => edge.targetId === target);
- if (edge) {
- pathEdges.push(edge.edgeId);
- if (source === node) {
- isCycle = true;
- break;
- }
- }
- }
- if (isCycle) cycles.push(pathEdges[pathEdges.length - 1]);
- return;
- }
- if (visited.has(node)) return; // 已访问过,且无环
- visited.add(node);
- stack.push(node);
- stackSet.add(node);
- let neighbors = graph[node] || [];
- for (const neighbor of neighbors) {
- visit(neighbor, startNode);
- }
- stack.pop();
- stackSet.delete(node);
- }
- for (const node in graph) {
- visit(node, node);
- }
- return cycles;
- }
- return findAllCycles(graph, edgeMap);
- };
- // 网关坐标
- static getGatewayWaypoints = (test: any, outGoingDi: any, outgoing: any, xmlDoc: any, connectWaypoint?: any) => {
- let newList: any = [];
- let id = outGoingDi.getAttribute('bpmnElement');
- let gateway = xmlDoc.querySelector(`#${id}`);
- let itemDi: any = xmlDoc.querySelector(`#${id}_di`);
- let itemDiWaypoint = itemDi.getElementsByTagName('di:waypoint');
- for (let i = 0; i < itemDiWaypoint.length; i++) {
- newList.push({
- x: itemDiWaypoint[i].getAttribute('x'),
- y: itemDiWaypoint[i].getAttribute('y'),
- });
- }
- // 获取网关子坐标 如果子元素还是网关则继续查找后代元素
- let childrenElementId = gateway.getAttribute('targetRef');
- let childrenElement = xmlDoc.querySelector(`#${childrenElementId}`);
- if (childrenElementId.includes('Gateway_')) {
- let childrenOutGoingList = childrenElement.getElementsByTagName(bpmnOutgoing);
- let childrenOutGoingId = outgoing[0].innerText || outgoing[0].textContent;
- let childrenOutGoingDi: any = xmlDoc.querySelector(`#${childrenOutGoingId}_di`);
- let childrenList: any = this.getGatewayWaypoints(test, childrenOutGoingDi, childrenOutGoingList, xmlDoc);
- if (!test.has(id)) test.add(id);
- else newList.pop();
- newList = newList.concat(childrenList);
- } else if (connectWaypoint?.length > 0) {
- // 如果是其它节点
- for (let i = 0; i < connectWaypoint.length - 1; i++) {
- newList.unshift({
- x: connectWaypoint[i].getAttribute('x'),
- y: connectWaypoint[i].getAttribute('y'),
- });
- }
- }
- return newList;
- };
- // 校验连线是否存在条件标签 不存则需要手动添加。
- static verificationConnect = bpmn => {
- let elementRegistry: any = bpmn.get('elementRegistry');
- let modeling = bpmn.get('modeling');
- let moddle = bpmn.get('moddle');
- let connect = elementRegistry.getAll().filter((element: any) => {
- if (is(element, 'bpmn:SequenceFlow') && !element?.businessObject?.conditionExpression && element.type != 'label') return element;
- });
- if (connect?.length > 0) {
- connect.forEach(sequenceFlow => {
- let conditionExpression = moddle.create('bpmn:FormalExpression', {
- body: '${' + `${sequenceFlow.id}` + '}',
- });
- modeling.updateProperties(sequenceFlow, {
- conditionExpression: conditionExpression,
- });
- if (sequenceFlow.label?.x) {
- let label = elementRegistry.get(sequenceFlow.label.id);
- label.x = sequenceFlow.label.x;
- label.y = sequenceFlow.label.y;
- modeling.updateProperties(label, {});
- }
- });
- }
- };
- static gatewayTypeSettings = (bpmn: any, node: any) => {
- let elementRegistry: any = bpmn.get('elementRegistry');
- let allElement = elementRegistry.getAll();
- let jnpfData = bpmn.get('jnpfData');
- allElement.map((element: any) => {
- if (hasGatewayType.has(element.wnType)) {
- let sourceElement = element.incoming[0]?.source;
- jnpfData.setValue(sourceElement.id, { divideRule: element.wnType });
- if(sourceElement.wmType != typeOutside && node[sourceElement.id]) node[sourceElement.id].divideRule = element.wnType;
- } else if (element.wnType != typeTrigger) {
- let sourceElement = element.incoming[0]?.source;
- if (sourceElement?.id && !hasGatewayType.has(sourceElement.wnType) && node[sourceElement.id]) {
- jnpfData.setValue(sourceElement.id, { divideRule: typeInclusion });
- node[sourceElement.id].divideRule = typeInclusion;
- }
- }
- });
- return node;
- };
- // 自动生成网关位置
- static handleCreateGatewayBounds = (xmlDoc, gatewayId, plane) => {
- let gatewayBpmnEdge = xmlDoc.createElement('bpmndi:BPMNShape');
- let waypoint = xmlDoc.createElement('dc:Bounds');
- gatewayBpmnEdge.setAttribute('id', gatewayId + '_di');
- gatewayBpmnEdge.setAttribute('bpmnElement', gatewayId);
- waypoint.setAttribute('x', '1');
- waypoint.setAttribute('y', '1');
- waypoint.setAttribute('width', '1');
- waypoint.setAttribute('height', '1');
- gatewayBpmnEdge.appendChild(waypoint);
- plane.appendChild(gatewayBpmnEdge);
- };
- // label生成位置
- static updateLabelWaypoints: any = (connection, elementRegistry, jnpfData, type = 0) => {
- let targetElement = elementRegistry.get(connection.target?.id);
- let sourceElement = elementRegistry.get(connection.source?.id);
- let labelCenter = getExternalLabelMid(connection);
- if (connection?.label && targetElement && sourceElement)
- labelCenter = this.updateLabelCenter(targetElement, sourceElement, labelCenter, connection, jnpfData.data?.layout?.value, type);
- return labelCenter;
- };
- static getNewLabelWaypoints: any = (connection, elementRegistry, jnpfData, type = 0) => {
- let targetElement = elementRegistry.get(connection.target.id);
- let sourceElement = elementRegistry.get(connection.source.id);
- let labelCenter = getExternalLabelMid(connection);
- labelCenter = this.updateLabelCenter(targetElement, sourceElement, labelCenter, connection, jnpfData.data?.layout?.value, type);
- return labelCenter;
- };
- static updateLabelCenter = (targetElement, sourceElement, labelCenter, connection, layoutType, type) => {
- let connectWaypointsStart = connection.waypoints[0];
- let connectWaypointsEnd = connection.waypoints[connection.waypoints.length - 1];
- let defaultLabelCenter = labelCenter;
- if (layoutType === 'horizontal' && type != 1) {
- if (targetElement?.incoming?.length > 1) {
- labelCenter = {
- x: sourceElement.x + sourceElement.width + 16,
- y: sourceElement.y + sourceElement.height / 2 - 35,
- };
- // 如果线条箭头y坐标在targetElement 顶部或者底部 取线条的顶部或者底部位置
- if (connectWaypointsEnd?.y === targetElement.y || connectWaypointsEnd?.y === targetElement.y + targetElement.height) {
- labelCenter.y = connection.waypoints[1]?.y - 35;
- }
- if (connectWaypointsStart?.y === sourceElement.y) {
- labelCenter = {
- x: connectWaypointsStart.x - 70,
- y: connectWaypointsStart.y - 35,
- };
- }
- if (connectWaypointsStart.y === sourceElement.y + sourceElement.height) {
- labelCenter = {
- x: connectWaypointsStart.x - 70,
- y: connectWaypointsStart.y + 10,
- };
- }
- if (connectWaypointsStart.x === sourceElement.x) {
- labelCenter = {
- x: connectWaypointsStart.x - 140,
- y: connectWaypointsStart.y - 35,
- };
- }
- if (sourceElement.outgoing.length > 1) {
- labelCenter = defaultLabelCenter
- }
- } else {
- // 根据箭头坐标位置不同显示不同的坐标
- labelCenter = {
- x: targetElement.x - 140,
- y: targetElement.y + targetElement.height / 2 - 35,
- };
- // 上方
- if (connectWaypointsEnd?.y === targetElement.y)
- labelCenter = {
- x: connectWaypointsEnd?.x - 70,
- y: connectWaypointsEnd?.y - 35,
- };
- // 下方
- if (connectWaypointsEnd?.y === targetElement.y + targetElement.height)
- labelCenter = {
- x: connectWaypointsEnd?.x - 70,
- y: connectWaypointsEnd?.y + 10,
- };
- // 右方
- if (connectWaypointsEnd?.x === targetElement.x + targetElement.width) {
- labelCenter = {
- x: connectWaypointsEnd?.x + 10,
- y: connectWaypointsEnd?.y - 35,
- };
- }
- // 左方
- if (connectWaypointsEnd?.x === targetElement.x) {
- labelCenter = {
- x: connectWaypointsEnd?.x - 140,
- y: connectWaypointsEnd?.y - 35,
- };
- }
- }
- }
- if ((layoutType === 'vertical' && type != 1) || type === 1) {
- if (targetElement?.incoming?.length > 1) {
- labelCenter = {
- x: connectWaypointsStart.x - 70,
- y: sourceElement.y + sourceElement.height + 10,
- };
- // 左右
- if (connectWaypointsStart?.x === sourceElement.x || connectWaypointsStart?.x === sourceElement.x + sourceElement.width) {
- labelCenter = {
- x: connection.waypoints[1].x - 70,
- y: connection.waypoints[2]?.y > connection.waypoints[1]?.y ? connection.waypoints[1].y + 35 : connection.waypoints[1].y - 35,
- };
- }
- //上方
- if (connectWaypointsStart?.y === sourceElement.y) {
- labelCenter = {
- x: connectWaypointsStart.x - 70,
- y: sourceElement.y - 35,
- };
- }
- if (sourceElement.outgoing.length > 1) {
- labelCenter = defaultLabelCenter
- }
- } else {
- labelCenter = {
- x: targetElement.x + targetElement.width / 2 - 20,
- y: targetElement.y - 60,
- };
- // 上方
- if (connectWaypointsEnd?.y === targetElement.y)
- labelCenter = {
- x: connectWaypointsEnd?.x - 70,
- y: connectWaypointsEnd?.y - 35,
- };
- // 下方
- if (connectWaypointsEnd?.y === targetElement.y + targetElement.height)
- labelCenter = {
- x: connectWaypointsEnd?.x - 70,
- y: connectWaypointsEnd?.y + 10,
- };
- // 左方
- if (connectWaypointsEnd?.x === targetElement.x)
- labelCenter = {
- x: targetElement.x - 140,
- y: connectWaypointsEnd?.y - 35,
- };
- // 右方
- if (connectWaypointsEnd.x === targetElement?.x + targetElement.width) {
- labelCenter = {
- x: connectWaypointsEnd?.x + 10,
- y: connectWaypointsEnd?.y - 35,
- };
- }
- }
- }
- return labelCenter;
- };
- }
|