拆分大型 Repository 文件职责
This commit is contained in:
@@ -0,0 +1,242 @@
|
||||
package listing
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"gorm.io/datatypes"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
func (r *Repository) ListPublic(ctx context.Context, query PublicListQuery) (*PublicListResult, error) {
|
||||
page, pageSize := normalizedPublicPage(query)
|
||||
if canListPublicWithSQL(query) {
|
||||
return r.listPublicPage(ctx, query, page, pageSize)
|
||||
}
|
||||
|
||||
var rows []listingRow
|
||||
err := r.baseQuery(ctx).
|
||||
Where("l.status = ? AND l.review_status = ? AND l.in_transaction = ?", "published", "approved", false).
|
||||
Order("l.published_at DESC, l.id DESC").
|
||||
Scan(&rows).Error
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
items := publicListings(rowsToDTO(rows))
|
||||
baseQuery := query
|
||||
baseQuery.Zone = ""
|
||||
items = filterPublicListings(items, baseQuery)
|
||||
zoneCounts := publicZoneCounts(items)
|
||||
if query.Zone != "" && query.Zone != "all" {
|
||||
items = filterPublicListings(items, query)
|
||||
}
|
||||
sortPublicListings(items, query.Sort)
|
||||
total := int64(len(items))
|
||||
start := (page - 1) * pageSize
|
||||
if start < 0 {
|
||||
start = 0
|
||||
}
|
||||
if start >= len(items) {
|
||||
items = []ListingDTO{}
|
||||
} else {
|
||||
end := start + pageSize
|
||||
if end > len(items) {
|
||||
end = len(items)
|
||||
}
|
||||
items = items[start:end]
|
||||
}
|
||||
return &PublicListResult{
|
||||
Items: items,
|
||||
Total: total,
|
||||
Page: page,
|
||||
PageSize: pageSize,
|
||||
ZoneCounts: zoneCounts,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (r *Repository) listPublicPage(ctx context.Context, query PublicListQuery, page int, pageSize int) (*PublicListResult, error) {
|
||||
var total int64
|
||||
if err := r.db.WithContext(ctx).Table("rental_listings AS l").
|
||||
Where("l.status = ? AND l.review_status = ? AND l.in_transaction = ?", "published", "approved", false).
|
||||
Count(&total).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var rows []listingRow
|
||||
offset := (page - 1) * pageSize
|
||||
err := applyPublicSQLSort(r.baseQuery(ctx), query.Sort).
|
||||
Where("l.status = ? AND l.review_status = ? AND l.in_transaction = ?", "published", "approved", false).
|
||||
Limit(pageSize).
|
||||
Offset(offset).
|
||||
Scan(&rows).Error
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
zoneCounts, err := r.publicZoneCountsCached(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &PublicListResult{
|
||||
Items: publicListings(rowsToDTO(rows)),
|
||||
Total: total,
|
||||
Page: page,
|
||||
PageSize: pageSize,
|
||||
ZoneCounts: zoneCounts,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func normalizedPublicPage(query PublicListQuery) (int, int) {
|
||||
page := query.Page
|
||||
if page <= 0 {
|
||||
page = 1
|
||||
}
|
||||
pageSize := query.PageSize
|
||||
if pageSize <= 0 {
|
||||
pageSize = 20
|
||||
}
|
||||
if pageSize > 50 {
|
||||
pageSize = 50
|
||||
}
|
||||
return page, pageSize
|
||||
}
|
||||
|
||||
func canListPublicWithSQL(query PublicListQuery) bool {
|
||||
if query.Keyword != "" {
|
||||
return false
|
||||
}
|
||||
if query.Zone != "" && query.Zone != "all" {
|
||||
return false
|
||||
}
|
||||
if len(query.Server) > 0 || len(query.Region) > 0 || len(query.LoginMethod) > 0 || len(query.Rank) > 0 {
|
||||
return false
|
||||
}
|
||||
if len(query.Insurance) > 0 || len(query.Stamina) > 0 || len(query.Load) > 0 {
|
||||
return false
|
||||
}
|
||||
if len(query.SkinGroup) > 0 || len(query.SkinName) > 0 || len(query.ResourceRanges) > 0 {
|
||||
return false
|
||||
}
|
||||
if query.MinCoin != nil || query.MaxCoin != nil || query.MinPrice != nil || query.MaxPrice != nil {
|
||||
return false
|
||||
}
|
||||
if query.MinDeposit != nil || query.MaxDeposit != nil || query.MinTotal != nil || query.MaxTotal != nil {
|
||||
return false
|
||||
}
|
||||
if query.MinFireLevel != nil || query.MaxFireLevel != nil || query.MinSecretKD != nil || query.MaxSecretKD != nil {
|
||||
return false
|
||||
}
|
||||
switch query.Sort {
|
||||
case "", "published", "recommended", "comprehensive", "priceAsc", "priceDesc", "coinDesc":
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
func applyPublicSQLSort(db *gorm.DB, sortKey string) *gorm.DB {
|
||||
switch sortKey {
|
||||
case "priceAsc":
|
||||
return db.Order("l.price_cent ASC, l.published_at DESC, l.id DESC")
|
||||
case "priceDesc":
|
||||
return db.Order("l.price_cent DESC, l.published_at DESC, l.id DESC")
|
||||
case "coinDesc":
|
||||
return db.Order("a.haf_coin_amount DESC, l.published_at DESC, l.id DESC")
|
||||
default:
|
||||
return db.Order("l.published_at DESC, l.id DESC")
|
||||
}
|
||||
}
|
||||
|
||||
func (r *Repository) publicZoneCountsCached(ctx context.Context) (map[string]int64, error) {
|
||||
now := time.Now()
|
||||
r.publicZoneCountsMu.Lock()
|
||||
defer r.publicZoneCountsMu.Unlock()
|
||||
if r.publicZoneCounts.Counts != nil && now.Before(r.publicZoneCounts.ExpiresAt) {
|
||||
return copyPublicZoneCounts(r.publicZoneCounts.Counts), nil
|
||||
}
|
||||
|
||||
var rows []publicZoneRow
|
||||
err := r.db.WithContext(ctx).Table("rental_listings AS l").
|
||||
Select("a.login_platform, a.haf_coin_amount, a.asset_summary").
|
||||
Joins("JOIN game_accounts AS a ON a.id = l.account_id").
|
||||
Where("l.status = ? AND l.review_status = ? AND l.in_transaction = ?", "published", "approved", false).
|
||||
Scan(&rows).Error
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
counts := map[string]int64{
|
||||
"all": int64(len(rows)),
|
||||
"sale": 0,
|
||||
"gift": 0,
|
||||
"night": 0,
|
||||
"password": 0,
|
||||
"highCoin": 0,
|
||||
}
|
||||
for _, row := range rows {
|
||||
summary := decodeAssetSummary(row.AssetSummary)
|
||||
if isAcceleratedSale(summary) {
|
||||
counts["sale"]++
|
||||
}
|
||||
if hasGiftResourcesSummary(summary) {
|
||||
counts["gift"]++
|
||||
}
|
||||
if isNightAvailableSummary(summary) {
|
||||
counts["night"]++
|
||||
}
|
||||
if strings.Contains(row.LoginPlatform, "账密") || strings.Contains(row.LoginPlatform, "账号密码") {
|
||||
counts["password"]++
|
||||
}
|
||||
if float64(row.HafCoinAmount)/1000000 >= 100 {
|
||||
counts["highCoin"]++
|
||||
}
|
||||
}
|
||||
r.publicZoneCounts = publicZoneCountCache{
|
||||
Counts: counts,
|
||||
ExpiresAt: now.Add(publicZoneCountCacheTTL),
|
||||
}
|
||||
return copyPublicZoneCounts(counts), nil
|
||||
}
|
||||
|
||||
func copyPublicZoneCounts(counts map[string]int64) map[string]int64 {
|
||||
copied := make(map[string]int64, len(counts))
|
||||
for key, value := range counts {
|
||||
copied[key] = value
|
||||
}
|
||||
return copied
|
||||
}
|
||||
|
||||
func (r *Repository) FindPublic(ctx context.Context, id uint64) (*ListingDTO, error) {
|
||||
dto, err := r.findDTO(ctx, "l.id = ? AND l.status = ? AND l.review_status = ? AND l.in_transaction = ?", id, "published", "approved", false)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
applyPublicListingURLs(dto)
|
||||
return dto, nil
|
||||
}
|
||||
|
||||
func (r *Repository) FindPublicCoverKey(ctx context.Context, id uint64) (string, error) {
|
||||
return r.FindPublicScreenshotKey(ctx, id, 0)
|
||||
}
|
||||
|
||||
func (r *Repository) FindPublicScreenshotKey(ctx context.Context, id uint64, index int) (string, error) {
|
||||
if index < 0 {
|
||||
return "", gorm.ErrRecordNotFound
|
||||
}
|
||||
dto, err := r.findDTO(ctx, "l.id = ? AND l.status = ? AND l.review_status = ? AND l.in_transaction = ?", id, "published", "approved", false)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if index >= len(dto.ScreenshotURLS) {
|
||||
return "", gorm.ErrRecordNotFound
|
||||
}
|
||||
if key := extractListingObjectKey(dto.ScreenshotURLS[index]); key != "" {
|
||||
return key, nil
|
||||
}
|
||||
return "", gorm.ErrRecordNotFound
|
||||
}
|
||||
|
||||
type publicZoneRow struct {
|
||||
LoginPlatform string
|
||||
HafCoinAmount int64
|
||||
AssetSummary datatypes.JSON `gorm:"column:asset_summary"`
|
||||
}
|
||||
Reference in New Issue
Block a user