This commit is contained in:
zhangjianjun 2026-03-27 18:48:09 +08:00
parent ee3715b0d3
commit ce9ec9b381
31 changed files with 336 additions and 141 deletions

View File

@ -142,3 +142,8 @@ body {
.logo-dark { .logo-dark {
filter: brightness(0) saturate(100%) invert(16%) sepia(25%) saturate(4500%) hue-rotate(223deg) brightness(80%) contrast(85%); filter: brightness(0) saturate(100%) invert(16%) sepia(25%) saturate(4500%) hue-rotate(223deg) brightness(80%) contrast(85%);
} }
.w-72-inner {
margin: 0 auto;
width: 72%;
}

View File

@ -10,6 +10,14 @@
justify-content: flex-end; justify-content: flex-end;
} }
.heroIcon {
width: 10rem;
height: 10rem;
object-fit: cover;
margin-left: -1.875rem;
margin-bottom: -2.5rem;
}
.bgSwiper { .bgSwiper {
position: absolute; position: absolute;
inset: 0; inset: 0;

View File

@ -40,7 +40,7 @@ function BannerSlideVideo({
if (!v) return; if (!v) return;
if (active) { if (active) {
v.currentTime = 0; v.currentTime = 0;
void v.play().catch(() => {}); void v.play().catch(() => { });
} else { } else {
v.pause(); v.pause();
} }
@ -60,6 +60,7 @@ type Props = {
largedesc?: string; largedesc?: string;
titleSize?: "large" | "medium" | string; titleSize?: "large" | "medium" | string;
backgroundImage: string | string[]; backgroundImage: string | string[];
icon?: string;
}; };
export default function Banner({ export default function Banner({
@ -70,6 +71,7 @@ export default function Banner({
largedesc, largedesc,
titleSize = "large", titleSize = "large",
backgroundImage, backgroundImage,
icon
}: Props) { }: Props) {
const appConfig = useStore((s) => s.appConfig); const appConfig = useStore((s) => s.appConfig);
const navItems = appConfig?.navItems ?? []; const navItems = appConfig?.navItems ?? [];
@ -115,7 +117,10 @@ export default function Banner({
const heroContent = ( const heroContent = (
<div className={styles.heroContent} style={{ gap: "1.875rem" }}> <div className={styles.heroContent} style={{ gap: "1.875rem" }}>
<ScrollReveal preset="slideUp"> <ScrollReveal preset="slideUp">
<h1 className={`${styles.heroTitle} ${titleSize === "medium" ? styles.heroTitleMedium : ""}`}>{title}</h1> {icon ? <img src={icon} alt="" className={styles.heroIcon} />
:
<h1 className={`${styles.heroTitle} ${titleSize === "medium" ? styles.heroTitleMedium : ""}`}>{title}</h1>
}
</ScrollReveal> </ScrollReveal>
{subtitle && <ScrollReveal preset="slideUp" delay={0.2}> {subtitle && <ScrollReveal preset="slideUp" delay={0.2}>
<h2 className={styles.heroSubtitle}>{subtitle}</h2> <h2 className={styles.heroSubtitle}>{subtitle}</h2>
@ -128,7 +133,7 @@ export default function Banner({
</ScrollReveal>} </ScrollReveal>}
<ScrollReveal preset="fadeIn" delay={0.2}> <ScrollReveal preset="fadeIn" delay={0.2}>
<div className={styles.breadcrumb}> <div className={styles.breadcrumb}>
{ !notShowBreadcrumbPaths.includes(location.pathname) && {!notShowBreadcrumbPaths.includes(location.pathname) &&
(breadcrumbItems ?? []).map((item, i) => ( (breadcrumbItems ?? []).map((item, i) => (
<span key={i}> <span key={i}>
{i > 0 && <span>{" > "}</span>} {i > 0 && <span>{" > "}</span>}

View File

@ -1,8 +1,14 @@
.scrollContainer { .scrollContainer {
width: 100%; width: 100%;
overflow-x: auto; overflow-x: auto;
overflow-y: auto; overflow-y: hidden;
cursor: all-scroll; cursor: all-scroll;
scrollbar-width: none;
-ms-overflow-style: none;
}
.scrollContainer::-webkit-scrollbar {
display: none;
} }
.content { .content {
@ -86,3 +92,5 @@
list-style: disc; list-style: disc;
margin-left: 1.25em; margin-left: 1.25em;
} }

View File

@ -1,6 +1,6 @@
.article { .article {
width: 100%; width: 100%;
/* min-height: 100vh; */ min-height: 100vh;
padding: 7.5rem 0; padding: 7.5rem 0;
.articleHeaderLine, .articleHeader, .articleContent, .articleBottomLine { .articleHeaderLine, .articleHeader, .articleContent, .articleBottomLine {

View File

@ -54,8 +54,9 @@
.contentText { .contentText {
font-weight: 400; font-weight: 400;
font-size: 1.125rem; font-size: 1.125rem;
line-height: 1.625rem; line-height: 2.5rem;
margin-top: 1.25rem; margin-top: 1.25rem;
white-space: pre-line;
} }
} }

View File

@ -3,6 +3,7 @@ import styles from './index.module.css';
type Data = { type Data = {
title: string; title: string;
backgroundImage: string;
items: { items: {
largeTitle: string; largeTitle: string;
title: string; title: string;
@ -10,7 +11,7 @@ type Data = {
} }
export default function HonorGrids({ data }: { data: Data }) { export default function HonorGrids({ data }: { data: Data }) {
return ( return (
<section className={styles.honorGrids}> <section className={styles.honorGrids} style={{ backgroundImage: `url(${data.backgroundImage})` }}>
<div className={styles.honorGridsTitle}>{data.title}</div> <div className={styles.honorGridsTitle}>{data.title}</div>
<div className={styles.honorGridsItems}> <div className={styles.honorGridsItems}>

View File

@ -8,8 +8,8 @@
} }
.sectionContent { .sectionContent {
/* width: 72%; */ /* width: 72%;
/* margin: 0 auto; */ margin: 0 auto; */
} }
.mask { .mask {

View File

@ -2,6 +2,9 @@
min-height: calc(100vh / var(--zoom-compensation, 1)); min-height: calc(100vh / var(--zoom-compensation, 1));
padding: 6.25rem 16.25rem; padding: 6.25rem 16.25rem;
background: #D8D8D8; background: #D8D8D8;
background-size: cover;
background-position: center;
background-repeat: repeat;
} }
.carouselWrapper { .carouselWrapper {
@ -115,9 +118,10 @@
.swiperDesc { .swiperDesc {
font-size: 1rem; font-size: 1rem;
color: #FFFFFF; color: #FFFFFF;
line-height: 1.5rem; line-height: 1.875rem;
margin: 2.5rem 3.75rem; margin: 2.5rem 3.75rem;
opacity: 0; opacity: 0;
white-space: pre-line;
} }
} }
} }

View File

@ -9,6 +9,7 @@ import { useLocation } from "react-router-dom";
import ScrollReveal from "@/components/ScrollReveal"; import ScrollReveal from "@/components/ScrollReveal";
type Data = { type Data = {
title: string; title: string;
backgroundImage?: string;
cardItems: { cardItems: {
title: string; title: string;
desc?: string; desc?: string;
@ -39,7 +40,7 @@ export default function SwiperCardSection({ data }: { data: Data }) {
} }
}, [hashId, data.cardItems, swiperRef]) }, [hashId, data.cardItems, swiperRef])
return ( return (
<section className={styles.swiperCardSection} id={data.cardItems[activeIndex]?.title}> <section className={styles.swiperCardSection} id={data.cardItems[activeIndex]?.title} style={{ backgroundImage: `url(${data.backgroundImage})` }}>
<SectionTitle title={data.title} /> <SectionTitle title={data.title} />
<div className={styles.carouselWrapper} > <div className={styles.carouselWrapper} >
{activeIndex > 0 && ( {activeIndex > 0 && (
@ -48,7 +49,7 @@ export default function SwiperCardSection({ data }: { data: Data }) {
className={styles.navBtn} className={styles.navBtn}
onClick={() => swiperRef?.slidePrev()} onClick={() => swiperRef?.slidePrev()}
> >
<LeftOutlined color="#14355C" /> <svg viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2821" width="24" height="24"><path d="M737.9 888.2L361.7 512l376.2-376.2c16.4-16.4 16.4-43.1 0-59.5s-43.1-16.4-59.5 0L295.8 458.9c-14.2 14.2-22 33-22 53.1s7.8 38.9 22 53.1l382.6 382.6c16.4 16.4 43.1 16.4 59.5 0 16.4-16.5 16.4-43.1 0-59.5z" fill="#272636" p-id="2822"></path></svg>
</button> </button>
)} )}
<Swiper <Swiper
@ -62,16 +63,16 @@ export default function SwiperCardSection({ data }: { data: Data }) {
{data.cardItems.map((item, index) => ( {data.cardItems.map((item, index) => (
<SwiperSlide key={item.title}> <SwiperSlide key={item.title}>
<ScrollReveal preset="slideUp" amount={0.2} delay={index > 2 ? 0 : index * 0.5}> <ScrollReveal preset="slideUp" amount={0.2} delay={index > 2 ? 0 : index * 0.5}>
<div className={styles.swiperCardItem}> <div className={styles.swiperCardItem}>
<img src={item.backgroundImage ?? item.image ?? ""} alt={item.title} /> <img src={item.backgroundImage ?? item.image ?? ""} alt={item.title} />
<div className={styles.swiperMask}></div> <div className={styles.swiperMask}></div>
<div className={styles.swiperContent}> <div className={styles.swiperContent}>
<div className={styles.swiperTitle}> <div className={styles.swiperTitle}>
<span>{item.title}</span> <span>{item.title}</span>
</div>
<p className={styles.swiperDesc}>{item.content ?? item.desc}</p>
</div> </div>
<p className={styles.swiperDesc}>{item.content ?? item.desc}</p>
</div> </div>
</div>
</ScrollReveal> </ScrollReveal>
</SwiperSlide> </SwiperSlide>
))} ))}
@ -82,7 +83,7 @@ export default function SwiperCardSection({ data }: { data: Data }) {
className={`${styles.navBtn} ${styles.nextBtn}`} className={`${styles.navBtn} ${styles.nextBtn}`}
onClick={() => swiperRef?.slideNext()} onClick={() => swiperRef?.slideNext()}
> >
<RightOutlined color="#14355C" /> <svg viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1638" width="24" height="24"><path d="M318.57 223.95l322.99 322.99c21.87 21.87 57.33 21.87 79.2 0 21.87-21.87 21.87-57.33 0-79.2l-323-322.99c-21.87-21.87-57.33-21.87-79.2 0-21.86 21.87-21.86 57.33 0.01 79.2z" fill="#14355C" p-id="1639"></path><path d="M729.75 555.95L406.76 878.93c-21.87 21.87-57.33 21.87-79.2 0-21.87-21.87-21.87-57.33 0-79.2l322.99-322.99c21.87-21.87 57.33-21.87 79.2 0 21.87 21.88 21.87 57.34 0 79.21z" fill="#14355C" p-id="1640"></path></svg>
</button> </button>
)} )}
</div> </div>

View File

@ -13,14 +13,14 @@
font-weight: 400; font-weight: 400;
font-size: 1.5rem; font-size: 1.5rem;
line-height: 2.125rem; line-height: 2.125rem;
border-bottom: .0625rem solid #D5D8DC; /* border-bottom: .0625rem solid #D5D8DC; */
width: 100%; width: 100%;
overflow: hidden;
} }
.topTabsNavBtn { .topTabsNavBtn {
position: absolute; position: absolute;
top: 50%; top: 0%;
transform: translateY(-50%);
z-index: 1; z-index: 1;
width: 2.25rem; width: 2.25rem;
height: 2.25rem; height: 2.25rem;
@ -85,11 +85,12 @@
flex-shrink: 0; flex-shrink: 0;
cursor: pointer; cursor: pointer;
color: #222222; color: #222222;
font-weight: 500; font-weight: 400;
} }
.topTabsTabItem.active { .topTabsTabItem.active {
color: #14355C; color: #14355C;
font-weight: 600;
} }
.topTabsContent { .topTabsContent {
@ -162,11 +163,10 @@
} }
.topTabsContentItems { .topTabsContentItems {
width: 57.5rem;
margin: 0 auto; margin: 0 auto;
display: grid; display: grid;
grid-template-columns: repeat(3, 1fr); grid-template-columns: repeat(3, 1fr);
gap: 1.25rem; gap: 1.25rem 12.5rem;
} }
.topTabsContentItem { .topTabsContentItem {

View File

@ -79,8 +79,11 @@ export default function TopTabsSection({ data, className }: { data: Data, classN
</div> </div>
</div> </div>
<ScrollReveal preset="slideUp" delay={0.9} duration={1.1}> <ScrollReveal preset="slideUp" delay={0.9} duration={1.1}>
<p className={styles.topTabsContentLeftDesc}> <p className={`${styles.topTabsContentLeftDesc} normal-p`}
{data.tabItems[activeIndex].contentText ?? data.tabItems[activeIndex].content}
dangerouslySetInnerHTML={{ __html: data.tabItems[activeIndex].contentText ?? data.tabItems[activeIndex].content as any }}
>
{/* {data.tabItems[activeIndex].contentText ?? data.tabItems[activeIndex].content} */}
</p> </p>
</ScrollReveal> </ScrollReveal>
</div> </div>

View File

@ -24,7 +24,7 @@
.footerTitle { .footerTitle {
font-size: .875rem; font-size: .875rem;
font-weight: 600; font-weight: 600;
color: #333; color: #222;
margin-bottom: .25rem; margin-bottom: .25rem;
} }

View File

@ -258,6 +258,10 @@
line-height: 3.125rem; line-height: 3.125rem;
color: #222222; color: #222222;
text-decoration: none; text-decoration: none;
&:hover {
color: #14355C;
}
} }
@media (max-width: 64rem) { @media (max-width: 64rem) {

View File

@ -166,6 +166,8 @@
grid-auto-rows: auto; grid-auto-rows: auto;
align-items: start; align-items: start;
gap: 1rem; gap: 1rem;
width: 70%;
margin: 0 auto;
} }
.section3Item { .section3Item {
@ -195,7 +197,7 @@
} }
.timelineWrapper { .timelineWrapper {
width: 100%; width: 100%;
overflow: auto; overflow: hidden;
} }
} }
@ -253,3 +255,25 @@
padding: 1.5rem; padding: 1.5rem;
} }
} }
.virtualScrollBar {
width: 82.4375rem;
height: 6px;
background: #DFE4EA;
border-radius: 450px 450px 450px 450px;
margin: 0 auto;
cursor: pointer;
max-width: calc(100% - 2rem);
margin-bottom: 6.25rem;
margin-top: 20px;
.virtualScrollBarInner {
width: 0;
height: 6px;
background: #14355C;
border-radius: 450px 450px 450px 450px;
transform: translateX(0px);
transition: transform 0.2s ease-out;
cursor: grab;
}
}

View File

@ -101,6 +101,12 @@ export default function AboutFounder() {
function TimeLineComponent({ section4Data }: { section4Data: any }) { function TimeLineComponent({ section4Data }: { section4Data: any }) {
const refElement = useRef<HTMLDivElement>(null); const refElement = useRef<HTMLDivElement>(null);
const sectionRef = useRef<HTMLElement>(null); const sectionRef = useRef<HTMLElement>(null);
const virtualBarRef = useRef<HTMLDivElement>(null);
const [thumbLeft, setThumbLeft] = useState(0);
const [thumbWidth, setThumbWidth] = useState(0);
const [isDraggingThumb, setIsDraggingThumb] = useState(false);
const dragStartX = useRef(0);
const dragStartScrollLeft = useRef(0);
const [isSectionInView, setIsSectionInView] = useState(false); const [isSectionInView, setIsSectionInView] = useState(false);
useEffect(() => { useEffect(() => {
@ -133,6 +139,40 @@ function TimeLineComponent({ section4Data }: { section4Data: any }) {
smoothWheel: true, smoothWheel: true,
}); });
const updateVirtualScrollBar = () => {
const bar = virtualBarRef.current;
if (!bar) return;
const totalScrollable = wrapper.scrollWidth - wrapper.clientWidth;
const maxThumbTravel = bar.clientWidth;
if (wrapper.scrollWidth <= 0 || bar.clientWidth <= 0) return;
if (totalScrollable <= 0) {
setThumbWidth(bar.clientWidth);
setThumbLeft(0);
return;
}
const nextThumbWidth = Math.max(
(wrapper.clientWidth / wrapper.scrollWidth) * bar.clientWidth,
72
);
const maxLeft = Math.max(maxThumbTravel - nextThumbWidth, 0);
const nextLeft = (wrapper.scrollLeft / totalScrollable) * maxLeft;
setThumbWidth(nextThumbWidth);
setThumbLeft(nextLeft);
};
const resizeObserver = new ResizeObserver(() => {
updateVirtualScrollBar();
});
resizeObserver.observe(wrapper);
if (content) resizeObserver.observe(content);
if (virtualBarRef.current) resizeObserver.observe(virtualBarRef.current);
wrapper.addEventListener("scroll", updateVirtualScrollBar, { passive: true });
updateVirtualScrollBar();
let rafId = 0; let rafId = 0;
const raf = (time: number) => { const raf = (time: number) => {
lenis.raf(time); lenis.raf(time);
@ -143,9 +183,61 @@ function TimeLineComponent({ section4Data }: { section4Data: any }) {
return () => { return () => {
cancelAnimationFrame(rafId); cancelAnimationFrame(rafId);
wrapper.removeEventListener("scroll", updateVirtualScrollBar);
resizeObserver.disconnect();
lenis.destroy(); lenis.destroy();
}; };
}, [isSectionInView]); }, [isSectionInView]);
const handleTrackClick = (event: React.MouseEvent<HTMLDivElement>) => {
if (!refElement.current || !virtualBarRef.current) return;
const wrapper = refElement.current;
const barRect = virtualBarRef.current.getBoundingClientRect();
const clickedX = event.clientX - barRect.left;
const desiredThumbLeft = clickedX - thumbWidth / 2;
const maxLeft = Math.max(barRect.width - thumbWidth, 0);
const clampedThumbLeft = Math.max(0, Math.min(desiredThumbLeft, maxLeft));
const totalScrollable = wrapper.scrollWidth - wrapper.clientWidth;
if (totalScrollable <= 0 || maxLeft <= 0) return;
wrapper.scrollLeft = (clampedThumbLeft / maxLeft) * totalScrollable;
};
const handleThumbMouseDown = (event: React.MouseEvent<HTMLDivElement>) => {
event.preventDefault();
if (!refElement.current) return;
setIsDraggingThumb(true);
dragStartX.current = event.clientX;
dragStartScrollLeft.current = refElement.current.scrollLeft;
};
useEffect(() => {
if (!isDraggingThumb) return;
const handleMouseMove = (event: MouseEvent) => {
if (!refElement.current || !virtualBarRef.current) return;
const wrapper = refElement.current;
const bar = virtualBarRef.current;
const totalScrollable = wrapper.scrollWidth - wrapper.clientWidth;
const maxLeft = Math.max(bar.clientWidth - thumbWidth, 0);
if (totalScrollable <= 0 || maxLeft <= 0) return;
const deltaX = event.clientX - dragStartX.current;
const deltaScroll = (deltaX / maxLeft) * totalScrollable;
wrapper.scrollLeft = dragStartScrollLeft.current + deltaScroll;
};
const handleMouseUp = () => {
setIsDraggingThumb(false);
};
window.addEventListener("mousemove", handleMouseMove);
window.addEventListener("mouseup", handleMouseUp);
return () => {
window.removeEventListener("mousemove", handleMouseMove);
window.removeEventListener("mouseup", handleMouseUp);
};
}, [isDraggingThumb, thumbWidth]);
return ( return (
<> <>
{section4Data && ( {section4Data && (
@ -157,6 +249,13 @@ function TimeLineComponent({ section4Data }: { section4Data: any }) {
<div className={styles.section4Title}>{section4Data?.title}</div> <div className={styles.section4Title}>{section4Data?.title}</div>
<div className={styles.timelineWrapper}> <div className={styles.timelineWrapper}>
<SineWaveTimeline items={section4Data?.items ?? []} refElement={refElement} /> <SineWaveTimeline items={section4Data?.items ?? []} refElement={refElement} />
<div className={styles.virtualScrollBar} ref={virtualBarRef} onClick={handleTrackClick}>
<div
className={styles.virtualScrollBarInner}
onMouseDown={handleThumbMouseDown}
style={{ width: `${thumbWidth}px`, transform: `translateX(${thumbLeft}px)` }}
/>
</div>
</div> </div>
</section> </section>
)} )}

View File

@ -9,12 +9,17 @@
); );
min-height: calc(100vh / var(--zoom-compensation, 1)); min-height: calc(100vh / var(--zoom-compensation, 1));
width: 100%; width: 100%;
padding: 6.25rem auto; padding: 6.25rem 0;
padding-bottom: 9.375rem; padding-bottom: 9.375rem;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
} }
.sectionInner {
margin: 0 auto;
width: 72%;
}
.headRow { .headRow {
width: 100%; width: 100%;
display: flex; display: flex;

View File

@ -58,6 +58,7 @@ export default function AboutHistory() {
/> />
<section className={styles.section}> <section className={styles.section}>
<div className={styles.sectionInner}>
<div className={styles.headRow}> <div className={styles.headRow}>
<YearPicker placeholder="年份" value={year} onChange={handleYearChange} /> <YearPicker placeholder="年份" value={year} onChange={handleYearChange} />
</div> </div>
@ -66,6 +67,7 @@ export default function AboutHistory() {
selectedYear={year} selectedYear={year}
onYearChange={setYear} onYearChange={setYear}
/> />
</div>
</section> </section>
</div> </div>
); );

View File

@ -20,15 +20,7 @@ export default function BaseGroup() {
const section5Data = data.section5Data; const section5Data = data.section5Data;
const swiperCardData = section2Data const swiperCardData = section2Data
? {
title: section2Data.title,
cardItems: section2Data.cardItems?.map((c: { title: string; content: string; backgroundImage?: string }) => ({
title: c.title,
content: c.content,
backgroundImage: c.backgroundImage,
})) ?? [],
}
: null;
const rowAccordionData = section3Data const rowAccordionData = section3Data
? { ? {
@ -49,8 +41,8 @@ export default function BaseGroup() {
{section1Data && <ParagraphSection data={section1Data} />} {section1Data && <ParagraphSection data={section1Data} />}
{swiperCardData && <SwiperCardSection data={swiperCardData} />} {swiperCardData && <SwiperCardSection data={swiperCardData} />}
{rowAccordionData && <RowAccordion data={rowAccordionData} placement="top" />} {rowAccordionData && <RowAccordion data={rowAccordionData} placement="top" />}
{section4Data && <HonorGrids data={section4Data} />}
{section5Data && <BottomTabsSection data={section5Data} />} {section5Data && <BottomTabsSection data={section5Data} />}
{section4Data && <HonorGrids data={section4Data} />}
</div> </div>
); );
} }

View File

@ -130,7 +130,7 @@ export default function BusinessCommercialGroup() {
<section <section
className={`${styles.twoColSection} ${styles.propertyServices}`} className={`${styles.twoColSection} ${styles.propertyServices}`}
style={{ style={{
backgroundImage: `url(/images/bg-overview.png), ${FALLBACK_GRADIENT}`, backgroundImage: `url(${section4Data?.backgroundImage}), ${FALLBACK_GRADIENT}`,
}} }}
> >
<div className={styles.propertyServicesContent}> <div className={styles.propertyServicesContent}>

View File

@ -18,6 +18,7 @@ export default function BusinessCommercialGroupDetail() {
<div> <div>
<Banner <Banner
title={banner?.title ?? ""} title={banner?.title ?? ""}
icon={banner?.icon ?? ""}
largedesc={(banner as BannerConfig)?.largeContent} largedesc={(banner as BannerConfig)?.largeContent}
titleSize={(banner as BannerConfig)?.titleSize ?? "large"} titleSize={(banner as BannerConfig)?.titleSize ?? "large"}
backgroundImage={banner?.backgroundImage ?? "/images/bg-commercial-group.png"} backgroundImage={banner?.backgroundImage ?? "/images/bg-commercial-group.png"}

View File

@ -1,24 +1,45 @@
.investGroup { .investGroup {
width: 100%; width: 100%;
height: 50rem; height: 50rem;
padding: 6.25rem 16.25rem; padding: 6.25rem 0;
background: rgba(0, 39, 83, 0.7); background: rgba(0, 39, 83, 0.7);
background-size: cover;
background-position: center;
background-repeat: repeat;
.investGroupInner {
margin: 0 auto;
width: 72%;
}
.investGroupContent { .investGroupContent {
color: #FFFFFF; color: #FFFFFF;
height: 28.75rem; height: 28.75rem;
margin-top: 7.5rem;
.investGroupContentItems { .investGroupContentItems {
display: flex; display: flex;
height: 28.75rem; height: 28.75rem;
gap: 200px;
position: relative;
.investGroupContentItem:first-child { &::after {
content: '';
position: absolute;
left: 50%;
top: -10%;
width: 1px;
height: 100%;
background: rgba(255, 255, 255, 0.5);
}
/* .investGroupContentItem:first-child {
padding-right: 6.25rem; padding-right: 6.25rem;
} }
.investGroupContentItem:last-child { .investGroupContentItem:last-child {
padding-left: 6.25rem; padding-left: 6.25rem;
} } */
.investGroupContentItem { .investGroupContentItem {
flex: 1; flex: 1;
@ -57,6 +78,9 @@
width: 100%; width: 100%;
padding: 6.25rem 16.25rem; padding: 6.25rem 16.25rem;
background: rgba(255, 255, 255, 0.6); background: rgba(255, 255, 255, 0.6);
background-size: cover;
background-position: center;
background-repeat: repeat;
.equityInvestmentItems { .equityInvestmentItems {
/* 5列布局 */ /* 5列布局 */
@ -81,6 +105,7 @@
} }
.industryFoster { .industryFoster {
width: 100%; width: 100%;
height: calc(100vh / var(--zoom-compensation, 1)); height: calc(100vh / var(--zoom-compensation, 1));
@ -103,6 +128,7 @@
background: rgba(20, 53, 92, 0.5); background: rgba(20, 53, 92, 0.5);
color: #fff; color: #fff;
padding: 3.75rem 3.125rem; padding: 3.75rem 3.125rem;
margin-left: 16.25rem;
.industryFosterMaskTitle { .industryFosterMaskTitle {
font-weight: 500; font-weight: 500;

View File

@ -30,37 +30,45 @@ export default function InvestGroup() {
{section1Data && <ParagraphSection data={section1Data} />} {section1Data && <ParagraphSection data={section1Data} />}
{section2Data && ( {section2Data && (
<section className={styles.investGroup} id={section2Data.title}> <section className={styles.investGroup} id={section2Data.title} style={{
<SectionTitle title={section2Data.title} color="#fff" /> backgroundImage: `url(${section2Data.backgroundImage})`
<div className={styles.investGroupContent}> }}>
<div className={styles.investGroupContentItems}> <div className={styles.investGroupInner}>
{section2Data.items?.map((item: { title: string; content: string }, index: number) => ( <SectionTitle title={section2Data.title} color="#fff" />
<ScrollReveal preset="slideUp" amount={0.2} delay={index * 0.5}> <div className={styles.investGroupContent}>
<div className={styles.investGroupContentItem} key={index}> <div className={styles.investGroupContentItems}>
<div className={styles.investGroupContentItemTitle}>{item.title}</div> {section2Data.items?.map((item: { title: string; content: string }, index: number) => (
<div className={styles.investGroupContentItemContent}>{item.content}</div> <ScrollReveal preset="slideUp" amount={0.2} delay={index * 0.5}>
</div> <div className={styles.investGroupContentItem} key={index}>
</ScrollReveal> <div className={styles.investGroupContentItemTitle}>{item.title}</div>
))} <div className={styles.investGroupContentItemContent}>{item.content}</div>
</div>
</ScrollReveal>
))}
</div>
</div> </div>
</div> </div>
</section> </section>
)} )}
{section3Data && ( {section3Data && (
<section className={styles.equityInvestment} id={section3Data.title}> <section className={styles.equityInvestment} id={section3Data.title}
style={{
backgroundImage: `url(${section3Data.backgroundImage})`
}}
>
<SectionTitle title={section3Data.title} /> <SectionTitle title={section3Data.title} />
<div className={styles.equityInvestmentItems}> <div className={styles.equityInvestmentItems}>
{section3Data.items?.map((item: { logo: string; title: string }, index: number) => ( {section3Data.items?.map((item: { logo: string; title: string }, index: number) => (
<ScrollReveal preset="slideUp" amount={0.2} delay={index * 0.5}> <ScrollReveal preset="slideUp" amount={0.2} delay={index * 0.5}>
<div className={styles.equityInvestmentItem} key={index}> <div className={styles.equityInvestmentItem} key={index}>
<img <img
src={item.logo} src={item.logo}
alt={item.title} alt={item.title}
className={styles.equityInvestmentItemLogo} className={styles.equityInvestmentItemLogo}
/> />
<div className={styles.equityInvestmentItemTitle}>{item.title}</div> <div className={styles.equityInvestmentItemTitle}>{item.title}</div>
</div> </div>
</ScrollReveal> </ScrollReveal>
))} ))}
</div> </div>
@ -76,10 +84,10 @@ export default function InvestGroup() {
height="100vh" height="100vh"
> >
<ScrollReveal preset="slideUp" amount={0.2}> <ScrollReveal preset="slideUp" amount={0.2}>
<div className={styles.industryFosterMask}> <div className={styles.industryFosterMask}>
<div className={styles.industryFosterMaskTitle}>{section4Data.title}</div> <div className={styles.industryFosterMaskTitle}>{section4Data.title}</div>
<div className={styles.industryFosterMaskContent}>{section4Data.content}</div> <div className={styles.industryFosterMaskContent}>{section4Data.content}</div>
</div> </div>
</ScrollReveal> </ScrollReveal>
</Section> </Section>
</div> </div>

View File

@ -18,9 +18,8 @@ export default function RealtyGroup() {
const section2Data = data.section2Data; const section2Data = data.section2Data;
const section3Data = data.section3Data; const section3Data = data.section3Data;
const section4Data = data.section4Data; const section4Data = data.section4Data;
const section5Data = data.section5Data;
const topTabsData = section2Data ? { tabItems: section2Data.tabItems ?? [] } : null; const topTabsData = section2Data
const rowAccordionData = section3Data const rowAccordionData = section3Data
? { ? {
@ -46,7 +45,6 @@ export default function RealtyGroup() {
{topTabsData && <TopTabsSection data={topTabsData} />} {topTabsData && <TopTabsSection data={topTabsData} />}
{rowAccordionData && <RowAccordion data={rowAccordionData} />} {rowAccordionData && <RowAccordion data={rowAccordionData} />}
{section4Data && <HonorGrids data={section4Data} />} {section4Data && <HonorGrids data={section4Data} />}
{section5Data && <BottomTabsSection data={section5Data} />}
</div> </div>
); );
} }

View File

@ -21,15 +21,7 @@ export default function RuijingGroup() {
const section4Data = data.section4Data; const section4Data = data.section4Data;
const swiperCardData = section2Data const swiperCardData = section2Data
? {
title: section2Data.title,
cardItems: section2Data.cardItems?.map((c: { title: string; content: string; backgroundImage?: string }) => ({
title: c.title,
content: c.content,
backgroundImage: c.backgroundImage,
})) ?? [],
}
: null;
return ( return (
<div> <div>
@ -48,15 +40,17 @@ export default function RuijingGroup() {
title={section3Data.title} title={section3Data.title}
subtitle={section3Data.subtitle} subtitle={section3Data.subtitle}
titleColor="#fff" titleColor="#fff"
background="/images/bg-overview.png" background={section3Data.backgroundImage}
maskBackground="rgba(2,17,48,0.5)" maskBackground="rgba(2,17,48,0.5)"
> >
<ScrollReveal preset="slideUp" amount={0.2} delay={0.5}> <div className="w-72-inner">
<div className={styles.businessFeatureContent}>{section3Data.content}</div> <ScrollReveal preset="slideUp" amount={0.2} delay={0.5}>
</ScrollReveal> <div className={styles.businessFeatureContent}>{section3Data.content}</div>
{section3Data.statsData && ( </ScrollReveal>
<StatsRow data={section3Data.statsData} color="#fff" /> {section3Data.statsData && (
)} <StatsRow data={section3Data.statsData} color="#fff" />
)}
</div>
</Section> </Section>
)} )}

View File

@ -311,8 +311,9 @@
.newsGrid { .newsGrid {
gap: 1.25rem; gap: 1.25rem;
align-items: start; align-items: start;
display: flex;
width: 72%; width: 72%;
display: grid;
grid-template-columns: 1fr 1fr;
margin: 0 auto; margin: 0 auto;
} }

View File

@ -110,7 +110,7 @@ export default function JoinCampus() {
/> />
<Section maskBackground="#FFFFFF"> <Section maskBackground="#FFFFFF">
<div className={styles.campusRow}> <div className={`${styles.campusRow} w-72-inner`}>
<div className={styles.campusColLeft}> <div className={styles.campusColLeft}>
<SearchInput value={searchValue} placeholder="搜索职位" onChange={setSearchValue} onEnter={refreshData} /> <SearchInput value={searchValue} placeholder="搜索职位" onChange={setSearchValue} onEnter={refreshData} />

View File

@ -20,16 +20,16 @@ export default function Culture() {
title={banner?.title ?? ""} title={banner?.title ?? ""}
content={(banner as BannerConfig)?.content} content={(banner as BannerConfig)?.content}
titleSize={(banner as BannerConfig)?.titleSize ?? "large"} titleSize={(banner as BannerConfig)?.titleSize ?? "large"}
backgroundImage={banner?.backgroundImage ?? "/images/bg-overview.png"} backgroundImage={banner?.backgroundImage ?? ""}
/> />
{section1Data && ( {section1Data && (
<Section <Section
title={section1Data.title} title={section1Data.title}
background="/images/bg-overview.png" background={section1Data.backgroundImage ?? ""}
maskBackground="#D8D8D8" maskBackground="transparent"
> >
<div className={styles.cultureItems}> <div className={`${styles.cultureItems} w-72-inner`}>
{section1Data.items?.map((item: any, index: number) => ( {section1Data.items?.map((item: any, index: number) => (
<ScrollReveal preset="slideUp" amount={0.2} delay={index * 0.5} key={index} className={styles.cultureItem}> <ScrollReveal preset="slideUp" amount={0.2} delay={index * 0.5} key={index} className={styles.cultureItem}>
<div <div
@ -52,10 +52,10 @@ export default function Culture() {
{section2Data && ( {section2Data && (
<Section <Section
title={section2Data.title} title={section2Data.title}
background="" background={section2Data.backgroundImage ?? ""}
maskBackground="rgba(216,216,216,0.6)" maskBackground="rgba(216,216,216,0.6)"
> >
<div className={styles.valuesItems}> <div className={`${styles.valuesItems}`} style={{ margin: "0 auto", width: "60%" }}>
{section2Data.items?.map((item: { title: string; content?: string; icon?: string }, index: number) => ( {section2Data.items?.map((item: { title: string; content?: string; icon?: string }, index: number) => (
<ScrollReveal preset="slideUp" amount={0.2} delay={index * 0.5} key={index} className={styles.cultureItem}> <ScrollReveal preset="slideUp" amount={0.2} delay={index * 0.5} key={index} className={styles.cultureItem}>
<div key={index} className={styles.valuesItem}> <div key={index} className={styles.valuesItem}>

View File

@ -20,11 +20,11 @@ export default function Media() {
title={banner?.title ?? ""} title={banner?.title ?? ""}
content={(banner as BannerConfig)?.content} content={(banner as BannerConfig)?.content}
titleSize={(banner as BannerConfig)?.titleSize ?? "large"} titleSize={(banner as BannerConfig)?.titleSize ?? "large"}
backgroundImage={banner?.backgroundImage ?? "/images/bg-overview.png"} backgroundImage={banner?.backgroundImage ?? ""}
/> />
<Section background="/images/bg-overview.png" maskBackground="rgba(1,11,72,0.8)"> <Section background={section1Data.backgroundImage ?? ""} maskBackground="rgba(1,11,72,0.8)">
<div className={styles.mediaItems}> <div className={`${styles.mediaItems} w-72-inner`}>
{items.map((item: { title: string; content?: string }, index: number) => ( {items.map((item: { title: string; content?: string }, index: number) => (
<ScrollReveal preset="slideUp" amount={0.2} delay={index * 0.5} key={index} className={styles.mediaItem}> <ScrollReveal preset="slideUp" amount={0.2} delay={index * 0.5} key={index} className={styles.mediaItem}>
<div className={styles.mediaItemTitle}>{item.title}</div> <div className={styles.mediaItemTitle}>{item.title}</div>

View File

@ -28,10 +28,11 @@ export default function Foundation() {
return newsList.filter((item: any) => item.lang.toLowerCase() === locale.split('-')[0]); return newsList.filter((item: any) => item.lang.toLowerCase() === locale.split('-')[0]);
}, [newsList, locale]) }, [newsList, locale])
const getNewsList = useCallback(() => { const getNewsList = useCallback(() => {
appApi.getNewsList({ page: 1, size: 1000, sort: "create_time DESC", appApi.getNewsList({
page: 1, size: 1000, sort: "create_time DESC",
category_id: String(categoryList?.find((item: any) => item.name.includes('【银泰公益基金会】公益传播'))?.id ?? ''), category_id: String(categoryList?.find((item: any) => item.name.includes('【银泰公益基金会】公益传播'))?.id ?? ''),
}).then((res:any) => { }).then((res: any) => {
setNewsList(res.data.items.map((item:any) => { setNewsList(res.data.items.map((item: any) => {
return { return {
id: item.id, id: item.id,
title: item.title, title: item.title,
@ -58,7 +59,7 @@ export default function Foundation() {
size: 1000, size: 1000,
// category_id: String(categoryList?.find((item: any) => item.name.includes('社会责任报告'))?.id ?? '') // category_id: String(categoryList?.find((item: any) => item.name.includes('社会责任报告'))?.id ?? '')
}) })
const items = res.data.items.filter((item:any) => item.category_name.includes("信息公开")) const items = res.data.items.filter((item: any) => item.category_name.includes("信息公开"))
console.log("------items-----", items) console.log("------items-----", items)
setFileList(items) setFileList(items)
}, []) }, [])
@ -85,10 +86,10 @@ export default function Foundation() {
{section2Data && ( {section2Data && (
<Section <Section
title={section2Data.title} title={section2Data.title}
background="" background={section2Data.backgroundImage ?? ""}
maskBackground="rgba(255,255,255,0.3)" maskBackground="rgba(255,255,255,0.3)"
> >
<div className={styles.publicWelfareDataItems}> <div className={`${styles.publicWelfareDataItems} w-72-inner`}>
{localNewsList?.map((item: any, index: number) => ( {localNewsList?.map((item: any, index: number) => (
<ScrollReveal preset="slideUp" amount={0.2} delay={(index % 2) * 0.5} <ScrollReveal preset="slideUp" amount={0.2} delay={(index % 2) * 0.5}
key={index} key={index}
@ -97,8 +98,8 @@ export default function Foundation() {
<AnimateTopCard data={item} /> <AnimateTopCard data={item} />
</ScrollReveal> </ScrollReveal>
))} ))}
<div style={{ marginBottom: "3.125rem" }} />
</div> </div>
<div style={{ marginBottom: "3.125rem" }} />
</Section> </Section>
)} )}
@ -110,19 +111,19 @@ export default function Foundation() {
maskBackground="rgba(255,255,255,0.1)" maskBackground="rgba(255,255,255,0.1)"
height="47.5rem" height="47.5rem"
> >
<div className={styles.informationPublicDataContent}> <div className={`${styles.informationPublicDataContent} w-72-inner`}>
<div className={styles.informationPublicDataItems}> <div className={styles.informationPublicDataItems}>
{localFileList {localFileList
.filter((item:any) => item.category_name.includes( .filter((item: any) => item.category_name.includes(
section3Data.tabItems?.[activeIndex]?.tabName ?? '' section3Data.tabItems?.[activeIndex]?.tabName ?? ''
)) ))
.map((item: any, index: number) => ( .map((item: any, index: number) => (
<div key={index} className={styles.informationPublicDataItem}> <div key={index} className={styles.informationPublicDataItem}>
<li onClick={() => window.open(item.path, '_blank')}> <li onClick={() => window.open(item.path, '_blank')}>
<span>{item.name}</span> <span>{item.name}</span>
</li> </li>
</div> </div>
))} ))}
</div> </div>
<BottomTabs <BottomTabs
tabItems={section3Data.tabItems ?? []} tabItems={section3Data.tabItems ?? []}
@ -135,12 +136,12 @@ export default function Foundation() {
{section4Data && ( {section4Data && (
<Section title={section4Data.title} background="" maskBackground="#F7FBFF"> <Section title={section4Data.title} background="" maskBackground="#F7FBFF">
<div className={styles.partnerItems}> <div className={`${styles.partnerItems} w-72-inner`}>
{section4Data.items?.map((item: any, index: number) => ( {section4Data.items?.map((item: any, index: number) => (
<ScrollReveal preset="slideUp" amount={0.2} delay={index * 0.5} key={index}> <ScrollReveal preset="slideUp" amount={0.2} delay={index * 0.5} key={index}>
<div key={index} className={styles.partnerItem}> <div key={index} className={styles.partnerItem}>
<img src={item.logo} alt="logo" /> <img src={item.logo} alt="logo" />
</div> </div>
</ScrollReveal> </ScrollReveal>
))} ))}
</div> </div>

View File

@ -93,7 +93,7 @@ export default function Sustainability() {
const resItems: any[] = [] const resItems: any[] = []
// 去重 id lang 相同 // 去重 id lang 相同
items.forEach((item: any) => { items.forEach((item: any) => {
if(!resItems.some((i: any) => i.id === item.id && i.lang === item.lang)) { if (!resItems.some((i: any) => i.id === item.id && i.lang === item.lang)) {
resItems.push(item) resItems.push(item)
} }
}) })
@ -121,29 +121,31 @@ export default function Sustainability() {
{section1Data && ( {section1Data && (
<ParagraphSection data={section1Data}> <ParagraphSection data={section1Data}>
<div style={{ width: "100%", height: "100px" }}></div>
<ColumnXGrids items={columnXGridsData} /> <ColumnXGrids items={columnXGridsData} />
</ParagraphSection> </ParagraphSection>
)} )}
{section3Data && ( {section3Data && (
<Section <Section
title={section3Data.title} title={section3Data.title}
background="" background=""
maskBackground="rgba(255,255,255,0.3)" maskBackground="rgba(255,255,255,0.3)"
> >
<p className={styles.socialResponsibilityCaseDataContent}> <div className="w-72-inner">
{section3Data.content} <p className={styles.socialResponsibilityCaseDataContent}>
</p> {section3Data.content}
<div className={styles.socialResponsibilityCaseDataItems}> </p>
{localNewsItems?.map((item: any, index: number) => ( <div className={styles.socialResponsibilityCaseDataItems}>
<ScrollReveal preset="slideUp" amount={0.2} delay={(index % 2) * 0.5} {localNewsItems?.map((item: any, index: number) => (
key={index} <ScrollReveal preset="slideUp" amount={0.2} delay={(index % 2) * 0.5}
className={styles.socialResponsibilityCaseDataItem} key={index}
> className={styles.socialResponsibilityCaseDataItem}
>
<AnimateTopCard data={item} /> <AnimateTopCard data={item} />
</ScrollReveal> </ScrollReveal>
))} ))}
</div>
</div> </div>
</Section> </Section>
)} )}
@ -154,6 +156,7 @@ export default function Sustainability() {
background="" background=""
maskBackground="#F7FBFF" maskBackground="#F7FBFF"
> >
<div className="w-72-inner">
<div className={styles.socialResponsibilityReportData}> <div className={styles.socialResponsibilityReportData}>
{localReportItems?.map((item: any, index: number) => ( {localReportItems?.map((item: any, index: number) => (
<ScrollReveal preset="slideUp" amount={0.2} delay={(index % 4) * 0.5} <ScrollReveal preset="slideUp" amount={0.2} delay={(index % 4) * 0.5}
@ -176,7 +179,7 @@ export default function Sustainability() {
<div <div
className={styles.socialResponsibilityReportItemMore} className={styles.socialResponsibilityReportItemMore}
onClick={() => { onClick={() => {
if(localReportItems.length < total) { if (localReportItems.length < total) {
setPage(page + 1) setPage(page + 1)
} else { } else {
setReportItems(prev => [...prev.slice(0, 8)]) setReportItems(prev => [...prev.slice(0, 8)])
@ -186,6 +189,7 @@ export default function Sustainability() {
> >
{localReportItems.length < total ? "了解更多" : "收起"} {localReportItems.length < total ? "了解更多" : "收起"}
</div> </div>
</div>
</Section> </Section>
)} )}
</div> </div>