Все версии

Создание кампании: поля, сводка и последствия настроек

Дата: 01.11.2026. Статус: история (анализ 01.11). Форма кампании внедрена в P07-P08: серверные черновики, SaaS DSP и основная DSP, см. ../../implementation/reviews/P08.md. Актуальное решение после трех дополнительных итераций: рендер v2, обоснование и компонентная схема, PDF v2. Три итерации завершены, 51 проверка пройдена. Первый образец ниже сохранен для сравнения: рендер v1, снимок v1.

Найденные проблемы

Проверены две независимые редакции. В основной DSP (src/pages/campaigns/CampaignFormPage.vue) есть Element Plus, вкладки, CampaignSidePanel, useCampaignSummary, серверный черновик useCampaignDraft, сравнение с опубликованными значениями. Часть UI зависит от campaignReadiness и campaignDraftUI. Это не компоненты SaaS. В SaaS (src/editions/saas/pages/CampaignFormPage.vue) есть BcInput/BcSelect/BcCheckbox, но нет автосохранения, восстановления, sticky-сводки и сравнения изменений.

| Проблема | Свидетельство | Доработка | | --- | --- | --- | | Типы визуально не различаются | BcInput для названия, денег, CTR, даты; универсальная высота 48 и радиус от поиска | Общая оболочка поля и специализированные контроли | | Денежный ввод требует точку | pattern принимает точку, русская запятая не принимается | Нормализовать запятую, пробелы и неразрывные пробелы на границе ввода; в API десятичная строка | | Числа неоднозначны | Нет валюты и единицы у бюджетного поля; number без step=1 допускает нежелательные состояния | Суффиксы руб., %, показов; точность и ограничения по типу | | Настройки трудно обозреть | SaaS: одна длинная колонка | Секции, sticky summary, компактная сводка на мобильном | | Оценка слишком скрыта | SaaS: одна строка бюджет/CPM; основная сводка не прогнозирует результаты | Постоянная панель расчетов с формулой и допущениями | | Черновик различается по редакциям | SaaS сразу вызывает create/update; основная DSP сохраняет через debounce 800 мс | Единый пользовательский контракт, отдельная интеграция API каждой редакции | | Готовность не означает фактические показы | В useCampaignSummary флайт рекомендован, креативы не проверяются | Разделить заполнение формы и техническую готовность доставки | | Риски сохранения | useCampaignDraft не сериализует параллельные PUT, unmount не ожидает запрос; поиск последнего draft ограничен 500 записями | Очередь/ревизии, route guard, beforeunload при несохраненных данных, серверный поиск draft |

Компонентная схема системы

Действующий слой: src/utils/design-system/{tokens.css,fonts.css,icons/} -> адаптеры Element Plus основной DSP и src/editions/saas/ui/Bc* SaaS/admin -> компоненты предметной области -> страницы. Общий слой SSP копируется только штатными sync-скриптами. Нельзя объявлять Bc* единственным UI всей системы или напрямую смешивать две редакции.

Целевая схема: токены -> FieldShell -> типизированный контрол -> CampaignSection -> CampaignForm + CampaignSummary + CampaignOutcome + DraftStatus + ChangeReview. FieldShell владеет label, required, hint, error, aria-describedby; контрол владеет парсингом, клавиатурой и значением; предметный слой владеет правилами и расчетами.

| Тип | Сейчас | Предлагаемый компонент и контракт | | --- | --- | --- | | Строка, URL, многострочный текст | BcInput / el-input | TextField, UrlField, TextArea; trim при подтверждении, счетчик, ограничения длины | | Целое число | BcInput type=number / el-input-number | IntegerField; integer или null, min/max/step=1; пусто не равно 0 | | Деньги | BcInput + pattern | MoneyField; decimal string или null, валюта, 2 знака; без float для API | | Процент | BcInput + pattern | PercentField; 0..100, согласованная точность; отдельно процент и доля API | | Короткий выбор | BcSelect / el-select | SelectField; стабильный id, очистка, Arrow/Enter/Escape/Tab | | Растущий справочник | el-select, специализированные пикеры | EntityCombobox; поиск на сервере, страницы, отмена устаревшего ответа, loading/error/empty | | Несколько значений | специализированные пикеры | MultiSelectField; чипы, счетчик, доступное удаление, выбранное вне текущей страницы | | Список строк / доменов | отдельные редакторы | ListEditor; построчная проверка, paste, удаление дублей, ошибка с номером строки | | Иерархия размещения | InventoryWhitelistPicker | TreePicker; наследование, частичный выбор, исключения и итоговое покрытие | | Период и время | BcInput date/time, BcDateRange / el-date-picker | DateTimeRangeField; часовой пояс, конец позже начала, явное отсутствие окончания | | Режим и флаг | BcRadio/BcToggle/BcCheckbox | SegmentedField для модели оплаты, Checkbox для согласия, Toggle для немедленной настройки | | Файл | BcUpload | UploadField; формат, размер, прогресс, повтор, проверка сервером |

Для всех полей: default, hover, focus, filled, disabled, readonly, error; async-контроли также loading, empty, network-error. Высота 44 px, радиус 10 px как предложение для плотной формы; не менять глобальный радиус поиска. Label 13-14 px, значение 15 px, helper 12-13 px; Inter, существующая палитра A. Ошибка текстом и рамкой, фокус 2 px. Обязательные/необязательные поля обозначаются словами; placeholder не заменяет label.

Композиция и ожидаемое поведение

Основная колонка: 1. Название и рекламодатель. 2. Период и часовой пояс. 3. Модель оплаты, бюджет, ставка, лимит в день. 4. Аудитория и размещение. 5. Объявления, маркировка и проверка. Расширенные параметры раскрываются по запросу. Справа: сводка условий; расчет результатов; что произойдет после публикации; готовность доставки; изменения относительно опубликованного снимка. На 390 px панели идут в потоке перед финальным действием; форма не имеет горизонтальной прокрутки. Клик по проблеме переводит к полю, включая скрытую вкладку.

Расчеты: CPM -> floor(бюджет/CPM*1000) расчетных показов; дневной лимит и число дней ограничивают результат минимумом. CPC -> floor(бюджет/цена клика) расчетных кликов, CPV -> досмотров, CPA -> конверсий. Это предел по бюджету, не прогноз аукциона. CTR/VTR в форме - пороги остановки участия после 1000 показов, а не обещанные результаты. Охват, фактические клики и конверсии не выводить без исторических данных, источника, даты обновления и диапазона неопределенности. Нулевые/невалидные/пустые вводы дают «Недостаточно данных», а не Infinity, NaN или нулевой прогноз.

В рендере выбран пример: 120000 руб., CPM 240 руб., 14 дней, 30000 показов/день. Расчет по бюджету 500000; ограничение расписанием 420000; расчетные расходы 100800 руб. Остаток бюджета 19200 руб. Видно предупреждение о недоосвоении. При смене CPM на CPC единица цены и результата меняется; показы по формуле CPM не выводятся.

Черновик и публикация

Основная DSP: сущность создается status=draft, редактирование через PUT draft, восстановление GET draft, публикация отдельной операцией. Статусы UI: изменено, сохраняется, сохранено с временем, ошибка + повтор. Пока сохранение не подтверждено, не писать «Сохранено». Публикация ожидает актуальный снимок, блокирует повторное нажатие и показывает серверные ошибки у полей. Отмена восстанавливает опубликованное. Нужны защита от конфликтов вкладок и других пользователей, отсутствие отложенного PUT после publish/discard, предупреждение при уходе во время ошибки.

Рендер демонстрирует локальное восстановление и повтор после ошибки хранилища. Это не серверный черновик продукта. Серверные проверки вынесены в профильный unit-тест существующего composable; успешный сценарий на настоящем API без учетной записи не подтвержден.

План внедрения и приемка

| Шаг | Приоритет | Результат и критерий готовности | | --- | --- | --- | | C1 | P0 | FieldShell + Money/Integer/Percent; запятая, paste, null/0, границы; единый aria-контракт в обеих редакциях | | C2 | P0 | Надежный draft основной DSP: последовательность PUT, блокировка publish/discard до завершения сохранения, guard и ошибка сети; регрессии гонок | | C3 | P0 | Серверный контракт черновика SaaS и UI; возврат на ту же кампанию после reload, изоляция рекламодателей и пользователей, отсутствие запуска при сохранении | | C4 | P1 | Секции и панели summary/outcome/change-review; суммы и единицы пересчитываются, лимиты объяснены, незаполненные данные не выглядят прогнозом | | C5 | P1 | Select/Combobox/MultiSelect/List/Tree; 1000 элементов, поиск и клавиатура, ошибки строк, возврат к полю | | C6 | P1 | Проверка доставки: даты, статус, флайты, креативы, модерация, инвентарь; причины блокировки отдельно от заполненности формы | | C7 | P1 | Приемка на реальных API: создание -> ввод -> reload -> публикация -> diff -> отмена; 390/768/1440, обе темы, клавиатура, медленная сеть, два редактора |

Зависимости: C4 после C1; C3 требует API SaaS; C7 после C1-C6. Размеры и радиусы принимаются после проверки настоящих контролов. План не отмечается выполненным по прототипу.

Фактические проверки предложения