2026-05-18 19:19:17 +08:00
|
|
|
|
package util
|
|
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
|
"encoding/json"
|
2026-05-23 18:08:09 +08:00
|
|
|
|
"strconv"
|
2026-05-18 19:19:17 +08:00
|
|
|
|
|
|
|
|
|
|
"github.com/gogf/gf/v2/container/gvar"
|
2026-05-29 17:54:19 +08:00
|
|
|
|
gfgjson "github.com/gogf/gf/v2/encoding/gjson"
|
2026-05-18 19:19:17 +08:00
|
|
|
|
"github.com/gogf/gf/v2/util/gconv"
|
2026-05-23 18:08:09 +08:00
|
|
|
|
tGjson "github.com/tidwall/gjson"
|
|
|
|
|
|
"github.com/tidwall/sjson"
|
2026-05-18 19:19:17 +08:00
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
// ConvertToMessages 将原始数据转换为消息列表
|
|
|
|
|
|
func ConvertToMessages(raw any) []map[string]any {
|
|
|
|
|
|
if raw == nil {
|
|
|
|
|
|
return nil
|
|
|
|
|
|
}
|
2026-05-20 11:36:39 +08:00
|
|
|
|
|
2026-05-29 17:54:19 +08:00
|
|
|
|
j := gfgjson.New(raw)
|
|
|
|
|
|
messages := j.Get("messages")
|
|
|
|
|
|
if !messages.IsNil() {
|
|
|
|
|
|
return gconv.Maps(messages.Val())
|
2026-05-18 19:19:17 +08:00
|
|
|
|
}
|
2026-05-20 11:36:39 +08:00
|
|
|
|
return []map[string]any{j.Map()}
|
2026-05-18 19:19:17 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// FormToJSON 将表单数据转换为 JSON 字符串
|
2026-05-29 17:54:19 +08:00
|
|
|
|
func FormToJSON(form []map[string]any) string {
|
2026-05-18 19:19:17 +08:00
|
|
|
|
if form == nil {
|
2026-05-29 17:54:19 +08:00
|
|
|
|
return "[]"
|
2026-05-18 19:19:17 +08:00
|
|
|
|
}
|
|
|
|
|
|
b, _ := json.Marshal(form)
|
|
|
|
|
|
return string(b)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-05-20 11:36:39 +08:00
|
|
|
|
// UserFormToJSON 将用户表单数据转换为 JSON 字符串
|
|
|
|
|
|
func UserFormToJSON(form []map[string]any) string {
|
|
|
|
|
|
if form == nil {
|
2026-05-18 19:19:17 +08:00
|
|
|
|
return "{}"
|
|
|
|
|
|
}
|
2026-05-20 11:36:39 +08:00
|
|
|
|
|
|
|
|
|
|
b, _ := json.Marshal(form)
|
2026-05-18 19:19:17 +08:00
|
|
|
|
return string(b)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-05-23 18:08:09 +08:00
|
|
|
|
// MustMarshalToMap 将对象序列化为 map[string]any,失败时返回空 map
|
|
|
|
|
|
func MustMarshalToMap(v any) map[string]any {
|
2026-05-20 11:36:39 +08:00
|
|
|
|
b, err := json.Marshal(v)
|
|
|
|
|
|
if err != nil {
|
2026-05-23 18:08:09 +08:00
|
|
|
|
return make(map[string]any)
|
2026-05-18 19:19:17 +08:00
|
|
|
|
}
|
2026-05-23 18:08:09 +08:00
|
|
|
|
var m map[string]any
|
|
|
|
|
|
json.Unmarshal(b, &m)
|
|
|
|
|
|
return m
|
2026-05-18 19:19:17 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// JSONPretty 将任意类型转为格式化的 JSON 字符串
|
|
|
|
|
|
func JSONPretty(v any) string {
|
|
|
|
|
|
if gv, ok := v.(*gvar.Var); ok {
|
|
|
|
|
|
v = gconv.Map(gv.String())
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
var tmp map[string]any
|
|
|
|
|
|
if err := gconv.Struct(v, &tmp); err != nil {
|
|
|
|
|
|
return gconv.String(v)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
b, _ := json.MarshalIndent(tmp, "", " ")
|
|
|
|
|
|
return string(b)
|
|
|
|
|
|
}
|
2026-05-20 11:36:39 +08:00
|
|
|
|
|
|
|
|
|
|
// ParseJSONFieldFromGvar 专门处理 *gvar.Var 类型的 JSON 字段解析
|
|
|
|
|
|
func ParseJSONFieldFromGvar(source any, target any) {
|
|
|
|
|
|
if source == nil {
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
switch v := source.(type) {
|
|
|
|
|
|
case *gvar.Var:
|
|
|
|
|
|
if v.IsNil() {
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 尝试获取 map
|
|
|
|
|
|
if m := v.Map(); len(m) > 0 {
|
|
|
|
|
|
data, _ := json.Marshal(m)
|
|
|
|
|
|
json.Unmarshal(data, target)
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 尝试解析 JSON 字符串
|
|
|
|
|
|
str := v.String()
|
|
|
|
|
|
if str != "" && str != "<nil>" {
|
|
|
|
|
|
json.Unmarshal([]byte(str), target)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
|
// 其他类型走原来的逻辑
|
|
|
|
|
|
data, _ := json.Marshal(source)
|
|
|
|
|
|
json.Unmarshal(data, target)
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2026-05-23 18:08:09 +08:00
|
|
|
|
|
|
|
|
|
|
// MergeConsult 将 consult 附件合并到模型生成的 messages 结构中。
|
|
|
|
|
|
//
|
|
|
|
|
|
// 参数说明:
|
|
|
|
|
|
// - req: 请求参数 map,需包含 "consult" 字段,值为 []any,每个元素是 {"type":"xxx","url":"..."}
|
|
|
|
|
|
// - messages: 模型生成的返回结构(如 rounds[...].messages[...].content 数组)
|
|
|
|
|
|
// - extendMapping: 附加映射配置,格式:
|
|
|
|
|
|
// {"attachments": {"image": {"template": {...}, "target_path": "...", "field_mapping": {...}}, ...}}
|
|
|
|
|
|
//
|
|
|
|
|
|
// 返回值:合并后的完整 map。
|
|
|
|
|
|
func MergeConsult(req map[string]any, messages map[string]any, extendMapping map[string]any) map[string]any {
|
|
|
|
|
|
if len(req) == 0 || len(messages) == 0 || len(extendMapping) == 0 {
|
|
|
|
|
|
return messages
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
reqJSON, _ := json.Marshal(req)
|
|
|
|
|
|
msgJSON, _ := json.Marshal(messages)
|
|
|
|
|
|
extJSON, _ := json.Marshal(extendMapping)
|
|
|
|
|
|
|
|
|
|
|
|
reqStr := string(reqJSON)
|
|
|
|
|
|
msgStr := string(msgJSON)
|
|
|
|
|
|
extStr := string(extJSON)
|
|
|
|
|
|
|
|
|
|
|
|
// 获取 consult 数组
|
|
|
|
|
|
consultResult := tGjson.Get(reqStr, "consult")
|
|
|
|
|
|
if !consultResult.Exists() || !consultResult.IsArray() {
|
|
|
|
|
|
return messages
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 获取 attachments 配置
|
|
|
|
|
|
attachmentsResult := tGjson.Get(extStr, "attachments")
|
|
|
|
|
|
if !attachmentsResult.Exists() || !attachmentsResult.IsObject() {
|
|
|
|
|
|
return messages
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
consultArr := consultResult.Array()
|
|
|
|
|
|
attachmentsMap := attachmentsResult.Map()
|
|
|
|
|
|
|
|
|
|
|
|
for _, consultItem := range consultArr {
|
|
|
|
|
|
if !consultItem.IsObject() {
|
|
|
|
|
|
continue
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
itemType := consultItem.Get("type").String()
|
|
|
|
|
|
if itemType == "" {
|
|
|
|
|
|
continue
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 查找对应类型的附件配置
|
|
|
|
|
|
attachResult, ok := attachmentsMap[itemType]
|
|
|
|
|
|
if !ok || !attachResult.IsObject() {
|
|
|
|
|
|
continue
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 获取模板
|
|
|
|
|
|
templateResult := attachResult.Get("template")
|
|
|
|
|
|
if !templateResult.Exists() || !templateResult.IsObject() {
|
|
|
|
|
|
continue
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 深拷贝模板
|
|
|
|
|
|
filledTemplateStr := templateResult.Raw
|
|
|
|
|
|
|
|
|
|
|
|
// 应用字段映射
|
|
|
|
|
|
fieldMappingResult := attachResult.Get("field_mapping")
|
|
|
|
|
|
if fieldMappingResult.Exists() && fieldMappingResult.IsObject() {
|
|
|
|
|
|
fieldMapping := fieldMappingResult.Map()
|
|
|
|
|
|
for fieldPath, valueSource := range fieldMapping {
|
|
|
|
|
|
sourceKey := valueSource.String()
|
|
|
|
|
|
valueResult := consultItem.Get(sourceKey)
|
|
|
|
|
|
if valueResult.Exists() {
|
|
|
|
|
|
var err error
|
|
|
|
|
|
filledTemplateStr, err = sjson.SetRaw(filledTemplateStr, fieldPath, valueResult.Raw)
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
continue
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 获取目标路径
|
|
|
|
|
|
targetPath := attachResult.Get("target_path").String()
|
|
|
|
|
|
if targetPath == "" {
|
|
|
|
|
|
continue
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 检查目标路径是否存在且为数组
|
|
|
|
|
|
targetResult := tGjson.Get(msgStr, targetPath)
|
|
|
|
|
|
if !targetResult.Exists() || !targetResult.IsArray() {
|
|
|
|
|
|
continue
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 追加到数组末尾
|
|
|
|
|
|
arrLen := len(targetResult.Array())
|
|
|
|
|
|
appendPath := targetPath + "." + strconv.Itoa(arrLen)
|
|
|
|
|
|
var err error
|
|
|
|
|
|
msgStr, err = sjson.SetRaw(msgStr, appendPath, filledTemplateStr)
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
continue
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 转回 map[string]any
|
|
|
|
|
|
var result map[string]any
|
|
|
|
|
|
if err := json.Unmarshal([]byte(msgStr), &result); err != nil {
|
|
|
|
|
|
return messages
|
|
|
|
|
|
}
|
|
|
|
|
|
return result
|
|
|
|
|
|
}
|
2026-05-27 09:36:26 +08:00
|
|
|
|
|
|
|
|
|
|
// GetUserMessage 获取用户消息
|
|
|
|
|
|
func GetUserMessage(taskReq map[string]any) map[string]any {
|
|
|
|
|
|
// 先取 requestPayload
|
|
|
|
|
|
rp, ok := taskReq["requestPayload"].(map[string]any)
|
|
|
|
|
|
if !ok {
|
|
|
|
|
|
return nil
|
|
|
|
|
|
}
|
|
|
|
|
|
// 再取 messages
|
|
|
|
|
|
messages, ok := rp["messages"].([]any)
|
|
|
|
|
|
if !ok {
|
|
|
|
|
|
return nil
|
|
|
|
|
|
}
|
|
|
|
|
|
for _, msg := range messages {
|
|
|
|
|
|
m, ok := msg.(map[string]any)
|
|
|
|
|
|
if ok && m["role"] == "user" {
|
|
|
|
|
|
return m
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
return nil
|
|
|
|
|
|
}
|