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

6.8 KiB
Raw Permalink Blame History

ТЗ: Веб-интерфейс для 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 недоступен: тост-уведомление «Сервис временно недоступен» • Пустой запрос: подсветка поля красным + текст «Введите запрос»


Внизу страницы, маленькая ссылка «О базе данных»: • Модальное окно при клике • Показывает:

  • Всего сообщений в индексе
  • Количество топиков
  • Статус 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


Стилизация

Тема: тёмная

--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)

<!-- 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

Добавить:

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)