fix(systemconfig): 首页入口展示开关与发布选项编码修复
This commit is contained in:
@@ -129,6 +129,12 @@ describe('mergeHomeConfig', () => {
|
||||
expect(config.banners.length).toBeGreaterThan(0)
|
||||
expect(config.banners[0]?.pc.image_url).toBe('')
|
||||
})
|
||||
|
||||
it('首页业务入口总开关缺省关闭,显式开启时透传', () => {
|
||||
expect(mergeHomeConfig({}).home_entries_enabled).toBe(false)
|
||||
expect(mergeHomeConfig({ home_entries_enabled: true }).home_entries_enabled).toBe(true)
|
||||
expect(mergeHomeConfig({ home_entries_enabled: false }).home_entries_enabled).toBe(false)
|
||||
})
|
||||
})
|
||||
|
||||
describe('createBannerHotspot', () => {
|
||||
|
||||
@@ -209,8 +209,13 @@ export interface MobileHomeConfig {
|
||||
publish_options: ListingPublishOptions
|
||||
aw_recycle: AWRecycleConfig
|
||||
cooperation_feedback: CooperationFeedbackConfig
|
||||
/** 首页业务入口总开关:关闭后 PC/移动端同时隐藏回收与合作入口。 */
|
||||
home_entries_enabled: boolean
|
||||
}
|
||||
|
||||
/** 总开关默认关闭,避免新环境误展示尚未准备好的业务入口。 */
|
||||
export const defaultHomeEntriesEnabled = false
|
||||
|
||||
export const defaultAWRecycleConfig: AWRecycleConfig = {
|
||||
title: 'AW炫彩回收',
|
||||
subtitle: '点击查看回收说明',
|
||||
@@ -320,6 +325,10 @@ export function mergeHomeConfig(config?: Partial<MobileHomeConfig>): MobileHomeC
|
||||
publish_options: mergeListingPublishOptions(config?.publish_options),
|
||||
aw_recycle: awRecycle,
|
||||
cooperation_feedback: cooperationFeedback,
|
||||
home_entries_enabled:
|
||||
typeof config?.home_entries_enabled === 'boolean'
|
||||
? config.home_entries_enabled
|
||||
: defaultHomeEntriesEnabled,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@ import {
|
||||
defaultCooperationFeedbackConfig,
|
||||
defaultHomeAnnouncements,
|
||||
defaultHomeBanners,
|
||||
defaultHomeEntriesEnabled,
|
||||
fetchMobileHomeConfig,
|
||||
normalizeHomeBanner,
|
||||
type AWRecycleConfig,
|
||||
@@ -71,6 +72,20 @@ const awRecycle = ref<AWRecycleConfig>({ ...defaultAWRecycleConfig })
|
||||
const awRecycleDialogVisible = ref(false)
|
||||
const cooperationFeedback = ref<CooperationFeedbackConfig>({ ...defaultCooperationFeedbackConfig })
|
||||
const cooperationFeedbackDialogVisible = ref(false)
|
||||
const homeEntriesEnabled = ref(defaultHomeEntriesEnabled)
|
||||
const showAWRecycle = computed(() => homeEntriesEnabled.value && awRecycle.value.enabled)
|
||||
const showCooperationFeedback = computed(
|
||||
() => homeEntriesEnabled.value && cooperationFeedback.value.enabled
|
||||
)
|
||||
const showBizEntryRail = computed(
|
||||
() => !siteStore.isDistribution || showAWRecycle.value || showCooperationFeedback.value
|
||||
)
|
||||
const bizEntryCount = computed(
|
||||
() =>
|
||||
(siteStore.isDistribution ? 0 : 1) +
|
||||
(showAWRecycle.value ? 1 : 0) +
|
||||
(showCooperationFeedback.value ? 1 : 0)
|
||||
)
|
||||
const publishOptions = ref<ListingPublishOptions>(emptyListingPublishOptions)
|
||||
interface SortButtonItem {
|
||||
key: string
|
||||
@@ -251,12 +266,14 @@ async function loadHome() {
|
||||
banners.value = config.banners
|
||||
awRecycle.value = config.aw_recycle
|
||||
cooperationFeedback.value = config.cooperation_feedback
|
||||
homeEntriesEnabled.value = config.home_entries_enabled
|
||||
publishOptions.value = config.publish_options
|
||||
} catch {
|
||||
announcements.value = defaultHomeAnnouncements
|
||||
banners.value = defaultHomeBanners
|
||||
awRecycle.value = { ...defaultAWRecycleConfig }
|
||||
cooperationFeedback.value = { ...defaultCooperationFeedbackConfig }
|
||||
homeEntriesEnabled.value = defaultHomeEntriesEnabled
|
||||
publishOptions.value = emptyListingPublishOptions
|
||||
} finally {
|
||||
loading.value = false
|
||||
@@ -404,6 +421,7 @@ function restoreFromCache(): boolean {
|
||||
banners.value = pcHomeCache.banners.map(slide => normalizeHomeBanner(slide))
|
||||
awRecycle.value = { ...pcHomeCache.awRecycle }
|
||||
cooperationFeedback.value = { ...pcHomeCache.cooperationFeedback }
|
||||
homeEntriesEnabled.value = pcHomeCache.homeEntriesEnabled
|
||||
publishOptions.value = pcHomeCache.publishOptions
|
||||
}
|
||||
return true
|
||||
@@ -425,6 +443,7 @@ function saveToCache() {
|
||||
banners: banners.value,
|
||||
awRecycle: awRecycle.value,
|
||||
cooperationFeedback: cooperationFeedback.value,
|
||||
homeEntriesEnabled: homeEntriesEnabled.value,
|
||||
publishOptions: publishOptions.value,
|
||||
})
|
||||
pcHomeCache.saveScrollTop(window.scrollY)
|
||||
@@ -539,11 +558,16 @@ if (!restored) {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="hero-section">
|
||||
<div class="hero-section" :class="{ 'without-entry-rail': !showBizEntryRail }">
|
||||
<HomeBanner :banners="displayBanners" :stats="statCards" />
|
||||
|
||||
<!-- 业务入口:贴在轮播右侧竖排;原「租号大厅」只是跳回首页,已移除 -->
|
||||
<div class="biz-entry-rail" aria-label="业务入口">
|
||||
<div
|
||||
v-if="showBizEntryRail"
|
||||
class="biz-entry-rail"
|
||||
:class="{ 'single-entry': bizEntryCount === 1 }"
|
||||
aria-label="业务入口"
|
||||
>
|
||||
<RouterLink v-if="!siteStore.isDistribution" class="biz-entry crash" to="/crash">
|
||||
<div class="biz-title-row">
|
||||
<strong>撞车 <em>NEW</em></strong>
|
||||
@@ -552,7 +576,7 @@ if (!restored) {
|
||||
<van-icon name="arrow" :size="14" class="biz-arrow" />
|
||||
</RouterLink>
|
||||
<button
|
||||
v-if="awRecycle.enabled"
|
||||
v-if="showAWRecycle"
|
||||
type="button"
|
||||
class="biz-entry aw-recycle"
|
||||
@click="openAWRecycle"
|
||||
@@ -564,7 +588,7 @@ if (!restored) {
|
||||
<van-icon name="arrow" :size="14" class="biz-arrow" />
|
||||
</button>
|
||||
<button
|
||||
v-if="cooperationFeedback.enabled"
|
||||
v-if="showCooperationFeedback"
|
||||
type="button"
|
||||
class="biz-entry cooperation-feedback"
|
||||
@click="openCooperationFeedback"
|
||||
@@ -699,6 +723,10 @@ if (!restored) {
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.hero-section.without-entry-rail {
|
||||
grid-template-columns: minmax(0, 1fr);
|
||||
}
|
||||
|
||||
.biz-entry-rail {
|
||||
display: grid;
|
||||
grid-auto-rows: minmax(0, 1fr);
|
||||
@@ -706,6 +734,11 @@ if (!restored) {
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.biz-entry-rail.single-entry {
|
||||
grid-auto-rows: auto;
|
||||
align-content: start;
|
||||
}
|
||||
|
||||
.biz-entry {
|
||||
position: relative;
|
||||
display: flex;
|
||||
@@ -843,6 +876,14 @@ if (!restored) {
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.biz-entry-rail.single-entry {
|
||||
grid-template-columns: minmax(0, 1fr);
|
||||
}
|
||||
|
||||
.biz-entry-rail.two-entries {
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
}
|
||||
|
||||
.biz-entry {
|
||||
min-height: 76px;
|
||||
padding: 14px 40px 14px 16px;
|
||||
|
||||
@@ -493,6 +493,14 @@
|
||||
margin: 0 0 12px;
|
||||
}
|
||||
|
||||
.biz-entry-grid.single-entry {
|
||||
grid-template-columns: minmax(0, 1fr);
|
||||
}
|
||||
|
||||
.biz-entry-grid.two-entries {
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
}
|
||||
|
||||
.biz-entry {
|
||||
position: relative;
|
||||
display: flex;
|
||||
|
||||
@@ -18,6 +18,7 @@ import {
|
||||
defaultCooperationFeedbackConfig,
|
||||
defaultHomeAnnouncements,
|
||||
defaultHomeBanners,
|
||||
defaultHomeEntriesEnabled,
|
||||
fetchMobileHomeConfig,
|
||||
hasBannerImage,
|
||||
normalizeHomeBanner,
|
||||
@@ -126,6 +127,21 @@ const awRecycle = ref<AWRecycleConfig>({ ...defaultAWRecycleConfig })
|
||||
const awRecyclePreviewVisible = ref(false)
|
||||
const cooperationFeedback = ref<CooperationFeedbackConfig>({ ...defaultCooperationFeedbackConfig })
|
||||
const cooperationFeedbackPreviewVisible = ref(false)
|
||||
const homeEntriesEnabled = ref(defaultHomeEntriesEnabled)
|
||||
const showAWRecycle = computed(() => homeEntriesEnabled.value && awRecycle.value.enabled)
|
||||
const showCooperationFeedback = computed(
|
||||
() => homeEntriesEnabled.value && cooperationFeedback.value.enabled
|
||||
)
|
||||
const showCrashEntry = computed(() => !siteStore.isDistribution)
|
||||
const showBizEntryGrid = computed(
|
||||
() => showCrashEntry.value || showAWRecycle.value || showCooperationFeedback.value
|
||||
)
|
||||
const bizEntryCount = computed(
|
||||
() =>
|
||||
(showCrashEntry.value ? 1 : 0) +
|
||||
(showAWRecycle.value ? 1 : 0) +
|
||||
(showCooperationFeedback.value ? 1 : 0)
|
||||
)
|
||||
const supportLoading = ref(false)
|
||||
const showBackTop = ref(false)
|
||||
const mobilePageSize = 10
|
||||
@@ -361,6 +377,9 @@ function restoreHomeConfigFromCache() {
|
||||
if (!homeCache.homeConfigLoaded) return false
|
||||
announcements.value = homeCache.announcements.slice()
|
||||
bannerSlides.value = homeCache.bannerSlides.map(slide => normalizeHomeBanner(slide))
|
||||
awRecycle.value = { ...homeCache.awRecycle }
|
||||
cooperationFeedback.value = { ...homeCache.cooperationFeedback }
|
||||
homeEntriesEnabled.value = homeCache.homeEntriesEnabled
|
||||
publishOptions.value = homeCache.publishOptions
|
||||
return true
|
||||
}
|
||||
@@ -479,10 +498,14 @@ async function loadHomeConfig() {
|
||||
bannerSlides.value = config.banners
|
||||
awRecycle.value = config.aw_recycle
|
||||
cooperationFeedback.value = config.cooperation_feedback
|
||||
homeEntriesEnabled.value = config.home_entries_enabled
|
||||
publishOptions.value = config.publish_options
|
||||
homeCache.saveHomeConfig({
|
||||
announcements: config.announcements,
|
||||
bannerSlides: config.banners,
|
||||
awRecycle: config.aw_recycle,
|
||||
cooperationFeedback: config.cooperation_feedback,
|
||||
homeEntriesEnabled: config.home_entries_enabled,
|
||||
publishOptions: config.publish_options,
|
||||
})
|
||||
} catch {
|
||||
@@ -490,6 +513,7 @@ async function loadHomeConfig() {
|
||||
bannerSlides.value = defaultHomeBanners
|
||||
awRecycle.value = { ...defaultAWRecycleConfig }
|
||||
cooperationFeedback.value = { ...defaultCooperationFeedbackConfig }
|
||||
homeEntriesEnabled.value = defaultHomeEntriesEnabled
|
||||
publishOptions.value = emptyListingPublishOptions
|
||||
}
|
||||
}
|
||||
@@ -556,10 +580,14 @@ async function onRefresh() {
|
||||
bannerSlides.value = nextHomeConfig.banners
|
||||
awRecycle.value = nextHomeConfig.aw_recycle
|
||||
cooperationFeedback.value = nextHomeConfig.cooperation_feedback
|
||||
homeEntriesEnabled.value = nextHomeConfig.home_entries_enabled
|
||||
publishOptions.value = nextHomeConfig.publish_options
|
||||
homeCache.saveHomeConfig({
|
||||
announcements: nextHomeConfig.announcements,
|
||||
bannerSlides: nextHomeConfig.banners,
|
||||
awRecycle: nextHomeConfig.aw_recycle,
|
||||
cooperationFeedback: nextHomeConfig.cooperation_feedback,
|
||||
homeEntriesEnabled: nextHomeConfig.home_entries_enabled,
|
||||
publishOptions: nextHomeConfig.publish_options,
|
||||
})
|
||||
showToast({ message: '刷新成功', icon: 'passed' })
|
||||
@@ -944,14 +972,22 @@ if (!restoreHomeConfigFromCache()) {
|
||||
</van-swipe-item>
|
||||
</van-swipe>
|
||||
|
||||
<div class="biz-entry-grid" aria-label="业务入口">
|
||||
<RouterLink v-if="!siteStore.isDistribution" class="biz-entry" to="/crash">
|
||||
<div
|
||||
v-if="showBizEntryGrid"
|
||||
class="biz-entry-grid"
|
||||
:class="{
|
||||
'single-entry': bizEntryCount === 1,
|
||||
'two-entries': bizEntryCount === 2,
|
||||
}"
|
||||
aria-label="业务入口"
|
||||
>
|
||||
<RouterLink v-if="showCrashEntry" class="biz-entry" to="/crash">
|
||||
<strong>撞车</strong>
|
||||
<small>选购商品 · 一键找客服</small>
|
||||
<em class="biz-entry-badge">NEW</em>
|
||||
</RouterLink>
|
||||
<button
|
||||
v-if="awRecycle.enabled"
|
||||
v-if="showAWRecycle"
|
||||
type="button"
|
||||
class="biz-entry aw-recycle"
|
||||
@click="openAWRecycle"
|
||||
@@ -960,7 +996,7 @@ if (!restoreHomeConfigFromCache()) {
|
||||
<small>{{ awRecycle.subtitle }}</small>
|
||||
</button>
|
||||
<button
|
||||
v-if="cooperationFeedback.enabled"
|
||||
v-if="showCooperationFeedback"
|
||||
type="button"
|
||||
class="biz-entry cooperation-feedback"
|
||||
@click="openCooperationFeedback"
|
||||
|
||||
Reference in New Issue
Block a user