testingwebapp fixes, weeek tasks 2948-2958

This commit is contained in:
Константин Лебединский
2026-05-04 21:29:23 +05:00
parent 0229bc250b
commit 1ea83aa6b4
9 changed files with 1035 additions and 214 deletions
+91 -13
View File
@@ -7,6 +7,8 @@
data-test-id="{{ test_id }}"
data-initial='{{ content | tojson | safe }}'>
<div id="editor-gen-toast" class="editor-gen-toast" role="status" aria-live="polite" hidden></div>
<section class="cabinet-brick cabinet-brick--hero hero-brick">
<a href="{{ url_for('tests.tests_list_page') }}" class="link-back">К тестам</a>
<textarea id="test-title" maxlength="200" rows="1" placeholder="Название теста"
@@ -164,6 +166,10 @@
placeholder="Например: охрана труда на производстве"
style="resize:none; overflow:hidden; font-family:inherit;"></textarea>
</label>
<label class="mt-2 inline-flex items-start gap-2 text-sm text-ink-700 cursor-pointer select-none">
<input type="checkbox" id="ai-keep-title" class="mt-1 rounded border-ink-300 text-brand-600 focus:ring-brand-500" />
<span>Не менять название теста в редакторе после генерации (оставить текущее)</span>
</label>
<div class="mt-2">
<button id="ai-generate-test"
class="btn btn-ghost" type="button" style="min-height:43px;">
@@ -185,7 +191,18 @@
<p class="text-xs text-ink-500 leading-snug mb-3">
<span class="font-medium text-ink-600">Предложить улучшение</span> — ИИ предложит правки по каждому вопросу (было → стало); вы отметите, что применить к черновику.
</p>
<div class="flex flex-wrap gap-2">
<div class="flex flex-col sm:flex-row sm:flex-wrap sm:items-end gap-2">
<label class="flex flex-col gap-1 min-w-[12rem] flex-1">
<span class="text-xs font-medium text-ink-600">Область улучшения</span>
<select id="ai-improve-focus"
class="form-input text-sm py-2 rounded-lg border border-ink-300 bg-white">
<option value="all">Всё: вопросы и варианты</option>
<option value="questions">Только формулировки вопросов</option>
<option value="distractors">Только неверные варианты (дистракторы)</option>
<option value="options">Все варианты ответа (без смены верности)</option>
</select>
</label>
<div class="flex flex-wrap gap-2">
<button id="ai-check"
class="btn btn-ghost" type="button" style="min-height:43px;">
<span class="material-symbols-outlined text-base" style="vertical-align:-3px;">fact_check</span>
@@ -196,13 +213,14 @@
<span class="material-symbols-outlined text-base" style="vertical-align:-3px;">auto_fix_high</span>
Предложить улучшение
</button>
</div>
</div>
</div>
{# ── Документ в вопросы ──────────────────────────────────── #}
<div class="question-editor-block test-detail-subsection test-detail-subsection--import">
<h3 class="test-detail-subsection__title">Документ в вопросы</h3>
<p class="text-xs text-ink-500 leading-snug mb-2">
<p class="text-xs text-ink-500 leading-snug mb-2 text-center">
<span class="font-medium text-ink-600">Сгенерировать из документа</span> — из файла извлекается текст; ИИ составляет вопросы по содержанию и шаблону из «Параметров» (число вопросов, вариантов, несколько верных и т.д.), с учётом поля «Пожелания», если оно заполнено. Перед заменой откроется предпросмотр: «Применить» подставит черновик вместо текущих вопросов; дальше сохраните тест на сервер — подсказки и версии ведут себя так же, как при генерации по теме.
</p>
<label id="ai-import-dropzone"
@@ -210,10 +228,15 @@
px-4 py-5 rounded-xl bg-white border-2 border-dashed border-ink-300/70
hover:border-brand-400 hover:bg-brand-50/40 cursor-pointer transition-colors">
<span class="material-symbols-outlined text-2xl text-brand-400">upload_file</span>
<span id="ai-import-dropzone-label" class="text-sm font-medium text-ink-700">Перетащите файл сюда или нажмите</span>
<span class="text-xs text-ink-400">PDF, DOCX, TXT, MD · до 16 МБ</span>
<input id="ai-import-file" type="file" accept=".pdf,.docx,.txt,.md" class="hidden" />
<span id="ai-import-dropzone-label" class="text-sm font-medium text-ink-700 text-center block w-full">Перетащите файлы сюда или нажмите</span>
<span class="text-xs text-ink-400 text-center block w-full">PDF, DOCX, TXT, MD · до 5 за раз · до 16 МБ · повторный выбор добавляет к уже загруженным; полный сброс — «Сбросить загрузку».</span>
<input id="ai-import-file" type="file" accept=".pdf,.docx,.txt,.md" multiple class="hidden" />
</label>
<div class="mt-2 flex flex-wrap gap-2">
<button type="button" id="ai-import-clear" class="btn btn-ghost btn--sm text-sm" style="min-height:36px;">
Сбросить загрузку
</button>
</div>
<label class="block mt-3">
<span class="form-label">Пожелания по содержанию <span class="text-ink-400 font-normal">(необязательно)</span></span>
<textarea id="doc-user-hint" rows="1"
@@ -226,7 +249,6 @@
<span class="material-symbols-outlined text-base" style="vertical-align:-3px;">auto_awesome</span>
Сгенерировать из документа
</button>
<p id="doc-progress" class="mt-2 text-xs text-ink-500 min-h-[1rem]"></p>
</div>
{# ── Модалка результата импорта документа ─────────────────── #}
@@ -238,7 +260,6 @@
</div>
</dialog>
<p id="ai-status" class="editor-generation-panel__status text-sm text-ink-500"></p>
</section>
</div>
@@ -257,7 +278,7 @@
<h2 class="font-semibold text-ink-900">Вопросы (<span id="q-count-mirror">0</span>)</h2>
</div>
<ol id="questions" class="mt-3 space-y-4"></ol>
<div class="mt-3 flex justify-center">
<div class="mt-3 flex justify-center flex-wrap gap-2">
<button id="add-question"
class="inline-flex items-center gap-1 px-3 py-2 rounded-lg
bg-white border border-ink-300/60 hover:border-brand-300 text-sm min-h-10
@@ -265,6 +286,14 @@
<span class="material-symbols-outlined text-base">add</span>
<span>Добавить вопрос</span>
</button>
<button id="add-question-ai" type="button"
class="inline-flex items-center gap-1 px-3 py-2 rounded-lg
bg-brand-50 border border-brand-200 hover:border-brand-400 text-sm min-h-10
btn btn-ghost question-editor__add-question-ai"
title="Добавляет пустой блок и вызывает ИИ для одного нового вопроса с вариантами">
<span class="material-symbols-outlined text-base">auto_awesome</span>
<span>Новый вопрос (ИИ)</span>
</button>
</div>
</section>
@@ -396,11 +425,26 @@
<input type="checkbox"
class="opt-correct w-5 h-5 rounded border-ink-300 text-brand-600 focus:ring-brand-500" />
</label>
<textarea rows="1"
class="opt-text flex-1 min-w-0 rounded-lg border border-ink-300 px-3 py-2
focus:border-brand-500 focus:ring-2 focus:ring-brand-500/20"
placeholder="Вариант ответа"
style="resize:none; overflow:hidden; font-family:inherit; line-height:1.55;"></textarea>
<div class="opt-text-wrap relative flex-1 min-w-0 self-start">
<textarea rows="1"
class="opt-text w-full rounded-lg border border-ink-300 px-3 py-2
focus:border-brand-500 focus:ring-2 focus:ring-brand-500/20"
placeholder="Вариант ответа"
style="resize:none; overflow:hidden; font-family:inherit; line-height:1.55;"></textarea>
<div class="opt-ai-overlay hidden absolute inset-0 rounded-lg z-[5]
bg-white/85 backdrop-blur-[2px] flex flex-col items-center justify-center gap-1
border border-ink-200/80 shadow-sm">
<span class="inline-block w-6 h-6 rounded-full
border-[3px] border-brand-200 border-t-brand-600 animate-spin"></span>
<span class="text-xs text-ink-600 font-medium px-2 text-center leading-snug">Улучшаю…</span>
</div>
</div>
<button type="button" class="opt-ai shrink-0 inline-flex items-center justify-center
rounded hover:bg-brand-50 text-brand-700 px-1.5 pt-1.5"
style="min-height:2.5rem; min-width:2.25rem;"
title="Улучшить только этот вариант (ИИ)" aria-label="Улучшить вариант ИИ">
<span class="material-symbols-outlined text-base">auto_fix_high</span>
</button>
<button class="opt-delete shrink-0 w-10 inline-flex items-center justify-center
rounded hover:bg-red-50 text-red-600 pt-1.5"
style="min-height:2.5rem;"
@@ -428,6 +472,40 @@
</div>
</dialog>
{# ── Выбор режима ИИ для непустого вопроса (улучшить / дистракторы) ── #}
<dialog id="dlg-q-ai-mode" class="save-modal" style="max-width: 24rem; width: calc(100% - 2rem);">
<div class="save-modal__inner">
<h3 class="text-base font-semibold text-ink-900 mb-1">Что сделать с вопросом?</h3>
<p class="text-xs text-ink-500 mb-3">Выберите, что должен сделать ИИ.</p>
<div class="flex flex-col gap-2">
<button type="button" id="q-ai-mode-distractors"
class="px-3 py-2.5 rounded-lg border border-ink-200 text-left text-sm
hover:bg-brand-50 hover:border-brand-200 transition-colors">
<span class="font-medium text-ink-800">Добавить дистракторы</span>
<span class="block text-ink-500 text-xs mt-0.5">Заполнить пустые поля вариантов</span>
</button>
<button type="button" id="q-ai-mode-question"
class="px-3 py-2.5 rounded-lg border border-ink-200 text-left text-sm
hover:bg-brand-50 hover:border-brand-200 transition-colors">
<span class="font-medium text-ink-800">Улучшить только вопрос</span>
<span class="block text-ink-500 text-xs mt-0.5">Переформулировать текст вопроса</span>
</button>
<button type="button" id="q-ai-mode-options"
class="px-3 py-2.5 rounded-lg border border-ink-200 text-left text-sm
hover:bg-brand-50 hover:border-brand-200 transition-colors">
<span class="font-medium text-ink-800">Улучшить только варианты</span>
<span class="block text-ink-500 text-xs mt-0.5">Тексты ответов, без смены верности</span>
</button>
</div>
<div class="mt-4 flex justify-end">
<button type="button" id="q-ai-mode-cancel"
class="px-3 py-2 rounded-lg text-ink-600 hover:bg-ink-100 text-sm">
Отмена
</button>
</div>
</div>
</dialog>
{# ── Модалка результата AI-проверки/улучшения (fullscreen на мобиле) ── #}
<dialog id="ai-modal"
class="m-0 p-0 w-full h-full sm:h-auto sm:max-w-3xl sm:w-full sm:max-h-[90vh]