Compare commits
No commits in common. "63f46da2b44bed8a7239fbcfa0dcf3406b9cf01b" and "3ab66f9fd673ecd8f7929f50ac2ff77539106bab" have entirely different histories.
63f46da2b4
...
3ab66f9fd6
@ -716,110 +716,4 @@ func (ctrl *GalleryController) GetInspirationFlow(c *gin.Context) {
|
||||
)
|
||||
|
||||
response.Success(c, flowDTO)
|
||||
}
|
||||
|
||||
// GetUserExhibitedAssets 获取他人展出的作品列表
|
||||
// @Summary 获取他人展出的作品列表
|
||||
// @Description 获取指定用户正在展出的作品列表
|
||||
// @Tags galleries
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Security BearerAuth
|
||||
// @Param user_id path int true "用户ID"
|
||||
// @Param page query int false "页码" default(1)
|
||||
// @Param page_size query int false "每页数量" default(20)
|
||||
// @Success 200 {object} response.Response{data=dto.GetMyExhibitedAssetsResponseDTO}
|
||||
// @Router /api/v1/users/{user_id}/exhibited-assets [get]
|
||||
func (ctrl *GalleryController) GetUserExhibitedAssets(c *gin.Context) {
|
||||
userIDStr := c.Param("user_id")
|
||||
targetUserID, err := strconv.ParseInt(userIDStr, 10, 64)
|
||||
if err != nil {
|
||||
response.Error(c, http.StatusBadRequest, "无效的用户ID")
|
||||
return
|
||||
}
|
||||
|
||||
callerUserID, exists := c.Get("user_id")
|
||||
if !exists {
|
||||
response.Error(c, http.StatusUnauthorized, "用户未认证")
|
||||
return
|
||||
}
|
||||
|
||||
callerStarID, exists := c.Get("star_id")
|
||||
if !exists {
|
||||
response.Error(c, http.StatusUnauthorized, "明星身份未设置")
|
||||
return
|
||||
}
|
||||
|
||||
page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
|
||||
pageSize, _ := strconv.Atoi(c.DefaultQuery("page_size", "20"))
|
||||
if page <= 0 {
|
||||
page = 1
|
||||
}
|
||||
if pageSize <= 0 {
|
||||
pageSize = 20
|
||||
}
|
||||
if pageSize > 100 {
|
||||
pageSize = 100
|
||||
}
|
||||
|
||||
ctx := context.WithValue(context.Background(), constant.AttachmentKey, map[string]interface{}{
|
||||
"user_id": strconv.FormatInt(callerUserID.(int64), 10),
|
||||
"star_id": strconv.FormatInt(callerStarID.(int64), 10),
|
||||
})
|
||||
|
||||
resp, err := ctrl.galleryService.GetUserExhibitedAssets(ctx, &pbGallery.GetUserExhibitedAssetsRequest{
|
||||
UserId: targetUserID,
|
||||
Page: int32(page),
|
||||
PageSize: int32(pageSize),
|
||||
})
|
||||
if err != nil {
|
||||
logger.Logger.Error("GetUserExhibitedAssets RPC failed",
|
||||
zap.Any("caller_user_id", callerUserID),
|
||||
zap.Any("star_id", callerStarID),
|
||||
zap.Int64("target_user_id", targetUserID),
|
||||
zap.Error(err),
|
||||
)
|
||||
_, msg := parseRPCError(err)
|
||||
errorMsg := "获取他人展出的作品列表失败"
|
||||
if msg != "" {
|
||||
errorMsg += "," + msg
|
||||
}
|
||||
response.Error(c, http.StatusInternalServerError, errorMsg)
|
||||
return
|
||||
}
|
||||
|
||||
if resp.Base.Code != pbCommon.StatusCode_STATUS_OK {
|
||||
response.Error(c, http.StatusBadRequest, resp.Base.Message)
|
||||
return
|
||||
}
|
||||
|
||||
items := make([]*dto.ExhibitedAssetItemDTO, 0, len(resp.Data.Items))
|
||||
for _, item := range resp.Data.Items {
|
||||
items = append(items, &dto.ExhibitedAssetItemDTO{
|
||||
AssetID: item.AssetId,
|
||||
Name: item.Name,
|
||||
CoverURL: item.CoverUrl,
|
||||
LikeCount: item.LikeCount,
|
||||
ExhibitedAt: item.ExhibitedAt,
|
||||
ExpireAt: item.ExpireAt,
|
||||
Earnings: item.Earnings,
|
||||
})
|
||||
}
|
||||
|
||||
result := &dto.GetMyExhibitedAssetsResponseDTO{
|
||||
Items: items,
|
||||
Page: resp.Data.Page,
|
||||
PageSize: resp.Data.PageSize,
|
||||
Total: resp.Data.Total,
|
||||
HasMore: resp.Data.HasMore,
|
||||
}
|
||||
|
||||
logger.Logger.Info("GetUserExhibitedAssets success",
|
||||
zap.Any("caller_user_id", callerUserID),
|
||||
zap.Any("star_id", callerStarID),
|
||||
zap.Int64("target_user_id", targetUserID),
|
||||
zap.Int32("count", int32(len(items))),
|
||||
)
|
||||
|
||||
response.Success(c, result)
|
||||
}
|
||||
@ -947,201 +947,3 @@ func (ctrl *SocialController) GetMyLikedAssets(c *gin.Context) {
|
||||
"has_more": resp.Data.HasMore,
|
||||
})
|
||||
}
|
||||
|
||||
// GetMyTodayLikedAssets 获取我今日点赞的作品列表
|
||||
// @Summary 获取我今日点赞的作品列表
|
||||
// @Description 获取当前用户今日点赞过的作品列表(只返回展出中且未过期的)
|
||||
// @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/me/today-liked-assets [get]
|
||||
func (ctrl *SocialController) GetMyTodayLikedAssets(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.GetMyTodayLikedAssets(ctx, &pbSocial.GetMyTodayLikedAssetsRequest{
|
||||
Page: int32(page),
|
||||
PageSize: int32(pageSize),
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
logger.Logger.Error("GetMyTodayLikedAssets 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.Data.Items))
|
||||
for _, item := range resp.Data.Items {
|
||||
items = append(items, map[string]interface{}{
|
||||
"asset_id": item.AssetId,
|
||||
"name": item.Name,
|
||||
"cover_url": item.CoverUrl,
|
||||
"like_count": item.LikeCount,
|
||||
"liked_at": item.LikedAt,
|
||||
"earnings": item.Earnings,
|
||||
})
|
||||
}
|
||||
|
||||
response.Success(c, gin.H{
|
||||
"items": items,
|
||||
"total": resp.Data.Total,
|
||||
"page": resp.Data.Page,
|
||||
"page_size": resp.Data.PageSize,
|
||||
"has_more": resp.Data.HasMore,
|
||||
})
|
||||
}
|
||||
|
||||
// GetMyWeekLikedAssets 获取我本周点赞的作品列表
|
||||
// @Summary 获取我本周点赞的作品列表
|
||||
// @Description 获取当前用户本周点赞过的作品列表(只返回展出中且未过期的)
|
||||
// @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/me/week-liked-assets [get]
|
||||
func (ctrl *SocialController) GetMyWeekLikedAssets(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.GetMyWeekLikedAssets(ctx, &pbSocial.GetMyWeekLikedAssetsRequest{
|
||||
Page: int32(page),
|
||||
PageSize: int32(pageSize),
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
logger.Logger.Error("GetMyWeekLikedAssets 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.Data.Items))
|
||||
for _, item := range resp.Data.Items {
|
||||
items = append(items, map[string]interface{}{
|
||||
"asset_id": item.AssetId,
|
||||
"name": item.Name,
|
||||
"cover_url": item.CoverUrl,
|
||||
"like_count": item.LikeCount,
|
||||
"liked_at": item.LikedAt,
|
||||
"earnings": item.Earnings,
|
||||
})
|
||||
}
|
||||
|
||||
response.Success(c, gin.H{
|
||||
"items": items,
|
||||
"total": resp.Data.Total,
|
||||
"page": resp.Data.Page,
|
||||
"page_size": resp.Data.PageSize,
|
||||
"has_more": resp.Data.HasMore,
|
||||
})
|
||||
}
|
||||
|
||||
// GetUserLikedAssets 获取他人点赞的作品列表
|
||||
// @Summary 获取他人点赞的作品列表
|
||||
// @Description 获取指定用户点赞过的作品列表(只返回展出中且未过期的)
|
||||
// @Tags social
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Security BearerAuth
|
||||
// @Param user_id path int true "用户ID"
|
||||
// @Param page query int false "页码,默认1"
|
||||
// @Param page_size query int false "每页数量,默认20,最大100"
|
||||
// @Success 200 {object} response.Response
|
||||
// @Router /api/v1/users/{user_id}/liked-assets [get]
|
||||
func (ctrl *SocialController) GetUserLikedAssets(c *gin.Context) {
|
||||
userIDStr := c.Param("user_id")
|
||||
targetUserID, err := strconv.ParseInt(userIDStr, 10, 64)
|
||||
if err != nil {
|
||||
response.Error(c, http.StatusBadRequest, "无效的用户ID")
|
||||
return
|
||||
}
|
||||
|
||||
callerUserID, _ := c.Get("user_id")
|
||||
callerStarID, _ := 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(callerUserID.(int64), 10),
|
||||
"star_id": strconv.FormatInt(callerStarID.(int64), 10),
|
||||
})
|
||||
|
||||
resp, err := ctrl.socialService.GetUserLikedAssets(ctx, &pbSocial.GetUserLikedAssetsRequest{
|
||||
UserId: targetUserID,
|
||||
Page: int32(page),
|
||||
PageSize: int32(pageSize),
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
logger.Logger.Error("GetUserLikedAssets 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.Data.Items))
|
||||
for _, item := range resp.Data.Items {
|
||||
items = append(items, map[string]interface{}{
|
||||
"asset_id": item.AssetId,
|
||||
"name": item.Name,
|
||||
"cover_url": item.CoverUrl,
|
||||
"like_count": item.LikeCount,
|
||||
"liked_at": item.LikedAt,
|
||||
"earnings": item.Earnings,
|
||||
})
|
||||
}
|
||||
|
||||
response.Success(c, gin.H{
|
||||
"items": items,
|
||||
"total": resp.Data.Total,
|
||||
"page": resp.Data.Page,
|
||||
"page_size": resp.Data.PageSize,
|
||||
"has_more": resp.Data.HasMore,
|
||||
})
|
||||
}
|
||||
|
||||
@ -100,11 +100,8 @@ func SetupRouter(userClient *client.Client, socialClient *client.Client, assetCl
|
||||
|
||||
// 用户相关路由(公开)
|
||||
users := v1.Group("/users")
|
||||
users.Use(middleware.AuthMiddleware())
|
||||
{
|
||||
users.GET("/:user_id", userCtrl.GetUser) // 获取指定用户信息
|
||||
users.GET("/:user_id/liked-assets", socialCtrl.GetUserLikedAssets) // 获取他人点赞的作品列表
|
||||
users.GET("/:user_id/exhibited-assets", galleryCtrl.GetUserExhibitedAssets) // 获取他人展出的作品列表
|
||||
}
|
||||
|
||||
// 粉丝档案相关路由(公开)
|
||||
@ -127,8 +124,6 @@ func SetupRouter(userClient *client.Client, socialClient *client.Client, assetCl
|
||||
me.PUT("/nickname", userCtrl.UpdateNickname) // 更新昵称
|
||||
me.PUT("/avatar", userCtrl.UpdateAvatar) // 更新头像
|
||||
me.GET("/liked-assets", socialCtrl.GetMyLikedAssets) // 获取我点赞的作品列表
|
||||
me.GET("/today-liked-assets", socialCtrl.GetMyTodayLikedAssets) // 获取我今日点赞的作品列表
|
||||
me.GET("/week-liked-assets", socialCtrl.GetMyWeekLikedAssets) // 获取我本周点赞的作品列表
|
||||
me.GET("/exhibited-assets", galleryCtrl.GetMyExhibitedAssets) // 获取我展出的作品列表
|
||||
}
|
||||
|
||||
|
||||
@ -1507,120 +1507,6 @@ func (x *InspirationFlowItem) GetMaterialType() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
// 获取他人展出的作品列表请求(暂不实现)
|
||||
type GetUserExhibitedAssetsRequest struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
UserId int64 `protobuf:"varint,1,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` // 他人用户ID
|
||||
Page int32 `protobuf:"varint,2,opt,name=page,proto3" json:"page,omitempty"` // 页码(默认1)
|
||||
PageSize int32 `protobuf:"varint,3,opt,name=page_size,json=pageSize,proto3" json:"page_size,omitempty"` // 每页数量(默认20,最大100)
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *GetUserExhibitedAssetsRequest) Reset() {
|
||||
*x = GetUserExhibitedAssetsRequest{}
|
||||
mi := &file_gallery_proto_msgTypes[24]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *GetUserExhibitedAssetsRequest) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*GetUserExhibitedAssetsRequest) ProtoMessage() {}
|
||||
|
||||
func (x *GetUserExhibitedAssetsRequest) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_gallery_proto_msgTypes[24]
|
||||
if x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use GetUserExhibitedAssetsRequest.ProtoReflect.Descriptor instead.
|
||||
func (*GetUserExhibitedAssetsRequest) Descriptor() ([]byte, []int) {
|
||||
return file_gallery_proto_rawDescGZIP(), []int{24}
|
||||
}
|
||||
|
||||
func (x *GetUserExhibitedAssetsRequest) GetUserId() int64 {
|
||||
if x != nil {
|
||||
return x.UserId
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *GetUserExhibitedAssetsRequest) GetPage() int32 {
|
||||
if x != nil {
|
||||
return x.Page
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *GetUserExhibitedAssetsRequest) GetPageSize() int32 {
|
||||
if x != nil {
|
||||
return x.PageSize
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// 获取他人展出的作品列表响应(暂不实现)
|
||||
type GetUserExhibitedAssetsResponse struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
Base *common.BaseResponse `protobuf:"bytes,1,opt,name=base,proto3" json:"base,omitempty"`
|
||||
Data *ExhibitedAssetsData `protobuf:"bytes,2,opt,name=data,proto3" json:"data,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *GetUserExhibitedAssetsResponse) Reset() {
|
||||
*x = GetUserExhibitedAssetsResponse{}
|
||||
mi := &file_gallery_proto_msgTypes[25]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *GetUserExhibitedAssetsResponse) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*GetUserExhibitedAssetsResponse) ProtoMessage() {}
|
||||
|
||||
func (x *GetUserExhibitedAssetsResponse) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_gallery_proto_msgTypes[25]
|
||||
if x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use GetUserExhibitedAssetsResponse.ProtoReflect.Descriptor instead.
|
||||
func (*GetUserExhibitedAssetsResponse) Descriptor() ([]byte, []int) {
|
||||
return file_gallery_proto_rawDescGZIP(), []int{25}
|
||||
}
|
||||
|
||||
func (x *GetUserExhibitedAssetsResponse) GetBase() *common.BaseResponse {
|
||||
if x != nil {
|
||||
return x.Base
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *GetUserExhibitedAssetsResponse) GetData() *ExhibitedAssetsData {
|
||||
if x != nil {
|
||||
return x.Data
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
var File_gallery_proto protoreflect.FileDescriptor
|
||||
|
||||
const file_gallery_proto_rawDesc = "" +
|
||||
@ -1741,14 +1627,7 @@ const file_gallery_proto_rawDesc = "" +
|
||||
"like_count\x18\x04 \x01(\x05R\tlikeCount\x12%\n" +
|
||||
"\x0eowner_nickname\x18\x05 \x01(\tR\rownerNickname\x12\x12\n" +
|
||||
"\x04span\x18\x06 \x01(\x05R\x04span\x12#\n" +
|
||||
"\rmaterial_type\x18\a \x01(\tR\fmaterialType\"i\n" +
|
||||
"\x1dGetUserExhibitedAssetsRequest\x12\x17\n" +
|
||||
"\auser_id\x18\x01 \x01(\x03R\x06userId\x12\x12\n" +
|
||||
"\x04page\x18\x02 \x01(\x05R\x04page\x12\x1b\n" +
|
||||
"\tpage_size\x18\x03 \x01(\x05R\bpageSize\"\x8c\x01\n" +
|
||||
"\x1eGetUserExhibitedAssetsResponse\x120\n" +
|
||||
"\x04base\x18\x01 \x01(\v2\x1c.topfans.common.BaseResponseR\x04base\x128\n" +
|
||||
"\x04data\x18\x02 \x01(\v2$.topfans.gallery.ExhibitedAssetsDataR\x04data2\xf4\b\n" +
|
||||
"\rmaterial_type\x18\a \x01(\tR\fmaterialType2\xc6\a\n" +
|
||||
"\x0eGalleryService\x12u\n" +
|
||||
"\fGetMyGallery\x12$.topfans.gallery.GetMyGalleryRequest\x1a%.topfans.gallery.GetMyGalleryResponse\"\x18\x82\xd3\xe4\x93\x02\x12\x12\x10/api/mygalleries\x12\x86\x01\n" +
|
||||
"\x0eGetUserGallery\x12&.topfans.gallery.GetUserGalleryRequest\x1a'.topfans.gallery.GetUserGalleryResponse\"#\x82\xd3\xe4\x93\x02\x1d\x12\x1b/api/galleries/{target_uid}\x12v\n" +
|
||||
@ -1758,8 +1637,7 @@ const file_gallery_proto_rawDesc = "" +
|
||||
"UnlockSlot\x12\".topfans.gallery.UnlockSlotRequest\x1a#.topfans.gallery.UnlockSlotResponse\"&\x82\xd3\xe4\x93\x02 :\x01*\"\x1b/api/galleries/slots_unlock\x12\x8f\x01\n" +
|
||||
"\x0eRemoveFromSlot\x12&.topfans.gallery.RemoveFromSlotRequest\x1a'.topfans.gallery.RemoveFromSlotResponse\",\x82\xd3\xe4\x93\x02&*$/api/galleries/slots/{slot_id}/asset\x12\x98\x01\n" +
|
||||
"\x14GetMyExhibitedAssets\x12,.topfans.gallery.GetMyExhibitedAssetsRequest\x1a-.topfans.gallery.GetMyExhibitedAssetsResponse\"#\x82\xd3\xe4\x93\x02\x1d\x12\x1b/api/v1/me/exhibited-assets\x12\x8f\x01\n" +
|
||||
"\x12GetInspirationFlow\x12*.topfans.gallery.GetInspirationFlowRequest\x1a+.topfans.gallery.GetInspirationFlowResponse\" \x82\xd3\xe4\x93\x02\x1a\x12\x18/api/v1/inspiration-flow\x12\xab\x01\n" +
|
||||
"\x16GetUserExhibitedAssets\x12..topfans.gallery.GetUserExhibitedAssetsRequest\x1a/.topfans.gallery.GetUserExhibitedAssetsResponse\"0\x82\xd3\xe4\x93\x02*\x12(/api/v1/users/{user_id}/exhibited-assetsB6Z4github.com/topfans/backend/pkg/proto/gallery;galleryb\x06proto3"
|
||||
"\x12GetInspirationFlow\x12*.topfans.gallery.GetInspirationFlowRequest\x1a+.topfans.gallery.GetInspirationFlowResponse\" \x82\xd3\xe4\x93\x02\x1a\x12\x18/api/v1/inspiration-flowB6Z4github.com/topfans/backend/pkg/proto/gallery;galleryb\x06proto3"
|
||||
|
||||
var (
|
||||
file_gallery_proto_rawDescOnce sync.Once
|
||||
@ -1773,78 +1651,72 @@ func file_gallery_proto_rawDescGZIP() []byte {
|
||||
return file_gallery_proto_rawDescData
|
||||
}
|
||||
|
||||
var file_gallery_proto_msgTypes = make([]protoimpl.MessageInfo, 26)
|
||||
var file_gallery_proto_msgTypes = make([]protoimpl.MessageInfo, 24)
|
||||
var file_gallery_proto_goTypes = []any{
|
||||
(*GetMyGalleryRequest)(nil), // 0: topfans.gallery.GetMyGalleryRequest
|
||||
(*GetMyGalleryResponse)(nil), // 1: topfans.gallery.GetMyGalleryResponse
|
||||
(*GetUserGalleryRequest)(nil), // 2: topfans.gallery.GetUserGalleryRequest
|
||||
(*GetUserGalleryResponse)(nil), // 3: topfans.gallery.GetUserGalleryResponse
|
||||
(*PlaceAssetRequest)(nil), // 4: topfans.gallery.PlaceAssetRequest
|
||||
(*PlaceAssetResponse)(nil), // 5: topfans.gallery.PlaceAssetResponse
|
||||
(*UnlockSlotRequest)(nil), // 6: topfans.gallery.UnlockSlotRequest
|
||||
(*UnlockSlotResponse)(nil), // 7: topfans.gallery.UnlockSlotResponse
|
||||
(*GalleryData)(nil), // 8: topfans.gallery.GalleryData
|
||||
(*SlotInfo)(nil), // 9: topfans.gallery.SlotInfo
|
||||
(*AssetInfo)(nil), // 10: topfans.gallery.AssetInfo
|
||||
(*UnlockCondition)(nil), // 11: topfans.gallery.UnlockCondition
|
||||
(*PlaceAssetData)(nil), // 12: topfans.gallery.PlaceAssetData
|
||||
(*UnlockSlotData)(nil), // 13: topfans.gallery.UnlockSlotData
|
||||
(*RemoveFromSlotRequest)(nil), // 14: topfans.gallery.RemoveFromSlotRequest
|
||||
(*RemoveFromSlotResponse)(nil), // 15: topfans.gallery.RemoveFromSlotResponse
|
||||
(*GetMyExhibitedAssetsRequest)(nil), // 16: topfans.gallery.GetMyExhibitedAssetsRequest
|
||||
(*GetMyExhibitedAssetsResponse)(nil), // 17: topfans.gallery.GetMyExhibitedAssetsResponse
|
||||
(*ExhibitedAssetsData)(nil), // 18: topfans.gallery.ExhibitedAssetsData
|
||||
(*ExhibitedAssetItem)(nil), // 19: topfans.gallery.ExhibitedAssetItem
|
||||
(*GetInspirationFlowRequest)(nil), // 20: topfans.gallery.GetInspirationFlowRequest
|
||||
(*GetInspirationFlowResponse)(nil), // 21: topfans.gallery.GetInspirationFlowResponse
|
||||
(*InspirationFlowData)(nil), // 22: topfans.gallery.InspirationFlowData
|
||||
(*InspirationFlowItem)(nil), // 23: topfans.gallery.InspirationFlowItem
|
||||
(*GetUserExhibitedAssetsRequest)(nil), // 24: topfans.gallery.GetUserExhibitedAssetsRequest
|
||||
(*GetUserExhibitedAssetsResponse)(nil), // 25: topfans.gallery.GetUserExhibitedAssetsResponse
|
||||
(*common.BaseResponse)(nil), // 26: topfans.common.BaseResponse
|
||||
(*GetMyGalleryRequest)(nil), // 0: topfans.gallery.GetMyGalleryRequest
|
||||
(*GetMyGalleryResponse)(nil), // 1: topfans.gallery.GetMyGalleryResponse
|
||||
(*GetUserGalleryRequest)(nil), // 2: topfans.gallery.GetUserGalleryRequest
|
||||
(*GetUserGalleryResponse)(nil), // 3: topfans.gallery.GetUserGalleryResponse
|
||||
(*PlaceAssetRequest)(nil), // 4: topfans.gallery.PlaceAssetRequest
|
||||
(*PlaceAssetResponse)(nil), // 5: topfans.gallery.PlaceAssetResponse
|
||||
(*UnlockSlotRequest)(nil), // 6: topfans.gallery.UnlockSlotRequest
|
||||
(*UnlockSlotResponse)(nil), // 7: topfans.gallery.UnlockSlotResponse
|
||||
(*GalleryData)(nil), // 8: topfans.gallery.GalleryData
|
||||
(*SlotInfo)(nil), // 9: topfans.gallery.SlotInfo
|
||||
(*AssetInfo)(nil), // 10: topfans.gallery.AssetInfo
|
||||
(*UnlockCondition)(nil), // 11: topfans.gallery.UnlockCondition
|
||||
(*PlaceAssetData)(nil), // 12: topfans.gallery.PlaceAssetData
|
||||
(*UnlockSlotData)(nil), // 13: topfans.gallery.UnlockSlotData
|
||||
(*RemoveFromSlotRequest)(nil), // 14: topfans.gallery.RemoveFromSlotRequest
|
||||
(*RemoveFromSlotResponse)(nil), // 15: topfans.gallery.RemoveFromSlotResponse
|
||||
(*GetMyExhibitedAssetsRequest)(nil), // 16: topfans.gallery.GetMyExhibitedAssetsRequest
|
||||
(*GetMyExhibitedAssetsResponse)(nil), // 17: topfans.gallery.GetMyExhibitedAssetsResponse
|
||||
(*ExhibitedAssetsData)(nil), // 18: topfans.gallery.ExhibitedAssetsData
|
||||
(*ExhibitedAssetItem)(nil), // 19: topfans.gallery.ExhibitedAssetItem
|
||||
(*GetInspirationFlowRequest)(nil), // 20: topfans.gallery.GetInspirationFlowRequest
|
||||
(*GetInspirationFlowResponse)(nil), // 21: topfans.gallery.GetInspirationFlowResponse
|
||||
(*InspirationFlowData)(nil), // 22: topfans.gallery.InspirationFlowData
|
||||
(*InspirationFlowItem)(nil), // 23: topfans.gallery.InspirationFlowItem
|
||||
(*common.BaseResponse)(nil), // 24: topfans.common.BaseResponse
|
||||
}
|
||||
var file_gallery_proto_depIdxs = []int32{
|
||||
26, // 0: topfans.gallery.GetMyGalleryResponse.base:type_name -> topfans.common.BaseResponse
|
||||
24, // 0: topfans.gallery.GetMyGalleryResponse.base:type_name -> topfans.common.BaseResponse
|
||||
8, // 1: topfans.gallery.GetMyGalleryResponse.data:type_name -> topfans.gallery.GalleryData
|
||||
26, // 2: topfans.gallery.GetUserGalleryResponse.base:type_name -> topfans.common.BaseResponse
|
||||
24, // 2: topfans.gallery.GetUserGalleryResponse.base:type_name -> topfans.common.BaseResponse
|
||||
8, // 3: topfans.gallery.GetUserGalleryResponse.data:type_name -> topfans.gallery.GalleryData
|
||||
26, // 4: topfans.gallery.PlaceAssetResponse.base:type_name -> topfans.common.BaseResponse
|
||||
24, // 4: topfans.gallery.PlaceAssetResponse.base:type_name -> topfans.common.BaseResponse
|
||||
12, // 5: topfans.gallery.PlaceAssetResponse.data:type_name -> topfans.gallery.PlaceAssetData
|
||||
26, // 6: topfans.gallery.UnlockSlotResponse.base:type_name -> topfans.common.BaseResponse
|
||||
24, // 6: topfans.gallery.UnlockSlotResponse.base:type_name -> topfans.common.BaseResponse
|
||||
13, // 7: topfans.gallery.UnlockSlotResponse.data:type_name -> topfans.gallery.UnlockSlotData
|
||||
9, // 8: topfans.gallery.GalleryData.slots:type_name -> topfans.gallery.SlotInfo
|
||||
10, // 9: topfans.gallery.SlotInfo.asset:type_name -> topfans.gallery.AssetInfo
|
||||
11, // 10: topfans.gallery.SlotInfo.unlock_condition:type_name -> topfans.gallery.UnlockCondition
|
||||
26, // 11: topfans.gallery.RemoveFromSlotResponse.base:type_name -> topfans.common.BaseResponse
|
||||
26, // 12: topfans.gallery.GetMyExhibitedAssetsResponse.base:type_name -> topfans.common.BaseResponse
|
||||
24, // 11: topfans.gallery.RemoveFromSlotResponse.base:type_name -> topfans.common.BaseResponse
|
||||
24, // 12: topfans.gallery.GetMyExhibitedAssetsResponse.base:type_name -> topfans.common.BaseResponse
|
||||
18, // 13: topfans.gallery.GetMyExhibitedAssetsResponse.data:type_name -> topfans.gallery.ExhibitedAssetsData
|
||||
19, // 14: topfans.gallery.ExhibitedAssetsData.items:type_name -> topfans.gallery.ExhibitedAssetItem
|
||||
26, // 15: topfans.gallery.GetInspirationFlowResponse.base:type_name -> topfans.common.BaseResponse
|
||||
24, // 15: topfans.gallery.GetInspirationFlowResponse.base:type_name -> topfans.common.BaseResponse
|
||||
22, // 16: topfans.gallery.GetInspirationFlowResponse.data:type_name -> topfans.gallery.InspirationFlowData
|
||||
23, // 17: topfans.gallery.InspirationFlowData.items:type_name -> topfans.gallery.InspirationFlowItem
|
||||
26, // 18: topfans.gallery.GetUserExhibitedAssetsResponse.base:type_name -> topfans.common.BaseResponse
|
||||
18, // 19: topfans.gallery.GetUserExhibitedAssetsResponse.data:type_name -> topfans.gallery.ExhibitedAssetsData
|
||||
0, // 20: topfans.gallery.GalleryService.GetMyGallery:input_type -> topfans.gallery.GetMyGalleryRequest
|
||||
2, // 21: topfans.gallery.GalleryService.GetUserGallery:input_type -> topfans.gallery.GetUserGalleryRequest
|
||||
4, // 22: topfans.gallery.GalleryService.PlaceAsset:input_type -> topfans.gallery.PlaceAssetRequest
|
||||
6, // 23: topfans.gallery.GalleryService.UnlockSlot:input_type -> topfans.gallery.UnlockSlotRequest
|
||||
14, // 24: topfans.gallery.GalleryService.RemoveFromSlot:input_type -> topfans.gallery.RemoveFromSlotRequest
|
||||
16, // 25: topfans.gallery.GalleryService.GetMyExhibitedAssets:input_type -> topfans.gallery.GetMyExhibitedAssetsRequest
|
||||
20, // 26: topfans.gallery.GalleryService.GetInspirationFlow:input_type -> topfans.gallery.GetInspirationFlowRequest
|
||||
24, // 27: topfans.gallery.GalleryService.GetUserExhibitedAssets:input_type -> topfans.gallery.GetUserExhibitedAssetsRequest
|
||||
1, // 28: topfans.gallery.GalleryService.GetMyGallery:output_type -> topfans.gallery.GetMyGalleryResponse
|
||||
3, // 29: topfans.gallery.GalleryService.GetUserGallery:output_type -> topfans.gallery.GetUserGalleryResponse
|
||||
5, // 30: topfans.gallery.GalleryService.PlaceAsset:output_type -> topfans.gallery.PlaceAssetResponse
|
||||
7, // 31: topfans.gallery.GalleryService.UnlockSlot:output_type -> topfans.gallery.UnlockSlotResponse
|
||||
15, // 32: topfans.gallery.GalleryService.RemoveFromSlot:output_type -> topfans.gallery.RemoveFromSlotResponse
|
||||
17, // 33: topfans.gallery.GalleryService.GetMyExhibitedAssets:output_type -> topfans.gallery.GetMyExhibitedAssetsResponse
|
||||
21, // 34: topfans.gallery.GalleryService.GetInspirationFlow:output_type -> topfans.gallery.GetInspirationFlowResponse
|
||||
25, // 35: topfans.gallery.GalleryService.GetUserExhibitedAssets:output_type -> topfans.gallery.GetUserExhibitedAssetsResponse
|
||||
28, // [28:36] is the sub-list for method output_type
|
||||
20, // [20:28] is the sub-list for method input_type
|
||||
20, // [20:20] is the sub-list for extension type_name
|
||||
20, // [20:20] is the sub-list for extension extendee
|
||||
0, // [0:20] is the sub-list for field type_name
|
||||
0, // 18: topfans.gallery.GalleryService.GetMyGallery:input_type -> topfans.gallery.GetMyGalleryRequest
|
||||
2, // 19: topfans.gallery.GalleryService.GetUserGallery:input_type -> topfans.gallery.GetUserGalleryRequest
|
||||
4, // 20: topfans.gallery.GalleryService.PlaceAsset:input_type -> topfans.gallery.PlaceAssetRequest
|
||||
6, // 21: topfans.gallery.GalleryService.UnlockSlot:input_type -> topfans.gallery.UnlockSlotRequest
|
||||
14, // 22: topfans.gallery.GalleryService.RemoveFromSlot:input_type -> topfans.gallery.RemoveFromSlotRequest
|
||||
16, // 23: topfans.gallery.GalleryService.GetMyExhibitedAssets:input_type -> topfans.gallery.GetMyExhibitedAssetsRequest
|
||||
20, // 24: topfans.gallery.GalleryService.GetInspirationFlow:input_type -> topfans.gallery.GetInspirationFlowRequest
|
||||
1, // 25: topfans.gallery.GalleryService.GetMyGallery:output_type -> topfans.gallery.GetMyGalleryResponse
|
||||
3, // 26: topfans.gallery.GalleryService.GetUserGallery:output_type -> topfans.gallery.GetUserGalleryResponse
|
||||
5, // 27: topfans.gallery.GalleryService.PlaceAsset:output_type -> topfans.gallery.PlaceAssetResponse
|
||||
7, // 28: topfans.gallery.GalleryService.UnlockSlot:output_type -> topfans.gallery.UnlockSlotResponse
|
||||
15, // 29: topfans.gallery.GalleryService.RemoveFromSlot:output_type -> topfans.gallery.RemoveFromSlotResponse
|
||||
17, // 30: topfans.gallery.GalleryService.GetMyExhibitedAssets:output_type -> topfans.gallery.GetMyExhibitedAssetsResponse
|
||||
21, // 31: topfans.gallery.GalleryService.GetInspirationFlow:output_type -> topfans.gallery.GetInspirationFlowResponse
|
||||
25, // [25:32] is the sub-list for method output_type
|
||||
18, // [18:25] is the sub-list for method input_type
|
||||
18, // [18:18] is the sub-list for extension type_name
|
||||
18, // [18:18] is the sub-list for extension extendee
|
||||
0, // [0:18] is the sub-list for field type_name
|
||||
}
|
||||
|
||||
func init() { file_gallery_proto_init() }
|
||||
@ -1858,7 +1730,7 @@ func file_gallery_proto_init() {
|
||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||
RawDescriptor: unsafe.Slice(unsafe.StringData(file_gallery_proto_rawDesc), len(file_gallery_proto_rawDesc)),
|
||||
NumEnums: 0,
|
||||
NumMessages: 26,
|
||||
NumMessages: 24,
|
||||
NumExtensions: 0,
|
||||
NumServices: 1,
|
||||
},
|
||||
|
||||
@ -50,8 +50,6 @@ const (
|
||||
GalleryServiceGetMyExhibitedAssetsProcedure = "/topfans.gallery.GalleryService/GetMyExhibitedAssets"
|
||||
// GalleryServiceGetInspirationFlowProcedure is the fully-qualified name of the GalleryService's GetInspirationFlow RPC.
|
||||
GalleryServiceGetInspirationFlowProcedure = "/topfans.gallery.GalleryService/GetInspirationFlow"
|
||||
// GalleryServiceGetUserExhibitedAssetsProcedure is the fully-qualified name of the GalleryService's GetUserExhibitedAssets RPC.
|
||||
GalleryServiceGetUserExhibitedAssetsProcedure = "/topfans.gallery.GalleryService/GetUserExhibitedAssets"
|
||||
)
|
||||
|
||||
var (
|
||||
@ -67,7 +65,6 @@ type GalleryService interface {
|
||||
RemoveFromSlot(ctx context.Context, req *RemoveFromSlotRequest, opts ...client.CallOption) (*RemoveFromSlotResponse, error)
|
||||
GetMyExhibitedAssets(ctx context.Context, req *GetMyExhibitedAssetsRequest, opts ...client.CallOption) (*GetMyExhibitedAssetsResponse, error)
|
||||
GetInspirationFlow(ctx context.Context, req *GetInspirationFlowRequest, opts ...client.CallOption) (*GetInspirationFlowResponse, error)
|
||||
GetUserExhibitedAssets(ctx context.Context, req *GetUserExhibitedAssetsRequest, opts ...client.CallOption) (*GetUserExhibitedAssetsResponse, error)
|
||||
}
|
||||
|
||||
// NewGalleryService constructs a client for the gallery.GalleryService service.
|
||||
@ -146,17 +143,9 @@ func (c *GalleryServiceImpl) GetInspirationFlow(ctx context.Context, req *GetIns
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
func (c *GalleryServiceImpl) GetUserExhibitedAssets(ctx context.Context, req *GetUserExhibitedAssetsRequest, opts ...client.CallOption) (*GetUserExhibitedAssetsResponse, error) {
|
||||
resp := new(GetUserExhibitedAssetsResponse)
|
||||
if err := c.conn.CallUnary(ctx, []interface{}{req}, resp, "GetUserExhibitedAssets", opts...); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
var GalleryService_ClientInfo = client.ClientInfo{
|
||||
InterfaceName: "topfans.gallery.GalleryService",
|
||||
MethodNames: []string{"GetMyGallery", "GetUserGallery", "PlaceAsset", "UnlockSlot", "RemoveFromSlot", "GetMyExhibitedAssets", "GetInspirationFlow", "GetUserExhibitedAssets"},
|
||||
MethodNames: []string{"GetMyGallery", "GetUserGallery", "PlaceAsset", "UnlockSlot", "RemoveFromSlot", "GetMyExhibitedAssets", "GetInspirationFlow"},
|
||||
ConnectionInjectFunc: func(dubboCliRaw interface{}, conn *client.Connection) {
|
||||
dubboCli := dubboCliRaw.(*GalleryServiceImpl)
|
||||
dubboCli.conn = conn
|
||||
@ -172,7 +161,6 @@ type GalleryServiceHandler interface {
|
||||
RemoveFromSlot(context.Context, *RemoveFromSlotRequest) (*RemoveFromSlotResponse, error)
|
||||
GetMyExhibitedAssets(context.Context, *GetMyExhibitedAssetsRequest) (*GetMyExhibitedAssetsResponse, error)
|
||||
GetInspirationFlow(context.Context, *GetInspirationFlowRequest) (*GetInspirationFlowResponse, error)
|
||||
GetUserExhibitedAssets(context.Context, *GetUserExhibitedAssetsRequest) (*GetUserExhibitedAssetsResponse, error)
|
||||
}
|
||||
|
||||
func RegisterGalleryServiceHandler(srv *server.Server, hdlr GalleryServiceHandler, opts ...server.ServiceOption) error {
|
||||
@ -292,20 +280,5 @@ var GalleryService_ServiceInfo = server.ServiceInfo{
|
||||
return triple_protocol.NewResponse(res), nil
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "GetUserExhibitedAssets",
|
||||
Type: constant.CallUnary,
|
||||
ReqInitFunc: func() interface{} {
|
||||
return new(GetUserExhibitedAssetsRequest)
|
||||
},
|
||||
MethodFunc: func(ctx context.Context, args []interface{}, handler interface{}) (interface{}, error) {
|
||||
req := args[0].(*GetUserExhibitedAssetsRequest)
|
||||
res, err := handler.(GalleryServiceHandler).GetUserExhibitedAssets(ctx, req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return triple_protocol.NewResponse(res), nil
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
@ -2628,120 +2628,6 @@ func (x *GetMyWeekLikedAssetsResponse) GetData() *LikedAssetsData {
|
||||
return nil
|
||||
}
|
||||
|
||||
// 获取他人点赞的作品列表请求(暂不实现)
|
||||
type GetUserLikedAssetsRequest struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
UserId int64 `protobuf:"varint,1,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` // 他人用户ID
|
||||
Page int32 `protobuf:"varint,2,opt,name=page,proto3" json:"page,omitempty"` // 页码(默认1)
|
||||
PageSize int32 `protobuf:"varint,3,opt,name=page_size,json=pageSize,proto3" json:"page_size,omitempty"` // 每页数量(默认20,最大100)
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *GetUserLikedAssetsRequest) Reset() {
|
||||
*x = GetUserLikedAssetsRequest{}
|
||||
mi := &file_social_proto_msgTypes[41]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *GetUserLikedAssetsRequest) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*GetUserLikedAssetsRequest) ProtoMessage() {}
|
||||
|
||||
func (x *GetUserLikedAssetsRequest) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_social_proto_msgTypes[41]
|
||||
if x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use GetUserLikedAssetsRequest.ProtoReflect.Descriptor instead.
|
||||
func (*GetUserLikedAssetsRequest) Descriptor() ([]byte, []int) {
|
||||
return file_social_proto_rawDescGZIP(), []int{41}
|
||||
}
|
||||
|
||||
func (x *GetUserLikedAssetsRequest) GetUserId() int64 {
|
||||
if x != nil {
|
||||
return x.UserId
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *GetUserLikedAssetsRequest) GetPage() int32 {
|
||||
if x != nil {
|
||||
return x.Page
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *GetUserLikedAssetsRequest) GetPageSize() int32 {
|
||||
if x != nil {
|
||||
return x.PageSize
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// 获取他人点赞的作品列表响应(暂不实现)
|
||||
type GetUserLikedAssetsResponse struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
Base *common.BaseResponse `protobuf:"bytes,1,opt,name=base,proto3" json:"base,omitempty"`
|
||||
Data *LikedAssetsData `protobuf:"bytes,2,opt,name=data,proto3" json:"data,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *GetUserLikedAssetsResponse) Reset() {
|
||||
*x = GetUserLikedAssetsResponse{}
|
||||
mi := &file_social_proto_msgTypes[42]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *GetUserLikedAssetsResponse) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*GetUserLikedAssetsResponse) ProtoMessage() {}
|
||||
|
||||
func (x *GetUserLikedAssetsResponse) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_social_proto_msgTypes[42]
|
||||
if x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use GetUserLikedAssetsResponse.ProtoReflect.Descriptor instead.
|
||||
func (*GetUserLikedAssetsResponse) Descriptor() ([]byte, []int) {
|
||||
return file_social_proto_rawDescGZIP(), []int{42}
|
||||
}
|
||||
|
||||
func (x *GetUserLikedAssetsResponse) GetBase() *common.BaseResponse {
|
||||
if x != nil {
|
||||
return x.Base
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *GetUserLikedAssetsResponse) GetData() *LikedAssetsData {
|
||||
if x != nil {
|
||||
return x.Data
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
var File_social_proto protoreflect.FileDescriptor
|
||||
|
||||
const file_social_proto_rawDesc = "" +
|
||||
@ -2939,14 +2825,7 @@ const file_social_proto_rawDesc = "" +
|
||||
"\tpage_size\x18\x02 \x01(\x05R\bpageSize\"\x85\x01\n" +
|
||||
"\x1cGetMyWeekLikedAssetsResponse\x120\n" +
|
||||
"\x04base\x18\x01 \x01(\v2\x1c.topfans.common.BaseResponseR\x04base\x123\n" +
|
||||
"\x04data\x18\x02 \x01(\v2\x1f.topfans.social.LikedAssetsDataR\x04data\"e\n" +
|
||||
"\x19GetUserLikedAssetsRequest\x12\x17\n" +
|
||||
"\auser_id\x18\x01 \x01(\x03R\x06userId\x12\x12\n" +
|
||||
"\x04page\x18\x02 \x01(\x05R\x04page\x12\x1b\n" +
|
||||
"\tpage_size\x18\x03 \x01(\x05R\bpageSize\"\x83\x01\n" +
|
||||
"\x1aGetUserLikedAssetsResponse\x120\n" +
|
||||
"\x04base\x18\x01 \x01(\v2\x1c.topfans.common.BaseResponseR\x04base\x123\n" +
|
||||
"\x04data\x18\x02 \x01(\v2\x1f.topfans.social.LikedAssetsDataR\x04data2\x94\x14\n" +
|
||||
"\x04data\x18\x02 \x01(\v2\x1f.topfans.social.LikedAssetsDataR\x04data2\xf8\x12\n" +
|
||||
"\rSocialService\x12\x8d\x01\n" +
|
||||
"\x11SendFriendRequest\x12(.topfans.social.SendFriendRequestRequest\x1a).topfans.social.SendFriendRequestResponse\"#\x82\xd3\xe4\x93\x02\x1d:\x01*\"\x18/api/v1/friends/requests\x12\x8a\x01\n" +
|
||||
"\x11GetFriendRequests\x12(.topfans.social.GetFriendRequestsRequest\x1a).topfans.social.GetFriendRequestsResponse\" \x82\xd3\xe4\x93\x02\x1a\x12\x18/api/v1/friends/requests\x12\xa7\x01\n" +
|
||||
@ -2964,8 +2843,7 @@ const file_social_proto_rawDesc = "" +
|
||||
"\x0eCheckAssetLike\x12%.topfans.social.CheckAssetLikeRequest\x1a&.topfans.social.CheckAssetLikeResponse\"-\x82\xd3\xe4\x93\x02'\x12%/api/v1/social/assets/{asset_id}/like\x12\x86\x01\n" +
|
||||
"\x10GetMyLikedAssets\x12'.topfans.social.GetMyLikedAssetsRequest\x1a(.topfans.social.GetMyLikedAssetsResponse\"\x1f\x82\xd3\xe4\x93\x02\x19\x12\x17/api/v1/me/liked-assets\x12\x9b\x01\n" +
|
||||
"\x15GetMyTodayLikedAssets\x12,.topfans.social.GetMyTodayLikedAssetsRequest\x1a-.topfans.social.GetMyTodayLikedAssetsResponse\"%\x82\xd3\xe4\x93\x02\x1f\x12\x1d/api/v1/me/today-liked-assets\x12\x97\x01\n" +
|
||||
"\x14GetMyWeekLikedAssets\x12+.topfans.social.GetMyWeekLikedAssetsRequest\x1a,.topfans.social.GetMyWeekLikedAssetsResponse\"$\x82\xd3\xe4\x93\x02\x1e\x12\x1c/api/v1/me/week-liked-assets\x12\x99\x01\n" +
|
||||
"\x12GetUserLikedAssets\x12).topfans.social.GetUserLikedAssetsRequest\x1a*.topfans.social.GetUserLikedAssetsResponse\",\x82\xd3\xe4\x93\x02&\x12$/api/v1/users/{user_id}/liked-assetsB4Z2github.com/topfans/backend/pkg/proto/social;socialb\x06proto3"
|
||||
"\x14GetMyWeekLikedAssets\x12+.topfans.social.GetMyWeekLikedAssetsRequest\x1a,.topfans.social.GetMyWeekLikedAssetsResponse\"$\x82\xd3\xe4\x93\x02\x1e\x12\x1c/api/v1/me/week-liked-assetsB4Z2github.com/topfans/backend/pkg/proto/social;socialb\x06proto3"
|
||||
|
||||
var (
|
||||
file_social_proto_rawDescOnce sync.Once
|
||||
@ -2979,7 +2857,7 @@ func file_social_proto_rawDescGZIP() []byte {
|
||||
return file_social_proto_rawDescData
|
||||
}
|
||||
|
||||
var file_social_proto_msgTypes = make([]protoimpl.MessageInfo, 43)
|
||||
var file_social_proto_msgTypes = make([]protoimpl.MessageInfo, 41)
|
||||
var file_social_proto_goTypes = []any{
|
||||
(*FriendRequest)(nil), // 0: topfans.social.FriendRequest
|
||||
(*Friendship)(nil), // 1: topfans.social.Friendship
|
||||
@ -3022,81 +2900,75 @@ var file_social_proto_goTypes = []any{
|
||||
(*GetMyTodayLikedAssetsResponse)(nil), // 38: topfans.social.GetMyTodayLikedAssetsResponse
|
||||
(*GetMyWeekLikedAssetsRequest)(nil), // 39: topfans.social.GetMyWeekLikedAssetsRequest
|
||||
(*GetMyWeekLikedAssetsResponse)(nil), // 40: topfans.social.GetMyWeekLikedAssetsResponse
|
||||
(*GetUserLikedAssetsRequest)(nil), // 41: topfans.social.GetUserLikedAssetsRequest
|
||||
(*GetUserLikedAssetsResponse)(nil), // 42: topfans.social.GetUserLikedAssetsResponse
|
||||
(*common.BaseResponse)(nil), // 43: topfans.common.BaseResponse
|
||||
(*common.BaseResponse)(nil), // 41: topfans.common.BaseResponse
|
||||
}
|
||||
var file_social_proto_depIdxs = []int32{
|
||||
43, // 0: topfans.social.SendFriendRequestResponse.base:type_name -> topfans.common.BaseResponse
|
||||
41, // 0: topfans.social.SendFriendRequestResponse.base:type_name -> topfans.common.BaseResponse
|
||||
20, // 1: topfans.social.SendFriendRequestResponse.matched_users:type_name -> topfans.social.FanProfileSearchResult
|
||||
43, // 2: topfans.social.GetFriendRequestsResponse.base:type_name -> topfans.common.BaseResponse
|
||||
41, // 2: topfans.social.GetFriendRequestsResponse.base:type_name -> topfans.common.BaseResponse
|
||||
0, // 3: topfans.social.GetFriendRequestsResponse.items:type_name -> topfans.social.FriendRequest
|
||||
43, // 4: topfans.social.HandleFriendRequestResponse.base:type_name -> topfans.common.BaseResponse
|
||||
43, // 5: topfans.social.GetFriendListResponse.base:type_name -> topfans.common.BaseResponse
|
||||
41, // 4: topfans.social.HandleFriendRequestResponse.base:type_name -> topfans.common.BaseResponse
|
||||
41, // 5: topfans.social.GetFriendListResponse.base:type_name -> topfans.common.BaseResponse
|
||||
1, // 6: topfans.social.GetFriendListResponse.items:type_name -> topfans.social.Friendship
|
||||
43, // 7: topfans.social.DeleteFriendResponse.base:type_name -> topfans.common.BaseResponse
|
||||
43, // 8: topfans.social.SetFriendRemarkResponse.base:type_name -> topfans.common.BaseResponse
|
||||
43, // 9: topfans.social.CheckFriendshipResponse.base:type_name -> topfans.common.BaseResponse
|
||||
43, // 10: topfans.social.GetFriendCountResponse.base:type_name -> topfans.common.BaseResponse
|
||||
43, // 11: topfans.social.SearchUserForFriendResponse.base:type_name -> topfans.common.BaseResponse
|
||||
41, // 7: topfans.social.DeleteFriendResponse.base:type_name -> topfans.common.BaseResponse
|
||||
41, // 8: topfans.social.SetFriendRemarkResponse.base:type_name -> topfans.common.BaseResponse
|
||||
41, // 9: topfans.social.CheckFriendshipResponse.base:type_name -> topfans.common.BaseResponse
|
||||
41, // 10: topfans.social.GetFriendCountResponse.base:type_name -> topfans.common.BaseResponse
|
||||
41, // 11: topfans.social.SearchUserForFriendResponse.base:type_name -> topfans.common.BaseResponse
|
||||
20, // 12: topfans.social.SearchUserForFriendResponse.user:type_name -> topfans.social.FanProfileSearchResult
|
||||
43, // 13: topfans.social.GetRandomUsersResponse.base:type_name -> topfans.common.BaseResponse
|
||||
41, // 13: topfans.social.GetRandomUsersResponse.base:type_name -> topfans.common.BaseResponse
|
||||
21, // 14: topfans.social.GetRandomUsersResponse.users:type_name -> topfans.social.RandomUser
|
||||
43, // 15: topfans.social.GetUsersPagedResponse.base:type_name -> topfans.common.BaseResponse
|
||||
41, // 15: topfans.social.GetUsersPagedResponse.base:type_name -> topfans.common.BaseResponse
|
||||
24, // 16: topfans.social.GetUsersPagedResponse.users:type_name -> topfans.social.PagedUser
|
||||
43, // 17: topfans.social.LikeAssetResponse.base:type_name -> topfans.common.BaseResponse
|
||||
43, // 18: topfans.social.UnlikeAssetResponse.base:type_name -> topfans.common.BaseResponse
|
||||
43, // 19: topfans.social.CheckAssetLikeResponse.base:type_name -> topfans.common.BaseResponse
|
||||
43, // 20: topfans.social.GetMyLikedAssetsResponse.base:type_name -> topfans.common.BaseResponse
|
||||
41, // 17: topfans.social.LikeAssetResponse.base:type_name -> topfans.common.BaseResponse
|
||||
41, // 18: topfans.social.UnlikeAssetResponse.base:type_name -> topfans.common.BaseResponse
|
||||
41, // 19: topfans.social.CheckAssetLikeResponse.base:type_name -> topfans.common.BaseResponse
|
||||
41, // 20: topfans.social.GetMyLikedAssetsResponse.base:type_name -> topfans.common.BaseResponse
|
||||
35, // 21: topfans.social.GetMyLikedAssetsResponse.data:type_name -> topfans.social.LikedAssetsData
|
||||
36, // 22: topfans.social.LikedAssetsData.items:type_name -> topfans.social.LikedAssetItem
|
||||
43, // 23: topfans.social.GetMyTodayLikedAssetsResponse.base:type_name -> topfans.common.BaseResponse
|
||||
41, // 23: topfans.social.GetMyTodayLikedAssetsResponse.base:type_name -> topfans.common.BaseResponse
|
||||
35, // 24: topfans.social.GetMyTodayLikedAssetsResponse.data:type_name -> topfans.social.LikedAssetsData
|
||||
43, // 25: topfans.social.GetMyWeekLikedAssetsResponse.base:type_name -> topfans.common.BaseResponse
|
||||
41, // 25: topfans.social.GetMyWeekLikedAssetsResponse.base:type_name -> topfans.common.BaseResponse
|
||||
35, // 26: topfans.social.GetMyWeekLikedAssetsResponse.data:type_name -> topfans.social.LikedAssetsData
|
||||
43, // 27: topfans.social.GetUserLikedAssetsResponse.base:type_name -> topfans.common.BaseResponse
|
||||
35, // 28: topfans.social.GetUserLikedAssetsResponse.data:type_name -> topfans.social.LikedAssetsData
|
||||
2, // 29: topfans.social.SocialService.SendFriendRequest:input_type -> topfans.social.SendFriendRequestRequest
|
||||
4, // 30: topfans.social.SocialService.GetFriendRequests:input_type -> topfans.social.GetFriendRequestsRequest
|
||||
6, // 31: topfans.social.SocialService.HandleFriendRequest:input_type -> topfans.social.HandleFriendRequestRequest
|
||||
8, // 32: topfans.social.SocialService.GetFriendList:input_type -> topfans.social.GetFriendListRequest
|
||||
10, // 33: topfans.social.SocialService.DeleteFriend:input_type -> topfans.social.DeleteFriendRequest
|
||||
12, // 34: topfans.social.SocialService.SetFriendRemark:input_type -> topfans.social.SetFriendRemarkRequest
|
||||
14, // 35: topfans.social.SocialService.CheckFriendship:input_type -> topfans.social.CheckFriendshipRequest
|
||||
16, // 36: topfans.social.SocialService.GetFriendCount:input_type -> topfans.social.GetFriendCountRequest
|
||||
18, // 37: topfans.social.SocialService.SearchUserForFriend:input_type -> topfans.social.SearchUserForFriendRequest
|
||||
22, // 38: topfans.social.SocialService.GetRandomUsers:input_type -> topfans.social.GetRandomUsersRequest
|
||||
25, // 39: topfans.social.SocialService.GetUsersPaged:input_type -> topfans.social.GetUsersPagedRequest
|
||||
27, // 40: topfans.social.SocialService.LikeAsset:input_type -> topfans.social.LikeAssetRequest
|
||||
29, // 41: topfans.social.SocialService.UnlikeAsset:input_type -> topfans.social.UnlikeAssetRequest
|
||||
31, // 42: topfans.social.SocialService.CheckAssetLike:input_type -> topfans.social.CheckAssetLikeRequest
|
||||
33, // 43: topfans.social.SocialService.GetMyLikedAssets:input_type -> topfans.social.GetMyLikedAssetsRequest
|
||||
37, // 44: topfans.social.SocialService.GetMyTodayLikedAssets:input_type -> topfans.social.GetMyTodayLikedAssetsRequest
|
||||
39, // 45: topfans.social.SocialService.GetMyWeekLikedAssets:input_type -> topfans.social.GetMyWeekLikedAssetsRequest
|
||||
41, // 46: topfans.social.SocialService.GetUserLikedAssets:input_type -> topfans.social.GetUserLikedAssetsRequest
|
||||
3, // 47: topfans.social.SocialService.SendFriendRequest:output_type -> topfans.social.SendFriendRequestResponse
|
||||
5, // 48: topfans.social.SocialService.GetFriendRequests:output_type -> topfans.social.GetFriendRequestsResponse
|
||||
7, // 49: topfans.social.SocialService.HandleFriendRequest:output_type -> topfans.social.HandleFriendRequestResponse
|
||||
9, // 50: topfans.social.SocialService.GetFriendList:output_type -> topfans.social.GetFriendListResponse
|
||||
11, // 51: topfans.social.SocialService.DeleteFriend:output_type -> topfans.social.DeleteFriendResponse
|
||||
13, // 52: topfans.social.SocialService.SetFriendRemark:output_type -> topfans.social.SetFriendRemarkResponse
|
||||
15, // 53: topfans.social.SocialService.CheckFriendship:output_type -> topfans.social.CheckFriendshipResponse
|
||||
17, // 54: topfans.social.SocialService.GetFriendCount:output_type -> topfans.social.GetFriendCountResponse
|
||||
19, // 55: topfans.social.SocialService.SearchUserForFriend:output_type -> topfans.social.SearchUserForFriendResponse
|
||||
23, // 56: topfans.social.SocialService.GetRandomUsers:output_type -> topfans.social.GetRandomUsersResponse
|
||||
26, // 57: topfans.social.SocialService.GetUsersPaged:output_type -> topfans.social.GetUsersPagedResponse
|
||||
28, // 58: topfans.social.SocialService.LikeAsset:output_type -> topfans.social.LikeAssetResponse
|
||||
30, // 59: topfans.social.SocialService.UnlikeAsset:output_type -> topfans.social.UnlikeAssetResponse
|
||||
32, // 60: topfans.social.SocialService.CheckAssetLike:output_type -> topfans.social.CheckAssetLikeResponse
|
||||
34, // 61: topfans.social.SocialService.GetMyLikedAssets:output_type -> topfans.social.GetMyLikedAssetsResponse
|
||||
38, // 62: topfans.social.SocialService.GetMyTodayLikedAssets:output_type -> topfans.social.GetMyTodayLikedAssetsResponse
|
||||
40, // 63: topfans.social.SocialService.GetMyWeekLikedAssets:output_type -> topfans.social.GetMyWeekLikedAssetsResponse
|
||||
42, // 64: topfans.social.SocialService.GetUserLikedAssets:output_type -> topfans.social.GetUserLikedAssetsResponse
|
||||
47, // [47:65] is the sub-list for method output_type
|
||||
29, // [29:47] is the sub-list for method input_type
|
||||
29, // [29:29] is the sub-list for extension type_name
|
||||
29, // [29:29] is the sub-list for extension extendee
|
||||
0, // [0:29] is the sub-list for field type_name
|
||||
2, // 27: topfans.social.SocialService.SendFriendRequest:input_type -> topfans.social.SendFriendRequestRequest
|
||||
4, // 28: topfans.social.SocialService.GetFriendRequests:input_type -> topfans.social.GetFriendRequestsRequest
|
||||
6, // 29: topfans.social.SocialService.HandleFriendRequest:input_type -> topfans.social.HandleFriendRequestRequest
|
||||
8, // 30: topfans.social.SocialService.GetFriendList:input_type -> topfans.social.GetFriendListRequest
|
||||
10, // 31: topfans.social.SocialService.DeleteFriend:input_type -> topfans.social.DeleteFriendRequest
|
||||
12, // 32: topfans.social.SocialService.SetFriendRemark:input_type -> topfans.social.SetFriendRemarkRequest
|
||||
14, // 33: topfans.social.SocialService.CheckFriendship:input_type -> topfans.social.CheckFriendshipRequest
|
||||
16, // 34: topfans.social.SocialService.GetFriendCount:input_type -> topfans.social.GetFriendCountRequest
|
||||
18, // 35: topfans.social.SocialService.SearchUserForFriend:input_type -> topfans.social.SearchUserForFriendRequest
|
||||
22, // 36: topfans.social.SocialService.GetRandomUsers:input_type -> topfans.social.GetRandomUsersRequest
|
||||
25, // 37: topfans.social.SocialService.GetUsersPaged:input_type -> topfans.social.GetUsersPagedRequest
|
||||
27, // 38: topfans.social.SocialService.LikeAsset:input_type -> topfans.social.LikeAssetRequest
|
||||
29, // 39: topfans.social.SocialService.UnlikeAsset:input_type -> topfans.social.UnlikeAssetRequest
|
||||
31, // 40: topfans.social.SocialService.CheckAssetLike:input_type -> topfans.social.CheckAssetLikeRequest
|
||||
33, // 41: topfans.social.SocialService.GetMyLikedAssets:input_type -> topfans.social.GetMyLikedAssetsRequest
|
||||
37, // 42: topfans.social.SocialService.GetMyTodayLikedAssets:input_type -> topfans.social.GetMyTodayLikedAssetsRequest
|
||||
39, // 43: topfans.social.SocialService.GetMyWeekLikedAssets:input_type -> topfans.social.GetMyWeekLikedAssetsRequest
|
||||
3, // 44: topfans.social.SocialService.SendFriendRequest:output_type -> topfans.social.SendFriendRequestResponse
|
||||
5, // 45: topfans.social.SocialService.GetFriendRequests:output_type -> topfans.social.GetFriendRequestsResponse
|
||||
7, // 46: topfans.social.SocialService.HandleFriendRequest:output_type -> topfans.social.HandleFriendRequestResponse
|
||||
9, // 47: topfans.social.SocialService.GetFriendList:output_type -> topfans.social.GetFriendListResponse
|
||||
11, // 48: topfans.social.SocialService.DeleteFriend:output_type -> topfans.social.DeleteFriendResponse
|
||||
13, // 49: topfans.social.SocialService.SetFriendRemark:output_type -> topfans.social.SetFriendRemarkResponse
|
||||
15, // 50: topfans.social.SocialService.CheckFriendship:output_type -> topfans.social.CheckFriendshipResponse
|
||||
17, // 51: topfans.social.SocialService.GetFriendCount:output_type -> topfans.social.GetFriendCountResponse
|
||||
19, // 52: topfans.social.SocialService.SearchUserForFriend:output_type -> topfans.social.SearchUserForFriendResponse
|
||||
23, // 53: topfans.social.SocialService.GetRandomUsers:output_type -> topfans.social.GetRandomUsersResponse
|
||||
26, // 54: topfans.social.SocialService.GetUsersPaged:output_type -> topfans.social.GetUsersPagedResponse
|
||||
28, // 55: topfans.social.SocialService.LikeAsset:output_type -> topfans.social.LikeAssetResponse
|
||||
30, // 56: topfans.social.SocialService.UnlikeAsset:output_type -> topfans.social.UnlikeAssetResponse
|
||||
32, // 57: topfans.social.SocialService.CheckAssetLike:output_type -> topfans.social.CheckAssetLikeResponse
|
||||
34, // 58: topfans.social.SocialService.GetMyLikedAssets:output_type -> topfans.social.GetMyLikedAssetsResponse
|
||||
38, // 59: topfans.social.SocialService.GetMyTodayLikedAssets:output_type -> topfans.social.GetMyTodayLikedAssetsResponse
|
||||
40, // 60: topfans.social.SocialService.GetMyWeekLikedAssets:output_type -> topfans.social.GetMyWeekLikedAssetsResponse
|
||||
44, // [44:61] is the sub-list for method output_type
|
||||
27, // [27:44] is the sub-list for method input_type
|
||||
27, // [27:27] is the sub-list for extension type_name
|
||||
27, // [27:27] is the sub-list for extension extendee
|
||||
0, // [0:27] is the sub-list for field type_name
|
||||
}
|
||||
|
||||
func init() { file_social_proto_init() }
|
||||
@ -3110,7 +2982,7 @@ func file_social_proto_init() {
|
||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||
RawDescriptor: unsafe.Slice(unsafe.StringData(file_social_proto_rawDesc), len(file_social_proto_rawDesc)),
|
||||
NumEnums: 0,
|
||||
NumMessages: 43,
|
||||
NumMessages: 41,
|
||||
NumExtensions: 0,
|
||||
NumServices: 1,
|
||||
},
|
||||
|
||||
@ -89,9 +89,6 @@ type SocialService interface {
|
||||
UnlikeAsset(ctx context.Context, req *UnlikeAssetRequest, opts ...client.CallOption) (*UnlikeAssetResponse, error)
|
||||
CheckAssetLike(ctx context.Context, req *CheckAssetLikeRequest, opts ...client.CallOption) (*CheckAssetLikeResponse, error)
|
||||
GetMyLikedAssets(ctx context.Context, req *GetMyLikedAssetsRequest, opts ...client.CallOption) (*GetMyLikedAssetsResponse, error)
|
||||
GetMyTodayLikedAssets(ctx context.Context, req *GetMyTodayLikedAssetsRequest, opts ...client.CallOption) (*GetMyTodayLikedAssetsResponse, error)
|
||||
GetMyWeekLikedAssets(ctx context.Context, req *GetMyWeekLikedAssetsRequest, opts ...client.CallOption) (*GetMyWeekLikedAssetsResponse, error)
|
||||
GetUserLikedAssets(ctx context.Context, req *GetUserLikedAssetsRequest, opts ...client.CallOption) (*GetUserLikedAssetsResponse, error)
|
||||
}
|
||||
|
||||
// NewSocialService constructs a client for the social.SocialService service.
|
||||
@ -234,33 +231,9 @@ func (c *SocialServiceImpl) GetMyLikedAssets(ctx context.Context, req *GetMyLike
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
func (c *SocialServiceImpl) GetMyTodayLikedAssets(ctx context.Context, req *GetMyTodayLikedAssetsRequest, opts ...client.CallOption) (*GetMyTodayLikedAssetsResponse, error) {
|
||||
resp := new(GetMyTodayLikedAssetsResponse)
|
||||
if err := c.conn.CallUnary(ctx, []interface{}{req}, resp, "GetMyTodayLikedAssets", opts...); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
func (c *SocialServiceImpl) GetMyWeekLikedAssets(ctx context.Context, req *GetMyWeekLikedAssetsRequest, opts ...client.CallOption) (*GetMyWeekLikedAssetsResponse, error) {
|
||||
resp := new(GetMyWeekLikedAssetsResponse)
|
||||
if err := c.conn.CallUnary(ctx, []interface{}{req}, resp, "GetMyWeekLikedAssets", opts...); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
func (c *SocialServiceImpl) GetUserLikedAssets(ctx context.Context, req *GetUserLikedAssetsRequest, opts ...client.CallOption) (*GetUserLikedAssetsResponse, error) {
|
||||
resp := new(GetUserLikedAssetsResponse)
|
||||
if err := c.conn.CallUnary(ctx, []interface{}{req}, resp, "GetUserLikedAssets", opts...); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
var SocialService_ClientInfo = client.ClientInfo{
|
||||
InterfaceName: "topfans.social.SocialService",
|
||||
MethodNames: []string{"SendFriendRequest", "GetFriendRequests", "HandleFriendRequest", "GetFriendList", "DeleteFriend", "SetFriendRemark", "CheckFriendship", "GetFriendCount", "SearchUserForFriend", "GetRandomUsers", "GetUsersPaged", "LikeAsset", "UnlikeAsset", "CheckAssetLike", "GetMyLikedAssets", "GetMyTodayLikedAssets", "GetMyWeekLikedAssets", "GetUserLikedAssets"},
|
||||
MethodNames: []string{"SendFriendRequest", "GetFriendRequests", "HandleFriendRequest", "GetFriendList", "DeleteFriend", "SetFriendRemark", "CheckFriendship", "GetFriendCount", "SearchUserForFriend", "GetRandomUsers", "GetUsersPaged", "LikeAsset", "UnlikeAsset", "CheckAssetLike", "GetMyLikedAssets"},
|
||||
ConnectionInjectFunc: func(dubboCliRaw interface{}, conn *client.Connection) {
|
||||
dubboCli := dubboCliRaw.(*SocialServiceImpl)
|
||||
dubboCli.conn = conn
|
||||
@ -284,9 +257,6 @@ type SocialServiceHandler interface {
|
||||
UnlikeAsset(context.Context, *UnlikeAssetRequest) (*UnlikeAssetResponse, error)
|
||||
CheckAssetLike(context.Context, *CheckAssetLikeRequest) (*CheckAssetLikeResponse, error)
|
||||
GetMyLikedAssets(context.Context, *GetMyLikedAssetsRequest) (*GetMyLikedAssetsResponse, error)
|
||||
GetMyTodayLikedAssets(context.Context, *GetMyTodayLikedAssetsRequest) (*GetMyTodayLikedAssetsResponse, error)
|
||||
GetMyWeekLikedAssets(context.Context, *GetMyWeekLikedAssetsRequest) (*GetMyWeekLikedAssetsResponse, error)
|
||||
GetUserLikedAssets(context.Context, *GetUserLikedAssetsRequest) (*GetUserLikedAssetsResponse, error)
|
||||
}
|
||||
|
||||
func RegisterSocialServiceHandler(srv *server.Server, hdlr SocialServiceHandler, opts ...server.ServiceOption) error {
|
||||
@ -526,50 +496,5 @@ var SocialService_ServiceInfo = server.ServiceInfo{
|
||||
return triple_protocol.NewResponse(res), nil
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "GetMyTodayLikedAssets",
|
||||
Type: constant.CallUnary,
|
||||
ReqInitFunc: func() interface{} {
|
||||
return new(GetMyTodayLikedAssetsRequest)
|
||||
},
|
||||
MethodFunc: func(ctx context.Context, args []interface{}, handler interface{}) (interface{}, error) {
|
||||
req := args[0].(*GetMyTodayLikedAssetsRequest)
|
||||
res, err := handler.(SocialServiceHandler).GetMyTodayLikedAssets(ctx, req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return triple_protocol.NewResponse(res), nil
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "GetMyWeekLikedAssets",
|
||||
Type: constant.CallUnary,
|
||||
ReqInitFunc: func() interface{} {
|
||||
return new(GetMyWeekLikedAssetsRequest)
|
||||
},
|
||||
MethodFunc: func(ctx context.Context, args []interface{}, handler interface{}) (interface{}, error) {
|
||||
req := args[0].(*GetMyWeekLikedAssetsRequest)
|
||||
res, err := handler.(SocialServiceHandler).GetMyWeekLikedAssets(ctx, req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return triple_protocol.NewResponse(res), nil
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "GetUserLikedAssets",
|
||||
Type: constant.CallUnary,
|
||||
ReqInitFunc: func() interface{} {
|
||||
return new(GetUserLikedAssetsRequest)
|
||||
},
|
||||
MethodFunc: func(ctx context.Context, args []interface{}, handler interface{}) (interface{}, error) {
|
||||
req := args[0].(*GetUserLikedAssetsRequest)
|
||||
res, err := handler.(SocialServiceHandler).GetUserLikedAssets(ctx, req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return triple_protocol.NewResponse(res), nil
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
@ -61,13 +61,6 @@ service GalleryService {
|
||||
get: "/api/v1/inspiration-flow"
|
||||
};
|
||||
}
|
||||
|
||||
// 获取他人展出的作品列表(暂不实现)
|
||||
rpc GetUserExhibitedAssets(GetUserExhibitedAssetsRequest) returns (GetUserExhibitedAssetsResponse) {
|
||||
option (google.api.http) = {
|
||||
get: "/api/v1/users/{user_id}/exhibited-assets"
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// 请求和响应消息定义
|
||||
@ -231,18 +224,3 @@ message InspirationFlowItem {
|
||||
int32 span = 6; // 卡片大小: 0-30→1, 31-100→2, 101-200→3, 200+→4
|
||||
string material_type = 7; // 素材类型: hot(人气王者), potential(潜力之星), new(新鲜上架)
|
||||
}
|
||||
|
||||
// ==================== 他人作品相关消息(暂不实现)====================
|
||||
|
||||
// 获取他人展出的作品列表请求(暂不实现)
|
||||
message GetUserExhibitedAssetsRequest {
|
||||
int64 user_id = 1; // 他人用户ID
|
||||
int32 page = 2; // 页码(默认1)
|
||||
int32 page_size = 3; // 每页数量(默认20,最大100)
|
||||
}
|
||||
|
||||
// 获取他人展出的作品列表响应(暂不实现)
|
||||
message GetUserExhibitedAssetsResponse {
|
||||
topfans.common.BaseResponse base = 1;
|
||||
ExhibitedAssetsData data = 2;
|
||||
}
|
||||
|
||||
@ -317,19 +317,6 @@ message GetMyWeekLikedAssetsResponse {
|
||||
LikedAssetsData data = 2;
|
||||
}
|
||||
|
||||
// 获取他人点赞的作品列表请求(暂不实现)
|
||||
message GetUserLikedAssetsRequest {
|
||||
int64 user_id = 1; // 他人用户ID
|
||||
int32 page = 2; // 页码(默认1)
|
||||
int32 page_size = 3; // 每页数量(默认20,最大100)
|
||||
}
|
||||
|
||||
// 获取他人点赞的作品列表响应(暂不实现)
|
||||
message GetUserLikedAssetsResponse {
|
||||
topfans.common.BaseResponse base = 1;
|
||||
LikedAssetsData data = 2;
|
||||
}
|
||||
|
||||
// ==================== 社交服务(包含好友等功能)====================
|
||||
|
||||
service SocialService {
|
||||
@ -464,12 +451,5 @@ service SocialService {
|
||||
get: "/api/v1/me/week-liked-assets"
|
||||
};
|
||||
}
|
||||
|
||||
// 获取他人点赞的作品列表(暂不实现)
|
||||
rpc GetUserLikedAssets(GetUserLikedAssetsRequest) returns (GetUserLikedAssetsResponse) {
|
||||
option (google.api.http) = {
|
||||
get: "/api/v1/users/{user_id}/liked-assets"
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -396,31 +396,6 @@ func (p *GalleryProvider) GetInspirationFlow(ctx context.Context, req *pb.GetIns
|
||||
}, nil
|
||||
}
|
||||
|
||||
// GetUserExhibitedAssets 获取他人展出的作品列表
|
||||
func (p *GalleryProvider) GetUserExhibitedAssets(ctx context.Context, req *pb.GetUserExhibitedAssetsRequest) (*pb.GetUserExhibitedAssetsResponse, error) {
|
||||
logger.Logger.Info("Received GetUserExhibitedAssets request",
|
||||
zap.Int64("target_user_id", req.UserId),
|
||||
)
|
||||
|
||||
// 从 Dubbo attachments 获取用户信息(网关已验证并传递)
|
||||
userID, starID, err := extractUserInfoFromDubboAttachments(ctx)
|
||||
if err != nil {
|
||||
logger.Logger.Error("Failed to extract user info from attachments",
|
||||
zap.Error(err),
|
||||
)
|
||||
return &pb.GetUserExhibitedAssetsResponse{
|
||||
Base: &pbCommon.BaseResponse{
|
||||
Code: pbCommon.StatusCode_STATUS_UNAUTHORIZED,
|
||||
Message: "user authentication required",
|
||||
Timestamp: 0,
|
||||
},
|
||||
}, err
|
||||
}
|
||||
|
||||
// 调用Service层
|
||||
return p.exhibitionService.GetUserExhibitedAssets(ctx, userID, starID, req)
|
||||
}
|
||||
|
||||
// ==================== 辅助函数 ====================
|
||||
|
||||
// extractUserInfoFromDubboAttachments 从Dubbo attachments提取用户信息
|
||||
|
||||
@ -32,11 +32,6 @@ type GalleryRepository interface {
|
||||
// 资产注册表相关
|
||||
UpdateAssetRegistryDisplayStatus(assetID int64, displayStatus int32) error
|
||||
|
||||
// 事务性操作:创建展品并更新展示状态(原子操作)
|
||||
PlaceExhibitionTx(exhibition *models.Exhibition, displayStatus int32) error
|
||||
// 事务性操作:删除展品并更新展示状态(原子操作)
|
||||
RemoveExhibitionTx(exhibitionID int64, assetID int64) error
|
||||
|
||||
// ========== 我的作品相关 ==========
|
||||
|
||||
// GetMyExhibitedAssets 获取我展出的作品列表(只返回展出中且未过期的,含收益)
|
||||
@ -47,14 +42,6 @@ type GalleryRepository interface {
|
||||
// 返回: 作品列表、总数量
|
||||
GetMyExhibitedAssets(userID, starID int64, page, pageSize int) ([]*ExhibitedAssetInfo, int64, error)
|
||||
|
||||
// GetUserExhibitedAssets 获取他人展出的作品列表(只返回展出中且未过期的)
|
||||
// userID: 他人用户ID
|
||||
// starID: 明星ID
|
||||
// page: 页码(从1开始)
|
||||
// pageSize: 每页数量
|
||||
// 返回: 作品列表、总数量
|
||||
GetUserExhibitedAssets(userID, starID int64, page, pageSize int) ([]*ExhibitedAssetInfo, int64, error)
|
||||
|
||||
// ========== 灵感瀑布相关 ==========
|
||||
|
||||
// CountValidExhibitions 统计有效展品数量
|
||||
@ -287,59 +274,6 @@ func (r *galleryRepository) UpdateAssetRegistryDisplayStatus(assetID int64, disp
|
||||
Update("display_status", displayStatus).Error
|
||||
}
|
||||
|
||||
// PlaceExhibitionTx 事务性创建展品并更新展示状态(原子操作)
|
||||
func (r *galleryRepository) PlaceExhibitionTx(exhibition *models.Exhibition, displayStatus int32) error {
|
||||
now := time.Now().UnixMilli()
|
||||
exhibition.CreatedAt = now
|
||||
exhibition.UpdatedAt = now
|
||||
exhibition.DeletedAt = nil
|
||||
|
||||
return r.db.Transaction(func(tx *gorm.DB) error {
|
||||
// 1. 物理删除已软删除的旧记录
|
||||
if err := tx.Exec(`
|
||||
DELETE FROM exhibitions
|
||||
WHERE asset_id = ? AND deleted_at IS NOT NULL
|
||||
`, exhibition.AssetID).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
// 2. 插入新记录
|
||||
if err := tx.Create(exhibition).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
// 3. 更新展示状态(与展出操作在同一事务中)
|
||||
if err := tx.Model(&models.AssetRegistry{}).
|
||||
Where("asset_id = ?", exhibition.AssetID).
|
||||
Update("display_status", displayStatus).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
// RemoveExhibitionTx 事务性删除展品并更新展示状态(原子操作)
|
||||
func (r *galleryRepository) RemoveExhibitionTx(exhibitionID int64, assetID int64) error {
|
||||
now := time.Now().UnixMilli()
|
||||
|
||||
return r.db.Transaction(func(tx *gorm.DB) error {
|
||||
// 1. 软删除展品记录
|
||||
if err := tx.Model(&models.Exhibition{}).
|
||||
Where("id = ?", exhibitionID).
|
||||
Updates(map[string]interface{}{
|
||||
"deleted_at": now,
|
||||
"updated_at": now,
|
||||
}).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
// 2. 更新展示状态为未展示(与删除操作在同一事务中)
|
||||
if err := tx.Model(&models.AssetRegistry{}).
|
||||
Where("asset_id = ?", assetID).
|
||||
Update("display_status", int32(0)).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
// ========== 我的作品相关实现 ==========
|
||||
|
||||
// GetMyExhibitedAssets 获取我展出的作品列表(只返回展出中且未过期的,含收益)
|
||||
@ -362,56 +296,15 @@ func (r *galleryRepository) GetMyExhibitedAssets(userID, starID int64, page, pag
|
||||
err = r.db.Model(&models.Exhibition{}).
|
||||
Raw(`
|
||||
SELECT exhibitions.asset_id, a.name, a.cover_url, a.like_count,
|
||||
exhibitions.start_time as exhibited_at, exhibitions.expire_at, bs.slot_index,
|
||||
exhibitions.start_time as exhibited_at, exhibitions.expire_at,
|
||||
COALESCE(CAST(SUM(err.crystal_amount) / 10 AS bigint), 0) as earnings
|
||||
FROM exhibitions
|
||||
JOIN assets a ON a.id = exhibitions.asset_id
|
||||
JOIN booth_slots bs ON bs.slot_id = exhibitions.slot_id
|
||||
LEFT JOIN exhibition_revenue_records err ON err.asset_id = a.id AND err.status = 'claimable'
|
||||
WHERE exhibitions.occupier_uid = ? AND exhibitions.occupier_star_id = ?
|
||||
AND exhibitions.deleted_at IS NULL AND exhibitions.expire_at > ?
|
||||
GROUP BY exhibitions.asset_id, a.name, a.cover_url, a.like_count, exhibitions.start_time, exhibitions.expire_at, bs.slot_index
|
||||
ORDER BY bs.slot_index ASC
|
||||
LIMIT ? OFFSET ?
|
||||
`, userID, starID, now, pageSize, offset).Scan(&items).Error
|
||||
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
return items, total, nil
|
||||
}
|
||||
|
||||
// GetUserExhibitedAssets 获取他人展出的作品列表(只返回展出中且未过期的)
|
||||
func (r *galleryRepository) GetUserExhibitedAssets(userID, starID int64, page, pageSize int) ([]*ExhibitedAssetInfo, int64, error) {
|
||||
var items []*ExhibitedAssetInfo
|
||||
var total int64
|
||||
|
||||
now := time.Now().UnixMilli()
|
||||
|
||||
// 计数查询
|
||||
err := r.db.Model(&models.Exhibition{}).
|
||||
Where("occupier_uid = ? AND occupier_star_id = ? AND deleted_at IS NULL AND expire_at > ?", userID, starID, now).
|
||||
Count(&total).Error
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
// 数据查询
|
||||
offset := (page - 1) * pageSize
|
||||
err = r.db.Model(&models.Exhibition{}).
|
||||
Raw(`
|
||||
SELECT exhibitions.asset_id, a.name, a.cover_url, a.like_count,
|
||||
exhibitions.start_time as exhibited_at, exhibitions.expire_at, bs.slot_index,
|
||||
COALESCE(CAST(SUM(err.crystal_amount) / 10 AS bigint), 0) as earnings
|
||||
FROM exhibitions
|
||||
JOIN assets a ON a.id = exhibitions.asset_id
|
||||
JOIN booth_slots bs ON bs.slot_id = exhibitions.slot_id
|
||||
LEFT JOIN exhibition_revenue_records err ON err.asset_id = a.id AND err.status = 'claimable'
|
||||
WHERE exhibitions.occupier_uid = ? AND exhibitions.occupier_star_id = ?
|
||||
AND exhibitions.deleted_at IS NULL AND exhibitions.expire_at > ?
|
||||
GROUP BY exhibitions.asset_id, a.name, a.cover_url, a.like_count, exhibitions.start_time, exhibitions.expire_at, bs.slot_index
|
||||
ORDER BY bs.slot_index ASC
|
||||
GROUP BY exhibitions.asset_id, a.name, a.cover_url, a.like_count, exhibitions.start_time, exhibitions.expire_at
|
||||
ORDER BY exhibitions.start_time DESC
|
||||
LIMIT ? OFFSET ?
|
||||
`, userID, starID, now, pageSize, offset).Scan(&items).Error
|
||||
|
||||
|
||||
@ -400,78 +400,6 @@ func (p *SocialProvider) GetMyLikedAssets(ctx context.Context, req *pb.GetMyLike
|
||||
return p.assetLikeService.GetMyLikedAssets(ctx, req, userID, starID)
|
||||
}
|
||||
|
||||
// GetMyTodayLikedAssets 获取我今日点赞的作品列表
|
||||
func (p *SocialProvider) GetMyTodayLikedAssets(ctx context.Context, req *pb.GetMyTodayLikedAssetsRequest) (*pb.GetMyTodayLikedAssetsResponse, error) {
|
||||
userID, starID, err := extractUserInfo(ctx)
|
||||
if err != nil {
|
||||
logger.Logger.Warn("Failed to extract user info from context", zap.Error(err))
|
||||
return &pb.GetMyTodayLikedAssetsResponse{
|
||||
Base: &common.BaseResponse{
|
||||
Code: common.StatusCode_STATUS_UNAUTHORIZED,
|
||||
Message: "Unauthorized: " + err.Error(),
|
||||
Timestamp: time.Now().UnixMilli(),
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
logger.Logger.Debug("GetMyTodayLikedAssets called",
|
||||
zap.Int64("user_id", userID),
|
||||
zap.Int64("star_id", starID),
|
||||
zap.Int32("page", req.Page),
|
||||
zap.Int32("page_size", req.PageSize),
|
||||
)
|
||||
|
||||
return p.assetLikeService.GetMyTodayLikedAssets(ctx, req, userID, starID)
|
||||
}
|
||||
|
||||
// GetMyWeekLikedAssets 获取我本周点赞的作品列表
|
||||
func (p *SocialProvider) GetMyWeekLikedAssets(ctx context.Context, req *pb.GetMyWeekLikedAssetsRequest) (*pb.GetMyWeekLikedAssetsResponse, error) {
|
||||
userID, starID, err := extractUserInfo(ctx)
|
||||
if err != nil {
|
||||
logger.Logger.Warn("Failed to extract user info from context", zap.Error(err))
|
||||
return &pb.GetMyWeekLikedAssetsResponse{
|
||||
Base: &common.BaseResponse{
|
||||
Code: common.StatusCode_STATUS_UNAUTHORIZED,
|
||||
Message: "Unauthorized: " + err.Error(),
|
||||
Timestamp: time.Now().UnixMilli(),
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
logger.Logger.Debug("GetMyWeekLikedAssets called",
|
||||
zap.Int64("user_id", userID),
|
||||
zap.Int64("star_id", starID),
|
||||
zap.Int32("page", req.Page),
|
||||
zap.Int32("page_size", req.PageSize),
|
||||
)
|
||||
|
||||
return p.assetLikeService.GetMyWeekLikedAssets(ctx, req, userID, starID)
|
||||
}
|
||||
|
||||
// GetUserLikedAssets 获取他人点赞的作品列表
|
||||
func (p *SocialProvider) GetUserLikedAssets(ctx context.Context, req *pb.GetUserLikedAssetsRequest) (*pb.GetUserLikedAssetsResponse, error) {
|
||||
userID, starID, err := extractUserInfo(ctx)
|
||||
if err != nil {
|
||||
logger.Logger.Warn("Failed to extract user info from context", zap.Error(err))
|
||||
return &pb.GetUserLikedAssetsResponse{
|
||||
Base: &common.BaseResponse{
|
||||
Code: common.StatusCode_STATUS_UNAUTHORIZED,
|
||||
Message: "Unauthorized: " + err.Error(),
|
||||
Timestamp: time.Now().UnixMilli(),
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
logger.Logger.Debug("GetUserLikedAssets called",
|
||||
zap.Int64("user_id", userID),
|
||||
zap.Int64("star_id", starID),
|
||||
zap.Int32("page", req.Page),
|
||||
zap.Int32("page_size", req.PageSize),
|
||||
)
|
||||
|
||||
return p.assetLikeService.GetUserLikedAssets(ctx, req, userID, starID)
|
||||
}
|
||||
|
||||
// extractUserInfo 从 Dubbo attachments 中提取用户信息
|
||||
// 网关调用:网关已验证 Token 并将 user_id 和 star_id 通过 attachments 传递
|
||||
func extractUserInfo(ctx context.Context) (int64, int64, error) {
|
||||
|
||||
@ -111,30 +111,6 @@ type SocialRepository interface {
|
||||
// pageSize: 每页数量
|
||||
// 返回: 作品列表、总数量
|
||||
GetMyLikedAssets(userID, starID int64, page, pageSize int) ([]*LikedAssetInfo, int64, error)
|
||||
|
||||
// GetMyTodayLikedAssets 获取我今日点赞的作品列表(只返回展出中且未过期的)
|
||||
// userID: 用户ID
|
||||
// starID: 明星ID
|
||||
// page: 页码(从1开始)
|
||||
// pageSize: 每页数量
|
||||
// 返回: 作品列表、总数量
|
||||
GetMyTodayLikedAssets(userID, starID int64, page, pageSize int) ([]*LikedAssetInfo, int64, error)
|
||||
|
||||
// GetMyWeekLikedAssets 获取我本周点赞的作品列表(只返回展出中且未过期的)
|
||||
// userID: 用户ID
|
||||
// starID: 明星ID
|
||||
// page: 页码(从1开始)
|
||||
// pageSize: 每页数量
|
||||
// 返回: 作品列表、总数量
|
||||
GetMyWeekLikedAssets(userID, starID int64, page, pageSize int) ([]*LikedAssetInfo, int64, error)
|
||||
|
||||
// GetUserLikedAssets 获取他人点赞的作品列表(只返回展出中且未过期的)
|
||||
// userID: 他人用户ID
|
||||
// starID: 明星ID
|
||||
// page: 页码(从1开始)
|
||||
// pageSize: 每页数量
|
||||
// 返回: 作品列表、总数量
|
||||
GetUserLikedAssets(userID, starID int64, page, pageSize int) ([]*LikedAssetInfo, int64, error)
|
||||
}
|
||||
|
||||
// LikedAssetInfo 我点赞的作品信息
|
||||
@ -617,142 +593,3 @@ func (r *socialRepositoryImpl) GetMyLikedAssets(userID, starID int64, page, page
|
||||
|
||||
return items, total, nil
|
||||
}
|
||||
|
||||
// GetMyTodayLikedAssets 获取我今日点赞的作品列表(只返回展出中且未过期的)
|
||||
func (r *socialRepositoryImpl) GetMyTodayLikedAssets(userID, starID int64, page, pageSize int) ([]*LikedAssetInfo, int64, error) {
|
||||
now := time.Now()
|
||||
startOfDay := time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, now.Location()).UnixMilli()
|
||||
|
||||
var items []*LikedAssetInfo
|
||||
var total int64
|
||||
|
||||
countQuery := r.db.Model(&models.AssetLike{}).
|
||||
Joins("JOIN assets a ON a.id = asset_likes.asset_id").
|
||||
Joins("JOIN exhibitions e ON e.asset_id = a.id").
|
||||
Where("asset_likes.user_id = ? AND asset_likes.star_id = ?", userID, starID).
|
||||
Where("asset_likes.created_at >= ?", startOfDay).
|
||||
Where("a.deleted_at IS NULL AND a.is_active = ?", true).
|
||||
Where("e.deleted_at IS NULL AND e.expire_at > ?", now.UnixMilli())
|
||||
|
||||
if err := countQuery.Distinct("asset_likes.asset_id").Count(&total).Error; err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
offset := (page - 1) * pageSize
|
||||
err := r.db.Model(&models.AssetLike{}).
|
||||
Select(`asset_likes.asset_id, a.name, a.cover_url, a.like_count,
|
||||
asset_likes.created_at as liked_at,
|
||||
COALESCE(SUM(err.crystal_amount), 0) as earnings`).
|
||||
Joins("JOIN assets a ON a.id = asset_likes.asset_id").
|
||||
Joins("JOIN exhibitions e ON e.asset_id = a.id").
|
||||
Joins("LEFT JOIN exhibition_revenue_records err ON err.asset_id = a.id AND err.status = 'claimable'").
|
||||
Where("asset_likes.user_id = ? AND asset_likes.star_id = ?", userID, starID).
|
||||
Where("asset_likes.created_at >= ?", startOfDay).
|
||||
Where("a.deleted_at IS NULL AND a.is_active = ?", true).
|
||||
Where("e.deleted_at IS NULL AND e.expire_at > ?", now.UnixMilli()).
|
||||
Group("asset_likes.asset_id, a.name, a.cover_url, a.like_count, asset_likes.created_at").
|
||||
Order("asset_likes.created_at DESC").
|
||||
Limit(pageSize).
|
||||
Offset(offset).
|
||||
Scan(&items).Error
|
||||
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
return items, total, nil
|
||||
}
|
||||
|
||||
// GetMyWeekLikedAssets 获取我本周点赞的作品列表(只返回展出中且未过期的)
|
||||
func (r *socialRepositoryImpl) GetMyWeekLikedAssets(userID, starID int64, page, pageSize int) ([]*LikedAssetInfo, int64, error) {
|
||||
now := time.Now()
|
||||
// 本周开始于周一
|
||||
weekday := int(now.Weekday())
|
||||
if weekday == 0 {
|
||||
weekday = 7
|
||||
}
|
||||
startOfWeek := now.AddDate(0, 0, -weekday+1)
|
||||
startOfWeek = time.Date(startOfWeek.Year(), startOfWeek.Month(), startOfWeek.Day(), 0, 0, 0, 0, now.Location())
|
||||
startOfWeekMillis := startOfWeek.UnixMilli()
|
||||
|
||||
var items []*LikedAssetInfo
|
||||
var total int64
|
||||
|
||||
countQuery := r.db.Model(&models.AssetLike{}).
|
||||
Joins("JOIN assets a ON a.id = asset_likes.asset_id").
|
||||
Joins("JOIN exhibitions e ON e.asset_id = a.id").
|
||||
Where("asset_likes.user_id = ? AND asset_likes.star_id = ?", userID, starID).
|
||||
Where("asset_likes.created_at >= ?", startOfWeekMillis).
|
||||
Where("a.deleted_at IS NULL AND a.is_active = ?", true).
|
||||
Where("e.deleted_at IS NULL AND e.expire_at > ?", now.UnixMilli())
|
||||
|
||||
if err := countQuery.Distinct("asset_likes.asset_id").Count(&total).Error; err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
offset := (page - 1) * pageSize
|
||||
err := r.db.Model(&models.AssetLike{}).
|
||||
Select(`asset_likes.asset_id, a.name, a.cover_url, a.like_count,
|
||||
asset_likes.created_at as liked_at,
|
||||
COALESCE(SUM(err.crystal_amount), 0) as earnings`).
|
||||
Joins("JOIN assets a ON a.id = asset_likes.asset_id").
|
||||
Joins("JOIN exhibitions e ON e.asset_id = a.id").
|
||||
Joins("LEFT JOIN exhibition_revenue_records err ON err.asset_id = a.id AND err.status = 'claimable'").
|
||||
Where("asset_likes.user_id = ? AND asset_likes.star_id = ?", userID, starID).
|
||||
Where("asset_likes.created_at >= ?", startOfWeekMillis).
|
||||
Where("a.deleted_at IS NULL AND a.is_active = ?", true).
|
||||
Where("e.deleted_at IS NULL AND e.expire_at > ?", now.UnixMilli()).
|
||||
Group("asset_likes.asset_id, a.name, a.cover_url, a.like_count, asset_likes.created_at").
|
||||
Order("asset_likes.created_at DESC").
|
||||
Limit(pageSize).
|
||||
Offset(offset).
|
||||
Scan(&items).Error
|
||||
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
return items, total, nil
|
||||
}
|
||||
|
||||
// GetUserLikedAssets 获取他人点赞的作品列表(只返回展出中且未过期的)
|
||||
func (r *socialRepositoryImpl) GetUserLikedAssets(userID, starID int64, page, pageSize int) ([]*LikedAssetInfo, int64, error) {
|
||||
var items []*LikedAssetInfo
|
||||
var total int64
|
||||
|
||||
now := time.Now().UnixMilli()
|
||||
|
||||
countQuery := r.db.Model(&models.AssetLike{}).
|
||||
Joins("JOIN assets a ON a.id = asset_likes.asset_id").
|
||||
Joins("JOIN exhibitions e ON e.asset_id = a.id").
|
||||
Where("asset_likes.user_id = ? AND asset_likes.star_id = ?", userID, starID).
|
||||
Where("a.deleted_at IS NULL AND a.is_active = ?", true).
|
||||
Where("e.deleted_at IS NULL AND e.expire_at > ?", now)
|
||||
|
||||
if err := countQuery.Distinct("asset_likes.asset_id").Count(&total).Error; err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
offset := (page - 1) * pageSize
|
||||
err := r.db.Model(&models.AssetLike{}).
|
||||
Select(`asset_likes.asset_id, a.name, a.cover_url, a.like_count,
|
||||
asset_likes.created_at as liked_at,
|
||||
COALESCE(SUM(err.crystal_amount), 0) as earnings`).
|
||||
Joins("JOIN assets a ON a.id = asset_likes.asset_id").
|
||||
Joins("JOIN exhibitions e ON e.asset_id = a.id").
|
||||
Joins("LEFT JOIN exhibition_revenue_records err ON err.asset_id = a.id AND err.status = 'claimable'").
|
||||
Where("asset_likes.user_id = ? AND asset_likes.star_id = ?", userID, starID).
|
||||
Where("a.deleted_at IS NULL AND a.is_active = ?", true).
|
||||
Where("e.deleted_at IS NULL AND e.expire_at > ?", now).
|
||||
Group("asset_likes.asset_id, a.name, a.cover_url, a.like_count, asset_likes.created_at").
|
||||
Order("asset_likes.created_at DESC").
|
||||
Limit(pageSize).
|
||||
Offset(offset).
|
||||
Scan(&items).Error
|
||||
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
return items, total, nil
|
||||
}
|
||||
|
||||
@ -276,7 +276,6 @@ func (s *starbookService) buildAssetItemsFromRegistries(registries []*models.Ass
|
||||
var assetCoverMap map[int64]string // assetID -> coverURL
|
||||
var assetNameMap map[int64]string // assetID -> name
|
||||
var categoryMap map[int64]string // assetID -> category
|
||||
var assetLikeCountMap map[int64]int32 // assetID -> likeCount
|
||||
|
||||
switch assetType {
|
||||
case models.AssetTypeRegular:
|
||||
@ -284,11 +283,9 @@ func (s *starbookService) buildAssetItemsFromRegistries(registries []*models.Ass
|
||||
if err == nil && len(assets) > 0 {
|
||||
assetCoverMap = make(map[int64]string)
|
||||
assetNameMap = make(map[int64]string)
|
||||
assetLikeCountMap = make(map[int64]int32)
|
||||
for _, asset := range assets {
|
||||
assetCoverMap[asset.ID] = asset.CoverURL
|
||||
assetNameMap[asset.ID] = asset.Name
|
||||
assetLikeCountMap[asset.ID] = asset.LikeCount
|
||||
}
|
||||
}
|
||||
case models.AssetTypeCollection:
|
||||
@ -348,13 +345,6 @@ func (s *starbookService) buildAssetItemsFromRegistries(registries []*models.Ass
|
||||
item.Category = cat
|
||||
}
|
||||
|
||||
// 从 assets 表获取点赞数(regular 类型)
|
||||
if assetType == models.AssetTypeRegular {
|
||||
if likeCount, ok := assetLikeCountMap[reg.AssetID]; ok {
|
||||
item.LikeCount = likeCount
|
||||
}
|
||||
}
|
||||
|
||||
items = append(items, item)
|
||||
}
|
||||
|
||||
|
||||
@ -2,8 +2,8 @@
|
||||
"name" : "TopFans",
|
||||
"appid" : "__UNI__F199FF4",
|
||||
"description" : "",
|
||||
"versionName" : "1.0.4",
|
||||
"versionCode" : 102,
|
||||
"versionName" : "1.0.3",
|
||||
"versionCode" : 100,
|
||||
"transformPx" : false,
|
||||
/* 5+App特有相关 */
|
||||
"app-plus" : {
|
||||
@ -23,8 +23,7 @@
|
||||
"modules" : {
|
||||
"VideoPlayer" : {},
|
||||
"Camera" : {},
|
||||
"Speech" : {},
|
||||
"Push" : {}
|
||||
"Speech" : {}
|
||||
},
|
||||
/* 应用发布信息 */
|
||||
"distribute" : {
|
||||
@ -71,7 +70,12 @@
|
||||
"secretkey" : "1i5Aj8FwL3i11LYPeXMRwRWycictWq2X"
|
||||
}
|
||||
},
|
||||
"push" : {}
|
||||
"push" : {
|
||||
"unipush" : {
|
||||
"version" : "2",
|
||||
"offline" : false
|
||||
}
|
||||
}
|
||||
},
|
||||
"icons" : {
|
||||
"android" : {
|
||||
|
||||
@ -101,15 +101,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/profile/hisWorks",
|
||||
"style": {
|
||||
"navigationStyle": "custom",
|
||||
"app-plus": {
|
||||
"bounce": "none"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/exhibition/exhibition",
|
||||
"style": {
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
<view v-if="visible" class="asset-selector-mask" @tap="closeModal">
|
||||
<view class="asset-selector-modal" @tap.stop :class="{ 'show': animated }">
|
||||
<!-- 背景图片 -->
|
||||
<image class="modal-background" src="/static/starbookcontent/beijing.png" mode="aspectFill"></image>
|
||||
<image class="modal-background" src="/static/background/starbook.jpg" mode="aspectFill"></image>
|
||||
|
||||
<!-- 内容包装器 -->
|
||||
<view class="modal-content">
|
||||
@ -18,7 +18,7 @@
|
||||
</view>
|
||||
|
||||
<!-- 类型Tab -->
|
||||
<!-- <view class="modal-tabs">
|
||||
<view class="modal-tabs">
|
||||
<view
|
||||
v-for="tab in tabs"
|
||||
:key="tab.key"
|
||||
@ -28,7 +28,7 @@
|
||||
>
|
||||
<text>{{ tab.label }}</text>
|
||||
</view>
|
||||
</view> -->
|
||||
</view>
|
||||
|
||||
<!-- 加载中 -->
|
||||
<view v-if="loading" class="modal-loading">
|
||||
@ -46,11 +46,6 @@
|
||||
<template v-if="currentType === 'regular'">
|
||||
<view v-for="gradeItem in regularGrades" :key="gradeItem.grade" class="grade-section">
|
||||
<view class="grade-header">
|
||||
<image
|
||||
class="grade-header-bg"
|
||||
:src="getGradeBackground(gradeItem.grade)"
|
||||
mode="aspectFill"
|
||||
></image>
|
||||
<text class="grade-title">{{ formatGrade(gradeItem.grade) }}</text>
|
||||
</view>
|
||||
<scroll-view class="asset-row" scroll-x :show-scrollbar="false" :enable-flex="true">
|
||||
@ -63,20 +58,18 @@
|
||||
>
|
||||
<image
|
||||
class="asset-image"
|
||||
:class="{ 'nft-image-displayed': item.display_status === 1 }"
|
||||
:src="item.coverUrl || '/static/nft/collection.png'"
|
||||
mode="aspectFill"
|
||||
/>
|
||||
<view v-if="item.display_status === 1" class="status-overlay">
|
||||
<text class="status-text-center">已展示</text>
|
||||
</view>
|
||||
<view class="card-rate-badge-overlay">
|
||||
<image class="heart-icon" src="/static/icon/heart-icon.png" mode="aspectFit"></image>
|
||||
<text class="card-rate-text">{{ item.like_count || 0 }}</text>
|
||||
</view>
|
||||
<!-- <view class="asset-info">
|
||||
<text class="status-text-center">已展示</text>
|
||||
</view>
|
||||
<view v-else class="status-overlay-pending">
|
||||
<text class="status-text-pending">待展示</text>
|
||||
</view>
|
||||
<view class="asset-info">
|
||||
<text class="asset-name">{{ item.name }}</text>
|
||||
</view> -->
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
@ -96,17 +89,15 @@
|
||||
>
|
||||
<image
|
||||
class="asset-image"
|
||||
:class="{ 'nft-image-displayed': item.display_status === 1 }"
|
||||
:src="item.coverUrl || '/static/nft/collection.png'"
|
||||
mode="aspectFill"
|
||||
/>
|
||||
<view v-if="item.display_status === 1" class="status-overlay">
|
||||
<text class="status-text-center">已展示</text>
|
||||
</view>
|
||||
<view class="card-rate-badge-overlay">
|
||||
<image class="heart-icon" src="/static/icon/heart-icon.png" mode="aspectFit"></image>
|
||||
<text class="card-rate-text">{{ item.like_count || 0 }}</text>
|
||||
</view>
|
||||
<text class="status-text-center">已展示</text>
|
||||
</view>
|
||||
<view v-else class="status-overlay-pending">
|
||||
<text class="status-text-pending">待展示</text>
|
||||
</view>
|
||||
<view class="asset-info">
|
||||
<text class="asset-name">{{ item.name }}</text>
|
||||
</view>
|
||||
@ -203,18 +194,7 @@ const currentItems = computed(() => {
|
||||
|
||||
// grade 中文转换
|
||||
const gradeMap = { 1: '一', 2: '二', 3: '三', 4: '四', 5: '五' };
|
||||
const formatGrade = (grade) => `V${grade}`;
|
||||
|
||||
// 获取等级背景图
|
||||
const getGradeBackground = (grade) => {
|
||||
if (grade <= 2) {
|
||||
return '/static/starbookcontent/V1dengji.png';
|
||||
} else if (grade <= 4) {
|
||||
return '/static/starbookcontent/V2dengji.png';
|
||||
} else {
|
||||
return '/static/starbookcontent/V3dengji.png';
|
||||
}
|
||||
};
|
||||
const formatGrade = (grade) => `等级${gradeMap[grade] || grade}`;
|
||||
|
||||
// 切换类型
|
||||
const switchType = (type) => {
|
||||
@ -485,38 +465,21 @@ const handleTouchEnd = (e) => {
|
||||
}
|
||||
|
||||
.grade-section {
|
||||
background: #f0839960;
|
||||
background: rgba(255, 255, 255, 0.03);
|
||||
border-radius: 16rpx;
|
||||
padding: 20rpx;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.grade-header {
|
||||
position: relative;
|
||||
margin-bottom: 16rpx;
|
||||
padding: 16rpx 24rpx;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 160rpx;
|
||||
height: 32rpx;
|
||||
}
|
||||
|
||||
.grade-header-bg {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 160rpx;
|
||||
height: 64rpx;
|
||||
z-index: 0;
|
||||
padding-bottom: 10rpx;
|
||||
border-bottom: 1rpx solid rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
|
||||
.grade-title {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
font-size: 24rpx;
|
||||
font-size: 26rpx;
|
||||
color: rgba(255, 255, 255, 0.8);
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.asset-row {
|
||||
@ -551,17 +514,12 @@ const handleTouchEnd = (e) => {
|
||||
|
||||
.asset-image {
|
||||
width: 192rpx;
|
||||
height: 100%;
|
||||
height: 224rpx;
|
||||
border-radius: 16rpx;
|
||||
background: rgba(255, 255, 255, 0.05);
|
||||
display: block;
|
||||
}
|
||||
|
||||
/* 已展示的图片 - 灰色滤镜 */
|
||||
.nft-image-displayed {
|
||||
filter: grayscale(25%);
|
||||
}
|
||||
|
||||
.status-overlay {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
@ -610,40 +568,6 @@ const handleTouchEnd = (e) => {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
/* 点赞数徽章 - 图片上覆盖层 */
|
||||
.card-rate-badge-overlay {
|
||||
position: absolute;
|
||||
bottom: 12rpx;
|
||||
left: 12rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
background: linear-gradient(to bottom right,
|
||||
#F0E4B1 0%,
|
||||
#F08399 50%,
|
||||
#B94E73 100%);
|
||||
border-radius: 999rpx;
|
||||
padding: 8rpx 20rpx 8rpx 40rpx;
|
||||
box-shadow:
|
||||
0 4rpx 12rpx rgba(255, 143, 158, 0.2),
|
||||
inset 0 2rpx 4rpx rgba(255, 255, 255, 0.4);
|
||||
|
||||
border-radius: 20rpx;
|
||||
padding: 6rpx 12rpx;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.card-rate-badge-overlay .heart-icon {
|
||||
width: 24rpx;
|
||||
height: 24rpx;
|
||||
margin-right: 6rpx;
|
||||
}
|
||||
|
||||
.card-rate-badge-overlay .card-rate-text {
|
||||
font-size: 22rpx;
|
||||
color: #fff;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.asset-info {
|
||||
padding: 12rpx 0;
|
||||
text-align: center;
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<!-- 只渲染背景图,卡片由父组件 BannerCarousel 渲染在 swiper 外层 -->
|
||||
<view class="banner-top3-bg" >
|
||||
<view class="banner-top3-bg" @tap="onBannerTap">
|
||||
<image class="banner-bg" src="/static/square/paihangbang.png" mode="aspectFill" />
|
||||
</view>
|
||||
</template>
|
||||
@ -32,9 +32,9 @@ const loadTop3 = async () => {
|
||||
}
|
||||
};
|
||||
|
||||
// const onBannerTap = () => {
|
||||
// uni.navigateTo({ url: '/pages/profile/hisWorks?userId=1&nickname=用户' });
|
||||
// };
|
||||
const onBannerTap = () => {
|
||||
uni.navigateTo({ url: '/pages/rank/rank' });
|
||||
};
|
||||
|
||||
onMounted(loadTop3);
|
||||
defineExpose({ reload: loadTop3 });
|
||||
|
||||
@ -55,11 +55,11 @@
|
||||
>
|
||||
<image
|
||||
class="visit-icon"
|
||||
src="/static/square/dianjibaifang.png"
|
||||
src="/static/icon/visit-house.png"
|
||||
mode="aspectFit"
|
||||
lazy-load
|
||||
></image>
|
||||
<text class="visit-text">点击拜访</text>
|
||||
<text class="visit-text">拜访小屋</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
@ -71,8 +71,8 @@
|
||||
class="menu-item"
|
||||
@tap="handleMenuVisit"
|
||||
>
|
||||
<image class="menu-icon" src="/static/square/dianjibaifang.png" mode="aspectFit" lazy-load></image>
|
||||
<text class="menu-text">点击拜访</text>
|
||||
<image class="menu-icon" src="/static/icon/visit-house.png" mode="aspectFit" lazy-load></image>
|
||||
<text class="menu-text">拜访小屋</text>
|
||||
</view>
|
||||
<view class="menu-item" @tap="handleMenuViewProfile">
|
||||
<image class="menu-icon" src="/static/icon/character.png" mode="aspectFit" lazy-load></image>
|
||||
@ -207,14 +207,14 @@ const handleArtworkError = (e) => {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 24rpx;
|
||||
margin-bottom: 32rpx;
|
||||
gap: 20rpx;
|
||||
position:relative;
|
||||
}
|
||||
|
||||
.rank-decoration {
|
||||
position: absolute;
|
||||
bottom: -8rpx;
|
||||
bottom: -24rpx;
|
||||
left: 32rpx;
|
||||
width: 92%;
|
||||
height: 8rpx;
|
||||
@ -225,14 +225,14 @@ const handleArtworkError = (e) => {
|
||||
|
||||
/* 排名编号 */
|
||||
.rank-number {
|
||||
min-width: 64rpx;
|
||||
min-width: 48rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 8rpx;
|
||||
}
|
||||
|
||||
.rank-text {
|
||||
font-size: 32rpx;
|
||||
font-size: 48rpx;
|
||||
font-weight: bold;
|
||||
color: #FFFFFF;
|
||||
text-shadow:
|
||||
@ -269,8 +269,8 @@ const handleArtworkError = (e) => {
|
||||
|
||||
/* 作品图片 */
|
||||
.artwork-image {
|
||||
width: 80rpx;
|
||||
height: 104rpx;
|
||||
width: 96rpx;
|
||||
height: 120rpx;
|
||||
border-radius: 16rpx;
|
||||
border: 3rpx solid rgba(255, 255, 255, 0.6);
|
||||
/* 优化:2层阴影简化为1层 */
|
||||
@ -359,7 +359,6 @@ const handleArtworkError = (e) => {
|
||||
}
|
||||
|
||||
.popularity-container {
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 20rpx;
|
||||
@ -374,16 +373,12 @@ const handleArtworkError = (e) => {
|
||||
}
|
||||
|
||||
.fire-icon {
|
||||
width: 64rpx;
|
||||
height: 72rpx;
|
||||
position: absolute;
|
||||
left: -32rpx;
|
||||
top: -32rpx;
|
||||
width: 32rpx;
|
||||
height: 40rpx;
|
||||
}
|
||||
|
||||
.popularity-score {
|
||||
font-size: 24rpx;
|
||||
padding: 0 16rpx 0 32rpx;
|
||||
color: #FFFFFF;
|
||||
text-shadow:
|
||||
0 2rpx 4rpx rgba(0, 0, 0, 0.4),
|
||||
@ -406,8 +401,7 @@ const handleArtworkError = (e) => {
|
||||
.visit-icon {
|
||||
width: 80rpx;
|
||||
height: 80rpx;
|
||||
margin-bottom: 8rpx;
|
||||
/* transform: scale(1.2); */
|
||||
transform: scale(1.2);
|
||||
}
|
||||
.visit-text{
|
||||
color: #FFFFFF;
|
||||
|
||||
@ -59,7 +59,7 @@
|
||||
<TOP3Card v-for="user in top3Users" :key="user.userId" :ref="user.userId" :rank="user.rank"
|
||||
:avatar="user.avatar" :nickname="user.nickname" :popularityScore="user.popularityScore"
|
||||
:artworkImage="user.artworkImage" :userId="user.userId"
|
||||
:isCurrentUser="isCurrentUser(user.userId)" @visit="handleVisit(user.userId, user.nickname)"
|
||||
:isCurrentUser="isCurrentUser(user.userId)" @visit="handleVisit(user.userId)"
|
||||
@view-profile="handleViewProfile" @avatar-click="() => { }" />
|
||||
</view>
|
||||
|
||||
@ -76,7 +76,7 @@
|
||||
:userId="item.userId" :avatar="item.avatar" :nickname="item.nickname"
|
||||
:popularityScore="item.popularityScore" :artworkImage="item.artworkImage"
|
||||
:artworkId="item.artworkId" :showVisitButton="!isCurrentUser(item.userId)"
|
||||
:isCurrentUser="isCurrentUser(item.userId)" @visit="handleVisit(item.userId, item.nickname)"
|
||||
:isCurrentUser="isCurrentUser(item.userId)" @visit="handleVisit(item.userId)"
|
||||
@view-profile="handleViewProfile" @artwork-click="handleArtworkClick" />
|
||||
</view>
|
||||
|
||||
@ -970,8 +970,8 @@ const getCurrentTabInfo = () => {
|
||||
};
|
||||
|
||||
// 处理拜访按钮点击
|
||||
const handleVisit = (userId, nickname) => {
|
||||
emit('visit', { userId, nickname });
|
||||
const handleVisit = (userId) => {
|
||||
emit('visit', userId);
|
||||
};
|
||||
|
||||
// 处理查看个人信息
|
||||
@ -1295,12 +1295,15 @@ const handleTouchEnd = (e) => {
|
||||
|
||||
.modal-container {
|
||||
position: absolute;
|
||||
width: calc(100% - 16rpx);
|
||||
width: 100%;
|
||||
height: calc(100% - 224rpx);
|
||||
bottom: 32rpx;
|
||||
border-radius: 48rpx;
|
||||
overflow: hidden;
|
||||
z-index: 10;
|
||||
/* 优化:3层阴影简化为1层,提升渲染性能 */
|
||||
box-shadow: 0 16rpx 48rpx rgba(0, 0, 0, 0.35);
|
||||
border: 2rpx solid rgba(255, 255, 255, 0.2);
|
||||
/* 添加过渡动画,使下拉关闭更流畅 */
|
||||
transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
}
|
||||
@ -1316,10 +1319,9 @@ const handleTouchEnd = (e) => {
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
/* width: 100%;
|
||||
height: 100%; */
|
||||
background-image: url('/static/rank/paihangbang.png');
|
||||
background-size: 100% 100%;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-image: url('/static/rank/rank-bg.png');
|
||||
background-repeat: no-repeat;
|
||||
background-position: center;
|
||||
z-index: 0;
|
||||
@ -1354,7 +1356,6 @@ const handleTouchEnd = (e) => {
|
||||
margin-bottom: 40rpx;
|
||||
padding: 0 15rpx;
|
||||
position: relative;
|
||||
top: 16rpx;
|
||||
}
|
||||
|
||||
.nav-arrow {
|
||||
@ -1404,7 +1405,7 @@ const handleTouchEnd = (e) => {
|
||||
|
||||
.ranking-title-image.loaded {
|
||||
opacity: 1;
|
||||
transform: scale(2.3);
|
||||
transform: scale(2.5);
|
||||
}
|
||||
|
||||
|
||||
@ -1624,7 +1625,7 @@ const handleTouchEnd = (e) => {
|
||||
justify-content: space-between;
|
||||
gap: 60rpx;
|
||||
margin-bottom: 84rpx;
|
||||
padding: 0 48rpx;
|
||||
padding: 0 15rpx;
|
||||
}
|
||||
|
||||
/* 空数据提示 */
|
||||
@ -1651,7 +1652,7 @@ const handleTouchEnd = (e) => {
|
||||
/* 排名列表区域 */
|
||||
.ranking-list-section {
|
||||
margin-top: 20rpx;
|
||||
padding: 0 48rpx;
|
||||
padding: 0 15rpx;
|
||||
}
|
||||
|
||||
/* 加载更多容器 */
|
||||
@ -1701,9 +1702,9 @@ const handleTouchEnd = (e) => {
|
||||
/* 当前用户栏 - 固定在底部 */
|
||||
.current-user-bar {
|
||||
position: absolute;
|
||||
bottom: 152rpx;
|
||||
left: 84rpx;
|
||||
right: 84rpx;
|
||||
bottom: 148rpx;
|
||||
left: 20rpx;
|
||||
right: 20rpx;
|
||||
padding: 24rpx;
|
||||
/* 优化:5色渐变简化为2色,提升性能 */
|
||||
background: linear-gradient(135deg, rgba(255, 107, 157, 0.9) 0%, rgba(255, 177, 153, 0.9) 100%);
|
||||
@ -1732,12 +1733,11 @@ const handleTouchEnd = (e) => {
|
||||
/* gap: 34rpx; */
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
height: 64rpx;
|
||||
}
|
||||
|
||||
.current-user-avatar {
|
||||
width: 80rpx;
|
||||
height: 80rpx;
|
||||
width: 88rpx;
|
||||
height: 88rpx;
|
||||
border-radius: 50%;
|
||||
border: 4rpx solid rgba(255, 255, 255, 0.9);
|
||||
box-shadow:
|
||||
@ -1746,7 +1746,7 @@ const handleTouchEnd = (e) => {
|
||||
}
|
||||
|
||||
.current-user-avatar.no-artwork {
|
||||
width: 56rpx;
|
||||
width: 64rpx;
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
@ -2103,7 +2103,7 @@ const handleTouchEnd = (e) => {
|
||||
|
||||
.nav-arrow {
|
||||
min-width: 88rpx;
|
||||
transform: scale(1.7)
|
||||
transform: scale(2)
|
||||
}
|
||||
|
||||
.tab-item {
|
||||
|
||||
@ -1,12 +1,12 @@
|
||||
<template>
|
||||
<view class="starbook-content">
|
||||
<!-- 背景图片 -->
|
||||
<image class="background-image" src="/static/starbookcontent/beijing.png" mode="aspectFill"></image>
|
||||
<image class="background-image" src="/static/background/starbook.jpg" mode="aspectFill"></image>
|
||||
|
||||
<!-- 内容区域 -->
|
||||
<view class="content-wrapper">
|
||||
<!-- 类型Tab - 固定定位 -->
|
||||
<!-- <view class="type-tabs">
|
||||
<view class="type-tabs">
|
||||
<view
|
||||
class="tab-item"
|
||||
:class="{ active: currentType === 'regular' }"
|
||||
@ -28,7 +28,7 @@
|
||||
>
|
||||
<text>活动</text>
|
||||
</view>
|
||||
</view> -->
|
||||
</view>
|
||||
|
||||
<!-- 加载中 -->
|
||||
<view v-if="loading" class="loading-container">
|
||||
@ -53,11 +53,6 @@
|
||||
<!-- 该 category 下的所有 grades -->
|
||||
<view v-for="gradeItem in group.grades" :key="gradeItem.grade" class="grade-section">
|
||||
<view class="group-header">
|
||||
<image
|
||||
class="group-header-bg"
|
||||
:src="getGradeBackground(gradeItem.grade)"
|
||||
mode="aspectFill"
|
||||
></image>
|
||||
<text class="group-title">{{ formatGrade(gradeItem.grade) }}</text>
|
||||
</view>
|
||||
<scroll-view class="nft-row" scroll-x :show-scrollbar="false" :enable-flex="true">
|
||||
@ -78,9 +73,8 @@
|
||||
<view v-if="item.display_status === 1" class="status-overlay">
|
||||
<text class="status-text-center">已展示</text>
|
||||
</view>
|
||||
<view class="card-rate-badge-overlay">
|
||||
<image class="heart-icon" src="/static/icon/heart-icon.png" mode="aspectFit"></image>
|
||||
<text class="card-rate-text">{{ item.like_count || 0 }}</text>
|
||||
<view class="nft-info">
|
||||
<text class="nft-name">{{ item.name }}</text>
|
||||
</view>
|
||||
</view>
|
||||
<!-- 更多按钮 -->
|
||||
@ -219,20 +213,10 @@ const cardSize = computed(() => {
|
||||
return Math.floor(availableWidth / 2.5);
|
||||
});
|
||||
|
||||
// grade 转换
|
||||
// grade 中文转换
|
||||
const gradeMap = { 1: '一', 2: '二', 3: '三', 4: '四', 5: '五' };
|
||||
function formatGrade(grade) {
|
||||
return `V${grade}`;
|
||||
}
|
||||
|
||||
// 获取等级背景图
|
||||
function getGradeBackground(grade) {
|
||||
if (grade <= 2) {
|
||||
return '/static/starbookcontent/V1dengji.png';
|
||||
} else if (grade <= 4) {
|
||||
return '/static/starbookcontent/V2dengji.png';
|
||||
} else {
|
||||
return '/static/starbookcontent/V3dengji.png';
|
||||
}
|
||||
return `等级${gradeMap[grade] || grade}`;
|
||||
}
|
||||
|
||||
// 判断是否有数据
|
||||
@ -504,38 +488,21 @@ watch(() => props.isActive, (newVal) => {
|
||||
|
||||
/* 等级区块 */
|
||||
.grade-section {
|
||||
background: #f0839960;
|
||||
background: rgba(255, 255, 255, 0.03);
|
||||
border-radius: 16rpx;
|
||||
padding: 20rpx;
|
||||
}
|
||||
|
||||
/* 分组标题 */
|
||||
.group-header {
|
||||
position: relative;
|
||||
margin-bottom: 16rpx;
|
||||
padding: 16rpx 24rpx;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 160rpx;
|
||||
height: 32rpx;
|
||||
}
|
||||
|
||||
.group-header-bg {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 160rpx;
|
||||
height: 64rpx;
|
||||
z-index: 0;
|
||||
padding-bottom: 10rpx;
|
||||
border-bottom: 1rpx solid rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
|
||||
.group-title {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
font-size: 24rpx;
|
||||
font-size: 26rpx;
|
||||
color: rgba(255, 255, 255, 0.8);
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
/* 藏品行 - 水平滚动 */
|
||||
@ -543,14 +510,13 @@ watch(() => props.isActive, (newVal) => {
|
||||
width: 100%;
|
||||
height: 288rpx;
|
||||
white-space: nowrap;
|
||||
padding: 0.5rem;
|
||||
}
|
||||
|
||||
/* 藏品行内容容器 */
|
||||
.nft-row-content {
|
||||
display: inline-block;
|
||||
white-space: nowrap;
|
||||
/* padding-left: 24rpx; */
|
||||
padding-left: 24rpx;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
@ -575,7 +541,7 @@ watch(() => props.isActive, (newVal) => {
|
||||
/* NFT 图片 */
|
||||
.nft-image {
|
||||
width: 192rpx;
|
||||
height: 100%;
|
||||
height: 224rpx;
|
||||
border-radius: 16rpx;
|
||||
/* background: rgba(255, 255, 255, 0.05); */
|
||||
display: block;
|
||||
@ -583,7 +549,7 @@ watch(() => props.isActive, (newVal) => {
|
||||
|
||||
/* 已展示的图片 - 灰色滤镜 */
|
||||
.nft-image-displayed {
|
||||
filter: grayscale(25%);
|
||||
filter: grayscale(23%);
|
||||
}
|
||||
|
||||
/* 更多占位符 */
|
||||
@ -607,7 +573,7 @@ watch(() => props.isActive, (newVal) => {
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 192rpx;
|
||||
height: 100%;
|
||||
height: 224rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
@ -642,41 +608,6 @@ watch(() => props.isActive, (newVal) => {
|
||||
padding: 16rpx;
|
||||
}
|
||||
|
||||
/* 点赞数徽章 - 图片上覆盖层 */
|
||||
.card-rate-badge-overlay {
|
||||
position: absolute;
|
||||
bottom: 12rpx;
|
||||
left: 12rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
background: linear-gradient(to bottom right,
|
||||
#F0E4B1 0%,
|
||||
#F08399 50%,
|
||||
#B94E73 100%);
|
||||
border-radius: 999rpx;
|
||||
padding: 8rpx 20rpx 8rpx 40rpx;
|
||||
box-shadow:
|
||||
0 4rpx 12rpx rgba(255, 143, 158, 0.2),
|
||||
inset 0 2rpx 4rpx rgba(255, 255, 255, 0.4);
|
||||
|
||||
/* background: rgba(0, 0, 0, 0.5); */
|
||||
border-radius: 20rpx;
|
||||
padding: 6rpx 12rpx;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.card-rate-badge-overlay .heart-icon {
|
||||
width: 24rpx;
|
||||
height: 24rpx;
|
||||
margin-right: 6rpx;
|
||||
}
|
||||
|
||||
.card-rate-badge-overlay .card-rate-text {
|
||||
font-size: 22rpx;
|
||||
color: #fff;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.nft-name {
|
||||
display: block;
|
||||
font-size: 22rpx;
|
||||
@ -698,7 +629,7 @@ watch(() => props.isActive, (newVal) => {
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%); */
|
||||
width: 192rpx;
|
||||
height: 100%;
|
||||
height: 224rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
@ -97,8 +97,8 @@
|
||||
class="menu-item"
|
||||
@tap="handleMenuVisit"
|
||||
>
|
||||
<image class="menu-icon" src="/static/square/dianjibaifang.png" mode="aspectFit" lazy-load></image>
|
||||
<text class="menu-text">点击拜访</text>
|
||||
<image class="menu-icon" src="/static/icon/visit-house.png" mode="aspectFit" lazy-load></image>
|
||||
<text class="menu-text">拜访小屋</text>
|
||||
</view>
|
||||
<view class="menu-item" @tap="handleMenuViewProfile">
|
||||
<image class="menu-icon" src="/static/icon/character.png" mode="aspectFit" lazy-load></image>
|
||||
@ -426,8 +426,8 @@
|
||||
}
|
||||
|
||||
.user-nickname {
|
||||
font-size: 12rpx;
|
||||
margin-left: 10rpx;
|
||||
font-size: 14rpx;
|
||||
margin-left: 12rpx;
|
||||
color: #FFFFFF;
|
||||
text-align: center;
|
||||
max-width: 100%;
|
||||
|
||||
@ -11,9 +11,6 @@
|
||||
<text class="gallery-owner-title-text">
|
||||
{{ isViewingOthers ? (galleryOwnerNickname ? galleryOwnerNickname + '的展馆' : 'TA的展馆') : '我的展馆' }}
|
||||
</text>
|
||||
<view v-if="isViewingOthers" class="view-works-btn" @tap="goToHisWorks">
|
||||
<text class="view-works-btn-text">查看TA的作品</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 展览板容器 -->
|
||||
@ -811,15 +808,7 @@ export default {
|
||||
url: '/pages/castlove/mall'
|
||||
});
|
||||
};
|
||||
|
||||
// 跳转到查看TA的作品页面
|
||||
const goToHisWorks = () => {
|
||||
if (!galleryOwnerId.value || !galleryOwnerNickname.value) return;
|
||||
uni.navigateTo({
|
||||
url: `/pages/profile/hisWorks?userId=${galleryOwnerId.value}&nickname=${encodeURIComponent(galleryOwnerNickname.value)}`
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
// 处理底部按钮点击
|
||||
const handleBottomButtonClick = async () => {
|
||||
if (isMyGallery.value) {
|
||||
@ -1655,10 +1644,7 @@ export default {
|
||||
width: 100%;
|
||||
z-index: 99;
|
||||
text-align: center;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
gap: 16rpx;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.gallery-owner-title-text {
|
||||
@ -1669,20 +1655,6 @@ export default {
|
||||
letter-spacing: 4rpx;
|
||||
}
|
||||
|
||||
.view-works-btn {
|
||||
pointer-events: auto;
|
||||
background: linear-gradient(135deg, #F0E4B1 0%, #F08399 50%, #B94E73 100%);
|
||||
border-radius: 24rpx;
|
||||
padding: 12rpx 28rpx;
|
||||
box-shadow: 0 4rpx 12rpx rgba(185, 78, 115, 0.4);
|
||||
}
|
||||
|
||||
.view-works-btn-text {
|
||||
font-size: 24rpx;
|
||||
color: #fff;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
/* 展览板容器 */
|
||||
.exhibition-boards {
|
||||
position: relative;
|
||||
|
||||
@ -1,631 +0,0 @@
|
||||
<template>
|
||||
<view class="page-container">
|
||||
<!-- 背景图片 -->
|
||||
<image class="bg-image" src="/static/square/beijingban.png" mode="aspectFill"></image>
|
||||
|
||||
<!-- 顶部导航 -->
|
||||
<view class="nav-bar">
|
||||
<view class="nav-back" @tap="goBack">
|
||||
<image class="nav-back-icon" src="/static/icon/back.png" mode="aspectFit"></image>
|
||||
</view>
|
||||
<text class="nav-title">{{ nickname }}的作品</text>
|
||||
<view class="nav-placeholder"></view>
|
||||
</view>
|
||||
|
||||
<view class="scroll-content">
|
||||
|
||||
<!-- 他人的在展作品 -->
|
||||
<view class="section-block section-1">
|
||||
<view class="section-label section-label-1">
|
||||
<image class="section-label-bg" src="/static/nft/dingbutubiao_liang.png" mode="aspectFill"></image>
|
||||
<text class="section-label-text">当前在展作品</text>
|
||||
</view>
|
||||
|
||||
<view class="exhibition-grid">
|
||||
<view v-for="(item, index) in exhibitionWorks" :key="item.id" class="exhibition-card"
|
||||
:class="index % 2 === 0 ? 'card-tilt-left' : 'card-tilt-right'"
|
||||
@tap="goToAssetDetail(item.id)">
|
||||
<image class="card-image" :src="item.cover_url || '/static/nft/placeholder.png'"
|
||||
mode="aspectFill"></image>
|
||||
<image class="card-frame" src="/static/square/gerenzhongxincangpinkuang.png" mode="aspectFill">
|
||||
</image>
|
||||
<!-- 点赞数 -->
|
||||
<view class="card-rate-badge">
|
||||
<image class="heart-icon" src="/static/icon/heart-icon.png" mode="aspectFit"></image>
|
||||
<view class="card-rate-text-wrap">
|
||||
<text class="card-rate-text">{{ item.like_count || 0 }}</text>
|
||||
</view>
|
||||
</view>
|
||||
<!-- 图片下方收益 -->
|
||||
<view class="card-income-row"
|
||||
:class="index % 2 === 0 ? 'income-tilt-right' : 'income-tilt-left'">
|
||||
<image class="topfans-icon" src="/static/icon/crystal.png" mode="aspectFit"></image>
|
||||
<view class="card-income-text-wrap">
|
||||
<text class="card-income-text">{{ item.earnings || 0 }}/时</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 空状态占位 -->
|
||||
<view v-if="exhibitionWorks.length === 0" class="empty-exhibition">
|
||||
<text class="empty-text">该用户暂无在展作品</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 他人的点赞作品 -->
|
||||
<view class="section-block">
|
||||
<view class="liked-tabs">
|
||||
<view class="section-label" :class="{ 'tab-active': likedTab === 'current' }"
|
||||
@tap="switchLikedTab('current')">
|
||||
<image class="section-label-bg" src="/static/nft/dingbutubiao_liang.png" mode="aspectFill">
|
||||
</image>
|
||||
<text class="section-label-text">当前点赞作品</text>
|
||||
</view>
|
||||
<!-- <view class="section-label" :class="{ 'tab-active': likedTab === 'today' }"
|
||||
@tap="switchLikedTab('today')">
|
||||
<image class="section-label-bg" src="/static/nft/dingbutubiao_liang.png" mode="aspectFill">
|
||||
</image>
|
||||
<text class="section-label-text">今日点赞作品</text>
|
||||
</view>
|
||||
<view class="section-label" :class="{ 'tab-active': likedTab === 'week' }"
|
||||
@tap="switchLikedTab('week')">
|
||||
<image class="section-label-bg" src="/static/nft/dingbutubiao_liang.png" mode="aspectFill">
|
||||
</image>
|
||||
<text class="section-label-text">本周点赞作品</text>
|
||||
</view> -->
|
||||
</view>
|
||||
|
||||
<scroll-view class="liked-list" scroll-y="true" :show-scrollbar="false">
|
||||
<view v-for="(item, index) in likedWorks" :key="item.id" class="liked-row"
|
||||
@tap="goToAssetDetail(item.id)">
|
||||
<!-- 卡片主体 -->
|
||||
<view class="liked-item" :class="index === 0 ? 'liked-item-first' : ''">
|
||||
<!-- 排名图标 -->
|
||||
<image v-if="index < 3" :src="rankIcons[index]" :class="'rank-icon rank-icon-' + (index + 1)" mode="aspectFit"></image>
|
||||
<!-- 作品封面 -->
|
||||
<view class="liked-cover-wrap" :class="index === 0 ? 'liked-cover-wrap-first' : ''">
|
||||
<image class="liked-cover" :src="item.cover_url || '/static/nft/placeholder.png'"
|
||||
mode="aspectFill"></image>
|
||||
<image class="liked-cover-frame" src="/static/square/cangpinkuang1.png"
|
||||
mode="aspectFill"></image>
|
||||
</view>
|
||||
|
||||
<!-- 作品信息 -->
|
||||
<view class="liked-info">
|
||||
<text class="liked-status">{{ item.status_text }}</text>
|
||||
<view class="liked-score-row">
|
||||
<text class="liked-score">{{ formatScore(item.score) }}</text>
|
||||
<image class="fire-icon" src="/static/square/rementubiao.png" mode="aspectFit">
|
||||
</image>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 右侧奖励 -->
|
||||
<view class="liked-reward">
|
||||
<image class="reward-token-icon" :src="item.earnings > 10 ? '/static/square/shuijingtubiao.png' : '/static/icon/crystal.png'" mode="aspectFit">
|
||||
</image>
|
||||
<text class="reward-amount">+{{ item.reward }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 空状态 -->
|
||||
<view v-if="likedWorks.length === 0" class="empty-liked">
|
||||
<text class="empty-text">当前暂无点赞作品</text>
|
||||
</view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, onMounted } from 'vue';
|
||||
import { onLoad } from '@dcloudio/uni-app';
|
||||
import { getUserExhibitedAssetsApi, getUserLikedAssetsApi, getUserProfileApi } from '@/utils/api.js';
|
||||
|
||||
const userId = ref('');
|
||||
const nickname = ref('');
|
||||
|
||||
onLoad((options) => {
|
||||
if (options.userId) userId.value = options.userId;
|
||||
if (options.nickname) nickname.value = decodeURIComponent(options.nickname);
|
||||
});
|
||||
|
||||
const goBack = () => {
|
||||
const pages = getCurrentPages();
|
||||
if (pages.length > 1) {
|
||||
uni.navigateBack();
|
||||
} else {
|
||||
uni.reLaunch({
|
||||
url: '/pages/square/square'
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const goToAssetDetail = (id) => {
|
||||
if (!id) return;
|
||||
uni.navigateTo({ url: `/pages/asset-detail/asset-detail?asset_id=${id}` });
|
||||
};
|
||||
|
||||
const formatScore = (score) => {
|
||||
if (!score && score !== 0) return '0';
|
||||
return Number(score).toLocaleString();
|
||||
};
|
||||
|
||||
const rankIcons = [
|
||||
'/static/rank/rank-icon1.png',
|
||||
'/static/rank/rank-icon2.png',
|
||||
'/static/rank/rank-icon3.png',
|
||||
];
|
||||
|
||||
// 在展作品列表
|
||||
const exhibitionWorks = ref([]);
|
||||
|
||||
// 点赞作品列表
|
||||
const likedWorks = ref([]);
|
||||
|
||||
// 点赞标签状态: current-当前, today-今日, week-本周
|
||||
const likedTab = ref('current');
|
||||
|
||||
// 切换点赞标签
|
||||
const switchLikedTab = async (tab) => {
|
||||
if (likedTab.value === tab) return;
|
||||
likedTab.value = tab;
|
||||
likedWorks.value = [];
|
||||
await loadLikedAssets();
|
||||
};
|
||||
|
||||
// 加载他人的展出作品
|
||||
const loadExhibitedAssets = async () => {
|
||||
if (!userId.value) return;
|
||||
try {
|
||||
const res = await getUserExhibitedAssetsApi(userId.value, 1, 20);
|
||||
if (res.data && res.data.items) {
|
||||
exhibitionWorks.value = res.data.items.map(item => ({
|
||||
id: item.asset_id,
|
||||
cover_url: item.cover_url,
|
||||
like_count: item.like_count,
|
||||
earnings: item.earnings,
|
||||
name: item.name,
|
||||
}));
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('加载展出作品失败:', err);
|
||||
}
|
||||
};
|
||||
|
||||
// 加载他人的点赞作品
|
||||
const loadLikedAssets = async () => {
|
||||
if (!userId.value) return;
|
||||
try {
|
||||
let res;
|
||||
switch (likedTab.value) {
|
||||
case 'today':
|
||||
// 后端暂无今日/本周接口,暂时复用全部接口
|
||||
res = await getUserLikedAssetsApi(userId.value, 1, 20);
|
||||
break;
|
||||
case 'week':
|
||||
res = await getUserLikedAssetsApi(userId.value, 1, 20);
|
||||
break;
|
||||
default:
|
||||
res = await getUserLikedAssetsApi(userId.value, 1, 20);
|
||||
}
|
||||
if (res.data && res.data.items) {
|
||||
likedWorks.value = res.data.items.map((item, index) => ({
|
||||
id: item.asset_id,
|
||||
cover_url: item.cover_url,
|
||||
like_count: item.like_count,
|
||||
earnings: item.earnings,
|
||||
name: item.name,
|
||||
status_text: index < 3 ? '排名进榜' : '潜力待挖',
|
||||
score: item.like_count,
|
||||
reward: Math.floor(item.earnings || 0),
|
||||
}));
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('加载点赞作品失败:', err);
|
||||
}
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
loadExhibitedAssets();
|
||||
loadLikedAssets();
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.page-container {
|
||||
min-height: 100vh;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.bg-image {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 120%;
|
||||
z-index: 0;
|
||||
}
|
||||
|
||||
.nav-bar {
|
||||
position: relative;
|
||||
z-index: 10;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 80rpx 32rpx 16rpx;
|
||||
}
|
||||
|
||||
.nav-back {
|
||||
width: 80rpx;
|
||||
height: 80rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.nav-back-icon {
|
||||
width: 80rpx;
|
||||
height: 80rpx;
|
||||
}
|
||||
|
||||
.nav-title {
|
||||
font-size: 48rpx;
|
||||
font-weight: 700;
|
||||
color: #fff;
|
||||
text-shadow: 0 2rpx 4rpx rgba(0, 0, 0, 0.9);
|
||||
letter-spacing: 2rpx;
|
||||
}
|
||||
|
||||
.nav-placeholder {
|
||||
width: 80rpx;
|
||||
}
|
||||
|
||||
.scroll-content {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.section-block {
|
||||
/* background: rgb(249 159 192 / 45%);
|
||||
border-radius: 48rpx; */
|
||||
padding: 16rpx;
|
||||
}
|
||||
|
||||
.section-label {
|
||||
position: relative;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 80rpx;
|
||||
min-width: 180rpx;
|
||||
opacity: 0.6;
|
||||
transition: opacity 0.2s;
|
||||
}
|
||||
|
||||
.section-label.section-label-1 {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.section-label.tab-active {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.liked-tabs {
|
||||
display: flex;
|
||||
gap: 16rpx;
|
||||
margin-bottom: 16rpx;
|
||||
}
|
||||
|
||||
.section-label-bg {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.section-label-text {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
font-size: 26rpx;
|
||||
color: #fff;
|
||||
text-shadow: 0 2rpx 4rpx rgba(0, 0, 0, 0.9);
|
||||
font-weight: 600;
|
||||
padding: 0 28rpx;
|
||||
}
|
||||
|
||||
.exhibition-grid {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
padding: 10rpx 10rpx 80rpx;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.exhibition-card {
|
||||
width: 248rpx;
|
||||
height: 380rpx;
|
||||
border-radius: 20rpx;
|
||||
overflow: visible;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.card-tilt-left {
|
||||
transform: rotate(-4deg) translateY(10rpx);
|
||||
margin-right: 32rpx;
|
||||
}
|
||||
|
||||
.card-tilt-right {
|
||||
transform: rotate(4deg) translateY(10rpx);
|
||||
}
|
||||
|
||||
.card-income-row.income-tilt-right {
|
||||
transform: translateX(-50%) rotate(4deg);
|
||||
}
|
||||
|
||||
.card-income-row.income-tilt-left {
|
||||
transform: translateX(-50%) rotate(-4deg);
|
||||
}
|
||||
|
||||
.card-image {
|
||||
width: 88%;
|
||||
height: 92%;
|
||||
border-radius: 80rpx;
|
||||
transform-origin: center center;
|
||||
position: relative;
|
||||
z-index: 3;
|
||||
padding: 16rpx;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.card-frame {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.card-rate-badge {
|
||||
position: absolute;
|
||||
bottom: 16rpx;
|
||||
left: 40%;
|
||||
transform: translateX(-50%);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 6rpx;
|
||||
padding: 6rpx 16rpx;
|
||||
z-index: 9;
|
||||
}
|
||||
|
||||
.card-income-row {
|
||||
position: absolute;
|
||||
bottom: -52rpx;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
white-space: nowrap;
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
.topfans-icon {
|
||||
width: 52rpx;
|
||||
height: 52rpx;
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
margin-right: -16rpx;
|
||||
left: 20rpx;
|
||||
top: 8rpx;
|
||||
}
|
||||
|
||||
.card-income-text-wrap {
|
||||
width: 64rpx;
|
||||
background: linear-gradient(to bottom right,
|
||||
#F0E4B1 0%,
|
||||
#F08399 50%,
|
||||
#B94E73 100%);
|
||||
border-radius: 999rpx;
|
||||
padding: 8rpx 20rpx 8rpx 40rpx;
|
||||
box-shadow: 0 4rpx 12rpx rgba(255, 143, 158, 0.2),
|
||||
inset 0 2rpx 4rpx rgba(255, 255, 255, 0.4);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.card-income-text {
|
||||
font-size: 16rpx;
|
||||
color: #fff;
|
||||
font-weight: 700;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.heart-icon {
|
||||
width: 28rpx;
|
||||
height: 28rpx;
|
||||
}
|
||||
|
||||
.card-rate-text-wrap {
|
||||
background: linear-gradient(to bottom right,
|
||||
#F0E4B1 0%,
|
||||
#F08399 50%,
|
||||
#B94E73 100%);
|
||||
border-radius: 999rpx;
|
||||
padding: 2rpx 16rpx;
|
||||
box-shadow: 0 4rpx 12rpx rgba(255, 143, 158, 0.2),
|
||||
inset 0 2rpx 4rpx rgba(255, 255, 255, 0.4);
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.card-rate-text {
|
||||
font-size: 22rpx;
|
||||
color: #fff;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.empty-exhibition {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 80rpx 0;
|
||||
}
|
||||
|
||||
.empty-text {
|
||||
font-size: 28rpx;
|
||||
color: #b09cc0;
|
||||
}
|
||||
|
||||
.liked-list {
|
||||
max-height: 732rpx;
|
||||
}
|
||||
|
||||
.liked-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
margin-bottom: 16rpx;
|
||||
}
|
||||
|
||||
.liked-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
background: #ffffff50;
|
||||
border-radius: 32rpx;
|
||||
padding: 16rpx 20rpx;
|
||||
gap: 16rpx;
|
||||
overflow: hidden;
|
||||
box-sizing: border-box;
|
||||
width: 80%;
|
||||
padding-left: 10%;
|
||||
}
|
||||
|
||||
.liked-item-first {
|
||||
padding: 28rpx 20rpx;
|
||||
width: 90%;
|
||||
padding-left: 20%;
|
||||
}
|
||||
|
||||
/* 排名图标 - 排名越靠前越大 */
|
||||
.rank-icon {
|
||||
flex-shrink: 0;
|
||||
/* margin-right: 8rpx; */
|
||||
position: relative;
|
||||
left: 32rpx;
|
||||
}
|
||||
|
||||
.rank-icon-1 {
|
||||
width: 72rpx;
|
||||
height: 88rpx;
|
||||
}
|
||||
|
||||
.rank-icon-2 {
|
||||
width: 64rpx;
|
||||
height: 78rpx;
|
||||
}
|
||||
|
||||
.rank-icon-3 {
|
||||
width: 56rpx;
|
||||
height: 68rpx;
|
||||
}
|
||||
|
||||
.liked-cover-wrap {
|
||||
width: 88rpx;
|
||||
height: 88rpx;
|
||||
flex-shrink: 0;
|
||||
margin-left: -18rpx;
|
||||
margin-right: 48rpx;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.liked-cover {
|
||||
width: 90%;
|
||||
height: 90%;
|
||||
border-radius: 24rpx;
|
||||
transform: rotate(-22deg);
|
||||
transform-origin: center center;
|
||||
position: relative;
|
||||
z-index: 3;
|
||||
padding: 0.25rem;
|
||||
}
|
||||
|
||||
.liked-cover-frame {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 110%;
|
||||
height: 110%;
|
||||
z-index: 2;
|
||||
transform: rotate(-22deg);
|
||||
transform-origin: center center;
|
||||
}
|
||||
|
||||
.liked-info {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.liked-status {
|
||||
font-size: 28rpx;
|
||||
color: #fff;
|
||||
text-shadow: 0 2rpx 4rpx rgba(0, 0, 0, 0.7);
|
||||
font-weight: 600;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
margin-bottom: 16rpx;
|
||||
}
|
||||
|
||||
.liked-score-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.liked-score {
|
||||
font-size: 26rpx;
|
||||
color: #fff;
|
||||
text-shadow: 0 2rpx 4rpx rgba(0, 0, 0, 0.7);
|
||||
font-weight: 700;
|
||||
margin-right: 8rpx;
|
||||
}
|
||||
|
||||
.fire-icon {
|
||||
width: 32rpx;
|
||||
height: 32rpx;
|
||||
align-self: flex-end;
|
||||
margin-top: 4rpx;
|
||||
}
|
||||
|
||||
.liked-reward {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 8rpx;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.reward-token-icon {
|
||||
width: 56rpx;
|
||||
height: 56rpx;
|
||||
}
|
||||
|
||||
.reward-amount {
|
||||
font-size: 28rpx;
|
||||
color: #c060e0;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.empty-liked {
|
||||
padding: 60rpx 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
</style>
|
||||
@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<view class="page-container">
|
||||
<!-- 背景图片 -->
|
||||
<image class="bg-image" src="/static/square/squearbj.png" mode="aspectFill"></image>
|
||||
<image class="bg-image" src="/static/square/beijingban.png" mode="aspectFill"></image>
|
||||
|
||||
<!-- 顶部导航 -->
|
||||
<view class="nav-bar">
|
||||
@ -19,7 +19,7 @@
|
||||
|
||||
<!-- 我的在展作品 -->
|
||||
<view class="section-block section-1">
|
||||
<view class="section-label section-label-1">
|
||||
<view class="section-label">
|
||||
<image class="section-label-bg" src="/static/nft/dingbutubiao_liang.png" mode="aspectFill"></image>
|
||||
<text class="section-label-text">我的在展作品</text>
|
||||
</view>
|
||||
@ -76,38 +76,21 @@
|
||||
|
||||
<!-- 当前点赞作品 -->
|
||||
<view class="section-block">
|
||||
<view class="liked-tabs">
|
||||
<view class="section-label" :class="{ 'tab-active': likedTab === 'current' }"
|
||||
@tap="switchLikedTab('current')">
|
||||
<image class="section-label-bg" src="/static/nft/dingbutubiao_liang.png" mode="aspectFill">
|
||||
</image>
|
||||
<text class="section-label-text">当前点赞作品</text>
|
||||
</view>
|
||||
<!-- <view class="section-label" :class="{ 'tab-active': likedTab === 'today' }"
|
||||
@tap="switchLikedTab('today')">
|
||||
<image class="section-label-bg" src="/static/nft/dingbutubiao_liang.png" mode="aspectFill">
|
||||
</image>
|
||||
<text class="section-label-text">今日点赞作品</text>
|
||||
</view>
|
||||
<view class="section-label" :class="{ 'tab-active': likedTab === 'week' }"
|
||||
@tap="switchLikedTab('week')">
|
||||
<image class="section-label-bg" src="/static/nft/dingbutubiao_liang.png" mode="aspectFill">
|
||||
</image>
|
||||
<text class="section-label-text">本周点赞作品</text>
|
||||
</view> -->
|
||||
<view class="section-label">
|
||||
<image class="section-label-bg" src="/static/nft/dingbutubiao_liang.png" mode="aspectFill"></image>
|
||||
<text class="section-label-text">点赞作品</text>
|
||||
</view>
|
||||
|
||||
<scroll-view class="liked-list" scroll-y="true" :show-scrollbar="false">
|
||||
<view v-for="(item, index) in likedWorks" :key="item.id" class="liked-row"
|
||||
@tap="goToAssetDetail(item.id)">
|
||||
<!-- 排名图标,绝对定位在卡片左侧 -->
|
||||
<image v-if="index < 3" :src="rankIcons[index]" :class="'rank-icon rank-icon-' + (index + 1)" mode="aspectFit"></image>
|
||||
<!-- <image v-if="index < 3" :src="rankIcons[index]" class="rank-icon-img" mode="aspectFit"></image> -->
|
||||
|
||||
<!-- 卡片主体 -->
|
||||
|
||||
<view class="liked-item" :class="index === 0 ? 'liked-item-first' : ''">
|
||||
<!-- 作品封面 -->
|
||||
<view class="liked-cover-wrap" :class="index === 0 ? 'liked-cover-wrap-first' : ''" >
|
||||
<view class="liked-cover-wrap" :class="index === 0 ? 'liked-cover-wrap-first' : ''">
|
||||
<image class="liked-cover" :src="item.cover_url || '/static/nft/placeholder.png'"
|
||||
mode="aspectFill"></image>
|
||||
<image class="liked-cover-frame" src="/static/square/cangpinkuang1.png"
|
||||
@ -126,7 +109,7 @@
|
||||
|
||||
<!-- 右侧奖励 -->
|
||||
<view class="liked-reward">
|
||||
<image class="reward-token-icon" :src="item.reward > 10 ? '/static/square/shuijingtubiao.png' : '/static/icon/crystal.png'" mode="aspectFit">
|
||||
<image class="reward-token-icon" src="/static/icon/crystal.png" mode="aspectFit">
|
||||
</image>
|
||||
<text class="reward-amount">+{{ item.reward }}</text>
|
||||
</view>
|
||||
@ -151,7 +134,7 @@
|
||||
|
||||
<script setup>
|
||||
import { ref, onMounted } from 'vue';
|
||||
import { getMyExhibitedAssetsApi, getMyLikedAssetsApi, getMyTodayLikedAssetsApi, getMyWeekLikedAssetsApi, getMyGalleriesApi, placeAssetToGalleryApi } from '@/utils/api.js';
|
||||
import { getMyExhibitedAssetsApi, getMyLikedAssetsApi, getMyGalleriesApi, placeAssetToGalleryApi } from '@/utils/api.js';
|
||||
import AssetSelector from '../components/AssetSelector.vue';
|
||||
import { onShow } from '@dcloudio/uni-app';
|
||||
import { doubleTapLike } from '@/utils/likeHelper.js';
|
||||
@ -292,9 +275,9 @@ const handleExhibitionCardTap = (item, index) => {
|
||||
};
|
||||
|
||||
const rankIcons = [
|
||||
'/static/square/icon1.png',
|
||||
'/static/square/icon2.png',
|
||||
'/static/square/icon3.png',
|
||||
'/static/rank/rank-icon1.png',
|
||||
'/static/rank/rank-icon2.png',
|
||||
'/static/rank/rank-icon3.png',
|
||||
];
|
||||
|
||||
const formatScore = (score) => {
|
||||
@ -308,35 +291,20 @@ const exhibitionWorks = ref([]);
|
||||
// 当前点赞作品列表
|
||||
const likedWorks = ref([]);
|
||||
|
||||
// 点赞标签状态: current-当前, today-今日, week-本周
|
||||
const likedTab = ref('current');
|
||||
|
||||
// 切换点赞标签
|
||||
const switchLikedTab = async (tab) => {
|
||||
if (likedTab.value === tab) return;
|
||||
likedTab.value = tab;
|
||||
likedWorks.value = [];
|
||||
await loadLikedAssets();
|
||||
};
|
||||
|
||||
// 加载我的展出作品
|
||||
const loadExhibitedAssets = async () => {
|
||||
try {
|
||||
const res = await getMyExhibitedAssetsApi(1, 20);
|
||||
if (res.data && res.data.items) {
|
||||
exhibitionWorks.value = res.data.items
|
||||
.map(item => ({
|
||||
id: item.asset_id,
|
||||
cover_url: item.cover_url,
|
||||
like_count: item.like_count,
|
||||
earnings: item.earnings,
|
||||
exhibited_at: item.exhibited_at,
|
||||
expire_at: item.expire_at,
|
||||
name: item.name,
|
||||
slot_index: item.slot_index ?? 0,
|
||||
}))
|
||||
.sort((a, b) => (a.slot_index ?? 0) - (b.slot_index ?? 0));
|
||||
console.log('展出作品:', exhibitionWorks.value);
|
||||
exhibitionWorks.value = res.data.items.map(item => ({
|
||||
id: item.asset_id,
|
||||
cover_url: item.cover_url,
|
||||
like_count: item.like_count,
|
||||
earnings: item.earnings,
|
||||
exhibited_at: item.exhibited_at,
|
||||
expire_at: item.expire_at,
|
||||
name: item.name,
|
||||
}));
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('加载展出作品失败:', err);
|
||||
@ -346,17 +314,7 @@ const loadExhibitedAssets = async () => {
|
||||
// 加载我的点赞作品
|
||||
const loadLikedAssets = async () => {
|
||||
try {
|
||||
let res;
|
||||
switch (likedTab.value) {
|
||||
case 'today':
|
||||
res = await getMyTodayLikedAssetsApi(1, 20);
|
||||
break;
|
||||
case 'week':
|
||||
res = await getMyWeekLikedAssetsApi(1, 20);
|
||||
break;
|
||||
default:
|
||||
res = await getMyLikedAssetsApi(1, 20);
|
||||
}
|
||||
const res = await getMyLikedAssetsApi(1, 20);
|
||||
if (res.data && res.data.items) {
|
||||
likedWorks.value = res.data.items.map((item, index) => ({
|
||||
id: item.asset_id,
|
||||
@ -398,7 +356,7 @@ onShow(() => {
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 120%;
|
||||
height: 100%;
|
||||
z-index: 0;
|
||||
}
|
||||
|
||||
@ -469,9 +427,9 @@ onShow(() => {
|
||||
|
||||
}
|
||||
|
||||
.section-block {
|
||||
/* background: rgb(249 159 192 / 45%);
|
||||
border-radius: 48rpx; */
|
||||
.section-block{
|
||||
background: rgb(249 159 192 / 45%);
|
||||
border-radius: 48rpx;
|
||||
padding: 16rpx;
|
||||
}
|
||||
|
||||
@ -482,34 +440,15 @@ onShow(() => {
|
||||
padding: 16rpx; */
|
||||
}
|
||||
|
||||
/* 点赞标签容器 */
|
||||
.liked-tabs {
|
||||
display: flex;
|
||||
gap: 16rpx;
|
||||
margin-bottom: 16rpx;
|
||||
}
|
||||
|
||||
/* 区块标签 */
|
||||
.section-label {
|
||||
position: relative;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-bottom: 16rpx;
|
||||
height: 80rpx;
|
||||
min-width: 180rpx;
|
||||
opacity: 0.6;
|
||||
transition: opacity 0.2s;
|
||||
|
||||
|
||||
}
|
||||
|
||||
.section-label.section-label-1 {
|
||||
opacity: 1;
|
||||
|
||||
}
|
||||
|
||||
.section-label.tab-active {
|
||||
opacity: 1;
|
||||
min-width: 232rpx;
|
||||
}
|
||||
|
||||
.section-label-bg {
|
||||
@ -550,14 +489,10 @@ onShow(() => {
|
||||
.card-tilt-left {
|
||||
transform: rotate(-4deg) translateY(10rpx);
|
||||
margin-right: 32rpx;
|
||||
border-radius: 32rpx;
|
||||
box-shadow: -16rpx 16rpx 16rpx rgba(229, 76, 93, 0.9);
|
||||
}
|
||||
|
||||
.card-tilt-right {
|
||||
transform: rotate(4deg) translateY(10rpx);
|
||||
border-radius: 32rpx;
|
||||
box-shadow: 16rpx 16rpx 16rpx rgba(229, 76, 93, 0.9);
|
||||
}
|
||||
|
||||
.card-income-row.income-tilt-right {
|
||||
@ -620,7 +555,7 @@ onShow(() => {
|
||||
/* 图片下方收益 */
|
||||
.card-income-row {
|
||||
position: absolute;
|
||||
bottom: -88rpx;
|
||||
bottom: -52rpx;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
display: flex;
|
||||
@ -678,7 +613,7 @@ onShow(() => {
|
||||
box-shadow:
|
||||
0 4rpx 12rpx rgba(255, 143, 158, 0.2),
|
||||
inset 0 2rpx 4rpx rgba(255, 255, 255, 0.4);
|
||||
display: flex;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.card-rate-text {
|
||||
@ -767,7 +702,7 @@ onShow(() => {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
background: #ffffff50;
|
||||
border-radius: 48rpx;
|
||||
border-radius: 32rpx;
|
||||
padding: 16rpx 20rpx;
|
||||
gap: 16rpx;
|
||||
overflow: hidden;
|
||||
@ -780,32 +715,14 @@ onShow(() => {
|
||||
padding: 28rpx 20rpx;
|
||||
width: 90%;
|
||||
padding-left: 20%;
|
||||
background-image: url(/static/square/diyi.png);
|
||||
background-size: 102%;
|
||||
background-position: center;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
/* 排名图标 - 排名越靠前越大 */
|
||||
.rank-icon {
|
||||
/* 排名徽章 */
|
||||
.rank-icon-img {
|
||||
width: 56rpx;
|
||||
height: 68rpx;
|
||||
flex-shrink: 0;
|
||||
position: relative;
|
||||
left: 32rpx;
|
||||
}
|
||||
|
||||
.rank-icon-1 {
|
||||
width: 96rpx;
|
||||
height: 128rpx;
|
||||
}
|
||||
|
||||
.rank-icon-2 {
|
||||
width: 72rpx;
|
||||
height: 104rpx;
|
||||
}
|
||||
|
||||
.rank-icon-3 {
|
||||
width: 64rpx;
|
||||
height: 88rpx;
|
||||
margin-right: 8rpx;
|
||||
}
|
||||
|
||||
.rank-number-badge {
|
||||
|
||||
@ -10,11 +10,7 @@
|
||||
@touchend="onTouchEnd"
|
||||
@touchcancel="onTouchEnd"
|
||||
>
|
||||
<view
|
||||
class="waterfall-inner"
|
||||
:class="{ 'ios-animate': isIOS && !iosScrollPaused }"
|
||||
:style="{ width: totalWidth + 'px', height: '100%' }"
|
||||
>
|
||||
<view class="waterfall-inner" :style="{ width: totalWidth + 'px', height: '100%' }">
|
||||
<view
|
||||
v-for="card in cards"
|
||||
:key="card.id"
|
||||
@ -82,8 +78,8 @@ const GAP = rpx2px(16)
|
||||
const BORDER_W = rpx2px(2)
|
||||
const SCALE = 0.9
|
||||
const ROWS = 4
|
||||
const AUTO_SCROLL_SPEED = 0.3
|
||||
const AUTO_RESUME_DELAY = 1500
|
||||
const AUTO_SCROLL_SPEED = 0.1
|
||||
const AUTO_RESUME_DELAY = 1000
|
||||
const PRELOAD_THRESHOLD = rpx2px(300)
|
||||
|
||||
// ========== 状态 ==========
|
||||
@ -98,7 +94,6 @@ let isComponentMounted = false // 标记组件是否已卸载
|
||||
let mockDataOffset = 0 // 模拟数据循环偏移量
|
||||
let appendFailed = false // 标记追加是否已失败
|
||||
let isInitialLoading = true // 标记是否在初始加载中
|
||||
let isIOS = false // 是否为 iOS 平台
|
||||
|
||||
// ========== RAF 兼容 ==========
|
||||
const rafFn = (cb) => {
|
||||
@ -112,104 +107,67 @@ const cafFn = (id) => {
|
||||
clearTimeout(id)
|
||||
}
|
||||
|
||||
// ========== iOS 原生自动滚动 ==========
|
||||
// iOS 使用 setInterval + scroll-left 属性实现流畅滚动
|
||||
let iosScrollTimer = null
|
||||
let iosScrollPaused = false
|
||||
let iosLastUpdateTime = 0
|
||||
let iosLastScrollValue = 0 // 上次实际设置到 scrollLeft 的值
|
||||
const IOS_SCROLL_INTERVAL = 16 // ~60fps
|
||||
const IOS_MIN_DELTA = 0.5 // 最小变化量,避免频繁更新
|
||||
|
||||
const startIOSAutoScroll = () => {
|
||||
console.log('[iOS] startIOSAutoScroll called, isIOS:', isIOS, 'isComponentMounted:', isComponentMounted)
|
||||
if (!isComponentMounted) return
|
||||
if (!isIOS) return
|
||||
stopIOSAutoScroll()
|
||||
iosScrollPaused = false
|
||||
iosLastUpdateTime = 0
|
||||
iosLastScrollValue = autoScrollPos
|
||||
|
||||
iosScrollTimer = setInterval(() => {
|
||||
if (!isComponentMounted || iosScrollPaused) return
|
||||
|
||||
const now = Date.now()
|
||||
// 节流:每 16ms 更新一次
|
||||
if (now - iosLastUpdateTime >= IOS_SCROLL_INTERVAL) {
|
||||
iosLastUpdateTime = now
|
||||
const newPos = autoScrollPos + AUTO_SCROLL_SPEED
|
||||
|
||||
// 只在变化足够大时更新,减少抖动
|
||||
if (Math.abs(newPos - iosLastScrollValue) >= IOS_MIN_DELTA) {
|
||||
autoScrollPos = newPos
|
||||
iosLastScrollValue = newPos
|
||||
scrollLeft.value = newPos
|
||||
} else {
|
||||
autoScrollPos = newPos // 保持 autoScrollPos 增长但不同步到 scrollLeft
|
||||
}
|
||||
|
||||
// 预加载
|
||||
const remainingScroll = totalWidth.value - autoScrollPos - props.screenWidth
|
||||
if (remainingScroll < Math.max(totalWidth.value / 2, props.screenWidth)) {
|
||||
if (!isLoadingMore && !appendFailed && !isInitialLoading && props.useMockData) {
|
||||
appendMore()
|
||||
}
|
||||
}
|
||||
}
|
||||
}, 16)
|
||||
}
|
||||
|
||||
const stopIOSAutoScroll = () => {
|
||||
console.log('[iOS] stopIOSAutoScroll')
|
||||
clearInterval(iosScrollTimer)
|
||||
iosScrollTimer = null
|
||||
}
|
||||
|
||||
const pauseIOSAutoScroll = () => {
|
||||
console.log('[iOS] pauseIOSAutoScroll')
|
||||
iosScrollPaused = true
|
||||
}
|
||||
|
||||
const resumeIOSAutoScroll = () => {
|
||||
console.log('[iOS] resumeIOSAutoScroll')
|
||||
iosScrollPaused = false
|
||||
iosLastUpdateTime = 0
|
||||
autoScrollPos = currentScrollLeft
|
||||
iosLastScrollValue = currentScrollLeft
|
||||
}
|
||||
// ========== 自动滚动 ==========
|
||||
let rafId = null
|
||||
let userInteracting = false
|
||||
let resumeTimer = null
|
||||
let appendTimer = null // 防抖定时器
|
||||
let autoScrollPos = 0 // 自动滚动目标位置
|
||||
let momentumTimer = null // iOS 惯性滚动检测定时器
|
||||
let scrollUpdateTimer = null // 定期同步 scrollLeft 的定时器
|
||||
let iosAutoScrollTimer = null // iOS 原生滚动定时器(检测惯性结束)
|
||||
|
||||
const startAutoScroll = () => {
|
||||
if (!isComponentMounted || isIOS) return
|
||||
if (!isComponentMounted) {
|
||||
return
|
||||
}
|
||||
// 确保没有重复的 RAF 在运行
|
||||
if (rafId) {
|
||||
cafFn(rafId)
|
||||
rafId = null
|
||||
}
|
||||
// 重置滚动状态
|
||||
userInteracting = false
|
||||
autoScrollPos = currentScrollLeft
|
||||
|
||||
// 使用定时器定期更新 scrollLeft
|
||||
clearInterval(scrollUpdateTimer)
|
||||
scrollUpdateTimer = setInterval(() => {
|
||||
if (!isComponentMounted || userInteracting || isLoadingMore) return
|
||||
autoScrollPos += AUTO_SCROLL_SPEED
|
||||
scrollLeft.value = autoScrollPos
|
||||
let lastScrollLeft = 0 // 用于检测手动滚动
|
||||
|
||||
// 预加载
|
||||
const remainingScroll = totalWidth.value - autoScrollPos - props.screenWidth
|
||||
if (remainingScroll < Math.max(totalWidth.value / 2, props.screenWidth)) {
|
||||
if (!isLoadingMore && !appendFailed && !isInitialLoading && props.useMockData) {
|
||||
appendMore()
|
||||
}
|
||||
const step = () => {
|
||||
if (!isComponentMounted) {
|
||||
rafId = null
|
||||
return
|
||||
}
|
||||
}, 16)
|
||||
// 每次 RAF 循环开始时也检查一次
|
||||
if (!isComponentMounted) {
|
||||
rafId = null
|
||||
return
|
||||
}
|
||||
|
||||
if (!userInteracting && !isLoadingMore) {
|
||||
// 检测是否被手动滚动过(如果实际滚动位置和我们的不一致,说明用户手动滚了)
|
||||
const actualScroll = scrollLeft.value
|
||||
if (Math.abs(actualScroll - lastScrollLeft) > 5) {
|
||||
// 用户手动滚了,同步位置
|
||||
currentScrollLeft = actualScroll
|
||||
} else {
|
||||
// 正常累加
|
||||
currentScrollLeft += AUTO_SCROLL_SPEED
|
||||
scrollLeft.value = currentScrollLeft
|
||||
lastScrollLeft = currentScrollLeft
|
||||
}
|
||||
|
||||
// 预加载:剩余可滚动距离小于一半屏幕宽度时,触发追加
|
||||
const remainingScroll = totalWidth.value - currentScrollLeft - props.screenWidth
|
||||
if (remainingScroll < Math.max(totalWidth.value / 2, props.screenWidth)) {
|
||||
// 直接调用 appendMore(不需要防抖)
|
||||
// 注意:真实接口模式下不应该自动追加数据,由 has_more 控制
|
||||
if (!isLoadingMore && !appendFailed && !isInitialLoading && props.useMockData) {
|
||||
appendMore()
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// 用户交互中,记录当前滚动位置
|
||||
lastScrollLeft = scrollLeft.value
|
||||
currentScrollLeft = lastScrollLeft
|
||||
}
|
||||
rafId = rafFn(step)
|
||||
}
|
||||
rafId = rafFn(step)
|
||||
}
|
||||
|
||||
const stopAutoScroll = () => {
|
||||
@ -217,44 +175,21 @@ const stopAutoScroll = () => {
|
||||
cafFn(rafId)
|
||||
rafId = null
|
||||
}
|
||||
clearInterval(scrollUpdateTimer)
|
||||
scrollUpdateTimer = null
|
||||
clearTimeout(appendTimer)
|
||||
appendTimer = null
|
||||
clearTimeout(resumeTimer)
|
||||
resumeTimer = null
|
||||
clearTimeout(momentumTimer)
|
||||
momentumTimer = null
|
||||
clearTimeout(iosAutoScrollTimer)
|
||||
iosAutoScrollTimer = null
|
||||
userInteracting = false
|
||||
isLoadingMore = false
|
||||
}
|
||||
|
||||
// 检测 Android 惯性滚动是否结束
|
||||
let lastTouchEndPos = 0 // touchend 时的位置快照
|
||||
|
||||
const detectMomentumEnd = () => {
|
||||
clearTimeout(momentumTimer)
|
||||
lastTouchEndPos = currentScrollLeft
|
||||
const tick = () => {
|
||||
momentumTimer = setTimeout(() => {
|
||||
// 比较的是 lastTouchEndPos(touchend 时的位置),不受后续惯性影响
|
||||
if (Math.abs(currentScrollLeft - lastTouchEndPos) < 3) {
|
||||
// 安卓:恢复自动滚动
|
||||
autoScrollPos = currentScrollLeft
|
||||
startAutoScroll()
|
||||
} else {
|
||||
// 惯性中,更新快照
|
||||
lastTouchEndPos = currentScrollLeft
|
||||
tick()
|
||||
}
|
||||
}, 60)
|
||||
}
|
||||
tick()
|
||||
const pauseForUser = () => {
|
||||
userInteracting = true
|
||||
clearTimeout(resumeTimer)
|
||||
resumeTimer = setTimeout(() => { userInteracting = false }, AUTO_RESUME_DELAY)
|
||||
}
|
||||
|
||||
// 防抖:延迟追加
|
||||
// 防抖:延迟 500ms 后再执行追加,避免频繁调用
|
||||
const scheduleAppend = () => {
|
||||
if (!isComponentMounted || appendFailed) return
|
||||
if (appendTimer) clearTimeout(appendTimer)
|
||||
@ -267,62 +202,16 @@ const scheduleAppend = () => {
|
||||
}
|
||||
|
||||
// ========== 触摸 / 滚动事件 ==========
|
||||
let isManualScrolling = false // 是否正在手动滚动
|
||||
|
||||
const onTouchStart = (e) => {
|
||||
if (isIOS) {
|
||||
// iOS 设备:完全停止自动滚动
|
||||
stopIOSAutoScroll()
|
||||
isManualScrolling = true
|
||||
clearTimeout(momentumTimer)
|
||||
} else {
|
||||
// 安卓设备:自动滚动停止
|
||||
userInteracting = true
|
||||
clearTimeout(momentumTimer)
|
||||
clearInterval(scrollUpdateTimer)
|
||||
}
|
||||
}
|
||||
|
||||
const onTouchEnd = () => {
|
||||
if (isIOS) {
|
||||
// iOS 设备:检测惯性滚动是否结束
|
||||
clearTimeout(momentumTimer)
|
||||
lastTouchEndPos = currentScrollLeft
|
||||
const tick = () => {
|
||||
momentumTimer = setTimeout(() => {
|
||||
if (Math.abs(currentScrollLeft - lastTouchEndPos) < 2) {
|
||||
// 惯性真正结束,延迟 300ms 再恢复自动滚动(确保惯性完全停止)
|
||||
clearTimeout(momentumTimer)
|
||||
momentumTimer = setTimeout(() => {
|
||||
isManualScrolling = false
|
||||
autoScrollPos = currentScrollLeft
|
||||
startIOSAutoScroll()
|
||||
}, 300)
|
||||
} else {
|
||||
// 惯性中,更新快照继续检测
|
||||
lastTouchEndPos = currentScrollLeft
|
||||
tick()
|
||||
}
|
||||
}, 80)
|
||||
}
|
||||
tick()
|
||||
} else {
|
||||
// 安卓设备:检测惯性滚动是否结束
|
||||
detectMomentumEnd()
|
||||
}
|
||||
}
|
||||
const onTouchStart = () => pauseForUser()
|
||||
const onTouchEnd = () => {}
|
||||
|
||||
const onScroll = (e) => {
|
||||
if (!isComponentMounted) return
|
||||
currentScrollLeft = e.detail.scrollLeft
|
||||
|
||||
// iOS 手动滚动时,不再更新自动滚动相关变量
|
||||
if (isIOS && isManualScrolling) {
|
||||
return
|
||||
}
|
||||
|
||||
// 预加载:剩余可滚动距离小于一半屏幕宽度时,触发追加
|
||||
const remainingScroll = totalWidth.value - currentScrollLeft - props.screenWidth
|
||||
if (remainingScroll < Math.max(totalWidth.value / 2, props.screenWidth)) {
|
||||
// 注意:真实接口模式下不应该自动追加数据,由 has_more 控制
|
||||
if (!isLoadingMore && !appendFailed && !isInitialLoading && props.useMockData) {
|
||||
scheduleAppend()
|
||||
}
|
||||
@ -780,134 +669,52 @@ onMounted(() => {
|
||||
userInteracting = false
|
||||
currentScrollLeft = 0
|
||||
scrollLeft.value = 0
|
||||
// 获取设备平台信息,iOS 不使用自动滚动
|
||||
const sysInfo = uni.getSystemInfoSync()
|
||||
isIOS = sysInfo.platform === 'ios'
|
||||
console.log('[WaterfallGrid] onMounted, platform:', sysInfo.platform, 'isIOS:', isIOS)
|
||||
const containerH = props.screenHeight - props.bannerBottom
|
||||
layout = new WaterfallLayout(containerH, props.category)
|
||||
loadUsers().then(() => {
|
||||
isInitialLoading = false
|
||||
nextTick(() => {
|
||||
console.log('[WaterfallGrid] loadUsers done, calling auto scroll, isIOS:', isIOS)
|
||||
if (isIOS) {
|
||||
startIOSAutoScroll()
|
||||
} else {
|
||||
startAutoScroll()
|
||||
}
|
||||
})
|
||||
nextTick(() => startAutoScroll())
|
||||
})
|
||||
})
|
||||
|
||||
// ========== 可见性控制 ==========
|
||||
const stopAllAutoScroll = () => {
|
||||
stopAutoScroll()
|
||||
stopIOSAutoScroll()
|
||||
}
|
||||
|
||||
const resumeAllAutoScroll = () => {
|
||||
// 清理所有残留的滚动/惯性定时器,确保干净启动
|
||||
clearTimeout(momentumTimer)
|
||||
momentumTimer = null
|
||||
stopAllAutoScroll()
|
||||
if (!isComponentMounted) return
|
||||
// 使用 scrollLeft.value 而非 currentScrollLeft,因为手动滚动时
|
||||
// currentScrollLeft 不更新(onScroll 在 isManualScrolling 时直接 return)
|
||||
autoScrollPos = scrollLeft.value
|
||||
if (isIOS) {
|
||||
startIOSAutoScroll()
|
||||
} else {
|
||||
startAutoScroll()
|
||||
}
|
||||
}
|
||||
|
||||
// H5 页面可见性监听
|
||||
// 监听页面可见性变化
|
||||
const handleVisibilityChange = () => {
|
||||
if (!isComponentMounted) return
|
||||
if (document.hidden) {
|
||||
stopAllAutoScroll()
|
||||
userInteracting = true
|
||||
} else {
|
||||
// 页面从隐藏恢复时,momentum 已在 stopAllAutoScroll 中清掉,不需要等待
|
||||
resumeAllAutoScroll()
|
||||
userInteracting = false
|
||||
if (!rafId) {
|
||||
startAutoScroll()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// uni-app 生命周期:App 进入前台/后台
|
||||
let appShowListener = null
|
||||
let appHideListener = null
|
||||
|
||||
// iOS/Android 小程序可见性监听(通过页面 onShow/onHide)
|
||||
// uni-app 生命周期:App 进入前台/后台
|
||||
const onAppShowHandler = () => {
|
||||
if (!isComponentMounted) return
|
||||
// 页面从隐藏恢复时,momentum 已在 stopAllAutoScroll 中清掉,不需要等待
|
||||
// 直接 resume,iOS 靠自己的 RAF 驱动,Android 靠 setInterval
|
||||
resumeAllAutoScroll()
|
||||
}
|
||||
|
||||
const onAppHideHandler = () => {
|
||||
if (!isComponentMounted) return
|
||||
stopAllAutoScroll()
|
||||
}
|
||||
|
||||
if (typeof uni !== 'undefined') {
|
||||
uni.onAppShow(onAppShowHandler)
|
||||
uni.onAppHide(onAppHideHandler)
|
||||
}
|
||||
|
||||
// H5 环境额外监听 visibilitychange
|
||||
if (typeof document !== 'undefined') {
|
||||
document.addEventListener('visibilitychange', handleVisibilityChange)
|
||||
}
|
||||
|
||||
// 供父组件调用的可见性控制方法(通过 defineExpose 暴露)
|
||||
const handleAppShow = () => {
|
||||
if (!isComponentMounted) return
|
||||
setTimeout(() => {
|
||||
resumeAllAutoScroll()
|
||||
}, AUTO_RESUME_DELAY)
|
||||
}
|
||||
|
||||
const handleAppHide = () => {
|
||||
if (!isComponentMounted) return
|
||||
stopAllAutoScroll()
|
||||
}
|
||||
|
||||
// 暴露方法给父组件
|
||||
defineExpose({
|
||||
handleAppShow,
|
||||
handleAppHide,
|
||||
})
|
||||
|
||||
// 监听 isActive 属性变化(父组件控制)
|
||||
watch(() => props.isActive, (active) => {
|
||||
if (!isComponentMounted) return
|
||||
if (active) {
|
||||
stopAllAutoScroll()
|
||||
setTimeout(() => {
|
||||
resumeAllAutoScroll()
|
||||
}, 150)
|
||||
userInteracting = false
|
||||
if (!rafId) {
|
||||
startAutoScroll()
|
||||
}
|
||||
} else {
|
||||
stopAllAutoScroll()
|
||||
userInteracting = true
|
||||
}
|
||||
}, { immediate: false })
|
||||
|
||||
onUnmounted(() => {
|
||||
isComponentMounted = false
|
||||
stopAllAutoScroll()
|
||||
stopAutoScroll()
|
||||
clearTimeout(resumeTimer)
|
||||
clearTimeout(appendTimer)
|
||||
clearTimeout(momentumTimer)
|
||||
if (typeof document !== 'undefined') {
|
||||
document.removeEventListener('visibilitychange', handleVisibilityChange)
|
||||
}
|
||||
// 移除 uni-app 全局监听
|
||||
if (typeof uni !== 'undefined') {
|
||||
try {
|
||||
uni.offAppShow(onAppShowHandler)
|
||||
uni.offAppHide(onAppHideHandler)
|
||||
} catch (_) {}
|
||||
}
|
||||
})
|
||||
|
||||
watch(() => [props.screenHeight, props.bannerBottom], () => {
|
||||
@ -922,7 +729,7 @@ watch(() => [props.screenHeight, props.bannerBottom], () => {
|
||||
// 监听分类变化,重新加载数据
|
||||
watch(() => props.category, (newCategory) => {
|
||||
if (isComponentMounted) {
|
||||
stopAllAutoScroll()
|
||||
stopAutoScroll()
|
||||
|
||||
// 取消待执行的追加
|
||||
if (appendTimer) {
|
||||
@ -952,11 +759,7 @@ watch(() => props.category, (newCategory) => {
|
||||
|
||||
loadUsers().then(() => {
|
||||
nextTick(() => {
|
||||
if (isIOS) {
|
||||
startIOSAutoScroll()
|
||||
} else {
|
||||
startAutoScroll()
|
||||
}
|
||||
startAutoScroll()
|
||||
})
|
||||
})
|
||||
}
|
||||
@ -975,10 +778,6 @@ watch(() => props.category, (newCategory) => {
|
||||
top: 32rpx;
|
||||
}
|
||||
|
||||
.ios-animate {
|
||||
will-change: transform;
|
||||
}
|
||||
|
||||
.wf-card {
|
||||
position: absolute;
|
||||
cursor: pointer;
|
||||
|
||||
@ -108,11 +108,11 @@ const handleActivityClick = (item) => {
|
||||
})
|
||||
}
|
||||
|
||||
const handleRankingVisit = ({ userId, nickname }) => {
|
||||
const handleRankingVisit = (userId) => {
|
||||
showRankingModal.value = false
|
||||
uni.navigateTo({
|
||||
url: `/pages/profile/hisWorks?userId=${userId}&nickname=${encodeURIComponent(nickname)}`
|
||||
});
|
||||
// uni.navigateTo({
|
||||
// url: `/pages/exhibition/exhibition?target_uid=${userId}`,
|
||||
// })
|
||||
}
|
||||
|
||||
const handleRankingModalClose = (visible) => {
|
||||
@ -242,9 +242,9 @@ onUnmounted(() => {
|
||||
flex-direction: column;
|
||||
min-height: 448rpx;
|
||||
justify-content: space-between;
|
||||
/* background: rgb(249 159 192 / 45%);; */
|
||||
background: rgb(249 159 192 / 45%);;
|
||||
/* background: rgba(212, 127, 127, 0.8); */
|
||||
/* border-radius: 48rpx; */
|
||||
border-radius: 48rpx;
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
@ -257,7 +257,7 @@ onUnmounted(() => {
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 110%;
|
||||
height: 100%;
|
||||
z-index: 0;
|
||||
}
|
||||
|
||||
|
||||
@ -23,20 +23,12 @@
|
||||
>
|
||||
<image
|
||||
class="nft-cover"
|
||||
:class="{ 'nft-image-displayed': item.display_status === 1 }"
|
||||
:src="item.coverUrl || item.cover_url_signed"
|
||||
mode="aspectFill"
|
||||
/>
|
||||
<view v-if="item.display_status === 1" class="status-overlay">
|
||||
<text class="status-text-center">已展示</text>
|
||||
</view>
|
||||
<view class="card-rate-badge-overlay">
|
||||
<image class="heart-icon" src="/static/icon/heart-icon.png" mode="aspectFit"></image>
|
||||
<text class="card-rate-text">{{ item.like_count || 0 }}</text>
|
||||
</view>
|
||||
<!-- <view class="nft-info">
|
||||
<view class="nft-info">
|
||||
<text class="nft-name">{{ item.name }}</text>
|
||||
</view> -->
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
@ -240,7 +232,6 @@ onMounted(() => {
|
||||
}
|
||||
|
||||
.nft-grid-item {
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
@ -250,7 +241,7 @@ onMounted(() => {
|
||||
|
||||
.nft-cover {
|
||||
width: 192rpx;
|
||||
height: 256rpx;
|
||||
height: 224rpx;
|
||||
}
|
||||
|
||||
.nft-grid-item:active {
|
||||
@ -273,78 +264,6 @@ onMounted(() => {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
/* 已展示的图片 - 灰色滤镜 */
|
||||
.nft-image-displayed {
|
||||
filter: grayscale(25%);
|
||||
}
|
||||
|
||||
/* 展示状态覆盖层 - 居中显示 */
|
||||
.status-overlay {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 192rpx;
|
||||
height: 224rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: 16rpx;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.status-text-center {
|
||||
font-size: 24rpx;
|
||||
color: #fff;
|
||||
font-weight: bold;
|
||||
text-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.8);
|
||||
background: linear-gradient(to bottom right,
|
||||
#F0E4B1 0%,
|
||||
#F08399 50%,
|
||||
#B94E73 100%
|
||||
);
|
||||
border-radius: 24rpx;
|
||||
box-shadow:
|
||||
0 4rpx 12rpx rgba(255, 143, 158, 0.2),
|
||||
0 2rpx 6rpx rgba(255, 143, 158, 0.15),
|
||||
inset 0 2rpx 4rpx rgba(255, 255, 255, 0.4),
|
||||
inset 0 -2rpx 4rpx rgba(0, 0, 0, 0.05);
|
||||
padding: 16rpx;
|
||||
}
|
||||
|
||||
/* 点赞数徽章 - 图片上覆盖层 */
|
||||
.card-rate-badge-overlay {
|
||||
position: absolute;
|
||||
bottom: 12rpx;
|
||||
left: 12rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
background: linear-gradient(to bottom right,
|
||||
#F0E4B1 0%,
|
||||
#F08399 50%,
|
||||
#B94E73 100%);
|
||||
border-radius: 999rpx;
|
||||
padding: 8rpx 20rpx 8rpx 40rpx;
|
||||
box-shadow:
|
||||
0 4rpx 12rpx rgba(255, 143, 158, 0.2),
|
||||
inset 0 2rpx 4rpx rgba(255, 255, 255, 0.4);
|
||||
|
||||
border-radius: 20rpx;
|
||||
padding: 6rpx 12rpx;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.card-rate-badge-overlay .heart-icon {
|
||||
width: 24rpx;
|
||||
height: 24rpx;
|
||||
margin-right: 6rpx;
|
||||
}
|
||||
|
||||
.card-rate-badge-overlay .card-rate-text {
|
||||
font-size: 22rpx;
|
||||
color: #fff;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
/* 加载更多 */
|
||||
.load-more {
|
||||
display: flex;
|
||||
|
||||
|
Before Width: | Height: | Size: 399 KiB |
|
Before Width: | Height: | Size: 3.1 MiB |
|
Before Width: | Height: | Size: 191 KiB |
|
Before Width: | Height: | Size: 1.6 MiB |
|
Before Width: | Height: | Size: 1.4 MiB |
|
Before Width: | Height: | Size: 1.5 MiB |
|
Before Width: | Height: | Size: 106 KiB |
|
Before Width: | Height: | Size: 298 KiB After Width: | Height: | Size: 298 KiB |
|
Before Width: | Height: | Size: 17 KiB |
|
Before Width: | Height: | Size: 16 KiB |
|
Before Width: | Height: | Size: 17 KiB |
|
Before Width: | Height: | Size: 295 KiB |
|
Before Width: | Height: | Size: 302 KiB |
|
Before Width: | Height: | Size: 303 KiB |
|
Before Width: | Height: | Size: 2.1 MiB |
@ -568,22 +568,26 @@ export function getStarbookItemsApi(type, category, grade = null, page = 1, page
|
||||
})
|
||||
}
|
||||
|
||||
// ==================== 他人作品统计接口 ====================
|
||||
// ==================== 他人作品统计接口(暂不实现) ====================
|
||||
|
||||
// 获取他人点赞的作品列表
|
||||
// 获取他人点赞的作品列表(暂不实现)
|
||||
export function getUserLikedAssetsApi(userId, page = 1, pageSize = 20) {
|
||||
return request({
|
||||
url: `/api/v1/users/${userId}/liked-assets?page=${page}&page_size=${pageSize}`,
|
||||
method: 'GET'
|
||||
})
|
||||
return Promise.reject(new Error('接口暂未开放'))
|
||||
// 正式实现时启用:
|
||||
// return request({
|
||||
// url: `/api/v1/users/${userId}/liked-assets?page=${page}&page_size=${pageSize}`,
|
||||
// method: 'GET'
|
||||
// })
|
||||
}
|
||||
|
||||
// 获取他人展出的作品列表
|
||||
// 获取他人展出的作品列表(暂不实现)
|
||||
export function getUserExhibitedAssetsApi(userId, page = 1, pageSize = 20) {
|
||||
return request({
|
||||
url: `/api/v1/users/${userId}/exhibited-assets?page=${page}&page_size=${pageSize}`,
|
||||
method: 'GET'
|
||||
})
|
||||
return Promise.reject(new Error('接口暂未开放'))
|
||||
// 正式实现时启用:
|
||||
// return request({
|
||||
// url: `/api/v1/users/${userId}/exhibited-assets?page=${page}&page_size=${pageSize}`,
|
||||
// method: 'GET'
|
||||
// })
|
||||
}
|
||||
|
||||
// ==================== 我的作品统计接口 ====================
|
||||
@ -604,22 +608,6 @@ export function getMyLikedAssetsApi(page = 1, pageSize = 20) {
|
||||
})
|
||||
}
|
||||
|
||||
// 获取我今日点赞的作品列表
|
||||
export function getMyTodayLikedAssetsApi(page = 1, pageSize = 20) {
|
||||
return request({
|
||||
url: `/api/v1/me/today-liked-assets?page=${page}&page_size=${pageSize}`,
|
||||
method: 'GET'
|
||||
})
|
||||
}
|
||||
|
||||
// 获取我本周点赞的作品列表
|
||||
export function getMyWeekLikedAssetsApi(page = 1, pageSize = 20) {
|
||||
return request({
|
||||
url: `/api/v1/me/week-liked-assets?page=${page}&page_size=${pageSize}`,
|
||||
method: 'GET'
|
||||
})
|
||||
}
|
||||
|
||||
// ==================== 灵感瀑布相关接口 ====================
|
||||
|
||||
// 获取灵感瀑布藏品列表
|
||||
|
||||