mirror of
https://gitverse.ru/kpa39l/vesti.git
synced 2026-09-29 18:05:03 +00:00
fc6d725bd1
- БД: posts.comment TEXT, posts.rewritten_text TEXT (ALTER TABLE, миграция применена)
- GET /candidates: двухпанельный рендер — слева список с группировкой
(source/date/status, свертываемые <details>) + чекбоксы bulk,
справа детали поста (действия, комментарий, пересказ, оригинал с медиа)
- Роуты: POST /candidates/select, /candidates/bulk (approve/reject/reject-old),
/posts/{id}/comment, /posts/{id}/reclassify (qwen), /posts/{id}/rewrite (qwen)
- approve вынесен в impl_approve (переиспользуется bulk-approve: publisher + бандл)
- без JS (только формы); HTML: Jinja2 + Bootstrap 5.3
- Протестировано TestClient: группировка, bulk-reject, comment, reclassify
(реальный qwen), rewrite (реальный qwen), поиск, media, published — зелёные
- openspec: change candidates-mail-ui архивирован (2026-09-13-candidates-mail-ui),
spec влита в openspec/specs/candidates-mail-ui; validate — чисто
- docs: STATUS.md, WALKTHROUGH.md обновлены
4.1 KiB
4.1 KiB
design.md — candidates-mail-ui
Текущая структура (из чтения кода)
web/app.py(FastAPI) — роуты:GET /candidates— рендерcandidates.html(список карточек).POST /posts/{id}/approve— апрув (публикация через publisher).POST /posts/{id}/reject(или аналогичный) — отклонение.- GET /media/{filename} — медиа (добавлен в web-media-preview).
- Таблица
posts: id, source_id (FK), text, direction, lang, views, reactions, media_path, status (new/published/rejected?), classified, created_at. - Таблица
classifications: post_id, direction, relevance, interest, summary, model.
Архитектура нового UI
1. Левая панель: список + группировка + bulk
- Один маршрут
GET /candidatesс query-параметрами:group_by∈ {source, date, status} (по умолчанию source)filter(статус: new/published/rejected/all)q(поиск по тексту)
- Ответ: тот же HTML (серверный рендер, Jinja2), но layout — две колонки (Bootstrap 5 grid, уже подключён).
- Список строится из постов (new/rejected), сгруппированных по выбранному
признаку. Группы — сворачиваемые (
<details>/<summary>— без JS). - Каждый пост имеет чекбокс
<input type="checkbox" name="ids" value="{{ id }}">. - Форма bulk:
POST /candidates/bulkсids[]иaction(approve/reject/reject-old).
2. Правая панель: детальный просмотр + действия
- Выбранный пост:
GET /candidates/{id}(или та же страница с?selected=<id>). - Секции:
- Кнопки действий: Опубликовать, Отклонить, Переклассифицировать, Переписать новость (LLM).
- «Мой комментарий»:
<textarea name="comment">+POST /posts/{id}/comment. - Оригинальный пост: text (markdown), media (
/media/<basename>), мета (source @channel, канал, время, views/reactions), direction badge.
3. Новые роуты/данные
posts.comment TEXT(nullable) — комментарий пользователя к посту.POST /posts/{id}/comment— сохранить комментарий.POST /candidates/bulk— bulk-одобрение/отклонение (транзакция).POST /posts/{id}/reclassify— перезапуск классификатора (classifier.classify_text на посте, обновить direction/classifications).POST /posts/{id}/rewrite— LLM-пересказ (qwen3:8b через Ollama): сгенерировать черновик текста от себя (без копипасты), сохранить вposts.rewritten_text, вернуть в текстовое поле для редактирования.
4. Минимум JS
- Без JS: чекбоксы +
formс method=post (multi-select через чекбоксы в одной форме). - Группировка/сворачивание:
<details>. - Автоподсветка выбранного: сервер рендерит
class="active"поselectedid.
Реализация (по шагам)
- Миграция БД:
ALTER TABLE posts ADD COLUMN comment TEXT. - Роуты: GET /candidates (двухпанельный), POST /candidates/bulk, POST /posts/{id}/comment, POST /posts/{id}/reclassify, POST /posts/{id}/rewrite.
- Шаблоны: candidates.html переписать (двухколоночная), добавить new/reclassify/ comment/rewrite формы.
- Bulk-логика + группировка на сервере (Python).
- Тест: ручной сценарий (создать 2-3 поста, сгруппировать, bulk-отклонить, коммент, реклассификация).