thread-master/backend/internal/library/outreach/draft_context.go

108 lines
3.3 KiB
Go
Raw Permalink Normal View History

package outreach
import (
"fmt"
"strings"
libkg "haixun-backend/internal/library/knowledge"
libplacement "haixun-backend/internal/library/placement"
brandentity "haixun-backend/internal/model/brand/domain/entity"
branddomain "haixun-backend/internal/model/brand/domain/usecase"
scanpostusecase "haixun-backend/internal/model/scan_post/domain/usecase"
)
func FindGraphNode(nodes []libkg.Node, nodeID string) *libkg.Node {
nodeID = strings.TrimSpace(nodeID)
if nodeID == "" {
return nil
}
for i := range nodes {
if nodes[i].ID == nodeID {
return &nodes[i]
}
}
return nil
}
func BuildPlacementReason(post *scanpostusecase.ScanPostSummary) string {
if post == nil {
return ""
}
parts := []string{}
if post.Priority == "gold" {
parts = append(parts, "雙軌命中(相關+近期)")
} else if post.Priority == "recent" {
parts = append(parts, "近期軌命中")
}
if post.SolvedByProduct {
parts = append(parts, "產品可解此需求")
}
if post.ProductFitScore > 0 {
parts = append(parts, fmt.Sprintf("產品匹配 %d", post.ProductFitScore))
}
return strings.Join(parts, "")
}
func MergePlacementReason(base string, node *libkg.Node, post *scanpostusecase.ScanPostSummary) string {
parts := []string{}
if strings.TrimSpace(base) != "" {
parts = append(parts, strings.TrimSpace(base))
}
if node != nil {
if strings.TrimSpace(node.PlacementValue) != "" {
parts = append(parts, "置入價值 "+strings.TrimSpace(node.PlacementValue))
}
if node.ProductFitScore > 0 && (post == nil || post.ProductFitScore == 0) {
parts = append(parts, fmt.Sprintf("節點產品匹配 %d", node.ProductFitScore))
}
}
return strings.Join(parts, "")
}
func ProductBriefForBrand(brand *branddomain.BrandSummary, productID, searchTag, postText string) string {
if brand == nil {
return ""
}
if product := PickProductForOutreach(brand, productID, searchTag, postText); product != nil {
merged := libplacement.BuildMergedProductContext(brand.DisplayName, product.ProductContext, product.Label)
merged = libplacement.ApplyPlacementURL(merged, product.PlacementURL)
if pb := libplacement.ProductBriefFromContext(merged); pb != "" {
return pb
}
}
if pb := libplacement.ProductBriefFromContext(brand.ProductContext); pb != "" {
return pb
}
return strings.TrimSpace(brand.ProductBrief)
}
func PickProductForOutreach(brand *branddomain.BrandSummary, preferredProductID, searchTag, postText string) *branddomain.ProductSummary {
if brand == nil || len(brand.Products) == 0 {
return nil
}
entities := make([]brandentity.Product, len(brand.Products))
for i := range brand.Products {
entities[i] = brandentity.Product{
ID: brand.Products[i].ID,
Label: brand.Products[i].Label,
ProductContext: brand.Products[i].ProductContext,
MatchTags: append([]string(nil), brand.Products[i].MatchTags...),
}
}
if picked := libplacement.RecommendProductForPost(entities, searchTag, postText, preferredProductID); picked != nil {
for i := range brand.Products {
if brand.Products[i].ID == picked.ID {
return &brand.Products[i]
}
}
}
if id := strings.TrimSpace(preferredProductID); id != "" {
for i := range brand.Products {
if brand.Products[i].ID == id {
return &brand.Products[i]
}
}
}
return &brand.Products[0]
}