增加出售设置
This commit is contained in:
@@ -52,6 +52,7 @@ type PublishOptionsDTO struct {
|
|||||||
FireLevelMin int `json:"fire_level_min"`
|
FireLevelMin int `json:"fire_level_min"`
|
||||||
PriceConfig PublishPriceConfig `json:"price_config"`
|
PriceConfig PublishPriceConfig `json:"price_config"`
|
||||||
RatioConfig PublishRatioConfig `json:"ratio_config"`
|
RatioConfig PublishRatioConfig `json:"ratio_config"`
|
||||||
|
SalePriceConfig PublishSalePriceConfig `json:"sale_price_config"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type PublishOptionGroup struct {
|
type PublishOptionGroup struct {
|
||||||
@@ -103,3 +104,20 @@ type PublishCoinCorrection struct {
|
|||||||
ThresholdM float64 `json:"threshold_m"`
|
ThresholdM float64 `json:"threshold_m"`
|
||||||
Correction float64 `json:"correction"`
|
Correction float64 `json:"correction"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type PublishSalePriceConfig struct {
|
||||||
|
FixedMarkupRules []PublishSaleFixedMarkupRule `json:"fixed_markup_rules"`
|
||||||
|
RatioAdjustmentRules []PublishSaleRatioAdjustmentRule `json:"ratio_adjustment_rules"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type PublishSaleFixedMarkupRule struct {
|
||||||
|
MinM float64 `json:"min_m"`
|
||||||
|
MaxM float64 `json:"max_m"`
|
||||||
|
MarkupAmount float64 `json:"markup_amount"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type PublishSaleRatioAdjustmentRule struct {
|
||||||
|
MinM float64 `json:"min_m"`
|
||||||
|
MaxM float64 `json:"max_m,omitempty"`
|
||||||
|
RatioSubtract float64 `json:"ratio_subtract"`
|
||||||
|
}
|
||||||
|
|||||||
@@ -108,5 +108,22 @@ func DefaultPublishOptions() PublishOptionsDTO {
|
|||||||
{ThresholdM: 530, Correction: 5},
|
{ThresholdM: 530, Correction: 5},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
SalePriceConfig: PublishSalePriceConfig{
|
||||||
|
FixedMarkupRules: []PublishSaleFixedMarkupRule{
|
||||||
|
{MinM: 10, MaxM: 30, MarkupAmount: 28},
|
||||||
|
{MinM: 30, MaxM: 50, MarkupAmount: 31},
|
||||||
|
{MinM: 50, MaxM: 70, MarkupAmount: 34},
|
||||||
|
{MinM: 70, MaxM: 90, MarkupAmount: 38},
|
||||||
|
},
|
||||||
|
RatioAdjustmentRules: []PublishSaleRatioAdjustmentRule{
|
||||||
|
{MinM: 90, MaxM: 150, RatioSubtract: 5},
|
||||||
|
{MinM: 150, MaxM: 230, RatioSubtract: 4},
|
||||||
|
{MinM: 230, MaxM: 310, RatioSubtract: 3.5},
|
||||||
|
{MinM: 310, MaxM: 390, RatioSubtract: 3},
|
||||||
|
{MinM: 390, MaxM: 470, RatioSubtract: 0},
|
||||||
|
{MinM: 470, MaxM: 550, RatioSubtract: 0},
|
||||||
|
{MinM: 550, RatioSubtract: 0},
|
||||||
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -214,4 +214,10 @@ func normalizePublishOptions(options *PublishOptionsDTO) {
|
|||||||
if len(options.RatioConfig.CoinCorrections) == 0 {
|
if len(options.RatioConfig.CoinCorrections) == 0 {
|
||||||
options.RatioConfig.CoinCorrections = defaults.RatioConfig.CoinCorrections
|
options.RatioConfig.CoinCorrections = defaults.RatioConfig.CoinCorrections
|
||||||
}
|
}
|
||||||
|
if len(options.SalePriceConfig.FixedMarkupRules) == 0 {
|
||||||
|
options.SalePriceConfig.FixedMarkupRules = defaults.SalePriceConfig.FixedMarkupRules
|
||||||
|
}
|
||||||
|
if len(options.SalePriceConfig.RatioAdjustmentRules) == 0 {
|
||||||
|
options.SalePriceConfig.RatioAdjustmentRules = defaults.SalePriceConfig.RatioAdjustmentRules
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,19 @@
|
|||||||
|
当 10M <= 哈夫币 <= 90M:
|
||||||
|
出售价格 = 回收价格 + 固定加价
|
||||||
|
|
||||||
|
10M <= 币数 < 30M:+28元
|
||||||
|
30M <= 币数 < 50M:+31元
|
||||||
|
50M <= 币数 < 70M:+34元
|
||||||
|
70M <= 币数 <= 90M:+38元
|
||||||
|
|
||||||
|
当 哈夫币 > 90M:
|
||||||
|
出售比例 = 回收比例 - 比例修正
|
||||||
|
出售价格 = 哈夫币万数 / 出售比例
|
||||||
|
|
||||||
|
90M < 币数 < 150M:-5
|
||||||
|
150M <= 币数 < 230M:-4
|
||||||
|
230M <= 币数 < 310M:-3.5
|
||||||
|
310M <= 币数 < 390M:-3
|
||||||
|
390M <= 币数 < 470M:待定
|
||||||
|
470M <= 币数 < 550M:待定
|
||||||
|
550M <= 币数:待定
|
||||||
@@ -52,12 +52,29 @@ export interface PublishCoinCorrection {
|
|||||||
correction: number
|
correction: number
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface PublishSaleFixedMarkupRule {
|
||||||
|
min_m: number
|
||||||
|
max_m: number
|
||||||
|
markup_amount: number
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface PublishSaleRatioAdjustmentRule {
|
||||||
|
min_m: number
|
||||||
|
max_m: number
|
||||||
|
ratio_subtract: number
|
||||||
|
}
|
||||||
|
|
||||||
export interface PublishRatioConfig {
|
export interface PublishRatioConfig {
|
||||||
insurance_base_ratios: PublishInsuranceBaseRatio[]
|
insurance_base_ratios: PublishInsuranceBaseRatio[]
|
||||||
config_items: PublishRatioConfigItem[]
|
config_items: PublishRatioConfigItem[]
|
||||||
coin_corrections: PublishCoinCorrection[]
|
coin_corrections: PublishCoinCorrection[]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface PublishSalePriceConfig {
|
||||||
|
fixed_markup_rules: PublishSaleFixedMarkupRule[]
|
||||||
|
ratio_adjustment_rules: PublishSaleRatioAdjustmentRule[]
|
||||||
|
}
|
||||||
|
|
||||||
export interface ListingPublishOptions {
|
export interface ListingPublishOptions {
|
||||||
server_options: string[]
|
server_options: string[]
|
||||||
face_options: string[]
|
face_options: string[]
|
||||||
@@ -74,6 +91,7 @@ export interface ListingPublishOptions {
|
|||||||
fire_level_min: number
|
fire_level_min: number
|
||||||
price_config: PublishPriceConfig
|
price_config: PublishPriceConfig
|
||||||
ratio_config: PublishRatioConfig
|
ratio_config: PublishRatioConfig
|
||||||
|
sale_price_config: PublishSalePriceConfig
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ApiResponse<T> {
|
interface ApiResponse<T> {
|
||||||
@@ -106,6 +124,10 @@ export const emptyListingPublishOptions: ListingPublishOptions = {
|
|||||||
config_items: [],
|
config_items: [],
|
||||||
coin_corrections: [],
|
coin_corrections: [],
|
||||||
},
|
},
|
||||||
|
sale_price_config: {
|
||||||
|
fixed_markup_rules: [],
|
||||||
|
ratio_adjustment_rules: [],
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function fetchListingPublishOptions() {
|
export async function fetchListingPublishOptions() {
|
||||||
@@ -130,6 +152,7 @@ export function mergeListingPublishOptions(options?: Partial<ListingPublishOptio
|
|||||||
fire_level_min: readPositiveInteger(options?.fire_level_min, 38),
|
fire_level_min: readPositiveInteger(options?.fire_level_min, 38),
|
||||||
price_config: normalizePriceConfig(options?.price_config),
|
price_config: normalizePriceConfig(options?.price_config),
|
||||||
ratio_config: normalizeRatioConfig(options?.ratio_config),
|
ratio_config: normalizeRatioConfig(options?.ratio_config),
|
||||||
|
sale_price_config: normalizeSalePriceConfig(options?.sale_price_config),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -207,6 +230,18 @@ function normalizeRatioConfig(value?: unknown): PublishRatioConfig {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function normalizeSalePriceConfig(value?: unknown): PublishSalePriceConfig {
|
||||||
|
const row = isRecord(value) ? value : {}
|
||||||
|
return {
|
||||||
|
fixed_markup_rules: normalizeSaleFixedMarkupRules(
|
||||||
|
Array.isArray(row.fixed_markup_rules) ? row.fixed_markup_rules : [],
|
||||||
|
),
|
||||||
|
ratio_adjustment_rules: normalizeSaleRatioAdjustmentRules(
|
||||||
|
Array.isArray(row.ratio_adjustment_rules) ? row.ratio_adjustment_rules : [],
|
||||||
|
),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function normalizeInsuranceBaseRatios(values: unknown[]): PublishInsuranceBaseRatio[] {
|
function normalizeInsuranceBaseRatios(values: unknown[]): PublishInsuranceBaseRatio[] {
|
||||||
return values
|
return values
|
||||||
.map((item) => {
|
.map((item) => {
|
||||||
@@ -246,6 +281,37 @@ function normalizeCoinCorrections(values: unknown[]): PublishCoinCorrection[] {
|
|||||||
.filter((item) => item.threshold_m >= 0 && item.correction > 0)
|
.filter((item) => item.threshold_m >= 0 && item.correction > 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function normalizeSaleFixedMarkupRules(values: unknown[]): PublishSaleFixedMarkupRule[] {
|
||||||
|
return values
|
||||||
|
.map((item) => {
|
||||||
|
const row = isRecord(item) ? item : {}
|
||||||
|
return {
|
||||||
|
min_m: readNumber(row.min_m),
|
||||||
|
max_m: readNumber(row.max_m),
|
||||||
|
markup_amount: readNumber(row.markup_amount),
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.filter((item) => item.min_m >= 0 && item.max_m >= item.min_m && item.markup_amount >= 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
function normalizeSaleRatioAdjustmentRules(values: unknown[]): PublishSaleRatioAdjustmentRule[] {
|
||||||
|
return values
|
||||||
|
.map((item) => {
|
||||||
|
const row = isRecord(item) ? item : {}
|
||||||
|
return {
|
||||||
|
min_m: readNumber(row.min_m),
|
||||||
|
max_m: readNumber(row.max_m),
|
||||||
|
ratio_subtract: readNumber(row.ratio_subtract),
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.filter(
|
||||||
|
(item) =>
|
||||||
|
item.min_m >= 0 &&
|
||||||
|
(item.max_m === 0 || item.max_m >= item.min_m) &&
|
||||||
|
item.ratio_subtract >= 0,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
function readNumber(value: unknown) {
|
function readNumber(value: unknown) {
|
||||||
const parsed = Number(value)
|
const parsed = Number(value)
|
||||||
return Number.isFinite(parsed) ? parsed : 0
|
return Number.isFinite(parsed) ? parsed : 0
|
||||||
|
|||||||
@@ -54,6 +54,9 @@ const publishStats = computed(() => {
|
|||||||
resourceCount: options.quantity_items.length,
|
resourceCount: options.quantity_items.length,
|
||||||
screenshotCount: options.screenshot_slots.length,
|
screenshotCount: options.screenshot_slots.length,
|
||||||
regionCount: options.region_options.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(() => {
|
const homeStats = computed(() => {
|
||||||
@@ -281,6 +284,30 @@ function removeCoinCorrection(index: number) {
|
|||||||
publishOptionsDraft.value.ratio_config.coin_corrections.splice(index, 1)
|
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() {
|
function addHomeBanner() {
|
||||||
homeBannersDraft.value.push({
|
homeBannersDraft.value.push({
|
||||||
eyebrow: '首页推荐',
|
eyebrow: '首页推荐',
|
||||||
@@ -387,6 +414,10 @@ function readError(error: unknown, fallback: string) {
|
|||||||
<strong>{{ publishStats.regionCount }}</strong>
|
<strong>{{ publishStats.regionCount }}</strong>
|
||||||
<span>地区</span>
|
<span>地区</span>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="publish-stat">
|
||||||
|
<strong>{{ publishStats.saleRuleCount }}</strong>
|
||||||
|
<span>出售规则</span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
@@ -642,6 +673,53 @@ function readError(error: unknown, fallback: string) {
|
|||||||
|
|
||||||
</div>
|
</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">
|
||||||
<div class="editor-block-title">
|
<div class="editor-block-title">
|
||||||
<strong>皮肤分类</strong>
|
<strong>皮肤分类</strong>
|
||||||
|
|||||||
@@ -498,6 +498,12 @@
|
|||||||
font-weight: 800;
|
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) {
|
.total-price-field :deep(.van-field__control) {
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -117,6 +117,7 @@ const fireLevelPlaceholder = computed(
|
|||||||
() => `等级低于${fireLevelMin.value}级的号无法发布`
|
() => `等级低于${fireLevelMin.value}级的号无法发布`
|
||||||
);
|
);
|
||||||
const ratioConfig = computed(() => publishOptions.value.ratio_config);
|
const ratioConfig = computed(() => publishOptions.value.ratio_config);
|
||||||
|
const salePriceConfig = computed(() => publishOptions.value.sale_price_config);
|
||||||
const skinGroups = computed(() => publishOptions.value.skin_groups);
|
const skinGroups = computed(() => publishOptions.value.skin_groups);
|
||||||
const quantityItems = computed(() => publishOptions.value.quantity_items);
|
const quantityItems = computed(() => publishOptions.value.quantity_items);
|
||||||
const screenshotSlots = computed(() => publishOptions.value.screenshot_slots);
|
const screenshotSlots = computed(() => publishOptions.value.screenshot_slots);
|
||||||
@@ -127,10 +128,11 @@ const screenshotUrls = computed(() =>
|
|||||||
);
|
);
|
||||||
const coinMAmount = computed(() => Number(form.haf_coin_amount || 0));
|
const coinMAmount = computed(() => Number(form.haf_coin_amount || 0));
|
||||||
const coinWanAmount = computed(() => coinMAmount.value * 100);
|
const coinWanAmount = computed(() => coinMAmount.value * 100);
|
||||||
const calculatedRatio = computed(() => calculatePublishRatio());
|
const calculatedRecycleRatio = computed(() => calculatePublishRatio());
|
||||||
const calculatedCoinBasePrice = computed(() =>
|
const calculatedSalePricing = computed(() => calculateSalePricing());
|
||||||
calculatedRatio.value > 0 ? roundMoney(coinWanAmount.value / calculatedRatio.value) : 0
|
const calculatedRatio = computed(() => calculatedSalePricing.value.saleRatio);
|
||||||
);
|
const calculatedCoinBasePrice = computed(() => calculatedSalePricing.value.coinBasePrice);
|
||||||
|
const calculatedSaleRuleText = computed(() => calculatedSalePricing.value.ruleText);
|
||||||
const calculatedConsumablePrice = computed(() => calculateConsumablePrice());
|
const calculatedConsumablePrice = computed(() => calculateConsumablePrice());
|
||||||
const calculatedFinalPrice = computed(() =>
|
const calculatedFinalPrice = computed(() =>
|
||||||
calculatedRatio.value > 0
|
calculatedRatio.value > 0
|
||||||
@@ -443,10 +445,14 @@ function buildAssetSummary() {
|
|||||||
fire_level: Number(form.fire_level),
|
fire_level: Number(form.fire_level),
|
||||||
publish_ratio: calculatedRatio.value,
|
publish_ratio: calculatedRatio.value,
|
||||||
price_breakdown: {
|
price_breakdown: {
|
||||||
|
recycle_coin_base_price: calculatedSalePricing.value.recycleCoinBasePrice,
|
||||||
coin_base_price: calculatedCoinBasePrice.value,
|
coin_base_price: calculatedCoinBasePrice.value,
|
||||||
consumable_price: calculatedConsumablePrice.value,
|
consumable_price: calculatedConsumablePrice.value,
|
||||||
final_price: calculatedFinalPrice.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,
|
season_insurance: form.season_insurance,
|
||||||
stamina_level: form.stamina_level,
|
stamina_level: form.stamina_level,
|
||||||
@@ -515,6 +521,79 @@ function calculatePublishRatio() {
|
|||||||
return baseRatio + calculateConfigPenalty() + getCoinCorrection(coinMAmount.value);
|
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) {
|
function getInsuranceBaseRatio(insurance: string) {
|
||||||
return ratioConfig.value.insurance_base_ratios.find(
|
return ratioConfig.value.insurance_base_ratios.find(
|
||||||
(item) => item.insurance === insurance
|
(item) => item.insurance === insurance
|
||||||
@@ -921,15 +1000,21 @@ function readError(error: unknown, fallback: string) {
|
|||||||
<div class="result-grid">
|
<div class="result-grid">
|
||||||
<van-field
|
<van-field
|
||||||
:model-value="calculatedRatioText"
|
:model-value="calculatedRatioText"
|
||||||
label="比例"
|
label="出售比例"
|
||||||
readonly
|
readonly
|
||||||
:placeholder="priceConfig.ratio_description"
|
:placeholder="priceConfig.ratio_description"
|
||||||
class="publish-field result-field"
|
class="publish-field result-field"
|
||||||
>
|
>
|
||||||
<template #label>
|
<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>
|
</template>
|
||||||
</van-field>
|
</van-field>
|
||||||
|
<van-field
|
||||||
|
:model-value="calculatedSaleRuleText"
|
||||||
|
label="出售规则"
|
||||||
|
readonly
|
||||||
|
class="publish-field result-field muted-result-field"
|
||||||
|
/>
|
||||||
<van-field
|
<van-field
|
||||||
:model-value="calculatedCoinBasePrice ? `¥${calculatedCoinBasePrice}` : ''"
|
:model-value="calculatedCoinBasePrice ? `¥${calculatedCoinBasePrice}` : ''"
|
||||||
label="纯币基础价"
|
label="纯币基础价"
|
||||||
@@ -958,7 +1043,7 @@ function readError(error: unknown, fallback: string) {
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<p class="price-breakdown-hint">
|
<p class="price-breakdown-hint">
|
||||||
发布总价 = 纯币基础价 + 额外消耗品;只有标记为“收费”的消耗品会计入价格。
|
纯币基础价先按回收比例计算,再套出售加价规则;发布总价 = 纯币基础价 + 额外消耗品。
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<van-field
|
<van-field
|
||||||
|
|||||||
Reference in New Issue
Block a user