Перейти к содержанию

BPMN#

Пример отображения

BPMN - элемент управления для отрисовки диаграм в формате условных обозначений.

Контрол поставляется в отдельном пакете ecosoft-lexema8-bpmn. Для его использования необходимо установить последнюю версию пакета и настроить свойство controls раздела front.

Свойства#

id#

Идентификатор контрола.

Отнаследовано от Control.

hint#

Всплывающая подсказка, которая появляется при наведении на контрол.

Отнаследовано от Control.

hintLength#

тип значение по умолчанию допустимые значения
int -

максимальное количество символов для всплывающей подсказки

captionWidth#

Ширина заголовка в колонках (для Bootstrap-верстки).

Отнаследовано от Control.

editorWidth#

Ширина контрола в колонках (для Bootstrap-верстки).

Отнаследовано от Control.

captionTextAlign#

тип значение по умолчанию допустимые значения
string left left, right

Выравнивание текста заголовка контрола.

controlRows#

тип значение по умолчанию допустимые значения
int 1

Количество строк.

Количество однострочных контролов, по общей высоте которых (с учетом расстояния между ними) вычисляется высота memo,в случае заданного height вычисляется через height

readOnly#

тип значение по умолчанию допустимые значения
bool false true/false

Режим "только для чтения"

height#

тип значение по умолчанию допустимые значения
string auto

Высота мемо в пикселях.

По умолчанию "auto" и вычисляется через controlRows. Например, height = "100px".

denyRoles#

Список ролей без прав на данный элемент.

Отнаследовано от Control.

readRoles#

Список ролей на чтение данных.

Отнаследовано от Control.

writeRoles#

Список ролей на изменение данных.

Отнаследовано от Control.

visible#

Видимость контрола.

Отнаследовано от Control.

width#

Ширина контрола.

Отнаследовано от Control

Методы#

getRootElement#

Асинхронный метод, возвращает корневой элемент диаграммы для отрисовки.

getRootElement()
Пример
this.controls.bpmn.getRootElement().then((process) => {
        // добавляем что-то в этот корневой элемент
        const participantShape = this.controls.bpmn1.createParticipant({ name: 'Маршрут', height: 500, width: 1100 })
        this.controls.bpmn1.createObjectShape({
            shape: participantShape,
            x: 700,
            y: 300,
            canvas: process
        })
    })

getServices#

Метод, возвращающий объекты для взаимодействия с bpmn представлением.

getServices()
Пример
const editors = this.controls.bpmn.getServices()

Данный метод возвращает следующие элементы

параметр тип описание
args object объект с элементами
args.eventBus object шина событий, которая управляет всеми событиями в приложении
args.elementRegistry object реестр всех элементов диаграммы
args.modeling object сервис для модификации диаграммы
Возможности объектов
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
// Подписка на событие
eventBus.on('event.name', function(event) {
        console.log('Событие произошло:', event);
});
// Подписка с приоритетом (чем выше число, тем раньше выполнится)
eventBus.on('event.name', 1500, function(event) {
        console.log('Высокоприоритетный обработчик');
})
список всех возможных событий:
// Основные события элементов
'element.click'           // Клик на элемент
'element.dblclick'        // Двойной клик на элемент
'element.hover'           // Наведение на элемент
'element.mousedown'       // Нажатие кнопки мыши на элементе
'element.mouseup'         // Отпускание кнопки мыши на элементе
'element.contextmenu'     // Контекстное меню на элементе

// Изменения элементов
'element.changed'         // Элемент изменен
'element.marked'          // Элемент помечен
'element.unmarked'        // Элемент размаркирован

// Добавление/удаление элементов
'shape.added'             // Фигура добавлена
'shape.removed'           // Фигура удалена
'connection.added'        // Соединение добавлено
'connection.removed'      // Соединение удалено

// Выделение элементов
'selection.changed'       // Изменение выделения
'shape.selected'          // Фигура выделена
'shape.deselected'        // Фигура снята с выделения
// Zoom и viewport
'canvas.zoom'             // Изменение zoom
'canvas.viewbox.changed'  // Изменение viewbox
'canvas.scroll'           // Прокрутка canvas

// Размеры и отрисовка
'canvas.resized'          // Изменение размера canvas
'canvas.destroyed'        // Canvas уничтожен
'canvas.init'             // Canvas инициализирован

// Диаграмма
'diagram.clear'           // Диаграмма очищена
'diagram.destroy'         // Диаграмма уничтожена
'diagram.init'            // Диаграмма инициализирована
// Выполнение команд
'commandStack.preExecute'     // Перед выполнением команды
'commandStack.postExecute'    // После выполнения команды
'commandStack.executed'       // Команда выполнена

// Отмена команд
'commandStack.preUndo'        // Перед отменой команды
'commandStack.postUndo'       // После отмены команды
'commandStack.undone'         // Команда отменена

// Повтор команд
'commandStack.preRedo'        // Перед повтором команды
'commandStack.postRedo'       // После повтора команды
'commandStack.redone'         // Команда повторена

// Изменения стека
'commandStack.changed'        // Стек команд изменен
'commandStack.stack.changed'  // Изменение в стеке команд
// Direct Editing (прямое редактирование)
'directEditing.activate'      // Активация прямого редактирования
'directEditing.complete'      // Завершение прямого редактирования
'directEditing.cancel'        // Отмена прямого редактирования
'directEditing.resize'        // Изменение размера при редактировании

// Изменение свойств
'properties.panel.changed'    // Изменение в панели свойств
'properties.update'           // Обновление свойств
// Обновление элементов
'elements.changed'            // Элементы изменены
'root.set'                    // Установлен корневой элемент

// События обновления
'updateProperties'            // Свойства обновлены
'create'                      // Создание элемента
'delete'                      // Удаление элемента
'move'                        // Перемещение элемента
'resize'                      // Изменение размера элемента

'palette.getProviders'        // Получение провайдеров палитры
'palette.changed'             // Палитра изменена
'palette.create'              // Создание элемента из палитры

'contextPad.getProviders'     // Получение провайдеров контекстного меню
'contextPad.create'           // Создание из контекстного меню
'contextPad.click'            // Клик в контекстном меню
'contextPad.open'                // ContextPad открыт
'contextPad.close'               // ContextPad закрыт

'elements.paste'              // Вставка элементов
'elements.copy'               // Копирование элементов
'connection.create'           // Создание соединения
'connection.reconnect'        // Переподключение соединения
'connection.updateWaypoints'  // Обновление точек соединения

'drag.start'                  // Начало перетаскивания
'drag.move'                   // Перемещение при перетаскивании
'drag.end'                    // Конец перетаскивания
'drag.cleanup'                // Очистка после перетаскивания

// Особые события DnD
'shape.move.start'            // Начало перемещения фигуры
'shape.move.end'              // Конец перемещения фигуры
'connection.move.start'       // Начало перемещения соединения
'connection.move.end'         // Конец перемещения соединения

'import.parse.start'          // Начало парсинга импорта
'import.parse.complete'       // Завершение парсинга импорта
'import.done'                 // Импорт завершен

'export.start'                // Начало экспорта
'export.complete'             // Завершение экспорта

'saveXML.start'               // Начало сохранения XML
'saveXML.done'                // Завершение сохранения XML

'saveSVG.start'               // Начало сохранения SVG
'saveSVG.done'                // Завершение сохранения SVG
1
2
3
4
5
6
7
8
// Получить элемент по ID
elementRegistry.get(elementId)
// Получить все элементы
elementRegistry.getAll()
// Получить элементы по типу
elementRegistry.filter(element => element.type === elementType)
// Найти элемент по свойству
elementRegistry.find(element => element.businessObject && element.businessObject.name === name)
1
2
3
4
5
6
// Обновить свойства элемента
modeling.updateProperties(element, properties)
// Обновить метку (текст)
modeling.updateLabel(element, newText)
// Удалить элементы
modeling.removeElements(elements)
Пример обновления имени объекта в bpmn
1
2
3
4
5
        const editors = this.controls.bpmn.getServices()
        const modeling = editors.modeling
        const elementRegistry = editors.elementRegistry
        const Element = elementRegistry.get(id) // найти в bpmn объект по id
        modeling.updateLabel(Element, "newName") // обновление элемента Element изменив имя
Пример отслеживания клика по объекту
1
2
3
4
this.controls.bpmn.getServices().eventBus.on('element.click', 1500,  (event) => {
  event.preventDefault()
  event.stopPropagation() // отменить стандартное поведение
})

cleanAll#

Синхронный метод, удаляет все элементы с диаграммы.

cleanAll()
Пример
this.controls.bpmn.cleanAll()

moveObject#

Синхронный метод, изменяет координаты диаграммы.

moveObject(args)
параметр тип описание
args object объект со свойствами
args.object object объект который будет перемещаться
args.x number координата x
args.y number координата y
Пример
    this.controls.bpmn.moveObject({ object: participantShape, x: 100, y: 200 })

createParticipant#

Синхронный метод, создает диаграмму.

createParticipant(args)
параметр тип описание
args object объект со свойствами
args.name string текст подписи диаграммы
args.height number высота диаграммы
args.width number ширина диаграммы
args.x number координата x
Пример
1
2
3
4
5
    const participantShape = this.controls.bpmn.createParticipant({ 
        name: 'Маршрут', 
        height: 500, 
        width: 1100 
        })

После создание элемента необходимо передать его в параметр shape метода createObjectShape

createLanes#

Синхронный метод, создает полосы. Возвращает массив объектов полос диаграммы

createLanes(args)
параметр тип описание
args object объект со свойствами
args.laneName [string] массив имен полос
args.participantShape number диаграмма для которой будут добавляться линии
Пример
    countParticipant = this.controls.bpmn.createLanes({ laneName: ['ИмяОдин', 'ИмяДва', 'ИмяТри'], participantShape })

createShape#

Синхронный метод, создает элемент

createShape(args)
параметр тип описание
args object объект со свойствами
args.type string Параметр задающий то какой будет объект. Допустимые значения: bpmn:StartEvent, bpmn:BusinessRuleTask, bpmn:ExclusiveGateway, bpmn:EndEvent, bpmn:ParallelGateway
args.name string текст, который будет отображаться на экране в элементе
Пример
1
2
3
4
      const start = this.controls.bpmn1.createShape({
            type: 'bpmn:StartEvent',
            name: 'Запуск'
})

После создание элемента необходимо передать его в параметр shape метода createObjectShape

createObjectShape#

Синхронный метод, добавляет элемент на диаграмму

createObjectShape(args)
параметр тип описание
args object объект со свойствами
args.shape object объект создающий с помощью метода createShape или createParticipant
args.canvas object полотно в котором отрисовывается элемент
args.x number координата x
args.y number координата y
args.color string цвет элемента, при отсутствии цвет белый по умолчанию. Допустимые значения: Red, Green
args.textTimer string текст который будет отображаться в элементе часы
args.leftDocument function функция срабатываемая после клика по левому документу
args.rightDocument function функция срабатываемая после клика по правому документу
Пример
this.controls.bpmn.createObjectShape({
  shape: start,
  canvas: countParticipant[0],
  y: 40,
  x: 10,
  color: 'Green',
  textTimer: 'Завершен',
  leftDocument: () => { console.log('left') },
  rightDocument: () => { console.log('right') }
})

createConnection#

Синхронный метод, добавляет линию соединения

createConnection(args)
параметр тип описание
args object объект со свойствами
args.shapeBebin object объект откуда выходит линия соединения
args.shapeEnd object объект куда входит линия соединения
args.canvas object полотно в котором отрисовывается элемент
args.directionB string параметр, говорящий откуда из начального объекта выводить flow. Допустимые значения: left, right, top. По умолчанию значение top
args.directionE string параметр, говорящий куда в конечный объект вводить flow. Допустимые значения: left, right, top. По умолчанию значение top
args.canvas object полотно в котором отрисовывается элемент
args.curve string параметр, говорящий как искривить линию соединения. Допустимые значения: right, top. По умолчанию рисуется прямая линия без изгибов
args.text string текст который добавиться на линию соединения
args.textPosition string параметр, говорящий о том около какого из изгибов добавить текст при значении curve = right. Допустимые значения: bottom, top. По умолчанию значение bottom
args.finalLine boolean параметр говорящий о том что это линия заканчивающая распараллеливание, координаты x для кривой высчитвыаются как конечный объект минус 40
Пример
        this.controls.bpmn1.createConnection({
            shapeBebin: objectBegin,
            shapeEnd: objectEnd,
            directionB: 'right',
            directionE: 'left',
            canvas: countParticipant[1],
            curve: 'right',
            textPosition: 'top',
            text: 'Да',
            finalLine: true
        })

getElements#

Синхронный метод, возвращает массив объектов всх элементов с диаграммы

getElements()
Пример
const arrayElements = this.controls.bpmn.getElements()

importXML#

Асинхронный метод, импортирующий текст формата xml в диаграмму

importXML(string)
параметр тип описание
string string текст диаграммы в формате xml
Пример
const test = `<?xml version="1.0" encoding="UTF-8"?>
          <definitions xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:camunda="http://camunda.org/schema/1.0/bpmn" xmlns:omgdc="http://www.omg.org/spec/DD/20100524/DC" xmlns:signavio="http://www.signavio.com" id="sid-0b0aaa25-3baf-4875-9d7a-0907d599a9ef" targetNamespace="http://www.omg.org/spec/BPMN/20100524/MODEL" exporter="Camunda Modeler" exporterVersion="3.5.0" xsi:schemaLocation="http://www.omg.org/spec/BPMN/20100524/MODEL BPMN20.xsd">
            <process id="invoice" name="Invoice Receipt" isExecutable="true" camunda:versionTag="V2.0" camunda:historyTimeToLive="45">
              <startEvent id="Event_0b97amf" />
            </process>
            <bpmndi:BPMNDiagram id="BPMNDiagram_73">
              <bpmndi:BPMNPlane id="BPMNPlane_73" bpmnElement="invoice">
                <bpmndi:BPMNShape id="Event_0b97amf_di" bpmnElement="Event_0b97amf">
                  <omgdc:Bounds x="202" y="102" width="36" height="36" />
                </bpmndi:BPMNShape>
              </bpmndi:BPMNPlane>
            </bpmndi:BPMNDiagram>
          </definitions>
          `
  this.controls.bpmn1.importXML(test).then((res) => {
            console.log('res', res)
        }).catch((err) => {
            console.log('err', err)
        })

exportXML#

Асинхронный метод, экспортирующий диаграмму в текст формата xml. Возвращает string переменную

exportXML()
Пример
1
2
3
4
5
  this.controls.bpmn1.exportXML().then((result) => {
            console.log('result', result)
        }).catch((err) => {
            console.log('err', err)
        })

События#

valueChanged#

Возникает при смене значения

параметр тип описание
s BPMN экземпляр класса контрола
e object
e.args object аргументы события
e.args.element object измененный элемент
e.args.gfx object SVG элемент (визуальное представление)
1
2
3
4
5
6
7
8
9
s = BPMN {
    ... // экземпляр класса BPMN
},
e = {
    args: {
        element: {...'измененный элемент'},
        gfx: {...'SVG элемент (визуальное представление)'}
    }
}
Пример
<BPMN ... valueChanged="test" />
1
2
3
4
test (s, e) {
    console.log('s', s)
    console.log('e', e)
}

Особенности контрола#

У данного контрола нет свойств value и bind, поэтому для сохранения в базу данных рекомендуется использовать следующее решение:

Добавить в constructor документа следующий код:

Пример
1
2
3
4
5
6
7
8
        constructor (args) {
            super(args)
            this.controls.bpmn1.importXML(this.data.[имя bind к которому необходимо привязать контрол]()).then((res) => {
                console.log('res2', res)
            }).catch((err) => {
                console.log('err', err)
            })
        }

Так же необходимо добавить код в сохранение

Пример
1
2
3
        <Tool id="Save" image="current-theme/images/leftNavBar/save.png"
            clicked="saveDocument" caption="Сохранить"
        />
1
2
3
4
5
6
        saveDocument () {
            this.controls.bpmn1.exportXML().then((result) => {
                this.data.[имя bind к которому необходимо привязать контрол](result.xml)
                this.save()
            })
        }

Пример реализации#

Пример
        export default class myForm extends Document {
        constructor (args) {
            super(args)
            this.controls.bpmn1.importXML(this.data.longName()).then((res) => { // Выгрузить на лист диаграмму из базы данных
                console.log('res2', res, this)
            }).catch((err) => {
                console.log('err', err)
            })
        }

        test () {
            const laneName = ['ИмяОдин', 'ИмяДва', 'ИмяТри']
            this.controls.bpmn1.cleanAll() // Очистить все с диаграммы
            this.controls.bpmn1.getRootElement().then((process) => { // Вернуть корневой элемент
                const participantShape = this.controls.bpmn1.createParticipant({ name: 'Маршрут', height: 540, width: 1100 }) // Создать диаграмму
                this.controls.bpmn1.createObjectShape({ //Добавить диаграмму на лист
                    shape: participantShape,
                    x: 700,
                    y: 300,
                    canvas: process
                })
                const countParticipant = this.controls.bpmn1.createLanes({ laneName, participantShape }) // Создать линии на диаграмме
                const start = this.controls.bpmn1.createShape({ // создание первого элемента "Запуск"
                    type: 'bpmn:StartEvent',
                    name: 'Запуск'
                })
                this.controls.bpmn1.createObjectShape({ // Добавить первый элемент на лист
                    shape: start,
                    canvas: countParticipant[0],
                    y: countParticipant[0].y + countParticipant[0].height / 2,
                    x: 100
                })
                const task = this.controls.bpmn1.createShape({ // отрисовываем действие
                    type: 'bpmn:BusinessRuleTask',
                    name: 'Действие'
                })
                this.controls.bpmn1.createObjectShape({ // Добавить действие на лист
                    shape: task,
                    canvas: countParticipant[1],
                    y: countParticipant[1].y + countParticipant[1].height / 2,
                    x: 300,
                    color: 'Green',
                    textTimer: 'Завершен',
                    leftDocument: () => { console.log('left') },
                    rightDocument: () => { console.log('right') }
                })
                this.controls.bpmn1.createConnection({ // отрисовываем линию соединения от запуска к действию
                    shapeBebin: start,
                    directionB: 'right',
                    shapeEnd: task,
                    directionE: 'left',
                    canvas: countParticipant[1],
                    curve: 'right'
                })
                const end = this.controls.bpmn1.createShape({ // создание последнего элемента "Конец"
                    type: 'bpmn:EndEvent',
                    name: 'Конец'
                })
                this.controls.bpmn1.createObjectShape({ // Добавить конец на лист
                    shape: end,
                    canvas: countParticipant[2],
                    y: countParticipant[2].y + countParticipant[2].height / 2,
                    x: 500
                })
                this.controls.bpmn1.createConnection({ // отрисовываем линию соединения от конца к действию
                    shapeBebin: end,
                    directionB: 'top',
                    shapeEnd: task,
                    directionE: 'top',
                    canvas: countParticipant[2],
                    curve: 'top'
                })
                this.controls.bpmn1.moveObject({ object: participantShape, x: 100, y: 200 }) // сменить расположение диаграммы
            })
        }

        saveDocument () {
            this.controls.bpmn1.exportXML().then((result) => { // Сохранить диаграмму в базу данных
                this.data.longName(result)
                this.save()
            })
        }
    }