.
This commit is contained in:
@@ -2506,10 +2506,11 @@ public class MarketingAnalysisService {
|
|||||||
report.put("detailLevel", detailLevelName);
|
report.put("detailLevel", detailLevelName);
|
||||||
report.put("fullAnalysis",
|
report.put("fullAnalysis",
|
||||||
processedTextReport != null ? processedTextReport : "Анализ не удалось сгенерировать.");
|
processedTextReport != null ? processedTextReport : "Анализ не удалось сгенерировать.");
|
||||||
report.put("summary",
|
|
||||||
processedTextReport != null ? processedTextReport : "Анализ не удалось сгенерировать."); // Keep for
|
// Извлекаем только первую секцию (I. Краткое резюме) для поля summary
|
||||||
// backward
|
// чтобы избежать дублирования полного текста отчета
|
||||||
// compatibility
|
String shortSummary = extractSummarySection(processedTextReport);
|
||||||
|
report.put("summary", shortSummary != null ? shortSummary : "Анализ не удалось сгенерировать.");
|
||||||
|
|
||||||
// Извлекаем данные из analysisJson вместо повторных вызовов AI
|
// Извлекаем данные из analysisJson вместо повторных вызовов AI
|
||||||
logger.info("generateMarketingReport: Extracting targetAudience from analysisJson");
|
logger.info("generateMarketingReport: Extracting targetAudience from analysisJson");
|
||||||
@@ -2944,6 +2945,59 @@ public class MarketingAnalysisService {
|
|||||||
return strategy;
|
return strategy;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Извлекает только первую секцию "I. Краткое резюме" из полного текстового
|
||||||
|
* отчета.
|
||||||
|
* Используется для поля summary, чтобы избежать дублирования полного текста.
|
||||||
|
*
|
||||||
|
* @param fullReport Полный текстовый отчет
|
||||||
|
* @return Текст только первой секции (краткое резюме)
|
||||||
|
*/
|
||||||
|
private String extractSummarySection(String fullReport) {
|
||||||
|
if (fullReport == null || fullReport.trim().isEmpty()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Ищем начало первой секции "I. Краткое резюме"
|
||||||
|
int startIndex = fullReport.indexOf("I. Краткое резюме");
|
||||||
|
if (startIndex == -1) {
|
||||||
|
// Если не нашли, пробуем найти просто "Краткое резюме"
|
||||||
|
startIndex = fullReport.indexOf("Краткое резюме");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (startIndex == -1) {
|
||||||
|
// Если нет секции резюме, возвращаем первые 500 символов
|
||||||
|
return fullReport.length() > 500
|
||||||
|
? fullReport.substring(0, 500) + "..."
|
||||||
|
: fullReport;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ищем начало второй секции "II."
|
||||||
|
int endIndex = fullReport.indexOf("II.", startIndex + 1);
|
||||||
|
if (endIndex == -1) {
|
||||||
|
// Пробуем найти "II. " с пробелом
|
||||||
|
endIndex = fullReport.indexOf("\nII. ", startIndex + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (endIndex == -1) {
|
||||||
|
// Если не нашли вторую секцию, возвращаем от начала до 1000 символов
|
||||||
|
int maxLength = Math.min(startIndex + 1000, fullReport.length());
|
||||||
|
return fullReport.substring(startIndex, maxLength).trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Извлекаем текст между I. и II.
|
||||||
|
return fullReport.substring(startIndex, endIndex).trim();
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.warn("extractSummarySection: Error extracting summary: {}", e.getMessage());
|
||||||
|
// В случае ошибки возвращаем первые 500 символов
|
||||||
|
return fullReport.length() > 500
|
||||||
|
? fullReport.substring(0, 500) + "..."
|
||||||
|
: fullReport;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private String buildMarkdownFromReport(Map<String, Object> reportData, MarketingAnalysisRequest request) {
|
private String buildMarkdownFromReport(Map<String, Object> reportData, MarketingAnalysisRequest request) {
|
||||||
logger.info("buildMarkdownFromReport: Starting markdown generation for product: {}", request.getProduct());
|
logger.info("buildMarkdownFromReport: Starting markdown generation for product: {}", request.getProduct());
|
||||||
logger.debug("buildMarkdownFromReport: ReportData keys: {}", reportData != null ? reportData.keySet() : "null");
|
logger.debug("buildMarkdownFromReport: ReportData keys: {}", reportData != null ? reportData.keySet() : "null");
|
||||||
@@ -3009,109 +3063,14 @@ public class MarketingAnalysisService {
|
|||||||
}
|
}
|
||||||
markdown.append("\n");
|
markdown.append("\n");
|
||||||
|
|
||||||
// Add additional sections from JSON analysis if available
|
// ВАЖНО: Секции "Позиционирование", "УТП", "Рекомендации по контенту" УДАЛЕНЫ,
|
||||||
@SuppressWarnings("unchecked")
|
// так как они уже включены в fullAnalysis (генерируется методом
|
||||||
Map<String, Object> analysisJson = (Map<String, Object>) reportData.get("analysisJson");
|
// generatePolishedTextReport)
|
||||||
if (analysisJson != null && !analysisJson.isEmpty()) {
|
// и вызывали дублирование контента в отчете
|
||||||
// Positioning section
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
Map<String, Object> positioning = (Map<String, Object>) analysisJson.get("positioning");
|
|
||||||
if (positioning != null) {
|
|
||||||
markdown.append("## Позиционирование\n\n");
|
|
||||||
if (positioning.containsKey("brandImage")) {
|
|
||||||
markdown.append("**Образ бренда:** ").append(positioning.get("brandImage")).append("\n\n");
|
|
||||||
}
|
|
||||||
if (positioning.containsKey("keyMessage")) {
|
|
||||||
markdown.append("**Ключевое сообщение:** ").append(positioning.get("keyMessage")).append("\n\n");
|
|
||||||
}
|
|
||||||
if (positioning.containsKey("toneOfVoice")) {
|
|
||||||
markdown.append("**Стиль коммуникации:** ").append(positioning.get("toneOfVoice")).append("\n\n");
|
|
||||||
}
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
List<String> trustFactors = (List<String>) positioning.get("trustFactors");
|
|
||||||
if (trustFactors != null && !trustFactors.isEmpty()) {
|
|
||||||
markdown.append("**Факторы доверия:**\n");
|
|
||||||
for (String factor : trustFactors) {
|
|
||||||
markdown.append("- ").append(factor).append("\n");
|
|
||||||
}
|
|
||||||
markdown.append("\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Value Proposition section
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
Map<String, Object> valueProposition = (Map<String, Object>) analysisJson.get("valueProposition");
|
|
||||||
if (valueProposition != null) {
|
|
||||||
markdown.append("## Уникальное торговое предложение (УТП)\n\n");
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
List<String> utpVariants = (List<String>) valueProposition.get("utpVariants");
|
|
||||||
if (utpVariants != null && !utpVariants.isEmpty()) {
|
|
||||||
markdown.append("**Варианты УТП:**\n");
|
|
||||||
for (String utp : utpVariants) {
|
|
||||||
markdown.append("- ").append(utp).append("\n");
|
|
||||||
}
|
|
||||||
markdown.append("\n");
|
|
||||||
}
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
List<String> mainBenefits = (List<String>) valueProposition.get("mainBenefits");
|
|
||||||
if (mainBenefits != null && !mainBenefits.isEmpty()) {
|
|
||||||
markdown.append("**Основные преимущества:**\n");
|
|
||||||
for (String benefit : mainBenefits) {
|
|
||||||
markdown.append("- ").append(benefit).append("\n");
|
|
||||||
}
|
|
||||||
markdown.append("\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Content Recommendations section
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
Map<String, Object> contentRecommendations = (Map<String, Object>) analysisJson
|
|
||||||
.get("contentRecommendations");
|
|
||||||
if (contentRecommendations != null) {
|
|
||||||
markdown.append("## Рекомендации по контенту\n\n");
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
List<String> salesContent = (List<String>) contentRecommendations.get("salesContent");
|
|
||||||
if (salesContent != null && !salesContent.isEmpty()) {
|
|
||||||
markdown.append("### Продающий контент:\n");
|
|
||||||
for (String content : salesContent) {
|
|
||||||
markdown.append("- ").append(content).append("\n");
|
|
||||||
}
|
|
||||||
markdown.append("\n");
|
|
||||||
}
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
List<String> expertContent = (List<String>) contentRecommendations.get("expertContent");
|
|
||||||
if (expertContent != null && !expertContent.isEmpty()) {
|
|
||||||
markdown.append("### Экспертный контент:\n");
|
|
||||||
for (String content : expertContent) {
|
|
||||||
markdown.append("- ").append(content).append("\n");
|
|
||||||
}
|
|
||||||
markdown.append("\n");
|
|
||||||
}
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
List<String> trustContent = (List<String>) contentRecommendations.get("trustContent");
|
|
||||||
if (trustContent != null && !trustContent.isEmpty()) {
|
|
||||||
markdown.append("### Доверительный контент:\n");
|
|
||||||
for (String content : trustContent) {
|
|
||||||
markdown.append("- ").append(content).append("\n");
|
|
||||||
}
|
|
||||||
markdown.append("\n");
|
|
||||||
}
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
List<String> entertainmentContent = (List<String>) contentRecommendations.get("entertainmentContent");
|
|
||||||
if (entertainmentContent != null && !entertainmentContent.isEmpty()) {
|
|
||||||
markdown.append("### Развлекательный контент:\n");
|
|
||||||
for (String content : entertainmentContent) {
|
|
||||||
markdown.append("- ").append(content).append("\n");
|
|
||||||
}
|
|
||||||
markdown.append("\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Display full analysis - это основной блок с полным отчетом
|
// Display full analysis - это основной блок с полным отчетом
|
||||||
// Секции "Целевая аудитория", "Рекомендации", "Стратегия" уже включены в
|
// Все секции (I-XI) уже включены в fullAnalysis благодаря
|
||||||
// fullAnalysis
|
// generatePolishedTextReport
|
||||||
// благодаря методу generatePolishedTextReport, поэтому не дублируем их
|
|
||||||
String fullAnalysis = (String) reportData.get("fullAnalysis");
|
String fullAnalysis = (String) reportData.get("fullAnalysis");
|
||||||
if (fullAnalysis != null && !fullAnalysis.trim().isEmpty()) {
|
if (fullAnalysis != null && !fullAnalysis.trim().isEmpty()) {
|
||||||
// Получаем данные для графиков и заменяем плейсхолдеры
|
// Получаем данные для графиков и заменяем плейсхолдеры
|
||||||
@@ -3119,20 +3078,17 @@ public class MarketingAnalysisService {
|
|||||||
Map<String, Object> chartsData = (Map<String, Object>) reportData.get("chartsData");
|
Map<String, Object> chartsData = (Map<String, Object>) reportData.get("chartsData");
|
||||||
String processedAnalysis = replaceChartPlaceholders(fullAnalysis, chartsData);
|
String processedAnalysis = replaceChartPlaceholders(fullAnalysis, chartsData);
|
||||||
|
|
||||||
markdown.append("## Полный маркетинговый анализ\n\n");
|
// Добавляем полный отчет без дополнительного заголовка,
|
||||||
|
// так как fullAnalysis уже начинается с "I. Краткое резюме"
|
||||||
markdown.append(processedAnalysis).append("\n\n");
|
markdown.append(processedAnalysis).append("\n\n");
|
||||||
} else {
|
} else {
|
||||||
// Fallback to summary if fullAnalysis is not available
|
// Fallback to summary if fullAnalysis is not available
|
||||||
String summary = (String) reportData.get("summary");
|
String summary = (String) reportData.get("summary");
|
||||||
if (summary != null && !summary.trim().isEmpty()) {
|
if (summary != null && !summary.trim().isEmpty()) {
|
||||||
markdown.append("## Комплексный маркетинговый анализ\n\n");
|
|
||||||
markdown.append(summary).append("\n\n");
|
markdown.append(summary).append("\n\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Секции targetAudience, recommendations, strategy УДАЛЕНЫ,
|
|
||||||
// так как они уже включены в fullAnalysis и вызывали дублирование
|
|
||||||
|
|
||||||
return markdown.toString();
|
return markdown.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user