- Multi-stage Dockerfile (node:22-slim, bun build, standalone output, non-root) - docker-compose.yml with DB volume, healthcheck, memory limits - .dockerignore to exclude dev artifacts from build context - docs: full deployment guide with docker compose, manual docker, env vars, reverse proxy configs (Caddy/Nginx), update instructions, server requirements - docs: comparison table old (Node.js bot) vs new (Next.js admin)
19 KiB
Executable File
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)
Основные
- Dashboard — 4 KPI-карточки, 8 графиков (recharts), лента активности, авто-обновление
- Catalog — дерево локаций → категории → подкатегории → товары, CRUD, clone, экспорт
- Users — таблица + детальная страница, batch ban/unban, заметки, поиск, статус-вкладки
- Wallets — 4 вкладки (All/Owner/Transactions/Seeds), запись платежей, экспорт seed-фраз
- Purchases — таблица с batch approve/cancel, фильтры по статусу/дате, модаль деталей
- Audit Log — журнал действий, фильтры по действию/дате/поиску, копирование записей
- Categories — CRUD с просмотром товаров, подсчёт подкатегорий и продуктов
- Locations — CRUD (страна/город/район)
- Settings — редактирование параметров, экспорт/импорт данных (super_admin)
- Locales — inline-редактор EN/ES/DE переводов
- Danger Zone — Seed / Clear с reauth (super_admin)
ИИ-ассистент и Лиды
-
AI Chatbot (
#/chatbot) — полная конфигурация ИИ-бота:- Включение/выключение бота
- Спящий режим — при включении
/startпоказывает ИИ-чат вместо каталога - Системный промпт и приветственное сообщение
- Температура, max tokens, глубина истории
- База знаний — словарный лексикон (товары, цены, FAQ)
- Провайдер: OpenAI / DeepSeek / OpenRouter / Ollama / Custom
- API endpoint и ключ (маскированный при отображении)
-
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
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
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 | "" |
Поток чата
- TG-бот отправляет
POST /api/chatс{sessionId, message, telegramId} - Сервер находит/создаёт ChatSession
- Загружает конфигурацию бота (из кэша/БД)
- Формирует системный промпт:
system_prompt + knowledge_base + customer_profile + catalog_context - Если
sleep_mode— добавляет информацию о режиме пополнения - Отправляет в LLM (через z-ai-web-dev-sdk)
- Сохраняет сообщения в ChatSession
- Извлекает данные лида (имя, телефон, email, telegram) из текста
- Генерирует/обновляет AI-профиль клиента (intent, interests, sentiment, readiness)
- Автоматически создаёт/обновляет запись Lead
- Возвращает
{reply, sessionId, leadId?, profile?}
Профилирование клиента
Из каждой переписки ИИ автоматически генерирует профиль:
{
"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 | ~256–512 MB |
Быстрый старт (docker compose)
# 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)
# Сборка
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 (разработка)
# Установить зависимости
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
Первоначальная настройка после деплоя
- Открыть
http://<IP>:3000 - Войти с паролем из
ADMIN_SECRET - Перейти в Settings (
#/settings) — настроить параметры магазина - Перейти в AI Chatbot (
#/chatbot) — настроить ИИ-бота:- Ввести API-ключ и выбрать провайдера
- Настроить системный промпт
- Добавить базу знаний (словарный лексикон)
- Перейти в Danger Zone → Seed Demo Data для заполнения тестовыми данными
- Очистить тестовые данные через Clear Database перед продакшеном
Обновление
# 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:
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 пользователей (alice–jack)
- 10 товаров, 25–30 покупок
- 10 криптокошельков, 2 комиссионных платежа, 12 audit записей
Общие компоненты
Pagination— числовая пагинация с многоточиямиErrorBoundary— обработка ошибок рендерингаExportButton— экспорт CSV + JSONSortableHeader— сортируемые заголовки таблицuseDebounce— хук debounce (300ms)useMobile— хук определения мобильного устройстваuseKeyboardShortcuts— хук горячих клавиш (1–9)
Навигация
Хеш-роутинг (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 — закреплённые заголовки таблиц