init
This commit is contained in:
@@ -0,0 +1,150 @@
|
||||
<script setup>
|
||||
import { computed, ref, watch } from "vue";
|
||||
import { caseCategories, cases as defaultCases } from "~/data/cases";
|
||||
|
||||
const props = defineProps({
|
||||
cases: {
|
||||
type: Array,
|
||||
default: () => defaultCases,
|
||||
},
|
||||
title: {
|
||||
type: String,
|
||||
default: "",
|
||||
},
|
||||
previewLimit: {
|
||||
type: Number,
|
||||
default: 3,
|
||||
},
|
||||
preview: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
routes: {
|
||||
type: Array,
|
||||
default: () => [],
|
||||
},
|
||||
sectionId: {
|
||||
type: String,
|
||||
default: "cases",
|
||||
},
|
||||
});
|
||||
|
||||
const route = useRoute();
|
||||
const activeCategory = ref("全部");
|
||||
|
||||
const visibleCategories = computed(() =>
|
||||
props.preview ? ["全部"] : caseCategories,
|
||||
);
|
||||
|
||||
const filteredCases = computed(() => {
|
||||
const items =
|
||||
activeCategory.value === "全部"
|
||||
? props.cases
|
||||
: props.cases.filter((item) => item.category === activeCategory.value);
|
||||
|
||||
return props.preview
|
||||
? items.filter((item) => item.featured).slice(0, props.previewLimit)
|
||||
: items;
|
||||
});
|
||||
|
||||
watch(
|
||||
() => route.query.category,
|
||||
(category) => {
|
||||
activeCategory.value =
|
||||
typeof category === "string" && caseCategories.includes(category)
|
||||
? category
|
||||
: "全部";
|
||||
},
|
||||
{ immediate: true },
|
||||
);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<section :id="sectionId" class="bg-[#f7f8f7] py-20">
|
||||
<div class="container-gm">
|
||||
<div class="flex flex-col gap-6 md:flex-row md:items-end md:justify-between" data-reveal>
|
||||
<div class="max-w-3xl">
|
||||
<p class="text-sm uppercase tracking-[0.3em] text-[#9a9a9a]">Cases</p>
|
||||
<h2 class="section-title mt-4">
|
||||
{{ title || (preview ? "真实落地成果,见证增长实效" : "案例库") }}
|
||||
</h2>
|
||||
</div>
|
||||
<div class="flex flex-col items-start gap-3 md:items-end">
|
||||
<SectionRouteLinks :routes="routes" />
|
||||
<NuxtLink
|
||||
v-if="preview"
|
||||
to="/cases"
|
||||
class="inline-flex items-center gap-2 text-sm font-medium text-gm-green"
|
||||
>
|
||||
查看全部案例 <span aria-hidden="true">→</span>
|
||||
</NuxtLink>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-if="!preview" class="mt-8 flex flex-wrap gap-3" data-reveal>
|
||||
<button
|
||||
v-for="category in visibleCategories"
|
||||
:key="category"
|
||||
type="button"
|
||||
class="rounded-full border px-6 py-2 text-sm transition-all duration-300"
|
||||
:class="
|
||||
activeCategory === category
|
||||
? 'border-gm-green bg-gm-green text-white'
|
||||
: 'border-gm-border bg-white text-[#666] hover:border-[#d5d5d5]'
|
||||
"
|
||||
@click="activeCategory = category"
|
||||
>
|
||||
{{ category }}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="mt-10 grid gap-6 md:grid-cols-2 xl:grid-cols-3" data-stagger>
|
||||
<NuxtLink
|
||||
v-for="item in filteredCases"
|
||||
:key="item.title"
|
||||
:to="`/cases/${item.slug}`"
|
||||
class="overflow-hidden rounded-lg border border-gm-border bg-white shadow-sm transition hover:shadow-hover"
|
||||
data-stagger-item
|
||||
data-hover-card
|
||||
>
|
||||
<div class="h-56 overflow-hidden bg-gm-light">
|
||||
<img
|
||||
:src="item.image"
|
||||
:alt="item.title"
|
||||
class="h-full w-full object-cover transition duration-500 hover:scale-105"
|
||||
loading="lazy"
|
||||
/>
|
||||
</div>
|
||||
<div class="p-6">
|
||||
<p class="text-xs font-medium text-gm-green">{{ item.category }}</p>
|
||||
<h3 class="mt-3 text-xl font-semibold leading-7 text-[#262626]">
|
||||
{{ item.title }}
|
||||
</h3>
|
||||
<p class="mt-3 text-sm leading-7 text-[#777]">{{ item.summary }}</p>
|
||||
<div class="mt-5 flex flex-wrap gap-2">
|
||||
<span
|
||||
v-for="tag in item.tags"
|
||||
:key="tag"
|
||||
class="rounded-full bg-gm-light px-3 py-1 text-xs text-[#666]"
|
||||
>
|
||||
{{ tag }}
|
||||
</span>
|
||||
</div>
|
||||
<div class="mt-6 grid gap-2">
|
||||
<p
|
||||
v-for="metric in item.metrics"
|
||||
:key="metric"
|
||||
class="text-sm font-medium text-[#262626]"
|
||||
>
|
||||
{{ metric }}
|
||||
</p>
|
||||
</div>
|
||||
<p class="mt-5 font-mono text-[11px] text-[#999]">
|
||||
案例路径 {{ item.path }}
|
||||
</p>
|
||||
</div>
|
||||
</NuxtLink>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</template>
|
||||
Reference in New Issue
Block a user