优化弹窗和后台设置字体
This commit is contained in:
@@ -15,6 +15,7 @@ import {
|
||||
mergeHomeConfig,
|
||||
type HomeBannerSlide,
|
||||
} from '@/features/listings/api/homeConfig'
|
||||
import type { OrderAgreements } from '@/features/orders/api/orders'
|
||||
import { fetchSystemConfigs, type SystemConfig } from '@/features/admin/api/systemConfigs'
|
||||
import { formatDateTime } from '@/utils/time'
|
||||
import { safeParseJSON } from '@/utils/json'
|
||||
@@ -25,9 +26,21 @@ 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 OrderAgreementsDialog from '../components/OrderAgreementsDialog.vue'
|
||||
import GeneralConfigDialog from '../components/GeneralConfigDialog.vue'
|
||||
import AutoWelcomeConfig from '../components/AutoWelcomeConfig.vue'
|
||||
|
||||
const defaultOrderAgreements: OrderAgreements = {
|
||||
virtual_asset_purchase: {
|
||||
title: '虚拟资产购买协议',
|
||||
content: '',
|
||||
},
|
||||
renter_agreement: {
|
||||
title: '租客协议',
|
||||
content: '',
|
||||
},
|
||||
}
|
||||
|
||||
const loading = ref(false)
|
||||
const configs = ref<SystemConfig[]>([])
|
||||
const currentEditingConfig = ref<SystemConfig | null>(null)
|
||||
@@ -37,12 +50,14 @@ const publishVisible = ref(false)
|
||||
const salePriceVisible = ref(false)
|
||||
const announcementsVisible = ref(false)
|
||||
const bannersVisible = ref(false)
|
||||
const agreementsVisible = ref(false)
|
||||
const generalVisible = ref(false)
|
||||
|
||||
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 orderAgreementsConfig = computed(() => configs.value.find((item) => item.key === 'order.agreements') || null)
|
||||
|
||||
const regularConfigs = computed(() =>
|
||||
configs.value.filter(
|
||||
@@ -50,7 +65,8 @@ const regularConfigs = computed(() =>
|
||||
item.key !== 'listing.publish_options' &&
|
||||
item.key !== 'listing.sale_price_config' &&
|
||||
item.key !== 'mobile.home_announcements' &&
|
||||
item.key !== 'mobile.home_banners',
|
||||
item.key !== 'mobile.home_banners' &&
|
||||
item.key !== 'order.agreements',
|
||||
),
|
||||
)
|
||||
|
||||
@@ -87,6 +103,16 @@ const homeStats = computed(() => {
|
||||
}
|
||||
})
|
||||
|
||||
const agreementStats = computed(() => {
|
||||
const agreements = parseOrderAgreements(orderAgreementsConfig.value?.value || '')
|
||||
return {
|
||||
virtualTitle: agreements.virtual_asset_purchase.title || '购买协议',
|
||||
renterTitle: agreements.renter_agreement.title || '租客协议',
|
||||
virtualWords: countContentWords(agreements.virtual_asset_purchase.content),
|
||||
renterWords: countContentWords(agreements.renter_agreement.content),
|
||||
}
|
||||
})
|
||||
|
||||
onMounted(loadConfigs)
|
||||
|
||||
async function loadConfigs() {
|
||||
@@ -108,6 +134,8 @@ function openEdit(row: SystemConfig) {
|
||||
announcementsVisible.value = true
|
||||
} else if (row.key === 'mobile.home_banners') {
|
||||
bannersVisible.value = true
|
||||
} else if (row.key === 'order.agreements') {
|
||||
agreementsVisible.value = true
|
||||
} else {
|
||||
generalVisible.value = true
|
||||
}
|
||||
@@ -133,6 +161,28 @@ function parseHomeBanners(raw: string) {
|
||||
return cloneHomeBanners(mergeHomeConfig({ banners: Array.isArray(parsed) ? parsed : [] }).banners)
|
||||
}
|
||||
|
||||
function parseOrderAgreements(raw: string) {
|
||||
const parsed = safeParseJSON(raw, defaultOrderAgreements)
|
||||
return {
|
||||
virtual_asset_purchase: {
|
||||
title: readText(parsed.virtual_asset_purchase?.title, defaultOrderAgreements.virtual_asset_purchase.title),
|
||||
content: readText(parsed.virtual_asset_purchase?.content, defaultOrderAgreements.virtual_asset_purchase.content),
|
||||
},
|
||||
renter_agreement: {
|
||||
title: readText(parsed.renter_agreement?.title, defaultOrderAgreements.renter_agreement.title),
|
||||
content: readText(parsed.renter_agreement?.content, defaultOrderAgreements.renter_agreement.content),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
function readText(value: unknown, fallback: string) {
|
||||
return typeof value === 'string' && value.trim() ? value : fallback
|
||||
}
|
||||
|
||||
function countContentWords(value: string) {
|
||||
return value.replace(/\s/g, '').length
|
||||
}
|
||||
|
||||
function cloneOptions(options: ListingPublishOptions) {
|
||||
return JSON.parse(JSON.stringify(options)) as ListingPublishOptions
|
||||
}
|
||||
@@ -273,6 +323,39 @@ function formatConfigValue(row: SystemConfig) {
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section v-if="orderAgreementsConfig" class="publish-config-panel">
|
||||
<div class="publish-config-main">
|
||||
<div>
|
||||
<p class="eyebrow">Order Agreements</p>
|
||||
<h2>下单协议配置</h2>
|
||||
<span>管理下单前必须阅读并勾选确认的虚拟资产购买协议和租客协议。</span>
|
||||
</div>
|
||||
<el-button type="primary" @click="openEdit(orderAgreementsConfig)">编辑协议</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>{{ agreementStats.virtualWords }}</strong>
|
||||
<span>{{ agreementStats.virtualTitle }}字数</span>
|
||||
</div>
|
||||
<div class="publish-stat">
|
||||
<strong>{{ agreementStats.renterWords }}</strong>
|
||||
<span>{{ agreementStats.renterTitle }}字数</span>
|
||||
</div>
|
||||
<div class="publish-stat">
|
||||
<strong>接口</strong>
|
||||
<span>/api/order-agreements</span>
|
||||
</div>
|
||||
<div class="publish-stat">
|
||||
<strong>更新</strong>
|
||||
<span>{{ formatHomeConfigStatus(orderAgreementsConfig, '未初始化') }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<AutoWelcomeConfig />
|
||||
|
||||
<el-table v-loading="loading" class="table-panel" :data="regularConfigs">
|
||||
@@ -324,6 +407,13 @@ function formatConfigValue(row: SystemConfig) {
|
||||
@saved="loadConfigs"
|
||||
/>
|
||||
|
||||
<OrderAgreementsDialog
|
||||
v-if="orderAgreementsConfig"
|
||||
v-model="agreementsVisible"
|
||||
:config="orderAgreementsConfig"
|
||||
@saved="loadConfigs"
|
||||
/>
|
||||
|
||||
<GeneralConfigDialog
|
||||
v-if="currentEditingConfig"
|
||||
v-model="generalVisible"
|
||||
@@ -398,6 +488,19 @@ function formatConfigValue(row: SystemConfig) {
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
/* 按钮文字清晰度优化 */
|
||||
:deep(.el-button--primary) {
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
:deep(.el-button--primary span) {
|
||||
color: #ffffff !important;
|
||||
text-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);
|
||||
font-weight: 700;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
@media (max-width: 1100px) {
|
||||
.publish-stat-grid {
|
||||
grid-template-columns: repeat(3, minmax(0, 1fr));
|
||||
|
||||
Reference in New Issue
Block a user