Browse Source
- Split draft editor into AccSection Метаинформация and Содержание - AI generation: topic, question count (1–30), answers per question (2–8) - Move save and back-to-list to bottom command panel; remove AI from hero - Normalize generated options to requested count; sync ai topic on import draft - Add DOC/ШАГИ/ШАГ_2026-04-27_001.md and track design proposal doc Made-with: Cursordev
3 changed files with 481 additions and 214 deletions
@ -0,0 +1,20 @@
|
||||
# Шаг 2026-04-27 — редизайн формы редактора теста (ветка `dev-redisign`) |
||||
|
||||
## Сделано |
||||
|
||||
- Создана ветка `dev-redisign` от `dev` в репозитории `TestingWebApp`. |
||||
- Страница автора `frontend/src/pages/TestDetail.jsx` приведена к структуре из `docs/ПРЕДЛОЖЕНИЕ_ДИЗАЙН_СОЗДАНИЕ_ТЕСТА.md` (адаптация под существующий React/JSX, без Ant Design): |
||||
- блок **«Метаинформация»** — название, описание, порог зачёта; |
||||
- блок **«Содержание»** — мини-панель ИИ (тема, число вопросов 1…30, число вариантов 2…8, кнопка генерации) и список вопросов с локальными кнопками ИИ; |
||||
- панель **«Команды»** — «Сохранить черновик» (основная), «К списку»; строка статуса черновика под панелью. |
||||
- Кнопка **«Сгенерировать тест (ИИ)»** убрана из шапки; генерация строит `shape` из введённых чисел, тема — из поля «Тема» с запасным вариантом на «Название»; после ответа API варианты в каждом вопросе нормализуются к выбранному числу (добор/обрезка, минимум один верный). |
||||
- Копирование темы при загрузке редактора и при применении импорта/черновика LLM (`setAiGenTopic` при `applyGeneratedDraft`). |
||||
|
||||
## Бэкенд |
||||
|
||||
- Менять не требовалось: `POST .../ai/generate-test` уже принимает `shape` с `optionsCount` (см. `backend/src/services/aiEditorService.js`). |
||||
|
||||
## Проверка |
||||
|
||||
- `npm run lint` и `npm run build` в `TestingWebApp/frontend` — без ошибок. |
||||
- Ручной прогон `docker compose` по чек-листу из предложения — остаётся на стороне исполнителя. |
||||
@ -0,0 +1,140 @@
|
||||
# Предложение по редизайну страницы «Создание теста» |
||||
|
||||
**Ветка:** `dev-new-design-page-createtest` |
||||
**Затронутые файлы:** `frontend/src/components/TestForm/index.tsx`, `frontend/src/pages/TestCreate/index.tsx` (через общий компонент), частично `frontend/src/api/llm.ts` (расширение сигнатуры `generate`). |
||||
**Бэкенд:** менять не обязательно — у нас уже есть `POST /api/llm/generate` (см. `backend/app/api/llm.py`); нужно лишь принять параметры `questions_count` и `answers_count`. |
||||
|
||||
--- |
||||
|
||||
## 1. Цель |
||||
|
||||
Сделать форму создания теста читаемее: разбить «полотно» на три смысловые группы и чётко отделить редактируемое содержимое от служебных команд. Заодно — дать пользователю возможность сгенерировать тест сразу нужной формы, не нащёлкивая «+ вопрос» / «+ вариант» вручную. |
||||
|
||||
## 2. Текущее состояние (что есть) |
||||
|
||||
`TestForm/index.tsx` сейчас визуально устроен так: |
||||
|
||||
``` |
||||
┌─────────────────────────────────────────┐ |
||||
│ ← Назад Заголовок │ |
||||
├─────────────────────────────────────────┤ |
||||
│ Card «Основные настройки» │ |
||||
│ • название │ |
||||
│ • описание │ |
||||
│ • порог зачёта │ |
||||
│ • таймер │ |
||||
│ • разрешить возврат │ |
||||
├─────────────────────────────────────────┤ |
||||
│ [Сгенерировать с AI] [Проверить тест] │ ← вне карточек, между мета и вопросами |
||||
├─────────────────────────────────────────┤ |
||||
│ Card «Вопрос 1» │ |
||||
│ ... │ |
||||
│ Card «Вопрос N» │ |
||||
│ [+ Добавить вопрос] │ |
||||
├─────────────────────────────────────────┤ |
||||
│ [Создать тест] [Отмена] │ |
||||
└─────────────────────────────────────────┘ |
||||
``` |
||||
|
||||
Замечания: |
||||
- AI-кнопки висят «в воздухе» — не видно, к какой части формы они относятся. |
||||
- «Сгенерировать с AI» жёстко создаёт **7 вопросов** (см. `TestForm/index.tsx:123` — `llmApi.generate(title.trim(), 7)`), без выбора структуры. |
||||
- В fallback-сообщении ошибки упоминается «API ключ в настройках» (`TestForm/index.tsx:244`). |
||||
|
||||
## 3. Что меняем |
||||
|
||||
### 3.1. Три смысловых блока |
||||
|
||||
| Блок | Содержит | Визуально | |
||||
|------|----------|-----------| |
||||
| **Метаинформация** | название, описание, порог, таймер, навигация назад | `Card title="Метаинформация"` | |
||||
| **Содержание** | кнопка «Сгенерировать с AI», список вопросов, «+ Добавить вопрос» | `Card title="Содержание"` (вложенные карточки вопросов остаются) | |
||||
| **Команды** | «Создать тест», «Отмена», «Проверить тест» | блок `Space` снизу страницы | |
||||
|
||||
Кнопка **«Проверить тест»** логически — это команда над всем тестом, поэтому переезжает в нижнюю панель команд. Кнопка **«Сгенерировать с AI»** становится первым элементом блока «Содержание» — у неё там естественное место (она формирует именно содержание). |
||||
|
||||
### 3.2. Wireframe после редизайна |
||||
|
||||
``` |
||||
┌─────────────────────────────────────────┐ |
||||
│ ← Назад Создание теста │ |
||||
├─────────────────────────────────────────┤ |
||||
│ Card «Метаинформация» │ |
||||
│ • название │ |
||||
│ • описание │ |
||||
│ • порог зачёта │ |
||||
│ • таймер │ |
||||
│ • разрешить возврат │ |
||||
├─────────────────────────────────────────┤ |
||||
│ Card «Содержание» │ |
||||
│ ┌─ AI-генерация ────────────────────┐ │ |
||||
│ │ тема: [_________________] │ │ |
||||
│ │ вопросов: [7] вариантов: [3] │ │ |
||||
│ │ [🤖 Сгенерировать] │ │ |
||||
│ └──────────────────────────────────┘ │ |
||||
│ │ |
||||
│ Card «Вопрос 1» ... │ |
||||
│ Card «Вопрос N» ... │ |
||||
│ [+ Добавить вопрос] │ |
||||
├─────────────────────────────────────────┤ |
||||
│ [Создать тест] [Проверить тест] [Отмена] │ |
||||
└─────────────────────────────────────────┘ |
||||
``` |
||||
|
||||
### 3.3. Форма AI-генерации с тремя полями |
||||
|
||||
Внутри блока «Содержание» — компактный мини-блок (не модалка) с тремя полями: |
||||
|
||||
| Поле | Тип | По умолчанию | Лимиты | |
||||
|------|-----|--------------|--------| |
||||
| Тема | `Input` | значение `title` из метаинформации (auto-fill) | непустая | |
||||
| Количество вопросов | `InputNumber` | 7 | 1…30 | |
||||
| Количество вариантов на вопрос | `InputNumber` | 3 | 2…8 | |
||||
|
||||
Кнопка **«Сгенерировать»** запускает текущий поток `handleGenerate` (модалка-превью → «Применить все вопросы»), но передаёт оба числа в API. Превью показывает то же, что и сейчас. |
||||
|
||||
Поведение существующих кнопок «Улучшить» и «Дистракторы» внутри карточки вопроса **не меняется** — они и так локальные. |
||||
|
||||
### 3.4. Уход от текста про API-ключи |
||||
|
||||
Единственное место в форме, где упоминается ключ, — fallback-сообщение об ошибке: |
||||
|
||||
```ts |
||||
// TestForm/index.tsx:244 |
||||
setReviewText('Не удалось получить рекомендации. Проверьте API ключ в настройках.') |
||||
``` |
||||
|
||||
Заменяем на нейтральное: |
||||
|
||||
```ts |
||||
setReviewText('Не удалось получить рекомендации. Попробуйте позже или обратитесь к администратору.') |
||||
``` |
||||
|
||||
Сама страница `Settings` остаётся как есть — это её прямое назначение, и её редактируют только администраторы. |
||||
|
||||
## 4. План работ (чек-лист для исполнителя) |
||||
|
||||
- [ ] **Backend** (опционально, если ещё не принимает параметры): расширить схему `LLMGenerateRequest` в `backend/app/schemas/llm.py` полями `questions_count: int = 7`, `answers_count: int = 3`; передать их в промпт сервиса `app/services/llm.py`. |
||||
- [ ] **API-клиент**: в `frontend/src/api/llm.ts` обновить сигнатуру `generate(topic, questionsCount, answersCount)`. |
||||
- [ ] **TestForm**: обернуть текущий блок «Основные настройки» в `Card title="Метаинформация"`. |
||||
- [ ] **TestForm**: создать новый `Card title="Содержание"`, в него поместить: |
||||
- мини-блок AI-генерации (3 поля + кнопка), |
||||
- текущий `Form.List` вопросов с кнопкой «+ Добавить вопрос». |
||||
- [ ] **TestForm**: убрать текущий ряд из двух AI-кнопок между мета и вопросами; «Проверить тест» перенести в нижнюю панель команд рядом с «Создать»/«Отмена». |
||||
- [ ] **TestForm**: добавить локальный стейт `aiQuestionsCount`, `aiAnswersCount`, инициализация: 7 / 3. |
||||
- [ ] **TestForm**: в `handleGenerate` передавать оба числа; при `Применить` создавать соответствующее число пустых ответов в каждом вопросе (если бэк прислал меньше — добить пустыми, если больше — обрезать). |
||||
- [ ] **TestForm**: заменить fallback-текст про API-ключ. |
||||
- [ ] Прогнать `docker compose up`, проверить вручную: создание с дефолтами, генерация на 5 вопросов × 4 ответа, проверка теста, отмена. |
||||
- [ ] Документ-шаг в `DOC/ШАГИ/ШАГ_<дата>_<NNN>.md` по факту выполнения. |
||||
|
||||
## 5. Что **не** делаем в этой ветке |
||||
|
||||
- Не трогаем форму редактирования (`TestEdit`) — формально использует тот же `TestForm`, но эффект редизайна нужно отдельно проверить с уже заполненными вопросами и опциями версионирования. |
||||
- Не меняем поведение `Form.List` валидации (минимум 7 вопросов / 3 варианта) — это отдельная история. |
||||
- Не вводим drag-and-drop переупорядочивание вопросов. |
||||
|
||||
## 6. Открытые вопросы для согласования |
||||
|
||||
1. Нужно ли визуально подсвечивать мини-блок генерации (фон, бордер), чтобы он отличался от карточек вопросов? |
||||
2. После применения сгенерированных вопросов — нужно ли скрывать мини-блок, чтобы он не путал? |
||||
3. Лимиты «1…30 вопросов / 2…8 вариантов» — устраивают или нужны другие? |
||||
Loading…
Reference in new issue