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







