增加发布协议确认配置

This commit is contained in:
yml2213
2026-06-07 21:14:49 +08:00
parent 954c3d6be3
commit eebd2d3b04
19 changed files with 760 additions and 13 deletions
@@ -7,6 +7,7 @@ import {
mergeListingSalePriceConfig,
mergeListingPublishOptions,
type ListingPublishOptions,
type ListingPublishAgreements,
type PublishSalePriceConfig,
} from '@/features/listings/api/listingOptions'
import {
@@ -26,6 +27,7 @@ import PublishOptionsDialog from '../components/PublishOptionsDialog.vue'
import SalePriceDialog from '../components/SalePriceDialog.vue'
import HomeAnnouncementsDialog from '../components/HomeAnnouncementsDialog.vue'
import HomeBannersDialog from '../components/HomeBannersDialog.vue'
import ListingPublishAgreementsDialog from '../components/ListingPublishAgreementsDialog.vue'
import OrderAgreementsDialog from '../components/OrderAgreementsDialog.vue'
import PostRentalNoticeDialog from '../components/PostRentalNoticeDialog.vue'
import GeneralConfigDialog from '../components/GeneralConfigDialog.vue'
@@ -42,6 +44,17 @@ const defaultOrderAgreements: OrderAgreements = {
},
}
const defaultListingPublishAgreements: ListingPublishAgreements = {
virtual_asset_sale: {
title: '虚拟资产出售协议',
content: '',
},
seller_agreement: {
title: '号主协议',
content: '',
},
}
const loading = ref(false)
const configs = ref<SystemConfig[]>([])
const currentEditingConfig = ref<SystemConfig | null>(null)
@@ -51,6 +64,7 @@ const publishVisible = ref(false)
const salePriceVisible = ref(false)
const announcementsVisible = ref(false)
const bannersVisible = ref(false)
const listingPublishAgreementsVisible = ref(false)
const agreementsVisible = ref(false)
const postRentalNoticeVisible = ref(false)
const generalVisible = ref(false)
@@ -59,6 +73,7 @@ const publishConfig = computed(() => configs.value.find((item) => item.key === '
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 listingPublishAgreementsConfig = computed(() => configs.value.find((item) => item.key === 'listing.publish_agreements') || null)
const orderAgreementsConfig = computed(() => configs.value.find((item) => item.key === 'order.agreements') || null)
const postRentalNoticeConfig = computed(() => configs.value.find((item) => item.key === 'profile.post_rental_notice') || null)
@@ -69,6 +84,7 @@ const regularConfigs = computed(() =>
item.key !== 'listing.sale_price_config' &&
item.key !== 'mobile.home_announcements' &&
item.key !== 'mobile.home_banners' &&
item.key !== 'listing.publish_agreements' &&
item.key !== 'order.agreements' &&
item.key !== 'profile.post_rental_notice',
),
@@ -117,6 +133,16 @@ const agreementStats = computed(() => {
}
})
const listingPublishAgreementStats = computed(() => {
const agreements = parseListingPublishAgreements(listingPublishAgreementsConfig.value?.value || '')
return {
saleTitle: agreements.virtual_asset_sale.title || '出售协议',
sellerTitle: agreements.seller_agreement.title || '号主协议',
saleWords: countContentWords(agreements.virtual_asset_sale.content),
sellerWords: countContentWords(agreements.seller_agreement.content),
}
})
onMounted(loadConfigs)
async function loadConfigs() {
@@ -138,6 +164,8 @@ function openEdit(row: SystemConfig) {
announcementsVisible.value = true
} else if (row.key === 'mobile.home_banners') {
bannersVisible.value = true
} else if (row.key === 'listing.publish_agreements') {
listingPublishAgreementsVisible.value = true
} else if (row.key === 'order.agreements') {
agreementsVisible.value = true
} else if (row.key === 'profile.post_rental_notice') {
@@ -181,6 +209,20 @@ function parseOrderAgreements(raw: string) {
}
}
function parseListingPublishAgreements(raw: string) {
const parsed = safeParseJSON(raw, defaultListingPublishAgreements)
return {
virtual_asset_sale: {
title: readText(parsed.virtual_asset_sale?.title, defaultListingPublishAgreements.virtual_asset_sale.title),
content: readText(parsed.virtual_asset_sale?.content, defaultListingPublishAgreements.virtual_asset_sale.content),
},
seller_agreement: {
title: readText(parsed.seller_agreement?.title, defaultListingPublishAgreements.seller_agreement.title),
content: readText(parsed.seller_agreement?.content, defaultListingPublishAgreements.seller_agreement.content),
},
}
}
function readText(value: unknown, fallback: string) {
return typeof value === 'string' && value.trim() ? value : fallback
}
@@ -329,6 +371,39 @@ function formatConfigValue(row: SystemConfig) {
</div>
</section>
<section v-if="listingPublishAgreementsConfig" class="publish-config-panel">
<div class="publish-config-main">
<div>
<p class="eyebrow">Publish Agreements</p>
<h2>发布协议配置</h2>
<span>管理发布账号前必须勾选确认的虚拟资产出售协议和号主协议</span>
</div>
<el-button type="primary" @click="openEdit(listingPublishAgreementsConfig)">编辑发布协议</el-button>
</div>
<div class="publish-stat-grid home-stat-grid">
<div class="publish-stat">
<strong>2</strong>
<span>协议数量</span>
</div>
<div class="publish-stat">
<strong>{{ listingPublishAgreementStats.saleWords }}</strong>
<span>{{ listingPublishAgreementStats.saleTitle }}字数</span>
</div>
<div class="publish-stat">
<strong>{{ listingPublishAgreementStats.sellerWords }}</strong>
<span>{{ listingPublishAgreementStats.sellerTitle }}字数</span>
</div>
<div class="publish-stat">
<strong>接口</strong>
<span>/api/listing-publish-agreements</span>
</div>
<div class="publish-stat">
<strong>更新</strong>
<span>{{ formatHomeConfigStatus(listingPublishAgreementsConfig, '未初始化') }}</span>
</div>
</div>
</section>
<section v-if="orderAgreementsConfig" class="publish-config-panel">
<div class="publish-config-main">
<div>
@@ -446,6 +521,13 @@ function formatConfigValue(row: SystemConfig) {
@saved="loadConfigs"
/>
<ListingPublishAgreementsDialog
v-if="listingPublishAgreementsConfig"
v-model="listingPublishAgreementsVisible"
:config="listingPublishAgreementsConfig"
@saved="loadConfigs"
/>
<OrderAgreementsDialog
v-if="orderAgreementsConfig"
v-model="agreementsVisible"