内部加价分离, 不展示
This commit is contained in:
@@ -3,9 +3,12 @@ import { ElMessage } from 'element-plus'
|
||||
import { computed, onMounted, ref } from 'vue'
|
||||
|
||||
import {
|
||||
emptyListingSalePriceConfig,
|
||||
emptyListingPublishOptions,
|
||||
mergeListingSalePriceConfig,
|
||||
mergeListingPublishOptions,
|
||||
type ListingPublishOptions,
|
||||
type PublishSalePriceConfig,
|
||||
} from '@/api/listingOptions'
|
||||
import {
|
||||
defaultHomeAnnouncements,
|
||||
@@ -24,22 +27,26 @@ const activeConfig = ref<SystemConfig | null>(null)
|
||||
const value = ref('')
|
||||
const description = ref('')
|
||||
const publishOptionsDraft = ref<ListingPublishOptions>(cloneOptions(emptyListingPublishOptions))
|
||||
const salePriceConfigDraft = ref<PublishSalePriceConfig>(cloneSalePriceConfig(emptyListingSalePriceConfig))
|
||||
const homeAnnouncementLines = ref(itemsToLines(defaultHomeAnnouncements))
|
||||
const homeBannersDraft = ref<HomeBannerSlide[]>(cloneHomeBanners(defaultHomeBanners))
|
||||
const uploadingBannerIndex = ref<number | null>(null)
|
||||
|
||||
const publishConfig = computed(() => configs.value.find((item) => item.key === 'listing.publish_options') || null)
|
||||
const salePriceConfig = computed(() => configs.value.find((item) => item.key === 'listing.sale_price_config') || null)
|
||||
const homeAnnouncementsConfig = computed(() => configs.value.find((item) => item.key === 'mobile.home_announcements') || null)
|
||||
const homeBannersConfig = computed(() => configs.value.find((item) => item.key === 'mobile.home_banners') || null)
|
||||
const regularConfigs = computed(() =>
|
||||
configs.value.filter(
|
||||
(item) =>
|
||||
item.key !== 'listing.publish_options' &&
|
||||
item.key !== 'listing.sale_price_config' &&
|
||||
item.key !== 'mobile.home_announcements' &&
|
||||
item.key !== 'mobile.home_banners',
|
||||
),
|
||||
)
|
||||
const isPublishOptionsConfig = computed(() => activeConfig.value?.key === 'listing.publish_options')
|
||||
const isSalePriceConfig = computed(() => activeConfig.value?.key === 'listing.sale_price_config')
|
||||
const isHomeAnnouncementsConfig = computed(() => activeConfig.value?.key === 'mobile.home_announcements')
|
||||
const isHomeBannersConfig = computed(() => activeConfig.value?.key === 'mobile.home_banners')
|
||||
const publishStats = computed(() => {
|
||||
@@ -54,9 +61,13 @@ 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 salePriceStats = computed(() => {
|
||||
const config = safeParseSalePriceConfig(salePriceConfig.value?.value || '')
|
||||
return {
|
||||
fixedCount: config.fixed_markup_rules.length,
|
||||
ratioCount: config.ratio_adjustment_rules.length,
|
||||
}
|
||||
})
|
||||
const homeStats = computed(() => {
|
||||
@@ -72,6 +83,7 @@ const isStructuredConfig = computed(() => {
|
||||
const trimmed = value.value.trim()
|
||||
return (
|
||||
isPublishOptionsConfig.value ||
|
||||
isSalePriceConfig.value ||
|
||||
isHomeAnnouncementsConfig.value ||
|
||||
isHomeBannersConfig.value ||
|
||||
trimmed.startsWith('{') ||
|
||||
@@ -80,7 +92,7 @@ const isStructuredConfig = computed(() => {
|
||||
})
|
||||
|
||||
const dialogWidth = computed(() => {
|
||||
if (isPublishOptionsConfig.value || isHomeBannersConfig.value) return '920px'
|
||||
if (isPublishOptionsConfig.value || isSalePriceConfig.value || isHomeBannersConfig.value) return '920px'
|
||||
if (isHomeAnnouncementsConfig.value) return '680px'
|
||||
return '560px'
|
||||
})
|
||||
@@ -103,6 +115,9 @@ function openEdit(row: SystemConfig) {
|
||||
if (row.key === 'listing.publish_options') {
|
||||
publishOptionsDraft.value = parsePublishOptions(row.value)
|
||||
}
|
||||
if (row.key === 'listing.sale_price_config') {
|
||||
salePriceConfigDraft.value = parseSalePriceConfig(row.value)
|
||||
}
|
||||
if (row.key === 'mobile.home_announcements') {
|
||||
homeAnnouncementLines.value = itemsToLines(parseHomeAnnouncements(row.value, true))
|
||||
}
|
||||
@@ -118,6 +133,9 @@ async function handleSave() {
|
||||
if (isPublishOptionsConfig.value) {
|
||||
value.value = JSON.stringify(publishOptionsDraft.value, null, 2)
|
||||
}
|
||||
if (isSalePriceConfig.value) {
|
||||
value.value = JSON.stringify(salePriceConfigDraft.value, null, 2)
|
||||
}
|
||||
if (isHomeAnnouncementsConfig.value) {
|
||||
value.value = JSON.stringify(linesToItems(homeAnnouncementLines.value), null, 2)
|
||||
}
|
||||
@@ -161,6 +179,25 @@ function safeParsePublishOptions(raw: string) {
|
||||
}
|
||||
}
|
||||
|
||||
function parseSalePriceConfig(raw: string) {
|
||||
try {
|
||||
const parsed = raw.trim() ? JSON.parse(raw) : emptyListingSalePriceConfig
|
||||
return cloneSalePriceConfig(mergeListingSalePriceConfig(parsed))
|
||||
} catch {
|
||||
ElMessage.warning('出售定价规则 JSON 解析失败,已清空草稿')
|
||||
return cloneSalePriceConfig(emptyListingSalePriceConfig)
|
||||
}
|
||||
}
|
||||
|
||||
function safeParseSalePriceConfig(raw: string) {
|
||||
try {
|
||||
const parsed = raw.trim() ? JSON.parse(raw) : emptyListingSalePriceConfig
|
||||
return cloneSalePriceConfig(mergeListingSalePriceConfig(parsed))
|
||||
} catch {
|
||||
return cloneSalePriceConfig(emptyListingSalePriceConfig)
|
||||
}
|
||||
}
|
||||
|
||||
function parseHomeAnnouncements(raw: string, showWarning = false) {
|
||||
try {
|
||||
const parsed = raw.trim() ? JSON.parse(raw) : defaultHomeAnnouncements
|
||||
@@ -185,6 +222,10 @@ function cloneOptions(options: ListingPublishOptions) {
|
||||
return JSON.parse(JSON.stringify(options)) as ListingPublishOptions
|
||||
}
|
||||
|
||||
function cloneSalePriceConfig(config: PublishSalePriceConfig) {
|
||||
return JSON.parse(JSON.stringify(config)) as PublishSalePriceConfig
|
||||
}
|
||||
|
||||
function cloneHomeBanners(banners: HomeBannerSlide[]) {
|
||||
return JSON.parse(JSON.stringify(banners)) as HomeBannerSlide[]
|
||||
}
|
||||
@@ -285,7 +326,7 @@ function removeCoinCorrection(index: number) {
|
||||
}
|
||||
|
||||
function addSaleFixedMarkupRule() {
|
||||
publishOptionsDraft.value.sale_price_config.fixed_markup_rules.push({
|
||||
salePriceConfigDraft.value.fixed_markup_rules.push({
|
||||
min_m: 0,
|
||||
max_m: 0,
|
||||
markup_amount: 0,
|
||||
@@ -293,11 +334,11 @@ function addSaleFixedMarkupRule() {
|
||||
}
|
||||
|
||||
function removeSaleFixedMarkupRule(index: number) {
|
||||
publishOptionsDraft.value.sale_price_config.fixed_markup_rules.splice(index, 1)
|
||||
salePriceConfigDraft.value.fixed_markup_rules.splice(index, 1)
|
||||
}
|
||||
|
||||
function addSaleRatioAdjustmentRule() {
|
||||
publishOptionsDraft.value.sale_price_config.ratio_adjustment_rules.push({
|
||||
salePriceConfigDraft.value.ratio_adjustment_rules.push({
|
||||
min_m: 0,
|
||||
max_m: 0,
|
||||
ratio_subtract: 0,
|
||||
@@ -305,7 +346,7 @@ function addSaleRatioAdjustmentRule() {
|
||||
}
|
||||
|
||||
function removeSaleRatioAdjustmentRule(index: number) {
|
||||
publishOptionsDraft.value.sale_price_config.ratio_adjustment_rules.splice(index, 1)
|
||||
salePriceConfigDraft.value.ratio_adjustment_rules.splice(index, 1)
|
||||
}
|
||||
|
||||
function addHomeBanner() {
|
||||
@@ -414,9 +455,38 @@ function readError(error: unknown, fallback: string) {
|
||||
<strong>{{ publishStats.regionCount }}</strong>
|
||||
<span>地区</span>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section v-if="salePriceConfig" class="publish-config-panel">
|
||||
<div class="publish-config-main">
|
||||
<div>
|
||||
<p class="eyebrow">Sale Pricing</p>
|
||||
<h2>内部出售定价规则</h2>
|
||||
<span>管理出售加价和比例扣减规则,仅用于平台内部定价计算,不在发布页展示。</span>
|
||||
</div>
|
||||
<el-button type="primary" @click="openEdit(salePriceConfig)">编辑出售规则</el-button>
|
||||
</div>
|
||||
<div class="publish-stat-grid home-stat-grid">
|
||||
<div class="publish-stat">
|
||||
<strong>{{ publishStats.saleRuleCount }}</strong>
|
||||
<span>出售规则</span>
|
||||
<strong>{{ salePriceStats.fixedCount }}</strong>
|
||||
<span>固定加价</span>
|
||||
</div>
|
||||
<div class="publish-stat">
|
||||
<strong>{{ salePriceStats.ratioCount }}</strong>
|
||||
<span>比例扣减</span>
|
||||
</div>
|
||||
<div class="publish-stat">
|
||||
<strong>内部</strong>
|
||||
<span>不展示给发布用户</span>
|
||||
</div>
|
||||
<div class="publish-stat">
|
||||
<strong>配置</strong>
|
||||
<span>listing.sale_price_config</span>
|
||||
</div>
|
||||
<div class="publish-stat">
|
||||
<strong>更新</strong>
|
||||
<span>{{ formatHomeConfigStatus(salePriceConfig, '未初始化') }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
@@ -673,53 +743,6 @@ 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>
|
||||
@@ -792,6 +815,56 @@ function readError(error: unknown, fallback: string) {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-else-if="isSalePriceConfig" class="publish-options-editor">
|
||||
<div class="editor-toolbar">
|
||||
<span>内部出售定价规则</span>
|
||||
</div>
|
||||
|
||||
<div class="editor-block">
|
||||
<div class="editor-block-title subtle-title">
|
||||
<span>90M 及以下固定加价:出售价格 = 回收价格 + 固定加价</span>
|
||||
<el-button size="small" @click="addSaleFixedMarkupRule">添加固定加价</el-button>
|
||||
</div>
|
||||
<el-table :data="salePriceConfigDraft.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="salePriceConfigDraft.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>
|
||||
|
||||
<div v-else-if="isHomeAnnouncementsConfig" class="home-config-editor">
|
||||
<div class="editor-toolbar">
|
||||
<span>首页公告</span>
|
||||
|
||||
Reference in New Issue
Block a user