feat(listing): 优化优质号主发布与极品专区体验

This commit is contained in:
yml2213
2026-11-04 15:59:53 +08:00
parent 98174c0e33
commit e9102026ae
22 changed files with 812 additions and 88 deletions
@@ -49,7 +49,7 @@ func (s *Service) applyMainSiteReceivePricing(ctx context.Context, req *CreateRe
return err
}
applyMainSiteReceivePricing(req, options, config, receiveRatioDelta, receiveCostDelta, onDistributionSite)
return nil
return validateQualityOwnerPricingMode(req, onDistributionSite)
}
func applyMainSiteReceivePricing(req *CreateRequest, options systemconfig.PublishOptionsDTO, config salePriceConfig, receiveRatioDelta, receiveCostDelta float64, onDistributionSite bool) {
@@ -71,9 +71,16 @@ func applyMainSiteReceivePricing(req *CreateRequest, options systemconfig.Publis
if requestedRatio <= 0 {
requestedRatio = readSummaryNumber(breakdown["accelerated_sale_ratio"])
}
minSaleRatio := referenceRatio
if req.OwnerIsQualityOwner {
minSaleRatio = roundRatio(referenceRatio - NormalizeQualityOwnerRatioDiscount(options.RatioConfig.QualityOwnerRatioDiscount))
if minSaleRatio < minSiteReceiveRatio {
minSaleRatio = minSiteReceiveRatio
}
}
costDelta := NormalizeSiteReceiveCostDelta(receiveCostDelta)
ratioDelta := NormalizeSiteReceiveRatioDelta(receiveRatioDelta)
sellerRatio := clampSaleRatio(referenceRatio, requestedRatio)
sellerRatio := clampSaleRatio(referenceRatio, requestedRatio, minSaleRatio)
// 分站新口径:收号比例 = R + 压价点数(收号价更低),买家定价锚定主站参考比例 R,不随收号价联动。
if onDistributionSite {
sellerRatio = ApplySiteReceiveCostDelta(referenceRatio, costDelta)
@@ -98,6 +105,10 @@ func applyMainSiteReceivePricing(req *CreateRequest, options systemconfig.Publis
breakdown["consumable_price"] = consumablePrice
breakdown["daily_loss_ratio_adjustment"] = calculateDailyLossRatioAdjustment(dailyLoss)
breakdown["accelerated_sale_ratio"] = sellerRatio
if sellerRatio < referenceRatio {
breakdown["quality_owner_ratio_discount"] = roundRatio(referenceRatio - sellerRatio)
breakdown["pricing_mode"] = "quality_owner_exclusive"
}
if onDistributionSite {
breakdown["site_receive_cost_delta"] = costDelta
breakdown["pricing_model"] = "site_cost_decoupled_v1"
@@ -114,6 +125,18 @@ func applyMainSiteReceivePricing(req *CreateRequest, options systemconfig.Publis
req.PriceCent = yuanToCent(pricing.BuyerTotalPrice)
}
func validateQualityOwnerPricingMode(req *CreateRequest, onDistributionSite bool) error {
if req == nil || onDistributionSite || !req.OwnerIsQualityOwner || req.IsPremium {
return nil
}
breakdown := ensurePriceBreakdown(req.AssetSummary)
if readSummaryNumber(breakdown["seller_ratio"]) <
readSummaryNumber(breakdown["seller_reference_ratio"]) {
return ErrQualityRatioPremiumOnly
}
return nil
}
// NormalizeSiteReceiveCostDelta 将分站收号压价点数限制在 [0, 20]。
// 点数越大,分站收号比例越高(相对主站参考比例),收号价越低;0 表示与主站同价收号。
func NormalizeSiteReceiveCostDelta(delta float64) float64 {
@@ -136,6 +159,17 @@ func ApplySiteReceiveCostDelta(referenceRatio, delta float64) float64 {
return siteRatio
}
// NormalizeQualityOwnerRatioDiscount 限制优质号主专享比例下调值,默认 1、最大 10。
func NormalizeQualityOwnerRatioDiscount(value float64) float64 {
if value < 0 || math.IsNaN(value) || math.IsInf(value, 0) {
return 0
}
if value > maxAcceleratedSaleRatioIncrement {
return maxAcceleratedSaleRatioIncrement
}
return roundRatio(value)
}
// referenceSellerCoinBasePrice 计算主站参考比例下的号主基础价,用作买家定价锚点。
func referenceSellerCoinBasePrice(coinWan, referenceRatio float64) float64 {
if referenceRatio <= 0 {
@@ -182,7 +216,7 @@ func (s *Service) publishRatioOptions(ctx context.Context) (systemconfig.Publish
if strings.TrimSpace(value) == "" {
return options, nil
}
var parsed systemconfig.PublishOptionsDTO
parsed := options
if err := json.Unmarshal([]byte(value), &parsed); err != nil {
return options, nil
}
@@ -225,13 +259,13 @@ func calculateSellerReferenceRatio(coinM float64, summary map[string]any, option
calculateDailyLossRatioAdjustment(dailyLoss)
}
func clampSaleRatio(referenceRatio, requestedRatio float64) float64 {
func clampSaleRatio(referenceRatio, requestedRatio, minRatio float64) float64 {
maxRatio := roundRatio(referenceRatio + maxAcceleratedSaleRatioIncrement)
if requestedRatio <= 0 {
return referenceRatio
}
if requestedRatio < referenceRatio {
return referenceRatio
if requestedRatio < minRatio {
return minRatio
}
if requestedRatio > maxRatio {
return maxRatio