package cpweeklyrank import ( "strconv" "strings" "time" "hyapp-admin-server/internal/appctx" "hyapp-admin-server/internal/integration/activityclient" "hyapp-admin-server/internal/middleware" "hyapp-admin-server/internal/modules/shared" "hyapp-admin-server/internal/response" activityv1 "hyapp.local/api/proto/activity/v1" "github.com/gin-gonic/gin" ) type Handler struct { activity activityclient.Client audit shared.OperationLogger } func New(activity activityclient.Client, audit shared.OperationLogger) *Handler { return &Handler{activity: activity, audit: audit} } type configRequest struct { Enabled bool `json:"enabled"` TopCount int32 `json:"top_count"` Rewards []rewardDTO `json:"rewards"` } type configDTO struct { AppCode string `json:"app_code"` ActivityCode string `json:"activity_code"` Enabled bool `json:"enabled"` RelationType string `json:"relation_type"` TopCount int32 `json:"top_count"` Rewards []rewardDTO `json:"rewards"` UpdatedByAdminID int64 `json:"updated_by_admin_id,string"` CreatedAtMS int64 `json:"created_at_ms"` UpdatedAtMS int64 `json:"updated_at_ms"` } type rewardDTO struct { RankNo int32 `json:"rank_no"` ResourceGroupID int64 `json:"resource_group_id"` } type settlementDTO struct { SettlementID string `json:"settlement_id"` PeriodStartMS int64 `json:"period_start_ms"` PeriodEndMS int64 `json:"period_end_ms"` RankNo int32 `json:"rank_no"` RelationshipID string `json:"relationship_id"` UserID int64 `json:"user_id,string"` Score int64 `json:"score"` ResourceGroupID int64 `json:"resource_group_id"` WalletCommandID string `json:"wallet_command_id"` WalletGrantID string `json:"wallet_grant_id"` Status string `json:"status"` FailureReason string `json:"failure_reason"` AttemptCount int32 `json:"attempt_count"` CreatedAtMS int64 `json:"created_at_ms"` UpdatedAtMS int64 `json:"updated_at_ms"` } func (h *Handler) GetConfig(c *gin.Context) { resp, err := h.activity.GetCPWeeklyRankConfig(c.Request.Context(), &activityv1.GetCPWeeklyRankConfigRequest{Meta: h.meta(c)}) if err != nil { response.ServerError(c, "获取CP排行活动配置失败") return } response.OK(c, configFromProto(resp.GetConfig())) } func (h *Handler) UpdateConfig(c *gin.Context) { var req configRequest if err := c.ShouldBindJSON(&req); err != nil { response.BadRequest(c, "CP排行活动配置参数不正确") return } resp, err := h.activity.UpdateCPWeeklyRankConfig(c.Request.Context(), &activityv1.UpdateCPWeeklyRankConfigRequest{ Meta: h.meta(c), Config: req.toProto(), OperatorAdminId: int64(middleware.CurrentUserID(c)), }) if err != nil { response.BadRequest(c, err.Error()) return } item := configFromProto(resp.GetConfig()) shared.OperationLogWithResourceID(c, h.audit, "update-cp-weekly-rank-config", "cp_weekly_rank_configs", item.AppCode, "success", "") response.OK(c, item) } func (h *Handler) ListSettlements(c *gin.Context) { periodStartMS := parseInt64Query(c, "period_start_ms") periodEndMS := parseInt64Query(c, "period_end_ms") resp, err := h.activity.ListCPWeeklyRankSettlements(c.Request.Context(), &activityv1.ListCPWeeklyRankSettlementsRequest{ Meta: h.meta(c), PeriodStartMs: periodStartMS, PeriodEndMs: periodEndMS, }) if err != nil { response.ServerError(c, "获取CP排行活动发奖记录失败") return } items := make([]settlementDTO, 0, len(resp.GetSettlements())) for _, settlement := range resp.GetSettlements() { items = append(items, settlementFromProto(settlement)) } response.OK(c, gin.H{"items": items, "total": len(items), "period_start_ms": periodStartMS, "period_end_ms": periodEndMS}) } func (h *Handler) meta(c *gin.Context) *activityv1.RequestMeta { return &activityv1.RequestMeta{ RequestId: middleware.CurrentRequestID(c), Caller: "admin-server", AppCode: appctx.FromContext(c.Request.Context()), SentAtMs: time.Now().UTC().UnixMilli(), } } func (r configRequest) toProto() *activityv1.CPWeeklyRankConfig { topCount := r.TopCount if topCount <= 0 { topCount = 3 } rewards := make([]*activityv1.CPWeeklyRankReward, 0, len(r.Rewards)) for _, reward := range r.Rewards { // activity-service 会按 top_count 归一化和校验;admin-server 只做传输层适配, // 保留原 rank/resource_group 组合,避免两个服务出现不同的配置裁决口径。 rewards = append(rewards, &activityv1.CPWeeklyRankReward{RankNo: reward.RankNo, ResourceGroupId: reward.ResourceGroupID}) } return &activityv1.CPWeeklyRankConfig{ ActivityCode: "cp_weekly_rank", Enabled: r.Enabled, RelationType: "cp", TopCount: topCount, Rewards: rewards, } } func configFromProto(config *activityv1.CPWeeklyRankConfig) configDTO { if config == nil { return configDTO{ActivityCode: "cp_weekly_rank", Enabled: true, RelationType: "cp", TopCount: 3, Rewards: []rewardDTO{}} } rewards := make([]rewardDTO, 0, len(config.GetRewards())) for _, reward := range config.GetRewards() { rewards = append(rewards, rewardDTO{RankNo: reward.GetRankNo(), ResourceGroupID: reward.GetResourceGroupId()}) } return configDTO{ AppCode: config.GetAppCode(), ActivityCode: config.GetActivityCode(), Enabled: config.GetEnabled(), RelationType: config.GetRelationType(), TopCount: config.GetTopCount(), Rewards: rewards, UpdatedByAdminID: config.GetUpdatedByAdminId(), CreatedAtMS: config.GetCreatedAtMs(), UpdatedAtMS: config.GetUpdatedAtMs(), } } func settlementFromProto(settlement *activityv1.CPWeeklyRankSettlement) settlementDTO { if settlement == nil { return settlementDTO{} } return settlementDTO{ SettlementID: settlement.GetSettlementId(), PeriodStartMS: settlement.GetPeriodStartMs(), PeriodEndMS: settlement.GetPeriodEndMs(), RankNo: settlement.GetRankNo(), RelationshipID: settlement.GetRelationshipId(), UserID: settlement.GetUserId(), Score: settlement.GetScore(), ResourceGroupID: settlement.GetResourceGroupId(), WalletCommandID: settlement.GetWalletCommandId(), WalletGrantID: settlement.GetWalletGrantId(), Status: settlement.GetStatus(), FailureReason: settlement.GetFailureReason(), AttemptCount: settlement.GetAttemptCount(), CreatedAtMS: settlement.GetCreatedAtMs(), UpdatedAtMS: settlement.GetUpdatedAtMs(), } } func parseInt64Query(c *gin.Context, key string) int64 { value, _ := strconv.ParseInt(strings.TrimSpace(c.Query(key)), 10, 64) return value }