feat: simplify SOP to immediate-effect configuration
This commit is contained in:
89
internal/run/rules.go
Normal file
89
internal/run/rules.go
Normal file
@@ -0,0 +1,89 @@
|
||||
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
|
||||
}
|
||||
Reference in New Issue
Block a user