yintai-company-home/src/components/layout/TopTabsSection/index.tsx

136 lines
7.0 KiB
TypeScript

import { useEffect, useState } from 'react';
import styles from './index.module.css';
import TopTabs from './TopTabs';
import { useLocation } from 'react-router-dom';
import ScrollReveal from '@/components/ScrollReveal';
import { Swiper, SwiperSlide } from 'swiper/react';
import { Autoplay, Pagination } from 'swiper/modules';
import 'swiper/css';
import 'swiper/css/pagination';
type Data = {
tabItems: {
icon?: string;
tabName?: string;
contentTitle?: string;
contentSubtitle?: string;
contentText?: string;
content?: string;
/** 以 mockData 为准;传 string[] 时为右侧轮播 */
sideImage?: string | string[];
path?: string;
items?: { label: string }[];
}[]
backgroundImage?: string;
titleDirection?: 'row' | 'column';
}
function sideImageToSlides(sideImage: string | string[] | undefined): string[] {
if (Array.isArray(sideImage)) return sideImage.filter(Boolean);
if (sideImage) return [sideImage];
return [];
}
export default function TopTabsSection({ data, className }: { data: Data, className?: string }) {
const location = useLocation();
const hash = location.hash;
const hashId = decodeURIComponent(hash.replace('#', ''));
const [activeIndex, setActiveIndex] = useState(0);
useEffect(() => {
if (hashId && data.tabItems) {
const index = data.tabItems.findIndex((item) => item.tabName === hashId);
if (index !== -1) {
setActiveIndex(index);
}
}
}, [hashId, data.tabItems])
const sideSlides = sideImageToSlides(data.tabItems[activeIndex]?.sideImage);
return (
<section className={`${styles.topTabsSection} ${className}`} style={{ backgroundImage: `url(${data.backgroundImage})` }}>
<div aria-hidden="true">
{data.tabItems.map((item) => (
<div key={item.tabName} id={item.tabName} style={{ height: 0, overflow: "hidden" }} />
))}
</div>
<TopTabs data={data} activeIndex={activeIndex} setActiveIndex={setActiveIndex} />
<div className={styles.topTabsContent}>
{
data.tabItems[activeIndex]?.items && (data.tabItems[activeIndex]?.items as any).length > 0 ?
<ul className={styles.topTabsContentItems}>
{
(data.tabItems[activeIndex]?.items as any).map((item: { label: string }) => (
<li key={item.label} className={styles.topTabsContentItem}>
<span>{item.label}</span>
</li>
))
}
</ul> : (
<>
<div className={styles.topTabsContentLeft}>
<div className={styles.topTabsContentLeftHead}>
{
<ScrollReveal preset="slideRight" delay={0.3} >
{
data.tabItems[activeIndex].icon && (
<img src={data.tabItems[activeIndex].icon} alt="" style={{ width: '6.25rem', height: '6.25rem', marginRight: '1.25rem' }} />
)
}
</ScrollReveal>
}
<div className={`${styles.topTabsContentLeftTitle} ${data.titleDirection === 'column' ? styles.columnCenter : ''}`}>
<ScrollReveal preset="slideUp" delay={0.5} duration={1.1}>
<div className={styles.topTabsContentLeftTitleMain}>{data.tabItems[activeIndex].contentTitle}</div>
</ScrollReveal>
<ScrollReveal preset="slideUp" delay={0.7} duration={1.1}>
<div className={styles.topTabsContentLeftTitleSub}>{data.tabItems[activeIndex].contentSubtitle}</div>
</ScrollReveal>
</div>
</div>
<ScrollReveal preset="slideUp" delay={0.9} duration={1.1}>
<p className={`${styles.topTabsContentLeftDesc} normal-p`}
dangerouslySetInnerHTML={{ __html: data.tabItems[activeIndex].contentText ?? data.tabItems[activeIndex].content as any }}
>
{/* {data.tabItems[activeIndex].contentText ?? data.tabItems[activeIndex].content} */}
</p>
</ScrollReveal>
</div>
<div className={styles.topTabsContentRight}>
<ScrollReveal preset="slideLeft" delay={0.5} >
{sideSlides.length > 1 ? (
<Swiper
className={styles.sideImageSwiper}
modules={[Autoplay, Pagination]}
slidesPerView={1}
spaceBetween={0}
loop
allowTouchMove
autoplay={{
delay: 4500,
disableOnInteraction: false,
}}
pagination={{ clickable: true }}
>
{sideSlides.map((src, i) => (
<SwiperSlide key={`${src}-${i}`}>
<img src={src} alt="" />
</SwiperSlide>
))}
</Swiper>
) : (
<img src={sideSlides[0] || sideSlides as any} alt="" />
)}
</ScrollReveal>
</div>
</>
)
}
</div>
</section>
)
}