官网开发中 0731
This commit is contained in:
@@ -0,0 +1,87 @@
|
||||
<script setup lang="ts">
|
||||
import type { SectionBlock, SectionLayout } from '~/types/site';
|
||||
import LayoutHeroSplit from './layouts/LayoutHeroSplit.vue';
|
||||
import LayoutFullBanner from './layouts/LayoutFullBanner.vue';
|
||||
import LayoutFeatureGrid from './layouts/LayoutFeatureGrid.vue';
|
||||
import LayoutSplitContent from './layouts/LayoutSplitContent.vue';
|
||||
import LayoutGallery from './layouts/LayoutGallery.vue';
|
||||
import LayoutStats from './layouts/LayoutStats.vue';
|
||||
import LayoutVideoShowcase from './layouts/LayoutVideoShowcase.vue';
|
||||
import LayoutScrollNarrative from './layouts/LayoutScrollNarrative.vue';
|
||||
import LayoutQuote from './layouts/LayoutQuote.vue';
|
||||
import LayoutSpecTable from './layouts/LayoutSpecTable.vue';
|
||||
|
||||
const props = defineProps<{ section: SectionBlock }>();
|
||||
|
||||
// 布局类型 -> 组件映射
|
||||
const layoutComponents: Record<SectionLayout, unknown> = {
|
||||
hero_split: LayoutHeroSplit,
|
||||
full_banner: LayoutFullBanner,
|
||||
feature_grid: LayoutFeatureGrid,
|
||||
split_content: LayoutSplitContent,
|
||||
gallery: LayoutGallery,
|
||||
stats: LayoutStats,
|
||||
video_showcase: LayoutVideoShowcase,
|
||||
scroll_narrative: LayoutScrollNarrative,
|
||||
quote: LayoutQuote,
|
||||
spec_table: LayoutSpecTable
|
||||
};
|
||||
|
||||
const layoutComponent = computed(() => layoutComponents[props.section.layout] ?? null);
|
||||
|
||||
const isDark = computed(() => props.section.theme === 'dark');
|
||||
|
||||
// 遮罩透明度(decimal 字符串 -> 数值)
|
||||
const overlayOpacity = computed(() => Number(props.section.overlay_opacity) || 0);
|
||||
const showOverlay = computed(() => !!props.section.overlay_enabled && overlayOpacity.value > 0);
|
||||
|
||||
// 背景样式
|
||||
const bgStyle = computed(() => {
|
||||
const { bg_type, bg_value } = props.section;
|
||||
if (bg_type === 'color' && bg_value) {
|
||||
return { backgroundColor: bg_value };
|
||||
}
|
||||
return {};
|
||||
});
|
||||
|
||||
const hasBgImage = computed(() => props.section.bg_type === 'image' && !!props.section.bg_value);
|
||||
const hasBgVideo = computed(() => props.section.bg_type === 'video' && !!props.section.bg_value);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<section
|
||||
class="relative overflow-hidden"
|
||||
:class="isDark ? 'bg-gray-950 text-white' : 'bg-white text-gray-900 dark:bg-dark-900 dark:text-white'"
|
||||
:style="bgStyle"
|
||||
>
|
||||
<!-- 背景图 -->
|
||||
<div
|
||||
v-if="hasBgImage"
|
||||
class="absolute inset-0 bg-cover bg-center"
|
||||
:style="{ backgroundImage: `url(${section.bg_value})` }"
|
||||
/>
|
||||
|
||||
<!-- 背景视频 -->
|
||||
<video
|
||||
v-if="hasBgVideo"
|
||||
:src="section.bg_value"
|
||||
class="absolute inset-0 w-full h-full object-cover"
|
||||
autoplay
|
||||
muted
|
||||
loop
|
||||
playsinline
|
||||
/>
|
||||
|
||||
<!-- 遮罩层 -->
|
||||
<div
|
||||
v-if="showOverlay"
|
||||
class="absolute inset-0 bg-black"
|
||||
:style="{ opacity: overlayOpacity }"
|
||||
/>
|
||||
|
||||
<!-- 布局内容 -->
|
||||
<div class="relative z-10">
|
||||
<component :is="layoutComponent" v-if="layoutComponent" :section="section" />
|
||||
</div>
|
||||
</section>
|
||||
</template>
|
||||
Reference in New Issue
Block a user