Разработка мультишаговой формы обратной связи 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С-Битрикс

Мультишаговая форма обратной связи отличается от обычной пошаговой тем, что её цель — не продажа, а получение структурированного обращения. Технические запросы, жалобы, обращения в поддержку, заявки на возврат — ситуации, когда нужно последовательно собрать контекст. Тип обращения определяет, какие поля показывать дальше. Это уже условная логика, которая ближе к квиз-воронке, но ориентирована на сервисные, а не продажные сценарии.

Архитектура с условными полями

Ключевая особенность: на первом шаге пользователь выбирает тип обращения — и дальнейшие шаги меняются. Это требует условного рендеринга.

Конфигурация шагов с условиями:

const FEEDBACK_FORM_CONFIG = {
    steps: [
        {
            id: 'step_type',
            title: 'Тип обращения',
            fields: [
                {
                    name: 'type',
                    type: 'radio-cards',
                    required: true,
                    options: [
                        {value: 'technical', label: 'Технический вопрос', icon: '⚙️'},
                        {value: 'billing',   label: 'Вопрос по оплате',   icon: '💳'},
                        {value: 'complaint', label: 'Жалоба',             icon: '⚠️'},
                        {value: 'other',     label: 'Другое',             icon: '💬'},
                    ],
                },
            ],
        },
        {
            id: 'step_technical',
            showWhen: {field: 'type', value: 'technical'},
            title: 'Описание проблемы',
            fields: [
                {name: 'product', type: 'select', label: 'Продукт', required: true,
                 options: ['Мобильное приложение', 'Веб-сайт', 'API']},
                {name: 'error_text', type: 'textarea', label: 'Опишите ошибку', required: true},
                {name: 'screenshot', type: 'file', label: 'Скриншот (необязательно)', accept: 'image/*'},
            ],
        },
        {
            id: 'step_billing',
            showWhen: {field: 'type', value: 'billing'},
            title: 'Данные о платеже',
            fields: [
                {name: 'order_id',    type: 'text',   label: 'Номер заказа',   required: true},
                {name: 'amount',      type: 'number', label: 'Сумма платежа',  required: true},
                {name: 'issue_type',  type: 'select', label: 'Проблема',       required: true,
                 options: ['Двойное списание', 'Нет чека', 'Неверная сумма', 'Другое']},
            ],
        },
        {
            id: 'step_contact',
            title: 'Ваши контакты',
            fields: [
                {name: 'name',  type: 'text',  label: 'Имя',     required: true},
                {name: 'email', type: 'email', label: 'Email',   required: true},
                {name: 'phone', type: 'tel',   label: 'Телефон', required: false},
            ],
        },
    ],
};

JavaScript-контроллер с условной логикой

class ConditionalMultistepForm {
    constructor(config) {
        this.config    = config;
        this.answers   = {};
        this.stepsPath = this.calculatePath();
        this.currentIndex = 0;
    }

    // Вычислить актуальный путь шагов на основе текущих ответов
    calculatePath() {
        return this.config.steps.filter(step => {
            if (!step.showWhen) return true;
            const {field, value} = step.showWhen;
            const answer = this.answers[field];
            return Array.isArray(value) ? value.includes(answer) : answer === value;
        });
    }

    handleAnswer(fieldName, value) {
        this.answers[fieldName] = value;
        // Пересчитать путь — набор шагов мог измениться
        this.stepsPath = this.calculatePath();
    }

    get currentStep() {
        return this.stepsPath[this.currentIndex] ?? null;
    }

    get totalSteps() {
        return this.stepsPath.length;
    }

    canGoNext() {
        const step = this.currentStep;
        if (!step) return false;

        return step.fields
            .filter(f => f.required)
            .every(f => !!this.answers[f.name]);
    }

    next() {
        if (!this.canGoNext()) return false;
        if (this.currentIndex < this.stepsPath.length - 1) {
            this.currentIndex++;
            return true;
        }
        return false; // Последний шаг
    }

    prev() {
        if (this.currentIndex > 0) {
            this.currentIndex--;
        }
    }

    isLastStep() {
        return this.currentIndex === this.stepsPath.length - 1;
    }

    getSubmitData() {
        return {
            type:    this.answers.type,
            answers: this.answers,
        };
    }
}

Обработка файлов (скриншот)

Загрузка файлов в мультишаговой форме требует либо немедленной загрузки при выборе, либо отправки вместе с остальными данными.

Немедленная загрузка при выборе файла — через AJAX, возвращает ID загруженного файла в Битрикс:

// /local/ajax/upload_temp_file.php
if (!$_FILES['file'] || $_FILES['file']['error'] !== UPLOAD_ERR_OK) {
    echo json_encode(['error' => 'Ошибка загрузки']);
    exit;
}

// Проверка типа файла
$allowedMime = ['image/jpeg', 'image/png', 'image/gif', 'image/webp'];
if (!in_array($_FILES['file']['type'], $allowedMime)) {
    echo json_encode(['error' => 'Недопустимый тип файла']);
    exit;
}

// Сохранить как временный файл Битрикс
$fileId = \CFile::SaveFile([
    'name'     => $_FILES['file']['name'],
    'size'     => $_FILES['file']['size'],
    'tmp_name' => $_FILES['file']['tmp_name'],
    'type'     => $_FILES['file']['type'],
], 'feedback_forms');

echo json_encode(['file_id' => $fileId]);

При финальной отправке — передать file_id вместе с остальными данными.

Сохранение и создание обращения в CRM

Обращения направляются в зависимости от типа:

// /local/ajax/feedback_form_submit.php

$data = json_decode(file_get_contents('php://input'), true);
$type = $data['type'] ?? 'other';

\Bitrix\Main\Loader::includeModule('crm');

switch ($type) {
    case 'technical':
        // Технические обращения → сделка в воронке «Поддержка»
        $deal = new \CCrmDeal(false);
        $deal->Add([
            'TITLE'      => 'Тех. обращение: ' . ($data['answers']['product'] ?? ''),
            'CATEGORY_ID' => CRM_SUPPORT_PIPELINE_ID,
            'STAGE_ID'   => 'C' . CRM_SUPPORT_PIPELINE_ID . ':NEW',
            'COMMENTS'   => $data['answers']['error_text'] ?? '',
            'CONTACT_ID' => $this->findOrCreateContact($data),
        ]);
        break;

    case 'billing':
        // Финансовые вопросы → лид с тегом
        $lead = new \CCrmLead(false);
        $lead->Add([
            'TITLE'    => 'Биллинг: заказ #' . ($data['answers']['order_id'] ?? ''),
            'COMMENTS' => 'Проблема: ' . ($data['answers']['issue_type'] ?? ''),
        ]);
        break;

    default:
        // Прочие — лид
        $lead = new \CCrmLead(false);
        $lead->Add([
            'TITLE'   => 'Обращение: ' . $data['answers']['name'],
            'SOURCE_ID' => 'WEB',
        ]);
}

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

Уведомления

При получении обращения — уведомить ответственного. Используем почтовые события Битрикс (b_event_log):

\Bitrix\Main\Mail\Event::send([
    'EVENT_NAME' => 'FEEDBACK_NEW_TICKET',
    'LID'        => SITE_ID,
    'C_FIELDS'   => [
        'TYPE'  => $typeLabel,
        'NAME'  => $data['answers']['name'],
        'EMAIL' => $data['answers']['email'],
        'TEXT'  => json_encode($data['answers'], JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT),
    ],
    'TO_EMAIL'   => FEEDBACK_MANAGER_EMAIL,
]);

Шаблон почтового события создаётся в Настройки → Почтовые события → Почтовые шаблоны.

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

Вариант Состав Срок
Базовая мультишаговая 2–3 шага, тип обращения, лид в CRM 3–5 дней
С условной логикой Разные поля по типу, загрузка файлов 6–10 дней
Полный Service Desk + Личный кабинет, статусы обращений, SLA 15–25 дней