Files
jinshen-website/app/components/pages/homepage/HomepageSolutionSection.vue
R2m1liA d076088747 feat: 首页竖屏适配
- 首页Carousel高度根据屏幕宽度变化
- 首页推荐栏目卡片数量随屏幕宽度改变
2025-11-01 15:32:15 +08:00

229 lines
4.9 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<section class="homepage-section">
<h2>推荐解决方案</h2>
<p>了解我们的定制解决方案帮助您优化业务流程提高效率</p>
<div v-if="!pending">
<el-carousel
class="recommend-carousel"
:height="carouselHeight"
arrow="never"
indicator-position="outside"
:autoplay="false"
>
<el-carousel-item
v-for="n in pages"
ref="carouselItem"
:key="n"
class="recommend-list"
>
<div class="recommend-card-group">
<el-card
v-for="(item, index) in pageSolutions(n)"
:key="index"
class="recommend-card"
@click="handleSolutionCardClick(item.id.toString() || '')"
>
<template #header>
<el-image
:src="getImageUrl(item.cover)"
:alt="item.title"
fit="cover"
lazy
/>
</template>
<div class="recommend-card-body">
<!-- Title -->
<div class="text-center">
<span class="recommend-card-title">{{ item.title }}</span>
</div>
<!-- Description -->
<div class="recommend-card-description text-left opacity-25">
{{ item.summary }}
</div>
</div>
</el-card>
</div>
</el-carousel-item>
</el-carousel>
</div>
<div v-else>
<el-skeleton :rows="4" animated />
</div>
</section>
</template>
<script setup lang="ts">
const props = defineProps({
homepageData: {
type: Object as PropType<HomepageView>,
default: null,
},
pending: {
type: Boolean,
},
});
const carouselHeight = ref<string>('auto');
const perPage = ref(3);
const carouselItem = ref<HTMLElement | null>(null);
const { getImageUrl } = useDirectusImage();
const { height } = useElementSize(carouselItem);
const solutions = computed(
() => props.homepageData?.recommendSolutions || []
);
const pages = computed(() =>
Math.ceil(solutions.value.length / perPage.value)
);
const updatePerPage = () => {
const width = window.innerWidth;
if (width < 768) {
perPage.value = 1;
} else if (width < 1024) {
perPage.value = 2;
} else {
perPage.value = 3;
}
};
const pageSolutions = (n: number) => {
return solutions.value.slice((n - 1) * perPage.value, n * perPage.value);
};
const handleSolutionCardClick = (documentId: string) => {
// 使用路由导航到产品详情页
if (documentId) {
const localePath = useLocalePath();
const router = useRouter();
router.push(localePath(`/solutions/${documentId}`));
}
};
watch(height, (h) => {
if (h > 0) {
carouselHeight.value = h + 40 + 'px';
console.log('carouselHeight updated:', carouselHeight.value);
}
});
onMounted(() => {
updatePerPage();
window.addEventListener('resize', updatePerPage);
});
onBeforeUnmount(() => {
window.removeEventListener('resize', updatePerPage);
});
</script>
<style scoped>
section {
padding: 2rem;
}
section h2 {
color: var(--el-text-color-primary);
font-size: 1.5rem;
font-weight: bold;
margin-bottom: 0.5rem;
}
section p {
color: var(--el-text-color-regular);
line-height: 1.6;
}
.homepage-section {
max-width: 1200px;
margin: 0 auto;
}
.recommend-carousel :deep(.el-carousel__button) {
/* 指示器按钮样式 */
width: 8px;
height: 8px;
border-radius: 50%;
background-color: #475669;
transition: all 0.3s ease;
}
.homepage-section {
max-width: 1200px;
margin: 0 auto;
}
.recommend-carousel :deep(.el-carousel__button) {
/* 指示器按钮样式 */
width: 8px;
height: 8px;
border-radius: 50%;
background-color: #475669;
transition: all 0.3s ease;
}
.recommend-list {
display: flex;
padding: 1rem;
height: auto;
}
.recommend-card-group {
display: flex;
gap: 1rem;
width: 100%;
margin: 0 auto;
height: auto;
}
.recommend-card {
width: 33%;
transition: all 0.3s ease;
text-align: center;
}
.recommend-card :deep(.el-card__header) {
padding: 0;
border: none;
}
.recommend-card:hover {
transform: translateY(-4px);
box-shadow: 0 8px 25px rgba(0, 0, 0, 0.15);
cursor: pointer;
}
.recommend-card-body {
margin: 10px auto;
padding: 0px auto;
}
.recommend-card-title {
font-size: 1rem;
font-weight: 600;
}
.recommend-card-description {
font-size: 0.8rem;
margin-top: 5px;
}
.recommend-card .el-image {
width: 100%;
border-radius: 4px;
}
@media (max-width: 1024px) {
.recommend-card {
width: 50%;
}
}
@media (max-width: 768px) {
.recommend-card {
width: 100%;
}
}
</style>