package controller import ( "context" "net/http" "strconv" "time" "dubbo.apache.org/dubbo-go/v3/client" "dubbo.apache.org/dubbo-go/v3/common/constant" "github.com/gin-gonic/gin" "github.com/topfans/backend/gateway/dto" "github.com/topfans/backend/gateway/pkg/response" pbCommon "github.com/topfans/backend/pkg/proto/common" pbSocial "github.com/topfans/backend/pkg/proto/social" "go.uber.org/zap" "github.com/topfans/backend/pkg/logger" ) // SocialController 社交相关控制器 type SocialController struct { socialService pbSocial.SocialService } // NewSocialController 创建社交控制器 func NewSocialController(dubboClient *client.Client) (*SocialController, error) { // 创建 SocialService 客户端 socialService, err := pbSocial.NewSocialService(dubboClient) if err != nil { return nil, err } return &SocialController{ socialService: socialService, }, nil } // SendFriendRequest 发送好友请求 // @Summary 发送好友请求 // @Description 向指定用户发送好友请求 // @Tags social // @Accept json // @Produce json // @Security BearerAuth // @Param request body object{friend_user_id=integer,message=string} true "好友请求参数" // @Success 200 {object} response.Response // @Router /api/v1/social/friend-requests [post] func (ctrl *SocialController) SendFriendRequest(c *gin.Context) { // 从上下文获取用户信息 userID, exists := c.Get("user_id") if !exists { response.Error(c, http.StatusUnauthorized, "未授权") return } starID, exists := c.Get("star_id") if !exists { response.Error(c, http.StatusUnauthorized, "未授权") return } // 解析请求参数 var req struct { FriendUserID int64 `json:"friend_user_id" binding:"required"` Message string `json:"message"` } if err := c.ShouldBindJSON(&req); err != nil { response.Error(c, http.StatusBadRequest, "参数错误: "+err.Error()) return } // 设置上下文和 Dubbo attachments ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() ctx = context.WithValue(ctx, constant.AttachmentKey, map[string]interface{}{ "user_id": strconv.FormatInt(userID.(int64), 10), "star_id": strconv.FormatInt(starID.(int64), 10), }) // 调用 RPC resp, err := ctrl.socialService.SendFriendRequest(ctx, &pbSocial.SendFriendRequestRequest{ FriendUserId: req.FriendUserID, Message: req.Message, }) if err != nil { logger.Logger.Error("SendFriendRequest RPC failed", zap.Int64("user_id", userID.(int64)), zap.Int64("friend_user_id", req.FriendUserID), zap.Error(err), ) response.Error(c, http.StatusInternalServerError, "服务调用失败") return } // 处理响应 if resp.Base.Code != pbCommon.StatusCode_STATUS_OK { response.ErrorWithCode(c, int(resp.Base.Code), resp.Base.Message) return } response.Success(c, gin.H{ "request_id": resp.RequestId, "status": resp.Status, "created_at": resp.CreatedAt, "expires_at": resp.ExpiresAt, }) } // GetFriendRequests 获取好友请求列表 // @Summary 获取好友请求列表 // @Description 获取当前用户的好友请求列表 // @Tags social // @Accept json // @Produce json // @Security BearerAuth // @Param type query string false "请求类型: received/sent" // @Param status query string false "请求状态" // @Param page query int false "页码,默认1" // @Param page_size query int false "每页数量,默认20" // @Success 200 {object} response.Response // @Router /api/v1/social/friend-requests [get] func (ctrl *SocialController) GetFriendRequests(c *gin.Context) { userID, _ := c.Get("user_id") starID, _ := c.Get("star_id") // 解析查询参数 requestType := c.DefaultQuery("type", "received") // received/sent status := c.Query("status") page, _ := strconv.Atoi(c.DefaultQuery("page", "1")) pageSize, _ := strconv.Atoi(c.DefaultQuery("page_size", "20")) // 设置上下文 ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() ctx = context.WithValue(ctx, constant.AttachmentKey, map[string]interface{}{ "user_id": strconv.FormatInt(userID.(int64), 10), "star_id": strconv.FormatInt(starID.(int64), 10), }) // 调用 RPC resp, err := ctrl.socialService.GetFriendRequests(ctx, &pbSocial.GetFriendRequestsRequest{ Type: requestType, Status: status, Page: int32(page), PageSize: int32(pageSize), }) if err != nil { logger.Logger.Error("GetFriendRequests RPC failed", zap.Error(err)) response.Error(c, http.StatusInternalServerError, "服务调用失败") return } if resp.Base.Code != pbCommon.StatusCode_STATUS_OK { response.ErrorWithCode(c, int(resp.Base.Code), resp.Base.Message) return } // 转换响应 items := make([]map[string]interface{}, 0, len(resp.Items)) for _, item := range resp.Items { items = append(items, dto.ConvertFriendRequest(item)) } // 计算 has_more hasMore := int64(resp.Page)*int64(resp.PageSize) < resp.Total response.Success(c, gin.H{ "items": items, "total": resp.Total, "page": resp.Page, "page_size": resp.PageSize, "has_more": hasMore, }) } // HandleFriendRequest 处理好友请求(接受/拒绝) // @Summary 处理好友请求 // @Description 接受或拒绝好友请求 // @Tags social // @Accept json // @Produce json // @Security BearerAuth // @Param request body object{request_id=integer,action=string} true "处理请求参数: action=accept/reject" // @Success 200 {object} response.Response // @Router /api/v1/social/friend-requests/handle [post] func (ctrl *SocialController) HandleFriendRequest(c *gin.Context) { userID, _ := c.Get("user_id") starID, _ := c.Get("star_id") // 解析请求参数 var req struct { RequestID int64 `json:"request_id" binding:"required"` Action string `json:"action" binding:"required,oneof=accept reject"` // accept/reject } if err := c.ShouldBindJSON(&req); err != nil { response.Error(c, http.StatusBadRequest, "参数错误: "+err.Error()) return } // 设置上下文 ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() ctx = context.WithValue(ctx, constant.AttachmentKey, map[string]interface{}{ "user_id": strconv.FormatInt(userID.(int64), 10), "star_id": strconv.FormatInt(starID.(int64), 10), }) // 调用 RPC resp, err := ctrl.socialService.HandleFriendRequest(ctx, &pbSocial.HandleFriendRequestRequest{ RequestId: req.RequestID, Action: req.Action, }) if err != nil { logger.Logger.Error("HandleFriendRequest RPC failed", zap.Error(err)) response.Error(c, http.StatusInternalServerError, "服务调用失败") return } if resp.Base.Code != pbCommon.StatusCode_STATUS_OK { response.ErrorWithCode(c, int(resp.Base.Code), resp.Base.Message) return } response.Success(c, gin.H{ "action": resp.Action, "friendship_created": resp.FriendshipCreated, "processed_at": resp.ProcessedAt, }) } // GetFriendList 获取好友列表 // @Summary 获取好友列表 // @Description 获取当前用户的好友列表 // @Tags social // @Accept json // @Produce json // @Security BearerAuth // @Param keyword query string false "搜索关键词" // @Param page query int false "页码,默认1" // @Param page_size query int false "每页数量,默认20" // @Success 200 {object} response.Response // @Router /api/v1/social/friends [get] func (ctrl *SocialController) GetFriendList(c *gin.Context) { userID, _ := c.Get("user_id") starID, _ := c.Get("star_id") // 解析查询参数 keyword := c.Query("keyword") page, _ := strconv.Atoi(c.DefaultQuery("page", "1")) pageSize, _ := strconv.Atoi(c.DefaultQuery("page_size", "20")) // 设置上下文 ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() ctx = context.WithValue(ctx, constant.AttachmentKey, map[string]interface{}{ "user_id": strconv.FormatInt(userID.(int64), 10), "star_id": strconv.FormatInt(starID.(int64), 10), }) // 调用 RPC resp, err := ctrl.socialService.GetFriendList(ctx, &pbSocial.GetFriendListRequest{ Keyword: keyword, Page: int32(page), PageSize: int32(pageSize), }) if err != nil { logger.Logger.Error("GetFriendList RPC failed", zap.Error(err)) response.Error(c, http.StatusInternalServerError, "服务调用失败") return } if resp.Base.Code != pbCommon.StatusCode_STATUS_OK { response.ErrorWithCode(c, int(resp.Base.Code), resp.Base.Message) return } // 转换响应 items := make([]map[string]interface{}, 0, len(resp.Items)) for _, item := range resp.Items { items = append(items, dto.ConvertFriendship(item)) } // 计算 has_more hasMore := int64(resp.Page)*int64(resp.PageSize) < resp.Total response.Success(c, gin.H{ "items": items, "total": resp.Total, "page": resp.Page, "page_size": resp.PageSize, "has_more": hasMore, }) } // DeleteFriend 删除好友 // @Summary 删除好友 // @Description 删除指定好友 // @Tags social // @Accept json // @Produce json // @Security BearerAuth // @Param request body object{friend_user_id=integer} true "好友用户ID" // @Success 200 {object} response.Response // @Router /api/v1/social/friends [delete] func (ctrl *SocialController) DeleteFriend(c *gin.Context) { userID, _ := c.Get("user_id") starID, _ := c.Get("star_id") // 解析请求参数 var req struct { FriendUserID int64 `json:"friend_user_id" binding:"required"` } if err := c.ShouldBindJSON(&req); err != nil { response.Error(c, http.StatusBadRequest, "参数错误: "+err.Error()) return } // 设置上下文 ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() ctx = context.WithValue(ctx, constant.AttachmentKey, map[string]interface{}{ "user_id": strconv.FormatInt(userID.(int64), 10), "star_id": strconv.FormatInt(starID.(int64), 10), }) // 调用 RPC resp, err := ctrl.socialService.DeleteFriend(ctx, &pbSocial.DeleteFriendRequest{ FriendUserId: req.FriendUserID, }) if err != nil { logger.Logger.Error("DeleteFriend RPC failed", zap.Error(err)) response.Error(c, http.StatusInternalServerError, "服务调用失败") return } if resp.Base.Code != pbCommon.StatusCode_STATUS_OK { response.ErrorWithCode(c, int(resp.Base.Code), resp.Base.Message) return } response.Success(c, gin.H{ "success": resp.Success, }) } // SetFriendRemark 设置好友备注 // @Summary 设置好友备注 // @Description 设置指定好友的备注名称 // @Tags social // @Accept json // @Produce json // @Security BearerAuth // @Param request body object{friend_user_id=integer,remark=string} true "好友ID和备注" // @Success 200 {object} response.Response // @Router /api/v1/social/friends/remark [put] func (ctrl *SocialController) SetFriendRemark(c *gin.Context) { userID, _ := c.Get("user_id") starID, _ := c.Get("star_id") // 解析请求参数 var req struct { FriendUserID int64 `json:"friend_user_id" binding:"required"` Remark string `json:"remark" binding:"max=50"` } if err := c.ShouldBindJSON(&req); err != nil { response.Error(c, http.StatusBadRequest, "参数错误: "+err.Error()) return } // 设置上下文 ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() ctx = context.WithValue(ctx, constant.AttachmentKey, map[string]interface{}{ "user_id": strconv.FormatInt(userID.(int64), 10), "star_id": strconv.FormatInt(starID.(int64), 10), }) // 调用 RPC resp, err := ctrl.socialService.SetFriendRemark(ctx, &pbSocial.SetFriendRemarkRequest{ FriendUserId: req.FriendUserID, Remark: req.Remark, }) if err != nil { logger.Logger.Error("SetFriendRemark RPC failed", zap.Error(err)) response.Error(c, http.StatusInternalServerError, "服务调用失败") return } if resp.Base.Code != pbCommon.StatusCode_STATUS_OK { response.ErrorWithCode(c, int(resp.Base.Code), resp.Base.Message) return } response.Success(c, gin.H{ "remark": resp.Remark, }) } // CheckFriendship 检查好友关系 // @Summary 检查好友关系 // @Description 检查当前用户与指定用户是否为好友关系 // @Tags social // @Accept json // @Produce json // @Security BearerAuth // @Param friend_user_id query int true "好友用户ID" // @Success 200 {object} response.Response // @Router /api/v1/social/friendship/check [get] func (ctrl *SocialController) CheckFriendship(c *gin.Context) { userID, _ := c.Get("user_id") starID, _ := c.Get("star_id") // 解析查询参数 friendUserID, err := strconv.ParseInt(c.Query("friend_user_id"), 10, 64) if err != nil { response.Error(c, http.StatusBadRequest, "参数错误: friend_user_id 必须为数字") return } // 设置上下文 ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() ctx = context.WithValue(ctx, constant.AttachmentKey, map[string]interface{}{ "user_id": strconv.FormatInt(userID.(int64), 10), "star_id": strconv.FormatInt(starID.(int64), 10), }) // 调用 RPC resp, err := ctrl.socialService.CheckFriendship(ctx, &pbSocial.CheckFriendshipRequest{ UserId: userID.(int64), FriendUserId: friendUserID, }) if err != nil { logger.Logger.Error("CheckFriendship RPC failed", zap.Error(err)) response.Error(c, http.StatusInternalServerError, "服务调用失败") return } if resp.Base.Code != pbCommon.StatusCode_STATUS_OK { response.ErrorWithCode(c, int(resp.Base.Code), resp.Base.Message) return } response.Success(c, gin.H{ "is_friend": resp.IsFriend, }) } // GetFriendCount 获取好友数量 // @Summary 获取好友数量 // @Description 获取当前用户的好友数量 // @Tags social // @Accept json // @Produce json // @Security BearerAuth // @Success 200 {object} response.Response // @Router /api/v1/social/friends/count [get] func (ctrl *SocialController) GetFriendCount(c *gin.Context) { userID, _ := c.Get("user_id") starID, _ := c.Get("star_id") // 设置上下文 ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() ctx = context.WithValue(ctx, constant.AttachmentKey, map[string]interface{}{ "user_id": strconv.FormatInt(userID.(int64), 10), "star_id": strconv.FormatInt(starID.(int64), 10), }) // 调用 RPC resp, err := ctrl.socialService.GetFriendCount(ctx, &pbSocial.GetFriendCountRequest{}) if err != nil { logger.Logger.Error("GetFriendCount RPC failed", zap.Error(err)) response.Error(c, http.StatusInternalServerError, "服务调用失败") return } if resp.Base.Code != pbCommon.StatusCode_STATUS_OK { response.ErrorWithCode(c, int(resp.Base.Code), resp.Base.Message) return } response.Success(c, gin.H{ "count": resp.Count, }) } // SearchUserForFriend 查找用户信息(用于加好友) // @Summary 查找用户 // @Description 根据用户ID查找用户信息,用于添加好友 // @Tags social // @Accept json // @Produce json // @Security BearerAuth // @Param friend_fan_profile_id query int true "粉丝档案ID" // @Success 200 {object} response.Response // @Router /api/v1/social/search-user [get] func (ctrl *SocialController) SearchUserForFriend(c *gin.Context) { userID, _ := c.Get("user_id") starID, _ := c.Get("star_id") // 获取查询参数(前端传 friend_fan_profile_id) friendFanProfileIDStr := c.Query("friend_fan_profile_id") if friendFanProfileIDStr == "" { // 兼容旧参数名 friend_user_id friendFanProfileIDStr = c.Query("friend_user_id") } if friendFanProfileIDStr == "" { response.Error(c, http.StatusBadRequest, "参数 friend_fan_profile_id 不能为空") return } friendFanProfileID, err := strconv.ParseInt(friendFanProfileIDStr, 10, 64) if err != nil { response.Error(c, http.StatusBadRequest, "参数 friend_fan_profile_id 格式错误") return } // 设置上下文 ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() ctx = context.WithValue(ctx, constant.AttachmentKey, map[string]interface{}{ "user_id": strconv.FormatInt(userID.(int64), 10), "star_id": strconv.FormatInt(starID.(int64), 10), }) // 调用 RPC resp, err := ctrl.socialService.SearchUserForFriend(ctx, &pbSocial.SearchUserForFriendRequest{ FriendFanProfileId: friendFanProfileID, }) if err != nil { logger.Logger.Error("SearchUserForFriend RPC failed", zap.Int64("user_id", userID.(int64)), zap.Int64("friend_fan_profile_id", friendFanProfileID), zap.Error(err), ) response.Error(c, http.StatusInternalServerError, "服务调用失败") return } if resp.Base.Code != pbCommon.StatusCode_STATUS_OK { response.ErrorWithCode(c, int(resp.Base.Code), resp.Base.Message) return } // 构建响应 response.Success(c, dto.ToUserSearchResultDTO(resp.User)) } // GetUsersPaged 获取分页用户列表 // @Summary 获取分页用户列表 // @Description 获取同一明星身份下的分页用户列表,包含用户ID、展馆所有者ID、昵称、等级 // @Tags social // @Accept json // @Produce json // @Security BearerAuth // @Param page query int false "页码,默认1" // @Param page_size query int false "每页数量,默认20,最大100" // @Success 200 {object} response.Response // @Router /api/v1/social/users [get] func (ctrl *SocialController) GetUsersPaged(c *gin.Context) { userID, _ := c.Get("user_id") starID, _ := c.Get("star_id") page, _ := strconv.Atoi(c.DefaultQuery("page", "1")) pageSize, _ := strconv.Atoi(c.DefaultQuery("page_size", "20")) ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() ctx = context.WithValue(ctx, constant.AttachmentKey, map[string]interface{}{ "user_id": strconv.FormatInt(userID.(int64), 10), "star_id": strconv.FormatInt(starID.(int64), 10), }) resp, err := ctrl.socialService.GetUsersPaged(ctx, &pbSocial.GetUsersPagedRequest{ Page: int32(page), PageSize: int32(pageSize), }) if err != nil { logger.Logger.Error("GetUsersPaged RPC failed", zap.Error(err)) response.Error(c, http.StatusInternalServerError, "服务调用失败") return } if resp.Base.Code != pbCommon.StatusCode_STATUS_OK { response.ErrorWithCode(c, int(resp.Base.Code), resp.Base.Message) return } users := dto.ToPagedUsersDTO(resp.Users) hasMore := int64(resp.Page)*int64(resp.PageSize) < resp.Total response.Success(c, gin.H{ "users": users, "total": resp.Total, "page": resp.Page, "page_size": resp.PageSize, "has_more": hasMore, }) } // GetRandomUsers 获取随机用户(同一明星下) // @Summary 获取随机用户 // @Description 获取同一明星身份下的随机推荐用户 // @Tags social // @Accept json // @Produce json // @Security BearerAuth // @Param count query int false "获取数量,默认1,最大100" // @Success 200 {object} response.Response // @Router /api/v1/social/random-users [get] func (ctrl *SocialController) GetRandomUsers(c *gin.Context) { // 1. 获取用户信息(从 Token 中) userID, exists := c.Get("user_id") if !exists { response.Error(c, http.StatusUnauthorized, "未授权") return } starID, exists := c.Get("star_id") if !exists { response.Error(c, http.StatusUnauthorized, "未授权") return } // 2. 解析查询参数 countStr := c.DefaultQuery("count", "1") count, err := strconv.ParseInt(countStr, 10, 32) if err != nil || count <= 0 { count = 1 // 默认返回1个 } if count > 100 { count = 100 // 最大限制100个 } // 3. 设置上下文 ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() ctx = context.WithValue(ctx, constant.AttachmentKey, map[string]interface{}{ "user_id": strconv.FormatInt(userID.(int64), 10), "star_id": strconv.FormatInt(starID.(int64), 10), }) // 4. 调用 RPC resp, err := ctrl.socialService.GetRandomUsers(ctx, &pbSocial.GetRandomUsersRequest{ Count: int32(count), }) if err != nil { logger.Logger.Error("GetRandomUsers RPC failed", zap.Int64("user_id", userID.(int64)), zap.Int64("star_id", starID.(int64)), zap.Error(err), ) response.Error(c, http.StatusInternalServerError, "服务调用失败") return } if resp.Base.Code != pbCommon.StatusCode_STATUS_OK { response.ErrorWithCode(c, int(resp.Base.Code), resp.Base.Message) return } // 5. 构建响应 response.Success(c, dto.ToRandomUsersDTO(resp.Users)) } // LikeAsset 点赞资产 // @Summary 点赞资产 // @Description 对指定资产进行点赞 // @Tags social // @Accept json // @Produce json // @Security BearerAuth // @Param asset_id path int true "资产ID" // @Success 200 {object} response.Response // @Router /api/v1/social/assets/{asset_id}/like [post] func (ctrl *SocialController) LikeAsset(c *gin.Context) { // 1. 从上下文获取用户信息 userID, exists := c.Get("user_id") if !exists { response.Error(c, http.StatusUnauthorized, "未授权") return } starID, exists := c.Get("star_id") if !exists { response.Error(c, http.StatusUnauthorized, "未授权") return } // 2. 解析资产ID assetIDStr := c.Param("asset_id") assetID, err := strconv.ParseInt(assetIDStr, 10, 64) if err != nil { response.Error(c, http.StatusBadRequest, "参数错误: asset_id 必须为数字") return } // 3. 设置上下文 ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() ctx = context.WithValue(ctx, constant.AttachmentKey, map[string]interface{}{ "user_id": strconv.FormatInt(userID.(int64), 10), "star_id": strconv.FormatInt(starID.(int64), 10), }) // 4. 调用 RPC resp, err := ctrl.socialService.LikeAsset(ctx, &pbSocial.LikeAssetRequest{ AssetId: assetID, }) if err != nil { logger.Logger.Error("LikeAsset RPC failed", zap.Int64("user_id", userID.(int64)), zap.Int64("star_id", starID.(int64)), zap.Int64("asset_id", assetID), zap.Error(err), ) // 优先使用响应中的错误信息 if resp != nil && resp.Base != nil && resp.Base.Message != "" { response.ErrorWithCode(c, int(resp.Base.Code), resp.Base.Message) return } // 解析 RPC 错误字符串 code, msg := parseRPCError(err) response.ErrorWithCode(c, code, msg) return } if resp.Base.Code != pbCommon.StatusCode_STATUS_OK { response.ErrorWithCode(c, int(resp.Base.Code), resp.Base.Message) return } // 5. 构建响应 response.Success(c, gin.H{ "asset_id": resp.AssetId, "new_like_count": resp.NewLikeCount, }) } // UnlikeAsset 取消点赞资产 // @Summary 取消点赞 // @Description 取消对指定资产的点赞 // @Tags social // @Accept json // @Produce json // @Security BearerAuth // @Param asset_id path int true "资产ID" // @Success 200 {object} response.Response // @Router /api/v1/social/assets/{asset_id}/like [delete] func (ctrl *SocialController) UnlikeAsset(c *gin.Context) { // 1. 从上下文获取用户信息 userID, exists := c.Get("user_id") if !exists { response.Error(c, http.StatusUnauthorized, "未授权") return } starID, exists := c.Get("star_id") if !exists { response.Error(c, http.StatusUnauthorized, "未授权") return } // 2. 解析资产ID assetIDStr := c.Param("asset_id") assetID, err := strconv.ParseInt(assetIDStr, 10, 64) if err != nil { response.Error(c, http.StatusBadRequest, "参数错误: asset_id 必须为数字") return } // 3. 设置上下文 ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() ctx = context.WithValue(ctx, constant.AttachmentKey, map[string]interface{}{ "user_id": strconv.FormatInt(userID.(int64), 10), "star_id": strconv.FormatInt(starID.(int64), 10), }) // 4. 调用 RPC resp, err := ctrl.socialService.UnlikeAsset(ctx, &pbSocial.UnlikeAssetRequest{ AssetId: assetID, }) if err != nil { logger.Logger.Error("UnlikeAsset RPC failed", zap.Int64("user_id", userID.(int64)), zap.Int64("star_id", starID.(int64)), zap.Int64("asset_id", assetID), zap.Error(err), ) // 优先使用响应中的错误信息 if resp != nil && resp.Base != nil && resp.Base.Message != "" { response.ErrorWithCode(c, int(resp.Base.Code), resp.Base.Message) return } // 解析 RPC 错误字符串 code, msg := parseRPCError(err) response.ErrorWithCode(c, code, msg) return } if resp.Base.Code != pbCommon.StatusCode_STATUS_OK { response.ErrorWithCode(c, int(resp.Base.Code), resp.Base.Message) return } // 5. 构建响应 response.Success(c, gin.H{ "asset_id": resp.AssetId, "new_like_count": resp.NewLikeCount, }) } // 注意:CheckAssetLike 已被删除 // 检查点赞状态请通过 GET /api/v1/assets/:asset_id 获取,响应中的 is_liked 字段表示当前用户是否已点赞