package run import ( "encoding/json" "fmt" "git.iwork-ai.com/xdc/iqudo-top1/internal/model" "gorm.io/gorm" ) func deriveForScenario(db *gorm.DB, tenantID, scenarioID uint64, input map[string]interface{}) (map[string]interface{}, []string, error) { rules := make([]model.ScenarioRule, 0) if err := db.Where("tenant_id = ? AND scenario_id = ? AND status = ?", tenantID, scenarioID, "active").Order("priority, id").Find(&rules).Error; err != nil { return nil, nil, err } return applyScenarioRules(rules, input) } type ruleAction struct { Operation string `json:"operation"` Field string `json:"field"` Value interface{} `json:"value"` ValueFrom string `json:"value_from"` } func applyScenarioRules(rules []model.ScenarioRule, input map[string]interface{}) (map[string]interface{}, []string, error) { derived := map[string]interface{}{} matched := make([]string, 0) context := runtimeContext(input, derived, nil) for _, rule := range rules { ok, err := matchCondition(json.RawMessage(rule.Condition), context) if err != nil { return nil, nil, fmt.Errorf("规则 %s 条件不正确: %w", rule.RuleKey, err) } if !ok { continue } var actions []ruleAction if err := json.Unmarshal(rule.Actions, &actions); err != nil { return nil, nil, fmt.Errorf("规则 %s 动作不正确", rule.RuleKey) } for _, action := range actions { resolvedValues := []interface{}{action.Value} valueFromList := false if action.ValueFrom != "" { resolved, exists := lookupContextValue(context, action.ValueFrom) if !exists { continue } if list, ok := resolved.([]interface{}); ok { resolvedValues = list valueFromList = true } else { resolvedValues = []interface{}{resolved} } } switch action.Operation { case "set": if valueFromList { derived[action.Field] = resolvedValues } else if len(resolvedValues) == 1 { derived[action.Field] = resolvedValues[0] } else { derived[action.Field] = resolvedValues } case "append": targetValues, _ := derived[action.Field].([]interface{}) for _, value := range resolvedValues { duplicate := false for _, existing := range targetValues { if fmt.Sprint(existing) == fmt.Sprint(value) { duplicate = true break } } if !duplicate { targetValues = append(targetValues, value) } } derived[action.Field] = targetValues default: return nil, nil, fmt.Errorf("规则 %s 使用了不支持的动作", rule.RuleKey) } } matched = append(matched, rule.RuleKey) context = runtimeContext(input, derived, nil) } return derived, matched, nil }