@@ -125,7 +125,6 @@ const fireLevelMin = computed(() => publishOptions.value.fire_level_min || 38);
const fireLevelPlaceholder = computed (
( ) => ` 等级低于 ${ fireLevelMin . value } 级的号无法发布 `
) ;
const ratioConfig = computed ( ( ) => publishOptions . value . ratio _config ) ;
const skinGroups = computed ( ( ) => publishOptions . value . skin _groups ) ;
const quantityItems = computed ( ( ) => publishOptions . value . quantity _items ) ;
const screenshotSlots = computed ( ( ) => publishOptions . value . screenshot _slots ) ;
@@ -140,16 +139,14 @@ const dailyLossMAmount = computed(() => Number(form.daily_loss_m || 10));
const dailyLossRatioAdjustment = computed ( ( ) =>
Math . min ( Math . max ( Math . floor ( ( dailyLossMAmount . value - 10 ) / 10 ) , 0 ) , 4 )
) ;
const calculatedRecycleRatio = computed ( ( ) => calculatePublishRatio ( ) ) ;
const calculatedSalePricing = computed ( ( ) => calculateSalePricing ( ) ) ;
const calculatedDefaultSaleRatio = computed ( ( ) => calculatedSalePricing . value . saleRatio ) ;
const calculatedSellerReferenceRatio = computed ( ( ) => calculateSellerReferenceRatio ( ) ) ;
const calculatedDefaultSaleRatio = computed ( ( ) => calculatedSellerReferenceRatio . value ) ;
const maxAcceleratedSaleRatio = computed ( ( ) =>
calculatedDefaultSaleRatio . value > 0 ? roundRatio ( calculatedDefaultSaleRatio . value + 10 ) : 0
) ;
const calculatedRatio = computed ( ( ) => readFinalSaleRatio ( ) ) ;
const calculatedCoinBasePrice = computed ( ( ) => {
if ( calculatedRatio . value <= 0 ) return 0 ;
if ( ! hasAcceleratedSaleRatioInput ( ) ) return calculatedSalePricing . value . coinBasePrice ;
return roundMoney ( coinWanAmount . value / calculatedRatio . value ) ;
} ) ;
const acceleratedSaleRatioPlaceholder = computed ( ( ) => {
@@ -157,14 +154,23 @@ const acceleratedSaleRatioPlaceholder = computed(() => {
return ` 默认 ${ formatNumber ( calculatedDefaultSaleRatio . value ) } ,最高 ${ formatNumber ( maxAcceleratedSaleRatio . value ) } ` ;
} ) ;
const calculatedConsumablePrice = computed ( ( ) => calculateConsumablePrice ( ) ) ;
const calculatedFinalPrice = computed ( ( ) =>
const calculatedSellerPrice = computed ( ( ) =>
calculatedRatio . value > 0
? roundMoney ( calculatedCoinBasePrice . value + calculatedConsumablePrice . value )
: 0
) ;
const calculatedPlatformPricing = computed ( ( ) => calculatePlatformPricing ( ) ) ;
const calculatedFinalPrice = computed ( ( ) => calculatedPlatformPricing . value . buyerTotalPrice ) ;
const calculatedRatioText = computed ( ( ) =>
calculatedRatio . value > 0 ? ` 1: ${ formatNumber ( calculatedRatio . value ) } ` : ""
) ;
const calculatedDefaultSaleRatioText = computed ( ( ) =>
calculatedDefaultSaleRatio . value > 0 ? ` 1: ${ formatNumber ( calculatedDefaultSaleRatio . value ) } ` : "--"
) ;
const saleRatioRangeText = computed ( ( ) => {
if ( calculatedDefaultSaleRatio . value <= 0 ) return "完成基础信息后自动计算参考比例" ;
return ` 可设置 1: ${ formatNumber ( calculatedDefaultSaleRatio . value ) } ~ 1: ${ formatNumber ( maxAcceleratedSaleRatio . value ) } ` ;
} ) ;
onMounted ( ( ) => {
restoreDraft ( ) ;
@@ -403,6 +409,15 @@ function clampAcceleratedSaleRatioInput() {
form . accelerated _sale _ratio = roundRatio ( Math . min ( Math . max ( ratio , minRatio ) , maxRatio ) ) ;
}
function useReferenceSaleRatio ( ) {
form . accelerated _sale _ratio = "" ;
}
function useMaxAcceleratedSaleRatio ( ) {
if ( maxAcceleratedSaleRatio . value <= 0 ) return ;
form . accelerated _sale _ratio = maxAcceleratedSaleRatio . value ;
}
async function handleSubmit ( ) {
const error = validateForm ( ) ;
if ( error ) {
@@ -505,19 +520,20 @@ function buildAssetSummary() {
secret _kd : form . secret _kd ,
fire _level : Number ( form . fire _level ) ,
daily _loss _m : dailyLossMAmount . value ,
publish _ratio : calculatedRatio . value ,
publish _ratio : calculatedPlatformPricing . value . buyerRatio ,
price _breakdown : {
recycle _coin _base _price : calculatedSalePricing . value . recycleCoinBasePrice ,
default _coin _base _price : calculatedSalePricing . value . coinBasePrice ,
coin _base _price : calculatedCoinBasePrice . value ,
seller _reference _ratio : calculatedSellerReferenceRatio . value ,
seller _ratio : calculatedRatio . value ,
seller _coin _base _price : calculatedCoinBasePrice . value ,
seller _total _price : calculatedSellerPrice . value ,
consumable _price : calculatedConsumablePrice . value ,
final _price : calculatedFinalPrice . value ,
recycle _ratio : calculatedRecycleRatio . value ,
daily _loss _ratio _adjustment : dailyLossRatioAdjustment . value ,
default _sale _ratio : calculatedDefaultSaleRatio . value ,
sale _ratio : calculatedRatio . value ,
accelerated _sale _ratio : hasAcceleratedSaleRatioInput ( ) ? Number ( form . accelerated _sale _ratio ) : calculatedDefaultSaleRatio . value ,
sale _rule _type : calculatedSalePricing . value . ruleType ,
buyer _coin _base _price : calculatedPlatformPricing . value . buyerCoinBasePrice ,
buyer _total _price : calculatedFinalPrice . value ,
buyer _ratio : calculatedPlatformPricing . value . buyerRatio ,
platform _markup _amount : calculatedPlatformPricing . value . platformMarkupAmount ,
platform _rule _type : calculatedPlatformPricing . value . ruleType ,
} ,
season _insurance : form . season _insurance ,
stamina _level : form . stamina _level ,
@@ -571,7 +587,7 @@ function readUnitPrice(priceText: string) {
return singleMatch ? Number ( singleMatch [ 1 ] ) : 0 ;
}
function calculatePublishRatio ( ) {
function calculateSellerReferenceRatio ( ) {
if (
coinMAmount . value <= 0 ||
! form . season _insurance ||
@@ -580,13 +596,13 @@ function calculatePublishRatio() {
) {
return 0 ;
}
const baseRatio = getInsuranceBaseRatio ( form . season _insurance ) ;
const baseRatio = getInsuranceBaseRatio ( publishOptions . value . ratio _config , form . season _insurance ) ;
if ( baseRatio <= 0 ) return 0 ;
return (
baseRatio +
calculateConfigPenalty ( ) +
getCoinCorrection ( coinMAmount . value ) +
calculateConfigPenalty ( publishOptions . value . ratio _config ) +
getCoinCorrection ( publishOptions . value . ratio _config , coinMAmount . value ) +
dailyLossRatioAdjustment . value
) ;
}
@@ -604,42 +620,44 @@ function hasAcceleratedSaleRatioInput() {
return form . accelerated _sale _ratio !== "" && form . accelerated _sale _ratio !== null ;
}
function calculateSalePricing ( ) {
const recycleRatio = calculatedRecycleRatio . value ;
if ( recycleRatio <= 0 || coinWanAmount . value <= 0 ) {
return emptySalePricing ( ) ;
function calculatePlatformPricing ( ) {
if ( calculatedRatio . value < = 0 || calculatedCoinBasePrice . value <= 0 ) {
return emptyPlatformPricing ( ) ;
}
const recycleCoinBasePrice = roundMoney ( coinWanAmount . value / recycleRatio ) ;
const fixedRule = findSaleFixedMarkupRule ( ) ;
if ( fixedRule ) {
const coinBasePrice = roundMoney ( recycleCoinBasePrice + Number ( fixedRule . markup _amount || 0 ) ) ;
return {
recycleCoinBasePrice ,
coinBasePrice ,
saleRatio : calculateEffectiveRatio ( coinBasePrice ) ,
ruleType : "fixed_markup" ,
} ;
return buildPlatformPricing (
roundMoney ( calculatedCoinBasePrice . value + Number ( fixedRule . markup _amount || 0 ) ) ,
"fixed_markup" ,
) ;
}
const ratioRule = findSaleRatioAdjustmentRule ( ) ;
const ratioSubtract = ratioRule ? Number ( ratioRule . ratio _subtract || 0 ) : 0 ;
const saleRatio = recycleRatio - ratioSubtract ;
if ( saleRatio <= 0 ) {
return emptySalePricing ( recycleCoinBasePrice ) ;
const buyerRatio = calculatedRatio . value - ratioSubtract ;
if ( buyerRatio > 0 && ratioRule ) {
return buildPlatformPricing ( roundMoney ( coinWanAmount . value / buyerRatio ) , "ratio_subtract" ) ;
}
return buildPlatformPricing ( calculatedCoinBasePrice . value , "none" ) ;
}
function buildPlatformPricing ( buyerCoinBasePrice : number , ruleType : string ) {
const buyerTotalPrice = roundMoney ( buyerCoinBasePrice + calculatedConsumablePrice . value ) ;
return {
recycleCoinBasePrice ,
coinBasePrice : roundMoney ( coinWanAmount . value / saleRatio ) ,
saleRatio ,
ruleType : ratioRule ? "ratio_subtract" : "none" ,
buyerCoinBasePrice ,
buyerTotalPrice ,
buyerRatio : calculateEffectiveRatio ( buyerCoinBasePrice ) ,
platformMarkupAmount : roundMoney ( buyerTotalPrice - calculatedSellerPrice . value ) ,
ruleType ,
} ;
}
function emptySalePricing ( recycleCoinBasePrice = 0 ) {
function emptyPlatformPricing ( ) {
return {
recycleCoinBasePrice ,
coinBasePrice : 0 ,
saleRatio : 0 ,
buyerCoinBasePrice : 0 ,
buyerTotalPrice : 0 ,
buyerRatio : 0 ,
platformMarkupAmount : 0 ,
ruleType : "none" ,
} ;
}
@@ -647,18 +665,27 @@ function emptySalePricing(recycleCoinBasePrice = 0) {
function findSaleFixedMarkupRule ( ) {
return [ ... salePriceConfig . value . fixed _markup _rules ]
. sort ( ( a , b ) => a . min _m - b . min _m )
. find ( ( item ) => isCoinInSaleRange ( item ) ) ;
. find ( ( item , index , rules ) => isCoinInSaleRange ( item , index , rules , { includeLastMax : true } ) ) ;
}
function findSaleRatioAdjustmentRule ( ) {
return [ ... salePriceConfig . value . ratio _adjustment _rules ]
. sort ( ( a , b ) => a . min _m - b . min _m )
. find ( ( item ) => isCoinInSaleRange ( item ) ) ;
. find ( ( item , index , rules ) => isCoinInSaleRange ( item , index , rules , { excludeFirstMin : true } ) ) ;
}
function isCoinInSaleRange ( item : { min _m : number ; max _m : number } ) {
function isCoinInSaleRange (
item : { min _m : number ; max _m : number } ,
index : number ,
rules : Array < { min _m : number ; max _m : number } > ,
options : { includeLastMax ? : boolean ; excludeFirstMin ? : boolean } = { } ,
) {
const maxM = Number ( item . max _m || 0 ) ;
return coinMAmount . value > = Number ( item . min _m || 0 ) && ( maxM <= 0 || coinMAmount . value <= maxM ) ;
const minM = Number ( item . min _m || 0 ) ;
const minMatched = options . excludeFirstMin && index === 0 ? coinMAmount . value > minM : coinMAmount . value >= minM ;
const isLastRule = index === rules . length - 1 ;
const maxMatched = maxM <= 0 || coinMAmount . value < maxM || ( options . includeLastMax && isLastRule && coinMAmount . value <= maxM ) ;
return minMatched && maxMatched ;
}
function calculateEffectiveRatio ( price : number ) {
@@ -666,14 +693,14 @@ function calculateEffectiveRatio(price: number) {
return roundRatio ( coinWanAmount . value / price ) ;
}
function getInsuranceBaseRatio ( insurance : string ) {
return ratioConfig . value . insurance _base _ratios . find (
function getInsuranceBaseRatio ( config : { insurance _base _ratios : Array < { insurance : string ; ratio : number } > } , insurance : string ) {
return config . insurance _base _ratios . find (
( item ) => item . insurance === insurance
) ? . ratio || 0 ;
}
function calculateConfigPenalty ( ) {
return ratioConfig . value . config _items . reduce ( ( sum , item ) => {
function calculateConfigPenalty ( config : { config _items : Array < { kind : string ; group _key ? : string ; missing _penalty : number } > } ) {
return config . config _items . reduce ( ( sum , item ) => {
return isRatioConfigItemMatched ( item ) ? sum : sum + Number ( item . missing _penalty || 0 ) ;
} , 0 ) ;
}
@@ -703,8 +730,8 @@ function readLevelNumber(value: string) {
return match ? Number ( match [ 0 ] ) : 0 ;
}
function getCoinCorrection ( coinM : number ) {
return [ ... ratioConfig . value . coin _corrections ]
function getCoinCorrection ( config : { coin _corrections : Array < { threshold _m : number ; correction : number } > } , coinM : number ) {
return [ ... config . coin _corrections ]
. sort ( ( a , b ) => b . threshold _m - a . threshold _m )
. find ( ( item ) => coinM > item . threshold _m ) ? . correction || 0 ;
}
@@ -1092,28 +1119,69 @@ function readError(error: unknown, fallback: string) {
< p class = "field-hint" >
比例调整 : 在默认10M / 天 , 每增加10M , 出租比例相应 + 1 , 请根据实际需求合理设置 , 感谢您的配合 。
< / p >
< van-field
:model-value = "form.accelerated_sale_ratio"
label = "加速出售比例"
type = "number"
:placeholder = "acceleratedSaleRatioPlaceholder"
class = "publish-field"
@ update :model-value = "handleAcceleratedSaleRatioInput"
@blur ="clampAcceleratedSaleRatioInput"
/ >
< p class = "field-hint" >
请根据实际需求合理设置 , 感谢您的配合 。
< / p >
< div class = "ratio-panel" >
< div class = "ratio-reference" >
< span > 参考比例 < / span >
< strong > { { calculatedDefaultSaleRatioText } } < / strong >
< / div >
< p class = "ratio-range" > { { saleRatioRangeText } } , 比例越高出租速度越快 , 自行选择 。 < / p >
< div class = "ratio-mode-grid" >
< button
type = "button"
class = "ratio-mode-btn"
: class = "{ active: !hasAcceleratedSaleRatioInput() }"
: disabled = "calculatedDefaultSaleRatio <= 0"
@click ="useReferenceSaleRatio"
>
< strong > 参考比例 < / strong >
< span >
{ {
calculatedDefaultSaleRatio > 0
? ` 1元= ${ formatNumber ( calculatedDefaultSaleRatio ) } 万 `
: "自动计算"
} }
< / span >
< / button >
< button
type = "button"
class = "ratio-mode-btn"
: class = "{ active: hasAcceleratedSaleRatioInput() }"
: disabled = "maxAcceleratedSaleRatio <= 0"
@click ="useMaxAcceleratedSaleRatio"
>
< strong > 加速比例 < / strong >
< span >
{ {
maxAcceleratedSaleRatio > 0
? ` 1元= ${ formatNumber ( calculatedDefaultSaleRatio ) } ~ ${ formatNumber ( maxAcceleratedSaleRatio ) } 万 `
: "自动计算"
} }
< / span >
< / button >
< / div >
< van-field
:model-value = "form.accelerated_sale_ratio"
label = "自定比例"
type = "number"
:placeholder = "acceleratedSaleRatioPlaceholder"
class = "publish-field ratio-input-field"
@ update :model-value = "handleAcceleratedSaleRatioInput"
@blur ="clampAcceleratedSaleRatioInput"
/ >
< p class = "field-hint ratio-input-hint" >
留空使用参考比例 ; 填写后范围为参考比例到参考比例 + 10 , 请根据实际需求合理设置 。
< / p >
< / div >
< div class = "result-grid" >
< van-field
:model-value = "calculatedRatioText"
label = "出售 比例"
label = "卖家 比例"
readonly
:placeholder = "priceConfig.ratio_description"
class = "publish-field result-field"
>
< template # label >
< span class = "hint-label" :data-hint = "priceConfig.ratio_description" tabindex = "0" > 出售 比例< / span >
< span class = "hint-label" :data-hint = "priceConfig.ratio_description" tabindex = "0" > 卖家 比例< / span >
< / template >
< / van-field >
< van-field
@@ -1135,8 +1203,8 @@ function readError(error: unknown, fallback: string) {
class = "publish-field result-field"
/ >
< van-field
: model -value = " calculatedFinalPrice ? ` ¥ $ { calculatedFinalPrice } ` : ' ' "
label = "发布总价 "
: model -value = " calculatedSellerPrice ? ` ¥ $ { calculatedSellerPrice } ` : ' ' "
label = "卖家价格 "
readonly
required
:placeholder = "priceConfig.price_placeholder"
@@ -1144,7 +1212,7 @@ function readError(error: unknown, fallback: string) {
/ >
< / div >
< p class = "price-breakdown-hint" >
发布总价 = 纯币基础价 + 额外消耗品 ; 加速比例仅影响纯币基础价 。
卖家价格 = 纯币基础价 + 额外消耗品 ; 加速比例仅影响纯币基础价 。
< / p >
< van-field