Files
sundynix-micro-be/app/plant/api/internal/logic/userProfile/getmystarslogic.go
T
2026-05-24 01:41:22 +08:00

372 lines
10 KiB
Go

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
}