Files
telegram-shop/docs/guide.md
2026-08-05 23:29:23 +00:00

436 lines
19 KiB
Markdown
Executable File
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.
# Next.js Админ-Панель — Руководство
## Обзор
Новая админ-панель на **Next.js 16** (App Router) + **TypeScript** + **shadcn/ui** + **Prisma** (SQLite) + **Recharts**.
Полная замена EJS/SmartAdmin шаблонизатора.
## Стек
| Слой | Технология |
|---|---|
| Фреймворк | Next.js 16 (App Router, Turbopack) |
| Язык | TypeScript 5 |
| Стилизация | Tailwind CSS 4 + shadcn/ui (New York) |
| БД | Prisma ORM + SQLite |
| Графики | Recharts |
| Состояние | Zustand |
| ИИ/LLM | z-ai-web-dev-sdk (chat, vision) |
| Тема | next-themes (dark/light) |
| Уведомления | Sonner (toast) |
| Иконки | Lucide React |
## Авторизация
- Пароль: значение `ADMIN_SECRET` из `.env` (по умолчанию `changeme`)
- Если задан `SUPER_ADMIN_SECRET` (и ≠ `ADMIN_SECRET`) — вход с ним даёт роль `super_admin`
- Если не задан — все админы = `super_admin`
- Кука `admin_token` (httpOnly, sameSite=lax, 24ч, secure в production)
- Rate-limit: 5 попыток / 15 мин с IP
- HMAC-SHA256 подпись токена
## Экраны (15)
### Основные
1. **Dashboard** — 4 KPI-карточки, 8 графиков (recharts), лента активности, авто-обновление
2. **Catalog** — дерево локаций → категории → подкатегории → товары, CRUD, clone, экспорт
3. **Users** — таблица + детальная страница, batch ban/unban, заметки, поиск, статус-вкладки
4. **Wallets** — 4 вкладки (All/Owner/Transactions/Seeds), запись платежей, экспорт seed-фраз
5. **Purchases** — таблица с batch approve/cancel, фильтры по статусу/дате, модаль деталей
6. **Audit Log** — журнал действий, фильтры по действию/дате/поиску, копирование записей
7. **Categories** — CRUD с просмотром товаров, подсчёт подкатегорий и продуктов
8. **Locations** — CRUD (страна/город/район)
9. **Settings** — редактирование параметров, экспорт/импорт данных (super_admin)
10. **Locales** — inline-редактор EN/ES/DE переводов
11. **Danger Zone** — Seed / Clear с reauth (super_admin)
### ИИ-ассистент и Лиды
12. **AI Chatbot** (`#/chatbot`) — полная конфигурация ИИ-бота:
- Включение/выключение бота
- **Спящий режим** — при включении `/start` показывает ИИ-чат вместо каталога
- Системный промпт и приветственное сообщение
- Температура, max tokens, глубина истории
- **База знаний** — словарный лексикон (товары, цены, FAQ)
- Провайдер: OpenAI / DeepSeek / OpenRouter / Ollama / Custom
- API endpoint и ключ (маскированный при отображении)
13. **Leads** (`#/leads`) — управление лидами и переписками:
- Таблица лидов с поиском, фильтрами по статусу
- AI-профиль клиента (intent, interests, sentiment, readiness)
- Просмотр переписок в виде чат-пузырей
- **Вход оператора** — переключение бота на ручной режим
- Статусы: Новый / Контакт / Квалифицированный / Потерянный / Спам
- Заметки и quick-статус
## Спящий режим магазина
Когда спящий режим включён в настройках AI Chatbot:
- Пользователь через `/start` получает ИИ-чат вместо каталога
- Бот сообщает что магазин пополняется
- Можно собрать контакты для уведомления при открытии
- Все сессии сохраняются в таблице `chat_sessions`
- Из переписок автоматически извлекаются лиды
## API маршруты (48+)
### Основные
| Метод | Маршрут | Описание |
|---|---|---|
| POST | `/api/auth/login` | Вход, установка куки |
| GET | `/api/auth/session` | Проверка сессии |
| POST | `/api/auth/logout` | Выход |
| GET | `/api/stats/dashboard` | Статистика дашборда |
| GET/PUT | `/api/settings` | Настройки |
| GET | `/api/settings/export` | Полный экспорт БД (JSON) |
| POST | `/api/settings/import` | Импорт (в разработке) |
### Товары и каталог
| Метод | Маршрут | Описание |
|---|---|---|
| GET | `/api/products/bulk` | Список товаров |
| POST | `/api/products/add` | Создание товара |
| GET/PUT/DELETE | `/api/products/[id]` | CRUD товара |
| POST | `/api/products/[id]/clone` | Дублирование товара |
| GET | `/api/catalog/tree` | Дерево каталога |
| GET/POST | `/api/categories/bulk` | Список/создание категорий |
| GET/PUT/DELETE | `/api/categories/[id]` | CRUD категории |
| GET/POST | `/api/subcategories/bulk` | Список/создание подкатегорий |
| GET/PUT/DELETE | `/api/subcategories/[id]` | CRUD подкатегории |
| GET/POST | `/api/locations/bulk` | Список/создание локаций |
| GET/PUT/DELETE | `/api/locations/[id]` | CRUD локации |
### Пользователи и кошельки
| Метод | Маршрут | Описание |
|---|---|---|
| GET | `/api/users/bulk` | Список пользователей |
| GET/PUT | `/api/users/[id]` | Профиль пользователя |
| POST | `/api/users/[id]/adjust-balance` | Корректировка баланса |
| POST | `/api/users/batch-status` | Batch ban/unban |
| GET | `/api/wallets/bulk` | Список кошельков |
| GET | `/api/wallets/overview` | Обзор кошельков |
| GET | `/api/wallets/[userId]` | Кошельки пользователя |
| POST | `/api/wallets/record-payment` | Запись платежа |
| GET | `/api/wallets/seeds` | Seed-фразы (super_admin) |
| GET | `/api/wallets/export-seeds` | Экспорт seed-фраз CSV |
### Покупки и транзакции
| Метод | Маршрут | Описание |
|---|---|---|
| GET | `/api/purchases/bulk` | Список покупок |
| GET/PUT | `/api/purchases/[id]` | Детали/статус покупки |
| POST | `/api/purchases/batch-status` | Batch approve/cancel |
| GET | `/api/transactions/bulk` | Список транзакций |
### Аудит и локали
| Метод | Маршрут | Описание |
|---|---|---|
| GET | `/api/audit/bulk` | Журнал аудита |
| GET | `/api/locales` | Локализации (EN/ES/DE) |
| POST | `/api/seed/demo` | Генерация тестовых данных |
| POST | `/api/seed/clear` | Очистка БД |
### ИИ-чатбот и лиды
| Метод | Маршрут | Описание |
|---|---|---|
| GET/PUT | `/api/admin/chatbot` | Настройки ИИ-бота |
| POST | `/api/chat` | Точка входа чата (для TG-бота) |
| GET | `/api/leads/bulk` | Список лидов |
| GET/PUT | `/api/leads/[id]` | Профиль лида |
| GET | `/api/leads/[id]/sessions` | Чат-сессии лида |
| POST | `/api/operator` | Подключение/отключение оператора |
## Модель данных (Prisma)
Всего **15 моделей**:
| Модель | Описание |
|---|---|
| `TgUser` | Пользователи Telegram |
| `CryptoWallet` | Криптокошельки |
| `Transaction` | Транзакции |
| `Location` | Локации (страна/город/район) |
| `Category` | Категории товаров |
| `Subcategory` | Подкатегории |
| `Product` | Товары |
| `Purchase` | Покупки |
| `CommissionPayment` | Комиссионные платежи |
| `AuditLog` | Журнал аудита |
| `UserState` | Состояния пользователей ( FSM ) |
| `ChatSession` | Чат-сессии с ИИ-ботом |
| `Lead` | Лиды (авто-экстракция из чата) |
| `SiteSetting` | Ключ-значение настройки |
### ChatSession
```prisma
model ChatSession {
id Int @id @default(autoincrement())
sessionId String @unique
telegramId String?
leadId Int?
messages String // JSON: [{role, content, timestamp}]
customerProfile String? // AI-профиль клиента (JSON)
isActive Boolean @default(true)
operatorName String? // Подключённый оператор
autoReplyDisabled Boolean @default(false) // Ручной режим
operatorConnectedAt DateTime?
device / ip / country
createdAt / updatedAt
}
```
### Lead
```prisma
model Lead {
id Int @id @default(autoincrement())
telegramId String? @unique
name / phone / email / telegram
status String @default("new")
aiLeadScore Float? // 0-1 скор от ИИ
customFields String // JSON
chatSessions ChatSession[]
}
```
## Архитектура ИИ-бота
### Конфигурация (SiteSetting)
Все настройки бота хранятся в таблице `site_settings` как ключ-значение. Кэшируются 5 минут.
| Ключ | Тип | По умолчанию |
|---|---|---|
| `chatbot_enabled` | bool | true |
| `chatbot_sleep_mode` | bool | false |
| `chatbot_sleep_message` | text | "Магазин пополняется..." |
| `chatbot_system_prompt` | text | "Ты — AI-ассистент..." |
| `chatbot_welcome_message` | text | "Здравствуйте!..." |
| `chatbot_temperature` | float | 0.7 |
| `chatbot_max_tokens` | int | 500 |
| `chatbot_max_history` | int | 20 |
| `chatbot_knowledge_base` | text | "" |
| `chatbot_provider` | enum | openai |
| `chatbot_api_endpoint` | url | https://api.openai.com/v1 |
| `chatbot_api_key` | string | "" |
### Поток чата
1. TG-бот отправляет `POST /api/chat` с `{sessionId, message, telegramId}`
2. Сервер находит/создаёт ChatSession
3. Загружает конфигурацию бота (из кэша/БД)
4. Формирует системный промпт: `system_prompt + knowledge_base + customer_profile + catalog_context`
5. Если `sleep_mode` — добавляет информацию о режиме пополнения
6. Отправляет в LLM (через z-ai-web-dev-sdk)
7. Сохраняет сообщения в ChatSession
8. Извлекает данные лида (имя, телефон, email, telegram) из текста
9. Генерирует/обновляет AI-профиль клиента (intent, interests, sentiment, readiness)
10. Автоматически создаёт/обновляет запись Lead
11. Возвращает `{reply, sessionId, leadId?, profile?}`
### Профилирование клиента
Из каждой переписки ИИ автоматически генерирует профиль:
```json
{
"intent": "покупка|информация|поддержка|пробный период",
"interests": ["VPN-коды", "аналитика"],
"sentiment": "positive|neutral|negative",
"budgetHint": "бюджетный|высокий",
"readiness": "exploring|considering|ready",
"summary": "Цель: покупка. Интересуется VPN."
}
```
### Оператор
- Оператор может подключиться к любой сессии (`POST /api/operator`)
- При подключении: `autoReplyDisabled=true`, бот перестаёт отвечать
- Оператор видит всю историю переписки
- При отключении — бот снова отвечает
## Развертывание (Docker)
### Сравнение со старой версией
| | Старая (Node.js бот) | Новая (Next.js админка) |
|---|---|---|
| Dockerfile | `FROM node:22`, `npm install`, `CMD node src/index.js` | Multi-stage build, standalone output, non-root user |
| docker-compose | 1 сервис, BOT_TOKEN + ADMIN_IDS | 1 сервис, ADMIN_SECRET + CHATBOT_API_KEY |
| БД | `./db/shop.db` (sqlite3 напрямую) | `./db/custom.db` (через Prisma ORM) |
| Порт | Нет (только TG webhook) | 3000 (веб-интерфейс + API) |
| RAM | ~64 MB | ~256512 MB |
### Быстрый старт (docker compose)
```bash
# 1. Клонировать ветку
GIT_LFS_SKIP_SMUDGE=1 git clone -b feat/nextjs-admin https://git.softuniq.eu/Telegram-Market/telegram-shop.git
CD telegram-shop
# 2. Создать .env файл
cat > .env << 'EOF'
ADMIN_SECRET=your_admin_password
SUPER_ADMIN_SECRET=your_super_admin_password
CHATBOT_API_KEY=sk-your-openai-key # опционально, для ИИ-бота
CHATBOT_API_ENDPOINT=https://api.openai.com/v1 # или другой провайдер
EOF
# 3. Создать папку для БД
mkdir -p db
# 4. Собрать и запустить
COMPOSE_DOCKER_CLI_BUILD=1 DOCKER_BUILDKIT=1 docker compose up -d --build
# 5. Дождаться запуска (15-30 сек)
docker compose logs -f
```
После запуска админка доступна на `http://<IP>:3000`.
### Ручной Docker (без compose)
```bash
# Сборка
docker build -t tg-shop-admin .
# Запуск
docker run -d \
--name tg_shop_admin \
--restart always \
-p 3000:3000 \
-v $(pwd)/db:/app/db \
-e ADMIN_SECRET=your_admin_password \
-e SUPER_ADMIN_SECRET=your_super_admin_password \
-e CHATBOT_API_KEY=sk-xxx \
-m 512m \
tg-shop-admin
```
### Переменные окружения
| Переменная | Обязательна | По умолчанию | Описание |
|---|---|---|---|
| `DATABASE_URL` | Нет | `file:/app/db/custom.db` | Путь к SQLite БД внутри контейнера |
| `ADMIN_SECRET` | **Да** | `changeme` | Пароль для роли admin |
| `SUPER_ADMIN_SECRET` | Нет | — | Пароль для роли super_admin |
| `CHATBOT_API_KEY` | Нет | — | API-ключ для ИИ-бота (OpenAI/DeepSeek/etc) |
| `CHATBOT_API_ENDPOINT` | Нет | `https://api.openai.com/v1` | Endpoint LLM-провайдера |
### Запуск без Docker (разработка)
```bash
# Установить зависимости
bun install
# Инициализация БД
bun run db:push
# Создать .env
echo 'DATABASE_URL=file:./db/custom.db' > .env
echo 'ADMIN_SECRET=admin123' >> .env
echo 'SUPER_ADMIN_SECRET=superadmin456' >> .env
# Генерация тестовых данных (опционально)
curl -X POST http://localhost:3000/api/seed/demo \
-H 'Cookie: admin_token=<your_token>'
# Dev-сервер
bun run dev # http://localhost:3000
# Production
bun run build # сборка standalone
bun run start # запуск production
```
### Первоначальная настройка после деплоя
1. Открыть `http://<IP>:3000`
2. Войти с паролем из `ADMIN_SECRET`
3. Перейти в **Settings** (`#/settings`) — настроить параметры магазина
4. Перейти в **AI Chatbot** (`#/chatbot`) — настроить ИИ-бота:
- Ввести API-ключ и выбрать провайдера
- Настроить системный промпт
- Добавить базу знаний (словарный лексикон)
5. Перейти в **Danger Zone****Seed Demo Data** для заполнения тестовыми данными
6. Очистить тестовые данные через **Clear Database** перед продакшеном
### Обновление
```bash
# docker compose
git pull
docker compose up -d --build
# ручной
git pull
docker build -t tg-shop-admin .
docker stop tg_shop_admin && docker rm tg_shop_admin
# повторить docker run ...
```
**Важно:** БД хранится в volume `./db`, она сохраняется при пересборке.
### Требования к серверу
| Ресурс | Минимум | Рекомендуется |
|---|---|---|
| CPU | 1 ядро | 2 ядра |
| RAM | 256 MB | 512 MB |
| Диск | 500 MB (образ) + БД | 1 GB |
| Архитектура | x86_64, ARM64 | — |
### Reverse Proxy (Caddy / Nginx)
**Caddy** (авто HTTPS):
```
admin.yourdomain.com {
reverse_proxy localhost:3000
}
```
**Nginx**:
```nginx
server {
listen 443 ssl;
server_name admin.yourdomain.com;
# ... ssl certs ...
location / {
proxy_pass http://127.0.0.1:3000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
```
## Seed-данные
POST `/api/seed/demo` создаёт данные:
- 3 локации, 5 категорий, 11 подкатегорий
- 10 пользователей (alicejack)
- 10 товаров, 2530 покупок
- 10 криптокошельков, 2 комиссионных платежа, 12 audit записей
## Общие компоненты
- `Pagination` — числовая пагинация с многоточиями
- `ErrorBoundary` — обработка ошибок рендеринга
- `ExportButton` — экспорт CSV + JSON
- `SortableHeader` — сортируемые заголовки таблиц
- `useDebounce` — хук debounce (300ms)
- `useMobile` — хук определения мобильного устройства
- `useKeyboardShortcuts` — хук горячих клавиш (19)
## Навигация
Хеш-роутинг (`window.location.hash`). Горячие клавиши:
`1` Dashboard, `2` Catalog, `3` Users, `4` Wallets, `5` Purchases,
`6` Audit, `7` Categories, `8` Locations, `9` Settings
`Ctrl+K` — палитра команд
## Визуальные эффекты
- **Matrix Rain** — CSS-анимация падающих символов на странице логина (низкая непрозрачность)
- **Glass-card** — стеклянный эффект карточек (backdrop-blur)
- **KPI shimmer** — мерцание при наведении на KPI-карточки
- **Page-enter** — fade-in анимация страниц
- **Gradient borders** — градиентные рамки хедера/футера
- **Alternating rows** — чередующиеся строки таблиц
- **Sticky table headers** — закреплённые заголовки таблиц