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

81 lines
8.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Гайд: как встроить конструктор диаграмм в поле Bitrix
Короткая практическая версия — только три вопроса: куда положить билд, как собрать HTML и куда писать начальное значение. Про полноценный переиспользуемый тип свойства инфоблока (регистрация, `ConvertToDB` и т.п.) — отдельный документ, [`docs/bitrix-integration.md`](./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 с приложением, скрипт-мост между ними.
```html
<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` — зависит от того, где именно хранится значение на вашей стороне (поле БД, свойство инфоблока, опция и т.п.) — это единственное, что специфично для конкретной интеграции, дальше всё стандартно:
```php
$currentValue = /* ваш способ прочитать сохранённое значение, например: */
$arElement['PROPERTY_DIAGRAM_VALUE'] ?? '';
```
Требований к содержимому со стороны бэкенда — минимум: это либо пустая строка, либо синтаксически валидный JSON. Всю содержательную валидацию (обязательные поля узлов и т.п.) делает само React-приложение — бэкенду глубже проверять не нужно. Пример реального значения — в `docs/bitrix-integration.md`, раздел 6.
## Проверка
1. Открыть страницу — iframe показывает пустую диаграмму (для нового элемента) или ранее сохранённую.
2. Отредактировать (подвигать фигуры, поменять текст).
3. Сабмитнуть форму как обычно (не внутри iframe).
4. Перезагрузить страницу — изменения на месте.
5. Проверить напрямую в БД/хранилище — там лежит валидный JSON.