2026-05-26 20:06:23 +08:00

134 lines
4.0 KiB
Go

package rechargereward
import (
"context"
"net/http"
"strings"
"time"
)
// GetHome 返回当前登录用户的充值奖励 H5 数据。
func (s *Service) GetHome(ctx context.Context, user AuthUser) (*RechargeRewardHomeResponse, error) {
sysOrigin, err := requireRechargeRewardUser(user)
if err != nil {
return nil, err
}
if s.java == nil {
return nil, NewAppError(http.StatusServiceUnavailable, "java_gateway_unavailable", "java gateway is unavailable")
}
bundle, err := s.loadConfigBundle(ctx, sysOrigin)
if err != nil {
return nil, err
}
location := s.location
if bundle.Config != nil {
location = resolveLocation(bundle.Config.Timezone, s.location)
}
now := time.Now().In(location)
period := s.displayPeriod(now, location)
currentPeriod, periodActive := s.currentPeriod(now, location)
var currentRechargeCents int64
if periodActive {
currentRechargeCents, err = s.loadCurrentRechargeCents(ctx, sysOrigin, user.UserID, currentPeriod)
if err != nil {
return nil, err
}
}
accumulatedRechargeCents, err := s.loadAccumulatedRechargeCents(ctx, user.UserID)
if err != nil {
return nil, err
}
resp := &RechargeRewardHomeResponse{
ActivityStatus: rechargeRewardActivityStatus(bundle.Config != nil && bundle.Config.Enabled),
Configured: bundle.Config != nil,
Enabled: bundle.Config != nil && bundle.Config.Enabled,
SysOrigin: sysOrigin,
Timezone: location.String(),
PeriodStartAt: formatDateTime(period.StartAt),
PeriodEndAt: formatDateTime(period.EndAt),
CountdownMillis: maxInt64(0, period.EndAt.UnixMilli()-now.UnixMilli()),
UserID: user.UserID,
CurrentRechargeAmount: formatAmountCents(currentRechargeCents),
CurrentRechargeAmountCents: currentRechargeCents,
AccumulatedRechargeAmount: formatAmountCents(accumulatedRechargeCents),
AccumulatedRechargeAmountCents: accumulatedRechargeCents,
LevelConfigs: []RechargeRewardLevelPayload{},
}
if bundle.Config != nil {
resp.SysOrigin = bundle.Config.SysOrigin
resp.Timezone = normalizeRechargeRewardTimezone(bundle.Config.Timezone)
}
if profile, err := s.java.GetUserProfile(ctx, user.UserID); err == nil {
resp.UserAccount = profile.Account
resp.UserNickname = profile.UserNickname
resp.UserAvatar = profile.UserAvatar
} else if !isEmptyJavaProfileError(err) {
return nil, err
}
if bundle.Config == nil {
return resp, nil
}
matched, matchedOK := pickMatchedLevel(bundle.Levels, currentRechargeCents)
next, nextOK := pickNextLevel(bundle.Levels, currentRechargeCents)
if matchedOK {
resp.MatchedLevel = matched.Level
}
if nextOK {
resp.NextLevel = next.Level
resp.NextRechargeAmount = formatAmountCents(next.RechargeAmountCents)
resp.NextRechargeAmountCents = next.RechargeAmountCents
}
rewardItems := s.loadRewardItemsMap(ctx, resp.SysOrigin, bundle.Levels)
matchedLevel := 0
if matchedOK {
matchedLevel = matched.Level
}
resp.LevelConfigs = buildLevelPayloads(bundle.Levels, rewardItems, currentRechargeCents, matchedLevel)
return resp, nil
}
func (s *Service) loadAccumulatedRechargeCents(ctx context.Context, userID int64) (int64, error) {
recharges, err := s.java.MapUserTotalRecharge(ctx, []int64{userID})
if err != nil {
return 0, err
}
return totalRechargeCents(recharges[userID]), nil
}
func resolveLocation(timezone string, fallback *time.Location) *time.Location {
location, err := time.LoadLocation(normalizeRechargeRewardTimezone(timezone))
if err == nil {
return location
}
if fallback != nil {
return fallback
}
return time.UTC
}
func rechargeRewardActivityStatus(enabled bool) string {
if enabled {
return rechargeRewardActivityStatusOngoing
}
return rechargeRewardActivityStatusDisabled
}
func isEmptyJavaProfileError(err error) bool {
if err == nil {
return false
}
return strings.Contains(strings.ToLower(err.Error()), "empty")
}
func maxInt64(a, b int64) int64 {
if a > b {
return a
}
return b
}