Files
Portal-Chart-Builder/docs/backend-quickstart.md
T

8.0 KiB
Raw Blame History

Гайд: как встроить конструктор диаграмм в поле Bitrix

Короткая практическая версия — только три вопроса: куда положить билд, как собрать HTML и куда писать начальное значение. Про полноценный переиспользуемый тип свойства инфоблока (регистрация, ConvertToDB и т.п.) — отдельный документ, docs/bitrix-integration.md. Если поле одно и на одной странице — этого гайда достаточно.

1. Куда положить билд конструктора

Приложение — статическая сборка (npm run build → dist/), которая раздаётся тем же nginx, что и сам портал. Ничего разворачивать отдельно не нужно.

  1. Собрать в репозитории portal-chart-builder:
    VITE_BITRIX_ORIGIN=https://ВАШ-ДОМЕН-ПОРТАЛА VITE_BASE_PATH=/local/diagram-app/ npm run build
    
    • VITE_BITRIX_ORIGIN — origin портала (без пути). Обязателен — без него приложение намеренно не запустится (защита от случайного postMessage('*')).
    • VITE_BASE_PATH — подпуть, под которым будет отдаваться приложение. Должен совпадать с тем, куда положите dist/ на шаге 2.
  2. Скопировать содержимое dist/ в local/diagram-app/ внутри каталога сайта на сервере (тот же каталог, где лежит остальной код портала — bitrix_www/аналог на проде).
  3. Готово: приложение доступно по https://ВАШ-ДОМЕН-ПОРТАЛА/local/diagram-app/index.html.

При каждом повторном деплое (обновили React-приложение, положили новый dist/ поверх старого) — добавляйте к src iframe cache-busting параметр (?v=<дата/хэш билда>). У .html-файлов на большинстве Bitrix-стендов стоит Cache-Control на 30 дней — без версии в URL браузер администратора может продолжать открывать старый index.html со старыми хэшами JS/CSS ещё месяц.

2. Как сформировать HTML

Три части: скрытое поле со значением, iframe с приложением, скрипт-мост между ними.

<input type="hidden" id="DIAGRAM-DATA" name="DIAGRAM-DATA" value="<?= htmlspecialcharsbx($currentValue) ?>">
<iframe id="diagram-frame" src="/local/diagram-app/index.html" style="width:100%;height:600px;border:1px solid #d7dae0;border-radius:6px"></iframe>

<script>
(function () {
  var APP_ORIGIN = window.location.origin; // приложение и портал на одном домене
  var input = document.getElementById('DIAGRAM-DATA');
  var frame = document.getElementById('diagram-frame');

  window.addEventListener('message', function (event) {
    if (event.origin !== APP_ORIGIN || event.source !== frame.contentWindow) return;
    if (!event.data || typeof event.data !== 'object') return;

    if (event.data.type === 'diagram:ready') {
      frame.contentWindow.postMessage({ type: 'diagram:init', payload: input.value || null }, APP_ORIGIN);
    } else if (event.data.type === 'diagram:change') {
      input.value = event.data.payload;
    }
  });
})();
</script>

Как это работает:

  • iframe грузит приложение → оно шлёт мосту { type: 'diagram:ready' }.
  • Мост в ответ шлёт { type: 'diagram:init', payload: input.value } — приложение рисует диаграмму из этого значения (или пустой холст, если payload пуст).
  • Каждая правка в редакторе прилетает мосту как { type: 'diagram:change', payload: '<JSON-строка>' } — мост тут же кладёт её в input.value.
  • Дальше это обычный <input> внутри формы: если у него есть id, name и он лежит в <form> — браузер сам отправит его значение при обычном сабмите формы. Никакого дополнительного JS для сохранения не нужно.

id/name = "DIAGRAM-DATA" захардкожены — это ок, если поле на странице ровно одно. Если полей несколько (например, полноценный переиспользуемый тип свойства, который может стоять на разных элементах) — name должен быть уникальным и совпадать с тем, что ожидает обработчик сохранения на бэкенде (в терминах Bitrix custom property type — $strHTMLControlName['VALUE'], см. docs/bitrix-integration.md, раздел 3).

Обязательно к соблюдению, не опционально:

  • event.origin проверяется у входящих сообщений (уже в сниппете выше).
  • targetOrigin у postMessage — всегда конкретный домен (APP_ORIGIN), никогда '*'.
  • Значение попадает на страницу только через value-атрибут (htmlspecialcharsbx()), не через встраивание в JS-код — так не нужно никакого JSON-специфичного экранирования, обычного htmlspecialcharsbx() достаточно.

3. Куда записывать начальное значение

value="<?= htmlspecialcharsbx($currentValue) ?>" — сюда подставляется то, что уже сохранено для этого элемента/записи (JSON-строка со схемой диаграммы) или пустая строка, если диаграммы ещё нет.

Откуда взять $currentValue — зависит от того, где именно хранится значение на вашей стороне (поле БД, свойство инфоблока, опция и т.п.) — это единственное, что специфично для конкретной интеграции, дальше всё стандартно:

$currentValue = /* ваш способ прочитать сохранённое значение, например: */
    $arElement['PROPERTY_DIAGRAM_VALUE'] ?? '';

Требований к содержимому со стороны бэкенда — минимум: это либо пустая строка, либо синтаксически валидный JSON. Всю содержательную валидацию (обязательные поля узлов и т.п.) делает само React-приложение — бэкенду глубже проверять не нужно. Пример реального значения — в docs/bitrix-integration.md, раздел 6.

Проверка

  1. Открыть страницу — iframe показывает пустую диаграмму (для нового элемента) или ранее сохранённую.
  2. Отредактировать (подвигать фигуры, поменять текст).
  3. Сабмитнуть форму как обычно (не внутри iframe).
  4. Перезагрузить страницу — изменения на месте.
  5. Проверить напрямую в БД/хранилище — там лежит валидный JSON.