2025-06-17 15:23:37 +08:00

148 lines
7.3 KiB
JavaScript

"use client";
import { useEffect, useState } from "react";
import ModalVideo from "@/components/common/ModalVideo";
import Link from "next/link";
import axios from "axios";
import { Autoplay, Navigation, Pagination } from "swiper/modules";
import { Swiper, SwiperSlide } from "swiper/react";
export default function Hero({ showNavButtons = false }) {
const [isOpen, setIsOpen] = useState("");
const [heroData, setHeroData] = useState(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
async function fetchHeroData() {
try {
setLoading(true);
const res = await axios.get("/api/get-component-data", {
params: { component_name: "Hero" }
});
setHeroData(res.data.data);
} catch (err) {
setError("获取Hero数据失败");
} finally {
setLoading(false);
}
}
fetchHeroData();
}, []);
if (loading) return <div className="text-white text-center py-20">Loading...</div>;
if (error) return <div className="text-red-500 text-center py-20">{error}</div>;
if (!heroData) return null;
// 处理items
const items = heroData.items || [];
// 处理图片
const bgImages = [heroData.image, heroData.image_1, heroData.image_2].filter(Boolean);
// 处理标题和副标题
const titles = [heroData.title, ...(items.map(i => i.item_title))].filter(Boolean);
const subtitles = [heroData.subtitle, ...(items.map(i => i.item_subtitle))].filter(Boolean);
const descs = [heroData.description, ...(items.map(i => i.item_description))].filter(Boolean);
return (
<>
<div className="swiper-container swiper-hero dots-over relative z-10">
<Swiper
className="swiper h-full"
modules={[Navigation, Pagination, Autoplay]}
pagination={{
clickable: true,
el: ".spd7",
}}
spaceBetween={0}
speed={3000}
navigation={showNavButtons ? {
prevEl: ".snbp7",
nextEl: ".snbn7",
} : false}
>
{items.map((item, idx) => {
let alignClass = "";
switch ((item.content_align || "").toLowerCase()) {
case "center":
alignClass = "md:w-11/12 lg:w-8/12 xl:w-7/12 xxl:w-6/12 w-full !mx-auto text-center";
break;
case "right":
alignClass = "md:w-10/12 lg:w-7/12 xl:w-6/12 w-full max-w-full text-center lg:text-right xl:text-right lg:!ml-[41.666667%] xl:!ml-[50%] xxl:!ml-[50%]";
break;
case "left":
default:
alignClass = "md:w-10/12 md:!ml-[8.33333333%] lg:w-7/12 lg:!ml-0 xl:w-6/12 xxl:w-5/12 w-full max-w-full text-center lg:text-left xl:text-left";
break;
}
return (
<SwiperSlide
key={idx}
className="swiper-slide max-h-full bg-overlay bg-overlay-400 bg-[#21262c] opacity-100 bg-image !bg-cover !bg-[center_center] !h-[750px] before:content-[''] before:block before:absolute before:z-[1] before:w-full before:h-full before:left-0 before:top-0 before:bg-[rgba(30,34,40,.4)]"
style={{ backgroundImage: `url(${item.item_image || bgImages[idx] || bgImages[0] || "/assets/img/photos/bg7.jpg"})` }}
>
<div className="container !h-full">
<div className="flex flex-wrap !h-full items-center">
<div className={alignClass + " relative z-10"}>
<h2 className="xl:!text-[2.8rem] !leading-[1.2] font-bold !text-[calc(1.405rem_+_1.86vw)] !mb-4 !text-white animate__animated animate__slideInDown animate__delay-1s">
{item.item_title || heroData.title}
</h2>
<p className="lead text-[1.15rem] leading-normal !mb-7 !text-white animate__animated animate__slideInRight animate__delay-2s">
{item.item_subtitle || heroData.subtitle}
</p>
<div className="animate__animated animate__slideInUp animate__delay-3s">
{item.item_video_src ? (
<a
onClick={() => setIsOpen(item.item_video_src)}
className="btn btn-circle btn-white btn-play ripple !mx-auto !mb-5 !relative z-[2] xl:!text-[2.3rem] !w-[3.5rem] !h-[3.5rem] !text-[calc(1.355rem_+_1.26vw)] hover:translate-y-0 inline-flex items-center justify-center leading-none p-0 !rounded-[100%] before:content-[''] before:block before:absolute before:opacity-80 before:animate-[ripple-1_2s_infinite_ease-in-out] before:z-[-1] before:rounded-[50%] before:inset-0 before:bg-[#ffffff] after:content-[''] after:block after:absolute after:opacity-60 after:animate-[ripple-2_2s_infinite_ease-in-out] after:z-[-1] after:rounded-[50%] after:inset-0 after:bg-[#ffffff]"
style={{ cursor: "pointer" }}
>
<i className="icn-caret-right !ml-[0.15rem] !relative z-[2] before:content-['\\e900'] !text-[calc(1.355rem_+_1.26vw)]" />
</a>
) : (
item.item_button_text && item.item_button_link && (
item.item_button_link.startsWith("http") ? (
<a
href={item.item_button_link}
className="btn btn-outline-white !text-white bg-[#ffffff] !border-white !border-[2px] hover:!text-[#343f52] hover:bg-[#ffffff] hover:border-white focus:shadow-[rgba(255,255,255,1)] active:!text-[#343f52] active:bg-[#ffffff] active:border-white disabled:text-white disabled:bg-transparent disabled:border-white !rounded-[50rem]"
target="_blank"
rel="noopener noreferrer"
>
{item.item_button_text}
</a>
) : (
<Link
href={item.item_button_link}
className="btn btn-outline-white !text-white bg-[#ffffff] !border-white !border-[2px] hover:!text-[#343f52] hover:bg-[#ffffff] hover:border-white focus:shadow-[rgba(255,255,255,1)] active:!text-[#343f52] active:bg-[#ffffff] active:border-white disabled:text-white disabled:bg-transparent disabled:border-white !rounded-[50rem]"
>
{item.item_button_text}
</Link>
)
)
)}
</div>
</div>
</div>
</div>
</SwiperSlide>
);
})}
</Swiper>
<div className="swiper-controls">
{showNavButtons && (
<div className="swiper-navigation">
<div className="swiper-button swiper-button-prev snbp7"></div>
<div className="swiper-button swiper-button-next snbn7"></div>
</div>
)}
<div className="swiper-pagination spd7"></div>
</div>
</div>
<ModalVideo
isOpen={!!isOpen}
setIsOpen={() => setIsOpen("")}
src={isOpen}
/>
</>
);
}