Files
wiki/tasks/snowbike-rag/docs/TZ-UI.md
2026-04-12 21:55:33 +03:00

194 lines
6.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# ТЗ: Веб-интерфейс для Snowbike RAG
## Общее описание
Одностраничное веб-приложение для семантического поиска по базе знаний сноубайков. Тёмная тема, адаптивный дизайн, минималистичный интерфейс.
**URL:** `https://openclaw.mva154.duckdns.org/snowbike-rag/`
**Стек:** Flask (порт 5557) + HTML/CSS/JS (без сборщиков)
**Бизнес-требования:** `docs/BRD-UI.md`
---
## Архитектура
```
Браузер
Flask server.py (порт 5557)
GET /snowbike-rag/ → index.html
GET /snowbike-rag/api/search?q=... → JSON ответ
GET /snowbike-rag/api/stats → статистика
```
**Nginx:** `location /snowbike-rag/ → proxy_pass http://172.19.0.2:5557/` (уже настроен)
---
## Файлы
```
tasks/snowbike-rag/
├── templates/
│ └── index.html — единственная страница (HTML + CSS + JS)
├── static/
│ └── style.css — кастомные стили (если нужно, иначе inline)
├── server.py — обновить: добавить роуты / и /api/search, /api/stats
└── docs/
├── BRD.md — бизнес-требования (API)
├── BRD-UI.md — бизнес-требования (UI)
└── TZ-UI.md — это документ
```
---
## Страница: index.html
### 1. Заголовок
• Иконка снежинки или снегохода (emoji: 🏔️)
• Название: **Snowbike Поиск**
• Подзаголовок: «База знаний по 155 000 сообщений»
### 2. Поле ввода
`<textarea>` по центру экрана, ширина 80% (max 700px)
• Placeholder: «Спросите про сноубайки... Например: какое масло для Polaris 850?»
• Высота: 2 строки (auto-resize до 5 строк при вводе)
• Кнопка отправки: иконка 🔍 справа внизу поля
• Отправка по Ctrl+Enter
### 3. Результаты
• Появляются ниже поля ввода
• Анимация: fadeIn 0.3s
**Блок ответа:**
• Заголовок: «Ответ»
• Текст: Markdown → HTML (через marked.js)
• Максимальная ширина: 700px, выравнивание по левому краю
**Блок источников:**
• Заголовок: «Источники (N)»
• Список карточек (max 10, с прокруткой если больше)
• Каждая карточка:
- Дата: DD.MM.YYYY
- Топик: цветная метка (badge)
- Превью: 2 строки текста
- Ссылка: «Открыть в Telegram» (если message_id доступен)
**Мета-информация:**
• Время ответа: X.X секунд
• Найдено источников: N
### 4. Состояние загрузки
• Спиннер (три пульсирующие точки) вместо кнопки
• Skeleton-анимация для блока ответа (серые полосы)
### 5. Ошибки
• API недоступен: тост-уведомление «Сервис временно недоступен»
• Пустой запрос: подсветка поля красным + текст «Введите запрос»
---
## Страница: статистика (footer)
Внизу страницы, маленькая ссылка «О базе данных»:
• Модальное окно при клике
• Показывает:
- Всего сообщений в индексе
- Количество топиков
- Статус ChromaDB (генерация / готов)
- Последнее обновление
---
## API (новые роуты в server.py)
### GET /
Возвращает `templates/index.html`
### GET /api/search?q={query}&topics={ids}&limit={N}
Аналогично текущему `/search`, но:
• Добавить CORS-заголовки
• Возвращать JSON с полями: answer, sources, count, time_ms
### GET /api/stats
Аналогично текущему `/stats`
---
## Стилизация
### Тема: тёмная
```css
--bg-primary: #0F172A; /* фон страницы */
--bg-card: #1E293B; /* карточки */
--bg-input: #334155; /* поле ввода */
--text-primary: #F1F5F9; /* основной текст */
--text-secondary: #94A3B8; /* вторичный текст */
--accent: #3B82F6; /* акцент (синий) */
--accent-hover: #2563EB; /* акцент при наведении */
--error: #EF4444; /* ошибки */
--border: #334155; /* границы */
```
### Шрифты
• Основной: Inter (Google Fonts, через CDN)
• Моноширинный (код): JetBrains Mono (CDN)
### Адаптивность
• Мобильные (< 768px): поле ввода 95% ширины, источники в столбик
• Планшеты (7681024px): поле ввода 80% ширины
• Десктоп (> 1024px): поле ввода max 700px, по центру
---
## Зависимости (CDN)
```html
<!-- Tailwind CSS -->
<script src="https://cdn.tailwindcss.com"></script>
<!-- Marked.js (Markdown → HTML) -->
<script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
<!-- Google Fonts -->
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet">
```
---
## Обновление server.py
Добавить:
```python
from flask import render_template
@app.route('/')
def index():
return render_template('index.html')
```
Переименовать `/search``/api/search` (или оставить оба для обратной совместимости)
---
## Критерии приёмки
- [ ] `https://openclaw.mva154.duckdns.org/snowbike-rag/` — открывается страница поиска
- [ ] Ввод «какое масло для Polaris» → ответ с источниками
- [ ] Тёмная тема, красивый интерфейс
- [ ] Хорошо выглядит на телефоне
- [ ] Markdown ответ рендерится в HTML
- [ ] Источники — карточки с датой и топиком
- [ ] Спиннер при загрузке
- [ ] Ошибка при недоступности API
---
## Важно
• Всё в одном HTML-файле (inline CSS + JS)
• Tailwind через CDN (без сборки)
Не ломать существующие API-роуты
• Работает в контейнере (Flask :5557)