增加出售设置
This commit is contained in:
@@ -54,6 +54,9 @@ const publishStats = computed(() => {
|
||||
resourceCount: options.quantity_items.length,
|
||||
screenshotCount: options.screenshot_slots.length,
|
||||
regionCount: options.region_options.length,
|
||||
saleRuleCount:
|
||||
options.sale_price_config.fixed_markup_rules.length +
|
||||
options.sale_price_config.ratio_adjustment_rules.length,
|
||||
}
|
||||
})
|
||||
const homeStats = computed(() => {
|
||||
@@ -281,6 +284,30 @@ function removeCoinCorrection(index: number) {
|
||||
publishOptionsDraft.value.ratio_config.coin_corrections.splice(index, 1)
|
||||
}
|
||||
|
||||
function addSaleFixedMarkupRule() {
|
||||
publishOptionsDraft.value.sale_price_config.fixed_markup_rules.push({
|
||||
min_m: 0,
|
||||
max_m: 0,
|
||||
markup_amount: 0,
|
||||
})
|
||||
}
|
||||
|
||||
function removeSaleFixedMarkupRule(index: number) {
|
||||
publishOptionsDraft.value.sale_price_config.fixed_markup_rules.splice(index, 1)
|
||||
}
|
||||
|
||||
function addSaleRatioAdjustmentRule() {
|
||||
publishOptionsDraft.value.sale_price_config.ratio_adjustment_rules.push({
|
||||
min_m: 0,
|
||||
max_m: 0,
|
||||
ratio_subtract: 0,
|
||||
})
|
||||
}
|
||||
|
||||
function removeSaleRatioAdjustmentRule(index: number) {
|
||||
publishOptionsDraft.value.sale_price_config.ratio_adjustment_rules.splice(index, 1)
|
||||
}
|
||||
|
||||
function addHomeBanner() {
|
||||
homeBannersDraft.value.push({
|
||||
eyebrow: '首页推荐',
|
||||
@@ -387,6 +414,10 @@ function readError(error: unknown, fallback: string) {
|
||||
<strong>{{ publishStats.regionCount }}</strong>
|
||||
<span>地区</span>
|
||||
</div>
|
||||
<div class="publish-stat">
|
||||
<strong>{{ publishStats.saleRuleCount }}</strong>
|
||||
<span>出售规则</span>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
@@ -642,6 +673,53 @@ function readError(error: unknown, fallback: string) {
|
||||
|
||||
</div>
|
||||
|
||||
<div class="editor-block">
|
||||
<div class="editor-block-title">
|
||||
<strong>出售加价规则</strong>
|
||||
</div>
|
||||
<div class="editor-block-title subtle-title">
|
||||
<span>90M 及以下固定加价:出售价格 = 回收价格 + 固定加价</span>
|
||||
<el-button size="small" @click="addSaleFixedMarkupRule">添加固定加价</el-button>
|
||||
</div>
|
||||
<el-table :data="publishOptionsDraft.sale_price_config.fixed_markup_rules" size="small" border>
|
||||
<el-table-column label="最小 M" min-width="120">
|
||||
<template #default="{ row }"><el-input-number v-model="row.min_m" :min="0" :step="10" /></template>
|
||||
</el-table-column>
|
||||
<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="140">
|
||||
<template #default="{ row }"><el-input-number v-model="row.markup_amount" :min="0" :step="1" /></template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="90">
|
||||
<template #default="{ $index }">
|
||||
<el-button size="small" type="danger" plain @click="removeSaleFixedMarkupRule($index)">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<div class="editor-block-title subtle-title">
|
||||
<span>90M 以上比例调整:出售比例 = 回收比例 - 比例扣减;最大 M 为 0 表示无上限</span>
|
||||
<el-button size="small" @click="addSaleRatioAdjustmentRule">添加比例调整</el-button>
|
||||
</div>
|
||||
<el-table :data="publishOptionsDraft.sale_price_config.ratio_adjustment_rules" size="small" border>
|
||||
<el-table-column label="最小 M" min-width="120">
|
||||
<template #default="{ row }"><el-input-number v-model="row.min_m" :min="0" :step="10" /></template>
|
||||
</el-table-column>
|
||||
<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">
|
||||
<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">
|
||||
<template #default="{ $index }">
|
||||
<el-button size="small" type="danger" plain @click="removeSaleRatioAdjustmentRule($index)">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
|
||||
<div class="editor-block">
|
||||
<div class="editor-block-title">
|
||||
<strong>皮肤分类</strong>
|
||||
|
||||
@@ -498,6 +498,12 @@
|
||||
font-weight: 800;
|
||||
}
|
||||
|
||||
.muted-result-field :deep(.van-field__control) {
|
||||
color: #5c6470;
|
||||
font-size: 12px;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.total-price-field :deep(.van-field__control) {
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
@@ -117,6 +117,7 @@ const fireLevelPlaceholder = computed(
|
||||
() => `等级低于${fireLevelMin.value}级的号无法发布`
|
||||
);
|
||||
const ratioConfig = computed(() => publishOptions.value.ratio_config);
|
||||
const salePriceConfig = computed(() => publishOptions.value.sale_price_config);
|
||||
const skinGroups = computed(() => publishOptions.value.skin_groups);
|
||||
const quantityItems = computed(() => publishOptions.value.quantity_items);
|
||||
const screenshotSlots = computed(() => publishOptions.value.screenshot_slots);
|
||||
@@ -127,10 +128,11 @@ const screenshotUrls = computed(() =>
|
||||
);
|
||||
const coinMAmount = computed(() => Number(form.haf_coin_amount || 0));
|
||||
const coinWanAmount = computed(() => coinMAmount.value * 100);
|
||||
const calculatedRatio = computed(() => calculatePublishRatio());
|
||||
const calculatedCoinBasePrice = computed(() =>
|
||||
calculatedRatio.value > 0 ? roundMoney(coinWanAmount.value / calculatedRatio.value) : 0
|
||||
);
|
||||
const calculatedRecycleRatio = computed(() => calculatePublishRatio());
|
||||
const calculatedSalePricing = computed(() => calculateSalePricing());
|
||||
const calculatedRatio = computed(() => calculatedSalePricing.value.saleRatio);
|
||||
const calculatedCoinBasePrice = computed(() => calculatedSalePricing.value.coinBasePrice);
|
||||
const calculatedSaleRuleText = computed(() => calculatedSalePricing.value.ruleText);
|
||||
const calculatedConsumablePrice = computed(() => calculateConsumablePrice());
|
||||
const calculatedFinalPrice = computed(() =>
|
||||
calculatedRatio.value > 0
|
||||
@@ -443,10 +445,14 @@ function buildAssetSummary() {
|
||||
fire_level: Number(form.fire_level),
|
||||
publish_ratio: calculatedRatio.value,
|
||||
price_breakdown: {
|
||||
recycle_coin_base_price: calculatedSalePricing.value.recycleCoinBasePrice,
|
||||
coin_base_price: calculatedCoinBasePrice.value,
|
||||
consumable_price: calculatedConsumablePrice.value,
|
||||
final_price: calculatedFinalPrice.value,
|
||||
ratio: calculatedRatio.value,
|
||||
recycle_ratio: calculatedRecycleRatio.value,
|
||||
sale_ratio: calculatedRatio.value,
|
||||
sale_rule_type: calculatedSalePricing.value.ruleType,
|
||||
sale_rule_text: calculatedSalePricing.value.ruleText,
|
||||
},
|
||||
season_insurance: form.season_insurance,
|
||||
stamina_level: form.stamina_level,
|
||||
@@ -515,6 +521,79 @@ function calculatePublishRatio() {
|
||||
return baseRatio + calculateConfigPenalty() + getCoinCorrection(coinMAmount.value);
|
||||
}
|
||||
|
||||
function calculateSalePricing() {
|
||||
const recycleRatio = calculatedRecycleRatio.value;
|
||||
if (recycleRatio <= 0 || coinWanAmount.value <= 0) {
|
||||
return emptySalePricing();
|
||||
}
|
||||
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",
|
||||
ruleText: `${formatSaleRange(fixedRule)} 加价 ${formatNumber(fixedRule.markup_amount)}元`,
|
||||
};
|
||||
}
|
||||
|
||||
const ratioRule = findSaleRatioAdjustmentRule();
|
||||
const ratioSubtract = ratioRule ? Number(ratioRule.ratio_subtract || 0) : 0;
|
||||
const saleRatio = recycleRatio - ratioSubtract;
|
||||
if (saleRatio <= 0) {
|
||||
return emptySalePricing(recycleCoinBasePrice);
|
||||
}
|
||||
return {
|
||||
recycleCoinBasePrice,
|
||||
coinBasePrice: roundMoney(coinWanAmount.value / saleRatio),
|
||||
saleRatio,
|
||||
ruleType: ratioRule ? "ratio_subtract" : "none",
|
||||
ruleText: ratioRule
|
||||
? `${formatSaleRange(ratioRule)} 出售比例=回收比例-${formatNumber(ratioSubtract)}`
|
||||
: "未匹配出售加价规则,按回收比例计算",
|
||||
};
|
||||
}
|
||||
|
||||
function emptySalePricing(recycleCoinBasePrice = 0) {
|
||||
return {
|
||||
recycleCoinBasePrice,
|
||||
coinBasePrice: 0,
|
||||
saleRatio: 0,
|
||||
ruleType: "none",
|
||||
ruleText: "",
|
||||
};
|
||||
}
|
||||
|
||||
function findSaleFixedMarkupRule() {
|
||||
return [...salePriceConfig.value.fixed_markup_rules]
|
||||
.sort((a, b) => a.min_m - b.min_m)
|
||||
.find((item) => isCoinInSaleRange(item));
|
||||
}
|
||||
|
||||
function findSaleRatioAdjustmentRule() {
|
||||
return [...salePriceConfig.value.ratio_adjustment_rules]
|
||||
.sort((a, b) => a.min_m - b.min_m)
|
||||
.find((item) => isCoinInSaleRange(item));
|
||||
}
|
||||
|
||||
function isCoinInSaleRange(item: { min_m: number; max_m: number }) {
|
||||
const maxM = Number(item.max_m || 0);
|
||||
return coinMAmount.value >= Number(item.min_m || 0) && (maxM <= 0 || coinMAmount.value <= maxM);
|
||||
}
|
||||
|
||||
function calculateEffectiveRatio(price: number) {
|
||||
if (price <= 0) return 0;
|
||||
return Math.round((coinWanAmount.value / price) * 10) / 10;
|
||||
}
|
||||
|
||||
function formatSaleRange(item: { min_m: number; max_m: number }) {
|
||||
const minM = formatNumber(Number(item.min_m || 0));
|
||||
const maxM = Number(item.max_m || 0);
|
||||
return maxM > 0 ? `${minM}M-${formatNumber(maxM)}M` : `${minM}M以上`;
|
||||
}
|
||||
|
||||
function getInsuranceBaseRatio(insurance: string) {
|
||||
return ratioConfig.value.insurance_base_ratios.find(
|
||||
(item) => item.insurance === insurance
|
||||
@@ -921,15 +1000,21 @@ function readError(error: unknown, fallback: string) {
|
||||
<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
|
||||
:model-value="calculatedSaleRuleText"
|
||||
label="出售规则"
|
||||
readonly
|
||||
class="publish-field result-field muted-result-field"
|
||||
/>
|
||||
<van-field
|
||||
:model-value="calculatedCoinBasePrice ? `¥${calculatedCoinBasePrice}` : ''"
|
||||
label="纯币基础价"
|
||||
@@ -958,7 +1043,7 @@ function readError(error: unknown, fallback: string) {
|
||||
/>
|
||||
</div>
|
||||
<p class="price-breakdown-hint">
|
||||
发布总价 = 纯币基础价 + 额外消耗品;只有标记为“收费”的消耗品会计入价格。
|
||||
纯币基础价先按回收比例计算,再套出售加价规则;发布总价 = 纯币基础价 + 额外消耗品。
|
||||
</p>
|
||||
|
||||
<van-field
|
||||
|
||||
Reference in New Issue
Block a user