添加商品管理资产皮肤筛选

This commit is contained in:
yml2213
2026-07-05 20:21:18 +08:00
parent 090a90a268
commit 1984e07e91
8 changed files with 612 additions and 2 deletions
@@ -0,0 +1,45 @@
package listing
func hasAdminAssetFilters(query AdminListQuery) bool {
return len(query.Insurance) > 0 ||
len(query.Stamina) > 0 ||
len(query.Load) > 0 ||
len(query.SkinGroup) > 0 ||
len(query.SkinName) > 0
}
func filterAdminListings(items []ListingDTO, query AdminListQuery) []ListingDTO {
if !hasAdminAssetFilters(query) {
return items
}
filtered := make([]ListingDTO, 0, len(items))
for _, item := range items {
if !matchesAdminAssetQuery(item, query) {
continue
}
filtered = append(filtered, item)
}
return filtered
}
func matchesAdminAssetQuery(item ListingDTO, query AdminListQuery) bool {
if !matchesAny(query.Insurance, readAssetString(item.AssetSummary, "season_insurance")) {
return false
}
if !matchesAny(query.Stamina, readAssetString(item.AssetSummary, "stamina_level")) {
return false
}
if !matchesAny(query.Load, readAssetString(item.AssetSummary, "load_level")) {
return false
}
if len(query.SkinName) > 0 {
if len(query.SkinGroup) > 0 {
return skinGroupsContainAny(item.AssetSummary, query.SkinGroup, query.SkinName)
}
return intersects(query.SkinName, skinNamesFromSummary(item.AssetSummary))
}
if len(query.SkinGroup) > 0 {
return skinGroupsHaveAny(item.AssetSummary, query.SkinGroup)
}
return true
}
@@ -0,0 +1,94 @@
package listing
import "testing"
func TestFilterAdminListingsByAssetLevels(t *testing.T) {
items := []ListingDTO{
{
ID: 1,
AssetSummary: map[string]any{
"season_insurance": "3*3",
"stamina_level": "7级",
"load_level": "7级",
},
},
{
ID: 2,
AssetSummary: map[string]any{
"season_insurance": "2*3",
"stamina_level": "7级",
"load_level": "6级",
},
},
}
filtered := filterAdminListings(items, AdminListQuery{
Insurance: []string{"3*3"},
Stamina: []string{"7级"},
Load: []string{"7级"},
})
if len(filtered) != 1 || filtered[0].ID != 1 {
t.Fatalf("expected only listing 1 in 9/7/7 asset filter, got %#v", filtered)
}
}
func TestFilterAdminListingsBySkinGroupAndName(t *testing.T) {
items := []ListingDTO{
{
ID: 1,
AssetSummary: map[string]any{
"skin_groups": map[string]any{
"operatorRed": []any{"凌霄成卫"},
"weapon": []any{"K416命运"},
},
},
},
{
ID: 2,
AssetSummary: map[string]any{
"skin_groups": map[string]any{
"operatorGold": []any{"露娜-金牌射手"},
},
},
},
}
filtered := filterAdminListings(items, AdminListQuery{
SkinGroup: []string{"operatorRed"},
SkinName: []string{"凌霄成卫"},
})
if len(filtered) != 1 || filtered[0].ID != 1 {
t.Fatalf("expected only listing 1 by red skin name, got %#v", filtered)
}
}
func TestFilterAdminListingsBySkinGroupOnly(t *testing.T) {
items := []ListingDTO{
{
ID: 1,
AssetSummary: map[string]any{
"skin_groups": map[string]any{
"operatorRed": []any{"凌霄成卫"},
},
},
},
{
ID: 2,
AssetSummary: map[string]any{
"skin_groups": map[string]any{
"operatorGold": []any{"露娜-金牌射手"},
},
},
},
}
filtered := filterAdminListings(items, AdminListQuery{
SkinGroup: []string{"operatorGold"},
})
if len(filtered) != 1 || filtered[0].ID != 2 {
t.Fatalf("expected only listing 2 by gold skin group, got %#v", filtered)
}
}
+5
View File
@@ -76,6 +76,11 @@ type AdminListQuery struct {
Keyword string
Status string
ReviewStatus string
Insurance []string
Stamina []string
Load []string
SkinGroup []string
SkinName []string
Limit int
Page int
PageSize int
@@ -74,6 +74,11 @@ func parseAdminListQuery(c *gin.Context) (AdminListQuery, bool) {
query.Keyword = strings.TrimSpace(c.Query("keyword"))
query.Status = c.Query("status")
query.ReviewStatus = c.Query("review_status")
query.Insurance = parseCSVQuery(c.Query("insurance"))
query.Stamina = parseCSVQuery(c.Query("stamina"))
query.Load = parseCSVQuery(c.Query("load"))
query.SkinGroup = parseCSVQuery(c.Query("skin_group"))
query.SkinName = parseCSVQuery(firstNonEmpty(c.Query("skin_name"), c.Query("skin")))
return query, true
}
+31
View File
@@ -29,6 +29,37 @@ func (r *Repository) ListAdmin(ctx context.Context, query AdminListQuery) (*Admi
pageSize = 100
}
if hasAdminAssetFilters(query) {
var rows []listingRow
err := r.applyAdminListFilters(r.baseQuery(ctx), query).
Order("l.id DESC").
Scan(&rows).Error
if err != nil {
return nil, err
}
items := filterAdminListings(rowsToDTO(rows), query)
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 &AdminListResult{
Items: items,
Total: total,
Page: page,
PageSize: pageSize,
}, nil
}
countDB := r.applyAdminListFilters(r.db.WithContext(ctx).Table("rental_listings AS l"), query)
var total int64
if err := countDB.Count(&total).Error; err != nil {