Перенос дизайна в server-rendered веб-UI (web-ui)

Новая capability web-ui: презентационный перенос готового дизайна
(семантический HTML + единый jellybit.css, тёмная тема по настройке ОС)
в html/template без шага сборки.

- Встроенная (go:embed) отдача статики под /static с Cache-Control и
  cache-busting (?v=<hash> по содержимому css/js).
- Шрифты IBM Plex self-hosted (@font-face, cyrillic+latin), без CDN.
- Наколеночный менеджер зависимостей: вендор (htmx + шрифты) не хранится
  в репо (gitignore), идемпотентно добывается `task assets` по
  web/assets.manifest с проверкой sha256; task build/run зависят от assets.
- Общие партиалы: шапка, бейдж статуса (карта всех 14 состояний),
  виджет «файл источника → раскладка» (общий для review и download).
- Страницы: список с фильтром/поиском, ревью, новая страница просмотра
  загрузки (/download/{id}). deleted скрыт по умолчанию.
- Превью раскладки берётся из единой логики internal/layout
  (buildFileRows), без дублирования правил имён в шаблонах.
- Убраны meta-refresh и инлайн-стили; copyHash на vanilla с fallback
  на execCommand и честной индикацией (целевой деплой — HTTP LAN).

Вне scope (отдельный change): живые обновления прогресса и раздел
раздачи, клиентский режим ручной раскладки файл→серия (с Alpine.js).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
av
2026-06-30 19:59:19 +03:00
co-authored by Claude Opus 4.8
parent d190072647
commit 4e2593ac31
26 changed files with 1960 additions and 303 deletions
@@ -0,0 +1,46 @@
## 1. Статика и встраивание
- [x] 1.1 Создать структуру `web/static/{css,js,vendor}/`; `web/static/vendor/` в gitignore
- [x] 1.2 Шрифты IBM Plex Sans + IBM Plex Mono (cyrillic+latin, нужные начертания) — в манифест, фетч в `web/static/vendor/fonts/`
- [x] 1.3 Перенести `jellybit.css` из `tmp/design/` в `web/static/css/`, добавить `@font-face` на `../vendor/fonts/` (убрать ссылки на Google Fonts)
- [x] 1.4 Манифест `web/assets.manifest` (путь/URL/sha256) + идемпотентный `task assets` (нет файла или хеш не сошёлся → качаем, иначе с диска); `task build`/`run` зависят от `assets`
- [x] 1.5 Вынести `copyHash` в `web/static/js/app.js` (vanilla)
- [x] 1.6 Расширить `go:embed` в `web/web.go` на `static/*`
- [x] 1.7 Добавить роут `/static/*` (`http.FileServer` + `StripPrefix`) с `Cache-Control`; решить cache-busting CSS (хеш при старте)
## 2. Общие партиалы
- [x] 2.1 Партиал `web/templates/partials/header.html` (`.app-header`)
- [x] 2.2 Партиал `partials/status_badge.html` — карта `state→class/подпись` для всех 14 состояний (один источник)
- [x] 2.3 Партиал `partials/layout_widget.html` — виджет «файл источника → раскладка» (общий для review и download)
- [x] 2.4 Перенастроить `template.ParseFS` в `httpapi` на загрузку партиалов; сохранить/дополнить FuncMap
## 3. Страница списка (index)
- [x] 3.1 Перенести вёрстку `index.html` из `tmp/design/` в `web/templates/index.html` (карточки `range`, единое окно добавления, фильтр/поиск)
- [x] 3.2 Подключить `jellybit.css` и htmx; убрать `<meta http-equiv="refresh">` и инлайн-`<style>`
- [x] 3.3 Бейдж статуса через партиал; блок `.card-acts` — условия по `state` (соответствие `downloadView`)
- [x] 3.4 `deleted` скрыт по умолчанию + переключатель «показать всё»
- [x] 3.5 Проставить `name` полей форм действий под существующие хендлеры; сверить каждое действие по состоянию
## 4. Страница ревью (review)
- [x] 4.1 Перенести вёрстку `review.html` (догадка, кандидаты `range`, причины, уточнение, действия)
- [x] 4.2 Строка «нейронка» (`.nn-cand`) — обычный кандидат, не особый режим
- [x] 4.3 Превью путей через серверное поле `reviewView.Preview` (единая `internal/layout`)
- [x] 4.4 Сверить поля форм (`apply`/`refine`/`rerecognize`/`type`/`candidate`/`provider`/`nobase`/`defer`) с хендлерами
## 5. Страница просмотра (download)
- [x] 5.1 View-структура `downloadDetailView` (распознавание, файлы, раскладка, раздача, история)
- [x] 5.2 Хендлер `GET /download/{id}` + роут; 404 на отсутствующую загрузку
- [x] 5.3 Шаблон `web/templates/download.html` (переиспользует партиал виджета и бейдж)
- [x] 5.4 Таймлайн истории (`.timeline`) и действия по состоянию
## 6. Проверка и завершение
- [x] 6.1 `task lint` и `task test` зелёные
- [x] 6.2 Ручная проверка: все действия по каждому состоянию срабатывают, превью на ревью = реальная раскладка
- [x] 6.3 Проверить отсутствие внешних сетевых запросов (шрифты/стили только с `/static/`)
- [x] 6.4 `openspec validate --strict web-ui-design-port`
- [x] 6.5 Ревью кода (до archive) — пройдено; находки MEDIUM-1/2, LOW-2/3 исправлены