Files
inkreach-official-website/apps/website/app/components/CustomerCases.vue
T
yeuimu 6c61a4e871 feat(deploy): production deployment setup and fixes
- Debian-based api image (bookworm-slim), docker/debian mirrors, prisma
  binaryTargets for openssl 3.0
- nginx: admin SPA under /admin, TLS via acme.sh (ZeroSSL) + auto-renewal
  cron, http->https redirect
- prisma: add origin_goods.delisted migration, sync missing schema
  (good_image/tag_font_color/good_tags), fix users.createdAt Timestamptz
- api: CORS wildcard reflection, helmet CORP cross-origin, price
  backfill in persistProductDetail, categoryIcon ancestor fallback,
  mediaByColor per-color gallery in public goods detail
- admin: /admin base path (vite + router)
- import-data.mjs: udt_name casting, serial sequence advance fix
2026-08-26 14:23:09 +08:00

126 lines
6.2 KiB
Vue

<script setup>
const customerCases = ref([
{ id: 1, platform: 'TEMU卖家', isPrimary: true, title: '复古水洗 经典重塑', description: '巡演灵感做旧款,粉丝自发应援首选', salesGrowth: '260%', monthlySales: '45W美元', image: '/case-temu-washed.png' },
{ id: 2, platform: 'TikTok卖家', isPrimary: false, title: '冠军荣耀 同款套装', description: '夺冠纪念球衣,球迷珍藏爆款', salesGrowth: '300%', monthlySales: '68W美元', image: '/case-tiktok-kit.png' },
{ id: 3, platform: 'SHEIN卖家', isPrimary: false, title: '潮流印花 全棉舒适', description: '自制设计印花图案,无尾货压力轻松售', salesGrowth: '180%', monthlySales: '22W美元', image: '/case-shein-print.png' },
{ id: 4, platform: 'TEMU卖家', isPrimary: true, title: '天然彩棉 亲肤百搭', description: '达人联名系列,持续热卖无库存压力', salesGrowth: '210%', monthlySales: '38W美元', image: '/case-temu-cotton.png' },
{ id: 5, platform: 'TikTok卖家', isPrimary: false, title: '日系简约 清凉无袖', description: '音乐节应援款,透气轻便人气高', salesGrowth: '240%', monthlySales: '32W美元', image: '/case-tiktok-sleeveless.png' },
]);
</script>
<template>
<section class="cases-section py-10 lg:py-16 bg-gray-50 overflow-hidden">
<div class="max-w-7xl mx-auto px-4 lg:px-6">
<h2 class="text-[clamp(1.5rem,3vw,2.5rem)] font-bold text-gray-900 text-center mb-8 lg:mb-12">用户案例</h2>
</div>
<div class="hidden lg:block overflow-hidden" aria-label="用户案例自动轮播">
<div class="case-track flex gap-8 w-max">
<div
v-for="(testCase, idx) in [...customerCases, ...customerCases]"
:key="'a-' + idx"
class="case-card relative flex-shrink-0 w-[350px] h-[420px] bg-white rounded-xl overflow-hidden"
>
<div class="case-media relative h-48">
<span
:class="['absolute top-4 left-4', testCase.isPrimary ? 'bg-primary' : 'bg-black', 'text-white px-3 py-1 rounded-full text-sm font-medium']"
>
{{ testCase.platform }}
</span>
<img :src="testCase.image" :alt="testCase.title" class="w-full h-full object-cover" />
</div>
<div class="case-details p-6">
<div class="case-metrics flex justify-between items-center mb-4">
<div class="growth-metric">
<p class="text-gray-500 text-sm">销量增长</p>
<p class="text-2xl lg:text-3xl font-bold text-primary">{{ testCase.salesGrowth }}</p>
</div>
<div class="sales-metric text-right">
<p class="text-gray-500 text-sm">月销售额</p>
<p class="text-2xl lg:text-3xl font-bold text-primary">{{ testCase.monthlySales }}</p>
</div>
</div>
<div class="case-copy">
<h3 class="text-lg lg:text-xl font-bold text-gray-900 mb-2">{{ testCase.title }}</h3>
<p class="text-gray-600 text-sm">{{ testCase.description }}</p>
</div>
</div>
</div>
</div>
</div>
<div class="lg:hidden overflow-hidden pb-4 px-4" aria-label="用户案例自动轮播">
<div class="case-track-mobile flex gap-4 w-max">
<div
v-for="(testCase, idx) in [...customerCases, ...customerCases]"
:key="'m-' + idx"
class="flex-shrink-0 w-[280px] bg-white rounded-xl overflow-hidden"
>
<div class="relative h-36">
<span
:class="['absolute top-3 left-3', testCase.isPrimary ? 'bg-primary' : 'bg-black', 'text-white px-2 py-1 rounded-full text-xs font-medium']"
>
{{ testCase.platform }}
</span>
<img :src="testCase.image" :alt="testCase.title" class="w-full h-full object-cover" />
</div>
<div class="p-4">
<div class="flex justify-between items-center mb-3">
<div>
<p class="text-gray-500 text-xs">销量增长</p>
<p class="text-xl font-bold text-primary">{{ testCase.salesGrowth }}</p>
</div>
<div class="text-right">
<p class="text-gray-500 text-xs">月销售额</p>
<p class="text-xl font-bold text-primary">{{ testCase.monthlySales }}</p>
</div>
</div>
<h3 class="text-base font-bold text-gray-900 mb-1">{{ testCase.title }}</h3>
<p class="text-gray-600 text-xs">{{ testCase.description }}</p>
</div>
</div>
</div>
</div>
</section>
</template>
<style scoped>
.case-track { animation: case-marquee 30s linear infinite; }
.case-track-mobile { animation: case-marquee-mobile 30s linear infinite; }
.case-track:hover,
.case-track:focus-within,
.case-track-mobile:hover,
.case-track-mobile:focus-within { animation-play-state: paused; }
@keyframes case-marquee {
to { transform: translateX(calc(-50% - 16px)); }
}
@keyframes case-marquee-mobile {
to { transform: translateX(calc(-50% - 8px)); }
}
@media (prefers-reduced-motion: reduce) {
.case-track,
.case-track-mobile { animation: none; }
}
@media (min-width: 1024px) {
.cases-section { height: 928px; padding-top: 54px; }
.case-track { padding-left: 122px; }
.case-card { width: 464px; height: 500px; }
.case-media { height: 360px; background: #f8f9fb; }
.case-media img { object-fit: contain; }
.case-details { position: absolute; inset: 0; padding: 0; pointer-events: none; }
.case-metrics { display: block; margin: 0; }
.case-metrics > div { position: absolute; right: 16px; width: 240px; text-align: right; }
.growth-metric { top: 148px; }
.sales-metric { top: 253px; }
.case-metrics p:first-child { margin-bottom: 2px; font-size: 16px; }
.case-metrics p:last-child { font-size: 48px; line-height: 1.1; white-space: nowrap; }
.case-copy { position: absolute; top: 392px; left: 0; width: 100%; padding: 0 24px; text-align: center; }
.case-copy h3 { margin-bottom: 12px; font-size: 24px; }
.case-copy p { font-size: 16px; white-space: nowrap; }
}
</style>