2026-05-18 19:19:17 +08:00
|
|
|
|
package util
|
|
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
|
"encoding/json"
|
2026-06-08 18:01:54 +08:00
|
|
|
|
"fmt"
|
2026-05-18 19:19:17 +08:00
|
|
|
|
|
|
|
|
|
|
"github.com/gogf/gf/v2/container/gvar"
|
2026-06-08 18:01:54 +08:00
|
|
|
|
"github.com/gogf/gf/v2/encoding/gjson"
|
2026-05-18 19:19:17 +08:00
|
|
|
|
"github.com/gogf/gf/v2/util/gconv"
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
// ConvertToMessages 将原始数据转换为消息列表
|
|
|
|
|
|
func ConvertToMessages(raw any) []map[string]any {
|
|
|
|
|
|
if raw == nil {
|
|
|
|
|
|
return nil
|
|
|
|
|
|
}
|
2026-05-20 11:36:39 +08:00
|
|
|
|
|
2026-06-08 18:01:54 +08:00
|
|
|
|
j := gjson.New(raw)
|
2026-05-29 17:54:19 +08:00
|
|
|
|
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)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-06-08 18:01:54 +08:00
|
|
|
|
b, _ := json.Marshal(tmp)
|
2026-05-18 19:19:17 +08:00
|
|
|
|
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
|
|
|
|
|
2026-06-08 18:01:54 +08:00
|
|
|
|
// MergeConsult 将 consult 附件合并到模型生成的 messages 结构中
|
2026-05-23 18:08:09 +08:00
|
|
|
|
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
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-06-08 18:01:54 +08:00
|
|
|
|
// 1) 获取 consult 数组
|
|
|
|
|
|
consult := gconv.Interfaces(req["consult"])
|
|
|
|
|
|
if len(consult) == 0 {
|
|
|
|
|
|
return messages
|
|
|
|
|
|
}
|
2026-05-23 18:08:09 +08:00
|
|
|
|
|
2026-06-08 18:01:54 +08:00
|
|
|
|
// 2) 获取配置
|
|
|
|
|
|
targetPath := gconv.String(extendMapping["target_content_path"])
|
|
|
|
|
|
if targetPath == "" {
|
2026-05-23 18:08:09 +08:00
|
|
|
|
return messages
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-06-08 18:01:54 +08:00
|
|
|
|
templates := gconv.Map(extendMapping["attachment_templates"])
|
|
|
|
|
|
if len(templates) == 0 {
|
2026-05-23 18:08:09 +08:00
|
|
|
|
return messages
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-06-08 18:01:54 +08:00
|
|
|
|
// 3) 转为 gjson 操作
|
|
|
|
|
|
msgJson := gjson.New(messages)
|
2026-05-23 18:08:09 +08:00
|
|
|
|
|
2026-06-08 18:01:54 +08:00
|
|
|
|
// 固定:如果有 rounds 结构,路径替换为 rounds.0.{targetPath}
|
|
|
|
|
|
if arr := msgJson.Get("rounds.0").Array(); arr != nil {
|
|
|
|
|
|
targetPath = "rounds.0." + targetPath
|
|
|
|
|
|
}
|
2026-05-23 18:08:09 +08:00
|
|
|
|
|
2026-06-08 18:01:54 +08:00
|
|
|
|
// 4) 遍历 consult,按类型生成附件并追加
|
|
|
|
|
|
for _, item := range consult {
|
|
|
|
|
|
itemJson := gjson.New(item)
|
2026-05-23 18:08:09 +08:00
|
|
|
|
|
2026-06-08 18:01:54 +08:00
|
|
|
|
itemType := itemJson.Get("type").String()
|
|
|
|
|
|
if itemType == "" {
|
2026-05-23 18:08:09 +08:00
|
|
|
|
continue
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-06-08 18:01:54 +08:00
|
|
|
|
// 查找对应模板
|
|
|
|
|
|
tmpl := gconv.Map(templates[itemType])
|
|
|
|
|
|
if len(tmpl) == 0 {
|
2026-05-23 18:08:09 +08:00
|
|
|
|
continue
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-06-08 18:01:54 +08:00
|
|
|
|
// 生成附件对象
|
|
|
|
|
|
attachment := buildAttachment(tmpl, itemJson.Get("url").String())
|
|
|
|
|
|
if attachment == nil {
|
2026-05-23 18:08:09 +08:00
|
|
|
|
continue
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-06-08 18:01:54 +08:00
|
|
|
|
// 获取当前数组长度,用索引追加
|
|
|
|
|
|
arr := msgJson.Get(targetPath).Array()
|
|
|
|
|
|
idx := len(arr)
|
|
|
|
|
|
indexPath := fmt.Sprintf("%s.%d", targetPath, idx)
|
|
|
|
|
|
_ = msgJson.Set(indexPath, attachment)
|
2026-05-23 18:08:09 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-06-08 18:01:54 +08:00
|
|
|
|
return msgJson.Map()
|
2026-05-23 18:08:09 +08:00
|
|
|
|
}
|
2026-05-27 09:36:26 +08:00
|
|
|
|
|
2026-06-08 18:01:54 +08:00
|
|
|
|
// buildAttachment 根据模板和用户数据生成附件对象
|
|
|
|
|
|
func buildAttachment(tmpl map[string]any, url string) map[string]any {
|
|
|
|
|
|
typ := gconv.String(tmpl["type"])
|
|
|
|
|
|
if typ == "" || url == "" {
|
2026-05-27 09:36:26 +08:00
|
|
|
|
return nil
|
|
|
|
|
|
}
|
2026-06-08 18:01:54 +08:00
|
|
|
|
|
|
|
|
|
|
// 深拷贝 body 并填充 url
|
|
|
|
|
|
body := gconv.Map(tmpl["body"])
|
|
|
|
|
|
bodyJson := gjson.New(body)
|
|
|
|
|
|
bodyJson = fillEmpty(bodyJson, url)
|
|
|
|
|
|
|
|
|
|
|
|
return map[string]any{
|
|
|
|
|
|
"type": typ,
|
|
|
|
|
|
typ: bodyJson.Map(),
|
2026-05-27 09:36:26 +08:00
|
|
|
|
}
|
2026-06-08 18:01:54 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// fillEmpty 递归查找空字符串并替换
|
|
|
|
|
|
func fillEmpty(j *gjson.Json, value string) *gjson.Json {
|
|
|
|
|
|
m := j.Map()
|
|
|
|
|
|
for k, v := range m {
|
|
|
|
|
|
switch vv := v.(type) {
|
|
|
|
|
|
case string:
|
|
|
|
|
|
if vv == "" {
|
|
|
|
|
|
_ = j.Set(k, value)
|
|
|
|
|
|
}
|
|
|
|
|
|
case map[string]any:
|
|
|
|
|
|
_ = j.Set(k, fillEmpty(gjson.New(vv), value).Map())
|
2026-05-27 09:36:26 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2026-06-08 18:01:54 +08:00
|
|
|
|
return j
|
2026-05-27 09:36:26 +08:00
|
|
|
|
}
|