.
This commit is contained in:
@@ -2506,10 +2506,11 @@ public class MarketingAnalysisService {
|
||||
report.put("detailLevel", detailLevelName);
|
||||
report.put("fullAnalysis",
|
||||
processedTextReport != null ? processedTextReport : "Анализ не удалось сгенерировать.");
|
||||
report.put("summary",
|
||||
processedTextReport != null ? processedTextReport : "Анализ не удалось сгенерировать."); // Keep for
|
||||
// backward
|
||||
// compatibility
|
||||
|
||||
// Извлекаем только первую секцию (I. Краткое резюме) для поля summary
|
||||
// чтобы избежать дублирования полного текста отчета
|
||||
String shortSummary = extractSummarySection(processedTextReport);
|
||||
report.put("summary", shortSummary != null ? shortSummary : "Анализ не удалось сгенерировать.");
|
||||
|
||||
// Извлекаем данные из analysisJson вместо повторных вызовов AI
|
||||
logger.info("generateMarketingReport: Extracting targetAudience from analysisJson");
|
||||
@@ -2944,6 +2945,59 @@ public class MarketingAnalysisService {
|
||||
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) {
|
||||
logger.info("buildMarkdownFromReport: Starting markdown generation for product: {}", request.getProduct());
|
||||
logger.debug("buildMarkdownFromReport: ReportData keys: {}", reportData != null ? reportData.keySet() : "null");
|
||||
@@ -3009,109 +3063,14 @@ public class MarketingAnalysisService {
|
||||
}
|
||||
markdown.append("\n");
|
||||
|
||||
// Add additional sections from JSON analysis if available
|
||||
@SuppressWarnings("unchecked")
|
||||
Map<String, Object> analysisJson = (Map<String, Object>) reportData.get("analysisJson");
|
||||
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");
|
||||
}
|
||||
}
|
||||
}
|
||||
// ВАЖНО: Секции "Позиционирование", "УТП", "Рекомендации по контенту" УДАЛЕНЫ,
|
||||
// так как они уже включены в fullAnalysis (генерируется методом
|
||||
// generatePolishedTextReport)
|
||||
// и вызывали дублирование контента в отчете
|
||||
|
||||
// Display full analysis - это основной блок с полным отчетом
|
||||
// Секции "Целевая аудитория", "Рекомендации", "Стратегия" уже включены в
|
||||
// fullAnalysis
|
||||
// благодаря методу generatePolishedTextReport, поэтому не дублируем их
|
||||
// Все секции (I-XI) уже включены в fullAnalysis благодаря
|
||||
// generatePolishedTextReport
|
||||
String fullAnalysis = (String) reportData.get("fullAnalysis");
|
||||
if (fullAnalysis != null && !fullAnalysis.trim().isEmpty()) {
|
||||
// Получаем данные для графиков и заменяем плейсхолдеры
|
||||
@@ -3119,20 +3078,17 @@ public class MarketingAnalysisService {
|
||||
Map<String, Object> chartsData = (Map<String, Object>) reportData.get("chartsData");
|
||||
String processedAnalysis = replaceChartPlaceholders(fullAnalysis, chartsData);
|
||||
|
||||
markdown.append("## Полный маркетинговый анализ\n\n");
|
||||
// Добавляем полный отчет без дополнительного заголовка,
|
||||
// так как fullAnalysis уже начинается с "I. Краткое резюме"
|
||||
markdown.append(processedAnalysis).append("\n\n");
|
||||
} else {
|
||||
// Fallback to summary if fullAnalysis is not available
|
||||
String summary = (String) reportData.get("summary");
|
||||
if (summary != null && !summary.trim().isEmpty()) {
|
||||
markdown.append("## Комплексный маркетинговый анализ\n\n");
|
||||
markdown.append(summary).append("\n\n");
|
||||
}
|
||||
}
|
||||
|
||||
// Секции targetAudience, recommendations, strategy УДАЛЕНЫ,
|
||||
// так как они уже включены в fullAnalysis и вызывали дублирование
|
||||
|
||||
return markdown.toString();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user