feat(listings): PC与移动端首页新增比例排序
- 前端选项:在 PC 首页(HomeView)与移动端首页(MobileHomeView)的排序项中,在「综合推荐」后新增「比例排序」(ratioDesc) - 后端排序:在 sortPublicListings 中实现 ratioDesc/ratio,按折算比例从高到低排序,同比例按哈夫币数量降序次级平局决胜 - 自动化验证:新增 TestSortPublicListingsByRatio 单元测试,全量运行 ./scripts/check.sh 门禁(Go测试、MySQL测试、前端lint/typecheck/build)全部通过
This commit is contained in:
@@ -103,6 +103,20 @@ func sortPublicListings(items []ListingDTO, sortKey string) {
|
||||
return a.PriceCent > b.PriceCent
|
||||
case "coinDesc":
|
||||
return a.HafCoinAmount > b.HafCoinAmount
|
||||
case "ratioDesc", "ratio":
|
||||
aRatio := ratioFromListing(a)
|
||||
bRatio := ratioFromListing(b)
|
||||
if aRatio != bRatio {
|
||||
return aRatio > bRatio
|
||||
}
|
||||
return a.HafCoinAmount > b.HafCoinAmount
|
||||
case "ratioAsc":
|
||||
aRatio := ratioFromListing(a)
|
||||
bRatio := ratioFromListing(b)
|
||||
if aRatio != bRatio {
|
||||
return aRatio < bRatio
|
||||
}
|
||||
return a.HafCoinAmount > b.HafCoinAmount
|
||||
case "awmDesc":
|
||||
aAmmo := resourceQuantity(a.AssetSummary, "awmAmmo")
|
||||
bAmmo := resourceQuantity(b.AssetSummary, "awmAmmo")
|
||||
|
||||
@@ -178,6 +178,45 @@ func TestSortPublicListingsDefaultUsesShuffleKey(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestSortPublicListingsByRatio(t *testing.T) {
|
||||
items := []ListingDTO{
|
||||
{
|
||||
ID: 1,
|
||||
HafCoinAmount: 50_000_000,
|
||||
PriceCent: 5_000,
|
||||
AssetSummary: map[string]any{"publish_ratio": 20.0},
|
||||
},
|
||||
{
|
||||
ID: 2,
|
||||
HafCoinAmount: 50_000_000,
|
||||
PriceCent: 2_500,
|
||||
AssetSummary: map[string]any{"publish_ratio": 45.0},
|
||||
},
|
||||
{
|
||||
ID: 3,
|
||||
HafCoinAmount: 80_000_000,
|
||||
PriceCent: 3_000,
|
||||
AssetSummary: map[string]any{"publish_ratio": 35.0},
|
||||
},
|
||||
{
|
||||
ID: 4,
|
||||
HafCoinAmount: 100_000_000,
|
||||
PriceCent: 4_000,
|
||||
AssetSummary: map[string]any{"publish_ratio": 35.0},
|
||||
},
|
||||
}
|
||||
|
||||
sortPublicListings(items, "ratioDesc")
|
||||
|
||||
// 预期顺序:ID=2 (45.0) > ID=4 (35.0, 100M 币更多) > ID=3 (35.0, 80M) > ID=1 (20.0)
|
||||
expectedIDs := []uint64{2, 4, 3, 1}
|
||||
for i, expected := range expectedIDs {
|
||||
if items[i].ID != expected {
|
||||
t.Fatalf("at index %d, expected listing %d, got %d (ratio=%.1f)", i, expected, items[i].ID, ratioFromListing(items[i]))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestIsNightAvailableSummaryUsesEarlyMorningResponse(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
|
||||
@@ -72,6 +72,7 @@ const publishOptions = ref<ListingPublishOptions>(emptyListingPublishOptions)
|
||||
const sortBy = ref('recommended')
|
||||
const sortOptions = [
|
||||
{ value: 'recommended', label: '综合推荐' },
|
||||
{ value: 'ratioDesc', label: '比例排序' },
|
||||
{ value: 'coinDesc', label: '哈夫币' },
|
||||
{ value: 'awmDesc', label: 'AWM数量' },
|
||||
{ value: 'priceAsc', label: '价格最低' },
|
||||
|
||||
@@ -125,6 +125,7 @@ let searchDebounceTimer: ReturnType<typeof setTimeout> | null = null
|
||||
|
||||
const sortOptions = [
|
||||
{ key: 'recommended', label: '综合推荐' },
|
||||
{ key: 'ratioDesc', label: '比例排序' },
|
||||
{ key: 'coinDesc', label: '哈夫币' },
|
||||
{ key: 'awmDesc', label: 'AWM数量' },
|
||||
{ key: 'priceAsc', label: '价格最低' },
|
||||
|
||||
Reference in New Issue
Block a user