Browse Source

fix: 更新流程设计面板

master
tony 3 years ago
parent
commit
b2ff2d6b2d
  1. 524
      ruoyi-ui/src/components/Process/customPanel/CustomContextPad.js
  2. 142
      ruoyi-ui/src/components/Process/customPanel/CustomPalette.js
  3. 8
      ruoyi-ui/src/components/Process/customPanel/index.js
  4. 8
      ruoyi-ui/src/components/Process/index.vue

524
ruoyi-ui/src/components/Process/customPanel/CustomContextPad.js

@ -0,0 +1,524 @@
import {
assign,
forEach,
isArray,
every
} from 'min-dash';
import {
is
} from 'bpmn-js/lib/util/ModelUtil';
import {
isExpanded,
isEventSubProcess
} from 'bpmn-js/lib/util/DiUtil';
import {
isAny
} from 'bpmn-js/lib/features/modeling/util/ModelingUtil';
import {
getChildLanes
} from 'bpmn-js/lib/features/modeling/util/LaneUtil';
import {
hasPrimaryModifier
} from 'diagram-js/lib/util/Mouse';
/**
* A provider for BPMN 2.0 elements context pad
*/
export default function ContextPadProvider(
config, injector, eventBus,
contextPad, modeling, elementFactory,
connect, create, popupMenu,
canvas, rules, translate) {
config = config || {};
contextPad.registerProvider(this);
this._contextPad = contextPad;
this._modeling = modeling;
this._elementFactory = elementFactory;
this._connect = connect;
this._create = create;
this._popupMenu = popupMenu;
this._canvas = canvas;
this._rules = rules;
this._translate = translate;
if (config.autoPlace !== false) {
this._autoPlace = injector.get('autoPlace', false);
}
eventBus.on('create.end', 250, function(event) {
var context = event.context,
shape = context.shape;
if (!hasPrimaryModifier(event) || !contextPad.isOpen(shape)) {
return;
}
var entries = contextPad.getEntries(shape);
if (entries.replace) {
entries.replace.action.click(event, shape);
}
});
}
ContextPadProvider.$inject = [
'config.contextPad',
'injector',
'eventBus',
'contextPad',
'modeling',
'elementFactory',
'connect',
'create',
'popupMenu',
'canvas',
'rules',
'translate'
];
ContextPadProvider.prototype.getMultiElementContextPadEntries = function(elements) {
var modeling = this._modeling;
var actions = {};
if (this._isDeleteAllowed(elements)) {
assign(actions, {
'delete': {
group: 'edit',
className: 'bpmn-icon-trash',
title: this._translate('Remove'),
action: {
click: function(event, elements) {
modeling.removeElements(elements.slice());
}
}
}
});
}
return actions;
};
/**
* @param {djs.model.Base[]} elements
* @return {boolean}
*/
ContextPadProvider.prototype._isDeleteAllowed = function(elements) {
var baseAllowed = this._rules.allowed('elements.delete', {
elements: elements
});
if (isArray(baseAllowed)) {
return every(baseAllowed, function(element) {
return includes(baseAllowed, element);
});
}
return baseAllowed;
};
ContextPadProvider.prototype.getContextPadEntries = function(element) {
var contextPad = this._contextPad,
modeling = this._modeling,
elementFactory = this._elementFactory,
connect = this._connect,
create = this._create,
popupMenu = this._popupMenu,
rules = this._rules,
autoPlace = this._autoPlace,
translate = this._translate;
var actions = {};
if (element.type === 'label') {
return actions;
}
var businessObject = element.businessObject;
function startConnect(event, element) {
connect.start(event, element);
}
function removeElement(e, element) {
modeling.removeElements([ element ]);
}
function getReplaceMenuPosition(element) {
var Y_OFFSET = 5;
var pad = contextPad.getPad(element).html;
var padRect = pad.getBoundingClientRect();
var pos = {
x: padRect.left,
y: padRect.bottom + Y_OFFSET
};
return pos;
}
/**
* Create an append action
*
* @param {string} type
* @param {string} className
* @param {string} [title]
* @param {Object} [options]
*
* @return {Object} descriptor
*/
function appendAction(type, className, title, options) {
if (typeof title !== 'string') {
options = title;
title = translate('Append {type}', { type: type.replace(/^bpmn:/, '') });
}
function appendStart(event, element) {
var shape = elementFactory.createShape(assign({ type: type }, options));
create.start(event, shape, {
source: element
});
}
var append = autoPlace ? function(event, element) {
var shape = elementFactory.createShape(assign({ type: type }, options));
autoPlace.append(element, shape);
} : appendStart;
return {
group: 'model',
className: className,
title: title,
action: {
dragstart: appendStart,
click: append
}
};
}
function splitLaneHandler(count) {
return function(event, element) {
// actual split
modeling.splitLane(element, count);
// refresh context pad after split to
// get rid of split icons
contextPad.open(element, true);
};
}
if (isAny(businessObject, [ 'bpmn:Lane', 'bpmn:Participant' ]) && isExpanded(element)) {
var childLanes = getChildLanes(element);
assign(actions, {
'lane-insert-above': {
group: 'lane-insert-above',
className: 'bpmn-icon-lane-insert-above',
title: translate('Add Lane above'),
action: {
click: function(event, element) {
modeling.addLane(element, 'top');
}
}
}
});
if (childLanes.length < 2) {
if (element.height >= 120) {
assign(actions, {
'lane-divide-two': {
group: 'lane-divide',
className: 'bpmn-icon-lane-divide-two',
title: translate('Divide into two Lanes'),
action: {
click: splitLaneHandler(2)
}
}
});
}
if (element.height >= 180) {
assign(actions, {
'lane-divide-three': {
group: 'lane-divide',
className: 'bpmn-icon-lane-divide-three',
title: translate('Divide into three Lanes'),
action: {
click: splitLaneHandler(3)
}
}
});
}
}
assign(actions, {
'lane-insert-below': {
group: 'lane-insert-below',
className: 'bpmn-icon-lane-insert-below',
title: translate('Add Lane below'),
action: {
click: function(event, element) {
modeling.addLane(element, 'bottom');
}
}
}
});
}
if (is(businessObject, 'bpmn:FlowNode')) {
if (is(businessObject, 'bpmn:EventBasedGateway')) {
assign(actions, {
'append.receive-task': appendAction(
'bpmn:ReceiveTask',
'bpmn-icon-receive-task',
translate('Append ReceiveTask')
),
'append.message-intermediate-event': appendAction(
'bpmn:IntermediateCatchEvent',
'bpmn-icon-intermediate-event-catch-message',
translate('Append MessageIntermediateCatchEvent'),
{ eventDefinitionType: 'bpmn:MessageEventDefinition' }
),
'append.timer-intermediate-event': appendAction(
'bpmn:IntermediateCatchEvent',
'bpmn-icon-intermediate-event-catch-timer',
translate('Append TimerIntermediateCatchEvent'),
{ eventDefinitionType: 'bpmn:TimerEventDefinition' }
),
'append.condition-intermediate-event': appendAction(
'bpmn:IntermediateCatchEvent',
'bpmn-icon-intermediate-event-catch-condition',
translate('Append ConditionIntermediateCatchEvent'),
{ eventDefinitionType: 'bpmn:ConditionalEventDefinition' }
),
'append.signal-intermediate-event': appendAction(
'bpmn:IntermediateCatchEvent',
'bpmn-icon-intermediate-event-catch-signal',
translate('Append SignalIntermediateCatchEvent'),
{ eventDefinitionType: 'bpmn:SignalEventDefinition' }
)
});
} else
if (isEventType(businessObject, 'bpmn:BoundaryEvent', 'bpmn:CompensateEventDefinition')) {
assign(actions, {
'append.compensation-activity':
appendAction(
'bpmn:Task',
'bpmn-icon-task',
translate('Append compensation activity'),
{
isForCompensation: true
}
)
});
} else
if (!is(businessObject, 'bpmn:EndEvent') &&
!businessObject.isForCompensation &&
!isEventType(businessObject, 'bpmn:IntermediateThrowEvent', 'bpmn:LinkEventDefinition') &&
!isEventSubProcess(businessObject)) {
assign(actions, {
'append.end-event': appendAction(
'bpmn:EndEvent',
'bpmn-icon-end-event-none',
translate('Append EndEvent')
),
'append.gateway': appendAction(
'bpmn:ExclusiveGateway',
'bpmn-icon-gateway-none',
translate('Append Gateway')
),
'append.append-user-task': appendAction(
'bpmn:Task',
'bpmn-icon-user-task',
translate('添加用户任务')
),
'append.intermediate-event': appendAction(
'bpmn:IntermediateThrowEvent',
'bpmn-icon-intermediate-event-none',
translate('Append Intermediate/Boundary Event')
)
});
}
}
if (!popupMenu.isEmpty(element, 'bpmn-replace')) {
// Replace menu entry
assign(actions, {
'replace': {
group: 'edit',
className: 'bpmn-icon-screw-wrench',
title: translate('Change type'),
action: {
click: function(event, element) {
var position = assign(getReplaceMenuPosition(element), {
cursor: { x: event.x, y: event.y }
});
popupMenu.open(element, 'bpmn-replace', position, {
title: translate('Change element'),
width: 300,
search: true
});
}
}
}
});
}
if (is(businessObject, 'bpmn:SequenceFlow')) {
assign(actions, {
'append.text-annotation': appendAction(
'bpmn:TextAnnotation',
'bpmn-icon-text-annotation'
)
});
}
if (
isAny(businessObject, [
'bpmn:FlowNode',
'bpmn:InteractionNode',
'bpmn:DataObjectReference',
'bpmn:DataStoreReference',
])
) {
assign(actions, {
'append.text-annotation': appendAction(
'bpmn:TextAnnotation',
'bpmn-icon-text-annotation'
),
'connect': {
group: 'connect',
className: 'bpmn-icon-connection-multi',
title: translate(
'Connect using ' +
(businessObject.isForCompensation
? ''
: 'Sequence/MessageFlow or ') +
'Association'
),
action: {
click: startConnect,
dragstart: startConnect,
},
},
});
}
if (is(businessObject, 'bpmn:TextAnnotation')) {
assign(actions, {
'connect': {
group: 'connect',
className: 'bpmn-icon-connection-multi',
title: translate('Connect using Association'),
action: {
click: startConnect,
dragstart: startConnect,
},
},
});
}
if (isAny(businessObject, [ 'bpmn:DataObjectReference', 'bpmn:DataStoreReference' ])) {
assign(actions, {
'connect': {
group: 'connect',
className: 'bpmn-icon-connection-multi',
title: translate('Connect using DataInputAssociation'),
action: {
click: startConnect,
dragstart: startConnect
}
}
});
}
if (is(businessObject, 'bpmn:Group')) {
assign(actions, {
'append.text-annotation': appendAction('bpmn:TextAnnotation', 'bpmn-icon-text-annotation')
});
}
// delete element entry, only show if allowed by rules
var deleteAllowed = rules.allowed('elements.delete', { elements: [ element ] });
if (isArray(deleteAllowed)) {
// was the element returned as a deletion candidate?
deleteAllowed = deleteAllowed[0] === element;
}
if (deleteAllowed) {
assign(actions, {
'delete': {
group: 'edit',
className: 'bpmn-icon-trash',
title: translate('Remove'),
action: {
click: removeElement
}
}
});
}
return actions;
};
// helpers /////////
function isEventType(eventBo, type, definition) {
var isType = eventBo.$instanceOf(type);
var isDefinition = false;
var definitions = eventBo.eventDefinitions || [];
forEach(definitions, function(def) {
if (def.$type === definition) {
isDefinition = true;
}
});
return isType && isDefinition;
}
function includes(array, item) {
return array.indexOf(item) !== -1;
}

142
ruoyi-ui/src/components/Process/customPanel/CustomPalette.js

@ -0,0 +1,142 @@
import { assign } from "min-dash";
export default function CustomPalette(
palette,
create,
elementFactory,
handTool,
lassoTool,
spaceTool,
globalConnect,
translate
) {
this.create = create;
this.elementFactory = elementFactory;
this.handTool = handTool;
this.lassoTool = lassoTool;
this.spaceTool = spaceTool;
this.globalConnect = globalConnect;
this.translate = translate;
palette.registerProvider(this);
}
CustomPalette.$inject = [
"palette",
"create",
"elementFactory",
"handTool",
"lassoTool",
"spaceTool",
"globalConnect",
"translate"
];
CustomPalette.prototype.getPaletteEntries = function (element) {
const {
create,
elementFactory,
handTool,
lassoTool,
spaceTool,
globalConnect,
translate
} = this;
function createAction(type, group, className, title, options) {
function createListener(event) {
var shape = elementFactory.createShape(assign({ type: type }, options));
if (options) {
shape.businessObject.di.isExpanded = options.isExpanded;
}
create.start(event, shape);
}
var shortType = type.replace(/^bpmn:/, "");
return {
group: group,
className: className,
title: title || translate("Create {type}", { type: shortType }),
action: {
dragstart: createListener,
click: createListener
}
};
}
return {
'hand-tool': {
group: 'tools',
className: 'bpmn-icon-hand-tool',
title: '激活抓手工具',
action: {
click: function(event) {
handTool.activateHand(event);
}
}
},
"lasso-tool": {
group: "tools",
className: "bpmn-icon-lasso-tool",
title: "激活套索工具",
action: {
click: function (event) {
lassoTool.activateSelection(event);
}
}
},
'space-tool': {
group: 'tools',
className: 'bpmn-icon-space-tool',
title: translate('Activate the create/remove space tool'),
action: {
click: function(event) {
spaceTool.activateSelection(event);
}
}
},
'global-connect-tool': {
group: 'tools',
className: 'bpmn-icon-connection-multi',
title: translate('Activate the global connect tool'),
action: {
click: function(event) {
globalConnect.start(event);
}
}
},
"tool-separator": {
group: "tools",
separator: true
},
"create.start-event": createAction(
"bpmn:StartEvent",
"event",
"bpmn-icon-start-event-none",
"创建开始节点"
),
"create.end-event": createAction(
"bpmn:EndEvent",
"event",
"bpmn-icon-end-event-none",
"创建结束节点"
),
"create.user-task": createAction(
"bpmn:UserTask",
"activity",
"bpmn-icon-user-task",
"创建用户任务"
),
"create.exclusive-gateway": createAction(
"bpmn:ExclusiveGateway",
"gateway",
"bpmn-icon-gateway-xor",
"创建排他网关"
)
};
};

8
ruoyi-ui/src/components/Process/customPanel/index.js

@ -0,0 +1,8 @@
import CustomContextPad from './CustomContextPad';
import CustomPalette from "./CustomPalette";
export default {
__init__: [ 'paletteProvider','contextPadProvider'],
paletteProvider: [ 'type', CustomPalette ],
contextPadProvider: [ 'type', CustomContextPad ],
};

8
ruoyi-ui/src/components/Process/index.vue

@ -57,6 +57,7 @@ import BpmData from './BpmData'
import getInitStr from './flowable/init'
// flowable
import FlowableModule from './flowable/flowable.json'
import customControlsModule from './customPanel'
export default {
name: 'WorkflowBpmnModeler',
components: {
@ -106,9 +107,10 @@ export default {
this.modeler = new Modeler({
container: this.$refs.canvas,
additionalModules: [
{
customControlsModule,
{ //
translate: ['value', customTranslate]
}
},
],
moddleExtensions: {
flowable: FlowableModule
@ -156,7 +158,7 @@ export default {
})
try {
await this.modeler.importXML(data)
this.adjustPalette()
// this.adjustPalette()
this.fitViewport()
} catch (err) {
console.error(err.message, err.warnings)

Loading…
Cancel
Save