syntax = "proto3"; package topfans.gallery; import "proto/common.proto"; import "google/api/annotations.proto"; option go_package = "github.com/topfans/backend/pkg/proto/gallery;gallery"; // 展馆服务 service GalleryService { // 获取我的展馆 rpc GetMyGallery(GetMyGalleryRequest) returns (GetMyGalleryResponse) { option (google.api.http) = { get: "/api/mygalleries" }; } // 获取他人展馆 rpc GetUserGallery(GetUserGalleryRequest) returns (GetUserGalleryResponse) { option (google.api.http) = { get: "/api/galleries/{target_uid}" }; } // 在展位展示藏品 rpc PlaceAsset(PlaceAssetRequest) returns (PlaceAssetResponse) { option (google.api.http) = { post: "/api/galleries/place" body: "*" }; } // 解锁/购买新展位 rpc UnlockSlot(UnlockSlotRequest) returns (UnlockSlotResponse) { option (google.api.http) = { post: "/api/galleries/slots_unlock" body: "*" }; } // 从展位移除资产(统一接口,支持展位所有者踢走和占位者下架) rpc RemoveFromSlot(RemoveFromSlotRequest) returns (RemoveFromSlotResponse) { option (google.api.http) = { delete: "/api/galleries/slots/{slot_id}/asset" }; } // ========== 我的作品相关 ========== // 获取我展出的作品列表 rpc GetMyExhibitedAssets(GetMyExhibitedAssetsRequest) returns (GetMyExhibitedAssetsResponse) { option (google.api.http) = { get: "/api/v1/me/exhibited-assets" }; } // 获取灵感瀑布藏品列表 rpc GetInspirationFlow(GetInspirationFlowRequest) returns (GetInspirationFlowResponse) { option (google.api.http) = { get: "/api/v1/inspiration-flow" }; } } // 请求和响应消息定义 message GetMyGalleryRequest {} message GetMyGalleryResponse { topfans.common.BaseResponse base = 1; GalleryData data = 2; } message GetUserGalleryRequest { int64 target_uid = 1; } message GetUserGalleryResponse { topfans.common.BaseResponse base = 1; GalleryData data = 2; } message PlaceAssetRequest { int64 asset_id = 1; int64 gallery_owner_id = 2; int64 slot_id = 3; } message PlaceAssetResponse { topfans.common.BaseResponse base = 1; PlaceAssetData data = 2; } message UnlockSlotRequest {} message UnlockSlotResponse { topfans.common.BaseResponse base = 1; UnlockSlotData data = 2; } // 数据模型 message GalleryData { int64 gallery_owner_id = 1; int32 slot_total = 2; repeated SlotInfo slots = 3; string nickname = 4; // 展馆所有者昵称(从 fan_profiles 表获取) } message SlotInfo { int64 slot_id = 1; int32 slot_index = 2; string status = 3; // EMPTY, OCCUPIED, LOCKED bool is_enabled = 4; AssetInfo asset = 5; int64 occupier_uid = 6; int64 occupied_at = 7; int64 expire_at = 8; UnlockCondition unlock_condition = 9; string visibility = 10; // public / private bool can_operate = 11; // 当前用户是否可以操作此展位 string operation = 12; // 操作类型: "place" | "remove" | "none" } message AssetInfo { int64 asset_id = 1; string name = 2; string cover_url = 3; int32 like_count = 4; int64 remain_time = 5; // 剩余时间(秒) } message UnlockCondition { string type = 1; // level, crystal int32 value = 2; } message PlaceAssetData { string status = 1; // OCCUPIED string occupied_until = 2; // ISO 8601格式 int64 occupier_uid = 3; // 占位者用户ID } message UnlockSlotData { int32 slot_total = 1; // 展位总数 int64 crystal_balance = 2; // 水晶余额(如果使用水晶购买,显示扣除后的余额) } // 从展位移除资产请求 message RemoveFromSlotRequest { int64 slot_id = 1; // 展位ID(必填) } // 从展位移除资产响应 message RemoveFromSlotResponse { topfans.common.BaseResponse base = 1; } // ==================== 我的作品相关消息 ==================== // 获取我展出的作品列表请求 message GetMyExhibitedAssetsRequest { int32 page = 1; // 页码(默认1) int32 page_size = 2; // 每页数量(默认20,最大100) } // 获取我展出的作品列表响应 message GetMyExhibitedAssetsResponse { topfans.common.BaseResponse base = 1; ExhibitedAssetsData data = 2; } // 展出作品数据 message ExhibitedAssetsData { repeated ExhibitedAssetItem items = 1; // 作品列表 int32 page = 2; // 当前页码 int32 page_size = 3; // 每页数量 int64 total = 4; // 总数量 bool has_more = 5; // 是否有更多 } // 展出作品项 message ExhibitedAssetItem { int64 asset_id = 1; // 资产ID string name = 2; // 藏品名称 string cover_url = 3; // 封面图URL int32 like_count = 4; // 实时点赞数 int64 exhibited_at = 5; // 展出开始时间(毫秒时间戳) int64 expire_at = 6; // 展出过期时间(毫秒时间戳) int64 earnings = 7; // 当前可领取收益 } // ==================== 灵感瀑布相关消息 ==================== // 获取灵感瀑布藏品列表请求 message GetInspirationFlowRequest { string cursor = 1; // 游标(首次请求为空) string direction = 2; // 滚动方向:right(加载新数据)/ left(加载历史) int32 limit = 3; // 每页数量(默认10,最大20) string type = 4; // 过滤类型:badge/poster/original/all(默认all) string session_id = 5; // 会话ID(首次请求时为空,后端返回新的session_id) } // 获取灵感瀑布藏品列表响应 message GetInspirationFlowResponse { topfans.common.BaseResponse base = 1; InspirationFlowData data = 2; } // 灵感瀑布数据 message InspirationFlowData { repeated InspirationFlowItem items = 1; // 藏品列表 string cursor = 2; // 下次请求的游标 bool has_more = 3; // 是否有更多 string session_id = 4; // 会话ID(首次请求时返回) } // 灵感瀑布藏品项 message InspirationFlowItem { int64 asset_id = 1; // 资产ID string name = 2; // 藏品名称 string cover_url = 3; // 封面图URL int32 like_count = 4; // 点赞数 string owner_nickname = 5; // 展出者昵称 }