diff --git a/pkg/service/ai/video_vl.go b/pkg/service/ai/video_vl.go index 3150b8ec..10615605 100644 --- a/pkg/service/ai/video_vl.go +++ b/pkg/service/ai/video_vl.go @@ -1,6 +1,7 @@ package ai import ( + "encoding/json" "errors" "fmt" "fonchain-fiee/pkg/common/qwen" @@ -74,6 +75,93 @@ type CompetitorReportRequest struct { type CompetitorReportResponse struct { ImageURL string `json:"image_url,omitempty"` // 生成的图片URL(1024*1024),非必须返回 Text string `json:"text,omitempty"` // 竞品报告文本内容,非必须返回 + JSON string `json:"json,omitempty"` // 竞品报告JSON格式,非必须返回 +} + +// CompetitorReportJSON AI返回的JSON结构 +type CompetitorReportJSON struct { + HighlightAnalysis HighlightAnalysis `json:"highlight_analysis"` + DataPerformance DataPerformance `json:"data_performance_analysis"` + OverallSummary string `json:"overall_summary_and_optimization"` +} + +type HighlightAnalysis struct { + Summary string `json:"summary"` + Points Points `json:"points"` +} + +type Points struct { + Theme string `json:"theme"` + Narrative string `json:"narrative"` + Content string `json:"content"` + Copywriting string `json:"copywriting"` + Data string `json:"data"` + Music string `json:"music,omitempty"` +} + +type DataPerformance struct { + Views string `json:"views"` + Completion string `json:"completion_rate,omitempty"` + Engagement string `json:"engagement"` +} + +// convertJSONToText 将 JSON 转换为纯文本格式 +func convertJSONToText(data CompetitorReportJSON, isVideo bool) string { + var sb strings.Builder + + // 一、亮点表现分析 + sb.WriteString("一、亮点表现分析\n") + sb.WriteString(data.HighlightAnalysis.Summary) + sb.WriteString("\n\n") + + sb.WriteString("1. 标题亮点:") + sb.WriteString(data.HighlightAnalysis.Points.Theme) + sb.WriteString("\n") + + sb.WriteString("2. 题材亮点:") + sb.WriteString(data.HighlightAnalysis.Points.Narrative) + sb.WriteString("\n") + + sb.WriteString("3. 内容亮点:") + sb.WriteString(data.HighlightAnalysis.Points.Content) + sb.WriteString("\n") + + sb.WriteString("4. 文案亮点:") + sb.WriteString(data.HighlightAnalysis.Points.Copywriting) + sb.WriteString("\n") + + sb.WriteString("5. 数据亮点:") + sb.WriteString(data.HighlightAnalysis.Points.Data) + sb.WriteString("\n") + + if isVideo && data.HighlightAnalysis.Points.Music != "" { + sb.WriteString("6. 配乐亮点:") + sb.WriteString(data.HighlightAnalysis.Points.Music) + sb.WriteString("\n") + } + + // 二、数据表现分析 + sb.WriteString("\n二、数据表现分析\n") + sb.WriteString("1. 浏览量表现:") + sb.WriteString(data.DataPerformance.Views) + sb.WriteString("\n") + + if isVideo && data.DataPerformance.Completion != "" { + sb.WriteString("2. 完播率表现:") + sb.WriteString(data.DataPerformance.Completion) + sb.WriteString("\n") + sb.WriteString("3. 点赞/分享/评论表现:") + } else { + sb.WriteString("2. 点赞/分享/评论表现:") + } + sb.WriteString(data.DataPerformance.Engagement) + sb.WriteString("\n") + + // 三、整体总结及可优化建议 + sb.WriteString("\n三、整体总结及可优化建议\n") + sb.WriteString(data.OverallSummary) + + return sb.String() } // AICompetitorReport 生成竞品报告接口 @@ -303,7 +391,16 @@ func AICompetitorReport(ctx *gin.Context) { // 返回结果(只返回实际生成的内容) result := CompetitorReportResponse{} if needText { - result.Text = textRes.text + result.JSON = textRes.text // JSON 字段直接返回 AI 生成的 JSON + + // 将 JSON 解析并转换为纯文本 + var jsonData CompetitorReportJSON + if err := json.Unmarshal([]byte(textRes.text), &jsonData); err != nil { + // 如果解析失败,回退使用原始文本 + result.Text = textRes.text + } else { + result.Text = convertJSONToText(jsonData, len(req.Videos) > 0) + } } if needImage { result.ImageURL = imageRes.imageURL