feat(listing): 优化优质号主发布与极品专区体验
This commit is contained in:
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user