修复火箭内容

This commit is contained in:
hy001 2026-05-15 23:44:56 +08:00
parent ffd3eeddfd
commit 463d7374af
5 changed files with 212 additions and 13 deletions

View File

@ -83,7 +83,19 @@ func registerVoiceRoomRocketRoutes(
appGroup.GET("/reward-records", func(c *gin.Context) {
cursor, _ := strconv.Atoi(strings.TrimSpace(c.DefaultQuery("cursor", "1")))
limit, _ := strconv.Atoi(strings.TrimSpace(c.DefaultQuery("limit", "20")))
resp, err := service.PageRewardRecords(c.Request.Context(), mustAuthUser(c), parseInt64(c.Query("roomId")), cursor, limit)
user := mustAuthUser(c)
roomID := parseInt64(c.Query("roomId"))
launchNo := strings.TrimSpace(c.Query("launchNo"))
scope := strings.ToLower(strings.TrimSpace(c.Query("scope")))
var (
resp *voiceroomrocket.RewardRecordPageResponse
err error
)
if launchNo != "" || scope == "room" {
resp, err = service.PageRoomRewardRecords(c.Request.Context(), user, roomID, launchNo, cursor, limit)
} else {
resp, err = service.PageRewardRecords(c.Request.Context(), user, roomID, cursor, limit)
}
if err != nil {
writeError(c, err)
return

View File

@ -109,6 +109,103 @@ func TestProcessGiftPayloadDropsOverflowAndLaunchesOnce(t *testing.T) {
}
}
func TestPageRoomRewardRecordsReturnsAllLaunchWinnersWithProfiles(t *testing.T) {
service, db := newTestService(t)
ctx := context.Background()
gateway := newFakeRocketGateway()
gateway.profiles = map[int64]integration.UserProfile{
1001: {ID: integration.Int64Value(1001), Account: "1001026", UserNickname: "room1001026", UserAvatar: "https://avatar.example/1001.png"},
1002: {ID: integration.Int64Value(1002), Account: "1001027", UserNickname: "room1001027", UserAvatar: "https://avatar.example/1002.png"},
}
service.userProfiles = gateway
seedRocketConfig(t, db)
now := time.Now()
launch := model.VoiceRoomRocketLaunch{
ID: 1,
LaunchNo: "VRR-test-launch-1",
SysOrigin: "LIKEI",
RoomID: 9001,
DayKey: "2026-05-15",
RoundNo: 1,
Level: 3,
LaunchTime: now,
CreateTime: now,
UpdateTime: now,
}
if err := db.Create(&launch).Error; err != nil {
t.Fatalf("create launch: %v", err)
}
rewardItemID := int64(2001)
expireDays := 15
rows := []model.VoiceRoomRocketRewardRecord{
{
ID: 11,
LaunchID: launch.ID,
LaunchNo: launch.LaunchNo,
SysOrigin: "LIKEI",
RoomID: launch.RoomID,
DayKey: launch.DayKey,
RoundNo: launch.RoundNo,
Level: launch.Level,
UserID: 1001,
RewardScene: rewardSceneTop1,
RewardType: "GOLD",
RewardName: "Yumi",
RewardAmount: 5000,
GrantEventID: "grant-event-11",
GrantStatus: rewardStatusSuccess,
PopupStatus: popupStatusUnread,
CreateTime: now,
UpdateTime: now,
},
{
ID: 12,
LaunchID: launch.ID,
LaunchNo: launch.LaunchNo,
SysOrigin: "LIKEI",
RoomID: launch.RoomID,
DayKey: launch.DayKey,
RoundNo: launch.RoundNo,
Level: launch.Level,
UserID: 1002,
RewardScene: rewardSceneInRoom,
RewardType: "AVATAR_FRAME",
RewardItemID: &rewardItemID,
RewardName: "Frame",
RewardCover: "https://reward.example/frame.png",
RewardAmount: 1,
ExpireDays: &expireDays,
GrantEventID: "grant-event-12",
GrantStatus: rewardStatusSuccess,
PopupStatus: popupStatusUnread,
CreateTime: now.Add(time.Second),
UpdateTime: now.Add(time.Second),
},
}
if err := db.Create(&rows).Error; err != nil {
t.Fatalf("create reward records: %v", err)
}
resp, err := service.PageRoomRewardRecords(ctx, AuthUser{UserID: 9999, SysOrigin: "LIKEI"}, launch.RoomID, launch.LaunchNo, 1, 20)
if err != nil {
t.Fatalf("PageRoomRewardRecords() error = %v", err)
}
if len(resp.Records) != 2 {
t.Fatalf("records len = %d, want 2: %+v", len(resp.Records), resp.Records)
}
users := map[int64]RewardRecordView{}
for _, record := range resp.Records {
users[record.UserID] = record
}
if got := users[1001]; got.Account != "1001026" || got.UserNickname != "room1001026" || got.UserAvatar == "" {
t.Fatalf("user 1001 profile = %+v", got)
}
if got := users[1002]; got.Account != "1001027" || got.UserNickname != "room1001027" || got.UserAvatar == "" {
t.Fatalf("user 1002 profile = %+v", got)
}
}
func TestDecodeGiftEventPayloadEnvelope(t *testing.T) {
payload := `{"tag":"give_gift_v3","body":"{\"trackId\":\"t1\",\"sendUserId\":\"10\",\"roomId\":\"20\",\"giftValue\":{\"actualAmount\":\"30\"}}"}`
event, err := decodeGiftEventPayload(payload, "give_gift_v3")
@ -745,6 +842,7 @@ type fakeRocketGateway struct {
goldEvents map[string]integration.GoldReceiptCommand
props []integration.GivePropsBackpackRequest
badges []fakeBadgeGrant
profiles map[int64]integration.UserProfile
}
type fakeBadgeGrant struct {
@ -790,6 +888,12 @@ func (g *fakeRocketGateway) MapRoomProfiles(ctx context.Context, roomIDs []int64
}
func (g *fakeRocketGateway) GetUserProfile(ctx context.Context, userID int64) (integration.UserProfile, error) {
if profile, ok := g.profiles[userID]; ok {
if int64(profile.ID) == 0 {
profile.ID = integration.Int64Value(userID)
}
return profile, nil
}
return integration.UserProfile{ID: integration.Int64Value(userID), Account: strconv.FormatInt(userID, 10), UserNickname: "user", CountryCode: "SA"}, nil
}

View File

@ -333,6 +333,30 @@ func toRewardRecordView(row model.VoiceRoomRocketRewardRecord) RewardRecordView
}
}
func toRewardRecordViews(rows []model.VoiceRoomRocketRewardRecord, profiles map[int64]integration.UserProfile) []RewardRecordView {
records := make([]RewardRecordView, 0, len(rows))
for _, row := range rows {
view := toRewardRecordView(row)
if profile, ok := profiles[row.UserID]; ok {
applyRewardRecordProfile(&view, profile)
}
records = append(records, view)
}
return records
}
func applyRewardRecordProfile(view *RewardRecordView, profile integration.UserProfile) {
if strings.TrimSpace(profile.UserAvatar) != "" {
view.UserAvatar = profile.UserAvatar
}
if strings.TrimSpace(profile.UserNickname) != "" {
view.UserNickname = profile.UserNickname
}
if strings.TrimSpace(profile.Account) != "" {
view.Account = profile.Account
}
}
func toLaunchRecordView(row model.VoiceRoomRocketLaunch) LaunchRecordView {
return LaunchRecordView{
ID: row.ID,

View File

@ -3,6 +3,7 @@ package voiceroomrocket
import (
"context"
"net/http"
"strings"
"time"
"chatapp3-golang/internal/model"
@ -22,10 +23,7 @@ func (s *Service) ListRewardPopups(ctx context.Context, user AuthUser, roomID in
if err := query.Find(&rows).Error; err != nil {
return nil, err
}
records := make([]RewardRecordView, 0, len(rows))
for _, row := range rows {
records = append(records, toRewardRecordView(row))
}
records := toRewardRecordViews(rows, s.mapUserProfiles(ctx, rewardRecordUserIDs(rows)))
return &RewardPopupResponse{Records: records}, nil
}
@ -76,10 +74,7 @@ func (s *Service) PageRewardRecords(ctx context.Context, user AuthUser, roomID i
if err := query.Find(&rows).Error; err != nil {
return nil, err
}
records := make([]RewardRecordView, 0, len(rows))
for _, row := range rows {
records = append(records, toRewardRecordView(row))
}
records := toRewardRecordViews(rows, s.mapUserProfiles(ctx, rewardRecordUserIDs(rows)))
resp := &RewardRecordPageResponse{
Records: records,
Cursor: cursor,
@ -91,6 +86,54 @@ func (s *Service) PageRewardRecords(ctx context.Context, user AuthUser, roomID i
return resp, nil
}
// PageRoomRewardRecords 返回房间内某次火箭发射的全部中奖记录。
func (s *Service) PageRoomRewardRecords(ctx context.Context, user AuthUser, roomID int64, launchNo string, cursor int, limit int) (*RewardRecordPageResponse, error) {
cursor, limit = normalizePage(cursor, limit)
snapshot, err := s.loadConfig(ctx, user.SysOrigin)
if err != nil {
return nil, err
}
keepDays := snapshot.RewardRecordKeepDays
if keepDays <= 0 {
keepDays = defaultRewardRecordKeepDays
}
startAt := time.Now().AddDate(0, 0, -keepDays)
launchNo = strings.TrimSpace(launchNo)
if launchNo == "" {
query := s.repo.DB.WithContext(ctx).
Model(&model.VoiceRoomRocketRewardRecord{}).
Where("sys_origin = ? AND create_time >= ? AND launch_no <> ?", snapshot.SysOrigin, startAt, "").
Order("create_time DESC, id DESC").
Limit(1)
if roomID > 0 {
query = query.Where("room_id = ?", roomID)
}
var launchNos []string
if err := query.Pluck("launch_no", &launchNos).Error; err != nil {
return nil, err
}
if len(launchNos) == 0 {
return &RewardRecordPageResponse{Records: []RewardRecordView{}, Cursor: cursor, Limit: limit}, nil
}
launchNo = launchNos[0]
}
query := s.repo.DB.WithContext(ctx).
Where("sys_origin = ? AND launch_no = ? AND create_time >= ?", snapshot.SysOrigin, launchNo, startAt).
Order("create_time DESC, id DESC").
Offset((cursor - 1) * limit).
Limit(limit)
if roomID > 0 {
query = query.Where("room_id = ?", roomID)
}
var rows []model.VoiceRoomRocketRewardRecord
if err := query.Find(&rows).Error; err != nil {
return nil, err
}
records := toRewardRecordViews(rows, s.mapUserProfiles(ctx, rewardRecordUserIDs(rows)))
return &RewardRecordPageResponse{Records: records, Cursor: cursor, Limit: limit}, nil
}
// PageAdminLaunchRecords 返回后台发射记录。
func (s *Service) PageAdminLaunchRecords(ctx context.Context, sysOrigin string, roomID int64, cursor int, limit int) (*LaunchRecordPageResponse, error) {
cursor, limit = normalizePage(cursor, limit)
@ -134,9 +177,22 @@ func (s *Service) PageAdminRewardRecords(ctx context.Context, sysOrigin string,
if err := query.Find(&rows).Error; err != nil {
return nil, err
}
records := make([]RewardRecordView, 0, len(rows))
for _, row := range rows {
records = append(records, toRewardRecordView(row))
}
records := toRewardRecordViews(rows, s.mapUserProfiles(ctx, rewardRecordUserIDs(rows)))
return &RewardRecordPageResponse{Records: records, Cursor: cursor, Limit: limit}, nil
}
func rewardRecordUserIDs(rows []model.VoiceRoomRocketRewardRecord) []int64 {
seen := make(map[int64]struct{}, len(rows))
userIDs := make([]int64, 0, len(rows))
for _, row := range rows {
if row.UserID <= 0 {
continue
}
if _, ok := seen[row.UserID]; ok {
continue
}
seen[row.UserID] = struct{}{}
userIDs = append(userIDs, row.UserID)
}
return userIDs
}

View File

@ -457,6 +457,9 @@ type RewardRecordView struct {
RoundNo int `json:"roundNo"`
Level int `json:"level"`
UserID int64 `json:"userId,string"`
UserAvatar string `json:"userAvatar,omitempty"`
UserNickname string `json:"userNickname,omitempty"`
Account string `json:"account,omitempty"`
RewardScene string `json:"rewardScene"`
RewardType string `json:"rewardType"`
RewardItemID *int64 `json:"rewardItemId,string,omitempty"`