192 lines
5.0 KiB
Go
192 lines
5.0 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.redpowerfuture.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
|
||
}
|