save
This commit is contained in:
parent
4b0cee8ddb
commit
b527ad343b
|
|
@ -1,16 +1,55 @@
|
||||||
import { Link, useLocation } from "react-router-dom";
|
import { Link, useLocation } from "react-router-dom";
|
||||||
import { Swiper, SwiperSlide } from "swiper/react";
|
import { Swiper, SwiperSlide } from "swiper/react";
|
||||||
import { Autoplay, EffectFade } from "swiper/modules";
|
import { Autoplay, EffectFade } from "swiper/modules";
|
||||||
|
import type { Swiper as SwiperType } from "swiper";
|
||||||
import "swiper/css";
|
import "swiper/css";
|
||||||
import "swiper/css/effect-fade";
|
import "swiper/css/effect-fade";
|
||||||
import styles from "./Banner.module.css";
|
import styles from "./Banner.module.css";
|
||||||
import { useMemo } from "react";
|
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
||||||
import { useStore } from "@/store";
|
import { useStore } from "@/store";
|
||||||
import type { BannerConfig, NavItem, NavChild } from "@/type";
|
import type { BannerConfig, NavItem, NavChild } from "@/type";
|
||||||
import ScrollReveal from "@/components/ScrollReveal";
|
import ScrollReveal from "@/components/ScrollReveal";
|
||||||
|
|
||||||
const FALLBACK_GRADIENT = "linear-gradient(135deg, #1a2a4a 0%, #2d4a7c 100%)";
|
const FALLBACK_GRADIENT = "linear-gradient(135deg, #1a2a4a 0%, #2d4a7c 100%)";
|
||||||
|
|
||||||
|
const VIDEO_EXT = ["mp4", "webm", "ogg"];
|
||||||
|
|
||||||
|
function mediaExtension(url: string) {
|
||||||
|
const path = url.split("?")[0] ?? "";
|
||||||
|
return path.split(".").pop()?.toLowerCase() ?? "";
|
||||||
|
}
|
||||||
|
|
||||||
|
function isVideoUrl(url: string) {
|
||||||
|
return VIDEO_EXT.includes(mediaExtension(url));
|
||||||
|
}
|
||||||
|
|
||||||
|
function BannerSlideVideo({
|
||||||
|
src,
|
||||||
|
active,
|
||||||
|
onEnded,
|
||||||
|
className,
|
||||||
|
}: {
|
||||||
|
src: string;
|
||||||
|
active: boolean;
|
||||||
|
onEnded: () => void;
|
||||||
|
className: string;
|
||||||
|
}) {
|
||||||
|
const ref = useRef<HTMLVideoElement>(null);
|
||||||
|
useEffect(() => {
|
||||||
|
const v = ref.current;
|
||||||
|
if (!v) return;
|
||||||
|
if (active) {
|
||||||
|
v.currentTime = 0;
|
||||||
|
void v.play().catch(() => {});
|
||||||
|
} else {
|
||||||
|
v.pause();
|
||||||
|
}
|
||||||
|
}, [active, src]);
|
||||||
|
return (
|
||||||
|
<video ref={ref} src={src} className={className} muted playsInline onEnded={onEnded} />
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
export type { BannerConfig } from "@/type";
|
export type { BannerConfig } from "@/type";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
|
|
@ -101,7 +140,23 @@ export default function Banner({
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
||||||
const videoExtension = ["mp4", "webm", "ogg"];
|
const swiperRef = useRef<SwiperType | null>(null);
|
||||||
|
const [carouselRealIndex, setCarouselRealIndex] = useState(0);
|
||||||
|
|
||||||
|
const syncAutoplayForMedia = useCallback((swiper: SwiperType, urls: string[]) => {
|
||||||
|
const idx = swiper.realIndex;
|
||||||
|
const url = urls[idx];
|
||||||
|
if (url && isVideoUrl(url)) {
|
||||||
|
swiper.autoplay?.stop();
|
||||||
|
} else {
|
||||||
|
swiper.autoplay?.start();
|
||||||
|
}
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const handleVideoEnded = useCallback(() => {
|
||||||
|
swiperRef.current?.slideNext();
|
||||||
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<section
|
<section
|
||||||
className={styles.hero}
|
className={styles.hero}
|
||||||
|
|
@ -120,18 +175,24 @@ export default function Banner({
|
||||||
allowTouchMove={false}
|
allowTouchMove={false}
|
||||||
slidesPerView={1}
|
slidesPerView={1}
|
||||||
loop={true}
|
loop={true}
|
||||||
|
onSwiper={(swiper: SwiperType) => {
|
||||||
|
swiperRef.current = swiper;
|
||||||
|
setCarouselRealIndex(swiper.realIndex);
|
||||||
|
syncAutoplayForMedia(swiper, images);
|
||||||
|
}}
|
||||||
|
onSlideChange={(swiper: SwiperType) => {
|
||||||
|
setCarouselRealIndex(swiper.realIndex);
|
||||||
|
syncAutoplayForMedia(swiper, images);
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
{images.map((img, i) => (
|
{images.map((img, i) => (
|
||||||
<SwiperSlide key={i}>
|
<SwiperSlide key={i}>
|
||||||
{/* 图片后缀 */}
|
{isVideoUrl(img) ? (
|
||||||
{videoExtension.includes(img.split(".").pop() ?? "") ? (
|
<BannerSlideVideo
|
||||||
<video
|
|
||||||
src={img}
|
src={img}
|
||||||
|
active={carouselRealIndex === i}
|
||||||
|
onEnded={handleVideoEnded}
|
||||||
className={styles.bgVideo}
|
className={styles.bgVideo}
|
||||||
autoPlay
|
|
||||||
muted
|
|
||||||
loop
|
|
||||||
playsInline
|
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<div
|
<div
|
||||||
|
|
@ -141,11 +202,20 @@ export default function Banner({
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{/* 视频 */}
|
|
||||||
</SwiperSlide>
|
</SwiperSlide>
|
||||||
))}
|
))}
|
||||||
</Swiper>
|
</Swiper>
|
||||||
)}
|
)}
|
||||||
|
{!isCarousel && isVideoUrl(images[0]) && (
|
||||||
|
<video
|
||||||
|
src={images[0]}
|
||||||
|
className={styles.bgVideo}
|
||||||
|
autoPlay
|
||||||
|
muted
|
||||||
|
loop
|
||||||
|
playsInline
|
||||||
|
/>
|
||||||
|
)}
|
||||||
<div className={styles.heroOverlay} />
|
<div className={styles.heroOverlay} />
|
||||||
{heroContent}
|
{heroContent}
|
||||||
</section>
|
</section>
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,8 @@
|
||||||
|
|
||||||
/* Features Section */
|
/* Features Section */
|
||||||
.bottomTabsSectionContent {
|
.bottomTabsSectionContent {
|
||||||
width: 100%;
|
width: calc(100% - 520px);
|
||||||
|
margin: 0 auto;
|
||||||
height: 500px;
|
height: 500px;
|
||||||
margin-top: 200px;
|
margin-top: 200px;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ import SectionTitle from "../SectionTitle";
|
||||||
import styles from "./index.module.css";
|
import styles from "./index.module.css";
|
||||||
import { RightOutlined, LeftOutlined } from "@ant-design/icons";
|
import { RightOutlined, LeftOutlined } from "@ant-design/icons";
|
||||||
import { useLocation } from "react-router-dom";
|
import { useLocation } from "react-router-dom";
|
||||||
|
import ScrollReveal from "@/components/ScrollReveal";
|
||||||
type Data = {
|
type Data = {
|
||||||
title: string;
|
title: string;
|
||||||
cardItems: {
|
cardItems: {
|
||||||
|
|
@ -60,8 +61,9 @@ export default function SwiperCardSection({ data }: { data: Data }) {
|
||||||
className={styles.swiperCardList}
|
className={styles.swiperCardList}
|
||||||
onSlideChange={onSwiperChange}
|
onSlideChange={onSwiperChange}
|
||||||
>
|
>
|
||||||
{data.cardItems.map((item) => (
|
{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}>
|
||||||
<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>
|
||||||
|
|
@ -72,6 +74,7 @@ export default function SwiperCardSection({ data }: { data: Data }) {
|
||||||
<p className={styles.swiperDesc}>{item.content ?? item.desc}</p>
|
<p className={styles.swiperDesc}>{item.content ?? item.desc}</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</ScrollReveal>
|
||||||
</SwiperSlide>
|
</SwiperSlide>
|
||||||
))}
|
))}
|
||||||
</Swiper>
|
</Swiper>
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,6 @@
|
||||||
line-height: 34px;
|
line-height: 34px;
|
||||||
border-bottom: 1px solid #D5D8DC;
|
border-bottom: 1px solid #D5D8DC;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
overflow-y: hidden;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.topTabsNavBtn {
|
.topTabsNavBtn {
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ import { useEffect, useState } from 'react';
|
||||||
import styles from './index.module.css';
|
import styles from './index.module.css';
|
||||||
import TopTabs from './TopTabs';
|
import TopTabs from './TopTabs';
|
||||||
import { useLocation } from 'react-router-dom';
|
import { useLocation } from 'react-router-dom';
|
||||||
|
import ScrollReveal from '@/components/ScrollReveal';
|
||||||
|
|
||||||
|
|
||||||
type Data = {
|
type Data = {
|
||||||
|
|
@ -55,22 +56,35 @@ export default function TopTabsSection({ data, className }: { data: Data, classN
|
||||||
<>
|
<>
|
||||||
<div className={styles.topTabsContentLeft}>
|
<div className={styles.topTabsContentLeft}>
|
||||||
<div className={styles.topTabsContentLeftHead}>
|
<div className={styles.topTabsContentLeftHead}>
|
||||||
|
{
|
||||||
|
<ScrollReveal preset="slideRight" delay={0.3} >
|
||||||
{
|
{
|
||||||
data.tabItems[activeIndex].icon && (
|
data.tabItems[activeIndex].icon && (
|
||||||
<img src={data.tabItems[activeIndex].icon} alt="" style={{ width: '100px', height: '100px' }} />
|
<img src={data.tabItems[activeIndex].icon} alt="" style={{ width: '100px', height: '100px' }} />
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
</ScrollReveal>
|
||||||
|
}
|
||||||
<div className={`${styles.topTabsContentLeftTitle} ${data.titleDirection === 'column' ? styles.columnCenter : ''}`}>
|
<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>
|
<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>
|
<div className={styles.topTabsContentLeftTitleSub}>{data.tabItems[activeIndex].contentSubtitle}</div>
|
||||||
|
</ScrollReveal>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<ScrollReveal preset="slideUp" delay={0.9} duration={1.1}>
|
||||||
<p className={styles.topTabsContentLeftDesc}>
|
<p className={styles.topTabsContentLeftDesc}>
|
||||||
{data.tabItems[activeIndex].contentText ?? data.tabItems[activeIndex].content}
|
{data.tabItems[activeIndex].contentText ?? data.tabItems[activeIndex].content}
|
||||||
</p>
|
</p>
|
||||||
|
</ScrollReveal>
|
||||||
</div>
|
</div>
|
||||||
<div className={styles.topTabsContentRight}>
|
<div className={styles.topTabsContentRight}>
|
||||||
|
<ScrollReveal preset="slideLeft" delay={0.5} >
|
||||||
<img src={data.tabItems[activeIndex].sideImage} alt="side-image" />
|
<img src={data.tabItems[activeIndex].sideImage} alt="side-image" />
|
||||||
|
</ScrollReveal>
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ import Section from "@/components/layout/Section";
|
||||||
import SineWaveTimeline from "@/components/SineWaveTimeline";
|
import SineWaveTimeline from "@/components/SineWaveTimeline";
|
||||||
import { useEffect, useRef, useState } from "react";
|
import { useEffect, useRef, useState } from "react";
|
||||||
import Lenis from "lenis"
|
import Lenis from "lenis"
|
||||||
|
import ScrollReveal from "@/components/ScrollReveal";
|
||||||
|
|
||||||
export default function AboutFounder() {
|
export default function AboutFounder() {
|
||||||
const appConfig = useStore((s) => s.appConfig);
|
const appConfig = useStore((s) => s.appConfig);
|
||||||
|
|
@ -32,6 +33,7 @@ export default function AboutFounder() {
|
||||||
<ParagraphSection data={section1Data}>
|
<ParagraphSection data={section1Data}>
|
||||||
<div className={styles.images}>
|
<div className={styles.images}>
|
||||||
{section1Data.items?.map((item: { title: string; content?: string; backgroundImage?: string }, index: number) => (
|
{section1Data.items?.map((item: { title: string; content?: string; backgroundImage?: string }, index: number) => (
|
||||||
|
<ScrollReveal preset="slideUp" amount={0.2} delay={index * 0.5} key={item.title}>
|
||||||
<div className={styles.imageItem} key={item.title}>
|
<div className={styles.imageItem} key={item.title}>
|
||||||
<img src={item.backgroundImage} alt={item.title} />
|
<img src={item.backgroundImage} alt={item.title} />
|
||||||
<div className={styles.imageMask} />
|
<div className={styles.imageMask} />
|
||||||
|
|
@ -42,6 +44,7 @@ export default function AboutFounder() {
|
||||||
<div className={styles.imageOverlayDesc} dangerouslySetInnerHTML={{ __html: item.content ?? "" }}></div>
|
<div className={styles.imageOverlayDesc} dangerouslySetInnerHTML={{ __html: item.content ?? "" }}></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</ScrollReveal>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
</ParagraphSection>
|
</ParagraphSection>
|
||||||
|
|
@ -61,10 +64,14 @@ export default function AboutFounder() {
|
||||||
<p>{section2Data.subtitle}</p>
|
<p>{section2Data.subtitle}</p>
|
||||||
</div>
|
</div>
|
||||||
<div className={styles.founderPhoto}>
|
<div className={styles.founderPhoto}>
|
||||||
|
<ScrollReveal preset="slideRight" amount={0.2} delay={0} duration={1}>
|
||||||
<img src={section2Data.sideImage} alt="个人照" />
|
<img src={section2Data.sideImage} alt="个人照" />
|
||||||
|
</ScrollReveal>
|
||||||
|
<ScrollReveal preset="slideUp" amount={0.2} delay={0.9} duration={1}>
|
||||||
<div className={styles.founderPhotoContent}>
|
<div className={styles.founderPhotoContent}>
|
||||||
<p dangerouslySetInnerHTML={{ __html: section2Data.content ?? "" }} />
|
<p dangerouslySetInnerHTML={{ __html: section2Data.content ?? "" }} />
|
||||||
</div>
|
</div>
|
||||||
|
</ScrollReveal>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
)}
|
)}
|
||||||
|
|
@ -75,9 +82,11 @@ export default function AboutFounder() {
|
||||||
<div className={styles.section3Content}>
|
<div className={styles.section3Content}>
|
||||||
{
|
{
|
||||||
section3Data?.items.map((item: { title?: string }, index: number) => (
|
section3Data?.items.map((item: { title?: string }, index: number) => (
|
||||||
|
<ScrollReveal preset="slideUp" amount={0.2} delay={index * 0.5} key={item.title}>
|
||||||
<div key={index} className={styles.section3Item}>
|
<div key={index} className={styles.section3Item}>
|
||||||
{item.title ? <li>{item.title}</li> : null}
|
{item.title ? <li>{item.title}</li> : null}
|
||||||
</div>
|
</div>
|
||||||
|
</ScrollReveal>
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ import styles from "./History.module.css";
|
||||||
import { useState, useRef, useLayoutEffect, useEffect, useMemo } from "react";
|
import { useState, useRef, useLayoutEffect, useEffect, useMemo } from "react";
|
||||||
import { useStore } from "@/store";
|
import { useStore } from "@/store";
|
||||||
import appApi from "@/api/app";
|
import appApi from "@/api/app";
|
||||||
|
import ScrollReveal from "@/components/ScrollReveal";
|
||||||
type TimelineItem = { year: number; content: string, lang: string };
|
type TimelineItem = { year: number; content: string, lang: string };
|
||||||
|
|
||||||
export default function AboutHistory() {
|
export default function AboutHistory() {
|
||||||
|
|
@ -141,6 +142,7 @@ function HistoryTimeline({ data, selectedYear, onYearChange }: HistoryTimelinePr
|
||||||
<div className={styles.timelineLine} />
|
<div className={styles.timelineLine} />
|
||||||
<div className={styles.timelineContent}>
|
<div className={styles.timelineContent}>
|
||||||
{data.map((item, index) => (
|
{data.map((item, index) => (
|
||||||
|
<ScrollReveal preset="slideUp" delay={index * 0.1} key={item.year}>
|
||||||
<TimelineItemRow
|
<TimelineItemRow
|
||||||
key={item.year}
|
key={item.year}
|
||||||
item={item}
|
item={item}
|
||||||
|
|
@ -148,6 +150,7 @@ function HistoryTimeline({ data, selectedYear, onYearChange }: HistoryTimelinePr
|
||||||
isSelected={selectedYear === item.year}
|
isSelected={selectedYear === item.year}
|
||||||
onMouseEnter={() => onYearChange(item.year)}
|
onMouseEnter={() => onYearChange(item.year)}
|
||||||
/>
|
/>
|
||||||
|
</ScrollReveal>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -70,7 +70,7 @@
|
||||||
|
|
||||||
.twoColImage {
|
.twoColImage {
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
background: linear-gradient(135deg, #e8e8e8 0%, #d0d0d0 100%);
|
background: #f0f2f4;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
|
@ -266,6 +266,7 @@
|
||||||
background: #14355C;
|
background: #14355C;
|
||||||
border-color: #14355C;
|
border-color: #14355C;
|
||||||
color: #FFFFFF;
|
color: #FFFFFF;
|
||||||
|
border: 1px solid #FFFFFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ import ParagraphSection from "@/components/layout/ParagraphSection";
|
||||||
import Section from "@/components/layout/Section";
|
import Section from "@/components/layout/Section";
|
||||||
import TopTabs from "@/components/layout/TopTabsSection/TopTabs";
|
import TopTabs from "@/components/layout/TopTabsSection/TopTabs";
|
||||||
import SectionTitle from "@/components/layout/SectionTitle";
|
import SectionTitle from "@/components/layout/SectionTitle";
|
||||||
|
import ScrollReveal from "@/components/ScrollReveal";
|
||||||
|
|
||||||
const FALLBACK_GRADIENT = "linear-gradient(135deg, #1a2a4a 0%, #2d4a7c 100%)";
|
const FALLBACK_GRADIENT = "linear-gradient(135deg, #1a2a4a 0%, #2d4a7c 100%)";
|
||||||
|
|
||||||
|
|
@ -19,8 +20,8 @@ export default function BusinessCommercialGroup() {
|
||||||
const { viewDetail = "查看详情" } = appConfig?.__global__?.others
|
const { viewDetail = "查看详情" } = appConfig?.__global__?.others
|
||||||
const data = appConfig?.business?.commercialGroup;
|
const data = appConfig?.business?.commercialGroup;
|
||||||
const section3Data = data?.section3Data;
|
const section3Data = data?.section3Data;
|
||||||
|
const section4Data = data?.section4Data;
|
||||||
|
|
||||||
const [in77ImgError, setIn77ImgError] = useState(false);
|
|
||||||
const [activeTabIndex, setActiveTabIndex] = useState(0);
|
const [activeTabIndex, setActiveTabIndex] = useState(0);
|
||||||
const [activeFeaturesTabIndex, setActiveFeaturesTabIndex] = useState(0);
|
const [activeFeaturesTabIndex, setActiveFeaturesTabIndex] = useState(0);
|
||||||
|
|
||||||
|
|
@ -102,19 +103,20 @@ export default function BusinessCommercialGroup() {
|
||||||
<TopTabs className={styles.twoColSectionTabs} data={section2Data} activeIndex={activeTabIndex} setActiveIndex={setActiveTabIndex} />
|
<TopTabs className={styles.twoColSectionTabs} data={section2Data} activeIndex={activeTabIndex} setActiveIndex={setActiveTabIndex} />
|
||||||
<div className={styles.twoColSectionContent}>
|
<div className={styles.twoColSectionContent}>
|
||||||
<div className={styles.twoColImage}>
|
<div className={styles.twoColImage}>
|
||||||
{in77ImgError ? (
|
{(
|
||||||
<PlaceholderImage />
|
<ScrollReveal preset="slideRight" duration={1}>
|
||||||
) : (
|
|
||||||
<img
|
<img
|
||||||
src={section2Data.tabItems[activeTabIndex]?.sideImage as string}
|
src={section2Data.tabItems[activeTabIndex]?.sideImage as string}
|
||||||
alt=""
|
alt=""
|
||||||
onError={() => setIn77ImgError(true)}
|
|
||||||
style={{ width: "100%", height: "800px" }}
|
style={{ width: "100%", height: "800px" }}
|
||||||
/>
|
/>
|
||||||
|
</ScrollReveal>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div className={styles.twoColText}>
|
<div className={styles.twoColText}>
|
||||||
|
<ScrollReveal preset="slideUp" delay={0.5} >
|
||||||
<p className={styles.twoColDesc} dangerouslySetInnerHTML={{ __html: section2Data.tabItems[activeTabIndex]?.content ?? "" }}></p>
|
<p className={styles.twoColDesc} dangerouslySetInnerHTML={{ __html: section2Data.tabItems[activeTabIndex]?.content ?? "" }}></p>
|
||||||
|
</ScrollReveal>
|
||||||
<Link
|
<Link
|
||||||
to={section2Data.tabItems[activeTabIndex]?.path ?? "#"}
|
to={section2Data.tabItems[activeTabIndex]?.path ?? "#"}
|
||||||
className={styles.btnPrimary}
|
className={styles.btnPrimary}
|
||||||
|
|
@ -148,8 +150,12 @@ export default function BusinessCommercialGroup() {
|
||||||
</div>
|
</div>
|
||||||
<SectionTitle color="#fff" title={section3Data.title} subcontent={section3Data.content} />
|
<SectionTitle color="#fff" title={section3Data.title} subcontent={section3Data.content} />
|
||||||
<div className={styles.featuresHeroContent}>
|
<div className={styles.featuresHeroContent}>
|
||||||
|
<ScrollReveal preset="slideUp" >
|
||||||
<div className={styles.featuresHeroContentTitle}>{section3Data.tabItems[activeFeaturesTabIndex]?.tabName}</div>
|
<div className={styles.featuresHeroContentTitle}>{section3Data.tabItems[activeFeaturesTabIndex]?.tabName}</div>
|
||||||
|
</ScrollReveal>
|
||||||
|
<ScrollReveal preset="slideUp" >
|
||||||
<div className={styles.featuresHeroContentDesc}>{section3Data.tabItems[activeFeaturesTabIndex]?.content}</div>
|
<div className={styles.featuresHeroContentDesc}>{section3Data.tabItems[activeFeaturesTabIndex]?.content}</div>
|
||||||
|
</ScrollReveal>
|
||||||
</div>
|
</div>
|
||||||
<div ref={featuresHeroTabsRef} className={styles.featuresHeroTabs}>
|
<div ref={featuresHeroTabsRef} className={styles.featuresHeroTabs}>
|
||||||
<div
|
<div
|
||||||
|
|
@ -184,11 +190,13 @@ export default function BusinessCommercialGroup() {
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div className={styles.propertyServicesContent}>
|
<div className={styles.propertyServicesContent}>
|
||||||
<div className={styles.propertyServicesTitle}>物业服务</div>
|
<div className={styles.propertyServicesTitle}>{section4Data?.title}</div>
|
||||||
<p className={styles.propertyServicesSubtitle}>国内一流物业服务品牌</p>
|
<p className={styles.propertyServicesSubtitle}>{section4Data?.content}</p>
|
||||||
<Link to="/property-service" className={styles.propertyServicesBtn}>
|
<ScrollReveal preset="slideUp" className={styles.propertyServicesBtn}>
|
||||||
|
<Link to={section4Data?.path ?? "#"} >
|
||||||
{viewDetail}
|
{viewDetail}
|
||||||
</Link>
|
</Link>
|
||||||
|
</ScrollReveal>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue