yintai-company-home/src/pages/Business/CommercialGroup.tsx

159 lines
6.5 KiB
TypeScript

import { useLayoutEffect, useRef, useState } from "react";
import { Link } from "react-router-dom";
import { useStore } from "@/store";
import styles from "./CommercialGroup.module.css";
import Banner from "@/components/Banner";
import ParagraphSection from "@/components/layout/ParagraphSection";
import Section from "@/components/layout/Section";
import TopTabs from "@/components/layout/TopTabsSection/TopTabs";
import SectionTitle from "@/components/layout/SectionTitle";
import ScrollReveal from "@/components/ScrollReveal";
import BottomTabsSection from "@/components/layout/BottomTabsSection";
const FALLBACK_GRADIENT = "linear-gradient(135deg, #1a2a4a 0%, #2d4a7c 100%)";
function PlaceholderImage() {
return <div className={styles.placeholder}></div>;
}
export default function BusinessCommercialGroup() {
const appConfig = useStore((s) => s.appConfig);
const { viewDetail = "查看详情" } = appConfig?.__global__?.others
const data = appConfig?.business?.commercialGroup;
const section3Data = data?.section3Data;
const section4Data = data?.section4Data;
const [activeTabIndex, setActiveTabIndex] = useState(0);
const [activeFeaturesTabIndex, setActiveFeaturesTabIndex] = useState(0);
const featuresHeroTabsRef = useRef<HTMLDivElement>(null);
const featuresTabItemRefs = useRef<(HTMLDivElement | null)[]>([]);
const [featuresTabIndicator, setFeaturesTabIndicator] = useState({ x: 0, width: 0 });
const featuresFirstBg = section3Data?.tabItems?.[0]?.backgroundImage ?? "";
const [featuresBg, setFeaturesBg] = useState({
a: featuresFirstBg,
b: featuresFirstBg,
showA: true,
});
useLayoutEffect(() => {
if (!section3Data?.tabItems?.length) return;
const next = section3Data.tabItems[activeFeaturesTabIndex]?.backgroundImage ?? "";
setFeaturesBg((prev) => {
const visible = prev.showA ? prev.a : prev.b;
if (next === visible) return prev;
// 数据首帧就绪:直接铺满两层,避免从空图做一次淡入
if (!visible && next) {
return { a: next, b: next, showA: true };
}
if (prev.showA) {
return { ...prev, b: next, showA: false };
}
return { ...prev, a: next, showA: true };
});
}, [activeFeaturesTabIndex, section3Data]);
useLayoutEffect(() => {
if (!section3Data?.tabItems?.length) return;
const root = featuresHeroTabsRef.current;
if (!root) return;
const updateIndicator = () => {
const tab = featuresTabItemRefs.current[activeFeaturesTabIndex];
if (!tab) return;
const rootRect = root.getBoundingClientRect();
const tabRect = tab.getBoundingClientRect();
setFeaturesTabIndicator({
x: tabRect.left - rootRect.left,
width: tabRect.width,
});
};
updateIndicator();
const ro = new ResizeObserver(updateIndicator);
ro.observe(root);
window.addEventListener("resize", updateIndicator);
return () => {
ro.disconnect();
window.removeEventListener("resize", updateIndicator);
};
}, [activeFeaturesTabIndex, section3Data?.tabItems]);
if (!data) return null;
const banner = data.banner;
const section1Data = data.section1Data;
const section2Data = data.section2Data;
return (
<div>
<Banner
title={banner?.title ?? ""}
largedesc={banner?.content}
titleSize={banner?.titleSize as "medium" | "large" | undefined ?? "medium"}
backgroundImage={banner?.backgroundImage ?? "/images/bg-commercial-group.png"}
/>
{section1Data && <ParagraphSection data={section1Data} />}
<Section
background={section2Data.backgroundImage}
className={styles.twoColSection}
>
<TopTabs className={styles.twoColSectionTabs} data={section2Data} activeIndex={activeTabIndex} setActiveIndex={setActiveTabIndex} />
<div className={styles.twoColSectionContent}>
<ScrollReveal
preset="slideRight"
duration={1}
className={styles.twoColImageWrap}
>
<div className={styles.twoColImage} style={{
backgroundImage: `url(${section2Data.tabItems[activeTabIndex]?.sideImage as string})`,
}}>
</div>
</ScrollReveal>
<div className={styles.twoColText}>
<div className={styles.twoColTextContent}>
<ScrollReveal preset="slideUp" delay={0.5} >
<p className={styles.twoColDesc} dangerouslySetInnerHTML={{ __html: section2Data.tabItems[activeTabIndex]?.content ?? "" }}></p>
</ScrollReveal>
<Link
to={section2Data.tabItems[activeTabIndex]?.path ?? "#"}
className={styles.btnPrimary}
>
{viewDetail}
</Link>
</div>
</div>
</div>
</Section>
{section3Data && <BottomTabsSection data={section3Data} />}
{
section4Data.hide ? null : (
<section
className={`${styles.twoColSection} ${styles.propertyServices}`}
style={{
backgroundImage: `url(${section4Data?.backgroundImage}), ${FALLBACK_GRADIENT}`,
}}
>
<div className={styles.propertyServicesContent}>
<div className={styles.propertyServicesTitle}>{section4Data?.title}</div>
<p className={styles.propertyServicesSubtitle}>{section4Data?.content}</p>
<ScrollReveal preset="slideUp" className={styles.propertyServicesBtn}>
<Link to={section4Data?.path ?? "#"} >
{viewDetail}
</Link>
</ScrollReveal>
</div>
</section>
)
}
</div>
);
}