- 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
126 lines
6.2 KiB
Vue
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>
|