feat: implement core frontend dashboard, auth flow, and AI-driven case management system

This commit is contained in:
2026-05-13 00:16:58 +03:00
parent 0732acbda5
commit 38f3199c33
5 changed files with 171 additions and 3 deletions

View File

@@ -6,9 +6,11 @@
## 💎 Ключевые возможности
### 1. 🤖 AI Assistant (Интеграция с Google Gemini)
* **Авто-претензии:** Генерация юридически грамотных жалоб на нарушителей на основе артикула и площадки.
* **Умный ответчик:** Автоматическая генерация персонализированных ответов на отзывы покупателей (поддержка позитивного и отработка негативного сценария).
### 1. 🤖 AI Assistant & Content Factory
* **Умный генератор карточек:** Создание полноценного контента (описание, ТТХ, SEO-теги) по одному лишь названию товара.
* **ИИ-Фото Промпты:** Генерация детальных заданий для нейросетей (Midjourney/DALL-E) для создания идеальных изображений товара.
* **Авто-претензии:** Генерация юридически грамотных жалоб на нарушителей.
* **Умный ответчик:** Автоматическая генерация ответов на отзывы покупателей.
### 2. 📊 Multi-account Dashboard
* Единое окно управления для неограниченного количества магазинов и юридических лиц.

View File

@@ -77,3 +77,19 @@ def ai_generate_reply(current_user_id):
from ..utils.ai_utils import generate_review_reply
text = generate_review_reply(review_text, rating)
return jsonify({"text": text})
@ai_blueprint.route('/ai/generate-card', methods=['POST'])
@token_required
def ai_generate_card(current_user_id):
"""
Генерация полной карточки товара
"""
data = request.json
title = data.get('title')
if not title:
return jsonify({"error": "Название товара обязательно"}), 400
from ..utils.ai_utils import generate_product_card
card_data = generate_product_card(title)
return jsonify(card_data)

View File

@@ -63,3 +63,35 @@ def generate_review_reply(review_text, rating):
return response.text.strip()
except Exception as e:
return f"Ошибка ИИ: {str(e)}"
def generate_product_card(title):
"""Генерирует описание и характеристики товара по его названию."""
api_key = os.getenv('GEMINI_API_KEY')
if not api_key:
return {"error": "API ключ не настроен."}
genai.configure(api_key=api_key)
model = genai.GenerativeModel('gemini-1.5-flash')
prompt = f"""
Ты - эксперт по листингу на маркетплейсах Ozon и Wildberries.
Тебе дано название товара: "{title}"
Твоя задача - сгенерировать контент для карточки товара в формате JSON.
JSON должен содержать:
1. "description": Продающее описание (3-4 абзаца), выделяющее преимущества.
2. "features": Список из 5-8 ключевых характеристик (ключ: значение).
3. "seo_tags": Список из 10 ключевых слов для поиска.
4. "image_prompts": 3 подробных промпта для нейросети (на английском), чтобы сгенерировать идеальные фото этого товара (главное фото, в интерьере, детали).
Ответ дай ТОЛЬКО в виде чистого JSON, без лишних слов.
"""
try:
response = model.generate_content(prompt)
import json
# Очистка от markdown-обертки если есть
clean_json = response.text.replace('```json', '').replace('```', '').strip()
return json.loads(clean_json)
except Exception as e:
return {"error": f"Ошибка при генерации карточки: {str(e)}"}

View File

@@ -50,6 +50,7 @@
<button class="tab-btn" data-target="seo-section"><i data-lucide="trending-up" class="icon-sm"></i> SEO</button>
<button class="tab-btn" data-target="content-section"><i data-lucide="image" class="icon-sm"></i> Контент</button>
<button class="tab-btn" data-target="finance-section"><i data-lucide="wallet" class="icon-sm"></i> Финансы</button>
<button class="tab-btn" data-target="generator-section"><i data-lucide="wand-2" class="icon-sm"></i> Генератор</button>
</div>
<main class="container">
@@ -313,6 +314,47 @@
</div>
</section>
<!-- Product Generator Section -->
<section id="generator-section" class="section hidden">
<h2>Умный генератор карточек товара</h2>
<div class="platforms-grid">
<div class="platform-card" style="grid-column: 1 / -1;">
<p style="margin-bottom: 1.5rem; color: var(--color-text-dim);">
Введите название товара, и ИИ подготовит описание, характеристики и промпты для генерации изображений.
</p>
<div style="display: flex; gap: 1rem; max-width: 800px;">
<input type="text" id="gen-title-input" placeholder="Например: Беспроводная кофемолка с керамическими жерновами" style="flex: 1;">
<button class="btn-primary" id="ai-gen-card-btn">
<i data-lucide="sparkles" class="icon-sm"></i> Создать карточку
</button>
</div>
</div>
</div>
<div id="gen-result-container" class="hidden" style="margin-top: 2rem; animation: fadeIn 0.4s;">
<div class="platforms-grid">
<!-- Description & SEO -->
<div class="platform-card" style="grid-column: 1 / 2;">
<h3>Продающее описание</h3>
<div id="gen-description" style="margin-top: 1rem; line-height: 1.6; color: var(--color-text-dim);"></div>
<h3 style="margin-top: 2rem;">SEO Теги</h3>
<div id="gen-tags" style="display: flex; flex-wrap: wrap; gap: 0.5rem; margin-top: 1rem;"></div>
</div>
<!-- Features & Image Prompts -->
<div class="platform-card" style="grid-column: 2 / -1;">
<h3>Технические характеристики</h3>
<table id="gen-features-table" class="table" style="margin-top: 1rem;">
<tbody></tbody>
</table>
<h3 style="margin-top: 2rem;">Промпты для ИИ-фото (DALL-E/Midjourney)</h3>
<div id="gen-image-prompts" style="margin-top: 1rem;"></div>
</div>
</div>
</div>
</section>
<!-- Integrations List -->
<section id="integrations-section" class="section hidden">
<h2>Доступные маркетплейсы</h2>

View File

@@ -272,10 +272,86 @@ function initTabs() {
if(target === 'seo-section') loadSEO();
if(target === 'content-section') loadReferences();
if(target === 'finance-section') { /* No initial load */ }
if(target === 'generator-section') { /* No initial load */ }
});
});
}
document.getElementById('ai-gen-card-btn').addEventListener('click', async () => {
const title = document.getElementById('gen-title-input').value;
if (!title) {
alert('Введите название товара');
return;
}
const btn = document.getElementById('ai-gen-card-btn');
const originalText = btn.innerHTML;
btn.disabled = true;
btn.innerHTML = '<i data-lucide="loader-2" class="icon-sm spin"></i> Магия ИИ в процессе...';
if (window.lucide) lucide.createIcons();
try {
const token = localStorage.getItem('token');
const res = await fetch('http://localhost:5000/api/ai/generate-card', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${token}`
},
body: JSON.stringify({ title })
});
const data = await res.json();
if (data.error) throw new Error(data.error);
document.getElementById('gen-result-container').classList.remove('hidden');
document.getElementById('gen-description').innerText = data.description;
// Tags
const tagsDiv = document.getElementById('gen-tags');
tagsDiv.innerHTML = '';
data.seo_tags.forEach(tag => {
const span = document.createElement('span');
span.className = 'status-pill';
span.style.background = 'rgba(255,255,255,0.1)';
span.innerText = `#${tag}`;
tagsDiv.appendChild(span);
});
// Features
const featuresTbody = document.querySelector('#gen-features-table tbody');
featuresTbody.innerHTML = '';
for (const [key, val] of Object.entries(data.features)) {
const tr = document.createElement('tr');
tr.innerHTML = `<td><strong>${key}</strong></td><td>${val}</td>`;
featuresTbody.appendChild(tr);
}
// Image Prompts
const promptsDiv = document.getElementById('gen-image-prompts');
promptsDiv.innerHTML = '';
data.image_prompts.forEach((p, i) => {
const pBox = document.createElement('div');
pBox.style.background = 'rgba(0,0,0,0.2)';
pBox.style.padding = '10px';
pBox.style.borderRadius = '8px';
pBox.style.marginBottom = '10px';
pBox.style.fontSize = '0.8rem';
pBox.innerHTML = `<strong>Вариант ${i+1}:</strong><br>${p}`;
promptsDiv.appendChild(pBox);
});
showToast('Карточка успешно сгенерирована!', 'success');
} catch (err) {
alert(err.message);
} finally {
btn.disabled = false;
btn.innerHTML = originalText;
if (window.lucide) lucide.createIcons();
}
});
document.getElementById('pnl-form').addEventListener('submit', async (e) => {
e.preventDefault();
const fd = new FormData(e.target);