package userProfile import ( "context" "fmt" "time" filePb "sundynix-micro-go/app/file/rpc/file" "sundynix-micro-go/app/plant/api/internal/svc" "sundynix-micro-go/app/plant/api/internal/types" plantModel "sundynix-micro-go/app/plant/model" "github.com/zeromicro/go-zero/core/logx" "gorm.io/gorm" ) type GetMyStarsLogic struct { logx.Logger ctx context.Context svcCtx *svc.ServiceContext } func NewGetMyStarsLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetMyStarsLogic { return &GetMyStarsLogic{Logger: logx.WithContext(ctx), ctx: ctx, svcCtx: svcCtx} } func (l *GetMyStarsLogic) GetMyStars(req *types.PageReq) (interface{}, error) { userId := fmt.Sprintf("%v", l.ctx.Value("userId")) db := l.svcCtx.DB.Model(&plantModel.UserStar{}).Where("user_id = ?", userId) if req.Class == 1 { db = db.Where("type = ?", "wiki") } else if req.Class == 2 { db = db.Where("type = ?", "post") } var total int64 if err := db.Count(&total).Error; err != nil { return nil, err } pageSize := req.PageSize if pageSize <= 0 { pageSize = 10 } page := req.Current if page <= 0 { page = 1 } offset := (page - 1) * pageSize var stars []*plantModel.UserStar if err := db.Limit(pageSize).Offset(offset).Order("created_at desc").Find(&stars).Error; err != nil { return nil, err } // 提取 TargetID var wikiIds []string var postIds []string for _, s := range stars { if s.Type == "wiki" { wikiIds = append(wikiIds, s.TargetID) } else if s.Type == "post" { postIds = append(postIds, s.TargetID) } } // 1. 查询 Wiki 详情 wikiMap := make(map[string]map[string]interface{}) if len(wikiIds) > 0 { var wikis []*plantModel.Wiki if err := l.svcCtx.DB.Where("id IN ?", wikiIds).Find(&wikis).Error; err == nil { // 查本地 WikiOss type rel struct { WikiID string `gorm:"column:wiki_id"` OssID string `gorm:"column:oss_id"` } var rels []rel l.svcCtx.DB.Table("sundynix_plant_wiki_oss").Where("wiki_id IN ?", wikiIds).Find(&rels) wikiOssMap := make(map[string][]string) var allOssIds []string for _, r := range rels { wikiOssMap[r.WikiID] = append(wikiOssMap[r.WikiID], r.OssID) allOssIds = append(allOssIds, r.OssID) } // 通过 FileRpc 获取图片信息 fileMap := l.fetchFileMap(allOssIds) for _, w := range wikis { ossIds := wikiOssMap[w.ID] imgList := l.imgListToList(fileMap, ossIds) wikiMap[w.ID] = map[string]interface{}{ "id": w.ID, "name": w.Name, "latinName": w.LatinName, "aliases": w.Aliases, "genus": w.Genus, "difficulty": w.Difficulty, "isHot": w.IsHot, "growthHabit": w.GrowthHabit, "lightIntensity": w.LightIntensity, "classId": w.ClassID, "createdAt": w.CreatedAt.Format("2006-01-02 15:04:05"), "hasStar": 1, // 既然在这个列表中,说明一定是被收藏的 "imgList": imgList, } } } } // 2. 查询 Post 详情 postMap := make(map[string]map[string]interface{}) if len(postIds) > 0 { var posts []*plantModel.Post if err := l.svcCtx.DB. Preload("CommentList", func(db *gorm.DB) *gorm.DB { return db.Order("created_at asc") }). Preload("LikeList"). Where("id IN ?", postIds).Find(&posts).Error; err == nil { // 查帖子图片 postImgMap := l.queryPostImages(postIds) // 查用户信息 allUserIds := l.collectPostUserIds(posts) userMap := l.queryUserMap(allUserIds) // 点赞收藏状态 likedSet, starredSet := l.queryLikeStarStatus(userId, postIds) for _, p := range posts { item := map[string]interface{}{ "id": p.ID, "title": p.Title, "content": p.Content, "userId": p.UserID, "location": p.Location, "viewCount": p.ViewCount, "commentCount": p.CommentCount, "likeCount": p.LikeCount, "starCount": p.StarCount, "hasReviewed": p.HasReviewed, "createdAt": p.CreatedAt.Format(time.RFC3339), "updatedAt": p.UpdatedAt.Format(time.RFC3339), "createdAtStr": p.CreatedAt.Format("2006-01-02 15:04:05"), "hasLiked": 0, "hasStar": 0, "imgList": postImgMap[p.ID], "publisher": l.buildPublisherInfo(userMap, p.UserID), "commentList": l.buildCommentList(userMap, p.CommentList), "likeList": l.buildLikeList(userMap, p.LikeList), "starList": []map[string]interface{}{}, } if likedSet[p.ID] { item["hasLiked"] = 1 } if starredSet[p.ID] { item["hasStar"] = 1 } postMap[p.ID] = item } } } // 3. 按照 Stars 排序组装最终 List var list []map[string]interface{} for _, s := range stars { item := map[string]interface{}{ "id": s.ID, "userId": s.UserID, "targetId": s.TargetID, "type": s.Type, "createdAt": s.CreatedAt.Format("2006-01-02 15:04:05"), } if s.Type == "wiki" { if w, ok := wikiMap[s.TargetID]; ok { item["wiki"] = w list = append(list, item) } } else if s.Type == "post" { if p, ok := postMap[s.TargetID]; ok { item["post"] = p list = append(list, item) } } } if list == nil { list = []map[string]interface{}{} } return map[string]interface{}{ "list": list, "total": total, "page": page, "pageSize": pageSize, }, nil } func (l *GetMyStarsLogic) fetchFileMap(ids []string) map[string]map[string]interface{} { result := make(map[string]map[string]interface{}) if len(ids) == 0 { return result } resp, err := l.svcCtx.FileRpc.GetFilesByIds(l.ctx, &filePb.GetFilesByIdsReq{Ids: ids}) if err != nil || resp == nil { return result } for _, f := range resp.Files { result[f.Id] = map[string]interface{}{ "id": f.Id, "name": f.Name, "url": f.Url, "tag": f.Tag, "key": f.Key, "suffix": f.Suffix, "md5": f.Md5, "createdAt": time.Unix(f.CreatedAt, 0).Format(time.RFC3339), "updatedAt": time.Unix(f.CreatedAt, 0).Format(time.RFC3339), "createdAtStr": time.Unix(f.CreatedAt, 0).Format("2006-01-02 15:04:05"), } } return result } func (l *GetMyStarsLogic) imgListToList(fileMap map[string]map[string]interface{}, ossIds []string) []map[string]interface{} { var list []map[string]interface{} for _, id := range ossIds { if img, ok := fileMap[id]; ok { list = append(list, img) } } if list == nil { list = []map[string]interface{}{} } return list } func (l *GetMyStarsLogic) queryPostImages(postIds []string) map[string][]map[string]interface{} { type rel struct { PostID string `gorm:"column:post_id"` OssID string `gorm:"column:oss_id"` } var rels []rel l.svcCtx.DB.Table("sundynix_plant_post_oss").Where("post_id IN ?", postIds).Find(&rels) var allOssIds []string pidMap := make(map[string][]string) for _, r := range rels { pidMap[r.PostID] = append(pidMap[r.PostID], r.OssID) allOssIds = append(allOssIds, r.OssID) } fileInfos := l.fetchFileMap(allOssIds) result := make(map[string][]map[string]interface{}) for pid, ids := range pidMap { var imgs []map[string]interface{} for _, oid := range ids { if info, ok := fileInfos[oid]; ok { imgs = append(imgs, info) } } if imgs == nil { imgs = []map[string]interface{}{} } result[pid] = imgs } for _, pid := range postIds { if _, ok := result[pid]; !ok { result[pid] = []map[string]interface{}{} } } return result } func (l *GetMyStarsLogic) collectPostUserIds(posts []*plantModel.Post) []string { set := make(map[string]bool) for _, p := range posts { set[p.UserID] = true for _, c := range p.CommentList { set[c.UserID] = true } for _, l := range p.LikeList { set[l.UserID] = true } } var ids []string for id := range set { ids = append(ids, id) } return ids } func (l *GetMyStarsLogic) queryUserMap(ids []string) map[string]map[string]interface{} { result := make(map[string]map[string]interface{}) if len(ids) == 0 { return result } type userRow struct { ID string `gorm:"column:id"` NickName string `gorm:"column:nick_name"` Name string `gorm:"column:name"` AvatarID string `gorm:"column:avatar_id"` } var rows []userRow l.svcCtx.DB.Table("sundynix_user").Where("id IN ?", ids).Find(&rows) var avatarIds []string for _, row := range rows { if row.AvatarID != "" { avatarIds = append(avatarIds, row.AvatarID) } } avatarMap := l.fetchFileMap(avatarIds) for _, row := range rows { avatarData := map[string]interface{}{} if av, ok := avatarMap[row.AvatarID]; ok { avatarData = av } result[row.ID] = map[string]interface{}{ "id": row.ID, "nickName": row.NickName, "name": row.Name, "avatarId": row.AvatarID, "avatar": avatarData, } } return result } func (l *GetMyStarsLogic) queryLikeStarStatus(userId string, postIds []string) (likedSet, starredSet map[string]bool) { likedSet = make(map[string]bool) starredSet = make(map[string]bool) if len(postIds) == 0 { return } type rel struct { PostID string `gorm:"column:post_id"` } var likes []rel l.svcCtx.DB.Table("sundynix_plant_post_like").Where("post_id IN ? AND user_id = ?", postIds, userId).Find(&likes) for _, l := range likes { likedSet[l.PostID] = true } var stars []rel l.svcCtx.DB.Table("sundynix_plant_user_star").Where("target_id IN ? AND user_id = ? AND type = 'post'", postIds, userId).Find(&stars) for _, s := range stars { starredSet[s.PostID] = true } return } func (l *GetMyStarsLogic) buildPublisherInfo(userMap map[string]map[string]interface{}, userId string) map[string]interface{} { if u, ok := userMap[userId]; ok { return u } return map[string]interface{}{ "id": userId, "nickName": "", "name": "", "avatarId": "", "avatar": map[string]interface{}{}, } } func (l *GetMyStarsLogic) buildCommentList(userMap map[string]map[string]interface{}, comments []*plantModel.PostComment) []map[string]interface{} { var list []map[string]interface{} for _, c := range comments { list = append(list, map[string]interface{}{ "id": c.ID, "postId": c.PostID, "userId": c.UserID, "content": c.Content, "parentId": c.ParentID, "createdAt": c.CreatedAt.Format(time.RFC3339), "updatedAt": c.UpdatedAt.Format(time.RFC3339), "createdAtStr": c.CreatedAt.Format("2006-01-02 15:04:05"), "commentator": l.buildPublisherInfo(userMap, c.UserID), }) } if list == nil { list = []map[string]interface{}{} } return list } func (l *GetMyStarsLogic) buildLikeList(userMap map[string]map[string]interface{}, likes []*plantModel.PostLike) []map[string]interface{} { var list []map[string]interface{} for _, like := range likes { list = append(list, map[string]interface{}{ "id": like.ID, "postId": like.PostID, "userId": like.UserID, "liker": l.buildPublisherInfo(userMap, like.UserID), }) } if list == nil { list = []map[string]interface{}{} } return list }