doc/IT/programming/visual_programming_js/a_bpmn_2.md
2026-03-27 13:17:58 +03:00

22 KiB
Raw Blame History

Рассмотри варианты open-source конструкторов no-code/low-code для JavaScript, основанные на BPMN (Business Process Model and Notation), но а) поддерживающие браузерный JS б) с возможностью развертывания среды на github pages Покажи примеры разработки для них простого калькулятора: два поля ввода чисел, поле - справочник выбора четырех операций (+,-,/,*) и поле результата.

Для примера калькулятора приведу код на чистом HTML/CSS/JS, который можно разместить на GitHub Pages. Поскольку в результатах поиска нет готового примера именно калькулятора на bpmn-js, создам его самостоятельно, объяснив архитектуру: отображение BPMN-диаграммы и взаимодействие с пользовательскими элементами управления через прослушивание событий.

Структура ответа будет такой: ограничение существующих решений → bpmn-js как основная библиотека → архитектура no-code калькулятора на BPMN → полный код примера → инструкция по развертыванию на GitHub Pages.

Open-source BPMN-конструкторы для браузерного JavaScript с развертыванием на GitHub Pages

После анализа доступных open-source решений на основе BPMN, отвечающих вашим критериям (браузерный JavaScript + развертывание на GitHub Pages), я пришел к следующему выводу:

Готовых полноценных no-code/low-code платформ на BPMN с возможностью развертывания на GitHub Pages практически не существует. Большинство BPMN-инструментов (такие как Camunda, CIB seven, Operaton, IBM PAM) написаны на Java и требуют серверной инфраструктуры .

Однако есть одно архитектурное решение, которое полностью соответствует вашим требованиям:


bpmn-js — библиотека для браузерного рендеринга BPMN 2.0

Сайт: bpmn.io
GitHub: github.com/bpmn-io/bpmn-js
Лицензия: bpmn.io license (open-source)
NPM: npm install bpmn-js

bpmn-js — это JavaScript-библиотека для рендеринга и редактирования BPMN 2.0 диаграмм непосредственно в браузере . Она работает полностью на клиентской стороне, не требует серверной части и может быть развернута на GitHub Pages.

Почему bpmn-js подходит:

  1. Чистый браузерный JavaScript — работает в любом современном браузере
  2. Open-source — код доступен и расширяем
  3. Развертывание на GitHub Pages — статические файлы можно хостить бесплатно
  4. BPMN 2.0 совместимость — поддерживает стандарт BPMN 2.0
  5. Расширяемость — можно добавлять кастомную логику через JavaScript

Важное уточнение

bpmn-js — это библиотека для визуализации, а не готовая no-code платформа. Вы получаете:

  • Визуальный редактор BPMN-диаграмм
  • Возможность загружать/сохранять BPMN XML
  • Инструменты для создания кастомных no-code интерфейсов поверх BPMN

Но вам потребуется написать немного JavaScript, чтобы связать BPMN-процесс с логикой калькулятора.


📁 Пример: Калькулятор на основе BPMN-диаграммы

Ниже представлен полный пример веб-приложения, которое:

  1. Отображает BPMN-диаграмму процесса калькулятора
  2. Позволяет вводить числа и выбирать операцию
  3. Вычисляет результат на основе BPMN-модели

Структура проекта

bpmn-calculator/
├── index.html          # Главная страница
├── calculator.bpmn     # BPMN 2.0 диаграмма процесса
└── (bpmn-js via CDN)

1. BPMN-диаграмма (calculator.bpmn)

Создайте файл с определением BPMN-процесса:

<?xml version="1.0" encoding="UTF-8"?>
<definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL"
             xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI"
             targetNamespace="http://bpmn.io/schema/bpmn">
  <process id="CalculatorProcess" isExecutable="false">
    <startEvent id="StartEvent" name="Start" />
    
    <serviceTask id="CalculateTask" name="Выполнить вычисление" />
    
    <endEvent id="EndEvent" name="End" />
    
    <sequenceFlow id="flow1" sourceRef="StartEvent" targetRef="CalculateTask" />
    <sequenceFlow id="flow2" sourceRef="CalculateTask" targetRef="EndEvent" />
  </process>
  
  <bpmndi:BPMNDiagram id="BPMNDiagram_1">
    <bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="CalculatorProcess">
      <bpmndi:BPMNShape id="StartEvent_di" bpmnElement="StartEvent">
        <dc:Bounds x="100" y="150" width="36" height="36" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="CalculateTask_di" bpmnElement="CalculateTask">
        <dc:Bounds x="200" y="130" width="100" height="80" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="EndEvent_di" bpmnElement="EndEvent">
        <dc:Bounds x="350" y="150" width="36" height="36" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNEdge id="flow1_di" bpmnElement="flow1">
        <di:waypoint x="136" y="168" />
        <di:waypoint x="200" y="170" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="flow2_di" bpmnElement="flow2">
        <di:waypoint x="300" y="170" />
        <di:waypoint x="350" y="168" />
      </bpmndi:BPMNEdge>
    </bpmndi:BPMNPlane>
  </bpmndi:BPMNDiagram>
</definitions>

2. HTML-страница с калькулятором (index.html)

<!DOCTYPE html>
<html lang="ru">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>BPMN Калькулятор | No-Code на основе BPMN</title>
    
    <!-- Подключение bpmn-js -->
    <link rel="stylesheet" href="https://unpkg.com/bpmn-js@latest/dist/assets/diagram-js.css" />
    <link rel="stylesheet" href="https://unpkg.com/bpmn-js@latest/dist/assets/bpmn-font/css/bpmn.css" />
    
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }
        
        body {
            font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            min-height: 100vh;
            padding: 20px;
        }
        
        .container {
            max-width: 1200px;
            margin: 0 auto;
            display: grid;
            grid-template-columns: 1fr 400px;
            gap: 20px;
            background: white;
            border-radius: 20px;
            overflow: hidden;
            box-shadow: 0 20px 60px rgba(0,0,0,0.3);
        }
        
        /* Панель BPMN-диаграммы */
        .bpmn-panel {
            background: #f8f9fa;
            padding: 20px;
            min-height: 500px;
        }
        
        #canvas {
            width: 100%;
            height: 500px;
            background: white;
            border-radius: 12px;
            box-shadow: 0 2px 8px rgba(0,0,0,0.1);
        }
        
        /* Панель управления калькулятором */
        .calculator-panel {
            background: white;
            padding: 30px;
            border-left: 1px solid #e9ecef;
        }
        
        .calculator-panel h2 {
            margin-bottom: 20px;
            color: #2d3748;
            font-size: 1.5rem;
        }
        
        .form-group {
            margin-bottom: 20px;
        }
        
        label {
            display: block;
            margin-bottom: 8px;
            font-weight: 600;
            color: #4a5568;
        }
        
        input, select {
            width: 100%;
            padding: 12px;
            border: 2px solid #e2e8f0;
            border-radius: 8px;
            font-size: 16px;
            transition: all 0.3s;
        }
        
        input:focus, select:focus {
            outline: none;
            border-color: #667eea;
            box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.1);
        }
        
        .result {
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            padding: 20px;
            border-radius: 12px;
            text-align: center;
            margin-top: 20px;
        }
        
        .result-label {
            font-size: 14px;
            color: rgba(255,255,255,0.9);
            margin-bottom: 10px;
        }
        
        .result-value {
            font-size: 36px;
            font-weight: bold;
            color: white;
        }
        
        .info {
            margin-top: 20px;
            padding: 15px;
            background: #f7fafc;
            border-radius: 8px;
            font-size: 12px;
            color: #718096;
        }
        
        .bpmn-info {
            margin-top: 15px;
            padding: 10px;
            background: #e9ecef;
            border-radius: 8px;
            font-size: 12px;
            text-align: center;
            color: #495057;
        }
        
        @media (max-width: 768px) {
            .container {
                grid-template-columns: 1fr;
            }
            .calculator-panel {
                border-left: none;
                border-top: 1px solid #e9ecef;
            }
        }
    </style>
</head>
<body>
    <div class="container">
        <!-- Левая панель: BPMN-диаграмма -->
        <div class="bpmn-panel">
            <h3 style="margin-bottom: 15px;">📊 BPMN 2.0 Модель процесса</h3>
            <div id="canvas"></div>
            <div class="bpmn-info">
                ⚙️ BPMN-процесс: Start → Выполнить вычисление → End<br>
                🔄 При изменении входных данных процесс "выполняется" автоматически
            </div>
        </div>
        
        <!-- Правая панель: Интерфейс калькулятора -->
        <div class="calculator-panel">
            <h2>🧮 BPMN Калькулятор</h2>
            
            <div class="form-group">
                <label>Число A:</label>
                <input type="number" id="num1" value="10" step="any">
            </div>
            
            <div class="form-group">
                <label>Число B:</label>
                <input type="number" id="num2" value="5" step="any">
            </div>
            
            <div class="form-group">
                <label>Операция:</label>
                <select id="operation">
                    <option value="+"> Сложение (+)</option>
                    <option value="-"> Вычитание (-)</option>
                    <option value="*">✖️ Умножение (*)</option>
                    <option value="/">➗ Деление (/)</option>
                </select>
            </div>
            
            <div class="result">
                <div class="result-label">Результат вычисления:</div>
                <div class="result-value" id="result"></div>
            </div>
            
            <div class="info">
                <strong>💡 Как это работает:</strong><br>
                1. BPMN-диаграмма визуализирует процесс вычисления<br>
                2. JavaScript реализует бизнес-логику калькулятора<br>
                3. Любое изменение входных данных автоматически обновляет результат<br>
                4. BPMN-модель служит документацией процесса
            </div>
        </div>
    </div>

    <!-- Подключение bpmn-js и логика -->
    <script src="https://unpkg.com/bpmn-js@latest/dist/bpmn-modeler.development.js"></script>
    <script>
        // ========== Логика калькулятора (BPMN-совместимая) ==========
        function calculate(num1, num2, operation) {
            // Проверка на корректность ввода
            if (isNaN(num1) || isNaN(num2)) {
                return "Ошибка: введите числа";
            }
            
            // Выполнение операции
            switch(operation) {
                case '+':
                    return num1 + num2;
                case '-':
                    return num1 - num2;
                case '*':
                    return num1 * num2;
                case '/':
                    if (num2 === 0) {
                        return "Ошибка: деление на ноль";
                    }
                    return num1 / num2;
                default:
                    return "Ошибка: неизвестная операция";
            }
        }
        
        // Функция обновления результата
        function updateResult() {
            const num1 = parseFloat(document.getElementById('num1').value);
            const num2 = parseFloat(document.getElementById('num2').value);
            const operation = document.getElementById('operation').value;
            
            const result = calculate(num1, num2, operation);
            document.getElementById('result').textContent = 
                typeof result === 'number' ? result.toFixed(4) : result;
            
            // Визуальная анимация для BPMN-диаграммы
            highlightBPMNTask();
        }
        
        // Функция анимации BPMN-задачи (демонстрация выполнения процесса)
        function highlightBPMNTask() {
            const taskElement = document.querySelector('[data-element-id="CalculateTask"]');
            if (taskElement) {
                taskElement.style.transition = 'filter 0.3s';
                taskElement.style.filter = 'drop-shadow(0 0 8px #667eea)';
                setTimeout(() => {
                    taskElement.style.filter = '';
                }, 300);
            }
        }
        
        // ========== Инициализация BPMN-диаграммы ==========
        const canvas = document.getElementById('canvas');
        const bpmnXML = `<?xml version="1.0" encoding="UTF-8"?>
<definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL"
             xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI"
             xmlns:dc="http://www.omg.org/spec/DD/20100524/DC"
             xmlns:di="http://www.omg.org/spec/DD/20100524/DI"
             targetNamespace="http://bpmn.io/schema/bpmn">
  <process id="CalculatorProcess" isExecutable="false">
    <startEvent id="StartEvent" name="Начало" />
    <serviceTask id="CalculateTask" name="Вычислить: A + B = ?" />
    <endEvent id="EndEvent" name="Конец" />
    <sequenceFlow id="flow1" sourceRef="StartEvent" targetRef="CalculateTask" />
    <sequenceFlow id="flow2" sourceRef="CalculateTask" targetRef="EndEvent" />
  </process>
  <bpmndi:BPMNDiagram id="BPMNDiagram_1">
    <bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="CalculatorProcess">
      <bpmndi:BPMNShape id="StartEvent_di" bpmnElement="StartEvent">
        <dc:Bounds x="80" y="150" width="36" height="36" />
        <bpmndi:BPMNLabel>
          <dc:Bounds x="86" y="193" width="24" height="14" />
        </bpmndi:BPMNLabel>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="CalculateTask_di" bpmnElement="CalculateTask">
        <dc:Bounds x="180" y="130" width="120" height="80" />
        <bpmndi:BPMNLabel />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="EndEvent_di" bpmnElement="EndEvent">
        <dc:Bounds x="350" y="150" width="36" height="36" />
        <bpmndi:BPMNLabel>
          <dc:Bounds x="357" y="193" width="22" height="14" />
        </bpmndi:BPMNLabel>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNEdge id="flow1_di" bpmnElement="flow1">
        <di:waypoint x="116" y="168" />
        <di:waypoint x="180" y="170" />
        <bpmndi:BPMNLabel />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="flow2_di" bpmnElement="flow2">
        <di:waypoint x="300" y="170" />
        <di:waypoint x="350" y="168" />
        <bpmndi:BPMNLabel />
      </bpmndi:BPMNEdge>
    </bpmndi:BPMNPlane>
  </bpmndi:BPMNDiagram>
</definitions>`;
        
        // Создание экземпляра BpmnJS для просмотра
        const viewer = new BpmnJS({
            container: '#canvas'
        });
        
        // Загрузка BPMN-диаграммы
        viewer.importXML(bpmnXML, function(err) {
            if (err) {
                console.error('Ошибка загрузки BPMN:', err);
                canvas.innerHTML = '<div style="color:red; padding:20px;">❌ Ошибка загрузки BPMN-диаграммы</div>';
            } else {
                console.log('✅ BPMN-диаграмма успешно загружена');
                
                // Получаем доступ к элементам для анимации
                setTimeout(() => {
                    const overlays = viewer.get('overlays');
                    const elementRegistry = viewer.get('elementRegistry');
                    const taskElement = elementRegistry.get('CalculateTask');
                    
                    if (taskElement) {
                        // Добавляем атрибут для CSS-стилизации
                        const gfx = elementRegistry.getGraphics(taskElement);
                        if (gfx) {
                            gfx.setAttribute('data-element-id', 'CalculateTask');
                        }
                    }
                }, 100);
            }
        });
        
        // ========== Подписка на события ввода ==========
        document.getElementById('num1').addEventListener('input', updateResult);
        document.getElementById('num2').addEventListener('input', updateResult);
        document.getElementById('operation').addEventListener('change', updateResult);
        
        // Инициализация результата
        updateResult();
        
        // Добавляем обработчик для демонстрации выполнения BPMN-процесса
        setInterval(() => {
            const taskElement = document.querySelector('[data-element-id="CalculateTask"]');
            if (taskElement) {
                taskElement.style.filter = 'drop-shadow(0 0 4px #ddd)';
            }
        }, 2000);
    </script>
</body>
</html>

🚀 Развертывание на GitHub Pages

  1. Создайте репозиторий на GitHub

  2. Добавьте файлы:

    • index.html (с кодом выше)
    • (опционально) calculator.bpmn — BPMN-файл
  3. Включите GitHub Pages:

    • Перейдите в Settings → Pages
    • Выберите ветку main как источник
    • Сохраните
  4. Готово! Ваше приложение будет доступно по адресу:

    https://[username].github.io/[repository-name]/
    

🔍 Альтернативные варианты

Если вам нужна именно готовая no-code платформа на BPMN с возможностью развертывания в браузере, стоит рассмотреть:

Решение Тип Подходит для GitHub Pages?
bpmn-js + самодельный UI Библиотека Да
bpmn.io Modeler Демо-редактор Нет (серверная часть)
Camunda Modeler (desktop) Десктоп-приложение Нет

bpmn-js остается единственным open-source решением, работающим полностью в браузере без бэкенда .


📚 Полезные ссылки


Заключение

Используя bpmn-js, вы можете создавать no-code/low-code приложения на основе BPMN, которые:

  • Работают полностью в браузере
  • Могут быть развернуты на GitHub Pages бесплатно
  • Позволяют визуализировать бизнес-процессы
  • Дают возможность расширять функциональность через JavaScript

Представленный калькулятор демонстрирует, как BPMN-диаграмма может служить визуальной документацией процесса вычисления, а JavaScript реализует бизнес-логику. Такой подход сочетает наглядность BPMN с гибкостью JavaScript, создавая мощный инструмент для low-code разработки .