122 lines
3.9 KiB
TypeScript
122 lines
3.9 KiB
TypeScript
|
|
'use client';
|
|||
|
|
|
|||
|
|
import { useEffect, useState, useCallback } from 'react';
|
|||
|
|
import Link from 'next/link';
|
|||
|
|
import type { Banner } from '@/lib/types';
|
|||
|
|
import { resolveUploadUrl, cn } from '@/lib/utils';
|
|||
|
|
|
|||
|
|
const INTERVAL = 5000;
|
|||
|
|
|
|||
|
|
export function BannerCarousel({ banners }: { banners: Banner[] }) {
|
|||
|
|
const [idx, setIdx] = useState(0);
|
|||
|
|
const total = banners.length;
|
|||
|
|
|
|||
|
|
const next = useCallback(() => {
|
|||
|
|
setIdx((p) => (total === 0 ? 0 : (p + 1) % total));
|
|||
|
|
}, [total]);
|
|||
|
|
|
|||
|
|
useEffect(() => {
|
|||
|
|
if (total <= 1) return;
|
|||
|
|
const t = setInterval(next, INTERVAL);
|
|||
|
|
return () => clearInterval(t);
|
|||
|
|
}, [next, total]);
|
|||
|
|
|
|||
|
|
if (total === 0) {
|
|||
|
|
return <HeroPlaceholder />;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return (
|
|||
|
|
<div className="relative h-[420px] overflow-hidden bg-gray-100">
|
|||
|
|
{banners.map((b, i) => (
|
|||
|
|
<div
|
|||
|
|
key={b.id}
|
|||
|
|
className={cn(
|
|||
|
|
'absolute inset-0 transition-opacity duration-700',
|
|||
|
|
i === idx ? 'opacity-100' : 'opacity-0',
|
|||
|
|
)}
|
|||
|
|
>
|
|||
|
|
{b.link ? (
|
|||
|
|
<Link href={b.link} target="_blank" rel="noreferrer" className="block h-full w-full">
|
|||
|
|
<BG image={b.image} title={b.title} />
|
|||
|
|
</Link>
|
|||
|
|
) : (
|
|||
|
|
<BG image={b.image} title={b.title} />
|
|||
|
|
)}
|
|||
|
|
</div>
|
|||
|
|
))}
|
|||
|
|
{total > 1 && (
|
|||
|
|
<div className="absolute bottom-4 left-1/2 flex -translate-x-1/2 gap-2">
|
|||
|
|
{banners.map((_, i) => (
|
|||
|
|
<button
|
|||
|
|
key={i}
|
|||
|
|
aria-label={`第 ${i + 1} 张`}
|
|||
|
|
onClick={() => setIdx(i)}
|
|||
|
|
className={cn(
|
|||
|
|
'h-2 rounded-full transition-all',
|
|||
|
|
i === idx ? 'w-6 bg-white' : 'w-2 bg-white/50',
|
|||
|
|
)}
|
|||
|
|
/>
|
|||
|
|
))}
|
|||
|
|
</div>
|
|||
|
|
)}
|
|||
|
|
</div>
|
|||
|
|
);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
function BG({ image, title }: { image: string; title: string }) {
|
|||
|
|
return (
|
|||
|
|
<div
|
|||
|
|
className="relative h-full w-full bg-cover bg-center"
|
|||
|
|
style={{ backgroundImage: `url(${resolveUploadUrl(image)})` }}
|
|||
|
|
>
|
|||
|
|
<div className="absolute inset-0 bg-black/40" />
|
|||
|
|
<div className="container-page flex h-full items-center">
|
|||
|
|
<h2 className="max-w-xl text-2xl font-bold leading-snug text-white sm:text-3xl md:text-4xl">
|
|||
|
|
{title}
|
|||
|
|
</h2>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
function HeroPlaceholder() {
|
|||
|
|
return (
|
|||
|
|
<div className="relative flex h-[480px] items-center overflow-hidden bg-gradient-to-br from-brand-700 via-brand-600 to-brand-800">
|
|||
|
|
<div
|
|||
|
|
className="absolute inset-0 opacity-30"
|
|||
|
|
style={{
|
|||
|
|
backgroundImage:
|
|||
|
|
'radial-gradient(circle at 20% 50%, rgba(255,255,255,0.15) 0%, transparent 50%), radial-gradient(circle at 80% 20%, rgba(255,255,255,0.1) 0%, transparent 40%)',
|
|||
|
|
}}
|
|||
|
|
/>
|
|||
|
|
<div className="container-page relative">
|
|||
|
|
<span className="inline-block rounded-full bg-white/15 px-4 py-1.5 text-sm text-white backdrop-blur">
|
|||
|
|
物业管理系统 · 小程序 · SaaS
|
|||
|
|
</span>
|
|||
|
|
<h1 className="mt-6 max-w-2xl text-4xl font-bold leading-tight text-white sm:text-5xl md:text-6xl">
|
|||
|
|
让物业管理
|
|||
|
|
<br />
|
|||
|
|
像发微信一样简单
|
|||
|
|
</h1>
|
|||
|
|
<p className="mt-4 max-w-xl text-lg text-brand-100">
|
|||
|
|
懂物业,更懂“省”心。一站式物业管理平台,覆盖缴费、报修、公告、巡检全流程。
|
|||
|
|
</p>
|
|||
|
|
<div className="mt-8 flex flex-col gap-4 sm:flex-row">
|
|||
|
|
<Link
|
|||
|
|
href="/contact"
|
|||
|
|
className="rounded-lg bg-white px-7 py-3 text-sm font-semibold text-brand-700 shadow-lg transition-colors hover:bg-brand-50"
|
|||
|
|
>
|
|||
|
|
预约演示
|
|||
|
|
</Link>
|
|||
|
|
<Link
|
|||
|
|
href="/products"
|
|||
|
|
className="rounded-lg border border-white/40 px-7 py-3 text-sm font-medium text-white transition-colors hover:bg-white/10"
|
|||
|
|
>
|
|||
|
|
了解产品
|
|||
|
|
</Link>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
);
|
|||
|
|
}
|