website-vue/pages/cases.vue
2025-04-22 16:46:16 +08:00

344 lines
13 KiB
Vue

<template>
<div>
<!-- 页面标题 -->
<HeroBanner
:title="$t('cases.hero.title')"
:subtitle="$t('cases.hero.subtitle')"
/>
<!-- 案例筛选 -->
<section class="py-10">
<div class="container">
<div class="bg-white p-6 rounded-lg shadow-md">
<div class="flex flex-wrap items-center justify-between gap-4">
<div class="flex flex-wrap items-center gap-4">
<span class="text-gray-700 font-medium">{{ $t('cases.filter.byIndustry') }}</span>
<div class="flex flex-wrap gap-2">
<button
v-for="industry in industries"
:key="industry"
@click="toggleIndustryFilter(industry)"
:class="[
'px-4 py-2 rounded-full text-sm',
selectedIndustries.includes(industry)
? 'bg-secondary text-white'
: 'bg-gray-100 text-gray-700 hover:bg-gray-200'
]"
>
{{ industry }}
</button>
<button
@click="clearIndustryFilters"
class="px-4 py-2 rounded-full text-sm bg-gray-100 text-gray-700 hover:bg-gray-200"
>
{{ $t('cases.filter.all') }}
</button>
</div>
</div>
<div class="flex items-center">
<span class="text-gray-700 font-medium mr-4">{{ $t('cases.filter.sortBy') }}</span>
<select
v-model="sortBy"
class="px-4 py-2 border border-gray-300 rounded-md focus:ring-2 focus:ring-secondary focus:border-transparent"
>
<option value="latest">{{ $t('cases.filter.latest') }}</option>
<option value="default">{{ $t('cases.filter.default') }}</option>
</select>
</div>
</div>
</div>
</div>
</section>
<!-- 案例列表 -->
<section class="py-12">
<div class="container">
<div v-if="filteredCases.length === 0" class="text-center py-16">
<i class="fas fa-search text-4xl text-gray-300 mb-4"></i>
<p class="text-xl text-gray-500">{{ $t('cases.noResults.text') }}</p>
<button @click="clearIndustryFilters" class="mt-4 text-secondary hover:text-secondary/90">
{{ $t('cases.noResults.clearFilters') }}
</button>
</div>
<div v-else class="grid md:grid-cols-2 lg:grid-cols-3 gap-8">
<div
v-for="(case_item, index) in filteredCases"
:key="index"
class="bg-white rounded-lg shadow-lg overflow-hidden hover:shadow-xl transition-all duration-300 transform hover:-translate-y-1"
>
<div class="h-48 bg-gray-200 relative overflow-hidden">
<div class="absolute top-0 right-0 bg-secondary text-white px-3 py-1 text-sm">
{{ $t(case_item.industry) }}
</div>
</div>
<div class="p-6">
<h3 class="text-2xl font-semibold mb-4">{{ $t(case_item.titleKey) }}</h3>
<p class="text-gray-600 mb-6">{{ $t(case_item.summaryKey) }}</p>
<div class="flex justify-between items-center">
<button @click="openCaseDetail(case_item)" class="text-secondary hover:text-secondary/90 flex items-center">
{{ $t('cases.caseDetail.readDetails') }}
<i class="fas fa-arrow-right ml-2"></i>
</button>
<span class="text-sm text-gray-500">{{ case_item.date }}</span>
</div>
</div>
</div>
</div>
</div>
</section>
<!-- 案例详情弹窗 -->
<div v-if="selectedCase" class="fixed inset-0 bg-black/50 flex items-center justify-center z-50 p-4">
<div class="bg-white rounded-lg max-w-4xl w-full max-h-[90vh] overflow-y-auto">
<div class="p-6 border-b">
<div class="flex justify-between items-center">
<h3 class="text-2xl font-bold">{{ $t(selectedCase.titleKey) }}</h3>
<button @click="selectedCase = null" class="text-gray-500 hover:text-gray-700">
<i class="fas fa-times text-xl"></i>
</button>
</div>
</div>
<div class="p-6">
<div class="flex flex-wrap gap-2 mb-6">
<span class="px-3 py-1 bg-secondary/10 text-secondary text-sm rounded-full">
{{ $t(selectedCase.industry) }}
</span>
<span class="px-3 py-1 bg-gray-100 text-gray-700 text-sm rounded-full">
{{ selectedCase.date }}
</span>
</div>
<h4 class="text-xl font-semibold mb-4">{{ $t('cases.caseDetail.background') }}</h4>
<p class="text-gray-600 mb-6">{{ $t(selectedCase.backgroundKey) }}</p>
<h4 class="text-xl font-semibold mb-4">{{ $t('cases.caseDetail.challenges') }}</h4>
<ul class="list-disc pl-5 mb-6 space-y-2">
<li v-for="(challenge, idx) in selectedCase.challenges" :key="idx" class="text-gray-600">
{{ $t(challenge) }}
</li>
</ul>
<h4 class="text-xl font-semibold mb-4">{{ $t('cases.caseDetail.solution') }}</h4>
<p class="text-gray-600 mb-4">{{ $t(selectedCase.solutionKey) }}</p>
<h4 class="text-xl font-semibold mb-4">{{ $t('cases.caseDetail.results') }}</h4>
<ul class="list-disc pl-5 mb-6 space-y-2">
<li v-for="(result, idx) in selectedCase.results" :key="idx" class="text-gray-600">
{{ $t(result) }}
</li>
</ul>
</div>
<div class="p-6 border-t bg-gray-50">
<div class="flex justify-end">
<button @click="selectedCase = null" class="px-4 py-2 bg-gray-200 text-gray-700 rounded hover:bg-gray-300">
{{ $t('cases.caseDetail.close') }}
</button>
</div>
</div>
</div>
</div>
<!-- 联系我们 -->
<section class="py-16 bg-primary text-white">
<div class="container text-center">
<h2 class="text-4xl font-bold mb-6">{{ $t('cases.contact.title') }}</h2>
<p class="text-xl mb-8 max-w-2xl mx-auto leading-relaxed">{{ $t('cases.contact.subtitle') }}</p>
<NuxtLink to="/contact" class="inline-flex items-center bg-white text-black px-8 py-4 rounded-lg hover:bg-gray-100 transition-colors duration-300 text-lg font-semibold">
{{ $t('cases.contact.button') }}
<i class="fas fa-arrow-right ml-2"></i>
</NuxtLink>
</div>
</section>
</div>
</template>
<script setup lang="ts">
import { ref, computed } from 'vue';
import { useI18n } from 'vue-i18n';
const { t } = useI18n();
// 所有行业标签
const industries = [
t('cases.industries.finance'),
t('cases.industries.ecommerce'),
t('cases.industries.manufacturing'),
t('cases.industries.healthcare'),
t('cases.industries.education'),
t('cases.industries.government'),
t('cases.industries.media'),
t('cases.industries.logistics')
];
// 筛选和排序状态
const selectedIndustries = ref<string[]>([]);
const sortBy = ref('default');
const selectedCase = ref<any>(null);
// 客户案例数据
const caseStudies = [
{
titleKey: 'cases.caseStudies.ecommerce.title',
industry: 'cases.caseStudies.ecommerce.industry',
date: '2023-05-15',
summaryKey: 'cases.caseStudies.ecommerce.summary',
backgroundKey: 'cases.caseStudies.ecommerce.background',
challenges: [
'cases.caseStudies.ecommerce.challenges[0]',
'cases.caseStudies.ecommerce.challenges[1]',
'cases.caseStudies.ecommerce.challenges[2]',
'cases.caseStudies.ecommerce.challenges[3]'
],
solutionKey: 'cases.caseStudies.ecommerce.solution',
results: [
'cases.caseStudies.ecommerce.results[0]',
'cases.caseStudies.ecommerce.results[1]',
'cases.caseStudies.ecommerce.results[2]',
'cases.caseStudies.ecommerce.results[3]',
'cases.caseStudies.ecommerce.results[4]'
]
},
{
titleKey: 'cases.caseStudies.finance.title',
industry: 'cases.caseStudies.finance.industry',
date: '2023-03-20',
summaryKey: 'cases.caseStudies.finance.summary',
backgroundKey: 'cases.caseStudies.finance.background',
challenges: [
'cases.caseStudies.finance.challenges[0]',
'cases.caseStudies.finance.challenges[1]',
'cases.caseStudies.finance.challenges[2]',
'cases.caseStudies.finance.challenges[3]'
],
solutionKey: 'cases.caseStudies.finance.solution',
results: [
'cases.caseStudies.finance.results[0]',
'cases.caseStudies.finance.results[1]',
'cases.caseStudies.finance.results[2]',
'cases.caseStudies.finance.results[3]',
'cases.caseStudies.finance.results[4]'
]
},
{
titleKey: 'cases.caseStudies.healthcare.title',
industry: 'cases.caseStudies.healthcare.industry',
date: '2022-11-10',
summaryKey: 'cases.caseStudies.healthcare.summary',
backgroundKey: 'cases.caseStudies.healthcare.background',
challenges: [
'cases.caseStudies.healthcare.challenges[0]',
'cases.caseStudies.healthcare.challenges[1]',
'cases.caseStudies.healthcare.challenges[2]',
'cases.caseStudies.healthcare.challenges[3]'
],
solutionKey: 'cases.caseStudies.healthcare.solution',
results: [
'cases.caseStudies.healthcare.results[0]',
'cases.caseStudies.healthcare.results[1]',
'cases.caseStudies.healthcare.results[2]',
'cases.caseStudies.healthcare.results[3]',
'cases.caseStudies.healthcare.results[4]'
]
},
{
titleKey: 'cases.caseStudies.manufacturing.title',
industry: 'cases.caseStudies.manufacturing.industry',
date: '2022-09-05',
summaryKey: 'cases.caseStudies.manufacturing.summary',
backgroundKey: 'cases.caseStudies.manufacturing.background',
challenges: [
'cases.caseStudies.manufacturing.challenges[0]',
'cases.caseStudies.manufacturing.challenges[1]',
'cases.caseStudies.manufacturing.challenges[2]',
'cases.caseStudies.manufacturing.challenges[3]'
],
solutionKey: 'cases.caseStudies.manufacturing.solution',
results: [
'cases.caseStudies.manufacturing.results[0]',
'cases.caseStudies.manufacturing.results[1]',
'cases.caseStudies.manufacturing.results[2]',
'cases.caseStudies.manufacturing.results[3]',
'cases.caseStudies.manufacturing.results[4]'
]
},
{
titleKey: 'cases.caseStudies.logistics.title',
industry: 'cases.caseStudies.logistics.industry',
date: '2022-07-15',
summaryKey: 'cases.caseStudies.logistics.summary',
backgroundKey: 'cases.caseStudies.logistics.background',
challenges: [
'cases.caseStudies.logistics.challenges[0]',
'cases.caseStudies.logistics.challenges[1]',
'cases.caseStudies.logistics.challenges[2]',
'cases.caseStudies.logistics.challenges[3]'
],
solutionKey: 'cases.caseStudies.logistics.solution',
results: [
'cases.caseStudies.logistics.results[0]',
'cases.caseStudies.logistics.results[1]',
'cases.caseStudies.logistics.results[2]',
'cases.caseStudies.logistics.results[3]',
'cases.caseStudies.logistics.results[4]'
]
},
{
titleKey: 'cases.caseStudies.education.title',
industry: 'cases.caseStudies.education.industry',
date: '2022-05-08',
summaryKey: 'cases.caseStudies.education.summary',
backgroundKey: 'cases.caseStudies.education.background',
challenges: [
'cases.caseStudies.education.challenges[0]',
'cases.caseStudies.education.challenges[1]',
'cases.caseStudies.education.challenges[2]',
'cases.caseStudies.education.challenges[3]'
],
solutionKey: 'cases.caseStudies.education.solution',
results: [
'cases.caseStudies.education.results[0]',
'cases.caseStudies.education.results[1]',
'cases.caseStudies.education.results[2]',
'cases.caseStudies.education.results[3]',
'cases.caseStudies.education.results[4]'
]
}
];
// 行业筛选方法
const toggleIndustryFilter = (industry: string) => {
if (selectedIndustries.value.includes(industry)) {
selectedIndustries.value = selectedIndustries.value.filter(item => item !== industry);
} else {
selectedIndustries.value.push(industry);
}
};
// 清除筛选条件
const clearIndustryFilters = () => {
selectedIndustries.value = [];
};
// 打开案例详情
const openCaseDetail = (case_item: any) => {
selectedCase.value = case_item;
};
// 根据筛选条件和排序获取案例列表
const filteredCases = computed(() => {
let result = [...caseStudies];
// 应用行业筛选
if (selectedIndustries.value.length > 0) {
result = result.filter(item => selectedIndustries.value.includes(item.industry));
}
// 应用排序
if (sortBy.value === 'latest') {
result.sort((a, b) => new Date(b.date).getTime() - new Date(a.date).getTime());
}
return result;
});
</script>