package voiceroomrocket import ( "context" "net/http" "strings" "time" "chatapp3-golang/internal/model" ) // ListRewardPopups 返回当前用户未读中奖弹窗记录。 func (s *Service) ListRewardPopups(ctx context.Context, user AuthUser, roomID int64) (*RewardPopupResponse, error) { sysOrigin := s.normalizeSysOrigin(user.SysOrigin) query := s.repo.DB.WithContext(ctx). Where("sys_origin = ? AND user_id = ? AND popup_status = ?", sysOrigin, user.UserID, popupStatusUnread). Order("create_time DESC, id DESC"). Limit(100) 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 &RewardPopupResponse{Records: records}, nil } // AckRewardPopups 标记中奖弹窗为已读。 func (s *Service) AckRewardPopups(ctx context.Context, user AuthUser, req AckRewardPopupsRequest) error { if len(req.RewardRecordIDs) == 0 { return NewAppError(http.StatusBadRequest, "missing_reward_record_ids", "rewardRecordIds is required") } ids := make([]int64, 0, len(req.RewardRecordIDs)) for _, id := range req.RewardRecordIDs { if id.Int64() > 0 { ids = append(ids, id.Int64()) } } if len(ids) == 0 { return NewAppError(http.StatusBadRequest, "missing_reward_record_ids", "rewardRecordIds is required") } return s.repo.DB.WithContext(ctx). Model(&model.VoiceRoomRocketRewardRecord{}). Where("sys_origin = ? AND user_id = ? AND id IN ?", s.normalizeSysOrigin(user.SysOrigin), user.UserID, ids). Updates(map[string]any{ "popup_status": popupStatusRead, "update_time": time.Now(), }).Error } // PageRewardRecords 返回用户最近中奖记录。 func (s *Service) PageRewardRecords(ctx context.Context, user AuthUser, roomID int64, 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) query := s.repo.DB.WithContext(ctx). Where("sys_origin = ? AND user_id = ? AND create_time >= ?", snapshot.SysOrigin, user.UserID, 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))) resp := &RewardRecordPageResponse{ Records: records, Cursor: cursor, Limit: limit, } if len(records) == 0 { resp.EmptyReason = "仅展示最近 35 天的记录" } 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) query := s.repo.DB.WithContext(ctx). Where("sys_origin = ?", s.normalizeSysOrigin(sysOrigin)). Order("launch_time DESC, id DESC"). Offset((cursor - 1) * limit). Limit(limit) if roomID > 0 { query = query.Where("room_id = ?", roomID) } var rows []model.VoiceRoomRocketLaunch if err := query.Find(&rows).Error; err != nil { return nil, err } records := make([]LaunchRecordView, 0, len(rows)) for _, row := range rows { records = append(records, toLaunchRecordView(row)) } return &LaunchRecordPageResponse{Records: records, Cursor: cursor, Limit: limit}, nil } // PageAdminRewardRecords 返回后台奖励记录。 func (s *Service) PageAdminRewardRecords(ctx context.Context, sysOrigin string, roomID int64, userID int64, grantStatus string, cursor int, limit int) (*RewardRecordPageResponse, error) { cursor, limit = normalizePage(cursor, limit) query := s.repo.DB.WithContext(ctx). Where("sys_origin = ?", s.normalizeSysOrigin(sysOrigin)). Order("create_time DESC, id DESC"). Offset((cursor - 1) * limit). Limit(limit) if roomID > 0 { query = query.Where("room_id = ?", roomID) } if userID > 0 { query = query.Where("user_id = ?", userID) } if grantStatus != "" { query = query.Where("grant_status = ?", grantStatus) } 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 } 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 }