feat: 修改铸造消耗确认框和新增批量购买道具的功能,修改回退按钮的颜色

This commit is contained in:
zerosaturation 2026-05-22 00:14:28 +08:00
parent 569321bb41
commit ee0433464f
29 changed files with 1307 additions and 414 deletions

View File

@ -343,6 +343,131 @@ func (ctrl *ActivityController) PurchaseItem(c *gin.Context) {
response.Success(c, data) response.Success(c, data)
} }
// BatchPurchaseItem 批量购买道具
// @Summary 批量购买道具
// @Description 批量购买活动道具
// @Tags activities
// @Accept json
// @Produce json
// @Security BearerAuth
// @Param activity_id path int64 true "活动ID"
// @Param request body pbActivity.BatchPurchaseItemRequest true "批量购买请求"
// @Success 200 {object} response.Response
// @Router /api/v1/activities/{activity_id}/batch-purchase [post]
func (ctrl *ActivityController) BatchPurchaseItem(c *gin.Context) {
// 从上下文获取用户信息
userID, exists := c.Get("user_id")
if !exists {
response.Error(c, http.StatusUnauthorized, "未授权")
return
}
starID, exists := c.Get("star_id")
if !exists {
response.Error(c, http.StatusUnauthorized, "未授权")
return
}
// 解析路径参数
activityIDStr := c.Param("id")
activityID, err := strconv.ParseInt(activityIDStr, 10, 64)
if err != nil {
response.Error(c, http.StatusBadRequest, "活动ID参数错误")
return
}
// 解析请求体
var req struct {
Items []struct {
ItemType string `json:"item_type"`
Quantity int `json:"quantity"`
} `json:"items"`
}
if err := c.ShouldBindJSON(&req); err != nil {
response.Error(c, http.StatusBadRequest, "请求参数错误")
return
}
if len(req.Items) == 0 {
response.Error(c, http.StatusBadRequest, "items 是必填参数")
return
}
logger.Logger.Info("BatchPurchaseItem request",
zap.Int64("user_id", userID.(int64)),
zap.Int64("star_id", starID.(int64)),
zap.Int64("activity_id", activityID),
zap.Int("items_count", len(req.Items)),
)
// 设置上下文
ctx, cancel := context.WithTimeout(context.Background(), 10*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),
})
// 转换请求
pbItems := make([]*pbActivity.PurchaseItem, len(req.Items))
for i, item := range req.Items {
quantity := int32(item.Quantity)
if quantity <= 0 {
quantity = 1
}
pbItems[i] = &pbActivity.PurchaseItem{
ItemType: item.ItemType,
Quantity: quantity,
}
}
// 调用 RPC
resp, err := ctrl.activityService.BatchPurchaseItem(ctx, &pbActivity.BatchPurchaseItemRequest{
ActivityId: activityID,
Items: pbItems,
StarId: starID.(int64),
UserId: userID.(int64),
})
if err != nil {
logger.Logger.Error("BatchPurchaseItem 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
}
// 非 active 阶段:通过 message 信号返回 200 + activity_status
activityStatusMap := map[string]string{
"activity:expired": "expired",
"activity:pending": "pending",
"activity:completed": "completed",
"activity:incomplete": "incomplete",
"activity:active": "active",
}
activityMessageMap := map[string]string{
"expired": "活动已结束",
"pending": "活动未开始",
"completed": "活动已完成",
"incomplete": "活动未完成",
"active": "活动进行中",
}
if status, ok := activityStatusMap[resp.Base.Message]; ok {
response.Success(c, map[string]interface{}{
"activity_status": status,
"message": activityMessageMap[status],
})
return
}
// 正常购买成功
data := convertBatchPurchaseResponse(resp)
response.Success(c, data)
}
// GetContributionRanking 获取贡献点排名 // GetContributionRanking 获取贡献点排名
// @Summary 获取贡献点排名 // @Summary 获取贡献点排名
// @Description 获取活动贡献点排名 // @Description 获取活动贡献点排名
@ -742,6 +867,26 @@ func convertPurchaseResponse(resp *pbActivity.PurchaseItemResponse) map[string]i
} }
} }
// convertBatchPurchaseResponse 转换批量购买响应
func convertBatchPurchaseResponse(resp *pbActivity.BatchPurchaseItemResponse) map[string]interface{} {
fails := make([]map[string]interface{}, 0, len(resp.Fails))
for _, fail := range resp.Fails {
fails = append(fails, map[string]interface{}{
"item_type": fail.ItemType,
"reason": fail.Reason,
})
}
return map[string]interface{}{
"total_crystal_spent": resp.TotalCrystalSpent,
"total_contribution": resp.TotalContribution,
"current_progress": resp.CurrentProgress,
"remaining_balance": resp.RemainingBalance,
"success_count": resp.SuccessCount,
"fail_count": resp.FailCount,
"fails": fails,
}
}
// convertContributionRankingResponse 转换排名响应 // convertContributionRankingResponse 转换排名响应
func convertContributionRankingResponse(resp *pbActivity.ContributionRankingResponse) map[string]interface{} { func convertContributionRankingResponse(resp *pbActivity.ContributionRankingResponse) map[string]interface{} {
items := make([]map[string]interface{}, 0, len(resp.Items)) items := make([]map[string]interface{}, 0, len(resp.Items))

View File

@ -286,7 +286,7 @@ func (ctrl *AssetController) EstimateMintCost(c *gin.Context) {
"current_balance": resp.CurrentBalance, "current_balance": resp.CurrentBalance,
"balance_after": resp.BalanceAfter, "balance_after": resp.BalanceAfter,
"mint_count": resp.MintCount, "mint_count": resp.MintCount,
"next_tier_hint": resp.NextTierHint, "next_tier_cost": resp.NextTierCost,
} }
response.Success(c, data) response.Success(c, data)
} }

View File

@ -249,6 +249,7 @@ func SetupRouter(userClient *client.Client, socialClient *client.Client, assetCl
activities.GET("/:id/items", activityCtrl.GetActivityItems) // 获取活动道具列表 activities.GET("/:id/items", activityCtrl.GetActivityItems) // 获取活动道具列表
activities.GET("/:id/progress", activityCtrl.GetProgress) // 获取活动进度 activities.GET("/:id/progress", activityCtrl.GetProgress) // 获取活动进度
activities.POST("/:id/purchase", activityCtrl.PurchaseItem) // 购买道具 activities.POST("/:id/purchase", activityCtrl.PurchaseItem) // 购买道具
activities.POST("/:id/batch-purchase", activityCtrl.BatchPurchaseItem) // 批量购买道具
activities.GET("/:id/ranking", activityCtrl.GetContributionRanking) // 获取贡献点排名 activities.GET("/:id/ranking", activityCtrl.GetContributionRanking) // 获取贡献点排名
activities.GET("/:id/contributions/latest", activityCtrl.GetLatestContributions) // 获取最新贡献记录 activities.GET("/:id/contributions/latest", activityCtrl.GetLatestContributions) // 获取最新贡献记录
} }

View File

@ -496,6 +496,282 @@ func (x *PurchaseItemResponse) GetRemainingBalance() int64 {
return 0 return 0
} }
// 单个购买项(用于批量购买)
type PurchaseItem struct {
state protoimpl.MessageState `protogen:"open.v1"`
ItemType string `protobuf:"bytes,1,opt,name=item_type,json=itemType,proto3" json:"item_type,omitempty"`
Quantity int32 `protobuf:"varint,2,opt,name=quantity,proto3" json:"quantity,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *PurchaseItem) Reset() {
*x = PurchaseItem{}
mi := &file_activity_proto_msgTypes[5]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *PurchaseItem) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*PurchaseItem) ProtoMessage() {}
func (x *PurchaseItem) ProtoReflect() protoreflect.Message {
mi := &file_activity_proto_msgTypes[5]
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 PurchaseItem.ProtoReflect.Descriptor instead.
func (*PurchaseItem) Descriptor() ([]byte, []int) {
return file_activity_proto_rawDescGZIP(), []int{5}
}
func (x *PurchaseItem) GetItemType() string {
if x != nil {
return x.ItemType
}
return ""
}
func (x *PurchaseItem) GetQuantity() int32 {
if x != nil {
return x.Quantity
}
return 0
}
// 批量购买道具请求
type BatchPurchaseItemRequest struct {
state protoimpl.MessageState `protogen:"open.v1"`
ActivityId int64 `protobuf:"varint,1,opt,name=activity_id,json=activityId,proto3" json:"activity_id,omitempty"`
Items []*PurchaseItem `protobuf:"bytes,2,rep,name=items,proto3" json:"items,omitempty"` // 购买项列表
StarId int64 `protobuf:"varint,3,opt,name=star_id,json=starId,proto3" json:"star_id,omitempty"`
UserId int64 `protobuf:"varint,4,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` // 当前用户ID
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *BatchPurchaseItemRequest) Reset() {
*x = BatchPurchaseItemRequest{}
mi := &file_activity_proto_msgTypes[6]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *BatchPurchaseItemRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*BatchPurchaseItemRequest) ProtoMessage() {}
func (x *BatchPurchaseItemRequest) ProtoReflect() protoreflect.Message {
mi := &file_activity_proto_msgTypes[6]
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 BatchPurchaseItemRequest.ProtoReflect.Descriptor instead.
func (*BatchPurchaseItemRequest) Descriptor() ([]byte, []int) {
return file_activity_proto_rawDescGZIP(), []int{6}
}
func (x *BatchPurchaseItemRequest) GetActivityId() int64 {
if x != nil {
return x.ActivityId
}
return 0
}
func (x *BatchPurchaseItemRequest) GetItems() []*PurchaseItem {
if x != nil {
return x.Items
}
return nil
}
func (x *BatchPurchaseItemRequest) GetStarId() int64 {
if x != nil {
return x.StarId
}
return 0
}
func (x *BatchPurchaseItemRequest) GetUserId() int64 {
if x != nil {
return x.UserId
}
return 0
}
// 批量购买道具响应
type BatchPurchaseItemResponse struct {
state protoimpl.MessageState `protogen:"open.v1"`
Base *common.BaseResponse `protobuf:"bytes,1,opt,name=base,proto3" json:"base,omitempty"`
TotalCrystalSpent int64 `protobuf:"varint,2,opt,name=total_crystal_spent,json=totalCrystalSpent,proto3" json:"total_crystal_spent,omitempty"` // 本次消费水晶
TotalContribution int64 `protobuf:"varint,3,opt,name=total_contribution,json=totalContribution,proto3" json:"total_contribution,omitempty"` // 本次获得贡献点
CurrentProgress int64 `protobuf:"varint,4,opt,name=current_progress,json=currentProgress,proto3" json:"current_progress,omitempty"` // 当前活动进度
RemainingBalance int64 `protobuf:"varint,5,opt,name=remaining_balance,json=remainingBalance,proto3" json:"remaining_balance,omitempty"` // 剩余水晶余额
SuccessCount int32 `protobuf:"varint,6,opt,name=success_count,json=successCount,proto3" json:"success_count,omitempty"` // 成功购买数量
FailCount int32 `protobuf:"varint,7,opt,name=fail_count,json=failCount,proto3" json:"fail_count,omitempty"` // 失败购买数量
Fails []*PurchaseFailItem `protobuf:"bytes,8,rep,name=fails,proto3" json:"fails,omitempty"` // 失败的项
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *BatchPurchaseItemResponse) Reset() {
*x = BatchPurchaseItemResponse{}
mi := &file_activity_proto_msgTypes[7]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *BatchPurchaseItemResponse) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*BatchPurchaseItemResponse) ProtoMessage() {}
func (x *BatchPurchaseItemResponse) ProtoReflect() protoreflect.Message {
mi := &file_activity_proto_msgTypes[7]
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 BatchPurchaseItemResponse.ProtoReflect.Descriptor instead.
func (*BatchPurchaseItemResponse) Descriptor() ([]byte, []int) {
return file_activity_proto_rawDescGZIP(), []int{7}
}
func (x *BatchPurchaseItemResponse) GetBase() *common.BaseResponse {
if x != nil {
return x.Base
}
return nil
}
func (x *BatchPurchaseItemResponse) GetTotalCrystalSpent() int64 {
if x != nil {
return x.TotalCrystalSpent
}
return 0
}
func (x *BatchPurchaseItemResponse) GetTotalContribution() int64 {
if x != nil {
return x.TotalContribution
}
return 0
}
func (x *BatchPurchaseItemResponse) GetCurrentProgress() int64 {
if x != nil {
return x.CurrentProgress
}
return 0
}
func (x *BatchPurchaseItemResponse) GetRemainingBalance() int64 {
if x != nil {
return x.RemainingBalance
}
return 0
}
func (x *BatchPurchaseItemResponse) GetSuccessCount() int32 {
if x != nil {
return x.SuccessCount
}
return 0
}
func (x *BatchPurchaseItemResponse) GetFailCount() int32 {
if x != nil {
return x.FailCount
}
return 0
}
func (x *BatchPurchaseItemResponse) GetFails() []*PurchaseFailItem {
if x != nil {
return x.Fails
}
return nil
}
// 购买失败的项
type PurchaseFailItem struct {
state protoimpl.MessageState `protogen:"open.v1"`
ItemType string `protobuf:"bytes,1,opt,name=item_type,json=itemType,proto3" json:"item_type,omitempty"`
Reason string `protobuf:"bytes,2,opt,name=reason,proto3" json:"reason,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *PurchaseFailItem) Reset() {
*x = PurchaseFailItem{}
mi := &file_activity_proto_msgTypes[8]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *PurchaseFailItem) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*PurchaseFailItem) ProtoMessage() {}
func (x *PurchaseFailItem) ProtoReflect() protoreflect.Message {
mi := &file_activity_proto_msgTypes[8]
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 PurchaseFailItem.ProtoReflect.Descriptor instead.
func (*PurchaseFailItem) Descriptor() ([]byte, []int) {
return file_activity_proto_rawDescGZIP(), []int{8}
}
func (x *PurchaseFailItem) GetItemType() string {
if x != nil {
return x.ItemType
}
return ""
}
func (x *PurchaseFailItem) GetReason() string {
if x != nil {
return x.Reason
}
return ""
}
// 贡献点排名请求 // 贡献点排名请求
type ContributionRankingRequest struct { type ContributionRankingRequest struct {
state protoimpl.MessageState `protogen:"open.v1"` state protoimpl.MessageState `protogen:"open.v1"`
@ -510,7 +786,7 @@ type ContributionRankingRequest struct {
func (x *ContributionRankingRequest) Reset() { func (x *ContributionRankingRequest) Reset() {
*x = ContributionRankingRequest{} *x = ContributionRankingRequest{}
mi := &file_activity_proto_msgTypes[5] mi := &file_activity_proto_msgTypes[9]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
} }
@ -522,7 +798,7 @@ func (x *ContributionRankingRequest) String() string {
func (*ContributionRankingRequest) ProtoMessage() {} func (*ContributionRankingRequest) ProtoMessage() {}
func (x *ContributionRankingRequest) ProtoReflect() protoreflect.Message { func (x *ContributionRankingRequest) ProtoReflect() protoreflect.Message {
mi := &file_activity_proto_msgTypes[5] mi := &file_activity_proto_msgTypes[9]
if x != nil { if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
@ -535,7 +811,7 @@ func (x *ContributionRankingRequest) ProtoReflect() protoreflect.Message {
// Deprecated: Use ContributionRankingRequest.ProtoReflect.Descriptor instead. // Deprecated: Use ContributionRankingRequest.ProtoReflect.Descriptor instead.
func (*ContributionRankingRequest) Descriptor() ([]byte, []int) { func (*ContributionRankingRequest) Descriptor() ([]byte, []int) {
return file_activity_proto_rawDescGZIP(), []int{5} return file_activity_proto_rawDescGZIP(), []int{9}
} }
func (x *ContributionRankingRequest) GetActivityId() int64 { func (x *ContributionRankingRequest) GetActivityId() int64 {
@ -588,7 +864,7 @@ type ContributionRankingItem struct {
func (x *ContributionRankingItem) Reset() { func (x *ContributionRankingItem) Reset() {
*x = ContributionRankingItem{} *x = ContributionRankingItem{}
mi := &file_activity_proto_msgTypes[6] mi := &file_activity_proto_msgTypes[10]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
} }
@ -600,7 +876,7 @@ func (x *ContributionRankingItem) String() string {
func (*ContributionRankingItem) ProtoMessage() {} func (*ContributionRankingItem) ProtoMessage() {}
func (x *ContributionRankingItem) ProtoReflect() protoreflect.Message { func (x *ContributionRankingItem) ProtoReflect() protoreflect.Message {
mi := &file_activity_proto_msgTypes[6] mi := &file_activity_proto_msgTypes[10]
if x != nil { if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
@ -613,7 +889,7 @@ func (x *ContributionRankingItem) ProtoReflect() protoreflect.Message {
// Deprecated: Use ContributionRankingItem.ProtoReflect.Descriptor instead. // Deprecated: Use ContributionRankingItem.ProtoReflect.Descriptor instead.
func (*ContributionRankingItem) Descriptor() ([]byte, []int) { func (*ContributionRankingItem) Descriptor() ([]byte, []int) {
return file_activity_proto_rawDescGZIP(), []int{6} return file_activity_proto_rawDescGZIP(), []int{10}
} }
func (x *ContributionRankingItem) GetRank() int32 { func (x *ContributionRankingItem) GetRank() int32 {
@ -673,7 +949,7 @@ type ContributionRankingResponse struct {
func (x *ContributionRankingResponse) Reset() { func (x *ContributionRankingResponse) Reset() {
*x = ContributionRankingResponse{} *x = ContributionRankingResponse{}
mi := &file_activity_proto_msgTypes[7] mi := &file_activity_proto_msgTypes[11]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
} }
@ -685,7 +961,7 @@ func (x *ContributionRankingResponse) String() string {
func (*ContributionRankingResponse) ProtoMessage() {} func (*ContributionRankingResponse) ProtoMessage() {}
func (x *ContributionRankingResponse) ProtoReflect() protoreflect.Message { func (x *ContributionRankingResponse) ProtoReflect() protoreflect.Message {
mi := &file_activity_proto_msgTypes[7] mi := &file_activity_proto_msgTypes[11]
if x != nil { if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
@ -698,7 +974,7 @@ func (x *ContributionRankingResponse) ProtoReflect() protoreflect.Message {
// Deprecated: Use ContributionRankingResponse.ProtoReflect.Descriptor instead. // Deprecated: Use ContributionRankingResponse.ProtoReflect.Descriptor instead.
func (*ContributionRankingResponse) Descriptor() ([]byte, []int) { func (*ContributionRankingResponse) Descriptor() ([]byte, []int) {
return file_activity_proto_rawDescGZIP(), []int{7} return file_activity_proto_rawDescGZIP(), []int{11}
} }
func (x *ContributionRankingResponse) GetBase() *common.BaseResponse { func (x *ContributionRankingResponse) GetBase() *common.BaseResponse {
@ -758,7 +1034,7 @@ type MyContribution struct {
func (x *MyContribution) Reset() { func (x *MyContribution) Reset() {
*x = MyContribution{} *x = MyContribution{}
mi := &file_activity_proto_msgTypes[8] mi := &file_activity_proto_msgTypes[12]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
} }
@ -770,7 +1046,7 @@ func (x *MyContribution) String() string {
func (*MyContribution) ProtoMessage() {} func (*MyContribution) ProtoMessage() {}
func (x *MyContribution) ProtoReflect() protoreflect.Message { func (x *MyContribution) ProtoReflect() protoreflect.Message {
mi := &file_activity_proto_msgTypes[8] mi := &file_activity_proto_msgTypes[12]
if x != nil { if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
@ -783,7 +1059,7 @@ func (x *MyContribution) ProtoReflect() protoreflect.Message {
// Deprecated: Use MyContribution.ProtoReflect.Descriptor instead. // Deprecated: Use MyContribution.ProtoReflect.Descriptor instead.
func (*MyContribution) Descriptor() ([]byte, []int) { func (*MyContribution) Descriptor() ([]byte, []int) {
return file_activity_proto_rawDescGZIP(), []int{8} return file_activity_proto_rawDescGZIP(), []int{12}
} }
func (x *MyContribution) GetRank() int32 { func (x *MyContribution) GetRank() int32 {
@ -841,7 +1117,7 @@ type GetActivityListRequest struct {
func (x *GetActivityListRequest) Reset() { func (x *GetActivityListRequest) Reset() {
*x = GetActivityListRequest{} *x = GetActivityListRequest{}
mi := &file_activity_proto_msgTypes[9] mi := &file_activity_proto_msgTypes[13]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
} }
@ -853,7 +1129,7 @@ func (x *GetActivityListRequest) String() string {
func (*GetActivityListRequest) ProtoMessage() {} func (*GetActivityListRequest) ProtoMessage() {}
func (x *GetActivityListRequest) ProtoReflect() protoreflect.Message { func (x *GetActivityListRequest) ProtoReflect() protoreflect.Message {
mi := &file_activity_proto_msgTypes[9] mi := &file_activity_proto_msgTypes[13]
if x != nil { if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
@ -866,7 +1142,7 @@ func (x *GetActivityListRequest) ProtoReflect() protoreflect.Message {
// Deprecated: Use GetActivityListRequest.ProtoReflect.Descriptor instead. // Deprecated: Use GetActivityListRequest.ProtoReflect.Descriptor instead.
func (*GetActivityListRequest) Descriptor() ([]byte, []int) { func (*GetActivityListRequest) Descriptor() ([]byte, []int) {
return file_activity_proto_rawDescGZIP(), []int{9} return file_activity_proto_rawDescGZIP(), []int{13}
} }
func (x *GetActivityListRequest) GetStarId() int64 { func (x *GetActivityListRequest) GetStarId() int64 {
@ -911,7 +1187,7 @@ type GetActivityListResponse struct {
func (x *GetActivityListResponse) Reset() { func (x *GetActivityListResponse) Reset() {
*x = GetActivityListResponse{} *x = GetActivityListResponse{}
mi := &file_activity_proto_msgTypes[10] mi := &file_activity_proto_msgTypes[14]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
} }
@ -923,7 +1199,7 @@ func (x *GetActivityListResponse) String() string {
func (*GetActivityListResponse) ProtoMessage() {} func (*GetActivityListResponse) ProtoMessage() {}
func (x *GetActivityListResponse) ProtoReflect() protoreflect.Message { func (x *GetActivityListResponse) ProtoReflect() protoreflect.Message {
mi := &file_activity_proto_msgTypes[10] mi := &file_activity_proto_msgTypes[14]
if x != nil { if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
@ -936,7 +1212,7 @@ func (x *GetActivityListResponse) ProtoReflect() protoreflect.Message {
// Deprecated: Use GetActivityListResponse.ProtoReflect.Descriptor instead. // Deprecated: Use GetActivityListResponse.ProtoReflect.Descriptor instead.
func (*GetActivityListResponse) Descriptor() ([]byte, []int) { func (*GetActivityListResponse) Descriptor() ([]byte, []int) {
return file_activity_proto_rawDescGZIP(), []int{10} return file_activity_proto_rawDescGZIP(), []int{14}
} }
func (x *GetActivityListResponse) GetBase() *common.BaseResponse { func (x *GetActivityListResponse) GetBase() *common.BaseResponse {
@ -984,7 +1260,7 @@ type GetProgressRequest struct {
func (x *GetProgressRequest) Reset() { func (x *GetProgressRequest) Reset() {
*x = GetProgressRequest{} *x = GetProgressRequest{}
mi := &file_activity_proto_msgTypes[11] mi := &file_activity_proto_msgTypes[15]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
} }
@ -996,7 +1272,7 @@ func (x *GetProgressRequest) String() string {
func (*GetProgressRequest) ProtoMessage() {} func (*GetProgressRequest) ProtoMessage() {}
func (x *GetProgressRequest) ProtoReflect() protoreflect.Message { func (x *GetProgressRequest) ProtoReflect() protoreflect.Message {
mi := &file_activity_proto_msgTypes[11] mi := &file_activity_proto_msgTypes[15]
if x != nil { if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
@ -1009,7 +1285,7 @@ func (x *GetProgressRequest) ProtoReflect() protoreflect.Message {
// Deprecated: Use GetProgressRequest.ProtoReflect.Descriptor instead. // Deprecated: Use GetProgressRequest.ProtoReflect.Descriptor instead.
func (*GetProgressRequest) Descriptor() ([]byte, []int) { func (*GetProgressRequest) Descriptor() ([]byte, []int) {
return file_activity_proto_rawDescGZIP(), []int{11} return file_activity_proto_rawDescGZIP(), []int{15}
} }
func (x *GetProgressRequest) GetActivityId() int64 { func (x *GetProgressRequest) GetActivityId() int64 {
@ -1035,7 +1311,7 @@ type GetProgressResponse struct {
func (x *GetProgressResponse) Reset() { func (x *GetProgressResponse) Reset() {
*x = GetProgressResponse{} *x = GetProgressResponse{}
mi := &file_activity_proto_msgTypes[12] mi := &file_activity_proto_msgTypes[16]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
} }
@ -1047,7 +1323,7 @@ func (x *GetProgressResponse) String() string {
func (*GetProgressResponse) ProtoMessage() {} func (*GetProgressResponse) ProtoMessage() {}
func (x *GetProgressResponse) ProtoReflect() protoreflect.Message { func (x *GetProgressResponse) ProtoReflect() protoreflect.Message {
mi := &file_activity_proto_msgTypes[12] mi := &file_activity_proto_msgTypes[16]
if x != nil { if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
@ -1060,7 +1336,7 @@ func (x *GetProgressResponse) ProtoReflect() protoreflect.Message {
// Deprecated: Use GetProgressResponse.ProtoReflect.Descriptor instead. // Deprecated: Use GetProgressResponse.ProtoReflect.Descriptor instead.
func (*GetProgressResponse) Descriptor() ([]byte, []int) { func (*GetProgressResponse) Descriptor() ([]byte, []int) {
return file_activity_proto_rawDescGZIP(), []int{12} return file_activity_proto_rawDescGZIP(), []int{16}
} }
func (x *GetProgressResponse) GetBase() *common.BaseResponse { func (x *GetProgressResponse) GetBase() *common.BaseResponse {
@ -1130,7 +1406,7 @@ type MintingActivity struct {
func (x *MintingActivity) Reset() { func (x *MintingActivity) Reset() {
*x = MintingActivity{} *x = MintingActivity{}
mi := &file_activity_proto_msgTypes[13] mi := &file_activity_proto_msgTypes[17]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
} }
@ -1142,7 +1418,7 @@ func (x *MintingActivity) String() string {
func (*MintingActivity) ProtoMessage() {} func (*MintingActivity) ProtoMessage() {}
func (x *MintingActivity) ProtoReflect() protoreflect.Message { func (x *MintingActivity) ProtoReflect() protoreflect.Message {
mi := &file_activity_proto_msgTypes[13] mi := &file_activity_proto_msgTypes[17]
if x != nil { if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
@ -1155,7 +1431,7 @@ func (x *MintingActivity) ProtoReflect() protoreflect.Message {
// Deprecated: Use MintingActivity.ProtoReflect.Descriptor instead. // Deprecated: Use MintingActivity.ProtoReflect.Descriptor instead.
func (*MintingActivity) Descriptor() ([]byte, []int) { func (*MintingActivity) Descriptor() ([]byte, []int) {
return file_activity_proto_rawDescGZIP(), []int{13} return file_activity_proto_rawDescGZIP(), []int{17}
} }
func (x *MintingActivity) GetId() int64 { func (x *MintingActivity) GetId() int64 {
@ -1233,7 +1509,7 @@ type GetMintingActivitiesRequest struct {
func (x *GetMintingActivitiesRequest) Reset() { func (x *GetMintingActivitiesRequest) Reset() {
*x = GetMintingActivitiesRequest{} *x = GetMintingActivitiesRequest{}
mi := &file_activity_proto_msgTypes[14] mi := &file_activity_proto_msgTypes[18]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
} }
@ -1245,7 +1521,7 @@ func (x *GetMintingActivitiesRequest) String() string {
func (*GetMintingActivitiesRequest) ProtoMessage() {} func (*GetMintingActivitiesRequest) ProtoMessage() {}
func (x *GetMintingActivitiesRequest) ProtoReflect() protoreflect.Message { func (x *GetMintingActivitiesRequest) ProtoReflect() protoreflect.Message {
mi := &file_activity_proto_msgTypes[14] mi := &file_activity_proto_msgTypes[18]
if x != nil { if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
@ -1258,7 +1534,7 @@ func (x *GetMintingActivitiesRequest) ProtoReflect() protoreflect.Message {
// Deprecated: Use GetMintingActivitiesRequest.ProtoReflect.Descriptor instead. // Deprecated: Use GetMintingActivitiesRequest.ProtoReflect.Descriptor instead.
func (*GetMintingActivitiesRequest) Descriptor() ([]byte, []int) { func (*GetMintingActivitiesRequest) Descriptor() ([]byte, []int) {
return file_activity_proto_rawDescGZIP(), []int{14} return file_activity_proto_rawDescGZIP(), []int{18}
} }
func (x *GetMintingActivitiesRequest) GetStarId() int64 { func (x *GetMintingActivitiesRequest) GetStarId() int64 {
@ -1296,7 +1572,7 @@ type GetMintingActivitiesResponse struct {
func (x *GetMintingActivitiesResponse) Reset() { func (x *GetMintingActivitiesResponse) Reset() {
*x = GetMintingActivitiesResponse{} *x = GetMintingActivitiesResponse{}
mi := &file_activity_proto_msgTypes[15] mi := &file_activity_proto_msgTypes[19]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
} }
@ -1308,7 +1584,7 @@ func (x *GetMintingActivitiesResponse) String() string {
func (*GetMintingActivitiesResponse) ProtoMessage() {} func (*GetMintingActivitiesResponse) ProtoMessage() {}
func (x *GetMintingActivitiesResponse) ProtoReflect() protoreflect.Message { func (x *GetMintingActivitiesResponse) ProtoReflect() protoreflect.Message {
mi := &file_activity_proto_msgTypes[15] mi := &file_activity_proto_msgTypes[19]
if x != nil { if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
@ -1321,7 +1597,7 @@ func (x *GetMintingActivitiesResponse) ProtoReflect() protoreflect.Message {
// Deprecated: Use GetMintingActivitiesResponse.ProtoReflect.Descriptor instead. // Deprecated: Use GetMintingActivitiesResponse.ProtoReflect.Descriptor instead.
func (*GetMintingActivitiesResponse) Descriptor() ([]byte, []int) { func (*GetMintingActivitiesResponse) Descriptor() ([]byte, []int) {
return file_activity_proto_rawDescGZIP(), []int{15} return file_activity_proto_rawDescGZIP(), []int{19}
} }
func (x *GetMintingActivitiesResponse) GetBase() *common.BaseResponse { func (x *GetMintingActivitiesResponse) GetBase() *common.BaseResponse {
@ -1372,7 +1648,7 @@ type GetLatestContributionsRequest struct {
func (x *GetLatestContributionsRequest) Reset() { func (x *GetLatestContributionsRequest) Reset() {
*x = GetLatestContributionsRequest{} *x = GetLatestContributionsRequest{}
mi := &file_activity_proto_msgTypes[16] mi := &file_activity_proto_msgTypes[20]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
} }
@ -1384,7 +1660,7 @@ func (x *GetLatestContributionsRequest) String() string {
func (*GetLatestContributionsRequest) ProtoMessage() {} func (*GetLatestContributionsRequest) ProtoMessage() {}
func (x *GetLatestContributionsRequest) ProtoReflect() protoreflect.Message { func (x *GetLatestContributionsRequest) ProtoReflect() protoreflect.Message {
mi := &file_activity_proto_msgTypes[16] mi := &file_activity_proto_msgTypes[20]
if x != nil { if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
@ -1397,7 +1673,7 @@ func (x *GetLatestContributionsRequest) ProtoReflect() protoreflect.Message {
// Deprecated: Use GetLatestContributionsRequest.ProtoReflect.Descriptor instead. // Deprecated: Use GetLatestContributionsRequest.ProtoReflect.Descriptor instead.
func (*GetLatestContributionsRequest) Descriptor() ([]byte, []int) { func (*GetLatestContributionsRequest) Descriptor() ([]byte, []int) {
return file_activity_proto_rawDescGZIP(), []int{16} return file_activity_proto_rawDescGZIP(), []int{20}
} }
func (x *GetLatestContributionsRequest) GetActivityId() int64 { func (x *GetLatestContributionsRequest) GetActivityId() int64 {
@ -1449,7 +1725,7 @@ type ContributionRecord struct {
func (x *ContributionRecord) Reset() { func (x *ContributionRecord) Reset() {
*x = ContributionRecord{} *x = ContributionRecord{}
mi := &file_activity_proto_msgTypes[17] mi := &file_activity_proto_msgTypes[21]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
} }
@ -1461,7 +1737,7 @@ func (x *ContributionRecord) String() string {
func (*ContributionRecord) ProtoMessage() {} func (*ContributionRecord) ProtoMessage() {}
func (x *ContributionRecord) ProtoReflect() protoreflect.Message { func (x *ContributionRecord) ProtoReflect() protoreflect.Message {
mi := &file_activity_proto_msgTypes[17] mi := &file_activity_proto_msgTypes[21]
if x != nil { if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
@ -1474,7 +1750,7 @@ func (x *ContributionRecord) ProtoReflect() protoreflect.Message {
// Deprecated: Use ContributionRecord.ProtoReflect.Descriptor instead. // Deprecated: Use ContributionRecord.ProtoReflect.Descriptor instead.
func (*ContributionRecord) Descriptor() ([]byte, []int) { func (*ContributionRecord) Descriptor() ([]byte, []int) {
return file_activity_proto_rawDescGZIP(), []int{17} return file_activity_proto_rawDescGZIP(), []int{21}
} }
func (x *ContributionRecord) GetId() int64 { func (x *ContributionRecord) GetId() int64 {
@ -1572,7 +1848,7 @@ type GetLatestContributionsResponse struct {
func (x *GetLatestContributionsResponse) Reset() { func (x *GetLatestContributionsResponse) Reset() {
*x = GetLatestContributionsResponse{} *x = GetLatestContributionsResponse{}
mi := &file_activity_proto_msgTypes[18] mi := &file_activity_proto_msgTypes[22]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
} }
@ -1584,7 +1860,7 @@ func (x *GetLatestContributionsResponse) String() string {
func (*GetLatestContributionsResponse) ProtoMessage() {} func (*GetLatestContributionsResponse) ProtoMessage() {}
func (x *GetLatestContributionsResponse) ProtoReflect() protoreflect.Message { func (x *GetLatestContributionsResponse) ProtoReflect() protoreflect.Message {
mi := &file_activity_proto_msgTypes[18] mi := &file_activity_proto_msgTypes[22]
if x != nil { if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
@ -1597,7 +1873,7 @@ func (x *GetLatestContributionsResponse) ProtoReflect() protoreflect.Message {
// Deprecated: Use GetLatestContributionsResponse.ProtoReflect.Descriptor instead. // Deprecated: Use GetLatestContributionsResponse.ProtoReflect.Descriptor instead.
func (*GetLatestContributionsResponse) Descriptor() ([]byte, []int) { func (*GetLatestContributionsResponse) Descriptor() ([]byte, []int) {
return file_activity_proto_rawDescGZIP(), []int{18} return file_activity_proto_rawDescGZIP(), []int{22}
} }
func (x *GetLatestContributionsResponse) GetBase() *common.BaseResponse { func (x *GetLatestContributionsResponse) GetBase() *common.BaseResponse {
@ -1663,7 +1939,29 @@ const file_activity_proto_rawDesc = "" +
"\x13total_crystal_spent\x18\x02 \x01(\x03R\x11totalCrystalSpent\x12-\n" + "\x13total_crystal_spent\x18\x02 \x01(\x03R\x11totalCrystalSpent\x12-\n" +
"\x12total_contribution\x18\x03 \x01(\x03R\x11totalContribution\x12)\n" + "\x12total_contribution\x18\x03 \x01(\x03R\x11totalContribution\x12)\n" +
"\x10current_progress\x18\x04 \x01(\x03R\x0fcurrentProgress\x12+\n" + "\x10current_progress\x18\x04 \x01(\x03R\x0fcurrentProgress\x12+\n" +
"\x11remaining_balance\x18\x05 \x01(\x03R\x10remainingBalance\"\xa0\x01\n" + "\x11remaining_balance\x18\x05 \x01(\x03R\x10remainingBalance\"G\n" +
"\fPurchaseItem\x12\x1b\n" +
"\titem_type\x18\x01 \x01(\tR\bitemType\x12\x1a\n" +
"\bquantity\x18\x02 \x01(\x05R\bquantity\"\xa3\x01\n" +
"\x18BatchPurchaseItemRequest\x12\x1f\n" +
"\vactivity_id\x18\x01 \x01(\x03R\n" +
"activityId\x124\n" +
"\x05items\x18\x02 \x03(\v2\x1e.topfans.activity.PurchaseItemR\x05items\x12\x17\n" +
"\astar_id\x18\x03 \x01(\x03R\x06starId\x12\x17\n" +
"\auser_id\x18\x04 \x01(\x03R\x06userId\"\x82\x03\n" +
"\x19BatchPurchaseItemResponse\x120\n" +
"\x04base\x18\x01 \x01(\v2\x1c.topfans.common.BaseResponseR\x04base\x12.\n" +
"\x13total_crystal_spent\x18\x02 \x01(\x03R\x11totalCrystalSpent\x12-\n" +
"\x12total_contribution\x18\x03 \x01(\x03R\x11totalContribution\x12)\n" +
"\x10current_progress\x18\x04 \x01(\x03R\x0fcurrentProgress\x12+\n" +
"\x11remaining_balance\x18\x05 \x01(\x03R\x10remainingBalance\x12#\n" +
"\rsuccess_count\x18\x06 \x01(\x05R\fsuccessCount\x12\x1d\n" +
"\n" +
"fail_count\x18\a \x01(\x05R\tfailCount\x128\n" +
"\x05fails\x18\b \x03(\v2\".topfans.activity.PurchaseFailItemR\x05fails\"G\n" +
"\x10PurchaseFailItem\x12\x1b\n" +
"\titem_type\x18\x01 \x01(\tR\bitemType\x12\x16\n" +
"\x06reason\x18\x02 \x01(\tR\x06reason\"\xa0\x01\n" +
"\x1aContributionRankingRequest\x12\x1f\n" + "\x1aContributionRankingRequest\x12\x1f\n" +
"\vactivity_id\x18\x01 \x01(\x03R\n" + "\vactivity_id\x18\x01 \x01(\x03R\n" +
"activityId\x12\x17\n" + "activityId\x12\x17\n" +
@ -1769,13 +2067,15 @@ const file_activity_proto_rawDesc = "" +
"created_at\x18\f \x01(\x03R\tcreatedAt\"\x92\x01\n" + "created_at\x18\f \x01(\x03R\tcreatedAt\"\x92\x01\n" +
"\x1eGetLatestContributionsResponse\x120\n" + "\x1eGetLatestContributionsResponse\x120\n" +
"\x04base\x18\x01 \x01(\v2\x1c.topfans.common.BaseResponseR\x04base\x12>\n" + "\x04base\x18\x01 \x01(\v2\x1c.topfans.common.BaseResponseR\x04base\x12>\n" +
"\arecords\x18\x02 \x03(\v2$.topfans.activity.ContributionRecordR\arecords2\xce\t\n" + "\arecords\x18\x02 \x03(\v2$.topfans.activity.ContributionRecordR\arecords2\xf9\n" +
"\n" +
"\x0fActivityService\x12\x82\x01\n" + "\x0fActivityService\x12\x82\x01\n" +
"\x0fGetActivityList\x12(.topfans.activity.GetActivityListRequest\x1a).topfans.activity.GetActivityListResponse\"\x1a\x82\xd3\xe4\x93\x02\x14\x12\x12/api/v1/activities\x12y\n" + "\x0fGetActivityList\x12(.topfans.activity.GetActivityListRequest\x1a).topfans.activity.GetActivityListResponse\"\x1a\x82\xd3\xe4\x93\x02\x14\x12\x12/api/v1/activities\x12y\n" +
"\vGetActivity\x12$.topfans.activity.GetProgressRequest\x1a\x1a.topfans.activity.Activity\"(\x82\xd3\xe4\x93\x02\"\x12 /api/v1/activities/{activity_id}\x12\x91\x01\n" + "\vGetActivity\x12$.topfans.activity.GetProgressRequest\x1a\x1a.topfans.activity.Activity\"(\x82\xd3\xe4\x93\x02\"\x12 /api/v1/activities/{activity_id}\x12\x91\x01\n" +
"\x10GetActivityItems\x12$.topfans.activity.GetProgressRequest\x1a'.topfans.activity.ActivityItemsResponse\".\x82\xd3\xe4\x93\x02(\x12&/api/v1/activities/{activity_id}/items\x12\x8d\x01\n" + "\x10GetActivityItems\x12$.topfans.activity.GetProgressRequest\x1a'.topfans.activity.ActivityItemsResponse\".\x82\xd3\xe4\x93\x02(\x12&/api/v1/activities/{activity_id}/items\x12\x8d\x01\n" +
"\vGetProgress\x12$.topfans.activity.GetProgressRequest\x1a%.topfans.activity.GetProgressResponse\"1\x82\xd3\xe4\x93\x02+\x12)/api/v1/activities/{activity_id}/progress\x12\x93\x01\n" + "\vGetProgress\x12$.topfans.activity.GetProgressRequest\x1a%.topfans.activity.GetProgressResponse\"1\x82\xd3\xe4\x93\x02+\x12)/api/v1/activities/{activity_id}/progress\x12\x93\x01\n" +
"\fPurchaseItem\x12%.topfans.activity.PurchaseItemRequest\x1a&.topfans.activity.PurchaseItemResponse\"4\x82\xd3\xe4\x93\x02.:\x01*\")/api/v1/activities/{activity_id}/purchase\x12\xa7\x01\n" + "\fPurchaseItem\x12%.topfans.activity.PurchaseItemRequest\x1a&.topfans.activity.PurchaseItemResponse\"4\x82\xd3\xe4\x93\x02.:\x01*\")/api/v1/activities/{activity_id}/purchase\x12\xa8\x01\n" +
"\x11BatchPurchaseItem\x12*.topfans.activity.BatchPurchaseItemRequest\x1a+.topfans.activity.BatchPurchaseItemResponse\":\x82\xd3\xe4\x93\x024:\x01*\"//api/v1/activities/{activity_id}/batch-purchase\x12\xa7\x01\n" +
"\x16GetContributionRanking\x12,.topfans.activity.ContributionRankingRequest\x1a-.topfans.activity.ContributionRankingResponse\"0\x82\xd3\xe4\x93\x02*\x12(/api/v1/activities/{activity_id}/ranking\x12\x99\x01\n" + "\x16GetContributionRanking\x12,.topfans.activity.ContributionRankingRequest\x1a-.topfans.activity.ContributionRankingResponse\"0\x82\xd3\xe4\x93\x02*\x12(/api/v1/activities/{activity_id}/ranking\x12\x99\x01\n" +
"\x14GetMintingActivities\x12-.topfans.activity.GetMintingActivitiesRequest\x1a..topfans.activity.GetMintingActivitiesResponse\"\"\x82\xd3\xe4\x93\x02\x1c\x12\x1a/api/v1/minting-activities\x12\xba\x01\n" + "\x14GetMintingActivities\x12-.topfans.activity.GetMintingActivitiesRequest\x1a..topfans.activity.GetMintingActivitiesResponse\"\"\x82\xd3\xe4\x93\x02\x1c\x12\x1a/api/v1/minting-activities\x12\xba\x01\n" +
"\x16GetLatestContributions\x12/.topfans.activity.GetLatestContributionsRequest\x1a0.topfans.activity.GetLatestContributionsResponse\"=\x82\xd3\xe4\x93\x027\x125/api/v1/activities/{activity_id}/contributions/latestB8Z6github.com/topfans/backend/pkg/proto/activity;activityb\x06proto3" "\x16GetLatestContributions\x12/.topfans.activity.GetLatestContributionsRequest\x1a0.topfans.activity.GetLatestContributionsResponse\"=\x82\xd3\xe4\x93\x027\x125/api/v1/activities/{activity_id}/contributions/latestB8Z6github.com/topfans/backend/pkg/proto/activity;activityb\x06proto3"
@ -1792,64 +2092,73 @@ func file_activity_proto_rawDescGZIP() []byte {
return file_activity_proto_rawDescData return file_activity_proto_rawDescData
} }
var file_activity_proto_msgTypes = make([]protoimpl.MessageInfo, 19) var file_activity_proto_msgTypes = make([]protoimpl.MessageInfo, 23)
var file_activity_proto_goTypes = []any{ var file_activity_proto_goTypes = []any{
(*Activity)(nil), // 0: topfans.activity.Activity (*Activity)(nil), // 0: topfans.activity.Activity
(*ActivityItem)(nil), // 1: topfans.activity.ActivityItem (*ActivityItem)(nil), // 1: topfans.activity.ActivityItem
(*ActivityItemsResponse)(nil), // 2: topfans.activity.ActivityItemsResponse (*ActivityItemsResponse)(nil), // 2: topfans.activity.ActivityItemsResponse
(*PurchaseItemRequest)(nil), // 3: topfans.activity.PurchaseItemRequest (*PurchaseItemRequest)(nil), // 3: topfans.activity.PurchaseItemRequest
(*PurchaseItemResponse)(nil), // 4: topfans.activity.PurchaseItemResponse (*PurchaseItemResponse)(nil), // 4: topfans.activity.PurchaseItemResponse
(*ContributionRankingRequest)(nil), // 5: topfans.activity.ContributionRankingRequest (*PurchaseItem)(nil), // 5: topfans.activity.PurchaseItem
(*ContributionRankingItem)(nil), // 6: topfans.activity.ContributionRankingItem (*BatchPurchaseItemRequest)(nil), // 6: topfans.activity.BatchPurchaseItemRequest
(*ContributionRankingResponse)(nil), // 7: topfans.activity.ContributionRankingResponse (*BatchPurchaseItemResponse)(nil), // 7: topfans.activity.BatchPurchaseItemResponse
(*MyContribution)(nil), // 8: topfans.activity.MyContribution (*PurchaseFailItem)(nil), // 8: topfans.activity.PurchaseFailItem
(*GetActivityListRequest)(nil), // 9: topfans.activity.GetActivityListRequest (*ContributionRankingRequest)(nil), // 9: topfans.activity.ContributionRankingRequest
(*GetActivityListResponse)(nil), // 10: topfans.activity.GetActivityListResponse (*ContributionRankingItem)(nil), // 10: topfans.activity.ContributionRankingItem
(*GetProgressRequest)(nil), // 11: topfans.activity.GetProgressRequest (*ContributionRankingResponse)(nil), // 11: topfans.activity.ContributionRankingResponse
(*GetProgressResponse)(nil), // 12: topfans.activity.GetProgressResponse (*MyContribution)(nil), // 12: topfans.activity.MyContribution
(*MintingActivity)(nil), // 13: topfans.activity.MintingActivity (*GetActivityListRequest)(nil), // 13: topfans.activity.GetActivityListRequest
(*GetMintingActivitiesRequest)(nil), // 14: topfans.activity.GetMintingActivitiesRequest (*GetActivityListResponse)(nil), // 14: topfans.activity.GetActivityListResponse
(*GetMintingActivitiesResponse)(nil), // 15: topfans.activity.GetMintingActivitiesResponse (*GetProgressRequest)(nil), // 15: topfans.activity.GetProgressRequest
(*GetLatestContributionsRequest)(nil), // 16: topfans.activity.GetLatestContributionsRequest (*GetProgressResponse)(nil), // 16: topfans.activity.GetProgressResponse
(*ContributionRecord)(nil), // 17: topfans.activity.ContributionRecord (*MintingActivity)(nil), // 17: topfans.activity.MintingActivity
(*GetLatestContributionsResponse)(nil), // 18: topfans.activity.GetLatestContributionsResponse (*GetMintingActivitiesRequest)(nil), // 18: topfans.activity.GetMintingActivitiesRequest
(*common.BaseResponse)(nil), // 19: topfans.common.BaseResponse (*GetMintingActivitiesResponse)(nil), // 19: topfans.activity.GetMintingActivitiesResponse
(*GetLatestContributionsRequest)(nil), // 20: topfans.activity.GetLatestContributionsRequest
(*ContributionRecord)(nil), // 21: topfans.activity.ContributionRecord
(*GetLatestContributionsResponse)(nil), // 22: topfans.activity.GetLatestContributionsResponse
(*common.BaseResponse)(nil), // 23: topfans.common.BaseResponse
} }
var file_activity_proto_depIdxs = []int32{ var file_activity_proto_depIdxs = []int32{
1, // 0: topfans.activity.Activity.items:type_name -> topfans.activity.ActivityItem 1, // 0: topfans.activity.Activity.items:type_name -> topfans.activity.ActivityItem
1, // 1: topfans.activity.ActivityItemsResponse.items:type_name -> topfans.activity.ActivityItem 1, // 1: topfans.activity.ActivityItemsResponse.items:type_name -> topfans.activity.ActivityItem
19, // 2: topfans.activity.PurchaseItemResponse.base:type_name -> topfans.common.BaseResponse 23, // 2: topfans.activity.PurchaseItemResponse.base:type_name -> topfans.common.BaseResponse
19, // 3: topfans.activity.ContributionRankingResponse.base:type_name -> topfans.common.BaseResponse 5, // 3: topfans.activity.BatchPurchaseItemRequest.items:type_name -> topfans.activity.PurchaseItem
6, // 4: topfans.activity.ContributionRankingResponse.items:type_name -> topfans.activity.ContributionRankingItem 23, // 4: topfans.activity.BatchPurchaseItemResponse.base:type_name -> topfans.common.BaseResponse
8, // 5: topfans.activity.ContributionRankingResponse.my_contribution:type_name -> topfans.activity.MyContribution 8, // 5: topfans.activity.BatchPurchaseItemResponse.fails:type_name -> topfans.activity.PurchaseFailItem
19, // 6: topfans.activity.GetActivityListResponse.base:type_name -> topfans.common.BaseResponse 23, // 6: topfans.activity.ContributionRankingResponse.base:type_name -> topfans.common.BaseResponse
0, // 7: topfans.activity.GetActivityListResponse.activities:type_name -> topfans.activity.Activity 10, // 7: topfans.activity.ContributionRankingResponse.items:type_name -> topfans.activity.ContributionRankingItem
19, // 8: topfans.activity.GetProgressResponse.base:type_name -> topfans.common.BaseResponse 12, // 8: topfans.activity.ContributionRankingResponse.my_contribution:type_name -> topfans.activity.MyContribution
19, // 9: topfans.activity.GetMintingActivitiesResponse.base:type_name -> topfans.common.BaseResponse 23, // 9: topfans.activity.GetActivityListResponse.base:type_name -> topfans.common.BaseResponse
13, // 10: topfans.activity.GetMintingActivitiesResponse.activities:type_name -> topfans.activity.MintingActivity 0, // 10: topfans.activity.GetActivityListResponse.activities:type_name -> topfans.activity.Activity
19, // 11: topfans.activity.GetLatestContributionsResponse.base:type_name -> topfans.common.BaseResponse 23, // 11: topfans.activity.GetProgressResponse.base:type_name -> topfans.common.BaseResponse
17, // 12: topfans.activity.GetLatestContributionsResponse.records:type_name -> topfans.activity.ContributionRecord 23, // 12: topfans.activity.GetMintingActivitiesResponse.base:type_name -> topfans.common.BaseResponse
9, // 13: topfans.activity.ActivityService.GetActivityList:input_type -> topfans.activity.GetActivityListRequest 17, // 13: topfans.activity.GetMintingActivitiesResponse.activities:type_name -> topfans.activity.MintingActivity
11, // 14: topfans.activity.ActivityService.GetActivity:input_type -> topfans.activity.GetProgressRequest 23, // 14: topfans.activity.GetLatestContributionsResponse.base:type_name -> topfans.common.BaseResponse
11, // 15: topfans.activity.ActivityService.GetActivityItems:input_type -> topfans.activity.GetProgressRequest 21, // 15: topfans.activity.GetLatestContributionsResponse.records:type_name -> topfans.activity.ContributionRecord
11, // 16: topfans.activity.ActivityService.GetProgress:input_type -> topfans.activity.GetProgressRequest 13, // 16: topfans.activity.ActivityService.GetActivityList:input_type -> topfans.activity.GetActivityListRequest
3, // 17: topfans.activity.ActivityService.PurchaseItem:input_type -> topfans.activity.PurchaseItemRequest 15, // 17: topfans.activity.ActivityService.GetActivity:input_type -> topfans.activity.GetProgressRequest
5, // 18: topfans.activity.ActivityService.GetContributionRanking:input_type -> topfans.activity.ContributionRankingRequest 15, // 18: topfans.activity.ActivityService.GetActivityItems:input_type -> topfans.activity.GetProgressRequest
14, // 19: topfans.activity.ActivityService.GetMintingActivities:input_type -> topfans.activity.GetMintingActivitiesRequest 15, // 19: topfans.activity.ActivityService.GetProgress:input_type -> topfans.activity.GetProgressRequest
16, // 20: topfans.activity.ActivityService.GetLatestContributions:input_type -> topfans.activity.GetLatestContributionsRequest 3, // 20: topfans.activity.ActivityService.PurchaseItem:input_type -> topfans.activity.PurchaseItemRequest
10, // 21: topfans.activity.ActivityService.GetActivityList:output_type -> topfans.activity.GetActivityListResponse 6, // 21: topfans.activity.ActivityService.BatchPurchaseItem:input_type -> topfans.activity.BatchPurchaseItemRequest
0, // 22: topfans.activity.ActivityService.GetActivity:output_type -> topfans.activity.Activity 9, // 22: topfans.activity.ActivityService.GetContributionRanking:input_type -> topfans.activity.ContributionRankingRequest
2, // 23: topfans.activity.ActivityService.GetActivityItems:output_type -> topfans.activity.ActivityItemsResponse 18, // 23: topfans.activity.ActivityService.GetMintingActivities:input_type -> topfans.activity.GetMintingActivitiesRequest
12, // 24: topfans.activity.ActivityService.GetProgress:output_type -> topfans.activity.GetProgressResponse 20, // 24: topfans.activity.ActivityService.GetLatestContributions:input_type -> topfans.activity.GetLatestContributionsRequest
4, // 25: topfans.activity.ActivityService.PurchaseItem:output_type -> topfans.activity.PurchaseItemResponse 14, // 25: topfans.activity.ActivityService.GetActivityList:output_type -> topfans.activity.GetActivityListResponse
7, // 26: topfans.activity.ActivityService.GetContributionRanking:output_type -> topfans.activity.ContributionRankingResponse 0, // 26: topfans.activity.ActivityService.GetActivity:output_type -> topfans.activity.Activity
15, // 27: topfans.activity.ActivityService.GetMintingActivities:output_type -> topfans.activity.GetMintingActivitiesResponse 2, // 27: topfans.activity.ActivityService.GetActivityItems:output_type -> topfans.activity.ActivityItemsResponse
18, // 28: topfans.activity.ActivityService.GetLatestContributions:output_type -> topfans.activity.GetLatestContributionsResponse 16, // 28: topfans.activity.ActivityService.GetProgress:output_type -> topfans.activity.GetProgressResponse
21, // [21:29] is the sub-list for method output_type 4, // 29: topfans.activity.ActivityService.PurchaseItem:output_type -> topfans.activity.PurchaseItemResponse
13, // [13:21] is the sub-list for method input_type 7, // 30: topfans.activity.ActivityService.BatchPurchaseItem:output_type -> topfans.activity.BatchPurchaseItemResponse
13, // [13:13] is the sub-list for extension type_name 11, // 31: topfans.activity.ActivityService.GetContributionRanking:output_type -> topfans.activity.ContributionRankingResponse
13, // [13:13] is the sub-list for extension extendee 19, // 32: topfans.activity.ActivityService.GetMintingActivities:output_type -> topfans.activity.GetMintingActivitiesResponse
0, // [0:13] is the sub-list for field type_name 22, // 33: topfans.activity.ActivityService.GetLatestContributions:output_type -> topfans.activity.GetLatestContributionsResponse
25, // [25:34] is the sub-list for method output_type
16, // [16:25] is the sub-list for method input_type
16, // [16:16] is the sub-list for extension type_name
16, // [16:16] is the sub-list for extension extendee
0, // [0:16] is the sub-list for field type_name
} }
func init() { file_activity_proto_init() } func init() { file_activity_proto_init() }
@ -1863,7 +2172,7 @@ func file_activity_proto_init() {
GoPackagePath: reflect.TypeOf(x{}).PkgPath(), GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: unsafe.Slice(unsafe.StringData(file_activity_proto_rawDesc), len(file_activity_proto_rawDesc)), RawDescriptor: unsafe.Slice(unsafe.StringData(file_activity_proto_rawDesc), len(file_activity_proto_rawDesc)),
NumEnums: 0, NumEnums: 0,
NumMessages: 19, NumMessages: 23,
NumExtensions: 0, NumExtensions: 0,
NumServices: 1, NumServices: 1,
}, },

View File

@ -46,6 +46,8 @@ const (
ActivityServiceGetProgressProcedure = "/topfans.activity.ActivityService/GetProgress" ActivityServiceGetProgressProcedure = "/topfans.activity.ActivityService/GetProgress"
// ActivityServicePurchaseItemProcedure is the fully-qualified name of the ActivityService's PurchaseItem RPC. // ActivityServicePurchaseItemProcedure is the fully-qualified name of the ActivityService's PurchaseItem RPC.
ActivityServicePurchaseItemProcedure = "/topfans.activity.ActivityService/PurchaseItem" ActivityServicePurchaseItemProcedure = "/topfans.activity.ActivityService/PurchaseItem"
// ActivityServiceBatchPurchaseItemProcedure is the fully-qualified name of the ActivityService's BatchPurchaseItem RPC.
ActivityServiceBatchPurchaseItemProcedure = "/topfans.activity.ActivityService/BatchPurchaseItem"
// ActivityServiceGetContributionRankingProcedure is the fully-qualified name of the ActivityService's GetContributionRanking RPC. // ActivityServiceGetContributionRankingProcedure is the fully-qualified name of the ActivityService's GetContributionRanking RPC.
ActivityServiceGetContributionRankingProcedure = "/topfans.activity.ActivityService/GetContributionRanking" ActivityServiceGetContributionRankingProcedure = "/topfans.activity.ActivityService/GetContributionRanking"
// ActivityServiceGetMintingActivitiesProcedure is the fully-qualified name of the ActivityService's GetMintingActivities RPC. // ActivityServiceGetMintingActivitiesProcedure is the fully-qualified name of the ActivityService's GetMintingActivities RPC.
@ -65,6 +67,7 @@ type ActivityService interface {
GetActivityItems(ctx context.Context, req *GetProgressRequest, opts ...client.CallOption) (*ActivityItemsResponse, error) GetActivityItems(ctx context.Context, req *GetProgressRequest, opts ...client.CallOption) (*ActivityItemsResponse, error)
GetProgress(ctx context.Context, req *GetProgressRequest, opts ...client.CallOption) (*GetProgressResponse, error) GetProgress(ctx context.Context, req *GetProgressRequest, opts ...client.CallOption) (*GetProgressResponse, error)
PurchaseItem(ctx context.Context, req *PurchaseItemRequest, opts ...client.CallOption) (*PurchaseItemResponse, error) PurchaseItem(ctx context.Context, req *PurchaseItemRequest, opts ...client.CallOption) (*PurchaseItemResponse, error)
BatchPurchaseItem(ctx context.Context, req *BatchPurchaseItemRequest, opts ...client.CallOption) (*BatchPurchaseItemResponse, error)
GetContributionRanking(ctx context.Context, req *ContributionRankingRequest, opts ...client.CallOption) (*ContributionRankingResponse, error) GetContributionRanking(ctx context.Context, req *ContributionRankingRequest, opts ...client.CallOption) (*ContributionRankingResponse, error)
GetMintingActivities(ctx context.Context, req *GetMintingActivitiesRequest, opts ...client.CallOption) (*GetMintingActivitiesResponse, error) GetMintingActivities(ctx context.Context, req *GetMintingActivitiesRequest, opts ...client.CallOption) (*GetMintingActivitiesResponse, error)
GetLatestContributions(ctx context.Context, req *GetLatestContributionsRequest, opts ...client.CallOption) (*GetLatestContributionsResponse, error) GetLatestContributions(ctx context.Context, req *GetLatestContributionsRequest, opts ...client.CallOption) (*GetLatestContributionsResponse, error)
@ -130,6 +133,14 @@ func (c *ActivityServiceImpl) PurchaseItem(ctx context.Context, req *PurchaseIte
return resp, nil return resp, nil
} }
func (c *ActivityServiceImpl) BatchPurchaseItem(ctx context.Context, req *BatchPurchaseItemRequest, opts ...client.CallOption) (*BatchPurchaseItemResponse, error) {
resp := new(BatchPurchaseItemResponse)
if err := c.conn.CallUnary(ctx, []interface{}{req}, resp, "BatchPurchaseItem", opts...); err != nil {
return nil, err
}
return resp, nil
}
func (c *ActivityServiceImpl) GetContributionRanking(ctx context.Context, req *ContributionRankingRequest, opts ...client.CallOption) (*ContributionRankingResponse, error) { func (c *ActivityServiceImpl) GetContributionRanking(ctx context.Context, req *ContributionRankingRequest, opts ...client.CallOption) (*ContributionRankingResponse, error) {
resp := new(ContributionRankingResponse) resp := new(ContributionRankingResponse)
if err := c.conn.CallUnary(ctx, []interface{}{req}, resp, "GetContributionRanking", opts...); err != nil { if err := c.conn.CallUnary(ctx, []interface{}{req}, resp, "GetContributionRanking", opts...); err != nil {
@ -156,7 +167,7 @@ func (c *ActivityServiceImpl) GetLatestContributions(ctx context.Context, req *G
var ActivityService_ClientInfo = client.ClientInfo{ var ActivityService_ClientInfo = client.ClientInfo{
InterfaceName: "topfans.activity.ActivityService", InterfaceName: "topfans.activity.ActivityService",
MethodNames: []string{"GetActivityList", "GetActivity", "GetActivityItems", "GetProgress", "PurchaseItem", "GetContributionRanking", "GetMintingActivities", "GetLatestContributions"}, MethodNames: []string{"GetActivityList", "GetActivity", "GetActivityItems", "GetProgress", "PurchaseItem", "BatchPurchaseItem", "GetContributionRanking", "GetMintingActivities", "GetLatestContributions"},
ConnectionInjectFunc: func(dubboCliRaw interface{}, conn *client.Connection) { ConnectionInjectFunc: func(dubboCliRaw interface{}, conn *client.Connection) {
dubboCli := dubboCliRaw.(*ActivityServiceImpl) dubboCli := dubboCliRaw.(*ActivityServiceImpl)
dubboCli.conn = conn dubboCli.conn = conn
@ -170,6 +181,7 @@ type ActivityServiceHandler interface {
GetActivityItems(context.Context, *GetProgressRequest) (*ActivityItemsResponse, error) GetActivityItems(context.Context, *GetProgressRequest) (*ActivityItemsResponse, error)
GetProgress(context.Context, *GetProgressRequest) (*GetProgressResponse, error) GetProgress(context.Context, *GetProgressRequest) (*GetProgressResponse, error)
PurchaseItem(context.Context, *PurchaseItemRequest) (*PurchaseItemResponse, error) PurchaseItem(context.Context, *PurchaseItemRequest) (*PurchaseItemResponse, error)
BatchPurchaseItem(context.Context, *BatchPurchaseItemRequest) (*BatchPurchaseItemResponse, error)
GetContributionRanking(context.Context, *ContributionRankingRequest) (*ContributionRankingResponse, error) GetContributionRanking(context.Context, *ContributionRankingRequest) (*ContributionRankingResponse, error)
GetMintingActivities(context.Context, *GetMintingActivitiesRequest) (*GetMintingActivitiesResponse, error) GetMintingActivities(context.Context, *GetMintingActivitiesRequest) (*GetMintingActivitiesResponse, error)
GetLatestContributions(context.Context, *GetLatestContributionsRequest) (*GetLatestContributionsResponse, error) GetLatestContributions(context.Context, *GetLatestContributionsRequest) (*GetLatestContributionsResponse, error)
@ -262,6 +274,21 @@ var ActivityService_ServiceInfo = server.ServiceInfo{
return triple_protocol.NewResponse(res), nil return triple_protocol.NewResponse(res), nil
}, },
}, },
{
Name: "BatchPurchaseItem",
Type: constant.CallUnary,
ReqInitFunc: func() interface{} {
return new(BatchPurchaseItemRequest)
},
MethodFunc: func(ctx context.Context, args []interface{}, handler interface{}) (interface{}, error) {
req := args[0].(*BatchPurchaseItemRequest)
res, err := handler.(ActivityServiceHandler).BatchPurchaseItem(ctx, req)
if err != nil {
return nil, err
}
return triple_protocol.NewResponse(res), nil
},
},
{ {
Name: "GetContributionRanking", Name: "GetContributionRanking",
Type: constant.CallUnary, Type: constant.CallUnary,

View File

@ -951,7 +951,7 @@ type EstimateMintCostResponse struct {
CurrentBalance int64 `protobuf:"varint,3,opt,name=current_balance,json=currentBalance,proto3" json:"current_balance,omitempty"` // 当前余额(铸造前) CurrentBalance int64 `protobuf:"varint,3,opt,name=current_balance,json=currentBalance,proto3" json:"current_balance,omitempty"` // 当前余额(铸造前)
BalanceAfter int64 `protobuf:"varint,4,opt,name=balance_after,json=balanceAfter,proto3" json:"balance_after,omitempty"` // 铸造后余额 BalanceAfter int64 `protobuf:"varint,4,opt,name=balance_after,json=balanceAfter,proto3" json:"balance_after,omitempty"` // 铸造后余额
MintCount int32 `protobuf:"varint,5,opt,name=mint_count,json=mintCount,proto3" json:"mint_count,omitempty"` // 本次是第几次铸造 MintCount int32 `protobuf:"varint,5,opt,name=mint_count,json=mintCount,proto3" json:"mint_count,omitempty"` // 本次是第几次铸造
NextTierHint string `protobuf:"bytes,6,opt,name=next_tier_hint,json=nextTierHint,proto3" json:"next_tier_hint,omitempty"` // 下一阶梯提示 NextTierCost int64 `protobuf:"varint,6,opt,name=next_tier_cost,json=nextTierCost,proto3" json:"next_tier_cost,omitempty"` // 下一阶梯费用
unknownFields protoimpl.UnknownFields unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache sizeCache protoimpl.SizeCache
} }
@ -1021,11 +1021,11 @@ func (x *EstimateMintCostResponse) GetMintCount() int32 {
return 0 return 0
} }
func (x *EstimateMintCostResponse) GetNextTierHint() string { func (x *EstimateMintCostResponse) GetNextTierCost() int64 {
if x != nil { if x != nil {
return x.NextTierHint return x.NextTierCost
} }
return "" return 0
} }
// 获取我的藏品列表请求 // 获取我的藏品列表请求
@ -3736,7 +3736,7 @@ const file_asset_proto_rawDesc = "" +
"\rbalance_after\x18\x04 \x01(\x03R\fbalanceAfter\x12\x1d\n" + "\rbalance_after\x18\x04 \x01(\x03R\fbalanceAfter\x12\x1d\n" +
"\n" + "\n" +
"mint_count\x18\x05 \x01(\x05R\tmintCount\x12$\n" + "mint_count\x18\x05 \x01(\x05R\tmintCount\x12$\n" +
"\x0enext_tier_hint\x18\x06 \x01(\tR\fnextTierHint\"\x8b\x01\n" + "\x0enext_tier_cost\x18\x06 \x01(\x03R\fnextTierCost\"\x8b\x01\n" +
"\x12GetMyAssetsRequest\x12\x12\n" + "\x12GetMyAssetsRequest\x12\x12\n" +
"\x04page\x18\x01 \x01(\x05R\x04page\x12\x1b\n" + "\x04page\x18\x01 \x01(\x05R\x04page\x12\x1b\n" +
"\tpage_size\x18\x02 \x01(\x05R\bpageSize\x12\x16\n" + "\tpage_size\x18\x02 \x01(\x05R\bpageSize\x12\x16\n" +

View File

@ -42,6 +42,8 @@ const (
AssetServicePreCreateMintOrderProcedure = "/topfans.asset.AssetService/PreCreateMintOrder" AssetServicePreCreateMintOrderProcedure = "/topfans.asset.AssetService/PreCreateMintOrder"
// AssetServiceCreateMintOrderProcedure is the fully-qualified name of the AssetService's CreateMintOrder RPC. // AssetServiceCreateMintOrderProcedure is the fully-qualified name of the AssetService's CreateMintOrder RPC.
AssetServiceCreateMintOrderProcedure = "/topfans.asset.AssetService/CreateMintOrder" AssetServiceCreateMintOrderProcedure = "/topfans.asset.AssetService/CreateMintOrder"
// AssetServiceEstimateMintCostProcedure is the fully-qualified name of the AssetService's EstimateMintCost RPC.
AssetServiceEstimateMintCostProcedure = "/topfans.asset.AssetService/EstimateMintCost"
// AssetServiceGetMyAssetsProcedure is the fully-qualified name of the AssetService's GetMyAssets RPC. // AssetServiceGetMyAssetsProcedure is the fully-qualified name of the AssetService's GetMyAssets RPC.
AssetServiceGetMyAssetsProcedure = "/topfans.asset.AssetService/GetMyAssets" AssetServiceGetMyAssetsProcedure = "/topfans.asset.AssetService/GetMyAssets"
// AssetServiceGetAssetProcedure is the fully-qualified name of the AssetService's GetAsset RPC. // AssetServiceGetAssetProcedure is the fully-qualified name of the AssetService's GetAsset RPC.
@ -64,6 +66,16 @@ const (
AssetServiceGetAssetLikesProcedure = "/topfans.asset.AssetService/GetAssetLikes" AssetServiceGetAssetLikesProcedure = "/topfans.asset.AssetService/GetAssetLikes"
// AssetServiceClearAssetLikeRecordsProcedure is the fully-qualified name of the AssetService's ClearAssetLikeRecords RPC. // AssetServiceClearAssetLikeRecordsProcedure is the fully-qualified name of the AssetService's ClearAssetLikeRecords RPC.
AssetServiceClearAssetLikeRecordsProcedure = "/topfans.asset.AssetService/ClearAssetLikeRecords" AssetServiceClearAssetLikeRecordsProcedure = "/topfans.asset.AssetService/ClearAssetLikeRecords"
// AssetServiceUploadMaterialProcedure is the fully-qualified name of the AssetService's UploadMaterial RPC.
AssetServiceUploadMaterialProcedure = "/topfans.asset.AssetService/UploadMaterial"
// AssetServiceBindAssetMaterialsProcedure is the fully-qualified name of the AssetService's BindAssetMaterials RPC.
AssetServiceBindAssetMaterialsProcedure = "/topfans.asset.AssetService/BindAssetMaterials"
// AssetServiceGetAssetMaterialsProcedure is the fully-qualified name of the AssetService's GetAssetMaterials RPC.
AssetServiceGetAssetMaterialsProcedure = "/topfans.asset.AssetService/GetAssetMaterials"
// AssetServiceUpdateMaterialLayerOrderProcedure is the fully-qualified name of the AssetService's UpdateMaterialLayerOrder RPC.
AssetServiceUpdateMaterialLayerOrderProcedure = "/topfans.asset.AssetService/UpdateMaterialLayerOrder"
// AssetServiceUnbindAssetMaterialProcedure is the fully-qualified name of the AssetService's UnbindAssetMaterial RPC.
AssetServiceUnbindAssetMaterialProcedure = "/topfans.asset.AssetService/UnbindAssetMaterial"
) )
var ( var (
@ -75,6 +87,7 @@ type AssetService interface {
InitMintOrder(ctx context.Context, req *InitMintOrderRequest, opts ...client.CallOption) (*InitMintOrderResponse, error) InitMintOrder(ctx context.Context, req *InitMintOrderRequest, opts ...client.CallOption) (*InitMintOrderResponse, error)
PreCreateMintOrder(ctx context.Context, req *PreCreateMintOrderRequest, opts ...client.CallOption) (*PreCreateMintOrderResponse, error) PreCreateMintOrder(ctx context.Context, req *PreCreateMintOrderRequest, opts ...client.CallOption) (*PreCreateMintOrderResponse, error)
CreateMintOrder(ctx context.Context, req *CreateMintOrderRequest, opts ...client.CallOption) (*CreateMintOrderResponse, error) CreateMintOrder(ctx context.Context, req *CreateMintOrderRequest, opts ...client.CallOption) (*CreateMintOrderResponse, error)
EstimateMintCost(ctx context.Context, req *EstimateMintCostRequest, opts ...client.CallOption) (*EstimateMintCostResponse, error)
GetMyAssets(ctx context.Context, req *GetMyAssetsRequest, opts ...client.CallOption) (*GetMyAssetsResponse, error) GetMyAssets(ctx context.Context, req *GetMyAssetsRequest, opts ...client.CallOption) (*GetMyAssetsResponse, error)
GetAsset(ctx context.Context, req *GetAssetRequest, opts ...client.CallOption) (*GetAssetResponse, error) GetAsset(ctx context.Context, req *GetAssetRequest, opts ...client.CallOption) (*GetAssetResponse, error)
GetAssetStatus(ctx context.Context, req *GetAssetStatusRequest, opts ...client.CallOption) (*GetAssetStatusResponse, error) GetAssetStatus(ctx context.Context, req *GetAssetStatusRequest, opts ...client.CallOption) (*GetAssetStatusResponse, error)
@ -91,7 +104,6 @@ type AssetService interface {
GetAssetMaterials(ctx context.Context, req *GetAssetMaterialsRequest, opts ...client.CallOption) (*GetAssetMaterialsResponse, error) GetAssetMaterials(ctx context.Context, req *GetAssetMaterialsRequest, opts ...client.CallOption) (*GetAssetMaterialsResponse, error)
UpdateMaterialLayerOrder(ctx context.Context, req *UpdateMaterialLayerOrderRequest, opts ...client.CallOption) (*UpdateMaterialLayerOrderResponse, error) UpdateMaterialLayerOrder(ctx context.Context, req *UpdateMaterialLayerOrderRequest, opts ...client.CallOption) (*UpdateMaterialLayerOrderResponse, error)
UnbindAssetMaterial(ctx context.Context, req *UnbindAssetMaterialRequest, opts ...client.CallOption) (*UnbindAssetMaterialResponse, error) UnbindAssetMaterial(ctx context.Context, req *UnbindAssetMaterialRequest, opts ...client.CallOption) (*UnbindAssetMaterialResponse, error)
EstimateMintCost(ctx context.Context, req *EstimateMintCostRequest, opts ...client.CallOption) (*EstimateMintCostResponse, error)
} }
// NewAssetService constructs a client for the asset.AssetService service. // NewAssetService constructs a client for the asset.AssetService service.
@ -138,6 +150,14 @@ func (c *AssetServiceImpl) CreateMintOrder(ctx context.Context, req *CreateMintO
return resp, nil return resp, nil
} }
func (c *AssetServiceImpl) EstimateMintCost(ctx context.Context, req *EstimateMintCostRequest, opts ...client.CallOption) (*EstimateMintCostResponse, error) {
resp := new(EstimateMintCostResponse)
if err := c.conn.CallUnary(ctx, []interface{}{req}, resp, "EstimateMintCost", opts...); err != nil {
return nil, err
}
return resp, nil
}
func (c *AssetServiceImpl) GetMyAssets(ctx context.Context, req *GetMyAssetsRequest, opts ...client.CallOption) (*GetMyAssetsResponse, error) { func (c *AssetServiceImpl) GetMyAssets(ctx context.Context, req *GetMyAssetsRequest, opts ...client.CallOption) (*GetMyAssetsResponse, error) {
resp := new(GetMyAssetsResponse) resp := new(GetMyAssetsResponse)
if err := c.conn.CallUnary(ctx, []interface{}{req}, resp, "GetMyAssets", opts...); err != nil { if err := c.conn.CallUnary(ctx, []interface{}{req}, resp, "GetMyAssets", opts...); err != nil {
@ -266,17 +286,9 @@ func (c *AssetServiceImpl) UnbindAssetMaterial(ctx context.Context, req *UnbindA
return resp, nil return resp, nil
} }
func (c *AssetServiceImpl) EstimateMintCost(ctx context.Context, req *EstimateMintCostRequest, opts ...client.CallOption) (*EstimateMintCostResponse, error) {
resp := new(EstimateMintCostResponse)
if err := c.conn.CallUnary(ctx, []interface{}{req}, resp, "EstimateMintCost", opts...); err != nil {
return nil, err
}
return resp, nil
}
var AssetService_ClientInfo = client.ClientInfo{ var AssetService_ClientInfo = client.ClientInfo{
InterfaceName: "topfans.asset.AssetService", InterfaceName: "topfans.asset.AssetService",
MethodNames: []string{"InitMintOrder", "PreCreateMintOrder", "CreateMintOrder", "GetMyAssets", "GetAsset", "GetAssetStatus", "GetMintOrder", "CancelMintOrder", "GetAssetForRPC", "LikeAsset", "UnlikeAsset", "CheckAssetLike", "GetAssetLikes", "ClearAssetLikeRecords", "UploadMaterial", "BindAssetMaterials", "GetAssetMaterials", "UpdateMaterialLayerOrder", "UnbindAssetMaterial", "EstimateMintCost"}, MethodNames: []string{"InitMintOrder", "PreCreateMintOrder", "CreateMintOrder", "EstimateMintCost", "GetMyAssets", "GetAsset", "GetAssetStatus", "GetMintOrder", "CancelMintOrder", "GetAssetForRPC", "LikeAsset", "UnlikeAsset", "CheckAssetLike", "GetAssetLikes", "ClearAssetLikeRecords", "UploadMaterial", "BindAssetMaterials", "GetAssetMaterials", "UpdateMaterialLayerOrder", "UnbindAssetMaterial"},
ConnectionInjectFunc: func(dubboCliRaw interface{}, conn *client.Connection) { ConnectionInjectFunc: func(dubboCliRaw interface{}, conn *client.Connection) {
dubboCli := dubboCliRaw.(*AssetServiceImpl) dubboCli := dubboCliRaw.(*AssetServiceImpl)
dubboCli.conn = conn dubboCli.conn = conn
@ -288,6 +300,7 @@ type AssetServiceHandler interface {
InitMintOrder(context.Context, *InitMintOrderRequest) (*InitMintOrderResponse, error) InitMintOrder(context.Context, *InitMintOrderRequest) (*InitMintOrderResponse, error)
PreCreateMintOrder(context.Context, *PreCreateMintOrderRequest) (*PreCreateMintOrderResponse, error) PreCreateMintOrder(context.Context, *PreCreateMintOrderRequest) (*PreCreateMintOrderResponse, error)
CreateMintOrder(context.Context, *CreateMintOrderRequest) (*CreateMintOrderResponse, error) CreateMintOrder(context.Context, *CreateMintOrderRequest) (*CreateMintOrderResponse, error)
EstimateMintCost(context.Context, *EstimateMintCostRequest) (*EstimateMintCostResponse, error)
GetMyAssets(context.Context, *GetMyAssetsRequest) (*GetMyAssetsResponse, error) GetMyAssets(context.Context, *GetMyAssetsRequest) (*GetMyAssetsResponse, error)
GetAsset(context.Context, *GetAssetRequest) (*GetAssetResponse, error) GetAsset(context.Context, *GetAssetRequest) (*GetAssetResponse, error)
GetAssetStatus(context.Context, *GetAssetStatusRequest) (*GetAssetStatusResponse, error) GetAssetStatus(context.Context, *GetAssetStatusRequest) (*GetAssetStatusResponse, error)
@ -304,7 +317,6 @@ type AssetServiceHandler interface {
GetAssetMaterials(context.Context, *GetAssetMaterialsRequest) (*GetAssetMaterialsResponse, error) GetAssetMaterials(context.Context, *GetAssetMaterialsRequest) (*GetAssetMaterialsResponse, error)
UpdateMaterialLayerOrder(context.Context, *UpdateMaterialLayerOrderRequest) (*UpdateMaterialLayerOrderResponse, error) UpdateMaterialLayerOrder(context.Context, *UpdateMaterialLayerOrderRequest) (*UpdateMaterialLayerOrderResponse, error)
UnbindAssetMaterial(context.Context, *UnbindAssetMaterialRequest) (*UnbindAssetMaterialResponse, error) UnbindAssetMaterial(context.Context, *UnbindAssetMaterialRequest) (*UnbindAssetMaterialResponse, error)
EstimateMintCost(context.Context, *EstimateMintCostRequest) (*EstimateMintCostResponse, error)
} }
func RegisterAssetServiceHandler(srv *server.Server, hdlr AssetServiceHandler, opts ...server.ServiceOption) error { func RegisterAssetServiceHandler(srv *server.Server, hdlr AssetServiceHandler, opts ...server.ServiceOption) error {
@ -364,6 +376,21 @@ var AssetService_ServiceInfo = server.ServiceInfo{
return triple_protocol.NewResponse(res), nil return triple_protocol.NewResponse(res), nil
}, },
}, },
{
Name: "EstimateMintCost",
Type: constant.CallUnary,
ReqInitFunc: func() interface{} {
return new(EstimateMintCostRequest)
},
MethodFunc: func(ctx context.Context, args []interface{}, handler interface{}) (interface{}, error) {
req := args[0].(*EstimateMintCostRequest)
res, err := handler.(AssetServiceHandler).EstimateMintCost(ctx, req)
if err != nil {
return nil, err
}
return triple_protocol.NewResponse(res), nil
},
},
{ {
Name: "GetMyAssets", Name: "GetMyAssets",
Type: constant.CallUnary, Type: constant.CallUnary,
@ -604,20 +631,5 @@ var AssetService_ServiceInfo = server.ServiceInfo{
return triple_protocol.NewResponse(res), nil return triple_protocol.NewResponse(res), nil
}, },
}, },
{
Name: "EstimateMintCost",
Type: constant.CallUnary,
ReqInitFunc: func() interface{} {
return new(EstimateMintCostRequest)
},
MethodFunc: func(ctx context.Context, args []interface{}, handler interface{}) (interface{}, error) {
req := args[0].(*EstimateMintCostRequest)
res, err := handler.(AssetServiceHandler).EstimateMintCost(ctx, req)
if err != nil {
return nil, err
}
return triple_protocol.NewResponse(res), nil
},
},
}, },
} }

View File

@ -65,6 +65,38 @@ message PurchaseItemResponse {
int64 remaining_balance = 5; // int64 remaining_balance = 5; //
} }
//
message PurchaseItem {
string item_type = 1;
int32 quantity = 2;
}
//
message BatchPurchaseItemRequest {
int64 activity_id = 1;
repeated PurchaseItem items = 2; //
int64 star_id = 3;
int64 user_id = 4; // ID
}
//
message BatchPurchaseItemResponse {
topfans.common.BaseResponse base = 1;
int64 total_crystal_spent = 2; //
int64 total_contribution = 3; //
int64 current_progress = 4; //
int64 remaining_balance = 5; //
int32 success_count = 6; //
int32 fail_count = 7; //
repeated PurchaseFailItem fails = 8; //
}
//
message PurchaseFailItem {
string item_type = 1;
string reason = 2;
}
// //
message ContributionRankingRequest { message ContributionRankingRequest {
int64 activity_id = 1; int64 activity_id = 1;
@ -237,6 +269,14 @@ service ActivityService {
}; };
} }
//
rpc BatchPurchaseItem(BatchPurchaseItemRequest) returns (BatchPurchaseItemResponse) {
option (google.api.http) = {
post: "/api/v1/activities/{activity_id}/batch-purchase"
body: "*"
};
}
// //
rpc GetContributionRanking(ContributionRankingRequest) returns (ContributionRankingResponse) { rpc GetContributionRanking(ContributionRankingRequest) returns (ContributionRankingResponse) {
option (google.api.http) = { option (google.api.http) = {

View File

@ -129,7 +129,7 @@ message EstimateMintCostResponse {
int64 current_balance = 3; // int64 current_balance = 3; //
int64 balance_after = 4; // int64 balance_after = 4; //
int32 mint_count = 5; // int32 mint_count = 5; //
string next_tier_hint = 6; // int64 next_tier_cost = 6; //
} }
// ==================== ==================== // ==================== ====================

View File

@ -51,6 +51,20 @@ fi
echo "✅ 所有必需插件已安装" echo "✅ 所有必需插件已安装"
echo "" echo ""
# 辅助函数:移动 protoc-gen-go-triple v3 生成的文件到正确位置
# v3 插件根据 go_package 路径生成文件到 github.com/ 目录,需要手动移动
move_triple_files() {
local module_path="$1"
local target_dir="$2"
local triple_file=$(basename "$module_path").triple.go
local src_file="github.com/$module_path/$triple_file"
if [ -f "$src_file" ]; then
mv "$src_file" "$target_dir/"
rm -rf "github.com/$module_path"
echo "$triple_file 已移动到正确位置"
fi
}
# 预先创建目标目录 # 预先创建目标目录
echo "📁 创建目标目录..." echo "📁 创建目标目录..."
for name in common user social asset gallery ranking activity task starbook; do for name in common user social asset gallery ranking activity task starbook; do
@ -77,6 +91,7 @@ protoc --proto_path=proto \
--go-triple_out=pkg/proto/user \ --go-triple_out=pkg/proto/user \
--go-triple_opt=paths=source_relative \ --go-triple_opt=paths=source_relative \
user.proto user.proto
move_triple_files "topfans/backend/pkg/proto/user" "pkg/proto/user"
echo "✅ user.proto 编译完成" echo "✅ user.proto 编译完成"
echo "" echo ""
@ -90,6 +105,7 @@ protoc --proto_path=proto \
--go-triple_out=pkg/proto/social \ --go-triple_out=pkg/proto/social \
--go-triple_opt=paths=source_relative \ --go-triple_opt=paths=source_relative \
social.proto social.proto
move_triple_files "topfans/backend/pkg/proto/social" "pkg/proto/social"
echo "✅ social.proto 编译完成" echo "✅ social.proto 编译完成"
echo "" echo ""
@ -103,6 +119,7 @@ protoc --proto_path=proto \
--go-triple_out=pkg/proto/asset \ --go-triple_out=pkg/proto/asset \
--go-triple_opt=paths=source_relative \ --go-triple_opt=paths=source_relative \
asset.proto asset.proto
move_triple_files "topfans/backend/pkg/proto/asset" "pkg/proto/asset"
echo "✅ asset.proto 编译完成" echo "✅ asset.proto 编译完成"
echo "" echo ""
@ -116,6 +133,7 @@ protoc --proto_path=proto \
--go-triple_out=pkg/proto/gallery \ --go-triple_out=pkg/proto/gallery \
--go-triple_opt=paths=source_relative \ --go-triple_opt=paths=source_relative \
gallery.proto gallery.proto
move_triple_files "topfans/backend/pkg/proto/gallery" "pkg/proto/gallery"
echo "✅ gallery.proto 编译完成" echo "✅ gallery.proto 编译完成"
echo "" echo ""
@ -129,6 +147,7 @@ protoc --proto_path=proto \
--go-triple_out=pkg/proto/ranking \ --go-triple_out=pkg/proto/ranking \
--go-triple_opt=paths=source_relative \ --go-triple_opt=paths=source_relative \
ranking.proto ranking.proto
move_triple_files "topfans/backend/pkg/proto/ranking" "pkg/proto/ranking"
echo "✅ ranking.proto 编译完成" echo "✅ ranking.proto 编译完成"
echo "" echo ""
@ -142,6 +161,7 @@ protoc --proto_path=proto \
--go-triple_out=pkg/proto/activity \ --go-triple_out=pkg/proto/activity \
--go-triple_opt=paths=source_relative \ --go-triple_opt=paths=source_relative \
activity.proto activity.proto
move_triple_files "topfans/backend/pkg/proto/activity" "pkg/proto/activity"
echo "✅ activity.proto 编译完成" echo "✅ activity.proto 编译完成"
echo "" echo ""
@ -155,6 +175,7 @@ protoc --proto_path=proto \
--go-triple_out=pkg/proto/task \ --go-triple_out=pkg/proto/task \
--go-triple_opt=paths=source_relative \ --go-triple_opt=paths=source_relative \
task.proto task.proto
move_triple_files "topfans/backend/pkg/proto/task" "pkg/proto/task"
echo "✅ task.proto 编译完成" echo "✅ task.proto 编译完成"
echo "" echo ""
@ -168,6 +189,7 @@ protoc --proto_path=proto \
--go-triple_out=pkg/proto/starbook \ --go-triple_out=pkg/proto/starbook \
--go-triple_opt=paths=source_relative \ --go-triple_opt=paths=source_relative \
starbook.proto starbook.proto
move_triple_files "topfans/backend/pkg/proto/starbook" "pkg/proto/starbook"
echo "✅ starbook.proto 编译完成" echo "✅ starbook.proto 编译完成"
echo "" echo ""

View File

@ -162,6 +162,38 @@ func (p *ActivityProvider) PurchaseItem(ctx context.Context, req *pb.PurchaseIte
return resp, nil return resp, nil
} }
// BatchPurchaseItem 批量购买道具
func (p *ActivityProvider) BatchPurchaseItem(ctx context.Context, req *pb.BatchPurchaseItemRequest) (*pb.BatchPurchaseItemResponse, error) {
logger.Logger.Info("Received BatchPurchaseItem request",
zap.Int64("activity_id", req.ActivityId),
zap.Int("items_count", len(req.Items)),
zap.Int64("star_id", req.StarId),
)
// 调用Service层
resp, err := p.activityService.BatchPurchaseItem(ctx, req)
if err != nil {
logger.Logger.Error("BatchPurchaseItem failed", zap.Error(err))
return &pb.BatchPurchaseItemResponse{
Base: &pbCommon.BaseResponse{
Code: appErrors.ToStatusCode(err),
Message: err.Error(),
Timestamp: time.Now().UnixMilli(),
},
}, err
}
logger.Logger.Info("BatchPurchaseItem successful",
zap.Int64("total_crystal_spent", resp.TotalCrystalSpent),
zap.Int64("total_contribution", resp.TotalContribution),
zap.Int64("remaining_balance", resp.RemainingBalance),
zap.Int32("success_count", resp.SuccessCount),
zap.Int32("fail_count", resp.FailCount),
)
return resp, nil
}
// GetContributionRanking 获取贡献点排名 // GetContributionRanking 获取贡献点排名
func (p *ActivityProvider) GetContributionRanking(ctx context.Context, req *pb.ContributionRankingRequest) (*pb.ContributionRankingResponse, error) { func (p *ActivityProvider) GetContributionRanking(ctx context.Context, req *pb.ContributionRankingRequest) (*pb.ContributionRankingResponse, error) {
logger.Logger.Info("Received GetContributionRanking request", logger.Logger.Info("Received GetContributionRanking request",

View File

@ -32,6 +32,9 @@ type ActivityService interface {
// PurchaseItem 购买道具 // PurchaseItem 购买道具
PurchaseItem(ctx context.Context, req *pb.PurchaseItemRequest) (*pb.PurchaseItemResponse, error) PurchaseItem(ctx context.Context, req *pb.PurchaseItemRequest) (*pb.PurchaseItemResponse, error)
// BatchPurchaseItem 批量购买道具
BatchPurchaseItem(ctx context.Context, req *pb.BatchPurchaseItemRequest) (*pb.BatchPurchaseItemResponse, error)
// GetContributionRanking 获取贡献点排名 // GetContributionRanking 获取贡献点排名
GetContributionRanking(ctx context.Context, req *pb.ContributionRankingRequest) (*pb.ContributionRankingResponse, error) GetContributionRanking(ctx context.Context, req *pb.ContributionRankingRequest) (*pb.ContributionRankingResponse, error)
@ -411,6 +414,222 @@ func (s *activityService) PurchaseItem(ctx context.Context, req *pb.PurchaseItem
}, nil }, nil
} }
// BatchPurchaseItem 批量购买道具
func (s *activityService) BatchPurchaseItem(ctx context.Context, req *pb.BatchPurchaseItemRequest) (*pb.BatchPurchaseItemResponse, error) {
logger.Logger.Info("BatchPurchaseItem request",
zap.Int64("activity_id", req.ActivityId),
zap.Int("items_count", len(req.Items)),
zap.Int64("star_id", req.StarId),
)
// 参数校验
if req.ActivityId <= 0 {
return &pb.BatchPurchaseItemResponse{
Base: &pbCommon.BaseResponse{
Code: 400,
Message: "activity_id is required",
},
}, nil
}
if len(req.Items) == 0 {
return &pb.BatchPurchaseItemResponse{
Base: &pbCommon.BaseResponse{
Code: 400,
Message: "items 是必填参数",
},
}, nil
}
userID := req.UserId
// 获取活动
activity, err := s.activityRepo.GetActivityByID(req.ActivityId)
if err != nil {
logger.Logger.Error("GetActivity failed", zap.Error(err))
return &pb.BatchPurchaseItemResponse{
Base: &pbCommon.BaseResponse{
Code: 500,
Message: "获取活动失败: " + err.Error(),
},
}, nil
}
if activity == nil {
return &pb.BatchPurchaseItemResponse{
Base: &pbCommon.BaseResponse{
Code: 404,
Message: "活动不存在",
},
}, nil
}
// 检查活动状态
currentStatus := activity.GetCurrentStatus()
if currentStatus != "active" {
var message string
switch currentStatus {
case "expired":
message = "activity:expired"
case "pending":
message = "activity:pending"
case "completed":
message = "activity:completed"
default:
message = "activity:expired"
}
return &pb.BatchPurchaseItemResponse{
Base: &pbCommon.BaseResponse{
Code: pbCommon.StatusCode_STATUS_OK,
Message: message,
},
}, nil
}
// 通过RPC获取用户当前水晶余额只调用一次
profile, err := s.userRPCClient.GetFanProfile(userID, req.StarId)
if err != nil {
logger.Logger.Error("GetFanProfile failed", zap.Error(err))
return &pb.BatchPurchaseItemResponse{
Base: &pbCommon.BaseResponse{
Code: 500,
Message: "获取粉丝档案失败: " + err.Error(),
},
}, nil
}
if profile == nil {
return &pb.BatchPurchaseItemResponse{
Base: &pbCommon.BaseResponse{
Code: 404,
Message: "粉丝档案不存在",
},
}, nil
}
// 计算总消费水晶和贡献点(先计算,用于校验余额)
var totalCost int64
var totalContribution int64
itemInfoMap := make(map[string]*models.ActivityItem)
for _, item := range req.Items {
if item.Quantity <= 0 {
continue
}
activityItem, err := s.activityRepo.GetActivityItemByType(req.ActivityId, item.ItemType)
if err != nil || activityItem == nil {
logger.Logger.Warn("GetActivityItemByType failed or item not found",
zap.String("item_type", item.ItemType),
zap.Error(err),
)
continue
}
itemInfoMap[item.ItemType] = activityItem
totalCost += int64(activityItem.CrystalCost) * int64(item.Quantity)
totalContribution += int64(activityItem.ContributionPoints) * int64(item.Quantity)
}
// 检查水晶余额是否足够
if profile.CrystalBalance < totalCost {
return &pb.BatchPurchaseItemResponse{
Base: &pbCommon.BaseResponse{
Code: 400,
Message: "水晶余额不足",
},
}, nil
}
// 通过RPC扣减水晶
newBalance, err := s.userRPCClient.UpdateCrystalBalance(userID, req.StarId, -totalCost)
if err != nil {
logger.Logger.Error("UpdateCrystalBalance failed", zap.Error(err))
return &pb.BatchPurchaseItemResponse{
Base: &pbCommon.BaseResponse{
Code: 500,
Message: "扣减水晶失败: " + err.Error(),
},
}, nil
}
// 更新活动进度
newProgress := activity.CurrentProgress + totalContribution
if newProgress > activity.TargetProgress {
newProgress = activity.TargetProgress
}
err = s.activityRepo.UpdateActivityProgress(req.ActivityId, newProgress)
if err != nil {
logger.Logger.Error("UpdateActivityProgress failed", zap.Error(err))
}
// 创建贡献记录(合并为一个记录)
now := time.Now().UnixMilli()
contribution := &models.ActivityContribution{
ActivityID: req.ActivityId,
UserID: userID,
StarID: req.StarId,
Quantity: 0, // 批量购买不记录单数量
CrystalSpent: totalCost,
ContributionPoints: totalContribution,
CreatedAt: now,
}
err = s.activityRepo.CreateContribution(contribution)
if err != nil {
logger.Logger.Error("CreateContribution failed", zap.Error(err))
}
// 更新用户统计
stats, _ := s.activityRepo.GetUserStats(req.ActivityId, userID, req.StarId)
if stats == nil {
stats = &models.ActivityUserStats{
ActivityID: req.ActivityId,
UserID: userID,
StarID: req.StarId,
TotalContribution: 0,
TotalCrystalSpent: 0,
TotalItems: 0,
LastContributeAt: now,
CreatedAt: now,
UpdatedAt: now,
}
}
stats.TotalContribution += totalContribution
stats.TotalCrystalSpent += totalCost
stats.TotalItems += len(req.Items)
stats.LastContributeAt = now
stats.UpdatedAt = now
err = s.activityRepo.UpdateUserStats(stats)
if err != nil {
logger.Logger.Error("UpdateUserStats failed", zap.Error(err))
}
logger.Logger.Info("BatchPurchaseItem success",
zap.Int64("user_id", userID),
zap.Int64("total_cost", totalCost),
zap.Int64("total_contribution", totalContribution),
zap.Int64("new_progress", newProgress),
)
return &pb.BatchPurchaseItemResponse{
Base: &pbCommon.BaseResponse{
Code: 200,
Message: "ok",
},
TotalCrystalSpent: totalCost,
TotalContribution: totalContribution,
CurrentProgress: newProgress,
RemainingBalance: newBalance,
SuccessCount: int32(len(req.Items)),
FailCount: 0,
Fails: []*pb.PurchaseFailItem{},
}, nil
}
// GetContributionRanking 获取贡献点排名 // GetContributionRanking 获取贡献点排名
func (s *activityService) GetContributionRanking(ctx context.Context, req *pb.ContributionRankingRequest) (*pb.ContributionRankingResponse, error) { func (s *activityService) GetContributionRanking(ctx context.Context, req *pb.ContributionRankingRequest) (*pb.ContributionRankingResponse, error) {
logger.Logger.Info("GetContributionRanking request", logger.Logger.Info("GetContributionRanking request",

View File

@ -853,6 +853,6 @@ func (p *AssetProvider) EstimateMintCost(ctx context.Context, req *pb.EstimateMi
CurrentBalance: estimate.CurrentBalance, CurrentBalance: estimate.CurrentBalance,
BalanceAfter: estimate.AfterBalance, BalanceAfter: estimate.AfterBalance,
MintCount: estimate.MintCount, MintCount: estimate.MintCount,
NextTierHint: estimate.NextTierHint, NextTierCost: estimate.NextTierCost,
}, nil }, nil
} }

View File

@ -856,13 +856,13 @@ func (s *mintService) EstimateMintCost(userID, starID int64) (*MintCostEstimate,
afterBalance = 0 afterBalance = 0
} }
// 下一阶梯费用提示 // 下一阶梯费用
var nextTierHint string var nextTierCost int64
nextMintCount := currentMintCount + 2 // 下一次铸造的次数 nextMintCount := currentMintCount + 2 // 下一次铸造的次数
if nextMintCount <= 10 { if nextMintCount <= 10 {
nextCost, err := s.GetMintCost(nextMintCount) nextCost, err := s.GetMintCost(nextMintCount)
if err == nil { if err == nil {
nextTierHint = fmt.Sprintf("下一阶梯 %d 水晶", nextCost.CostCrystal) nextTierCost = nextCost.CostCrystal
} }
} }
@ -871,7 +871,7 @@ func (s *mintService) EstimateMintCost(userID, starID int64) (*MintCostEstimate,
CurrentBalance: currentBalance, CurrentBalance: currentBalance,
AfterBalance: afterBalance, AfterBalance: afterBalance,
MintCount: currentMintCount + 1, // 本次将是第几次铸造 MintCount: currentMintCount + 1, // 本次将是第几次铸造
NextTierHint: nextTierHint, NextTierCost: nextTierCost,
}, nil }, nil
} }
@ -881,7 +881,7 @@ type MintCostEstimate struct {
CurrentBalance int64 // 当前余额(铸造前) CurrentBalance int64 // 当前余额(铸造前)
AfterBalance int64 // 铸造后余额 AfterBalance int64 // 铸造后余额
MintCount int32 // 本次铸造是第几次 MintCount int32 // 本次铸造是第几次
NextTierHint string // 下一阶梯提示 NextTierCost int64 // 下一阶梯费用
} }
// UpdateMintCountAndBoost 更新铸爱次数和收益提升 // UpdateMintCountAndBoost 更新铸爱次数和收益提升

View File

@ -1,34 +1,43 @@
<template> <template>
<view v-show="visible" class="modal-overlay" :class="{ 'modal-visible': visible }" @tap="handleCancel"> <view v-show="visible" class="modal-overlay" :class="{ 'modal-visible': visible }" @tap="handleCancel">
<view class="modal-box" @tap.stop> <view class="modal-box" @tap.stop>
<!-- 左上角关闭按钮 -->
<view class="close-btn" @tap="handleCancel">
<image class="close-icon" src="/static/starbookcontent/tuichu.png" mode="aspectFit"></image>
</view>
<!-- 右上角水晶数量 -->
<view class="crystal-badge" v-if="currentBalance">
<image class="topfans-icon" src="/static/icon/crystal.png" mode="aspectFit"></image>
<view class="card-income-text-wrap">
<text class="card-income-text">{{ currentBalance }}</text>
</view>
</view>
<!-- 标题 --> <!-- 标题 -->
<view v-if="title" class="modal-title"> <view v-if="title" class="modal-title">
<text>{{ title }}</text> <text>{{ title }}</text>
</view> </view>
<view v-else class="modal-title"> <!-- <view v-else class="modal-title">
<text class="modal-title-text">铸造确认</text> <text class="modal-title-text">铸造确认</text>
</view> </view> -->
<!-- 铸造费用信息 --> <!-- 铸造费用信息 -->
<view v-if="costCrystal > 0 || currentBalance > 0" class="cost-info"> <view v-if="costCrystal > 0" class="cost-info">
<view class="cost-row"> <view class="cost-row">
<text class="cost-label">本次消耗</text> <text class="cost-label">本次消耗</text>
<text class="cost-value cost-crystal">{{ costCrystal }} 水晶</text> <view class="cost-num-wrap">
<text class="cost-num">{{ costCrystal }}</text>
<text class="cost-unit"> 水晶</text>
</view> </view>
<view class="cost-row">
<text class="cost-label">当前余额</text>
<text class="cost-value">{{ currentBalance }} 水晶</text>
</view>
<view class="cost-row">
<text class="cost-label">铸造后余额</text>
<text class="cost-value balance-after">{{ balanceAfter }} 水晶</text>
</view> </view>
<view v-if="mintCount > 0" class="cost-row"> <view v-if="mintCount > 0" class="cost-row">
<text class="cost-label">铸造次数</text> <text class="cost-label">铸造次数</text>
<text class="cost-value"> {{ mintCount }} </text> <view class="cost-num-wrap">
<text class="cost-unit"> </text>
<text class="cost-num">{{ mintCount }}</text>
<text class="cost-unit"> </text>
</view> </view>
<view v-if="nextTierHint" class="next-tier-hint">
<text>{{ nextTierHint }}</text>
</view> </view>
</view> </view>
@ -39,13 +48,17 @@
<!-- 按钮区 --> <!-- 按钮区 -->
<view class="modal-actions"> <view class="modal-actions">
<view v-if="showCancel" class="btn btn-cancel" @tap="handleCancel">
<text>{{ cancelText }}</text>
</view>
<view class="btn btn-confirm" @tap="handleConfirm"> <view class="btn btn-confirm" @tap="handleConfirm">
<text>{{ confirmText }}</text> <text>{{ confirmText }}</text>
</view> </view>
</view> </view>
<!-- 下一阶段消耗提示 -->
<view v-if="nextTierCost > 0" class="next-tier-cost">
<text class="cost-text">下一阶段消耗 </text>
<text class="cost-num">{{ nextTierCost }}</text>
<text class="cost-text"> 水晶</text>
</view>
</view> </view>
</view> </view>
</template> </template>
@ -74,14 +87,6 @@ const props = defineProps({
type: String, type: String,
default: '确认' default: '确认'
}, },
cancelText: {
type: String,
default: '取消'
},
showCancel: {
type: Boolean,
default: true
},
// //
costCrystal: { costCrystal: {
type: Number, type: Number,
@ -91,17 +96,13 @@ const props = defineProps({
type: Number, type: Number,
default: 0 default: 0
}, },
balanceAfter: {
type: Number,
default: 0
},
mintCount: { mintCount: {
type: Number, type: Number,
default: 0 default: 0
}, },
nextTierHint: { nextTierCost: {
type: String, type: Number,
default: '' default: 0
} }
}) })
@ -119,7 +120,10 @@ function handleCancel() {
<style scoped> <style scoped>
.modal-overlay { .modal-overlay {
position: fixed; position: fixed;
top: 0; left: 0; right: 0; bottom: 0; top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.5); background: rgba(0, 0, 0, 0.5);
z-index: 999; z-index: 999;
display: flex; display: flex;
@ -138,7 +142,7 @@ function handleCancel() {
.modal-box { .modal-box {
width: 560rpx; width: 560rpx;
/* background: #fff; */ /* background: #fff; */
background-image: url('/static/starbookcontent/beijing.png'); background-image: url('/static/icon/confirmbj.png');
background-size: cover; background-size: cover;
background-position: center bottom; background-position: center bottom;
border-radius: 24rpx; border-radius: 24rpx;
@ -147,6 +151,63 @@ function handleCancel() {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
align-items: center; align-items: center;
position: relative;
}
.close-btn {
position: absolute;
top: 8rpx;
left: 8rpx;
width: 64rpx;
height: 64rpx;
z-index: 10;
padding: 10rpx;
}
.close-icon {
width: 64rpx;
height: 64rpx;
}
.crystal-badge {
position: absolute;
top: 8rpx;
right: 8rpx;
/* background: rgba(0, 0, 0, 0.5); */
/* border-radius: 20rpx; */
/* padding: 8rpx 16rpx; */
display: flex;
align-items: center;
}
.topfans-icon {
width: 56rpx;
height: 56rpx;
position: relative;
z-index: 2;
margin-right: -16rpx;
left: 20rpx;
/* top: 8rpx */
transform: rotate(-15deg);
}
.card-income-text-wrap {
width: 64rpx;
height: 32rpx;
background-image: url('@/static/square/shuijingzhanshikuang.png');
background-size: 100% 100%;
background-position: center;
display: flex;
align-items: center;
justify-content: center;
padding: 0 16rpx 0 32rpx;
}
.card-income-text {
font-size: 24rpx;
color: #fff;
font-weight: 700;
text-align: center;
} }
.modal-title { .modal-title {
@ -157,8 +218,9 @@ function handleCancel() {
} }
.cost-info { .cost-info {
width: 100%; width: 480rpx;
margin-bottom: 32rpx; /* margin-bottom: 32rpx; */
padding: 80rpx 0 32rpx;
} }
.cost-row { .cost-row {
@ -166,18 +228,17 @@ function handleCancel() {
justify-content: space-between; justify-content: space-between;
align-items: center; align-items: center;
padding: 12rpx 0; padding: 12rpx 0;
/* border-bottom: 1rpx solid rgba(0, 0, 0, 0.05); */
}
.cost-row:last-child {
border-bottom: none;
} }
.cost-label { .cost-label {
background-image: url('@/static/rank/activity-support-icon/beijingkuang.png');
background-size: cover;
background-position: center;
padding: 16rpx;
border-radius: 999rpx;
font-size: 28rpx; font-size: 28rpx;
color: #fff; color: #fff;
text-shadow: 0 2px 8px rgba(0, 0, 0, 0.7); text-shadow: 0 2px 8px rgba(0, 0, 0, 0.7);
} }
.cost-value { .cost-value {
@ -185,31 +246,37 @@ function handleCancel() {
color: #fff; color: #fff;
font-weight: 500; font-weight: 500;
text-shadow: 0 2px 8px rgba(0, 0, 0, 0.7); text-shadow: 0 2px 8px rgba(0, 0, 0, 0.7);
} }
.cost-crystal { .cost-num {
color: #fff; font-size: 28rpx;
color: #ff9500;
font-weight: bold; font-weight: bold;
text-shadow: 0 2px 8px rgba(0, 0, 0, 0.7);
} }
.balance-after { .cost-num-wrap {
display: flex;
align-items: center;
gap: 4rpx;
}
.cost-unit {
font-size: 28rpx;
color: #fff; color: #fff;
text-shadow: 0 2px 8px rgba(0, 0, 0, 0.7);
} }
.next-tier-hint { .next-tier-cost {
margin-top: 16rpx; margin-top: 16rpx;
padding: 12rpx 16rpx; padding: 12rpx 16rpx;
background: rgba(255, 107, 157, 0.1);
border-radius: 12rpx; border-radius: 12rpx;
text-align: center; text-align: center;
} }
.next-tier-hint text { .next-tier-cost .cost-text {
font-size: 24rpx; font-size: 24rpx;
color: #FF6B9D; color: #fff;
text-shadow: 0 2px 8px rgba(0, 0, 0, 0.7);
} }
.modal-body { .modal-body {
@ -228,7 +295,7 @@ function handleCancel() {
} }
.modal-actions { .modal-actions {
width: 100%; width: 224rpx;
display: flex; display: flex;
gap: 24rpx; gap: 24rpx;
} }
@ -249,7 +316,13 @@ function handleCancel() {
} }
.btn-confirm { .btn-confirm {
background: linear-gradient(to right, #F08399, #B94E73); background: linear-gradient(to bottom right,
#F0E4B1 0%,
#F08399 50%,
#B94E73 100%);
box-shadow:
0 4rpx 12rpx rgba(255, 143, 158, 0.2),
inset 0 2rpx 4rpx rgba(255, 255, 255, 0.4);
color: #fff; color: #fff;
} }
</style> </style>

View File

@ -5,7 +5,7 @@
<!-- 左上角关闭按钮 --> <!-- 左上角关闭按钮 -->
<view class="close-btn" @click="handleClose"> <view class="close-btn" @click="handleClose">
<text class="back-icon" :style="{ color: backIconColor }"></text> <text class="nav-back" :style="{ color: backIconColor }"></text>
</view> </view>
<!-- 功能按钮区域 --> <!-- 功能按钮区域 -->
@ -144,13 +144,18 @@ const handleAdd = () => {
/* 关闭按钮 */ /* 关闭按钮 */
.close-btn { .close-btn {
font-size: 48rpx;
font-weight: bold;
}
.nav-back-icon {
width: 80rpx; width: 80rpx;
height: 80rpx; height: 80rpx;
display: flex;
align-items: center;
justify-content: center;
}
.nav-back {
font-size: 48rpx;
font-weight: bold;
color: #fff;
} }
/* 浮动装饰物 */ /* 浮动装饰物 */

View File

@ -23,29 +23,15 @@
</view> --> </view> -->
<!-- 光栅卡单张工作台预览陀螺仪 --> <!-- 光栅卡单张工作台预览陀螺仪 -->
<view <view class="lenticular-result-wrap" :class="{ 'cards-visible': isGiftOpened }">
class="lenticular-result-wrap"
:class="{ 'cards-visible': isGiftOpened }"
>
<view class="lenticular-result-card"> <view class="lenticular-result-card">
<view class="card-wrapper craft-card-wrapper"> <view class="card-wrapper craft-card-wrapper">
<image <image class="card-frame" src="/static/square/gerenzhongxincangpinkuang.png" mode="aspectFit" />
class="card-frame"
src="/static/square/gerenzhongxincangpinkuang.png"
mode="aspectFit"
/>
<view class="craft-lenticular-slot"> <view class="craft-lenticular-slot">
<LenticularCard <LenticularCard v-if="lenticularLayers.length > 0" class="craft-lenticular-card"
v-if="lenticularLayers.length > 0" :layers="lenticularLayers" :transforms="layerTransforms" :gyro-source="gyroSourceLabel"
class="craft-lenticular-card" :skip-built-in-touch="true" tilt-hint-text="晃动查看" :shimmer-mid-opacity="0.16"
:layers="lenticularLayers" @simulate="simulate" />
:transforms="layerTransforms"
:gyro-source="gyroSourceLabel"
:skip-built-in-touch="true"
tilt-hint-text="晃动查看"
:shimmer-mid-opacity="0.16"
@simulate="simulate"
/>
</view> </view>
</view> </view>
</view> </view>
@ -53,27 +39,13 @@
<!-- 礼盒 --> <!-- 礼盒 -->
<view class="gift-box" :class="{ 'gift-opened': isGiftOpened }"> <view class="gift-box" :class="{ 'gift-opened': isGiftOpened }">
<image <image v-if="!isGiftOpened" class="gift-image" src="/static/nft/lihe.png" mode="aspectFit" />
v-if="!isGiftOpened" <image v-else class="gift-image gift-image-opened" src="/static/nft/lihe_kaiqi.png" mode="aspectFit" />
class="gift-image"
src="/static/nft/lihe.png"
mode="aspectFit"
/>
<image
v-else
class="gift-image gift-image-opened"
src="/static/nft/lihe_kaiqi.png"
mode="aspectFit"
/>
</view> </view>
<!-- 底部按钮 --> <!-- 底部按钮 -->
<view class="bottom-action" :class="{ 'bottom-action--row': isCraftDetailFlow }"> <view class="bottom-action" :class="{ 'bottom-action--row': isCraftDetailFlow }">
<view <view v-if="isCraftDetailFlow" class="action-button action-button--secondary" @tap="handleRegenerate">
v-if="isCraftDetailFlow"
class="action-button action-button--secondary"
@tap="handleRegenerate"
>
<text class="button-text">重新生成</text> <text class="button-text">重新生成</text>
</view> </view>
<view class="action-button" @tap="selectAsset"> <view class="action-button" @tap="selectAsset">
@ -82,17 +54,9 @@
</view> </view>
<!-- 铸造确认弹窗 --> <!-- 铸造确认弹窗 -->
<ConfirmModal <ConfirmModal v-if="showConfirmModal" :visible="showConfirmModal" :cost-crystal="confirmCostInfo.costCrystal"
v-if="showConfirmModal" :current-balance="confirmCostInfo.currentBalance" :mint-count="confirmCostInfo.mintCount"
:visible="showConfirmModal" :next-tier-cost="confirmCostInfo.nextTierCost" @confirm="handleConfirmMint" @cancel="handleCancelMint" />
:cost-crystal="confirmCostInfo.costCrystal"
:current-balance="confirmCostInfo.currentBalance"
:balance-after="confirmCostInfo.balanceAfter"
:mint-count="confirmCostInfo.mintCount"
:next-tier-hint="confirmCostInfo.nextTierHint"
@confirm="handleConfirmMint"
@cancel="handleCancelMint"
/>
</view> </view>
</template> </template>
@ -131,9 +95,8 @@ const showConfirmModal = ref(false);
const confirmCostInfo = ref({ const confirmCostInfo = ref({
costCrystal: 0, costCrystal: 0,
currentBalance: 0, currentBalance: 0,
balanceAfter: 0,
mintCount: 0, mintCount: 0,
nextTierHint: '', nextTierCost: 0,
}); });
const lenticularLayers = ref([]); const lenticularLayers = ref([]);
@ -673,18 +636,16 @@ const selectAsset = async () => {
confirmCostInfo.value = { confirmCostInfo.value = {
costCrystal: costRes.data.cost_crystal || 0, costCrystal: costRes.data.cost_crystal || 0,
currentBalance: costRes.data.current_balance || 0, currentBalance: costRes.data.current_balance || 0,
balanceAfter: costRes.data.balance_after || 0,
mintCount: costRes.data.mint_count || 0, mintCount: costRes.data.mint_count || 0,
nextTierHint: costRes.data.next_tier_hint || '', nextTierCost: costRes.data.next_tier_cost || '',
}; };
} else { } else {
confirmCostInfo.value = { confirmCostInfo.value = {
costCrystal: 100, costCrystal: 100,
currentBalance: 0, currentBalance: 0,
balanceAfter: 0,
mintCount: 0, mintCount: 0,
nextTierHint: '', nextTierCost: 0,
}; };
} }
} catch (e) { } catch (e) {
@ -693,9 +654,8 @@ const selectAsset = async () => {
confirmCostInfo.value = { confirmCostInfo.value = {
costCrystal: 100, costCrystal: 100,
currentBalance: 0, currentBalance: 0,
balanceAfter: 0,
mintCount: 0, mintCount: 0,
nextTierHint: '', nextTierCost: 0,
}; };
} }
@ -775,7 +735,9 @@ onMounted(() => {
const imagesData = uni.getStorageSync(GENERATED_IMAGES_KEY); const imagesData = uni.getStorageSync(GENERATED_IMAGES_KEY);
if (!imagesData) { if (!imagesData) {
uni.showToast({ title: '未找到生成的图片', icon: 'none' }); uni.showToast({ title: '未找到生成的图片', icon: 'none' });
setTimeout(() => uni.navigateBack(), 1500); setTimeout(() => uni.navigateTo({
url: '/pages/castlove/lenticular/lenticular-create'
}), 1500);
return; return;
} }
const parsed = JSON.parse(imagesData); const parsed = JSON.parse(imagesData);
@ -796,7 +758,9 @@ onMounted(() => {
} catch (e) { } catch (e) {
console.error('[GenerationResult] 读取图片数据失败:', e); console.error('[GenerationResult] 读取图片数据失败:', e);
uni.showToast({ title: '数据错误', icon: 'none' }); uni.showToast({ title: '数据错误', icon: 'none' });
setTimeout(() => uni.navigateBack(), 1500); setTimeout(() => uni.navigateTo({
url: '/pages/castlove/lenticular/lenticular-create'
}), 1500);
} }
}); });
@ -852,10 +816,13 @@ onUnmounted(() => {
} }
@keyframes starTwinkle { @keyframes starTwinkle {
0%, 100% {
0%,
100% {
opacity: 0.3; opacity: 0.3;
transform: scale(1); transform: scale(1);
} }
50% { 50% {
opacity: 1; opacity: 1;
transform: scale(1.2); transform: scale(1.2);
@ -937,6 +904,7 @@ onUnmounted(() => {
transform: scale(0) translateY(100rpx); transform: scale(0) translateY(100rpx);
opacity: 0; opacity: 0;
} }
100% { 100% {
transform: scale(1) translateY(0); transform: scale(1) translateY(0);
opacity: 1; opacity: 1;
@ -968,9 +936,12 @@ onUnmounted(() => {
} }
@keyframes cardFloat { @keyframes cardFloat {
0%, 100% {
0%,
100% {
transform: translateY(0) rotate(var(--rotate, 0deg)); transform: translateY(0) rotate(var(--rotate, 0deg));
} }
50% { 50% {
transform: translateY(-20rpx) rotate(var(--rotate, 0deg)); transform: translateY(-20rpx) rotate(var(--rotate, 0deg));
} }
@ -1029,7 +1000,9 @@ onUnmounted(() => {
0% { 0% {
left: -100%; left: -100%;
} }
50%, 100% {
50%,
100% {
left: 100%; left: 100%;
} }
} }
@ -1109,9 +1082,11 @@ onUnmounted(() => {
0% { 0% {
transform: translate(-50%, -50%) scale(0); transform: translate(-50%, -50%) scale(0);
} }
50% { 50% {
transform: translate(-50%, -50%) scale(1.2); transform: translate(-50%, -50%) scale(1.2);
} }
100% { 100% {
transform: translate(-50%, -50%) scale(1); transform: translate(-50%, -50%) scale(1);
} }
@ -1147,9 +1122,12 @@ onUnmounted(() => {
} }
@keyframes giftFloat { @keyframes giftFloat {
0%, 100% {
0%,
100% {
transform: translateX(-50%) translateY(0); transform: translateX(-50%) translateY(0);
} }
50% { 50% {
transform: translateX(-50%) translateY(-20rpx); transform: translateX(-50%) translateY(-20rpx);
} }
@ -1171,9 +1149,11 @@ onUnmounted(() => {
transform: scale(0.8); transform: scale(0.8);
opacity: 0; opacity: 0;
} }
50% { 50% {
transform: scale(1.1); transform: scale(1.1);
} }
100% { 100% {
transform: scale(1); transform: scale(1);
opacity: 1; opacity: 1;

View File

@ -20,11 +20,8 @@
</view> </view>
<!-- 镭射批量导出离屏 --> <!-- 镭射批量导出离屏 -->
<canvas <canvas canvas-id="laserBatchCanvas" class="laser-batch-canvas"
canvas-id="laserBatchCanvas" :style="{ width: laserCanvasW + 'px', height: laserCanvasH + 'px' }" />
class="laser-batch-canvas"
:style="{ width: laserCanvasW + 'px', height: laserCanvasH + 'px' }"
/>
</view> </view>
</template> </template>
@ -99,7 +96,9 @@ const revertProgress = () => {
clearInterval(revertInterval); clearInterval(revertInterval);
// 退 // 退
setTimeout(() => { setTimeout(() => {
uni.navigateBack(); uni.navigateTo({
url: '/pages/castlove/lenticular/lenticular-create'
});
}, 500); }, 500);
} }
}, 100); }, 100);
@ -206,7 +205,9 @@ onMounted(() => {
const requestDataStr = uni.getStorageSync(GENERATION_REQUEST_KEY); const requestDataStr = uni.getStorageSync(GENERATION_REQUEST_KEY);
if (!requestDataStr) { if (!requestDataStr) {
uni.showToast({ title: '数据错误', icon: 'none' }); uni.showToast({ title: '数据错误', icon: 'none' });
setTimeout(() => uni.navigateBack(), 1500); setTimeout(() => uni.navigateTo({
url: '/pages/castlove/lenticular/lenticular-create'
}), 1500);
return; return;
} }
generationData = JSON.parse(requestDataStr); generationData = JSON.parse(requestDataStr);
@ -225,7 +226,9 @@ onMounted(() => {
} catch (e) { } catch (e) {
console.error('[GenerationLoading] mount', e); console.error('[GenerationLoading] mount', e);
uni.showToast({ title: '数据错误', icon: 'none' }); uni.showToast({ title: '数据错误', icon: 'none' });
setTimeout(() => uni.navigateBack(), 1500); setTimeout(() => uni.navigateTo({
url: '/pages/castlove/lenticular/lenticular-create'
}), 1500);
} }
}); });
</script> </script>
@ -268,10 +271,12 @@ onMounted(() => {
} }
@keyframes float { @keyframes float {
0%, 0%,
100% { 100% {
transform: translateX(-50%) translateY(0) rotate(0deg); transform: translateX(-50%) translateY(0) rotate(0deg);
} }
50% { 50% {
transform: translateX(-50%) translateY(-20rpx) rotate(2deg); transform: translateX(-50%) translateY(-20rpx) rotate(2deg);
} }
@ -336,10 +341,12 @@ onMounted(() => {
} }
@keyframes pulse { @keyframes pulse {
0%, 0%,
100% { 100% {
transform: scale(1); transform: scale(1);
} }
50% { 50% {
transform: scale(1.1); transform: scale(1.1);
} }

View File

@ -445,6 +445,7 @@ const handleBack = () => {
.back-icon { .back-icon {
font-size: 48rpx; font-size: 48rpx;
font-weight: bold; font-weight: bold;
color: #fff;
} }
.content-wrapper { .content-wrapper {

View File

@ -214,6 +214,7 @@ const handleUserInfoUpdate = () => {
const handleBalanceUpdate = (data) => { const handleBalanceUpdate = (data) => {
if (userInfo.value) { if (userInfo.value) {
userInfo.value = { ...userInfo.value, crystal_balance: data.crystal_balance }; userInfo.value = { ...userInfo.value, crystal_balance: data.crystal_balance };
exhibitionRevenue.value = data.crystal_balance || 0;
} else { } else {
loadUserInfo(); loadUserInfo();
} }

View File

@ -326,6 +326,7 @@ onUnmounted(() => {
.back-icon { .back-icon {
font-size: 48rpx; font-size: 48rpx;
font-weight: bold; font-weight: bold;
color: #fff;
} }
.content-wrapper { .content-wrapper {

View File

@ -361,6 +361,7 @@ onUnmounted(() => {
.nav-back-icon { .nav-back-icon {
font-size: 48rpx; font-size: 48rpx;
font-weight: bold; font-weight: bold;
color: #fff;
} }
.nav-title { .nav-title {

View File

@ -1019,6 +1019,7 @@ onShow(() => {
.nav-back-icon { .nav-back-icon {
font-size: 48rpx; font-size: 48rpx;
font-weight: bold; font-weight: bold;
color: #fff;
} }
.nav-title { .nav-title {

View File

@ -55,16 +55,9 @@
</view> </view>
<!-- 通用确认弹窗 --> <!-- 通用确认弹窗 -->
<ConfirmModal <ConfirmModal :visible="confirmModal.visible" :title="confirmModal.title" :content="confirmModal.content"
:visible="confirmModal.visible" :confirmText="confirmModal.confirmText" :cancelText="confirmModal.cancelText"
:title="confirmModal.title" :showCancel="confirmModal.showCancel" @confirm="onConfirmModal" @cancel="onCancelModal" />
:content="confirmModal.content"
:confirmText="confirmModal.confirmText"
:cancelText="confirmModal.cancelText"
:showCancel="confirmModal.showCancel"
@confirm="onConfirmModal"
@cancel="onCancelModal"
/>
</template> </template>
<script setup> <script setup>
@ -406,8 +399,8 @@ const handleNext = async () => {
.back-icon { .back-icon {
font-size: 48rpx; font-size: 48rpx;
color: #000000;
font-weight: bold; font-weight: bold;
color: #fff;
} }
.nav-title { .nav-title {

View File

@ -271,8 +271,8 @@ const handleNext = async () => {
.back-icon { .back-icon {
font-size: 48rpx; font-size: 48rpx;
color: #000000;
font-weight: bold; font-weight: bold;
color: #fff;
} }
.nav-title { .nav-title {

View File

@ -10,7 +10,7 @@
<image :src="userInfo?.avatar_url || '/static/icon/avatar-default.png'" class="user-avatar" mode="aspectFill" /> <image :src="userInfo?.avatar_url || '/static/icon/avatar-default.png'" class="user-avatar" mode="aspectFill" />
<view class="user-balance"> <view class="user-balance">
<image src="/static/icon/crystal.png" class="balance-icon" mode="aspectFit" /> <image src="/static/icon/crystal.png" class="balance-icon" mode="aspectFit" />
<text class="balance-text">{{ userInfo?.crystal_balance || 0 }}</text> <text class="balance-text">{{ crystalBalance || 0 }}</text>
</view> </view>
</view> </view>
@ -77,6 +77,7 @@
<script setup> <script setup>
import { ref, computed, onMounted, onUnmounted } from 'vue' import { ref, computed, onMounted, onUnmounted } from 'vue'
import { purchaseItem } from '@/utils/activity-config' import { purchaseItem } from '@/utils/activity-config'
import { getEarningsSummaryApi } from '@/utils/api'
import DiamondConfirmModal from './DiamondConfirmModal.vue' import DiamondConfirmModal from './DiamondConfirmModal.vue'
const props = defineProps({ const props = defineProps({
@ -147,15 +148,31 @@ function handleModalCancel() {
} }
const userInfo = ref(null); const userInfo = ref(null);
const crystalBalance = ref(0)
function loadUserInfo() { async function loadUserInfo() {
try { try {
const userStr = uni.getStorageSync('user') const userStr = uni.getStorageSync('user')
if (userStr) { if (userStr) {
userInfo.value = typeof userStr === 'string' ? JSON.parse(userStr) : userStr userInfo.value = typeof userStr === 'string' ? JSON.parse(userStr) : userStr
} }
// API
const res = await getEarningsSummaryApi()
if (res.code === 200 && res.data) {
crystalBalance.value = res.data.crystal_balance || 0
if (userInfo.value) {
userInfo.value.crystal_balance = crystalBalance.value
uni.setStorageSync('user', JSON.stringify(userInfo.value))
}
// Header
uni.$emit('balanceUpdated', { crystal_balance: crystalBalance.value })
} else {
crystalBalance.value = userInfo.value?.crystal_balance || 0
}
} catch (error) { } catch (error) {
console.error('加载用户信息失败:', error) console.error('加载用户信息失败:', error)
crystalBalance.value = userInfo.value?.crystal_balance || 0
} }
} }
@ -183,6 +200,11 @@ onMounted(() => {
// 线 // 线
loadPendingActions() loadPendingActions()
//
if (items.value && items.value.length > 0) {
selectedItem.value = items.value[0].type
}
// //
networkListener = uni.onNetworkStatusChange((res) => { networkListener = uni.onNetworkStatusChange((res) => {
const wasOffline = !isOnline.value const wasOffline = !isOnline.value
@ -333,33 +355,22 @@ async function handleConfirmContribute() {
return return
} }
// API // API
let successCount = 0 const res = await contributeItem(item, true, true, quantity.value)
let lastRemainingBalance = null console.log(`批量购买返回值:`, res)
let lastErrorMessage = ''
for (let i = 0; i < quantity.value; i++) {
const res = await contributeItem(item, true, true)
console.log(`${i+1}次调用返回值:`, res)
if (res && res.success !== false) {
successCount++
lastRemainingBalance = res.remainingBalance
} else {
lastErrorMessage = res?.message || '活动不在进行中,无法购买'
}
}
// 使 //
if (lastRemainingBalance !== null) { if (res && res.remainingBalance !== null) {
await updateLocalBalanceFromResult(lastRemainingBalance) await updateLocalBalanceFromResult(res.remainingBalance)
} }
// //
if (successCount === quantity.value) { if (res && res.success) {
showResultToast('✅', `贡献成功\n+${item.cost * successCount} 贡献值已到账`) showResultToast('✅', `贡献成功\n+${item.cost * quantity.value} 贡献值已到账`)
} else if (successCount > 0) { //
showResultToast('⚠️', `部分成功 ${successCount}/${quantity.value}`) emit('contribute', item.type, res.remainingBalance)
} else { } else {
showResultToast('❌', lastErrorMessage || '贡献失败') showResultToast('❌', res?.message || '贡献失败')
} }
} finally { } finally {
processingItems.delete(item.type) processingItems.delete(item.type)
@ -370,14 +381,11 @@ async function handleConfirmContribute() {
// //
async function validateBalance(cost) { async function validateBalance(cost) {
try { try {
if (!userInfo.value) { //
const userStr = uni.getStorageSync('user') if (crystalBalance.value === 0 && userInfo.value?.crystal_balance) {
if (userStr) { crystalBalance.value = userInfo.value.crystal_balance
userInfo.value = typeof userStr === 'string' ? JSON.parse(userStr) : { ...userStr }
} }
} return crystalBalance.value >= cost
const balance = Number(userInfo.value?.crystal_balance) || 0
return balance >= cost
} catch (error) { } catch (error) {
console.error('验证余额失败:', error) console.error('验证余额失败:', error)
return false return false
@ -385,11 +393,11 @@ async function validateBalance(cost) {
} }
// //
async function contributeItem(item, isRetry = false, silent = false) { async function contributeItem(item, isRetry = false, silent = false, qty = 1) {
try { try {
// 使 activity-config.js purchaseItem // 使 activity-config.js purchaseItem
const result = await purchaseItem(props.activityId, item.type, 1) const result = await purchaseItem(props.activityId, item.type, qty)
console.log(`[contributeItem] result:`, result, 'isRetry:', isRetry, 'silent:', silent) console.log(`[contributeItem] result:`, result, 'isRetry:', isRetry, 'silent:', silent, 'qty:', qty)
// //
if (!result.success) { if (!result.success) {
@ -478,6 +486,7 @@ function deductLocalBalance(cost) {
// //
uni.setStorageSync('user', JSON.stringify(user)) uni.setStorageSync('user', JSON.stringify(user))
userInfo.value = user userInfo.value = user
crystalBalance.value = user.crystal_balance
uni.$emit('balanceUpdated', { crystal_balance: user.crystal_balance }) uni.$emit('balanceUpdated', { crystal_balance: user.crystal_balance })
} }
} catch (error) { } catch (error) {
@ -504,6 +513,7 @@ function refundLocalBalance(cost) {
// //
uni.setStorageSync('user', JSON.stringify(user)) uni.setStorageSync('user', JSON.stringify(user))
userInfo.value = user userInfo.value = user
crystalBalance.value = user.crystal_balance
uni.$emit('balanceUpdated', { crystal_balance: user.crystal_balance }) uni.$emit('balanceUpdated', { crystal_balance: user.crystal_balance })
} }
} catch (error) { } catch (error) {
@ -529,6 +539,7 @@ async function updateLocalBalanceFromResult(newBalance) {
// //
uni.setStorageSync('user', JSON.stringify(user)) uni.setStorageSync('user', JSON.stringify(user))
userInfo.value = user userInfo.value = user
crystalBalance.value = user.crystal_balance
uni.$emit('balanceUpdated', { crystal_balance: user.crystal_balance }) uni.$emit('balanceUpdated', { crystal_balance: user.crystal_balance })
} }
} catch (error) { } catch (error) {

View File

@ -574,6 +574,7 @@ const handleCloseClick = (e) => {
.back-icon { .back-icon {
font-size: 48rpx; font-size: 48rpx;
font-weight: bold; font-weight: bold;
color: #fff;
} }
/* Tab 样式 */ /* Tab 样式 */

View File

Before

Width:  |  Height:  |  Size: 2.3 MiB

After

Width:  |  Height:  |  Size: 2.3 MiB

View File

@ -681,6 +681,17 @@ export function purchaseActivityItemApi(activityId, itemType, quantity = 1) {
}) })
} }
// 批量购买活动道具
export function batchPurchaseActivityItemsApi(activityId, items) {
return request({
url: `/api/v1/activities/${activityId}/batch-purchase`,
method: 'POST',
data: {
items: items
}
})
}
// 获取活动最新贡献记录(实时轮询用) // 获取活动最新贡献记录(实时轮询用)
export function getActivityContributionsLatestApi(activityId, sinceTimestamp = 0, sinceId = 0, limit = 5) { export function getActivityContributionsLatestApi(activityId, sinceTimestamp = 0, sinceId = 0, limit = 5) {
return request({ return request({