From 8d749cf53c5eac0359cc8118652701e11f135dfa Mon Sep 17 00:00:00 2001 From: root Date: Wed, 10 Dec 2025 19:05:55 +0500 Subject: [PATCH] . --- fix.md | 68 +++++++++++++++++++ frontend-chart-rendering.md | 42 ++++++++++++ .../service/MarketingAnalysisService.java | 2 + 3 files changed, 112 insertions(+) create mode 100644 fix.md create mode 100644 frontend-chart-rendering.md diff --git a/fix.md b/fix.md new file mode 100644 index 0000000..2002bdd --- /dev/null +++ b/fix.md @@ -0,0 +1,68 @@ +Я внимательно изучил поле `fullAnalysis` в присланном JSON. Там всё ещё обычный текст и списки, а не Markdown-блоки с JSON. + +**Вот пример того, что мы видим сейчас (в `fullAnalysis`):** + +```markdown +## VIII. Воронка спроса + +Воронка продаж показывает следующие этапы: + +- Охват: 1000 +- Вовлечённость: 300 (30%) + ... +``` + +**А должны были увидеть (согласно плану):** + +````markdown +## VIII. Воронка спроса + +```json:conversionFunnel +[ + { "stage": "Охват", "value": 1000, "conversion": 0 }, + ... +] +``` +```` + +```` + +--- + +### Почему так произошло? + +Проблема в архитектуре метода `processAnalysis` в вашем Java-коде. + +1. Вы изменили метод `buildMarkdownFromReport`, и он, скорее всего, работает правильно и генерирует строку с JSON-блоками. +2. **НО** эта строка (`markdownContent`) используется **только для генерации PDF**. +3. В базу данных и во фронтенд (в поле `reportData`) сохраняется старая версия текста, сгенерированная AI (Промпт №2), которая не знает о нашей новой логике встраивания графиков. + +### Как исправить? + +Нам нужно сказать Cursor'у, чтобы он **перезаписал** поле `fullAnalysis` внутри `reportData` тем Markdown-контентом, который генерирует метод `buildMarkdownFromReport`. + +**Промпт для Cursor (отправь это, чтобы починить):** + +```text +Я не вижу изменений в JSON-ответе для фронтенда. Проблема в методе `processAnalysis` класса `MarketingAnalysisService`. + +Сейчас переменная `markdownContent` (результат метода `buildMarkdownFromReport`) используется только для генерации PDF. +А в `analysis.setReportData(reportData)` попадает старый текст, сгенерированный AI. + +Пожалуйста, сделай следующее изменение в методе `processAnalysis`: + +1. После вызова: + String markdownContent = buildMarkdownFromReport(reportData, request); + +2. Добавь строку, которая обновляет reportData: + reportData.put("fullAnalysis", markdownContent); + +Это нужно, чтобы фронтенд получал именно сформированный Markdown с JSON-блоками (charts), а не просто текст от AI. +```` + +### Что произойдет после этого исправления: + +1. Backend сгенерирует Markdown с JSON-блоками. +2. Этот Markdown сохранится в базу данных как `fullAnalysis`. +3. Фронтенд получит JSON, где внутри поля `report.fullAnalysis` будут блоки кода ` ```json:seasonality... `. +4. Твой кастомный рендерер на фронтенде (о котором я писал выше) увидит эти блоки и нарисует графики. diff --git a/frontend-chart-rendering.md b/frontend-chart-rendering.md new file mode 100644 index 0000000..11c4f73 --- /dev/null +++ b/frontend-chart-rendering.md @@ -0,0 +1,42 @@ +## Frontend notes: rendering chart JSON blocks + +- Markdown now emits chart data as fenced code blocks with language tags like `json:seasonality`, `json:competitors`, `json:audienceSegmentation`, `json:channelsPotential`, and `json:funnel`. +- Each block is pretty-printed JSON; parse the string inside the fence to feed the relevant chart component. +- Headings stay the same; only tables were replaced by these code fences. + +### Expected shapes + +- `seasonality` – object map: `{ "Январь": 70, "Февраль": 60, ... }`. +- `competitors` – array of objects: `{ name, reach, activity, reviews, strengths, weaknesses }`. +- `audienceSegmentation` – object with optional arrays: `ageGroups[]`, `genders[]`, `segments[]`, each item `{ label, value }`. +- `channelsPotential` – array of objects: `{ name, potential, justification }`. +- `funnel` – array of objects: `{ stage, value, conversion }`. + +### Rendering hook (React + react-markdown) + +```javascript +components={{ + code({ node, inline, className, children, ...props }) { + const match = /language-(\w+):([\w-]+)/.exec(className || ""); + if (!inline && match && match[1] === "json") { + const chartType = match[2]; + const data = JSON.parse(String(children).replace(/\n$/, "")); + switch (chartType) { + case "seasonality": return ; + case "competitors": return ; + case "audienceSegmentation": return ; + case "channelsPotential": return ; + case "funnel": return ; + default: return
{children}
; + } + } + return {children}; + } +}} +``` + +### Tips + +- Trim trailing newline before `JSON.parse` to avoid parse errors. +- Keep a safe fallback (`
`) for unknown chart types.
+- If using another markdown renderer, ensure it preserves the code fence language string in a similar `json:` format.
diff --git a/src/main/java/kz/konturai/parser/service/MarketingAnalysisService.java b/src/main/java/kz/konturai/parser/service/MarketingAnalysisService.java
index 529708e..545f740 100644
--- a/src/main/java/kz/konturai/parser/service/MarketingAnalysisService.java
+++ b/src/main/java/kz/konturai/parser/service/MarketingAnalysisService.java
@@ -99,6 +99,8 @@ public class MarketingAnalysisService {
 
             // Generate markdown content for PDF
             String markdownContent = buildMarkdownFromReport(reportData, request);
+            // Save markdown content into report data so frontend gets JSON code blocks
+            reportData.put("fullAnalysis", markdownContent);
 
             // Generate PDF
             byte[] pdfBytes = researchPdfService.generatePdfReport(