Files
iqudo-top1/internal/run/start_presentation.go
2026-08-18 16:27:02 +08:00

161 lines
4.6 KiB
Go

package run
import (
"encoding/json"
"fmt"
"git.iwork-ai.com/xdc/iqudo-top1/internal/model"
"gorm.io/gorm"
)
type NodePresentation struct {
Summary []PresentationField `json:"summary"`
Items []PresentationItem `json:"items"`
Opening *PresentationCopy `json:"opening,omitempty"`
}
type PresentationField struct {
Key string `json:"key"`
Label string `json:"label"`
Kind string `json:"kind"`
Value interface{} `json:"value"`
}
type PresentationItem struct {
Fields []PresentationField `json:"fields"`
}
type PresentationCopy struct {
Title string `json:"title"`
Content string `json:"content"`
}
type startNodeConfig struct {
Presentation *startPresentationConfig `json:"presentation"`
}
type startPresentationConfig struct {
SummaryFieldKeys []string `json:"summary_field_keys"`
ItemFieldKeys []string `json:"item_field_keys"`
ImageFieldKeys []string `json:"image_field_keys"`
OpeningTitle string `json:"opening_title"`
OpeningTemplate string `json:"opening_template"`
}
func loadStartPresentation(db *gorm.DB, node model.SOPNode, tenantID uint64, context map[string]interface{}) (*NodePresentation, error) {
var config startNodeConfig
if err := json.Unmarshal(node.Config, &config); err != nil {
return nil, err
}
if config.Presentation == nil {
return nil, nil
}
keys := append([]string{}, config.Presentation.SummaryFieldKeys...)
keys = append(keys, config.Presentation.ItemFieldKeys...)
fields := make([]model.ScenarioField, 0)
if len(keys) > 0 {
if err := db.Table("scenario_fields sf").Select("sf.*").
Joins("JOIN sops s ON s.scenario_id = sf.scenario_id").
Joins("JOIN sop_versions sv ON sv.sop_id = s.id").
Where("sv.id = ? AND sf.tenant_id = ? AND sf.field_key IN ?", node.SOPVersionID, tenantID, keys).
Find(&fields).Error; err != nil {
return nil, err
}
}
byKey := make(map[string]model.ScenarioField, len(fields))
for _, field := range fields {
byKey[field.FieldKey] = field
}
return buildStartPresentation(*config.Presentation, byKey, context), nil
}
func buildStartPresentation(config startPresentationConfig, fields map[string]model.ScenarioField, context map[string]interface{}) *NodePresentation {
view := &NodePresentation{Summary: []PresentationField{}, Items: []PresentationItem{}}
imageKeys := make(map[string]bool, len(config.ImageFieldKeys))
for _, key := range config.ImageFieldKeys {
imageKeys[key] = true
}
for _, key := range config.SummaryFieldKeys {
value, ok := lookupContextValue(context, "input."+key)
if !ok || presentationValueEmpty(value) {
continue
}
view.Summary = append(view.Summary, presentationField(key, value, fields, imageKeys))
}
itemValues := make(map[string][]interface{}, len(config.ItemFieldKeys))
itemCount := 0
for _, key := range config.ItemFieldKeys {
value, _ := lookupContextValue(context, "input."+key)
values := presentationValues(value)
itemValues[key] = values
if len(values) > itemCount {
itemCount = len(values)
}
}
for index := 0; index < itemCount; index++ {
item := PresentationItem{Fields: []PresentationField{}}
for _, key := range config.ItemFieldKeys {
values := itemValues[key]
if index >= len(values) || presentationValueEmpty(values[index]) {
continue
}
item.Fields = append(item.Fields, presentationField(key, values[index], fields, imageKeys))
}
if len(item.Fields) > 0 {
view.Items = append(view.Items, item)
}
}
if config.OpeningTemplate != "" {
title := config.OpeningTitle
if title == "" {
title = "开场话术"
}
view.Opening = &PresentationCopy{Title: title, Content: fmt.Sprint(renderKnowledgeValue(config.OpeningTemplate, context))}
}
return view
}
func presentationField(key string, value interface{}, fields map[string]model.ScenarioField, imageKeys map[string]bool) PresentationField {
label := key
if field, ok := fields[key]; ok && field.FieldName != "" {
label = field.FieldName
}
kind := "text"
if imageKeys[key] {
kind = "image"
}
return PresentationField{Key: key, Label: label, Kind: kind, Value: value}
}
func presentationValues(value interface{}) []interface{} {
switch values := value.(type) {
case []interface{}:
return values
case []string:
result := make([]interface{}, 0, len(values))
for _, item := range values {
result = append(result, item)
}
return result
case nil:
return nil
default:
return []interface{}{value}
}
}
func presentationValueEmpty(value interface{}) bool {
switch typed := value.(type) {
case nil:
return true
case string:
return typed == ""
case []interface{}:
return len(typed) == 0
case []string:
return len(typed) == 0
default:
return false
}
}