package legacy import ( "context" "encoding/json" "fmt" "net/http" "time" filePb "sundynix-micro-go/app/file/rpc/file" "sundynix-micro-go/app/plant/api/internal/logic/complete" plantLogic "sundynix-micro-go/app/plant/api/internal/logic/myPlant" postLogic "sundynix-micro-go/app/plant/api/internal/logic/post" topicLogic "sundynix-micro-go/app/plant/api/internal/logic/topic" wikiLogic "sundynix-micro-go/app/plant/api/internal/logic/wiki" "sundynix-micro-go/app/plant/api/internal/svc" "sundynix-micro-go/app/plant/api/internal/types" plantModel "sundynix-micro-go/app/plant/model" plantPb "sundynix-micro-go/app/plant/rpc/plant" "sundynix-micro-go/common/response" "github.com/zeromicro/go-zero/rest/httpx" "gorm.io/gorm" ) func idFromQuery(r *http.Request) string { if id := r.URL.Query().Get("id"); id != "" { return id } if id := r.URL.Query().Get("wikiId"); id != "" { return id } if id := r.URL.Query().Get("postId"); id != "" { return id } if id := r.URL.Query().Get("itemId"); id != "" { return id } return r.URL.Query().Get("classId") } func fileListByIDs(r *http.Request, svcCtx *svc.ServiceContext, ids []string) []map[string]interface{} { if len(ids) == 0 { return []map[string]interface{}{} } resp, err := svcCtx.FileRpc.GetFilesByIds(r.Context(), &filePb.GetFilesByIdsReq{Ids: ids}) if err != nil { return []map[string]interface{}{} } list := make([]map[string]interface{}, 0, len(resp.Files)) for _, f := range resp.Files { list = append(list, 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": f.CreatedAt, }) } return list } func PlantDetailHandler(svcCtx *svc.ServiceContext) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { var myPlant plantModel.MyPlant if err := svcCtx.DB. Preload("CarePlans"). Preload("CareRecords", func(db *gorm.DB) *gorm.DB { return db.Order("created_at desc") }). Preload("GrowthRecords", func(db *gorm.DB) *gorm.DB { return db.Order("created_at desc") }). Where("id = ?", idFromQuery(r)).First(&myPlant).Error; err != nil { response.Fail(w, err.Error()) return } // 查图片(本地关联表 + FileRpc) imgList := queryImagesByPlant(svcCtx, r.Context(), myPlant.ID) // 成长记录图片 growthImgMap := queryGrowthImages(svcCtx, r.Context(), myPlant.GrowthRecords) response.OkWithData(w, map[string]interface{}{ "plant": toPlantMap(myPlant), "imgList": imgList, "carePlans": toPlanMapList(myPlant.CarePlans), "careRecords": toRecordMapList(myPlant.CareRecords), "careTasks": nil, "growthRecords": toGrowthMapList(myPlant.GrowthRecords, growthImgMap), }) } } func DeletePlanHandler(svcCtx *svc.ServiceContext) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { l := plantLogic.NewDeleteCarePlanLogic(r.Context(), svcCtx) if err := l.DeleteCarePlan(&types.IdsReq{Ids: []string{idFromQuery(r)}}); err != nil { response.Fail(w, err.Error()) return } response.Ok(w) } } func WikiDetailHandler(svcCtx *svc.ServiceContext) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { resp, err := svcCtx.PlantRpc.GetWikiDetail(r.Context(), &plantPb.IdReq{Id: idFromQuery(r)}) if err != nil { response.Fail(w, err.Error()) return } if resp != nil && resp.Wiki != nil { // 通过 FileRpc 获取完整图片信息 imgList := fetchFileMap(svcCtx, r.Context(), resp.Wiki.OssIds) response.OkWithData(w, map[string]interface{}{ "wiki": resp.Wiki, "imgList": imgListToList(imgList, resp.Wiki.OssIds), "classIds": resp.Wiki.ClassIds, "relatedWikiIds": resp.Wiki.RelatedWikiIds, }) return } response.OkWithData(w, resp) } } func WikiPageHandler(svcCtx *svc.ServiceContext) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { var req types.WikiListReq if err := httpx.Parse(r, &req); err != nil { response.Fail(w, err.Error()) return } resp, err := svcCtx.PlantRpc.GetWikiList(r.Context(), &plantPb.WikiListReq{ Current: int32(req.Current), PageSize: int32(req.PageSize), Name: req.Name, ClassId: req.ClassId, IsHot: int32(req.IsHot), }) if err != nil { response.Fail(w, err.Error()) return } // 查询所有 wiki 的图片 var wikiIds []string for _, w := range resp.List { wikiIds = append(wikiIds, w.Id) } // 查本地关联表获取 OSS ID type rel struct { WikiID string `gorm:"column:wiki_id"` OssID string `gorm:"column:oss_id"` } var rels []rel if len(wikiIds) > 0 { 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 := fetchFileMap(svcCtx, r.Context(), allOssIds) // 组装返回 var list []map[string]interface{} for _, w := range resp.List { ossIds := wikiOssMap[w.Id] imgList := imgListToList(fileMap, ossIds) hasStarVal := 0 if w.IsStar { hasStarVal = 1 } list = append(list, 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, "hasStar": hasStarVal, "imgList": imgList, }) } if list == nil { list = []map[string]interface{}{} } response.OkWithData(w, map[string]interface{}{ "list": list, "total": resp.Total, }) } } // imgListToList 将 fileMap 按顺序转为列表 func 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 WikiStarHandler(svcCtx *svc.ServiceContext) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { l := wikiLogic.NewToggleWikiStarLogic(r.Context(), svcCtx) if err := l.ToggleWikiStar(&types.IdReq{Id: idFromQuery(r)}); err != nil { response.Fail(w, err.Error()) return } response.Ok(w) } } func TopicDetailHandler(svcCtx *svc.ServiceContext) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { l := topicLogic.NewGetTopicDetailLogic(r.Context(), svcCtx) resp, err := l.GetTopicDetail(&types.IdPathReq{Id: idFromQuery(r)}) if err != nil { response.Fail(w, err.Error()) return } response.OkWithData(w, resp) } } func LikePostHandler(svcCtx *svc.ServiceContext) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { l := postLogic.NewLikePostLogic(r.Context(), svcCtx) if err := l.LikePost(&types.IdReq{Id: idFromQuery(r)}); err != nil { response.Fail(w, err.Error()) return } response.Ok(w) } } func StarPostHandler(svcCtx *svc.ServiceContext) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { l := postLogic.NewStarPostLogic(r.Context(), svcCtx) if err := l.StarPost(&types.IdReq{Id: idFromQuery(r)}); err != nil { response.Fail(w, err.Error()) return } response.Ok(w) } } func ExchangeItemDetailHandler(svcCtx *svc.ServiceContext) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { l := complete.NewGetExchangeItemDetailLogic(r.Context(), svcCtx) resp, err := l.GetExchangeItemDetail(&types.IdPathReq{Id: idFromQuery(r)}) if err != nil { response.Fail(w, err.Error()) return } response.OkWithData(w, resp) } } func PostPageHandler(svcCtx *svc.ServiceContext) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { var req types.PostListReq if err := httpx.Parse(r, &req); err != nil { response.Fail(w, err.Error()) return } userId := fmt.Sprintf("%v", r.Context().Value("userId")) db := svcCtx.DB.Model(&plantModel.Post{}) if req.Keyword != "" { db = db.Where("title like ? OR content like ?", "%"+req.Keyword+"%", "%"+req.Keyword+"%") } var total int64 db.Count(&total) pageSize := req.PageSize if pageSize <= 0 { pageSize = 20 } page := req.Current if page <= 0 { page = 1 } offset := (page - 1) * pageSize var posts []*plantModel.Post if err := db. Preload("CommentList", func(db *gorm.DB) *gorm.DB { return db.Order("created_at asc") }). Preload("LikeList"). Limit(pageSize).Offset(offset).Order("created_at desc").Find(&posts).Error; err != nil { response.Fail(w, err.Error()) return } // 组装完整响应 list := buildPostListResponse(svcCtx, r.Context(), posts, userId) response.OkWithData(w, map[string]interface{}{ "list": list, "total": total, "page": page, "pageSize": pageSize, }) } } func MyPostPageHandler(svcCtx *svc.ServiceContext) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { var req types.PostListReq if err := httpx.Parse(r, &req); err != nil { response.Fail(w, err.Error()) return } userId := fmt.Sprintf("%v", r.Context().Value("userId")) db := svcCtx.DB.Model(&plantModel.Post{}).Where("user_id = ?", userId) var total int64 db.Count(&total) pageSize := req.PageSize if pageSize <= 0 { pageSize = 20 } page := req.Current if page <= 0 { page = 1 } offset := (page - 1) * pageSize var posts []*plantModel.Post if err := db. Preload("CommentList", func(db *gorm.DB) *gorm.DB { return db.Order("created_at asc") }). Preload("LikeList"). Limit(pageSize).Offset(offset).Order("created_at desc").Find(&posts).Error; err != nil { response.Fail(w, err.Error()) return } list := buildPostListResponse(svcCtx, r.Context(), posts, userId) response.OkWithData(w, map[string]interface{}{ "list": list, "total": total, "page": page, "pageSize": pageSize, }) } } // ========== Post 列表辅助函数 ========== // buildPostListResponse 组装完整帖子列表响应 func buildPostListResponse(svcCtx *svc.ServiceContext, ctx context.Context, posts []*plantModel.Post, userId string) []map[string]interface{} { if len(posts) == 0 { return []map[string]interface{}{} } var postIds []string for _, p := range posts { postIds = append(postIds, p.ID) } // 1. 查帖子图片(本地关联表 + FileRpc) postImgMap := queryPostImages(svcCtx, ctx, postIds) // 2. 查用户信息 allUserIds := collectPostUserIds(posts) userMap := queryUserMapV2(svcCtx, allUserIds) // 3. 查当前用户点赞/收藏状态 likedSet, starredSet := queryLikeStarStatus(svcCtx, userId, postIds) // 4. 组装 var list []map[string]interface{} 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": buildPublisherInfo(userMap, p.UserID), "commentList": buildCommentList(userMap, p.CommentList), "likeList": buildLikeList(userMap, p.LikeList), "starList": []map[string]interface{}{}, } if likedSet[p.ID] { item["hasLiked"] = 1 } if starredSet[p.ID] { item["hasStar"] = 1 } list = append(list, item) } return list } func 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 } // queryPostImages 查询帖子图片 func queryPostImages(svcCtx *svc.ServiceContext, ctx context.Context, 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 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) } // 通过 FileRpc 获取文件信息 fileInfos := fetchFileMap(svcCtx, ctx, 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 } // fetchFileMap 通过 FileRpc 获取文件信息 func fetchFileMap(svcCtx *svc.ServiceContext, ctx context.Context, ids []string) map[string]map[string]interface{} { result := make(map[string]map[string]interface{}) if len(ids) == 0 { return result } resp, err := svcCtx.FileRpc.GetFilesByIds(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": unixToTimeStr(f.CreatedAt), "updatedAt": unixToTimeStr(f.CreatedAt), "createdAtStr": unixToTimeStrShort(f.CreatedAt), } } return result } func unixToTimeStr(ts int64) string { if ts == 0 { return "" } return time.Unix(ts, 0).Format(time.RFC3339) } func unixToTimeStrShort(ts int64) string { if ts == 0 { return "" } return time.Unix(ts, 0).Format("2006-01-02 15:04:05") } // queryUserMapV2 查询用户信息 func queryUserMapV2(svcCtx *svc.ServiceContext, 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 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) } } // 头像通过 FileRpc 获取 avatarMap := fetchFileMap(svcCtx, context.Background(), 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 } // queryLikeStarStatus 查询当前用户的点赞/收藏状态 func queryLikeStarStatus(svcCtx *svc.ServiceContext, 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 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 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 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 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": buildPublisherInfo(userMap, c.UserID), }) } if list == nil { list = []map[string]interface{}{} } return list } func buildLikeList(userMap map[string]map[string]interface{}, likes []*plantModel.PostLike) []map[string]interface{} { var list []map[string]interface{} for _, l := range likes { list = append(list, map[string]interface{}{ "id": l.ID, "postId": l.PostID, "userId": l.UserID, "liker": buildPublisherInfo(userMap, l.UserID), }) } if list == nil { list = []map[string]interface{}{} } return list } // ========== Plant Detail 辅助函数 ========== func queryImagesByPlant(svcCtx *svc.ServiceContext, ctx context.Context, plantID string) []map[string]interface{} { type rel struct { OssID string `gorm:"column:sundynix_oss_id"` } var rels []rel svcCtx.DB.Table("sundynix_plant_my_plant_oss"). Where("sundynix_my_plant_id = ?", plantID). Order("sundynix_oss_id asc"). Find(&rels) var ids []string for _, r := range rels { ids = append(ids, r.OssID) } fileMap := fetchFileMap(svcCtx, ctx, ids) var result []map[string]interface{} for _, id := range ids { if f, ok := fileMap[id]; ok { result = append(result, f) } } if result == nil { result = []map[string]interface{}{} } return result } func queryGrowthImages(svcCtx *svc.ServiceContext, ctx context.Context, records []*plantModel.GrowthRecord) map[string][]map[string]interface{} { if len(records) == 0 { return nil } var ids []string for _, gr := range records { ids = append(ids, gr.ID) } type rel struct { GrowthRecordID string `gorm:"column:growth_record_id"` OssID string `gorm:"column:oss_id"` } var rels []rel svcCtx.DB.Table("sundynix_plant_growth_record_oss"). Where("growth_record_id IN ?", ids). Find(&rels) var allOssIds []string gidMap := make(map[string][]string) for _, r := range rels { gidMap[r.GrowthRecordID] = append(gidMap[r.GrowthRecordID], r.OssID) allOssIds = append(allOssIds, r.OssID) } fileMap := fetchFileMap(svcCtx, ctx, allOssIds) result := make(map[string][]map[string]interface{}) for gid, ossIds := range gidMap { var imgs []map[string]interface{} for _, oid := range ossIds { if f, ok := fileMap[oid]; ok { imgs = append(imgs, f) } } result[gid] = imgs } return result } func toPlantMap(p plantModel.MyPlant) map[string]interface{} { return map[string]interface{}{ "id": p.ID, "createdAt": p.CreatedAt.Format(time.RFC3339), "updatedAt": p.UpdatedAt.Format(time.RFC3339), "createdAtStr": p.CreatedAt.Format("2006-01-02 15:04:05"), "userId": p.UserID, "name": p.Name, "plantTime": p.PlantTime.Format(time.RFC3339), "status": p.Status, "placement": p.Placement, "potMaterial": p.PotMaterial, "potSize": p.PotSize, "sunlight": p.Sunlight, "plantingMaterial": p.PlantingMaterial, } } func toPlanMapList(plans []*plantModel.CarePlan) []map[string]interface{} { var list []map[string]interface{} for _, p := range plans { list = append(list, map[string]interface{}{ "id": p.ID, "createdAt": p.CreatedAt.Format(time.RFC3339), "updatedAt": p.UpdatedAt.Format(time.RFC3339), "createdAtStr": p.CreatedAt.Format("2006-01-02 15:04:05"), "userId": p.UserID, "plantId": p.PlantID, "name": p.Name, "icon": p.Icon, "period": p.Period, "targetAction": p.TargetAction, }) } if list == nil { list = []map[string]interface{}{} } return list } func toRecordMapList(records []*plantModel.CareRecord) []map[string]interface{} { var list []map[string]interface{} for _, r := range records { list = append(list, map[string]interface{}{ "id": r.ID, "createdAt": r.CreatedAt.Format(time.RFC3339), "updatedAt": r.UpdatedAt.Format(time.RFC3339), "createdAtStr": r.CreatedAt.Format("2006-01-02 15:04:05"), "userId": r.UserID, "plantId": r.PlantID, "planId": r.PlanID, "name": r.Name, "remark": r.Remark, "icon": r.Icon, }) } if list == nil { list = []map[string]interface{}{} } return list } func toGrowthMapList(records []*plantModel.GrowthRecord, imgMap map[string][]map[string]interface{}) []map[string]interface{} { var list []map[string]interface{} for _, gr := range records { imgs := imgMap[gr.ID] if imgs == nil { imgs = []map[string]interface{}{} } list = append(list, map[string]interface{}{ "id": gr.ID, "createdAt": gr.CreatedAt.Format(time.RFC3339), "updatedAt": gr.UpdatedAt.Format(time.RFC3339), "createdAtStr": gr.CreatedAt.Format("2006-01-02 15:04:05"), "plantId": gr.PlantID, "userId": gr.UserID, "name": gr.Name, "tag": gr.Tag, "desc": gr.Desc, "content": gr.Content, "imgList": imgs, }) } if list == nil { list = []map[string]interface{}{} } return list } // queryOssList 批量查询 Oss 图片信息(供 WikiDetailHandler 使用) func queryOssList(svcCtx *svc.ServiceContext, ossIds []string) []map[string]interface{} { if len(ossIds) == 0 { return []map[string]interface{}{} } type OssRow struct { ID string `gorm:"column:id"` Name string `gorm:"column:name"` Url string `gorm:"column:url"` Tag string `gorm:"column:tag"` Key string `gorm:"column:key"` Suffix string `gorm:"column:suffix"` CreatedAt time.Time `gorm:"column:created_at"` UpdatedAt time.Time `gorm:"column:updated_at"` } var rows []OssRow svcCtx.DB.Table("sundynix_oss").Where("id IN ?", ossIds).Find(&rows) ossMap := make(map[string]OssRow) for _, row := range rows { ossMap[row.ID] = row } var result []map[string]interface{} for _, id := range ossIds { if row, ok := ossMap[id]; ok { result = append(result, map[string]interface{}{ "id": row.ID, "name": row.Name, "url": row.Url, "tag": row.Tag, "key": row.Key, "suffix": row.Suffix, "createdAt": row.CreatedAt.Format(time.RFC3339), "updatedAt": row.UpdatedAt.Format(time.RFC3339), "createdAtStr": row.CreatedAt.Format("2006-01-02 15:04:05"), }) } } return result } func AiChatSyncHandler(svcCtx *svc.ServiceContext) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { resp, err := svcCtx.PlantRpc.SyncAllWikiVector(r.Context(), &plantPb.PageReq{}) if err != nil { response.Fail(w, err.Error()) return } response.OkWithMsg(w, resp.Msg) } } func WikiSyncQdrantHandler(svcCtx *svc.ServiceContext) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { wikiID := idFromQuery(r) if wikiID == "" { var req types.IdReq _ = httpx.Parse(r, &req) wikiID = req.Id } if wikiID == "" { response.Fail(w, "wikiId 不能为空") return } if _, err := svcCtx.PlantRpc.SyncWikiVector(r.Context(), &plantPb.SyncWikiVectorReq{WikiId: wikiID}); err != nil { response.Fail(w, err.Error()) return } response.Ok(w) } } func WikiDeleteQdrantHandler(svcCtx *svc.ServiceContext) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { wikiID := idFromQuery(r) if wikiID == "" { var req types.IdReq _ = httpx.Parse(r, &req) wikiID = req.Id } if wikiID == "" { response.Fail(w, "wikiId 不能为空") return } if _, err := svcCtx.PlantRpc.DeleteWikiVector(r.Context(), &plantPb.SyncWikiVectorReq{WikiId: wikiID}); err != nil { response.Fail(w, err.Error()) return } response.Ok(w) } } func WikiUploadImgHandler(svcCtx *svc.ServiceContext) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { response.FailWithCode(w, 409, "设计/百科图片上传已迁移到 file-api,请先调用文件服务上传,再将返回的文件 id 作为 ossIds 传给 plant") } } func BadgeConfigDetailHandler(svcCtx *svc.ServiceContext) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { resp, err := svcCtx.PlantRpc.GetBadgeConfigDetail(r.Context(), &plantPb.IdReq{Id: idFromQuery(r)}) if err != nil { response.Fail(w, err.Error()) return } response.OkWithData(w, resp) } } func BadgeConfigDeleteHandler(svcCtx *svc.ServiceContext) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { if _, err := svcCtx.PlantRpc.DeleteBadgeConfig(r.Context(), &plantPb.IdsReq{Ids: []string{idFromQuery(r)}}); err != nil { response.Fail(w, err.Error()) return } response.Ok(w) } } func LevelConfigDetailHandler(svcCtx *svc.ServiceContext) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { resp, err := svcCtx.PlantRpc.GetLevelConfigDetail(r.Context(), &plantPb.IdReq{Id: idFromQuery(r)}) if err != nil { response.Fail(w, err.Error()) return } response.OkWithData(w, resp) } } func MediaCheckCallbackHandler(svcCtx *svc.ServiceContext) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { var payload struct { TraceID string `json:"traceId"` PostID string `json:"postId"` OssID string `json:"ossId"` UserID string `json:"userId"` Status int32 `json:"status"` Type int32 `json:"type"` ErrMsg string `json:"errMsg"` } if err := json.NewDecoder(r.Body).Decode(&payload); err != nil { response.Fail(w, err.Error()) return } if _, err := svcCtx.PlantRpc.MediaCheckCallback(r.Context(), &plantPb.MediaCheckCallbackReq{ TraceId: payload.TraceID, PostId: payload.PostID, OssId: payload.OssID, UserId: payload.UserID, Status: payload.Status, Type: payload.Type, ErrMsg: payload.ErrMsg, }); err != nil { response.Fail(w, err.Error()) return } response.Ok(w) } }