192 lines
4.9 KiB
Go
192 lines
4.9 KiB
Go
|
|
package service
|
|||
|
|
|
|||
|
|
import (
|
|||
|
|
"ai-agent/workflow/dao"
|
|||
|
|
"ai-agent/workflow/model/dto"
|
|||
|
|
"ai-agent/workflow/model/entity"
|
|||
|
|
"ai-agent/workflow/service/einograph"
|
|||
|
|
"context"
|
|||
|
|
"fmt"
|
|||
|
|
"sort"
|
|||
|
|
|
|||
|
|
"gitea.com/red-future/common/utils"
|
|||
|
|
"github.com/gogf/gf/v2/util/gconv"
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
var CreationInfoService = new(creationInfoService)
|
|||
|
|
|
|||
|
|
type creationInfoService struct{}
|
|||
|
|
|
|||
|
|
func (s *creationInfoService) Creation(ctx context.Context, req *dto.CreationInput) (err error) {
|
|||
|
|
run, err := einograph.BuildCreationGraph(ctx)
|
|||
|
|
if err != nil {
|
|||
|
|
return fmt.Errorf("构建失败: %w", err)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
output, err := run.Invoke(ctx, req)
|
|||
|
|
if err != nil {
|
|||
|
|
return fmt.Errorf("执行失败: %w", err)
|
|||
|
|
}
|
|||
|
|
// ========== 核心修复:先转 map,再取 output ==========
|
|||
|
|
var resultMap map[string]any
|
|||
|
|
if err := gconv.Scan(output, &resultMap); err != nil {
|
|||
|
|
return fmt.Errorf("解析结果map失败: %w", err)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 取出内层 output
|
|||
|
|
realOutput := resultMap["output"]
|
|||
|
|
|
|||
|
|
// 解析到你的结构体
|
|||
|
|
var creationOutput dto.CreationOutput
|
|||
|
|
if err := gconv.Scan(realOutput, &creationOutput); err != nil {
|
|||
|
|
return fmt.Errorf("解析CreationOutput失败: %w", err)
|
|||
|
|
}
|
|||
|
|
for _, item := range creationOutput.Items {
|
|||
|
|
dao.CreationInfoDao.Insert(ctx, &dto.Create{
|
|||
|
|
ImageUrls: item.ImageUrls,
|
|||
|
|
HtmlFileUrl: item.HtmlFileUrl,
|
|||
|
|
Title: item.Title,
|
|||
|
|
Theme: item.Theme,
|
|||
|
|
ContentType: item.ContentType,
|
|||
|
|
})
|
|||
|
|
}
|
|||
|
|
return
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
func (s *creationInfoService) List(ctx context.Context, req *dto.ListCreationInfoReq) (res *dto.ListCreationInfoRes, err error) {
|
|||
|
|
user, err := utils.GetUserInfo(ctx)
|
|||
|
|
if err != nil {
|
|||
|
|
return
|
|||
|
|
}
|
|||
|
|
req.Creator = user.UserName
|
|||
|
|
list, total, err := dao.CreationInfoDao.List(ctx, req)
|
|||
|
|
if err != nil {
|
|||
|
|
return
|
|||
|
|
}
|
|||
|
|
res = &dto.ListCreationInfoRes{
|
|||
|
|
Total: total,
|
|||
|
|
}
|
|||
|
|
res.ImgAddressPrefix, err = utils.GetFileAddressPrefix(ctx)
|
|||
|
|
if err != nil {
|
|||
|
|
return
|
|||
|
|
}
|
|||
|
|
tree := s.ConvertToTree(list)
|
|||
|
|
res.Tree = tree
|
|||
|
|
return
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// ConvertToTree
|
|||
|
|
// 第一层:日期 倒序
|
|||
|
|
// 第二层:ContentType 倒序
|
|||
|
|
// 第三层:Theme 倒序
|
|||
|
|
// Theme 下的 Title 按时间倒序编号 Title-1、Title-2…
|
|||
|
|
func (s *creationInfoService) ConvertToTree(list []*entity.CreationInfo) []dto.TimeNode {
|
|||
|
|
// ========== 1. 按日期分组 ==========
|
|||
|
|
timeMap := make(map[string][]*entity.CreationInfo)
|
|||
|
|
for _, item := range list {
|
|||
|
|
dateStr := item.CreatedAt.Format("Y-m-d")
|
|||
|
|
timeMap[dateStr] = append(timeMap[dateStr], item)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 日期倒序
|
|||
|
|
var dateList []string
|
|||
|
|
for dateStr := range timeMap {
|
|||
|
|
dateList = append(dateList, dateStr)
|
|||
|
|
}
|
|||
|
|
sort.Slice(dateList, func(i, j int) bool {
|
|||
|
|
return dateList[i] > dateList[j]
|
|||
|
|
})
|
|||
|
|
|
|||
|
|
var tree []dto.TimeNode
|
|||
|
|
|
|||
|
|
// ========== 2. 遍历日期 ==========
|
|||
|
|
for _, dateStr := range dateList {
|
|||
|
|
items := timeMap[dateStr]
|
|||
|
|
|
|||
|
|
// ========== ContentType 分组 + 【时间倒序】 ==========
|
|||
|
|
ctMap := make(map[string][]*entity.CreationInfo)
|
|||
|
|
for _, item := range items {
|
|||
|
|
ctMap[item.ContentType] = append(ctMap[item.ContentType], item)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 把 ContentType 按【最新时间倒序】排序
|
|||
|
|
var ctList []string
|
|||
|
|
for ct := range ctMap {
|
|||
|
|
ctList = append(ctList, ct)
|
|||
|
|
}
|
|||
|
|
sort.Slice(ctList, func(i, j int) bool {
|
|||
|
|
ctiItems := ctMap[ctList[i]]
|
|||
|
|
ctjItems := ctMap[ctList[j]]
|
|||
|
|
return ctiItems[0].CreatedAt.After(ctjItems[0].CreatedAt)
|
|||
|
|
})
|
|||
|
|
|
|||
|
|
var ctNodes []dto.ContentTypeNode
|
|||
|
|
for _, ct := range ctList {
|
|||
|
|
ctItems := ctMap[ct]
|
|||
|
|
|
|||
|
|
// ========== Theme 分组 + 【时间倒序】 ==========
|
|||
|
|
themeMap := make(map[string][]*entity.CreationInfo)
|
|||
|
|
for _, item := range ctItems {
|
|||
|
|
themeMap[item.Theme] = append(themeMap[item.Theme], item)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// Theme 按【最新时间倒序】排序
|
|||
|
|
var themeList []string
|
|||
|
|
for theme := range themeMap {
|
|||
|
|
themeList = append(themeList, theme)
|
|||
|
|
}
|
|||
|
|
sort.Slice(themeList, func(i, j int) bool {
|
|||
|
|
tiItems := themeMap[themeList[i]]
|
|||
|
|
tjItems := themeMap[themeList[j]]
|
|||
|
|
return tiItems[0].CreatedAt.After(tjItems[0].CreatedAt)
|
|||
|
|
})
|
|||
|
|
|
|||
|
|
var themeNodes []dto.ThemeNode
|
|||
|
|
for _, theme := range themeList {
|
|||
|
|
themeItems := themeMap[theme]
|
|||
|
|
|
|||
|
|
// ========== Theme 下的 Title 按【时间倒序】排列 + 编号 ==========
|
|||
|
|
sort.Slice(themeItems, func(a, b int) bool {
|
|||
|
|
return themeItems[a].CreatedAt.After(themeItems[b].CreatedAt)
|
|||
|
|
})
|
|||
|
|
|
|||
|
|
var titleNodes []dto.TitleNode
|
|||
|
|
for idx, item := range themeItems {
|
|||
|
|
titleName := fmt.Sprintf("%s-%d", item.Title, idx+1)
|
|||
|
|
|
|||
|
|
var imgList []dto.ImgNode
|
|||
|
|
for imgIdx, url := range item.ImageUrls {
|
|||
|
|
imgList = append(imgList, dto.ImgNode{
|
|||
|
|
Name: fmt.Sprintf("img-%d", imgIdx+1),
|
|||
|
|
Url: url,
|
|||
|
|
})
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
titleNodes = append(titleNodes, dto.TitleNode{
|
|||
|
|
Title: titleName,
|
|||
|
|
HtmlFileUrl: item.HtmlFileUrl,
|
|||
|
|
ImageUrls: imgList,
|
|||
|
|
})
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
themeNodes = append(themeNodes, dto.ThemeNode{
|
|||
|
|
Theme: theme,
|
|||
|
|
Titles: titleNodes,
|
|||
|
|
})
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
ctNodes = append(ctNodes, dto.ContentTypeNode{
|
|||
|
|
ContentType: ct,
|
|||
|
|
Themes: themeNodes,
|
|||
|
|
})
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
tree = append(tree, dto.TimeNode{
|
|||
|
|
CreatedDate: dateStr,
|
|||
|
|
ContentTypes: ctNodes,
|
|||
|
|
})
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return tree
|
|||
|
|
}
|