修复定价错误
This commit is contained in:
@@ -126,8 +126,21 @@ export const emptyListingPublishOptions: ListingPublishOptions = {
|
||||
}
|
||||
|
||||
export const emptyListingSalePriceConfig: PublishSalePriceConfig = {
|
||||
fixed_markup_rules: [],
|
||||
ratio_adjustment_rules: [],
|
||||
fixed_markup_rules: [
|
||||
{ min_m: 10, max_m: 30, markup_amount: 28 },
|
||||
{ min_m: 30, max_m: 50, markup_amount: 31 },
|
||||
{ min_m: 50, max_m: 70, markup_amount: 34 },
|
||||
{ min_m: 70, max_m: 90, markup_amount: 38 },
|
||||
],
|
||||
ratio_adjustment_rules: [
|
||||
{ min_m: 90, max_m: 150, ratio_subtract: 5 },
|
||||
{ min_m: 150, max_m: 230, ratio_subtract: 4 },
|
||||
{ min_m: 230, max_m: 310, ratio_subtract: 3.5 },
|
||||
{ min_m: 310, max_m: 390, ratio_subtract: 3 },
|
||||
{ min_m: 390, max_m: 470, ratio_subtract: 0 },
|
||||
{ min_m: 470, max_m: 550, ratio_subtract: 0 },
|
||||
{ min_m: 550, max_m: 0, ratio_subtract: 0 },
|
||||
],
|
||||
}
|
||||
|
||||
export async function fetchListingPublishOptions() {
|
||||
@@ -240,7 +253,7 @@ function normalizeRatioConfig(value?: unknown): PublishRatioConfig {
|
||||
|
||||
function normalizeSalePriceConfig(value?: unknown): PublishSalePriceConfig {
|
||||
const row = isRecord(value) ? value : {}
|
||||
return {
|
||||
const config = {
|
||||
fixed_markup_rules: normalizeSaleFixedMarkupRules(
|
||||
Array.isArray(row.fixed_markup_rules) ? row.fixed_markup_rules : [],
|
||||
),
|
||||
@@ -248,6 +261,10 @@ function normalizeSalePriceConfig(value?: unknown): PublishSalePriceConfig {
|
||||
Array.isArray(row.ratio_adjustment_rules) ? row.ratio_adjustment_rules : [],
|
||||
),
|
||||
}
|
||||
if (config.fixed_markup_rules.length === 0 && config.ratio_adjustment_rules.length === 0) {
|
||||
return JSON.parse(JSON.stringify(emptyListingSalePriceConfig)) as PublishSalePriceConfig
|
||||
}
|
||||
return config
|
||||
}
|
||||
|
||||
function normalizeInsuranceBaseRatios(values: unknown[]): PublishInsuranceBaseRatio[] {
|
||||
|
||||
@@ -463,7 +463,7 @@ function readError(error: unknown, fallback: string) {
|
||||
<div>
|
||||
<p class="eyebrow">Sale Pricing</p>
|
||||
<h2>内部出售定价规则</h2>
|
||||
<span>管理出售加价和比例扣减规则,仅用于平台内部定价计算,不在发布页展示。</span>
|
||||
<span>管理出售专用比例计算规则,仅用于平台内部定价计算,不在发布页展示。</span>
|
||||
</div>
|
||||
<el-button type="primary" @click="openEdit(salePriceConfig)">编辑出售规则</el-button>
|
||||
</div>
|
||||
@@ -474,7 +474,7 @@ function readError(error: unknown, fallback: string) {
|
||||
</div>
|
||||
<div class="publish-stat">
|
||||
<strong>{{ salePriceStats.ratioCount }}</strong>
|
||||
<span>比例扣减</span>
|
||||
<span>比例修正</span>
|
||||
</div>
|
||||
<div class="publish-stat">
|
||||
<strong>内部</strong>
|
||||
@@ -843,8 +843,8 @@ function readError(error: unknown, fallback: string) {
|
||||
</el-table>
|
||||
|
||||
<div class="editor-block-title subtle-title">
|
||||
<span>90M 以上比例调整:出售比例 = 回收比例 - 比例扣减;最大 M 为 0 表示无上限</span>
|
||||
<el-button size="small" @click="addSaleRatioAdjustmentRule">添加比例调整</el-button>
|
||||
<span>90M 以上比例修正:出售比例 = 回收比例 - 比例修正;最大 M 为 0 表示无上限</span>
|
||||
<el-button size="small" @click="addSaleRatioAdjustmentRule">添加比例修正</el-button>
|
||||
</div>
|
||||
<el-table :data="salePriceConfigDraft.ratio_adjustment_rules" size="small" border>
|
||||
<el-table-column label="最小 M" min-width="120">
|
||||
@@ -853,7 +853,7 @@ function readError(error: unknown, fallback: string) {
|
||||
<el-table-column label="最大 M" min-width="120">
|
||||
<template #default="{ row }"><el-input-number v-model="row.max_m" :min="0" :step="10" /></template>
|
||||
</el-table-column>
|
||||
<el-table-column label="比例扣减" min-width="130">
|
||||
<el-table-column label="比例修正" min-width="130">
|
||||
<template #default="{ row }"><el-input-number v-model="row.ratio_subtract" :min="0" :step="0.5" /></template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="90">
|
||||
|
||||
@@ -498,6 +498,104 @@
|
||||
font-weight: 800;
|
||||
}
|
||||
|
||||
.ratio-panel {
|
||||
display: grid;
|
||||
gap: 10px;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.ratio-reference {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 10px;
|
||||
min-height: 48px;
|
||||
padding: 10px 12px;
|
||||
border-radius: 8px;
|
||||
background: #f8fafc;
|
||||
}
|
||||
|
||||
.ratio-reference span {
|
||||
color: #30343a;
|
||||
font-size: 13px;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.ratio-reference strong {
|
||||
color: #ff6a00;
|
||||
font-size: 18px;
|
||||
font-weight: 900;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.ratio-range {
|
||||
margin: 0;
|
||||
color: #858c96;
|
||||
font-size: 11px;
|
||||
font-weight: 600;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.ratio-mode-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.ratio-mode-btn {
|
||||
display: grid;
|
||||
gap: 5px;
|
||||
min-width: 0;
|
||||
min-height: 74px;
|
||||
padding: 12px 8px;
|
||||
border: 1px solid #d7dce3;
|
||||
border-radius: 8px;
|
||||
background: #fff;
|
||||
color: #30343a;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.ratio-mode-btn strong,
|
||||
.ratio-mode-btn span {
|
||||
min-width: 0;
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
|
||||
.ratio-mode-btn strong {
|
||||
font-size: 14px;
|
||||
font-weight: 800;
|
||||
}
|
||||
|
||||
.ratio-mode-btn span {
|
||||
color: #858c96;
|
||||
font-size: 12px;
|
||||
font-weight: 700;
|
||||
line-height: 1.25;
|
||||
}
|
||||
|
||||
.ratio-mode-btn.active {
|
||||
border-color: #ff6a00;
|
||||
background: #fff7f0;
|
||||
color: #ff6a00;
|
||||
}
|
||||
|
||||
.ratio-mode-btn.active span {
|
||||
color: #ff6a00;
|
||||
}
|
||||
|
||||
.ratio-mode-btn:disabled {
|
||||
cursor: not-allowed;
|
||||
opacity: 0.58;
|
||||
}
|
||||
|
||||
.ratio-input-field {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.ratio-input-hint {
|
||||
margin: -2px 0 0;
|
||||
}
|
||||
|
||||
.total-price-field :deep(.van-field__control) {
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -36,7 +36,16 @@ async function offline(id: number) {
|
||||
}
|
||||
|
||||
function listingPrice(row: Listing) {
|
||||
return `¥${Number(row.price_daily || row.price_hourly || 0).toFixed(2)}`
|
||||
return `¥${readSellerPrice(row).toFixed(2)}`
|
||||
}
|
||||
|
||||
function readSellerPrice(row: Listing) {
|
||||
const breakdown = row.asset_summary?.price_breakdown
|
||||
if (typeof breakdown === 'object' && breakdown !== null) {
|
||||
const price = Number((breakdown as Record<string, unknown>).seller_total_price)
|
||||
if (Number.isFinite(price) && price > 0) return price
|
||||
}
|
||||
return Number(row.price_daily || row.price_hourly || 0)
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user