import { changeTypeByTaskShape, changeTypeByTrigger, hasGatewayType, typeConfig } from '../../../config';
|
import { jnpfConfigBpmnContextPad } from '../../../config/contextPad';
|
import {
|
bpmnEnd,
|
bpmnTask,
|
typeTask,
|
typeSubFlow,
|
typeLabel,
|
bpmnInclusive,
|
typeConfluence,
|
bpmnStart,
|
typeTrigger,
|
bpmnTrigger,
|
typeExecute,
|
bpmnLabel,
|
typeStart,
|
typeCopy,
|
bpmnCopy,
|
bpmnPaste,
|
typePaste,
|
bpmnChoose,
|
typeProcessing,
|
typeOutside,
|
typeEnd,
|
typeChoose,
|
typeCondition,
|
} from '../../../config/variableName';
|
import { BPMNTreeBuilder } from '../../../utils/constructTreeUtil';
|
import { DEFAULT_DISTANCE } from '../../../config/constants';
|
import { buildBitUUID } from '../../../utils/uuidUtil';
|
import { NodeUtils } from '../../../utils/nodeUtil';
|
import bpmnType from '../../../palette/bpmnType';
|
|
const CustomizeContextPad = (contextPadProvider: any, element: any) => {
|
let type = element.type;
|
let isAction = true;
|
if (typeConfig[type]) {
|
const {
|
_autoPlace: autoPlace,
|
_create: create,
|
_elementFactory: elementFactory,
|
_modeling: modeling,
|
_connect: connects,
|
_injector: injector,
|
_rules: rules,
|
_eventBus: eventBus,
|
} = contextPadProvider;
|
let wnType = element.wnType;
|
if (wnType === bpmnTrigger) type = bpmnTrigger;
|
if (changeTypeByTaskShape[wnType]) type = changeTypeByTaskShape[wnType];
|
const { contextPad, shapeType } = typeConfig[type];
|
const { del, copy, paste } = jnpfConfigBpmnContextPad;
|
let customization = contextPad?.customization;
|
|
if (type === bpmnLabel) {
|
let connect = element?.labelTarget;
|
let target = connect.target;
|
// 执行节点的线label使用groupCustomization
|
if (changeTypeByTaskShape[target.wnType]) {
|
customization = contextPad?.groupCustomization;
|
}
|
}
|
if (type === shapeType) {
|
if (contextPad) {
|
let jnpfData = injector.get('jnpfData');
|
let copyElement = jnpfData.getValue('copyType');
|
if (element.wnType === typeTrigger && changeTypeByTaskShape[copyElement.type]) customization = contextPad?.otherCustomization;
|
if (changeTypeByTaskShape[element.wnType] && changeTypeByTaskShape[copyElement.type]) customization = contextPad?.otherCustomization;
|
if (contextPad.default) return defaultContextPad;
|
else if (customization) {
|
let result: any = {};
|
for (let key of Object.keys(customization)) {
|
let data = customization[key];
|
if (data.group === 'model') {
|
let options: any = {
|
wnName: typeConfig[key]?.renderer.rendererName,
|
};
|
if (element.type === bpmnStart && hasGatewayType.has(key)) {
|
// 开始节点只有分类节点 因为网关的分流节点和合流节点类型一致 多增加一个字段来表示
|
options = {
|
wnName: typeConfig[key]?.renderer.rendererName,
|
wnGatewayType: key,
|
wnType: key,
|
icon: data.icon,
|
};
|
}
|
result[data.name] = appendAction(data.type, data.elementName, data.className, data.title, data.wnType, options);
|
} else if (data.group === 'connect') {
|
result[data.name] = {
|
group: data.group,
|
className: data.className,
|
title: data.title,
|
action: {
|
click: isAction && startConnect,
|
},
|
};
|
} else if (data.group === 'edit') {
|
result[data.name] = {
|
group: data.group,
|
className: data.className,
|
title: data.title,
|
action: {
|
click: removeElement,
|
},
|
};
|
}
|
}
|
return Object.assign(result);
|
} else return defaultContextPad();
|
}
|
// 单个节点删除功能
|
function removeElement() {
|
rules.allowed('elements.delete', { elements: [element] });
|
}
|
// 开始连线(拖拽)
|
function startConnect(event: any, element: any) {
|
connects.start(event, element);
|
}
|
// 添加事件
|
function appendAction(type: any, name: any, className: any, title: any, wnType: any, options?: any) {
|
const appendStart = (event: any, element: any) => {
|
let bpmnFactory = elementFactory._bpmnFactory;
|
if ([typeSubFlow, typeProcessing, typeOutside].includes(type)) type = bpmnTask;
|
let businessObject = bpmnFactory.create(type);
|
let shape = elementFactory.createShape(Object.assign({ type, name, wnType, ...options }, businessObject));
|
create.start(event, shape, { source: element });
|
};
|
const autoPlaceAppend = async (_event: any, element: any) => {
|
let isPaste = false;
|
if (wnType === typeCopy) {
|
copyElement(element.wnType);
|
return;
|
}
|
if (wnType === typePaste) {
|
let jnpfData = injector.get('jnpfData');
|
let data = jnpfData.getValue(bpmnCopy);
|
let copyElement = jnpfData.getValue('copyType');
|
isPaste = true;
|
if ([typeOutside, typeTrigger, 'default'].includes(copyElement.type)) {
|
type = data.type;
|
wnType = data.wnType;
|
className = data.className;
|
title = data.title;
|
options = data.options;
|
if (element.outgoing.length > 1) {
|
let connect = element.outgoing.find(connect => connect.target.wnType != typeTrigger);
|
element = connect.label;
|
} else {
|
element = element.outgoing[0]?.label;
|
}
|
}
|
if (copyElement.type === typeTrigger || changeTypeByTaskShape[copyElement.type]) {
|
type = data.type;
|
wnType = data.wnType;
|
className = data.className;
|
title = data.title;
|
options = data.options;
|
name = data.name;
|
}
|
}
|
let hasTaskType = new Set([typeSubFlow, typeProcessing, typeTrigger, typeOutside]);
|
if (hasTaskType.has(type) || changeTypeByTaskShape[wnType]) type = bpmnTask;
|
let bpmnFactory = elementFactory._bpmnFactory;
|
let isChoose = false;
|
if (type === bpmnChoose) {
|
type = bpmnInclusive;
|
isChoose = true;
|
}
|
let businessObject = type === bpmnType ? bpmnFactory.create(element.type) : bpmnFactory.create(type);
|
let shape = elementFactory.createShape(Object.assign({ type, name: name, businessObject, wnType: wnType }, options));
|
if (element.type === typeLabel) {
|
let businessTaskObject = bpmnFactory.create(bpmnTask);
|
let businessTask2Object = bpmnFactory.create(bpmnTask);
|
let businessInclusiveObject = bpmnFactory.create(bpmnInclusive);
|
let shape: any;
|
if (hasGatewayType.has(wnType)) {
|
let id = `Gateway_${buildBitUUID()}_isSimple`;
|
businessObject.id = id;
|
shape = elementFactory.createShape(Object.assign({ type, id: id, name: name, businessObject, wnType: wnType }, options));
|
} else {
|
shape = elementFactory.createShape(Object.assign({ type, name: name, businessObject, wnType: wnType }, options));
|
}
|
updateShapePosition(shape, element, businessTaskObject, businessInclusiveObject, businessTask2Object);
|
if (isChoose) {
|
modeling.updateProperties(shape, {
|
type: bpmnChoose,
|
});
|
}
|
} else {
|
autoPlace.append(element, shape);
|
// 自研
|
if (hasGatewayType.has(element.wnType)) {
|
// 获取对应的合流网关
|
const gateway = injector.get('elementRegistry').get(element.id + '_confluence');
|
modeling.connect(shape, gateway);
|
}
|
// 处理执行节点的美化 (获取到最近的合流节点 判断分组与合流坐标距离计算是否需要进行偏移)
|
if (changeTypeByTaskShape[shape.wnType]) {
|
modeling.updateProperties(shape, {
|
customGroupId: element.businessObject.$attrs.customGroupId,
|
});
|
let groupShape = injector.get('elementRegistry').get(element.businessObject.$attrs.customGroupId);
|
let shapeRight = shape.x + shape.width;
|
let shapeBottom = shape.y + shape.height;
|
let groupRight = groupShape.x + groupShape.width;
|
let groupBottom = groupShape.y + groupShape.height;
|
var newBounds: any = {
|
x: groupShape.x, // 保持 x 位置不变
|
y: groupShape.y, // 保持 y 位置不变
|
width: groupShape.width,
|
height: groupShape.height,
|
};
|
if (shapeRight >= groupRight) newBounds.width = shapeRight + 25 - groupShape.x;
|
if (shapeBottom >= groupBottom) newBounds.height = shapeBottom + 15 - groupShape.y;
|
modeling.resizeShape(groupShape, newBounds);
|
autoExecute(groupShape);
|
}
|
}
|
// 计算需要横向偏移的元素(只有出现分流的情况下需要用到)
|
if (element?.type === typeLabel || hasGatewayType.has(element.wnType) || element.wnType === typeTrigger || changeTypeByTaskShape[element.wnType])
|
onAutoPosition();
|
// 粘贴节点属性(需modeling.create后才能使用modeling.updatePropertie()生效)
|
if (isPaste) {
|
let jnpfData = injector.get('jnpfData');
|
let copyElement = jnpfData.getValue('copyType');
|
let newData = copyElement.data;
|
let newShape = injector.get('elementRegistry').get(shape.id);
|
let customGroupId = "";
|
|
if (changeTypeByTrigger[newShape.wnType] || newShape.wnType === typeTrigger) customGroupId = newShape?.businessObject?.$attrs?.customGroupId
|
else if (changeTypeByTaskShape[newShape.wnType]) customGroupId = element?.businessObject?.$attrs?.customGroupId
|
jnpfData.setValue(shape.id, { ...newData, nodeId: shape.id, groupId: customGroupId });
|
|
if (newShape) {
|
newShape['elementBodyName'] = newData?.content || '';
|
newShape['nodeName'] = newData?.nodeName || '';
|
modeling.updateProperties(newShape, {
|
customGroupId: customGroupId,
|
});
|
}
|
}
|
};
|
var append = autoPlace ? autoPlaceAppend : appendStart;
|
let disable = isAction;
|
let lastsource = element?.labelTarget?.source;
|
let nextTarget = element?.labelTarget?.target;
|
let targetType = nextTarget?.wnType
|
let sourceType = lastsource?.wnType
|
if ([typeConfluence].includes(sourceType) && (hasGatewayType.has(wnType) || wnType === typeTrigger)) disable = false;
|
if (sourceType === typeSubFlow && ([typeChoose].includes(wnType))) disable = false;
|
if (sourceType === typeOutside && ([typeChoose, typeTrigger, typeOutside, typeSubFlow].includes(wnType))) disable = false;
|
if (hasGatewayType.has(nextTarget?.wnType) && hasGatewayType.has(wnType)) disable = false;
|
if (nextTarget?.wnType === typeTrigger && ([typeSubFlow, typeSubFlow, typeExecute, typeTask].includes(wnType) || hasGatewayType.has(wnType)))
|
if (changeTypeByTaskShape[nextTarget?.wnType] && hasGatewayType.has(wnType)) disable = false;
|
if ([typeStart, typeSubFlow].includes(sourceType) && wnType === typeTrigger) disable = false;
|
if (([typeOutside].includes(wnType) && [typeOutside, typeSubFlow, typeChoose, typeEnd].includes(targetType))) disable = false;
|
if (([typeSubFlow].includes(wnType) && [typeChoose].includes(targetType))) disable = false;
|
if (([typeOutside].includes(wnType) && hasGatewayType.has(targetType))) {
|
if (nextTarget.outgoing.some(o => [typeOutside, typeSubFlow].includes(o.target.wnType))) disable = false;
|
let jnpfData = injector.get('jnpfData');
|
if (nextTarget.outgoing.some(o => jnpfData.getValue(o.id)?.conditions?.length > 0)) disable = false; // 线条如果有条件也无法添加外部节点
|
}
|
|
if ([typeOutside].includes(wnType)) {
|
// 如果外部节点的下一个节点是合流节点,则继续检查合流节点的下一个节点是否为结束节点,如果是则不可添加外部节点
|
while (nextTarget && targetType === typeConfluence) {
|
let nextOutgoing = nextTarget.outgoing || [];
|
// 合流网关后面如果是子流程,外部节点,结束节点,则禁用当前的外部节点
|
if (nextOutgoing.some(out => out.target && [typeEnd, typeSubFlow, typeOutside].includes(out.target.wnType))) {
|
disable = false;
|
break;
|
}
|
// 如果有多个分支,取第一个不是合流节点的分支继续判断,否则继续循环
|
let nextConfluence = nextOutgoing.find(out => out.target && out.target.wnType === typeConfluence);
|
if (nextConfluence) nextTarget = nextConfluence.target;
|
else break;
|
}
|
while (lastsource && sourceType === typeConfluence) {
|
let lastIncoming = lastsource.incoming || [];
|
// 合流网关后面如果是子流程,外部节点,结束节点,则禁用当前的外部节点
|
if (lastIncoming.some(incoming => incoming.source && [typeOutside].includes(incoming.source.wnType))) {
|
disable = false;
|
break;
|
}
|
// 如果有多个分支,取第一个不是合流节点的分支继续判断,否则继续循环
|
let lastConfluence = lastIncoming.find(incoming => incoming.source?.wnType === typeConfluence);
|
if (lastConfluence) lastsource = lastConfluence.source;
|
else break;
|
}
|
}
|
|
return {
|
group: 'model',
|
className: className,
|
title: title,
|
disable: disable,
|
action: { click: disable && append },
|
};
|
}
|
// 默认contextPad
|
function defaultContextPad() {
|
let obj = Object.assign({
|
[del.name]: {
|
group: del.group,
|
className: del.className,
|
title: del.title,
|
action: {
|
click: removeElement,
|
},
|
},
|
[copy.name]: {
|
group: copy.group,
|
className: copy.className,
|
title: copy.title,
|
action: {
|
click: () => copyElement(wnType === typeOutside ? typeOutside : "default"),
|
},
|
},
|
});
|
let jnpfData = injector.get('jnpfData');
|
let data = jnpfData.getValue('copyType');
|
let copyNode = jnpfData.getValue('copy');
|
let outgoing = element.outgoing?.filter(o => o.target.wnType != typeTrigger)
|
if (data.type === typeOutside) {
|
if ([typeTask, typeProcessing, typeSubFlow, typeStart].includes(wnType)) {
|
if (![typeOutside, typeSubFlow].includes(outgoing[0]?.target?.wnType)) {
|
obj[paste.name] = appendAction(bpmnPaste, typePaste, paste.className, paste.title, typePaste, { wnName: null });
|
}
|
}
|
} else if (wnType === typeOutside) {
|
if (([typeTask, typeProcessing, typeSubFlow, typeEnd].includes(outgoing[0]?.target?.wnType) && [typeTask, typeProcessing].includes(copyNode?.wnType)) || data.type === bpmnTrigger) {
|
obj[paste.name] = appendAction(bpmnPaste, typePaste, paste.className, paste.title, typePaste, { wnName: null });
|
}
|
} else {
|
if (data.type === 'default' || data.type === bpmnTrigger) {
|
if (!(data.type === bpmnTrigger && wnType === typeSubFlow)) {
|
if (!(outgoing[0]?.target?.wnType === typeOutside && [typeSubFlow].includes(copyNode.wnType)))
|
obj[paste.name] = appendAction(bpmnPaste, typePaste, paste.className, paste.title, typePaste, { wnName: null });
|
}
|
}
|
}
|
return obj;
|
}
|
// 判断元素与网关之间的垂直距离是否小于某个阈值
|
function isWithinThreshold(target, source, threshold, processedElements: any) {
|
// 这里假设网关在上方,即网关的 y 坐标小于当前元素的 y 坐标
|
let gatewayY = target.y;
|
let sourceElementY = source.y;
|
// let elementObj: any;
|
let map = new Map(
|
Array.from(processedElements, (item: any) => [item.id, item]), // 使用 id 作为键
|
);
|
// 如果当前元素是合流网关 获取分流到合流内所有元素 并且获取y最大值的元素与 当前分流坐标做对比
|
if (target.wnType === typeConfluence) {
|
let allElements = injector.get('elementRegistry').getAll();
|
let treeBuilder = new BPMNTreeBuilder(allElements);
|
let gatewayElement = injector.get('elementRegistry').get(target.id.replace('_confluence', ''));
|
treeBuilder.onComputerMaxElementH(injector, target, gatewayElement, [], null, false, map, threshold);
|
}
|
if (map.has(source.id)) {
|
sourceElementY = sourceElementY + threshold;
|
}
|
return gatewayY - sourceElementY > threshold && gatewayY > sourceElementY;
|
}
|
function moveConnectedElements(connection: any, height: any, useWithinThreshold: boolean = true) {
|
const stack: any = []; // 用于存储待处理的连接线
|
const processedElements = new Set(); // 记录已经处理过的目标元素
|
stack.push(connection); // 从给定的连接线开始
|
while (stack.length > 0) {
|
const currentConnection: any = stack.pop();
|
const target = currentConnection.target;
|
if (!target) continue; // 如果没有目标元素,跳过
|
if (processedElements.has(target)) continue; // 如果目标元素已经处理过,跳过
|
if (useWithinThreshold && isWithinThreshold(target, currentConnection.source, height, processedElements)) continue;
|
processedElements.add(target); // 标记该元素已经被处理
|
// 遍历目标元素的所有出线连接,并将它们压入栈
|
const outgoingConnections: any = target.outgoing || [];
|
for (const outgoingConnection of outgoingConnections) {
|
stack.push(outgoingConnection); // 将所有关联的连接线压入栈中
|
}
|
}
|
return Array.from(processedElements);
|
}
|
function autoExecute(groupShape: any) {
|
// 判断groupBottom 和该触发节点对应的任务节点元素与合流节点间的距离
|
// 1. 获取到触发节点对应的任务节点 后续获取到该元素在哪个合流元素内部 获取到合流网关 判断合流网关和当前的判断groupBottom坐标 如果小于则需要对合流后的所有元素进行统一偏移
|
let triggerSourceShape: any;
|
injector.get('elementRegistry').forEach(e => {
|
if (e.businessObject.$attrs.customGroupId === groupShape.id && e.wnType === typeTrigger) triggerSourceShape = e.incoming[0].source;
|
});
|
// 迭代获取最近的合流节点 如果下一个节点时分流节点 则获取到对应的合流节点继续获取下一个节点
|
function getConfluence(shape: any) {
|
let targetList = NodeUtils.getNextElementList(shape, injector.get('elementRegistry').getAll());
|
let confluence: any;
|
targetList.map((element: any) => {
|
if (element.wnType === typeConfluence) {
|
confluence = element;
|
return;
|
}
|
if (element.wnType != typeTrigger) confluence = getConfluence(element);
|
if (hasGatewayType.has(element.wnType)) confluence = getConfluence(injector.get('elementRegistry').get(element.id + '_confluence'));
|
});
|
return confluence;
|
}
|
let confluenceShape = getConfluence(triggerSourceShape);
|
if (confluenceShape) {
|
if (groupShape && groupShape.y + groupShape.height + 50 >= confluenceShape.y) {
|
modeling.moveElements(moveConnectedElements(confluenceShape.incoming[0], 0, false), {
|
x: 0,
|
y: groupShape.y + groupShape.height + DEFAULT_DISTANCE - 15 - confluenceShape.y,
|
});
|
}
|
}
|
}
|
async function updateShapePosition(shape: any, element: any, businessTaskObject, businessInclusiveObject, businessTask2Object) {
|
let connectElement: any = element?.labelTarget;
|
let targetElement = connectElement?.target;
|
let sourceElement = connectElement?.source;
|
let promises: any = [];
|
if (shape.wnType === typeTrigger) {
|
// 生成一个触发节点
|
let labelTargetY = (DEFAULT_DISTANCE + typeConfig[bpmnTask].renderer.attr.height) * 2;
|
let y = labelTargetY - (targetElement.y - sourceElement.y);
|
if (targetElement.wnType === typeConfluence) {
|
modeling.moveElements(moveConnectedElements(element.labelTarget, labelTargetY), {
|
x: 0,
|
y: y,
|
});
|
}
|
autoPlace.append(sourceElement, shape);
|
let groupShapes = modeling.createShape(
|
{
|
type: 'bpmn:Group',
|
},
|
{ x: shape.x - 25, y: shape.y - 15, width: 250, height: 118 },
|
shape.parent,
|
);
|
modeling.updateProperties(shape, {
|
customGroupId: groupShapes.id,
|
});
|
} else if (hasGatewayType.has(shape.wnType)) {
|
// 生成两个分支 包含分支 → 条件节点*2 → 任务节点*2 → 合流节点*1 最后融入到旧元素内
|
let shape1 = elementFactory.createShape(
|
Object.assign({ type: bpmnTask, name: typeTask, businessObject: businessTaskObject, wnType: typeTask }, { wnName: '审批节点' }),
|
);
|
businessInclusiveObject.id = shape.id + '_confluence';
|
let gateway = elementFactory.createShape(
|
Object.assign(
|
{
|
id: shape.id + '_confluence',
|
type: bpmnInclusive,
|
name: typeConfluence,
|
businessObject: businessInclusiveObject,
|
wnType: typeConfluence,
|
},
|
{ wnName: '合流' },
|
),
|
);
|
let shape2 = elementFactory.createShape(
|
Object.assign({ type: bpmnTask, name: typeTask, businessObject: businessTask2Object, wnType: typeTask }, { wnName: '审批节点' }),
|
);
|
let labelTargetY =
|
DEFAULT_DISTANCE * 4 +
|
typeConfig[bpmnTask].renderer.attr.height +
|
typeConfig[sourceElement.type].renderer.attr.height +
|
typeConfig[bpmnInclusive].renderer.attr.height;
|
promises.push(
|
modeling.moveElements(moveConnectedElements(element.labelTarget, labelTargetY), {
|
x: 0,
|
y: labelTargetY - (targetElement.y - sourceElement.y),
|
}),
|
);
|
promises.push(modeling.removeConnection(connectElement));
|
promises.push(autoPlace.append(sourceElement, shape));
|
promises.push(autoPlace.append(shape, shape1));
|
promises.push(autoPlace.append(shape, shape2));
|
promises.push(autoPlace.append(shape1, gateway));
|
promises.push(modeling.connect(shape2, gateway));
|
promises.push(modeling.connect(gateway, targetElement));
|
} else if (targetElement) {
|
let labelTargetY = (DEFAULT_DISTANCE + typeConfig[bpmnTask].renderer.attr.height) * 2;
|
let y = labelTargetY - (targetElement.y - sourceElement.y);
|
if (targetElement.type === bpmnEnd) y = DEFAULT_DISTANCE + typeConfig[bpmnTask].renderer.attr.height;
|
if (sourceElement.type === bpmnStart) y = DEFAULT_DISTANCE + typeConfig[bpmnTask].renderer.attr.height;
|
if (sourceElement.wnType === typeConfluence) {
|
y = DEFAULT_DISTANCE + typeConfig[bpmnTask].renderer.attr.height;
|
if (targetElement.y - sourceElement.y - DEFAULT_DISTANCE * 2 - typeConfig[bpmnTask].renderer.attr.height > 0) y = 0;
|
if (targetElement.y - sourceElement.y - DEFAULT_DISTANCE * 2 - typeConfig[bpmnTask].renderer.attr.height < 0)
|
y = (sourceElement.y + DEFAULT_DISTANCE * 2 + typeConfig[bpmnTask].renderer.attr.height) - targetElement.y;
|
|
}
|
if (sourceElement?.wnType === typeConfluence && targetElement?.wnType === typeConfluence) {
|
let maxY = -Infinity;
|
let id;
|
targetElement = injector.get('elementRegistry').get(targetElement.id);
|
targetElement.incoming?.length > 0 &&
|
targetElement.incoming.map(item => {
|
let currentElement: any = injector.get('elementRegistry').get(item.id);
|
if (currentElement.source?.y > maxY) {
|
id = currentElement.source.id;
|
maxY = currentElement.source.y;
|
}
|
});
|
if (targetElement.y - maxY <= DEFAULT_DISTANCE && sourceElement.id != id) {
|
y = DEFAULT_DISTANCE - (targetElement.y - maxY);
|
}
|
}
|
if (changeTypeByTaskShape[shape.wnType]) {
|
let source = contextPadProvider._injector.get('elementRegistry').get(connectElement.id).source;
|
// 需要增加customGroupId
|
modeling.updateProperties(shape, {
|
customGroupId: source.businessObject.$attrs.customGroupId,
|
});
|
}
|
promises.push(
|
modeling.moveElements(moveConnectedElements(element.labelTarget, labelTargetY), {
|
x: 0,
|
y: y,
|
}),
|
);
|
promises.push(modeling.removeConnection(connectElement));
|
autoPlace.append(sourceElement, shape);
|
promises.push(modeling.connect(shape, targetElement));
|
}
|
Promise.all(promises);
|
let elementRegistry = injector.get('elementRegistry');
|
let treeBuilder = new BPMNTreeBuilder(elementRegistry.getAll()); // 实例化工具类
|
treeBuilder.resizeGroupShape(elementRegistry.getAll(), injector);
|
if (changeTypeByTaskShape[shape.wnType]) {
|
let groupShape = injector.get('elementRegistry').get(targetElement.businessObject.$attrs.customGroupId);
|
autoExecute(groupShape);
|
}
|
}
|
async function onAutoPosition() {
|
let elementRegistry: any = await contextPadProvider._injector.get('elementRegistry');
|
let allElements = elementRegistry.getAll();
|
let treeBuilder = new BPMNTreeBuilder(allElements); // 实例化工具类
|
let bpmnTree = treeBuilder.constructTree(1); // 构建树状数据结构
|
let visited: any = new Map(); // 用于防止重复访问
|
let shapeList: any = []; // 修改触发节点旁的连接线坐标
|
let confluenceMap: any = new Map();
|
treeBuilder.calculateVirtualWidth(bpmnTree, elementRegistry); // 计算虚拟宽度
|
treeBuilder.traverseTreeBFS(bpmnTree, node => {
|
node?.offset && node.x != node.offset.x && visited.set(node.id, node);
|
if (node?.children?.length > 0) {
|
let hasTrigger = node.children.some(o => o.wnType === typeTrigger);
|
let hasConfluence = node.children.some(o => o.wnType === typeConfluence);
|
let shape = elementRegistry.get(node.id);
|
let confluence: any;
|
if (shape.outgoing?.length) {
|
shape.outgoing.map((connect: any) => {
|
if (connect.target.wnType === typeTrigger) hasTrigger = true;
|
if (connect.target.wnType === typeConfluence) {
|
confluence = connect.target;
|
hasConfluence = true;
|
}
|
});
|
}
|
if (hasTrigger && hasConfluence)
|
shapeList.push({ shape: elementRegistry.get(node.id), treeShape: node, treeConfluence: node.children[0], confluence: confluence });
|
if (node.wnType === typeConfluence) confluenceMap.set(node.id, node);
|
}
|
});
|
treeBuilder.formatCanvas(Array.from(visited.values()), modeling, elementRegistry);
|
// 如果某个节点的出线包含合流及触发节点元素 则将连接合流节点的线进行进行重新绘制(根据当前节点的虚拟宽度计算出偏移的xy轴坐标中点)
|
// 虚拟宽度的最左侧坐标为 当前元素的x + width/2 - 虚拟宽度/2
|
shapeList.map(({ shape, treeShape, treeConfluence, confluence }) => {
|
let confluenceElement = confluenceMap.get(treeConfluence.id);
|
let x = shape.x + shape.width / 2 - treeShape.virtualWidth / 2 + shape.width / 2;
|
let newWaypoints: any = [];
|
if (!confluenceElement) {
|
confluenceElement = confluenceMap.get(confluence.id);
|
let childrenShape = treeShape.children[treeShape.children.length - 1];
|
if (childrenShape.wnType === typeConfluence) {
|
childrenShape = treeShape.children[treeShape.children.length - 2];
|
}
|
x = (childrenShape.offset?.x ? childrenShape.offset.x : childrenShape.x) + childrenShape.virtualWidth / 2 + childrenShape.width / 2 + 120;
|
newWaypoints = [
|
{ x: shape.x + shape.width, y: shape.y + shape.height / 2 },
|
{ x: x, y: shape.y + shape.height / 2 },
|
{ x: x, y: confluenceElement.y },
|
{ x: confluenceElement.x, y: confluenceElement.y },
|
];
|
} else {
|
newWaypoints = [
|
{ x: shape.x, y: shape.y + shape.height / 2 },
|
{ x: x, y: shape.y + shape.height / 2 },
|
{ x: x, y: confluenceElement.y },
|
{ x: confluenceElement.x, y: confluenceElement.y },
|
];
|
}
|
let connect = shape.outgoing[0];
|
if (shape.outgoing?.length) {
|
connect = shape.outgoing.find(connect => connect.target.wnType != typeTrigger);
|
}
|
modeling.updateWaypoints(connect, newWaypoints);
|
});
|
treeBuilder.resizeGroupShape(elementRegistry.getAll(), injector);
|
}
|
// 复制节点
|
function copyElement(type) {
|
let jnpfData = injector.get('jnpfData');
|
let selection = injector.get('selection');
|
let copyData = jnpfData.getValue(element.id);
|
jnpfData.setValue(bpmnCopy, element);
|
jnpfData.setValue('copyType', { type: type, data: copyData });
|
eventBus.fire('custom.message', {
|
context: '复制成功',
|
messageType: 'success',
|
});
|
selection.select(null);
|
}
|
}
|
|
return undefined;
|
}
|
return undefined;
|
};
|
export default CustomizeContextPad;
|