292 lines
14 KiB
Markdown
Executable File
292 lines
14 KiB
Markdown
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)
|
||
|
||
### Основные
|
||
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 (ARM)
|
||
|
||
```bash
|
||
docker build -t tg-admin .
|
||
docker run -p 3000:3000 -v ./db:/app/db \
|
||
-e ADMIN_SECRET=your_secret \
|
||
-e SUPER_ADMIN_SECRET=super_secret \
|
||
-e CHATBOT_API_KEY=sk-xxx \
|
||
tg-admin
|
||
```
|
||
|
||
Требования: минимум 512 МБ RAM, ARM64/ARMv7/x86_64.
|
||
|
||
## Seed-данные
|
||
|
||
POST `/api/seed/demo` создаёт данные:
|
||
- 3 локации, 5 категорий, 11 подкатегорий
|
||
- 10 пользователей (alice–jack)
|
||
- 10 товаров, 25–30 покупок
|
||
- 10 криптокошельков, 2 комиссионных платежа, 12 audit записей
|
||
|
||
## Общие компоненты
|
||
|
||
- `Pagination` — числовая пагинация с многоточиями
|
||
- `ErrorBoundary` — обработка ошибок рендеринга
|
||
- `ExportButton` — экспорт CSV + JSON
|
||
- `SortableHeader` — сортируемые заголовки таблиц
|
||
- `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** — закреплённые заголовки таблиц |