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 }