feat: 新增创作作品管理模块及相关配置
This commit is contained in:
191
workflow/service/creation_info_service.go
Normal file
191
workflow/service/creation_info_service.go
Normal file
@@ -0,0 +1,191 @@
|
||||
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
|
||||
}
|
||||
Reference in New Issue
Block a user