Разработка конструктора форм на 1С-Битрикс

Наша компания занимается разработкой, поддержкой и обслуживанием решений на Битрикс и Битрикс24 любой сложности. От простых одностраничных сайтов до сложных интернет магазинов, CRM систем с интеграцией 1С и телефонии. Опыт разработчиков подтвержден сертификатами от вендора.
Предлагаемые услуги
Показано 1 из 1 услугВсе 1626 услуг
Разработка конструктора форм на 1С-Битрикс
Средняя
~1-2 недели
Часто задаваемые вопросы
Наши компетенции:
Этапы разработки
Последние работы
  • image_website-b2b-advance_0.png
    Разработка сайта компании B2B ADVANCE
    1177
  • image_bitrix-bitrix-24-1c_fixper_448_0.png
    Разработка веб-сайта для компании ФИКСПЕР
    811
  • image_bitrix-bitrix-24-1c_development_of_an_online_appointment_booking_widget_for_a_medical_center_594_0.webp
    Разработка на базе Битрикс, Битрикс24, 1С для компании Development of an Online Appointment Booking Widget for a Medical Center
    564
  • image_bitrix-bitrix-24-1c_mirsanbel_458_0.webp
    Разработка на базе 1С Предприятие для компании МИРСАНБЕЛ
    747
  • image_crm_dolbimby_434_0.webp
    Разработка сайта на CRM Битрикс24 для компании DOLBIMBY
    655
  • image_crm_technotorgcomplex_453_0.webp
    Разработка на базе Битрикс24 для компании ТЕХНОТОРГКОМПЛЕКС
    976

Разработка конструктора форм на 1С-Битрикс

Конструктор форм — инструмент, позволяющий менеджеру или маркетологу самостоятельно создавать произвольные формы без разработчика. Добавить поле, изменить порядок, задать валидацию, настроить куда отправлять данные — всё через веб-интерфейс. 1С-Битрикс имеет встроенный модуль form (Веб-формы), но у него есть серьёзные ограничения: устаревший интерфейс, отсутствие адаптивного UI, сложность интеграции с внешними системами. Кастомный конструктор решает эти ограничения.

Что хранить

Форма — это метаданные (набор полей и правила) плюс результаты (заполненные данные). Хранение через HL-блоки:

Таблица форм (b_hl_form_builder):

class FormBuilderTable extends \Bitrix\Main\ORM\Data\DataManager
{
    public static function getTableName(): string { return 'b_hl_form_builder'; }

    public static function getMap(): array
    {
        return [
            new IntegerField('ID', ['primary' => true, 'autocomplete' => true]),
            new StringField('TITLE'),
            new StringField('SLUG'),          // URL-идентификатор
            new TextField('FIELDS_JSON'),     // Описание полей
            new TextField('SETTINGS_JSON'),   // Настройки формы
            new BooleanField('IS_ACTIVE', ['values' => [false, true]]),
            new IntegerField('SUBMISSIONS_COUNT'),
            new DatetimeField('CREATED_AT'),
        ];
    }
}

FIELDS_JSON — массив полей с полной конфигурацией:

[
  {
    "id": "field_name",
    "type": "text",
    "label": "Ваше имя",
    "placeholder": "Иван Иванов",
    "required": true,
    "width": "half"
  },
  {
    "id": "field_phone",
    "type": "tel",
    "label": "Телефон",
    "required": true,
    "mask": "+7 (000) 000-00-00",
    "width": "half"
  },
  {
    "id": "field_service",
    "type": "select",
    "label": "Услуга",
    "options": ["Разработка", "Аудит", "Поддержка"],
    "required": true
  },
  {
    "id": "field_message",
    "type": "textarea",
    "label": "Сообщение",
    "rows": 4,
    "required": false
  }
]

SETTINGS_JSON — поведение формы:

{
  "submit_text": "Отправить заявку",
  "success_message": "Спасибо! Мы свяжемся с вами.",
  "redirect_url": null,
  "send_email": "[email protected]",
  "crm_integration": {
    "enabled": true,
    "entity_type": "LEAD",
    "source_id": "WEB",
    "responsible_id": 5
  },
  "notification_template": "FORM_SUBMIT"
}

Таблица результатов (b_hl_form_submissions):

class FormSubmissionTable extends \Bitrix\Main\ORM\Data\DataManager
{
    public static function getTableName(): string { return 'b_hl_form_submissions'; }

    public static function getMap(): array
    {
        return [
            new IntegerField('ID', ['primary' => true, 'autocomplete' => true]),
            new IntegerField('FORM_ID'),
            new TextField('DATA_JSON'),       // Заполненные данные
            new StringField('USER_IP'),
            new StringField('USER_AGENT'),
            new IntegerField('USER_ID'),      // NULL если анонимный
            new IntegerField('CRM_ENTITY_ID'),// ID созданного лида/сделки
            new DatetimeField('CREATED_AT'),
        ];
    }
}

Интерфейс конструктора (административная часть)

Интерфейс — drag-and-drop редактор полей. Реализуется в /local/admin/form_builder.php или как отдельная React/Vue-страница в /local/assets/form-builder/.

Упрощённая версия — без drag-and-drop, просто добавление полей через кнопку и сортировка стрелками. Это быстрее в разработке и достаточно для большинства задач.

// Простой конструктор полей без drag-and-drop
class FormBuilder {
    constructor(containerId) {
        this.container = document.getElementById(containerId);
        this.fields    = [];
        this.bindEvents();
    }

    addField(type) {
        const id    = 'field_' + Date.now();
        const field = {id, type, label: '', required: false, options: []};
        this.fields.push(field);
        this.renderFields();
        return field;
    }

    removeField(fieldId) {
        this.fields = this.fields.filter(f => f.id !== fieldId);
        this.renderFields();
    }

    moveField(fieldId, direction) {
        const idx = this.fields.findIndex(f => f.id === fieldId);
        if (direction === 'up' && idx > 0) {
            [this.fields[idx-1], this.fields[idx]] = [this.fields[idx], this.fields[idx-1]];
        } else if (direction === 'down' && idx < this.fields.length - 1) {
            [this.fields[idx], this.fields[idx+1]] = [this.fields[idx+1], this.fields[idx]];
        }
        this.renderFields();
    }

    getFieldsJson() {
        // Собрать актуальные значения из DOM
        this.fields = this.fields.map(field => {
            const row = this.container.querySelector(`[data-field-id="${field.id}"]`);
            if (!row) return field;
            return {
                ...field,
                label:    row.querySelector('.field-label').value,
                required: row.querySelector('.field-required').checked,
                placeholder: row.querySelector('.field-placeholder')?.value || '',
            };
        });
        return JSON.stringify(this.fields, null, 2);
    }
}

Рендер формы на фронтенде

Компонент-рендерер читает JSON конфигурацию и строит HTML формы:

// /local/components/local/form.builder.render/class.php
class FormBuilderRenderComponent extends \CBitrixComponent
{
    public function executeComponent(): void
    {
        $formSlug = $this->arParams['FORM_SLUG'] ?? '';
        $form     = FormBuilderTable::getList([
            'filter' => ['SLUG' => $formSlug, 'IS_ACTIVE' => true],
        ])->fetch();

        if (!$form) {
            $this->arResult['NOT_FOUND'] = true;
            $this->includeComponentTemplate();
            return;
        }

        $form['FIELDS']   = json_decode($form['FIELDS_JSON'], true) ?? [];
        $form['SETTINGS'] = json_decode($form['SETTINGS_JSON'], true) ?? [];

        $this->arResult = [
            'FORM'   => $form,
            'SESSID' => bitrix_sessid(),
        ];

        $this->includeComponentTemplate();
    }
}

В template.php — итерация по $arResult['FORM']['FIELDS'] с switch по типу поля.

Обработчик сабмита

Универсальный обработчик работает с любой формой через FORM_ID:

// /local/ajax/form_builder_submit.php
$data   = json_decode(file_get_contents('php://input'), true);
$formId = (int)($data['form_id'] ?? 0);

$form = FormBuilderTable::getByPrimary($formId)->fetch();
if (!$form || !$form['IS_ACTIVE']) {
    echo json_encode(['error' => 'Form not found']);
    exit;
}

$fields   = json_decode($form['FIELDS_JSON'], true) ?? [];
$settings = json_decode($form['SETTINGS_JSON'], true) ?? [];

// Валидация обязательных полей
$errors = [];
foreach ($fields as $field) {
    if ($field['required'] && empty($data[$field['id']])) {
        $errors[$field['id']] = 'Поле обязательно';
    }
}

if ($errors) {
    echo json_encode(['errors' => $errors]);
    exit;
}

// Собрать данные для сохранения
$submissionData = [];
foreach ($fields as $field) {
    $submissionData[$field['label']] = htmlspecialchars($data[$field['id']] ?? '');
}

// Сохранить результат
$subId = FormSubmissionTable::add([
    'FORM_ID'    => $formId,
    'DATA_JSON'  => json_encode($submissionData, JSON_UNESCAPED_UNICODE),
    'USER_IP'    => $_SERVER['REMOTE_ADDR'],
    'CREATED_AT' => new \Bitrix\Main\Type\DateTime(),
])->getId();

// CRM-интеграция
if ($settings['crm_integration']['enabled'] ?? false) {
    // Найти поля name/phone/email по типу
    $nameField  = $this->findFieldByType($fields, 'text');
    $phoneField = $this->findFieldByType($fields, 'tel');
    $emailField = $this->findFieldByType($fields, 'email');

    \Bitrix\Main\Loader::includeModule('crm');
    $lead = new \CCrmLead(false);
    $lead->Add([
        'TITLE'     => $form['TITLE'] . ': ' . ($data[$nameField['id']] ?? 'Новый лид'),
        'NAME'      => $data[$nameField['id']] ?? '',
        'PHONE'     => [['VALUE' => $data[$phoneField['id']] ?? '', 'VALUE_TYPE' => 'WORK']],
        'EMAIL'     => [['VALUE' => $data[$emailField['id']] ?? '', 'VALUE_TYPE' => 'WORK']],
        'SOURCE_ID' => 'WEB',
        'COMMENTS'  => json_encode($submissionData, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT),
    ]);
}

echo json_encode(['success' => true]);

Сроки разработки

Вариант Состав Срок
Базовый конструктор Управление полями, сохранение, рендер 8–12 дней
С CRM-интеграцией + Лиды, маппинг полей, уведомления 12–18 дней
Drag-and-drop + аналитика + Визуальный редактор, статистика форм 18–28 дней