Вкладка «Аналитик» — дизайн-спека

шаг 4, продуктовый дизайн · макет: index.html

Что это и на чём основано

Спека описывает вкладку «Аналитик» конструктора отчётов РРЭ: состояния диалога, компоненты, поведение уточняющих вопросов и критерии приёмки для фронтенда.

Исходники сервиса недоступны (GITHUB_TOKEN в окружении шага отсутствует, репозиторий не клонирован — шаги 1–3 прогона по той же причине не выполнены). Поэтому спека и макет сняты с работающего сервиса sol-mspg313y-6zr.apps.sreda-ai.ru, проверено 12.08.2026:

Важно для приёмки: вкладка «Аналитик» на этом сервисе уже реализована и отвечает. Макет шага 4 — не первая её версия, а эталон вёрстки и поведения с исправлением найденных дефектов (раздел 6).

1. Экран и структура

Вкладка — четвёртая в существующей навигации (Данные · Конструктор · Отчёт ПУНЦ · Аналитик), сетка и палитра конструктора не меняются. Сверху вниз:

БлокСодержимоеСтатус
Панель «Диалог с аналитиком»заголовок + пилюля статуса, поясняющий абзац, строка понимания, область чата, поле ввода + «Отправить» / «Начать заново», подпись о движке разбораесть
Строка понимания запросачипы: Источник · Показатель · Разрез · Период · Единицы · Сравнение; заполненный — синий, спрашиваемый сейчас — жёлтый, пустой — серыйновое
Панель «Что будет посчитано»карточка подтверждения: человекочитаемое summary, свёрнутый JSON, кнопки «Считать» / «Поправить»есть
Панель «Результат»счётчик строк, кнопки Excel · CSV · PDF · «Открыть в конструкторе», таблица (дельта-колонки при сравнении), легенда дельты, предупреждения витриныесть
Панель «Контекст аналитика»7 источников, правила витрины, связи, открытые вопросы энергетику из ПРИЁМКА.md, словарь целикоместь

2. Состояния диалога

СостояниеЧто видит пользовательПризнак в ответе API
Пустоезаголовок «Спросите словами, что посчитать», пояснение про 7 источников и три чипа-примера, по клику отправляющие запрос
Уточнениепилюля «уточняет» (жёлтая), пузырь аналитика с вопросом, ряд быстрых ответов с подписью «Быстрый ответ», жёлтый чип спрашиваемого слотаstatus:"ask", question.options
Подтверждениепилюля «ждёт подтверждения» (синяя), карточка конфигурации с синей левой границей, кнопки «Считать» / «Поправить»status:"confirm", config, summary[]
Результатпилюля «посчитано» (зелёная), таблица, выгрузки, предупреждения, подсказки «Что дальше» status:"result", result
Оговоркацентрированный жёлтый пузырь «Важно» — например «Не понял, что с чем сравнивать — считаю без сравнения»notes[]
Ошибкакрасный пузырь «Ошибка» с текстом сервера; ввод остаётся доступен, состояние диалога не теряется HTTP 4xx/5xx или error
Ожиданиекурсивная строка «Аналитик думает…», поле ввода и кнопка заблокированызапрос в полёте

3. Уточняющие вопросы: слоты и порядок

Агент не додумывает недостающее. Порядок опроса — от того, без чего конфигурацию нельзя собрать, к деталям:

СлотКогда спрашиваетсяОпции быстрых ответов (реальные)
intentне назван ни показатель, ни разрезпримеры запросов
compare_fieldсказано «сравни», но разрез сравнения не определён вид начисления · уровень напряжения · ценовая категория · диапазон мощности · контрагент · договор · регион · подразделение
compare_value, compare_value2разрез сравнения есть, стороны не названы значения разреза из данных: ВН · НН · СН1 · СН2 · ФСК220
periodпериод не указан2024-08 (единственный период в data.db)
unitпоказатель «Объём»: в данных кВт·ч и кВт вперемешку, складывать нельзя кВт·ч · МВт·ч · кВт · разбить по единице измерения

Правила поведения

4. Компоненты и токены

Все переменные — из существующего конструктора, новых цветов не вводится: --accent:#2b6cb0, --line:#e2e5ea, --muted:#6b7684, --warnbg:#fff6e0, рост #1b6b45, снижение #a3261e.

КомпонентСпецификация
Пузырь .bubbleрадиус 12px (угол со стороны автора — 3px), max-width 78% (на мобильном 92%), надпись автора 11px uppercase; свой — заливка акцентом, аналитик — белый с рамкой, «Важно» — жёлтый по центру, «Ошибка» — красный слева
Лента .chatфиксированная высота 46vh (мобильный — 56vh), автоскролл вниз, aria-live="polite"; фиксированная высота вместо max-height — чтобы блок не «прыгал» при первом ответе
Быстрый ответ .quick buttonпилюля 14px, рамка #d3e0f0, текст акцентом, ховер #eef3fa, подпись ряда 11px серым
Чип слота .slot12px, три состояния: заполнен (синий), спрашивается (жёлтый), пуст (серый)
Карточка подтверждениярамка акцентом, левая граница 4px, фон #f7fbff, summary списком, JSON — в <details>
Дельта-ячейкаправое выравнивание, tabular-nums, ▲ рост зелёным / ▼ снижение красным, пусто — «—»; заголовок дельта-колонки на тон темнее (#e9eef5)
Пилюля статусаask — жёлтая «уточняет», confirm — синяя «ждёт подтверждения», result — зелёная «посчитано»

5. Контракт с бэкендом (снят с работающего сервиса)

POST /api/agent/chat
{ "message": "покажи начисления по регионам", "state": null }

200 →
{ "status": "ask",                        // ask | confirm | result
  "reply":  "За какой период считать? В данных есть: 2024-08.",
  "question": { "slot": "period", "text": "…", "options": ["2024-08"] },
  "notes":  [],                           // оговорки → пузыри «Важно»
  "config": {…}, "summary": ["Источник: Начисления (00102)", …],
  "result": { "row_count": 5, "columns": [{key,title,role,type,unit}], "rows": [...], "warnings": [] },
  "state":  {…} }                         // вернуть без изменений в следующем запросе

GET  /api/agent/context            → dictionary, sources[7], relations, rules, open_questions
POST /api/agent/export?fmt=xlsx|csv|pdf  → файл по состоянию диалога

Дельта-колонки приходят ключами *__delta и *__delta_pct — фронтенд опознаёт их по суффиксу и раскрашивает; легенда показывается только при их наличии.

6. Дефекты, найденные на работающем сервисе

Все воспроизведены 12.08.2026 через POST /api/agent/chat; реплики приведены дословно.

ДефектВоспроизведениеРешение в макете
UX-1. Ответ на собственный вопрос не принимается. Агент спросил, какое значение взять за базу сравнения, и перечислил «ВН, НН, СН1, СН2, ФСК220»; ответ «ВН» отвергается. «сравни объём по видам начисления» → «уровень напряжения» → «ВН» → «Не понял ответ. Сравниваю по разрезу "Уровень напряжения". Какое значение взять за базу сравнения (первое)?» Значение из question.options обязано приниматься — оно же подставляется кнопкой быстрого ответа. В макете такой ответ принимается и заполняет слот.
UX-2. Две стороны сравнения одной репликой не понимаются. «ВН и СН2» на вопрос о базе сравнения → «Не понял ответ». Разбор вытаскивает оба значения разреза из реплики: первое — база, второе — сторона сравнения.
UX-3. Разрез, названный в исходном запросе, спрашивается заново. «сравни объём по уровням напряжения» → агент всё равно спрашивает «Что с чем сравнить?». Разрез из запроса заполняет compare_field, спрашиваются только стороны.
UX-4. «Не понял ответ» без выхода. Повтор того же вопроса, вариантов действий не предложено. «2024-08» в ответ на вопрос о сравнении → дословный повтор вопроса. Вопрос сопровождается кнопками вариантов; ответ невпопад не стирает уже собранные слоты — они видны в строке понимания.
UX-5. Пустой чат ничего не предлагает. Только текст «Диалог пуст. Спросите словами, что посчитать» — энергетик не знает, какие формулировки понимаются. .chat:empty::after в текущей вёрстке. Пустое состояние с тремя кликабельными примерами запросов.
UX-6. Двойное отрицание в дельте. При снижении выводится «▼ -99,96»: стрелка уже несёт знак. текущая логика раскраски дельта-ячеек. В ячейку идёт модуль со стрелкой: «▼ −99,96 %»; заголовок процентной колонки — «Дельта, %».
UX-7. Вёрстка ломается на телефоне. min-width:420px у поля ввода даёт горизонтальный скролл на экранах уже ~460px. панель диалога в текущей разметке. Медиазапрос ≤720px: поле на всю ширину, кнопки в строку, пузыри до 92%, лента 56vh.
UX-8. Состояние разбора невидимо. Пользователь узнаёт, что понял агент, только на карточке подтверждения. Строка понимания над лентой, обновляется после каждой реплики.

7. Критерии приёмки для фронтенда

8. Что в макете не покрыто