Files
jinshen-website/app/components/pages/homepage/HomepageSolutionSection.vue
2025-11-01 16:08:25 +08:00

228 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';
}
});
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>