docs: актуализация под текущее состояние (Bootstrap вместо htmx, RestClient, интерцепторы, контроллеры, публикация по студентам, watch-опрос, автосейв без перезагрузки)

This commit is contained in:
2026-10-13 15:59:37 +03:00
parent 4fa400ddb1
commit b1f00fd776
7 changed files with 152 additions and 45 deletions

View File

@@ -146,6 +146,7 @@ sequenceDiagram
P->>DB: INSERT/UPDATE variant_assignments (manual=false)
P-->>W: DistributeResult(assigned, total)
W-->>A: «Распределено: N из M»
Note over A,W: UI — большая модалка «Выдача вариантов» на странице группы<br/>(фрагмент по fetch). Эндпоинт отвечает редиректом — это норма;<br/>модалка обновляется на месте, тост показывается поверх неё
```
## 6. Сдача решения студентом
@@ -214,13 +215,13 @@ sequenceDiagram
P-->>W: DefenseDto
W-->>S: «Работа сохранена»
Note over P,DB: DefenseService.syncTimeouts() переводит просроченные<br/>сессии в ready с ready_reason=timeout
Note over P,DB: DefenseService.syncTimeouts() переводит просроченные<br/>сессии в ready с ready_reason=timeout; кнопка «Готов» даёт ready_reason=button.<br/>В UI: «Готов к сдаче» (button) / «Вышло время» (timeout)
A->>W: «доп. задание: начать заново» → POST /admin/defenses/{id}/reset
P->>DB: UPDATE status=waiting, code=NULL, started_at=NULL
W-->>A: сессия снова ждёт кода
```
## 8. Оценка, комментарии и публикация
## 8. Оценка, комментарии и публикация (по студенту)
```mermaid
sequenceDiagram
@@ -235,19 +236,28 @@ sequenceDiagram
W->>P: POST /api/v1/grades (GradeSetRequest)
P->>DB: UPSERT lab_grades (student_id, lab_id, score)
P->>DB: DELETE grade_comments по паре, затем INSERT новых
P->>DB: UPSERT comment_templates (use_count++ для автоподсказок)
Note over DB: comment_templates — подсказки; частота считается<br/>по актуальным grade_comments (не по use_count)
P-->>W: GradeResponse
Note over DB: Студент оценку пока НЕ видит
A->>W: «опубликовать оценки» → POST /admin/groups/{gid}/publish
W->>P: POST /api/v1/grades/publish (labId, groupId, published=true)
P->>DB: INSERT/DELETE grade_publications (group_id, lab_id)
P-->>W: 200
A->>W: чекбокс публикации в ячейке (student×lab) → POST /admin/groups/{gid}/publish-student
W->>P: POST /api/v1/grades/publication {groupId, labId, studentIds[]} — заменяет набор
P->>DB: DELETE/INSERT grade_publication_students<br/>(легаси grade_publications снимается)
W-->>A: тост «Опубликовано: N из M», счётчик «глаза» обновлён
A->>W: «глаз» в шапке ЛР (всем / скрыть у всех) → POST /admin/groups/{gid}/publish (published=true|false)
W->>P: POST /api/v1/grades/publication {studentIds = все | []}
A->>W: поиск подсказок → GET /admin/comment-templates?q=
W->>P: GET /api/v1/comment-templates?q=
P-->>W: [{text, tone, count}] — частота по текущим оценкам
A->>W: удалить подсказку с частотой 0 → POST /admin/comment-templates/delete (text)
W->>P: DELETE /api/v1/comment-templates?text= (400, если где-то используется)
S->>W: GET /student/labs/{labId}
W->>P: GET /api/v1/me/grades?groupId=... (Bearer)
P->>DB: SELECT lab_grades + grade_comments + grade_publications
P-->>W: только опубликованные оценки группы
P->>DB: SELECT lab_grades + grade_comments; фильтр isPublished(group, lab, student)
P-->>W: только опубликованные этому студенту оценки
W-->>S: оценка и комментарии списками: позитивный / негативный / нейтральный
```
@@ -314,16 +324,18 @@ sequenceDiagram
G->>ID: GroupService.detail (студенты по ФИО)
W->>G: GET /api/v1/labs
G->>AC: LabService.list (опубликованные ЛР)
W->>G: GET /api/v1/assignments/group/{gid}
G->>P: уровни и варианты всех студентов группы (bulk)
loop по каждой лабораторной
W->>G: GET /api/v1/assignments?labId
G->>P: варианты студентов
W->>G: GET /api/v1/submissions?labId
G->>P: последние сдачи
W->>G: GET /api/v1/defenses?labId
G->>P: сессии защиты
W->>G: GET /api/v1/grades/publication?groupId&labId
G->>P: состояние публикации {all, studentIds}
end
W->>G: GET /api/v1/grades + /grades/publications?groupId
G->>P: оценки
W->>G: GET /api/v1/grades
G->>P: все оценки (матрица)
W->>W: сборка матрицы «студент × лабораторная»
W-->>A: страница группы (оценки, защиты, поиск, фильтры, сортировка)
```
@@ -351,6 +363,32 @@ sequenceDiagram
AC->>DB: UPDATE chapters.position,<br/>sections.chapter_id/position,<br/>articles.section_id/position
AC-->>W: 200
W-->>UI: {"ok": true}
UI->>UI: location.reload() — страница из серверного состояния
UI->>UI: без перезагрузки — DOM уже перестроен, статус «сохранено»
Note over AC,DB: один запрос применяет и порядок, и перенос между родителями
Note over UI: раскрытые разделы и позиция скролла сохраняются (localStorage / ui-state.js)
```
## 12. Синхронизация таймеров защиты (опрос раз в 10 секунд)
```mermaid
sequenceDiagram
autonumber
actor A as Преподаватель
actor S as Студент
participant W as web
participant P as progress
loop каждые 10 c (страница группы)
A->>W: GET /admin/defense-watch?labs=...
W->>P: GET /api/v1/defenses/watch?labs=...
P-->>W: статусы, secondsLeft, readyReason
W-->>A: обновление ячеек; переход в ready → тост «ФИО — ЛР: Готов к сдаче / Вышло время»
end
loop каждые 10 c (страница лабы студента)
S->>W: GET /student/labs/{id}/defense-status
W->>P: GET /api/v1/me/defenses/{labId}/status
P-->>W: status / secondsLeft / readyReason
W-->>S: подстройка таймера; при status != started — перезагрузка страницы
end
```