925 lines
37 KiB
Markdown
925 lines
37 KiB
Markdown
# API Документация: Генерация стратегии продвижения (Frontend/AI Agent)
|
||
|
||
## Базовый URL
|
||
|
||
```
|
||
https://api.konturai.kz
|
||
```
|
||
|
||
## Обзор
|
||
|
||
API для генерации детальной стратегии продвижения продукта на основе маркетингового анализа. Стратегия включает:
|
||
|
||
1. **Недельный план** - темы и рекомендации по контенту для каждой недели
|
||
2. **Календарь постов** - детальный план публикаций с датами, платформами, текстами и хештегами
|
||
|
||
Процесс состоит из двух этапов:
|
||
|
||
1. **Запуск генерации стратегии** - создание задачи и начало асинхронной обработки
|
||
2. **Получение результатов** - проверка статуса и получение готовой стратегии
|
||
|
||
Генерация стратегии выполняется асинхронно и занимает примерно 3-5 минут.
|
||
|
||
**Важно**: Для генерации стратегии требуется завершенный маркетинговый анализ. Сначала необходимо получить `analysisId` из завершенного анализа.
|
||
|
||
---
|
||
|
||
## Эндпоинты
|
||
|
||
### 1. Запуск генерации стратегии продвижения
|
||
|
||
**POST** `/api/marketing/strategy/generate`
|
||
|
||
Создает новую задачу на генерацию стратегии продвижения и запускает асинхронную обработку.
|
||
|
||
#### Параметры запроса
|
||
|
||
| Параметр | Тип | Расположение | Обязательный | Описание |
|
||
| ------------------- | ------- | ------------ | ------------ | --------------------------------------- |
|
||
| `analysisId` | string | Query | ✅ | ID завершенного маркетингового анализа |
|
||
| `durationWeeks` | integer | Body | ❌ | Длительность стратегии в неделях (1-12) |
|
||
| `priorityPlatforms` | array | Body | ❌ | Приоритетные платформы для продвижения |
|
||
|
||
#### Заголовки запроса
|
||
|
||
```
|
||
Content-Type: application/json
|
||
```
|
||
|
||
#### Тело запроса (JSON, опционально)
|
||
|
||
| Поле | Тип | Обязательный | Описание | Пример значения |
|
||
| ------------------- | ------- | ------------ | --------------------------------------- | ------------------------------------- |
|
||
| `durationWeeks` | integer | ❌ | Длительность стратегии в неделях (1-12) | 4 |
|
||
| `priorityPlatforms` | array | ❌ | Список приоритетных платформ | ["Instagram", "LinkedIn", "Telegram"] |
|
||
|
||
#### Валидация полей
|
||
|
||
**`durationWeeks`** (integer, опциональное)
|
||
|
||
- Минимальное значение: 1
|
||
- Максимальное значение: 12
|
||
- По умолчанию: 4 (если не указано)
|
||
|
||
**`priorityPlatforms`** (array, опциональное)
|
||
|
||
- Допустимые платформы: `Instagram`, `Facebook`, `LinkedIn`, `Telegram`, `TikTok`, `YouTube`, `21MC` и другие
|
||
- Если не указано, используются все популярные платформы
|
||
|
||
#### Пример запроса
|
||
|
||
```http
|
||
POST /api/marketing/strategy/generate?analysisId=507f1f77bcf86cd799439011
|
||
Content-Type: application/json
|
||
|
||
{
|
||
"durationWeeks": 4,
|
||
"priorityPlatforms": ["Instagram", "LinkedIn", "Telegram"]
|
||
}
|
||
```
|
||
|
||
Или без тела запроса (используются значения по умолчанию):
|
||
|
||
```http
|
||
POST /api/marketing/strategy/generate?analysisId=507f1f77bcf86cd799439011
|
||
```
|
||
|
||
#### Пример успешного ответа (200 OK)
|
||
|
||
```json
|
||
{
|
||
"success": true,
|
||
"message": "Генерация стратегии запущена успешно. Результаты будут готовы в течение 3-5 минут.",
|
||
"data": {
|
||
"strategyId": "507f1f77bcf86cd799439012",
|
||
"analysisId": "507f1f77bcf86cd799439011",
|
||
"status": "queued",
|
||
"createdAt": "2025-01-20T15:40:00",
|
||
"durationWeeks": 4,
|
||
"priorityPlatforms": ["Instagram", "LinkedIn", "Telegram"]
|
||
}
|
||
}
|
||
```
|
||
|
||
#### Структура ответа
|
||
|
||
| Поле | Тип | Описание |
|
||
| ------------------------ | ------- | ----------------------------------------------------------------------- |
|
||
| `success` | boolean | Флаг успешности операции |
|
||
| `message` | string | Сообщение о результате операции |
|
||
| `data.strategyId` | string | Уникальный идентификатор стратегии (MongoDB ObjectId) |
|
||
| `data.analysisId` | string | ID маркетингового анализа |
|
||
| `data.status` | string | Статус стратегии: `"queued"`, `"processing"`, `"completed"`, `"failed"` |
|
||
| `data.createdAt` | string | ISO 8601 дата/время создания |
|
||
| `data.durationWeeks` | integer | Длительность стратегии в неделях |
|
||
| `data.priorityPlatforms` | array | Список приоритетных платформ |
|
||
|
||
#### Пример ошибки (404 Not Found - анализ не найден)
|
||
|
||
```json
|
||
{
|
||
"success": false,
|
||
"message": "Анализ не найден",
|
||
"error": {
|
||
"code": "INVALID_ANALYSIS",
|
||
"message": "Анализ с ID 507f1f77bcf86cd799439011 не найден"
|
||
}
|
||
}
|
||
```
|
||
|
||
#### Пример ошибки (400 Bad Request - анализ не завершен)
|
||
|
||
```json
|
||
{
|
||
"success": false,
|
||
"message": "Анализ еще не завершен",
|
||
"error": {
|
||
"code": "ANALYSIS_NOT_COMPLETED",
|
||
"message": "Анализ еще не завершен. Статус: processing"
|
||
}
|
||
}
|
||
```
|
||
|
||
#### Пример ошибки валидации (400 Bad Request)
|
||
|
||
```json
|
||
{
|
||
"success": false,
|
||
"message": "Ошибка валидации",
|
||
"error": {
|
||
"code": "VALIDATION_ERROR",
|
||
"message": "Ошибка валидации входных данных",
|
||
"details": {
|
||
"durationWeeks": "Длительность стратегии должна быть не менее 1 недели"
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
### 2. Получение стратегии по ID
|
||
|
||
**GET** `/api/marketing/strategy/{strategyId}`
|
||
|
||
Возвращает статус и результаты стратегии по идентификатору.
|
||
|
||
#### Параметры пути
|
||
|
||
| Параметр | Тип | Описание |
|
||
| ------------ | ------ | ----------------------- |
|
||
| `strategyId` | string | Идентификатор стратегии |
|
||
|
||
#### Пример запроса
|
||
|
||
```
|
||
GET /api/marketing/strategy/507f1f77bcf86cd799439012
|
||
```
|
||
|
||
#### Пример ответа (когда стратегия завершена - 200 OK)
|
||
|
||
```json
|
||
{
|
||
"success": true,
|
||
"message": "Операция выполнена успешно",
|
||
"data": {
|
||
"strategyId": "507f1f77bcf86cd799439012",
|
||
"analysisId": "507f1f77bcf86cd799439011",
|
||
"status": "completed",
|
||
"createdAt": "2025-01-20T15:40:00",
|
||
"completedAt": "2025-01-20T15:43:00",
|
||
"durationWeeks": 4,
|
||
"priorityPlatforms": ["Instagram", "LinkedIn", "Telegram"],
|
||
"strategy": {
|
||
"weeklyPlans": [
|
||
{
|
||
"weekNumber": 1,
|
||
"mainThemes": [
|
||
"Презентация продукта",
|
||
"Ключевые преимущества",
|
||
"Решение проблем клиентов"
|
||
],
|
||
"contentRecommendations": "Сфокусируйтесь на представлении продукта и его основных преимуществах. Используйте визуальный контент для привлечения внимания. Подчеркните уникальные особенности, которые выделяют ваш продукт на рынке.",
|
||
"priorityPlatforms": ["Instagram", "LinkedIn"]
|
||
},
|
||
{
|
||
"weekNumber": 2,
|
||
"mainThemes": [
|
||
"Кейсы успешных клиентов",
|
||
"Отзывы и рекомендации",
|
||
"Демонстрация результатов"
|
||
],
|
||
"contentRecommendations": "Публикуйте реальные истории успеха ваших клиентов. Используйте отзывы и рекомендации для повышения доверия. Покажите конкретные результаты и достижения.",
|
||
"priorityPlatforms": ["Instagram", "Telegram"]
|
||
},
|
||
{
|
||
"weekNumber": 3,
|
||
"mainThemes": [
|
||
"Образовательный контент",
|
||
"Советы и рекомендации",
|
||
"Индустриальные инсайты"
|
||
],
|
||
"contentRecommendations": "Создавайте образовательный контент, который помогает вашей целевой аудитории. Делитесь экспертными знаниями и инсайтами индустрии. Позиционируйте себя как эксперта в области.",
|
||
"priorityPlatforms": ["LinkedIn", "Telegram"]
|
||
},
|
||
{
|
||
"weekNumber": 4,
|
||
"mainThemes": [
|
||
"Призыв к действию",
|
||
"Специальные предложения",
|
||
"Завершение кампании"
|
||
],
|
||
"contentRecommendations": "Активно призывайте к действию. Предлагайте специальные условия или бонусы. Подводите итоги кампании и демонстрируйте достигнутые результаты.",
|
||
"priorityPlatforms": ["Instagram", "LinkedIn", "Telegram"]
|
||
}
|
||
],
|
||
"postCalendar": [
|
||
{
|
||
"publishDate": "2025-01-21T10:00:00",
|
||
"platform": "Instagram",
|
||
"contentType": "пост",
|
||
"theme": "Презентация продукта",
|
||
"postText": "🚀 Представляем наш новый продукт! Мы создали решение, которое поможет вашему бизнесу достичь новых высот. Узнайте больше о ключевых преимуществах в нашем профиле. #бизнес #инновации #продукт",
|
||
"hashtags": [
|
||
"#бизнес",
|
||
"#инновации",
|
||
"#продукт",
|
||
"#маркетинг",
|
||
"#развитие"
|
||
],
|
||
"publishTime": "10:00"
|
||
},
|
||
{
|
||
"publishDate": "2025-01-21T14:00:00",
|
||
"platform": "LinkedIn",
|
||
"contentType": "пост",
|
||
"theme": "Ключевые преимущества",
|
||
"postText": "Наш продукт предлагает уникальные преимущества для B2B клиентов: быстрая интеграция, масштабируемость и надежная поддержка. Свяжитесь с нами для консультации. #B2B #технологии #бизнес",
|
||
"hashtags": [
|
||
"#B2B",
|
||
"#технологии",
|
||
"#бизнес",
|
||
"#решения",
|
||
"#консультация"
|
||
],
|
||
"publishTime": "14:00"
|
||
},
|
||
{
|
||
"publishDate": "2025-01-22T18:00:00",
|
||
"platform": "Instagram",
|
||
"contentType": "сторис",
|
||
"theme": "Решение проблем клиентов",
|
||
"postText": "Знаете ли вы, что 80% компаний сталкиваются с проблемой X? Наш продукт решает эту проблему эффективно и быстро. Swipe up для деталей! 👆",
|
||
"hashtags": ["#решение", "#проблемы", "#эффективность"],
|
||
"publishTime": "18:00"
|
||
},
|
||
{
|
||
"publishDate": "2025-01-23T10:00:00",
|
||
"platform": "Telegram",
|
||
"contentType": "пост",
|
||
"theme": "Кейс успешного клиента",
|
||
"postText": "📊 Кейс: Как компания X увеличила эффективность на 150% с помощью нашего продукта. Читайте полную историю в нашем канале. #кейс #успех #результаты",
|
||
"hashtags": ["#кейс", "#успех", "#результаты", "#бизнес"],
|
||
"publishTime": "10:00"
|
||
}
|
||
]
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
#### Пример ответа (когда стратегия еще обрабатывается - 200 OK)
|
||
|
||
```json
|
||
{
|
||
"success": true,
|
||
"message": "Операция выполнена успешно",
|
||
"data": {
|
||
"strategyId": "507f1f77bcf86cd799439012",
|
||
"analysisId": "507f1f77bcf86cd799439011",
|
||
"status": "processing",
|
||
"createdAt": "2025-01-20T15:40:00",
|
||
"completedAt": null,
|
||
"durationWeeks": 4,
|
||
"priorityPlatforms": ["Instagram", "LinkedIn", "Telegram"],
|
||
"strategy": null
|
||
}
|
||
}
|
||
```
|
||
|
||
#### Статусы стратегии
|
||
|
||
| Статус | Описание |
|
||
| ------------ | ------------------------------- |
|
||
| `queued` | Запрос в очереди на обработку |
|
||
| `processing` | Стратегия генерируется |
|
||
| `completed` | Стратегия завершена успешно |
|
||
| `failed` | Стратегия завершилась с ошибкой |
|
||
|
||
#### Структура ответа
|
||
|
||
| Поле | Тип | Описание |
|
||
| ---------------------------------------------------- | ------- | ------------------------------------------------------ |
|
||
| `success` | boolean | Флаг успешности операции |
|
||
| `message` | string | Сообщение о результате операции |
|
||
| `data.strategyId` | string | Уникальный идентификатор стратегии |
|
||
| `data.analysisId` | string | ID маркетингового анализа |
|
||
| `data.status` | string | Статус стратегии |
|
||
| `data.createdAt` | string | ISO 8601 дата/время создания |
|
||
| `data.completedAt` | string | ISO 8601 дата/время завершения (null если не завершен) |
|
||
| `data.durationWeeks` | integer | Длительность стратегии в неделях |
|
||
| `data.priorityPlatforms` | array | Список приоритетных платформ |
|
||
| `data.strategy` | object | Объект со стратегией (null если не завершен) |
|
||
| `data.strategy.weeklyPlans` | array | Список недельных планов |
|
||
| `data.strategy.weeklyPlans[].weekNumber` | integer | Номер недели (1, 2, 3, ...) |
|
||
| `data.strategy.weeklyPlans[].mainThemes` | array | Основные темы недели (массив строк) |
|
||
| `data.strategy.weeklyPlans[].contentRecommendations` | string | Рекомендации по контенту для недели |
|
||
| `data.strategy.weeklyPlans[].priorityPlatforms` | array | Приоритетные платформы для недели |
|
||
| `data.strategy.postCalendar` | array | Календарь постов |
|
||
| `data.strategy.postCalendar[].publishDate` | string | ISO 8601 дата/время публикации |
|
||
| `data.strategy.postCalendar[].platform` | string | Платформа для публикации |
|
||
| `data.strategy.postCalendar[].contentType` | string | Тип контента (пост, сторис, видео, баннер) |
|
||
| `data.strategy.postCalendar[].theme` | string | Тема поста |
|
||
| `data.strategy.postCalendar[].postText` | string | Полный текст поста (готовый к публикации) |
|
||
| `data.strategy.postCalendar[].hashtags` | array | Список хештегов (массив строк) |
|
||
| `data.strategy.postCalendar[].publishTime` | string | Время публикации в формате HH:mm |
|
||
| `data.strategy.postCalendar[].imageUrl` | string | Путь к изображению в MinIO (может быть null) |
|
||
| `data.strategy.postCalendar[].imageFilename` | string | Имя файла изображения в MinIO (может быть null) |
|
||
|
||
#### Пример ошибки (404 Not Found)
|
||
|
||
```json
|
||
{
|
||
"success": false,
|
||
"message": "Стратегия не найдена",
|
||
"error": {
|
||
"code": "NOT_FOUND",
|
||
"message": "Стратегия с указанным ID не найдена"
|
||
}
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
### 3. Получение стратегии по ID анализа
|
||
|
||
**GET** `/api/marketing/analysis/{analysisId}/strategy`
|
||
|
||
Возвращает стратегию, связанную с указанным маркетинговым анализом.
|
||
|
||
#### Параметры пути
|
||
|
||
| Параметр | Тип | Описание |
|
||
| ------------ | ------ | --------------------- |
|
||
| `analysisId` | string | Идентификатор анализа |
|
||
|
||
#### Пример запроса
|
||
|
||
```
|
||
GET /api/marketing/analysis/507f1f77bcf86cd799439011/strategy
|
||
```
|
||
|
||
#### Пример ответа
|
||
|
||
Структура ответа идентична эндпоинту `GET /api/marketing/strategy/{strategyId}` (см. выше).
|
||
|
||
#### Пример ошибки (404 Not Found)
|
||
|
||
```json
|
||
{
|
||
"success": false,
|
||
"message": "Стратегия не найдена",
|
||
"error": {
|
||
"code": "NOT_FOUND",
|
||
"message": "Стратегия для указанного анализа не найдена"
|
||
}
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## Обработка ошибок
|
||
|
||
### Коды ошибок
|
||
|
||
| Код | HTTP статус | Описание |
|
||
| ------------------------ | ----------- | ------------------------------- |
|
||
| `VALIDATION_ERROR` | 400 | Ошибка валидации входных данных |
|
||
| `INVALID_ANALYSIS` | 404 | Анализ не найден |
|
||
| `ANALYSIS_NOT_COMPLETED` | 400 | Анализ еще не завершен |
|
||
| `NOT_FOUND` | 404 | Стратегия не найдена |
|
||
| `INTERNAL_SERVER_ERROR` | 500 | Внутренняя ошибка сервера |
|
||
|
||
### Формат ошибки
|
||
|
||
```json
|
||
{
|
||
"success": false,
|
||
"message": "Описание ошибки",
|
||
"error": {
|
||
"code": "ERROR_CODE",
|
||
"message": "Детальное сообщение об ошибке",
|
||
"details": {
|
||
"field1": "Сообщение об ошибке для поля 1",
|
||
"field2": "Сообщение об ошибке для поля 2"
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
**Примечание**: Поле `details` присутствует только для ошибок валидации (`VALIDATION_ERROR`).
|
||
|
||
---
|
||
|
||
## Примеры использования
|
||
|
||
### JavaScript/TypeScript (Fetch API)
|
||
|
||
#### Запуск генерации стратегии
|
||
|
||
```javascript
|
||
async function generateStrategy(analysisId, options = {}) {
|
||
const params = new URLSearchParams();
|
||
params.append('analysisId', analysisId);
|
||
|
||
const response = await fetch(
|
||
`https://api.konturai.kz/api/marketing/strategy/generate?${params}`,
|
||
{
|
||
method: 'POST',
|
||
headers: {
|
||
'Content-Type': 'application/json',
|
||
},
|
||
body: JSON.stringify({
|
||
durationWeeks: options.durationWeeks || 4,
|
||
priorityPlatforms: options.priorityPlatforms || [],
|
||
}),
|
||
}
|
||
);
|
||
|
||
const result = await response.json();
|
||
|
||
if (result.success) {
|
||
console.log('Strategy ID:', result.data.strategyId);
|
||
return result.data.strategyId;
|
||
} else {
|
||
console.error('Error:', result.error);
|
||
throw new Error(result.error.message);
|
||
}
|
||
}
|
||
```
|
||
|
||
#### Проверка статуса и получение результата
|
||
|
||
```javascript
|
||
async function getStrategyResult(strategyId) {
|
||
const response = await fetch(
|
||
`https://api.konturai.kz/api/marketing/strategy/${strategyId}`
|
||
);
|
||
|
||
const result = await response.json();
|
||
|
||
if (result.success) {
|
||
const { status, strategy } = result.data;
|
||
|
||
if (status === 'completed' && strategy) {
|
||
console.log('Strategy completed!');
|
||
console.log('Weekly plans:', strategy.weeklyPlans);
|
||
console.log('Post calendar:', strategy.postCalendar);
|
||
return strategy;
|
||
} else if (status === 'processing') {
|
||
console.log('Strategy is still generating...');
|
||
return null; // Повторить запрос позже
|
||
} else if (status === 'failed') {
|
||
throw new Error('Strategy generation failed');
|
||
}
|
||
} else {
|
||
throw new Error(result.error.message);
|
||
}
|
||
}
|
||
```
|
||
|
||
#### Получение стратегии по ID анализа
|
||
|
||
```javascript
|
||
async function getStrategyByAnalysis(analysisId) {
|
||
const response = await fetch(
|
||
`https://api.konturai.kz/api/marketing/analysis/${analysisId}/strategy`
|
||
);
|
||
|
||
const result = await response.json();
|
||
|
||
if (result.success) {
|
||
return result.data;
|
||
} else {
|
||
throw new Error(result.error.message);
|
||
}
|
||
}
|
||
```
|
||
|
||
#### Полный цикл с polling
|
||
|
||
```javascript
|
||
async function waitForStrategyCompletion(
|
||
strategyId,
|
||
maxAttempts = 60,
|
||
intervalMs = 10000
|
||
) {
|
||
for (let i = 0; i < maxAttempts; i++) {
|
||
const result = await getStrategyResult(strategyId);
|
||
|
||
if (result) {
|
||
return result; // Стратегия завершена
|
||
}
|
||
|
||
// Ждем перед следующей проверкой
|
||
await new Promise((resolve) => setTimeout(resolve, intervalMs));
|
||
}
|
||
|
||
throw new Error('Strategy generation timeout');
|
||
}
|
||
|
||
// Использование
|
||
async function runFullStrategyGeneration() {
|
||
try {
|
||
// 1. Получаем завершенный анализ (предполагается, что analysisId уже есть)
|
||
const analysisId = '507f1f77bcf86cd799439011';
|
||
|
||
// 2. Запускаем генерацию стратегии
|
||
const strategyId = await generateStrategy(analysisId, {
|
||
durationWeeks: 4,
|
||
priorityPlatforms: ['Instagram', 'LinkedIn', 'Telegram'],
|
||
});
|
||
|
||
console.log(`Strategy generation started: ${strategyId}`);
|
||
|
||
// 3. Ждем завершения (проверяем каждые 10 секунд, максимум 10 минут)
|
||
const strategy = await waitForStrategyCompletion(strategyId, 60, 10000);
|
||
|
||
// 4. Используем результаты
|
||
console.log('Weekly plans:', strategy.weeklyPlans);
|
||
console.log('Post calendar:', strategy.postCalendar);
|
||
|
||
// Отображаем календарь постов
|
||
strategy.postCalendar.forEach((post) => {
|
||
console.log(`${post.publishDate} - ${post.platform}: ${post.theme}`);
|
||
});
|
||
|
||
return strategy;
|
||
} catch (error) {
|
||
console.error('Error:', error);
|
||
}
|
||
}
|
||
```
|
||
|
||
### React примеры
|
||
|
||
#### Компонент для отображения стратегии
|
||
|
||
```javascript
|
||
import React, { useState, useEffect } from 'react';
|
||
|
||
function StrategyView({ analysisId }) {
|
||
const [strategy, setStrategy] = useState(null);
|
||
const [loading, setLoading] = useState(true);
|
||
const [error, setError] = useState(null);
|
||
|
||
useEffect(() => {
|
||
async function loadStrategy() {
|
||
try {
|
||
// Сначала пытаемся получить существующую стратегию
|
||
let response = await fetch(
|
||
`/api/marketing/analysis/${analysisId}/strategy`
|
||
);
|
||
let result = await response.json();
|
||
|
||
if (result.success && result.data.status === 'completed') {
|
||
setStrategy(result.data);
|
||
setLoading(false);
|
||
return;
|
||
}
|
||
|
||
// Если стратегии нет или она еще обрабатывается, запускаем генерацию
|
||
if (!result.success || result.data.status === 'processing') {
|
||
// Запускаем генерацию
|
||
response = await fetch(
|
||
`/api/marketing/strategy/generate?analysisId=${analysisId}`,
|
||
{
|
||
method: 'POST',
|
||
headers: { 'Content-Type': 'application/json' },
|
||
body: JSON.stringify({
|
||
durationWeeks: 4,
|
||
priorityPlatforms: ['Instagram', 'LinkedIn', 'Telegram'],
|
||
}),
|
||
}
|
||
);
|
||
result = await response.json();
|
||
|
||
if (result.success) {
|
||
// Polling для получения результата
|
||
pollStrategy(result.data.strategyId);
|
||
} else {
|
||
setError(result.error.message);
|
||
setLoading(false);
|
||
}
|
||
}
|
||
} catch (err) {
|
||
setError(err.message);
|
||
setLoading(false);
|
||
}
|
||
}
|
||
|
||
async function pollStrategy(strategyId) {
|
||
const maxAttempts = 60;
|
||
let attempts = 0;
|
||
|
||
const interval = setInterval(async () => {
|
||
attempts++;
|
||
try {
|
||
const response = await fetch(`/api/marketing/strategy/${strategyId}`);
|
||
const result = await response.json();
|
||
|
||
if (result.success) {
|
||
if (result.data.status === 'completed') {
|
||
setStrategy(result.data);
|
||
setLoading(false);
|
||
clearInterval(interval);
|
||
} else if (result.data.status === 'failed') {
|
||
setError('Strategy generation failed');
|
||
setLoading(false);
|
||
clearInterval(interval);
|
||
}
|
||
}
|
||
|
||
if (attempts >= maxAttempts) {
|
||
setError('Strategy generation timeout');
|
||
setLoading(false);
|
||
clearInterval(interval);
|
||
}
|
||
} catch (err) {
|
||
setError(err.message);
|
||
setLoading(false);
|
||
clearInterval(interval);
|
||
}
|
||
}, 10000); // Проверяем каждые 10 секунд
|
||
}
|
||
|
||
if (analysisId) {
|
||
loadStrategy();
|
||
}
|
||
}, [analysisId]);
|
||
|
||
if (loading) {
|
||
return <div>Генерация стратегии...</div>;
|
||
}
|
||
|
||
if (error) {
|
||
return <div>Ошибка: {error}</div>;
|
||
}
|
||
|
||
if (!strategy || !strategy.strategy) {
|
||
return <div>Стратегия не найдена</div>;
|
||
}
|
||
|
||
return (
|
||
<div className='strategy-view'>
|
||
<h2>Стратегия продвижения</h2>
|
||
|
||
{/* Недельный план */}
|
||
<section className='weekly-plans'>
|
||
<h3>Недельный план</h3>
|
||
{strategy.strategy.weeklyPlans.map((plan) => (
|
||
<div key={plan.weekNumber} className='week-plan'>
|
||
<h4>Неделя {plan.weekNumber}</h4>
|
||
<div className='themes'>
|
||
<strong>Темы:</strong>
|
||
<ul>
|
||
{plan.mainThemes.map((theme, idx) => (
|
||
<li key={idx}>{theme}</li>
|
||
))}
|
||
</ul>
|
||
</div>
|
||
<div className='recommendations'>
|
||
<strong>Рекомендации:</strong>
|
||
<p>{plan.contentRecommendations}</p>
|
||
</div>
|
||
<div className='platforms'>
|
||
<strong>Платформы:</strong>
|
||
{plan.priorityPlatforms.join(', ')}
|
||
</div>
|
||
</div>
|
||
))}
|
||
</section>
|
||
|
||
{/* Календарь постов */}
|
||
<section className='post-calendar'>
|
||
<h3>Календарь постов</h3>
|
||
<div className='calendar-grid'>
|
||
{strategy.strategy.postCalendar.map((post, idx) => (
|
||
<div key={idx} className='post-item'>
|
||
<div className='post-header'>
|
||
<span className='date'>
|
||
{new Date(post.publishDate).toLocaleDateString('ru-RU')}
|
||
</span>
|
||
<span className='time'>{post.publishTime}</span>
|
||
<span className='platform'>{post.platform}</span>
|
||
<span className='content-type'>{post.contentType}</span>
|
||
</div>
|
||
<div className='post-theme'>
|
||
<strong>Тема:</strong> {post.theme}
|
||
</div>
|
||
<div className='post-text'>{post.postText}</div>
|
||
<div className='post-hashtags'>
|
||
{post.hashtags.map((tag, tagIdx) => (
|
||
<span key={tagIdx} className='hashtag'>
|
||
{tag}
|
||
</span>
|
||
))}
|
||
</div>
|
||
</div>
|
||
))}
|
||
</div>
|
||
</section>
|
||
</div>
|
||
);
|
||
}
|
||
|
||
export default StrategyView;
|
||
```
|
||
|
||
#### Компонент для отображения календаря постов
|
||
|
||
```javascript
|
||
import React from 'react';
|
||
|
||
function PostCalendar({ postCalendar }) {
|
||
// Группируем посты по датам
|
||
const postsByDate = postCalendar.reduce((acc, post) => {
|
||
const date = new Date(post.publishDate).toLocaleDateString('ru-RU');
|
||
if (!acc[date]) {
|
||
acc[date] = [];
|
||
}
|
||
acc[date].push(post);
|
||
return acc;
|
||
}, {});
|
||
|
||
return (
|
||
<div className='post-calendar'>
|
||
<h3>Календарь публикаций</h3>
|
||
{Object.entries(postsByDate).map(([date, posts]) => (
|
||
<div key={date} className='date-group'>
|
||
<h4>{date}</h4>
|
||
{posts.map((post, idx) => (
|
||
<div key={idx} className='post-card'>
|
||
<div className='post-meta'>
|
||
<span className='platform-badge'>{post.platform}</span>
|
||
<span className='content-type-badge'>{post.contentType}</span>
|
||
<span className='time'>{post.publishTime}</span>
|
||
</div>
|
||
<div className='post-content'>
|
||
<h5>{post.theme}</h5>
|
||
<p>{post.postText}</p>
|
||
<div className='hashtags'>
|
||
{post.hashtags.map((tag, tagIdx) => (
|
||
<span key={tagIdx} className='hashtag'>
|
||
{tag}
|
||
</span>
|
||
))}
|
||
</div>
|
||
</div>
|
||
</div>
|
||
))}
|
||
</div>
|
||
))}
|
||
</div>
|
||
);
|
||
}
|
||
|
||
export default PostCalendar;
|
||
```
|
||
|
||
### Vue.js примеры
|
||
|
||
```javascript
|
||
// composable для работы со стратегией
|
||
export function useMarketingStrategy() {
|
||
const baseUrl = '';
|
||
|
||
const generateStrategy = async (analysisId, options = {}) => {
|
||
const params = new URLSearchParams();
|
||
params.append('analysisId', analysisId);
|
||
|
||
const response = await fetch(
|
||
`${baseUrl}/api/marketing/strategy/generate?${params}`,
|
||
{
|
||
method: 'POST',
|
||
headers: { 'Content-Type': 'application/json' },
|
||
body: JSON.stringify({
|
||
durationWeeks: options.durationWeeks || 4,
|
||
priorityPlatforms: options.priorityPlatforms || [],
|
||
}),
|
||
}
|
||
);
|
||
|
||
const result = await response.json();
|
||
if (!result.success) {
|
||
throw new Error(result.error.message);
|
||
}
|
||
|
||
return result.data;
|
||
};
|
||
|
||
const getStrategy = async (strategyId) => {
|
||
const response = await fetch(
|
||
`${baseUrl}/api/marketing/strategy/${strategyId}`
|
||
);
|
||
const result = await response.json();
|
||
if (!result.success) {
|
||
throw new Error(result.error.message);
|
||
}
|
||
return result.data;
|
||
};
|
||
|
||
const getStrategyByAnalysis = async (analysisId) => {
|
||
const response = await fetch(
|
||
`${baseUrl}/api/marketing/analysis/${analysisId}/strategy`
|
||
);
|
||
const result = await response.json();
|
||
if (!result.success) {
|
||
throw new Error(result.error.message);
|
||
}
|
||
return result.data;
|
||
};
|
||
|
||
return {
|
||
generateStrategy,
|
||
getStrategy,
|
||
getStrategyByAnalysis,
|
||
};
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## Рекомендации по интеграции
|
||
|
||
### 1. Polling стратегия
|
||
|
||
Рекомендуется проверять статус стратегии каждые 10-15 секунд. Максимальное время ожидания - 5-7 минут.
|
||
|
||
### 2. Обработка ошибок
|
||
|
||
Всегда проверяйте поле `success` в ответе и обрабатывайте ошибки соответствующим образом. Особое внимание уделите случаям, когда анализ еще не завершен.
|
||
|
||
### 3. Валидация на клиенте
|
||
|
||
Перед отправкой запроса рекомендуется валидировать данные на клиенте:
|
||
|
||
- Проверка наличия `analysisId`
|
||
- Проверка диапазона `durationWeeks` (1-12)
|
||
- Проверка формата массива `priorityPlatforms`
|
||
|
||
### 4. UX рекомендации
|
||
|
||
- Показывайте индикатор загрузки во время генерации стратегии
|
||
- Отображайте примерное время завершения (3-5 минут)
|
||
- Предоставьте возможность отменить ожидание и проверить результат позже
|
||
- Сохраняйте `strategyId` для последующей проверки статуса
|
||
- Отображайте календарь постов в удобном формате (календарь, список, таблица)
|
||
- Позвольте пользователю копировать текст постов и хештеги
|
||
|
||
### 5. Кэширование
|
||
|
||
После получения результатов можно кэшировать их локально, используя `strategyId` или `analysisId` как ключ.
|
||
|
||
### 6. Экспорт данных
|
||
|
||
Рассмотрите возможность экспорта стратегии в различных форматах:
|
||
|
||
- CSV для календаря постов
|
||
- PDF для полной стратегии
|
||
- iCal для импорта в календарные приложения
|
||
|
||
---
|
||
|
||
## Примечания
|
||
|
||
1. **Формат даты**: Все даты возвращаются в формате ISO 8601 без timezone (LocalDateTime)
|
||
2. **Идентификаторы**: Используются MongoDB ObjectId (24 символа hex)
|
||
3. **Асинхронность**: Генерация стратегии выполняется асинхронно, не блокируя запрос
|
||
4. **Таймауты**: Рекомендуется устанавливать таймаут на запросы (минимум 30 секунд для запуска генерации)
|
||
5. **Зависимость от анализа**: Стратегия может быть сгенерирована только для завершенного анализа
|
||
6. **Повторная генерация**: Если стратегия уже существует для анализа, возвращается существующая стратегия
|
||
7. **Платформы**: Поддерживаются все популярные платформы: Instagram, Facebook, LinkedIn, Telegram, TikTok, YouTube, 21MC и другие
|
||
|
||
---
|
||
|
||
## Поддержка
|
||
|
||
При возникновении проблем с API обращайтесь в техническую поддержку с указанием:
|
||
|
||
- `strategyId` (если есть)
|
||
- `analysisId`
|
||
- Время запроса
|
||
- Описание проблемы
|
||
- Код ошибки (если есть)
|