351 lines
12 KiB
Go
351 lines
12 KiB
Go
package weeklystar
|
|
|
|
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 cycleRequest struct {
|
|
CycleID string `json:"cycle_id"`
|
|
Title string `json:"title"`
|
|
Status string `json:"status"`
|
|
RegionID int64 `json:"region_id"`
|
|
StartMS int64 `json:"start_ms"`
|
|
EndMS int64 `json:"end_ms"`
|
|
GiftIDs []string `json:"gift_ids"`
|
|
Gifts []giftDTO `json:"gifts"`
|
|
Rewards []rewardDTO `json:"rewards"`
|
|
Top1ResourceGroupID int64 `json:"top1_resource_group_id"`
|
|
Top2ResourceGroupID int64 `json:"top2_resource_group_id"`
|
|
Top3ResourceGroupID int64 `json:"top3_resource_group_id"`
|
|
}
|
|
|
|
type statusRequest struct {
|
|
Status string `json:"status"`
|
|
}
|
|
|
|
type cycleDTO struct {
|
|
AppCode string `json:"app_code,omitempty"`
|
|
CycleID string `json:"cycle_id"`
|
|
ActivityCode string `json:"activity_code"`
|
|
RegionID int64 `json:"region_id"`
|
|
Title string `json:"title"`
|
|
Status string `json:"status"`
|
|
StartMS int64 `json:"start_ms"`
|
|
EndMS int64 `json:"end_ms"`
|
|
Gifts []giftDTO `json:"gifts"`
|
|
Rewards []rewardDTO `json:"rewards"`
|
|
CreatedByAdminID int64 `json:"created_by_admin_id"`
|
|
UpdatedByAdminID int64 `json:"updated_by_admin_id"`
|
|
SettledAtMS int64 `json:"settled_at_ms"`
|
|
CreatedAtMS int64 `json:"created_at_ms"`
|
|
UpdatedAtMS int64 `json:"updated_at_ms"`
|
|
}
|
|
|
|
type giftDTO struct {
|
|
GiftID string `json:"gift_id"`
|
|
SortOrder int32 `json:"sort_order"`
|
|
}
|
|
|
|
type rewardDTO struct {
|
|
RankNo int32 `json:"rank_no"`
|
|
ResourceGroupID int64 `json:"resource_group_id"`
|
|
}
|
|
|
|
type leaderboardEntryDTO struct {
|
|
RankNo int32 `json:"rank_no"`
|
|
UserID int64 `json:"user_id"`
|
|
Score int64 `json:"score"`
|
|
FirstScoredAtMS int64 `json:"first_scored_at_ms"`
|
|
LastScoredAtMS int64 `json:"last_scored_at_ms"`
|
|
DisplayUserID string `json:"display_user_id,omitempty"`
|
|
Username string `json:"username,omitempty"`
|
|
Avatar string `json:"avatar,omitempty"`
|
|
}
|
|
|
|
type settlementDTO struct {
|
|
SettlementID string `json:"settlement_id"`
|
|
CycleID string `json:"cycle_id"`
|
|
RankNo int32 `json:"rank_no"`
|
|
UserID int64 `json:"user_id"`
|
|
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) ListCycles(c *gin.Context) {
|
|
options := shared.ListOptions(c)
|
|
resp, err := h.activity.ListWeeklyStarCycles(c.Request.Context(), &activityv1.ListWeeklyStarCyclesRequest{
|
|
Meta: h.meta(c),
|
|
Status: strings.TrimSpace(options.Status),
|
|
StartMs: parseInt64Query(c, "start_ms"),
|
|
EndMs: parseInt64Query(c, "end_ms"),
|
|
RegionId: parseInt64Query(c, "region_id"),
|
|
Page: int32(options.Page),
|
|
PageSize: int32(options.PageSize),
|
|
})
|
|
if err != nil {
|
|
response.ServerError(c, "获取周星周期失败")
|
|
return
|
|
}
|
|
items := make([]cycleDTO, 0, len(resp.GetCycles()))
|
|
for _, cycle := range resp.GetCycles() {
|
|
items = append(items, cycleFromProto(cycle))
|
|
}
|
|
response.OK(c, response.Page{Items: items, Page: options.Page, PageSize: options.PageSize, Total: resp.GetTotal()})
|
|
}
|
|
|
|
func (h *Handler) CreateCycle(c *gin.Context) {
|
|
var req cycleRequest
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
|
response.BadRequest(c, "周星周期参数不正确")
|
|
return
|
|
}
|
|
resp, err := h.activity.CreateWeeklyStarCycle(c.Request.Context(), &activityv1.UpsertWeeklyStarCycleRequest{
|
|
Meta: h.meta(c),
|
|
Cycle: req.toProto(),
|
|
OperatorAdminId: int64(middleware.CurrentUserID(c)),
|
|
})
|
|
if err != nil {
|
|
response.BadRequest(c, err.Error())
|
|
return
|
|
}
|
|
item := cycleFromProto(resp.GetCycle())
|
|
shared.OperationLogWithResourceID(c, h.audit, "create-weekly-star-cycle", "weekly_star_cycles", item.CycleID, "success", "")
|
|
response.OK(c, item)
|
|
}
|
|
|
|
func (h *Handler) GetCycle(c *gin.Context) {
|
|
cycleID := strings.TrimSpace(c.Param("cycle_id"))
|
|
resp, err := h.activity.GetWeeklyStarCycle(c.Request.Context(), &activityv1.GetWeeklyStarCycleRequest{Meta: h.meta(c), CycleId: cycleID})
|
|
if err != nil {
|
|
response.ServerError(c, "获取周星周期详情失败")
|
|
return
|
|
}
|
|
response.OK(c, cycleFromProto(resp.GetCycle()))
|
|
}
|
|
|
|
func (h *Handler) UpdateCycle(c *gin.Context) {
|
|
var req cycleRequest
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
|
response.BadRequest(c, "周星周期参数不正确")
|
|
return
|
|
}
|
|
req.CycleID = strings.TrimSpace(c.Param("cycle_id"))
|
|
resp, err := h.activity.UpdateWeeklyStarCycle(c.Request.Context(), &activityv1.UpsertWeeklyStarCycleRequest{
|
|
Meta: h.meta(c),
|
|
Cycle: req.toProto(),
|
|
OperatorAdminId: int64(middleware.CurrentUserID(c)),
|
|
})
|
|
if err != nil {
|
|
response.BadRequest(c, err.Error())
|
|
return
|
|
}
|
|
item := cycleFromProto(resp.GetCycle())
|
|
shared.OperationLogWithResourceID(c, h.audit, "update-weekly-star-cycle", "weekly_star_cycles", item.CycleID, "success", "")
|
|
response.OK(c, item)
|
|
}
|
|
|
|
func (h *Handler) SetCycleStatus(c *gin.Context) {
|
|
var req statusRequest
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
|
response.BadRequest(c, "周星周期状态参数不正确")
|
|
return
|
|
}
|
|
cycleID := strings.TrimSpace(c.Param("cycle_id"))
|
|
resp, err := h.activity.SetWeeklyStarCycleStatus(c.Request.Context(), &activityv1.SetWeeklyStarCycleStatusRequest{
|
|
Meta: h.meta(c),
|
|
CycleId: cycleID,
|
|
Status: strings.TrimSpace(req.Status),
|
|
OperatorAdminId: int64(middleware.CurrentUserID(c)),
|
|
})
|
|
if err != nil {
|
|
response.BadRequest(c, err.Error())
|
|
return
|
|
}
|
|
item := cycleFromProto(resp.GetCycle())
|
|
shared.OperationLogWithResourceID(c, h.audit, "set-weekly-star-cycle-status", "weekly_star_cycles", item.CycleID, "success", "")
|
|
response.OK(c, item)
|
|
}
|
|
|
|
func (h *Handler) ListLeaderboard(c *gin.Context) {
|
|
resp, err := h.activity.ListWeeklyStarLeaderboard(c.Request.Context(), &activityv1.ListWeeklyStarLeaderboardRequest{
|
|
Meta: h.meta(c),
|
|
CycleId: strings.TrimSpace(c.Param("cycle_id")),
|
|
PageSize: int32(parseIntQuery(c, "page_size", 50)),
|
|
PageToken: strings.TrimSpace(c.Query("page_token")),
|
|
})
|
|
if err != nil {
|
|
response.ServerError(c, "获取周星排行榜失败")
|
|
return
|
|
}
|
|
items := make([]leaderboardEntryDTO, 0, len(resp.GetEntries()))
|
|
for _, entry := range resp.GetEntries() {
|
|
items = append(items, leaderboardEntryFromProto(entry))
|
|
}
|
|
response.OK(c, gin.H{"cycle": cycleFromProto(resp.GetCycle()), "items": items, "total": resp.GetTotal(), "next_page_token": resp.GetNextPageToken()})
|
|
}
|
|
|
|
func (h *Handler) ListSettlements(c *gin.Context) {
|
|
resp, err := h.activity.ListWeeklyStarSettlements(c.Request.Context(), &activityv1.ListWeeklyStarSettlementsRequest{
|
|
Meta: h.meta(c),
|
|
CycleId: strings.TrimSpace(c.Param("cycle_id")),
|
|
})
|
|
if err != nil {
|
|
response.ServerError(c, "获取周星结算记录失败")
|
|
return
|
|
}
|
|
items := make([]settlementDTO, 0, len(resp.GetSettlements()))
|
|
for _, settlement := range resp.GetSettlements() {
|
|
items = append(items, settlementFromProto(settlement))
|
|
}
|
|
response.OK(c, items)
|
|
}
|
|
|
|
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().UnixMilli(),
|
|
}
|
|
}
|
|
|
|
func (r cycleRequest) toProto() *activityv1.WeeklyStarCycle {
|
|
gifts := make([]*activityv1.WeeklyStarGift, 0, 3)
|
|
if len(r.Gifts) > 0 {
|
|
for _, gift := range r.Gifts {
|
|
gifts = append(gifts, &activityv1.WeeklyStarGift{GiftId: strings.TrimSpace(gift.GiftID), SortOrder: gift.SortOrder})
|
|
}
|
|
} else {
|
|
for index, giftID := range r.GiftIDs {
|
|
gifts = append(gifts, &activityv1.WeeklyStarGift{GiftId: strings.TrimSpace(giftID), SortOrder: int32(index + 1)})
|
|
}
|
|
}
|
|
rewards := make([]*activityv1.WeeklyStarReward, 0, 3)
|
|
if len(r.Rewards) > 0 {
|
|
for _, reward := range r.Rewards {
|
|
rewards = append(rewards, &activityv1.WeeklyStarReward{RankNo: reward.RankNo, ResourceGroupId: reward.ResourceGroupID})
|
|
}
|
|
} else {
|
|
rewards = append(rewards,
|
|
&activityv1.WeeklyStarReward{RankNo: 1, ResourceGroupId: r.Top1ResourceGroupID},
|
|
&activityv1.WeeklyStarReward{RankNo: 2, ResourceGroupId: r.Top2ResourceGroupID},
|
|
&activityv1.WeeklyStarReward{RankNo: 3, ResourceGroupId: r.Top3ResourceGroupID},
|
|
)
|
|
}
|
|
return &activityv1.WeeklyStarCycle{
|
|
CycleId: strings.TrimSpace(r.CycleID),
|
|
RegionId: r.RegionID,
|
|
Title: strings.TrimSpace(r.Title),
|
|
Status: strings.TrimSpace(r.Status),
|
|
StartMs: r.StartMS,
|
|
EndMs: r.EndMS,
|
|
Gifts: gifts,
|
|
Rewards: rewards,
|
|
}
|
|
}
|
|
|
|
func cycleFromProto(cycle *activityv1.WeeklyStarCycle) cycleDTO {
|
|
if cycle == nil {
|
|
return cycleDTO{Gifts: []giftDTO{}, Rewards: []rewardDTO{}}
|
|
}
|
|
gifts := make([]giftDTO, 0, len(cycle.GetGifts()))
|
|
for _, gift := range cycle.GetGifts() {
|
|
gifts = append(gifts, giftDTO{GiftID: gift.GetGiftId(), SortOrder: gift.GetSortOrder()})
|
|
}
|
|
rewards := make([]rewardDTO, 0, len(cycle.GetRewards()))
|
|
for _, reward := range cycle.GetRewards() {
|
|
rewards = append(rewards, rewardDTO{RankNo: reward.GetRankNo(), ResourceGroupID: reward.GetResourceGroupId()})
|
|
}
|
|
return cycleDTO{
|
|
AppCode: cycle.GetAppCode(),
|
|
CycleID: cycle.GetCycleId(),
|
|
ActivityCode: cycle.GetActivityCode(),
|
|
RegionID: cycle.GetRegionId(),
|
|
Title: cycle.GetTitle(),
|
|
Status: cycle.GetStatus(),
|
|
StartMS: cycle.GetStartMs(),
|
|
EndMS: cycle.GetEndMs(),
|
|
Gifts: gifts,
|
|
Rewards: rewards,
|
|
CreatedByAdminID: cycle.GetCreatedByAdminId(),
|
|
UpdatedByAdminID: cycle.GetUpdatedByAdminId(),
|
|
SettledAtMS: cycle.GetSettledAtMs(),
|
|
CreatedAtMS: cycle.GetCreatedAtMs(),
|
|
UpdatedAtMS: cycle.GetUpdatedAtMs(),
|
|
}
|
|
}
|
|
|
|
func leaderboardEntryFromProto(entry *activityv1.WeeklyStarLeaderboardEntry) leaderboardEntryDTO {
|
|
if entry == nil {
|
|
return leaderboardEntryDTO{}
|
|
}
|
|
return leaderboardEntryDTO{
|
|
RankNo: entry.GetRankNo(),
|
|
UserID: entry.GetUserId(),
|
|
Score: entry.GetScore(),
|
|
FirstScoredAtMS: entry.GetFirstScoredAtMs(),
|
|
LastScoredAtMS: entry.GetLastScoredAtMs(),
|
|
}
|
|
}
|
|
|
|
func settlementFromProto(settlement *activityv1.WeeklyStarSettlement) settlementDTO {
|
|
if settlement == nil {
|
|
return settlementDTO{}
|
|
}
|
|
return settlementDTO{
|
|
SettlementID: settlement.GetSettlementId(),
|
|
CycleID: settlement.GetCycleId(),
|
|
RankNo: settlement.GetRankNo(),
|
|
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
|
|
}
|
|
|
|
func parseIntQuery(c *gin.Context, key string, fallback int) int {
|
|
value, err := strconv.Atoi(strings.TrimSpace(c.Query(key)))
|
|
if err != nil || value <= 0 {
|
|
return fallback
|
|
}
|
|
return value
|
|
}
|