This commit is contained in:
zhangjianjun 2026-03-05 09:42:49 +08:00
parent 4f3cd4d890
commit f32745850e
86 changed files with 3953 additions and 406 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 606 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 680 B

View File

@ -24,7 +24,7 @@
work correctly both with client-side routing and a non-root public URL. work correctly both with client-side routing and a non-root public URL.
Learn how to configure a non-root public URL by running `npm run build`. Learn how to configure a non-root public URL by running `npm run build`.
--> -->
<title>加载中...</title> <title>银泰</title>
</head> </head>
<body> <body>
<noscript>You need to enable JavaScript to run this app.</noscript> <noscript>You need to enable JavaScript to run this app.</noscript>

View File

@ -1,7 +1,9 @@
* { * {
box-sizing: border-box; box-sizing: border-box;
&:not(p) {
margin: 0; margin: 0;
padding: 0; padding: 0;
}
} }
a { a {
text-decoration: none; text-decoration: none;
@ -51,8 +53,7 @@ ul, li {
} }
.page{ .page{
height: 100vh; /* overflow-x: hidden; */
overflow-x: hidden;
overflow-y: auto; overflow-y: auto;
} }
@ -91,9 +92,10 @@ ul, li {
} }
body { body {
overflow-x: hidden; /* overflow-x: hidden; */
background: #f0f2f4; /* background: #f0f2f4; */
font-family: Source Han Sans, Source Han Sans; font-family: Source Han Sans, Source Han Sans;
color: #222222;
} }
/* Layout: header + container + footer */ /* Layout: header + container + footer */

View File

@ -30,12 +30,9 @@ function App() {
const getAppConfig = useCallback(async () => { const getAppConfig = useCallback(async () => {
try { try {
let res = await appApi.getAppConfig(); let res = await appApi.getAppConfig();
console.log('-------res', res)
let data = res.data; let data = res.data;
try {
data.company.config = JSON.parse(data.company.config)
} catch (error) {
console.log(error)
}
store.setItem("appConfig", data); store.setItem("appConfig", data);
initState(data) initState(data)
} catch (error) { } catch (error) {
@ -48,7 +45,7 @@ function App() {
if (init) { if (init) {
return; return;
} }
// getAppConfig(); getAppConfig();
}, []) }, [])
return ( return (

View File

@ -5,23 +5,25 @@ import type { RouteObject } from "react-router-dom";
import About from "@/pages/About/index"; import About from "@/pages/About/index";
import AboutHistory from "@/pages/About/History"; import AboutHistory from "@/pages/About/History";
import AboutFounder from "@/pages/About/Founder"; import AboutFounder from "@/pages/About/Founder";
import Business from "@/pages/Business/index";
import BusinessCommercialGroup from "@/pages/Business/CommercialGroup"; import BusinessCommercialGroup from "@/pages/Business/CommercialGroup";
import BusinessCommercialGroupDetail from "@/pages/Business/CommercialGroupDetail"; import BusinessCommercialGroupDetail from "@/pages/Business/CommercialGroupDetail";
import BusinessBaseGroup from "@/pages/Business/BaseGroup"; import BusinessBaseGroup from "@/pages/Business/BaseGroup";
import BusinessRealtyGroup from "@/pages/Business/RealtyGroup"; import BusinessRealtyGroup from "@/pages/Business/RealtyGroup";
import BusinessInvestGroup from "@/pages/Business/InvestGroup"; import BusinessInvestGroup from "@/pages/Business/InvestGroup";
import BusinessRujingGroup from "@/pages/Business/RujingGroup"; import BusinessRujingGroup from "@/pages/Business/RuijingGroup";
import Social from "@/pages/Social/index";
import SocialSustainability from "@/pages/Social/Sustainability"; import SocialSustainability from "@/pages/Social/Sustainability";
import SocialFoundation from "@/pages/Social/Foundation"; import SocialFoundation from "@/pages/Social/Foundation";
import News from "@/pages/News/index"; import NewsPublic from "@/pages/News/NewsPublic";
import NewsConsult from "@/pages/News/Consult";
import NewsMedia from "@/pages/News/Media"; import NewsMedia from "@/pages/News/Media";
import Join from "@/pages/Join/index"; import NewsDetail from "@/pages/News/Detail";
import JoinCulture from "@/pages/Join/Culture"; import JoinCulture from "@/pages/Join/Culture";
import JoinCampus from "@/pages/Join/Campus"; import JoinCampus from "@/pages/Join/Campus";
import JoinCampusDetail from "@/pages/Join/CampusDetail";
import PropertyService from "@/pages/PropertyService/index"; import PropertyService from "@/pages/PropertyService/index";
import TermsOfUse from "@/pages/Others/TermsOfUse";
import PrivacyPolicy from "@/pages/Others/PrivacyPolicy";
import AuditReport from "@/pages/Others/AuditReport";
import SiteMap from "@/pages/Others/SiteMap";
const routes: RouteObject[] = [ const routes: RouteObject[] = [
{ {
@ -34,7 +36,6 @@ const routes: RouteObject[] = [
{ path: "about/history", element: <AboutHistory /> }, { path: "about/history", element: <AboutHistory /> },
{ path: "about/founder", element: <AboutFounder /> }, { path: "about/founder", element: <AboutFounder /> },
// 集团业务 // 集团业务
{ path: "business", element: <Business /> },
{ path: "business/commercial-group", element: <BusinessCommercialGroup /> }, { path: "business/commercial-group", element: <BusinessCommercialGroup /> },
{ path: "business/commercial-group/:detailType", element: <BusinessCommercialGroupDetail /> }, { path: "business/commercial-group/:detailType", element: <BusinessCommercialGroupDetail /> },
{ path: "business/base-group", element: <BusinessBaseGroup /> }, { path: "business/base-group", element: <BusinessBaseGroup /> },
@ -42,20 +43,24 @@ const routes: RouteObject[] = [
{ path: "business/invest-group", element: <BusinessInvestGroup /> }, { path: "business/invest-group", element: <BusinessInvestGroup /> },
{ path: "business/ruijing-group", element: <BusinessRujingGroup /> }, { path: "business/ruijing-group", element: <BusinessRujingGroup /> },
// 社会责任 // 社会责任
{ path: "social", element: <Social /> },
{ path: "social/sustainability", element: <SocialSustainability /> }, { path: "social/sustainability", element: <SocialSustainability /> },
{ path: "social/foundation", element: <SocialFoundation /> }, { path: "social/foundation", element: <SocialFoundation /> },
// 新闻中心 // 新闻中心
{ path: "news", element: <News /> }, { path: "news/public", element: <NewsPublic /> },
{ path: "news/consult", element: <NewsConsult /> },
{ path: "news/media", element: <NewsMedia /> }, { path: "news/media", element: <NewsMedia /> },
{ path: "news/detail/:id", element: <NewsDetail /> },
// 加入银泰 // 加入银泰
{ path: "join", element: <Join /> },
{ path: "join/culture", element: <JoinCulture /> }, { path: "join/culture", element: <JoinCulture /> },
{ path: "join/campus", element: <JoinCampus /> }, { path: "join/campus", element: <JoinCampus /> },
{ path: "join/campus/detail/:id", element: <JoinCampusDetail /> },
// 物业服务 // 物业服务
{ path: "property-service", element: <PropertyService /> }, { path: "/property-service", element: <PropertyService /> },
// 其它
// 使用条款 隐私保护 审计举报 网站地图
{ path: "/terms-of-use", element: <TermsOfUse /> },
{ path: "/privacy-policy", element: <PrivacyPolicy /> },
{ path: "/audit-report", element: <AuditReport /> },
{ path: "/site-map", element: <SiteMap /> },
], ],
}, },
{ {

View File

@ -1,11 +1,12 @@
import requests from "@/utils/request"; import requests from "@/utils/request";
import mockData from "./mockData"
const app = { const app = {
getAppConfig() { getAppConfig() {
return requests({ // return requests({
url: "/api/config", // url: "/api/config",
method: "get", // method: "get",
}); // });
return Promise.resolve({data: mockData});
}, },
getJobList(params: any) { getJobList(params: any) {
return requests({ return requests({

6
src/api/mockData.ts Normal file
View File

@ -0,0 +1,6 @@
const mockData = {
companyName: "银泰"
}
export default mockData;

View File

@ -10,9 +10,32 @@
justify-content: flex-end; justify-content: flex-end;
} }
.bgSwiper {
position: absolute;
inset: 0;
z-index: 0;
width: 100%;
height: 100%;
}
.bgSwiper :global(.swiper-slide) {
height: 100%;
}
.bgSlide {
position: absolute;
inset: 0;
width: 100%;
height: 100%;
background-size: cover;
background-position: center;
}
.heroOverlay { .heroOverlay {
position: absolute; position: absolute;
inset: 0; inset: 0;
z-index: 1;
pointer-events: none;
background: linear-gradient( background: linear-gradient(
to right, to right,
rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0.5) 0%,

View File

@ -0,0 +1,67 @@
.wrapper {
display: flex;
align-items: center;
justify-content: center;
gap: 8px;
flex-wrap: wrap;
}
.item,
.itemActive,
.arrow {
width: 45px;
height: 45px;
display: inline-flex;
align-items: center;
justify-content: center;
border-radius: 5px;
border: 1px solid #e0e0e0;
background: #fff;
color: #222;
font-size: 14px;
font-weight: 500;
font-family: inherit;
cursor: pointer;
transition: background-color 0.25s ease-in-out, color 0.25s ease-in-out, border-color 0.25s ease-in-out, opacity 0.25s ease-in-out;
}
.item:hover:not(:disabled),
.arrow:hover:not(:disabled) {
background: #e8e8e8;
}
.itemActive {
background: #14355c;
color: #ffffff;
border-color: #14355c;
}
.itemActive:hover {
background: #14355c;
color: #ffffff;
}
.arrow {
padding: 0;
}
.arrow:disabled {
cursor: not-allowed;
color: #dbdbdb;
background: #fff;
opacity: 0.7;
transition: background-color 0.25s ease-in-out, color 0.25s ease-in-out, opacity 0.25s ease-in-out;
}
.ellipsis {
width: 45px;
height: 45px;
font-weight: 400;
font-size: 20px;
color: rgba(0, 0, 0, 0.25);
line-height: 45px;
letter-spacing: 2px;
text-align: center;
font-style: normal;
text-transform: none;
}

View File

@ -0,0 +1,87 @@
import styles from "./index.module.css";
import { LeftOutlined, RightOutlined } from "@ant-design/icons";
type Props = {
total: number;
size: number; // 每页条数
page: number; // 当前页码
onChange: (page: number) => void;
};
function getPageItems(current: number, totalPages: number): (number | "...")[] {
if (totalPages <= 1) return [1];
if (totalPages <= 7) {
return Array.from({ length: totalPages }, (_, i) => i + 1);
}
const result: (number | "...")[] = [1];
if (current > 3) {
result.push("...");
}
const start = Math.max(2, current - 2);
const end = Math.min(totalPages - 1, current + 2);
for (let i = start; i <= end; i++) {
result.push(i);
}
if (current < totalPages - 2) {
result.push("...");
}
if (totalPages > 1 && result[result.length - 1] !== totalPages) {
result.push(totalPages);
}
return result;
}
export default function Pagination({ total, size, page, onChange }: Props) {
const totalPages = Math.max(1, Math.ceil(total / size));
const currentPage = Math.min(Math.max(1, page), totalPages);
const pageItems = getPageItems(currentPage, totalPages);
if (totalPages <= 1 && total <= 0) {
return null;
}
return (
<div className={styles.wrapper}>
<button
type="button"
className={styles.arrow}
disabled={currentPage <= 1}
onClick={() => onChange(currentPage - 1)}
aria-label="上一页"
>
<LeftOutlined />
</button>
{pageItems.map((item, index) =>
item === "..." ? (
<span key={`ellipsis-${index}`} className={styles.ellipsis}>
</span>
) : (
<button
key={item}
type="button"
className={currentPage === item ? styles.itemActive : styles.item}
onClick={() => onChange(item)}
>
{item}
</button>
)
)}
<button
type="button"
className={styles.arrow}
disabled={currentPage >= totalPages}
onClick={() => onChange(currentPage + 1)}
aria-label="下一页"
>
<RightOutlined />
</button>
</div>
);
}

View File

@ -1,5 +1,10 @@
import { Link } from "react-router-dom"; import { Link } from "react-router-dom";
import { Swiper, SwiperSlide } from "swiper/react";
import { Autoplay, EffectFade } from "swiper/modules";
import "swiper/css";
import "swiper/css/effect-fade";
import styles from "./Banner.module.css"; import styles from "./Banner.module.css";
const FALLBACK_GRADIENT = "linear-gradient(135deg, #1a2a4a 0%, #2d4a7c 100%)"; const FALLBACK_GRADIENT = "linear-gradient(135deg, #1a2a4a 0%, #2d4a7c 100%)";
type BreadcrumbItem = { label: string; to: string }; type BreadcrumbItem = { label: string; to: string };
@ -12,31 +17,74 @@ type Props = {
showBreadcrumb?: boolean; showBreadcrumb?: boolean;
breadcrumbItems?: BreadcrumbItem[]; breadcrumbItems?: BreadcrumbItem[];
titleSize?: "large" | "medium"; titleSize?: "large" | "medium";
backgroundImage: string; backgroundImage: string | string[];
} };
export default function Banner({ title, subtitle, desc, largedesc, showBreadcrumb, breadcrumbItems, titleSize = "large", backgroundImage }: Props) {
return ( export default function Banner({
<section title,
className={styles.hero} subtitle,
style={{ desc,
backgroundImage: `url(${backgroundImage}), ${FALLBACK_GRADIENT}`, largedesc,
}} showBreadcrumb,
> breadcrumbItems,
<div className={styles.heroOverlay} /> titleSize = "large",
<div className={styles.heroContent} style={{gap: '30px'}}> backgroundImage,
}: Props) {
const images = Array.isArray(backgroundImage) ? backgroundImage : [backgroundImage];
const isCarousel = images.length > 1;
console.log('isCarousel', isCarousel)
const heroContent = (
<div className={styles.heroContent} style={{ gap: "30px" }}>
<h1 className={`${styles.heroTitle} ${titleSize === "medium" ? styles.heroTitleMedium : ""}`}>{title}</h1> <h1 className={`${styles.heroTitle} ${titleSize === "medium" ? styles.heroTitleMedium : ""}`}>{title}</h1>
{subtitle && <h2 className={styles.heroSubtitle}>{subtitle}</h2>} {subtitle && <h2 className={styles.heroSubtitle}>{subtitle}</h2>}
{desc && <p className={styles.heroDesc}>{desc}</p>} {desc && <p className={styles.heroDesc}>{desc}</p>}
{largedesc && <p className={styles.heroLargeDesc}>{largedesc}</p>} {largedesc && <p className={styles.heroLargeDesc}>{largedesc}</p>}
<div className={styles.breadcrumb}> <div className={styles.breadcrumb}>
{showBreadcrumb && (breadcrumbItems ?? []).map((item, i) => ( {showBreadcrumb &&
(breadcrumbItems ?? []).map((item, i) => (
<span key={i}> <span key={i}>
{i > 0 && <span>{' > '}</span>} {i > 0 && <span>{" > "}</span>}
{item.to ? <Link to={item.to}>{item.label}</Link> : <span>{item.label}</span>} {item.to ? <Link to={item.to}>{item.label}</Link> : <span>{item.label}</span>}
</span> </span>
))} ))}
</div> </div>
</div> </div>
);
return (
<section
className={styles.hero}
style={
isCarousel
? undefined
: { backgroundImage: `url(${images[0]}), ${FALLBACK_GRADIENT}` }
}
>
{isCarousel && (
<Swiper
className={styles.bgSwiper}
modules={[Autoplay, EffectFade]}
effect="slide"
autoplay={{ delay: 3000, disableOnInteraction: false }}
allowTouchMove={false}
slidesPerView={1}
loop={true}
>
{images.map((img, i) => (
<SwiperSlide key={i}>
<div
className={styles.bgSlide}
style={{
backgroundImage: `url(${img}), ${FALLBACK_GRADIENT}`,
}}
/>
</SwiperSlide>
))}
</Swiper>
)}
<div className={styles.heroOverlay} />
{heroContent}
</section> </section>
) );
} }

View File

@ -0,0 +1,130 @@
.card {
background-size: cover;
background-position: center;
background-repeat: no-repeat;
.cardMask {
position: absolute;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.1);
}
&:hover {
.cardInner {
top: 0;
background: rgba(20, 53, 92, 0.9);
justify-content: flex-start;
transition-delay: 0s;
.cardTitle span {
left: 30px;
transform: translateX(0);
transition-delay: 0s;
}
}
.cardContent {
opacity: 1;
transition: opacity 0.3s ease 0.3s;
}
.cardTitleUnderline::before {
left: 30px;
transform: translateX(0);
transition-delay: 0s;
}
}
.cardInner {
padding: 50px;
width: 100%;
height: 100%;
background: transparent;
transition: all 0.3s ease;
transition-delay: 0.2s;
position: absolute;
top: calc(100% - 170px);
}
.cardTitle {
position: relative;
font-weight: 500;
font-size: 24px;
color: #FFFFFF;
height: 34px;
line-height: 34px;
font-style: normal;
text-transform: none;
padding: 0 30px;
span {
transition: all 0.3s ease;
transition-delay: 0.2s;
position: absolute;
left: 50%;
transform: translateX(-50%);
}
}
.cardTitleUnderline {
position: relative;
width: 100%;
height: 1px;
background: rgba(255,255,255,0.3);
margin-top: 30px;
&::before {
content: '';
display: block;
width: 300px;
height: 3px;
background: rgba(255,255,255,1);
position: absolute;
left: 50%;
top: -1px;
transform: translateX(-50%);
transition: all 0.3s ease;
transition-delay: 0.2s;
}
}
.cardContent {
margin-top: 20px;
padding: 0 30px;
font-weight: 400;
font-size: 18px;
color: #FFFFFF;
line-height: 34px;
text-align: justify;
font-style: normal;
text-transform: none;
opacity: 0;
transition: opacity 0.2s ease 0s;
.cardMore {
display: inline-block;
margin-top: 60px;
width: 104px;
height: 38px;
border-radius: 0px 0px 0px 0px;
border: 1px solid #FFFFFF;
font-weight: 400;
font-size: 16px;
color: #FFFFFF;
line-height: 22px;
text-align: center;
display: flex;
align-items: center;
justify-content: center;
&:hover {
background: #FFFFFF;
color: #14355C;
}
}
}
}

View File

@ -0,0 +1,24 @@
import styles from './index.module.css';
import { Link } from 'react-router-dom';
type Data = {
title: string;
content: string;
backgroundImage: string;
link: string;
}
export default function AnimateTopCard({ data }: { data: Data }) {
return (
<div className={styles.card} style={{ backgroundImage: `url(${data.backgroundImage})` }}>
<div className={styles.cardMask}></div>
<div className={styles.cardInner}>
<div className={styles.cardTitle}><span>{data.title}</span></div>
<div className={styles.cardTitleUnderline}></div>
<div className={styles.cardContent}>
<div>{data.content}</div>
<Link to={data.link} className={styles.cardMore}></Link>
</div>
</div>
</div>
);
}

View File

@ -0,0 +1,50 @@
.article {
width: 100%;
min-height: 100vh;
padding: 120px 100px;
.articleHeaderLine {
height: 100px;
border-bottom: 1px solid #222222;
display: flex;
.articleHeaderLineBack {
display: inline-flex;
align-items: center;
cursor: pointer;
}
}
.articleHeader {
padding: 60px 0;
margin-bottom: 60px;
.articleHeaderTitle {
font-weight: 700;
font-size: 32px;
color: #222222;
line-height: 42px;
text-align: center;
font-style: normal;
text-transform: none;
margin-bottom: 20px;
}
.articleHeaderTimeLine {
font-weight: 400;
font-size: 16px;
color: #666666;
line-height: 22px;
text-align: left;
font-style: normal;
text-transform: none;
display: flex;
gap: 40px;
}
}
.articleContent {
font-size: 20px;
}
}

View File

@ -0,0 +1,32 @@
import styles from "./index.module.css";
type Data = {
title: string;
createTime: string;
readTimes: string;
content: string;
}
export default function Article({ data }: { data: Data }) {
return (
<div className={styles.article}>
<div className={styles.articleHeaderLine}>
<div className={styles.articleHeaderLineBack} onClick={() => window.history.back()}>
<img src="/images/icon-arrowleft.png" alt="arrowleft" style={{ width: "20px", height: "20px" }} />
<span></span>
</div>
</div>
<div className={styles.articleHeader}>
<div className={styles.articleHeaderTitle}>{data.title}</div>
<div className={styles.articleHeaderTimeLine}>
<span className={styles.articleHeaderTime}>{data.createTime}</span>
<span className={styles.articleHeaderReadTimes}>{data.readTimes}</span>
</div>
</div>
<div className={styles.articleContent}>
<div className={styles.articleContentText} dangerouslySetInnerHTML={{ __html: data.content }}></div>
</div>
</div>
)
}

View File

@ -0,0 +1,20 @@
import { useState } from "react";
import styles from "./index.module.css";
type TabItems = {
tabName: string;
[key: string]: any;
}[]
export default function BottomTabs({ tabItems, activeIndex, setActiveIndex }: { tabItems: TabItems, activeIndex: number, setActiveIndex: (index: number) => void }) {
return (
<div className={styles.bottomTabsSectionContentTabs}>
{tabItems.map((item, i) => (
<div key={i} className={`${styles.bottomTabsSectionContentTab} ${activeIndex === i ? styles.active : ''}`} onClick={() => setActiveIndex(i)}>
<span>{item.tabName}</span>
</div>
))}
</div>
)
}

View File

@ -0,0 +1,67 @@
.bottomTabsSection {
width: 100%;
/* height: 1080px; */
height: 100vh;
padding: 100px 260px;
background-size: cover;
background-position: center;
background-repeat: no-repeat;
color: #fff;
box-sizing: border-box;
}
/* Features Section */
.bottomTabsSectionContent {
width: 100%;
height: 500px;
margin-top: 200px;
display: flex;
flex-direction: column;
justify-content: space-between;
}
.bottomTabsSectionContentContent {
width: 100%;
color: #FFFFFF;
.contentTitle {
font-weight: 500;
font-size: 30px;
line-height: 40px;
}
.contentText {
font-weight: 400;
font-size: 18px;
line-height: 26px;
margin-top: 20px;
}
}
.bottomTabsSectionContentTabs {
display: flex;
flex-direction: row;
justify-content: center;
gap: auto;
border-top: 1px solid rgba(255,255,255,0.5);
padding: 0 200px;
}
.bottomTabsSectionContentTab {
flex: 1;
font-weight: 500;
font-size: 20px;
color: #FFFFFF;
line-height: 60px;
height: 60px;
cursor: pointer;
span {
display: inline-block;
line-height: 60px;
height: 60px;
}
}
.bottomTabsSectionContentTab.active span {
border-top: 2px solid #FFFFFF;
}

View File

@ -0,0 +1,31 @@
import styles from './index.module.css';
import SectionTitle from '../SectionTitle';
import { useState } from 'react';
import BottomTabs from './BottomTabs';
type Data = {
title: string;
tabItems: {
tabName: string;
contentTitle: string;
contentText: string;
image: string;
}[]
}
export default function BottomTabsSection({ data }: { data: Data }) {
const [activeIndex, setActiveIndex] = useState(0);
return (
<div className={styles.bottomTabsSection} style={{ backgroundImage: `url(${data.tabItems[activeIndex].image})` }}>
<SectionTitle title={data.title} color="#fff" />
<div className={styles.bottomTabsSectionContent}>
<div className={styles.bottomTabsSectionContentContent}>
<div className={styles.contentTitle}>{data.tabItems[activeIndex].contentTitle}</div>
<div className={styles.contentText}>{data.tabItems[activeIndex].contentText}</div>
</div>
<BottomTabs tabItems={data.tabItems} activeIndex={activeIndex} setActiveIndex={setActiveIndex} />
</div>
</div>
)
}

View File

@ -0,0 +1,59 @@
.columnXGrids {
/* 3列 */
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 30px;
.columnXGridsItem {
color: #fff;
aspect-ratio: 446/430;
background-size: cover;
background-position: center;
background-repeat: no-repeat;
position: relative;
overflow: hidden;
.mask {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.2);
}
.columnXGridsItemInner {
position: absolute;
width: 100%;
height: 100%;
z-index: 2;
padding: 60px 40px;
transition: background 0.3s ease;
&:hover {
background: rgba(20,53,92,0.7);
.columnXGridsItemContent {
opacity: 1;
}
}
.columnXGridsItemTitle {
font-weight: 500;
font-size: 24px;
color: #FFFFFF;
line-height: 34px;
margin-bottom: 10px;
}
.columnXGridsItemContent {
font-weight: 500;
font-size: 18px;
color: #FFFFFF;
line-height: 34px;
opacity: 0;
transition: opacity 0.3s ease;
}
}
}
}

View File

@ -0,0 +1,25 @@
import styles from "./index.module.css";
type Props = {
items: {
title: string;
content: string;
backgroundImage: string;
}[];
}
export default function ColumnXGrids({ items }: Props) {
return (
<div className={styles.columnXGrids}>
{items.map((item, index) => (
<div key={index} className={styles.columnXGridsItem} style={{ backgroundImage: `url(${item.backgroundImage})` }}>
<div className={styles.mask}></div>
<div className={styles.columnXGridsItemInner}>
<div className={styles.columnXGridsItemTitle}>{item.title}</div>
<div className={styles.columnXGridsItemContent}>{item.content}</div>
</div>
</div>
))}
</div>
)
}

View File

@ -0,0 +1,38 @@
.honorGrids {
width: 100%;
padding: 100px 300px;
background: rgba(216,216,216,0.5);
.honorGridsTitle {
font-family: Source Han Sans, Source Han Sans;
font-weight: 700;
font-size: 40px;
color: #222222;
line-height: 50px;
margin-bottom: 100px;
text-align: center;
}
.honorGridsItems {
/* 4*n */
display: grid;
grid-template-columns: repeat(4, 1fr);
grid-template-rows: repeat(2, 1fr);
gap: 60px;
.honorGridsItem {
height: 116px;
display: flex;
align-items: center;
justify-content: center;
border: 1px solid #666;
.honorGridsTitle {
font-weight: 400;
font-size: 20px;
color: #222222;
line-height: 30px;
}
}
}
}

View File

@ -0,0 +1,23 @@
import styles from './index.module.css';
type Data = {
title: string;
items: {
title: string;
}[];
}
export default function HonorGrids({ data }: {data: Data}) {
return (
<section className={styles.honorGrids}>
<div className={styles.honorGridsTitle}>{data.title}</div>
<div className={styles.honorGridsItems}>
{data.items.map((item) => (
<div className={styles.honorGridsItem} key={item.title}>
<div className={styles.honorGridsItemTitle}>{item.title}</div>
</div>
))}
</div>
</section>
)
}

View File

@ -0,0 +1,47 @@
.jobPage {
width: 100%;
min-height: 100vh;
padding: 120px 100px;
.jobPageHeaderLine {
height: 100px;
border-bottom: 1px solid #222222;
display: flex;
.jobPageHeaderLineBack {
display: inline-flex;
align-items: center;
cursor: pointer;
}
}
.jobPageHeader {
padding: 60px 160px;
.jobPageHeaderTitle {
font-weight: 700;
font-size: 32px;
color: #222222;
line-height: 42px;
/* text-align: center; */
font-style: normal;
text-transform: none;
margin-bottom: 20px;
}
.jobPageHeaderTimeLine {
font-weight: 400;
font-size: 20px;
color: #333333;
line-height: 30px;
display: flex;
gap: 30px;
}
}
.jobPageContent {
font-size: 20px;
padding: 0 160px;
}
}

View File

@ -0,0 +1,38 @@
import styles from "./index.module.css";
type Data = {
title: string;
jobType: string;
businessArea: string;
businessPlate: string;
recruitNumber: string;
jobLocation: string;
content: string;
}
export default function JobPage({ data }: { data: Data }) {
return (
<div className={styles.jobPage}>
<div className={styles.jobPageHeaderLine}>
<div className={styles.jobPageHeaderLineBack} onClick={() => window.history.back()}>
<img src="/images/icon-arrowleft.png" alt="arrowleft" style={{ width: "20px", height: "20px" }} />
<span></span>
</div>
</div>
<div className={styles.jobPageHeader}>
<div className={styles.jobPageHeaderTitle}>{data.title}</div>
<div className={styles.jobPageHeaderTimeLine}>
<span>{data.jobType}</span>
<span>{data.businessArea}</span>
<span>{data.businessPlate}</span>
<span>{data.recruitNumber}</span>
<span>{data.jobLocation}</span>
</div>
</div>
<div className={styles.jobPageContent}>
<div className={styles.jobPageContentText} dangerouslySetInnerHTML={{ __html: data.content }}></div>
</div>
</div>
)
}

View File

@ -0,0 +1,21 @@
.paragraphSection {
padding: 100px 260px;
background: rgba(255, 255, 255, 0.8);
background-size: cover;
background-position: center;
background-repeat: repeat;
}
.paragraphSectionContent {
white-space: pre-line;
.paragraphSectionTitle {
font-weight: 500;
font-size: 40px;
color: #14355C;
line-height: 50px;
text-align: left;
font-style: normal;
text-transform: none;
}
}

View File

@ -0,0 +1,22 @@
import StatsRow from '../StatsRow/StatsRow';
import styles from './index.module.css';
type Data = {
title: string;
content: string;
statsData?: { num: string; label: string }[];
backgroundImage?: string;
}
export default function ParagraphSection({ data, children }: {data: Data, children?: React.ReactNode}) {
return (
<section className={styles.paragraphSection} style={{ backgroundImage: `url(${data.backgroundImage})` }}>
<div className={`${styles.paragraphSectionContent} normal-p`}>
<p><span className={styles.paragraphSectionTitle}>{data.title}</span>{data.content}</p>
</div>
{data.statsData && <StatsRow data={data.statsData} />}
{children}
</section>
)
}

View File

@ -0,0 +1,141 @@
:root {
--duration: 0.4s;
}
.rowAccordion {
position: relative;
overflow-anchor: none;
padding: 0 260px;
width: 100%;
height: 100vh;
}
.rowAccordionBgContainer {
position: absolute;
inset: 0;
z-index: 0;
}
.rowAccordionBgLayer {
position: absolute;
inset: 0;
background-size: cover;
background-position: center;
background-repeat: no-repeat;
transition: opacity var(--duration) ease;
}
.rowAccordion .headerRow,
.rowAccordion .contentRow {
position: relative;
z-index: 1;
}
.rowAccordion {
.headerRow {
width: 100%;
height: 250px;
display: flex;
align-items: center;
justify-content: center;
.title {
font-weight: 700;
font-size: 40px;
color: #FFFFFF;
line-height: 50px;
}
}
.contentRow {
height: 100%;
display: flex;
color: #fff;
.contentItem {
flex: 1;
transition: flex var(--duration) ease, padding-bottom var(--duration) ease;
display: flex;
flex-direction: column;
justify-content: flex-end;
padding-top: 100px;
padding-bottom: 100px;
border-left: 1px solid #fff;
&:last-child {
border-right: 1px solid #fff;
}
.contentItemContainer {
padding: 0 20px;
min-height: 100px;
display: flex;
flex-direction: column;
justify-content: center;
margin-left: -3px;
transition: all var(--duration) ease-in-out;
position: relative;
&::before {
content: '';
position: absolute;
left: 0;
top: 0;
width: 5px;
height: 100px;
background: #14355C;
}
}
.contentItemTitle {
height: 100px;
font-weight: 500;
font-size: 24px;
color: #FFFFFF;
transition: all var(--duration) ease-in-out;
margin-bottom: 6px;
display: flex;
align-items: center;
}
.contentItemSubtitle {
font-size: 20px;
transition: font-size var(--duration) ease-in-out;
}
.contentItemContentWrapper {
height: 0;
opacity: 0;
transition: all var(--duration) ease-in-out;
overflow: hidden;
display: flex;
flex-direction: column;
justify-content: space-between;
padding: 60px 0;
}
.contentItemContent {
font-size: 16px;
margin-top: 40px;
}
.contentItemLinks {
font-weight: 700;
font-size: 16px;
color: #FFFFFF;
line-height: 30px;
text-decoration-line: underline;
display: flex;
flex-direction: row;
flex-wrap: wrap;
gap: 30px 20px;
}
}
.contentItem.active {
flex: 2;
padding-bottom: 200px;
.contentItemContainer {
padding: 0 40px;
}
.contentItemTitle {
font-size: 40px;
}
.contentItemSubtitle {
font-size: 24px;
}
.contentItemContentWrapper {
height: 300px;
opacity: 1;
}
}
}
}

View File

@ -0,0 +1,81 @@
// 横向手风琴组件
import { useState } from 'react';
import styles from './index.module.css';
import { Link } from 'react-router-dom';
const FALLBACK_GRADIENT = "linear-gradient(0deg, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0.5) 100%)";
type Data = {
title?: string;
items: {
title: string;
subtitle?: string;
content?: string;
links?: {
text: string;
path: string;
}[];
image: string;
}[];
}
type Props = {
data: Data;
placement?: 'top' | 'bottom';
}
export default function RowAccordion({ data, placement='bottom' }: Props) {
const [activeIndex, setActiveIndex] = useState(0);
return (
<div className={styles.rowAccordion}>
<div className={styles.rowAccordionBgContainer}>
{data.items.map((item, index) => (
<div
key={index}
className={styles.rowAccordionBgLayer}
style={{
backgroundImage: `url(${item.image}), ${FALLBACK_GRADIENT}`,
opacity: activeIndex === index ? 1 : 0,
}}
/>
))}
</div>
{
data.title && (
<div className={styles.headerRow}>
<div className={styles.title}>{data.title}</div>
</div>
)
}
<div className={styles.contentRow} style={{ height: data.title ? 'calc(100% - 250px)' : '100%' }}>
{data.items.map((item, index) => (
<div className={`${styles.contentItem} ${activeIndex === index && styles.active}`} key={item.title}
style={{ justifyContent: placement === 'top' ? 'flex-start' : 'flex-end' }}
onMouseEnter={() => setActiveIndex(index)}
>
<div className={styles.contentItemContainer}>
<div className={styles.contentItemTitle}>{item.title}</div>
{item.subtitle && <div className={styles.contentItemSubtitle}>{item.subtitle}</div>}
{
(item.content || (item.links || []).length > 0) && (
<div className={styles.contentItemContentWrapper}>
{item.content && (
<div className={styles.contentItemContent}>{item.content}</div>
)}
{item.links && (
<div className={styles.contentItemLinks}>
{item.links?.map((link) => (
<Link key={link.text} to={link.path}>{link.text}</Link>
))}
</div>
)}
</div>
)
}
</div>
</div>
))}
</div>
</div>
);
}

View File

@ -0,0 +1,40 @@
import SectionTitle from "../SectionTitle";
type Props = {
title?: string;
subtitle?: string;
height?: string;
titleColor?: string;
children?: React.ReactNode;
background?: string;
maskBackground?: string;
className?: string;
}
export default function Section({ title, subtitle, height, titleColor, children, background, maskBackground, className }: Props) {
return (
<section style={{
padding: '100px 260px',
width: '100%',
height: height || 'auto',
position: 'relative',
backgroundImage: background ? `url(${background})` : 'transparent',
backgroundRepeat: 'no-repeat',
backgroundSize: 'cover',
backgroundPosition: 'center',
}} className={className}>
<div style={{
width: '100%',
height: '100%',
position: 'absolute',
top: 0,
left: 0,
background: maskBackground || 'rgba(20,53,92,0.4);',
}}></div>
<div style={{ position: 'relative', zIndex: 1 }}>
{title && <SectionTitle title={title} subtitle={subtitle} color={titleColor || '#222'} />}
{children}
</div>
</section>
)
}

View File

@ -1,8 +1,20 @@
.sectionTitle { .sectionTitle {
font-weight: 700; font-weight: 700;
font-size: 40px; font-size: 40px;
color: #222222;
line-height: 50px; line-height: 50px;
text-align: center; text-align: center;
margin-bottom: 100px; margin-bottom: 100px;
display: flex;
flex-direction: column;
.sectionTitleSubtitle {
font-weight: 500;
font-size: 24px;
line-height: 30px;
text-align: center;
font-style: normal;
text-transform: none;
margin-top: 20px;
}
} }

View File

@ -1,9 +1,16 @@
import styles from "./index.module.css"; import styles from "./index.module.css";
export default function SectionTitle({ title }: { title: string }) { type Props = {
title: string;
subtitle?: string;
color?: string;
}
export default function SectionTitle({ title, subtitle, color }: Props) {
return ( return (
<div className={styles.sectionTitle}> <div className={styles.sectionTitle} style={{ color: color || '#222', marginBottom: subtitle ? '60px' : '100px' }}>
<span>{title}</span> <span>{title}</span>
{subtitle && <span className={styles.sectionTitleSubtitle}>{subtitle}</span>}
</div> </div>
) )
} }

View File

@ -17,21 +17,22 @@
} }
.statItem:not(:last-child) { .statItem:not(:last-child) {
border-right: 1px solid #222222; border-right: 1px solid var(--stats-color);
} }
.statNum { .statNum {
font-size: 2.5rem; font-size: 2.5rem;
font-weight: 700; font-weight: 700;
color: #222; color: var(--stats-color);
line-height: 1.2; line-height: 1.2;
} }
.statNumDesc { .statNumDesc {
font-size: 1.875rem; font-size: 1.875rem;
color: var(--stats-color);
} }
.statLabel { .statLabel {
font-size: 1rem; font-size: 1rem;
color: #666; color: var(--stats-label-color);
} }

View File

@ -1,14 +1,24 @@
import styles from "./StatsRow.module.css"; import styles from "./StatsRow.module.css";
type StatsData = { type Data = {
num: string; num: string;
label: string; label: string;
} }
export default function StatsRow({ statsData }: { statsData: StatsData[] }) { type Props = {
data: Data[];
color?: string;
}
export default function StatsRow({ data, color }: Props) {
return ( return (
<div className={styles.statsRow}> <div className={styles.statsRow}
{statsData.map((item, i) => ( style={{
'--stats-color': color ?? '#222222',
'--stats-label-color': color ?? '#666'
} as React.CSSProperties}
>
{data.map((item, i) => (
<div key={i} className={styles.statItem}> <div key={i} className={styles.statItem}>
<div> <div>
<span className={`${styles.statNum} font-num`}> <span className={`${styles.statNum} font-num`}>

View File

@ -1,23 +1,55 @@
.swiperCardSection { .swiperCardSection {
min-height: 100vh; min-height: 100vh;
padding: 100px 260px; padding: 6.25rem 16.25rem;
background: #D8D8D8; background: #D8D8D8;
} }
.carouselWrapper {
display: flex;
align-items: center;
gap: 20px;
position: relative;
}
.navBtn {
flex-shrink: 0;
width: 50px;
height: 50px;
background: #FFFFFF;
box-shadow: 0px 0 12px 0px rgba(20, 53, 92, 0.2);
border: none;
border-radius: 50%;
cursor: pointer;
position: absolute;
top: 50%;
transform: translateY(-50%);
left: -90px;
z-index: 99;
}
.nextBtn {
left: auto;
right: -90px;
}
.swiperCardList { .swiperCardList {
display: flex; flex: 1;
flex-direction: row; overflow: hidden;
gap: 15px; }
.swiperCardItem {
.swiperCardList .swiperCardItem {
overflow: hidden;
position: relative; position: relative;
width: 100%; width: 100%;
aspect-ratio: 457 / 630; aspect-ratio: 457 / 630;
img { img {
width: 100%; width: 100%;
aspect-ratio: 457 / 630; aspect-ratio: 457 / 630;
object-fit: cover; object-fit: cover;
} }
.swiperMask { .swiperMask {
width: 100%; width: 100%;
aspect-ratio: 457 / 630; aspect-ratio: 457 / 630;
@ -27,31 +59,65 @@
background: rgba(0, 0, 0, 0.2); background: rgba(0, 0, 0, 0.2);
} }
&:hover {
.swiperContent {
background: rgba(20, 53, 92, 0.8);
top: 0;
.swiperTitle {
padding: 0 30px;
span {
left: 30px;
transform: translateX(0);
border-color: #fff;
}
}
.swiperDesc {
opacity: 1;
}
}
}
.swiperContent { .swiperContent {
color: #fff; color: #fff;
position: absolute; position: absolute;
top: 80%; top: 75%;
left: 0; left: 0;
width: 100%; width: 100%;
height: 100%; height: 100%;
transition: top 0.3s ease-in-out;
.swiperTitle { .swiperTitle {
position: relative;
font-weight: 500; font-weight: 500;
font-size: 24px; font-size: 24px;
color: #FFFFFF; color: #FFFFFF;
line-height: 80px; line-height: 80px;
height: 80px; height: 80px;
margin: 0 30px; margin: 0 30px;
text-align: center; border-bottom: 1px solid rgba(255, 255, 255, 0.3);
border-bottom: 1px solid rgba(255,255,255,0.3);
span { span {
display: inline-block; display: inline-block;
position: absolute;
left: 50%;
line-height: 80px; line-height: 80px;
height: 80px; height: 80px;
border-bottom: 3px solid #14355C; border-bottom: 3px solid #14355C;
transform: translateX(-50%);
transition: left 0.3s ease-in-out, transform 0.3s ease-in-out;
white-space: nowrap;
} }
} }
.swiperDesc {
font-size: 16px;
color: #FFFFFF;
line-height: 24px;
margin: 40px 60px;
opacity: 0;
} }
} }
} }

View File

@ -1,6 +1,10 @@
import { useCallback, useState } from "react";
import { Swiper, SwiperSlide } from "swiper/react";
import type { Swiper as SwiperType } from "swiper";
import "swiper/css";
import SectionTitle from "../SectionTitle"; import SectionTitle from "../SectionTitle";
import styles from "./index.module.css"; import styles from "./index.module.css";
import { RightOutlined, LeftOutlined } from "@ant-design/icons";
type Data = { type Data = {
title: string; title: string;
cardItems: { cardItems: {
@ -11,23 +15,57 @@ type Data = {
} }
export default function SwiperCardSection({ data }: { data: Data }) { export default function SwiperCardSection({ data }: { data: Data }) {
const [swiperRef, setSwiperRef] = useState<SwiperType | null>(null);
const [activeIndex, setActiveIndex] = useState(0);
const onSwiperChange = useCallback((e: any) => {
setActiveIndex(e.activeIndex);
}, [])
return ( return (
<section className={styles.swiperCardSection}> <section className={styles.swiperCardSection}>
<SectionTitle title={data.title} /> <SectionTitle title={data.title} />
<div className={styles.swiperCardList}> <div className={styles.carouselWrapper}>
{activeIndex > 0 && (
<button
type="button"
className={styles.navBtn}
onClick={() => swiperRef?.slidePrev()}
>
<LeftOutlined color="#14355C" />
</button>
)}
<Swiper
onSwiper={setSwiperRef}
slidesPerView={3}
spaceBetween={15}
allowTouchMove={false}
className={styles.swiperCardList}
onSlideChange={onSwiperChange}
>
{data.cardItems.map((item) => ( {data.cardItems.map((item) => (
<div key={item.title} className={styles.swiperCardItem}> <SwiperSlide key={item.title}>
<div className={styles.swiperCardItem}>
<img src={item.image} alt={item.title} /> <img src={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> </div>
{/* <p>{item.desc}</p> */} <p className={styles.swiperDesc}>{item.desc}</p>
</div> </div>
</div> </div>
</SwiperSlide>
))} ))}
</Swiper>
{activeIndex < data.cardItems.length - 1 && (
<button
type="button"
className={`${styles.navBtn} ${styles.nextBtn}`}
onClick={() => swiperRef?.slideNext()}
>
<RightOutlined color="#14355C" />
</button>
)}
</div> </div>
</section> </section>
) );
} }

View File

@ -0,0 +1,48 @@
import { useState } from 'react';
import styles from './index.module.css';
type Data = {
tabItems: {
icon?: string;
tabName: string;
contentTitle: string;
contentSubtitle: string;
contentText: string;
image: string;
}[]
}
export default function TopTabs({ data }: { data: Data }) {
const [activeIndex, setActiveIndex] = useState(0);
return (
<div>
<div className={styles.topTabsTabs}>
{data.tabItems.map((item, index) => (
<div key={index} className={`${styles.topTabsTabItem} ${activeIndex === index ? styles.active : ''}`} onClick={() => setActiveIndex(index)}>
<span>{item.tabName}</span>
</div>
))}
</div>
<div className={styles.topTabsContent}>
<div className={styles.topTabsContentLeft}>
<div className={styles.topTabsContentLeftHead}>
{
data.tabItems[activeIndex].icon && (
<img src={data.tabItems[activeIndex].icon} alt="" style={{ width: '100px', height: '100px' }} />
)
}
<div className={styles.topTabsContentLeftTitle}>
<div className={styles.topTabsContentLeftTitleMain}>{data.tabItems[activeIndex].contentTitle}</div>
<div className={styles.topTabsContentLeftTitleSub}>{data.tabItems[activeIndex].contentSubtitle}</div>
</div>
</div>
<p className={styles.topTabsContentLeftDesc}>
{data.tabItems[activeIndex].contentText}
</p>
</div>
<div className={styles.topTabsContentRight}>
<img src={data.tabItems[activeIndex].image} alt="" />
</div>
</div>
</div>
)
}

View File

@ -0,0 +1,95 @@
.topTabsSection {
padding: 100px 260px 150px 260px;
width: 100%;
min-height: 100vh;
background-size: cover;
background-position: center;
background-repeat: no-repeat;
}
.topTabsTabs {
height: 60px;
display: flex;
flex-direction: row;
justify-content: center;
justify-content: space-between;
font-weight: 400;
font-size: 24px;
line-height: 34px;
border-bottom: 1px solid #D5D8DC;
padding: 0 260px;
}
.topTabsTabItem {
height: 60px;
cursor: pointer;
color: #222222;
}
.topTabsTabItem.active {
border-bottom: 2px solid #000000;
color: #14355C;
}
.topTabsContent {
padding-top: 150px;
display: flex;
gap: 80px;
flex-direction: row;
}
.topTabsContentLeft {
flex: 6;
margin: auto 0;
.topTabsContentLeftHead {
margin-bottom: 30px;
display: flex;
gap: 10px;
.topTabsContentLeftTitle {
display: flex;
align-items: flex-end;
gap: 10px;
.topTabsContentLeftTitleMain {
font-weight: 700;
font-size: 40px;
color: #222222;
line-height: 50px;
text-align: left;
font-style: normal;
text-transform: none;
}
.topTabsContentLeftTitleSub {
font-weight: 400;
font-size: 18px;
color: #14355C;
line-height: 26px;
text-align: left;
font-style: normal;
text-transform: none;
}
}
}
.topTabsContentLeftDesc {
font-weight: 400;
font-size: 18px;
color: #222222;
line-height: 34px;
text-align: justify;
font-style: normal;
text-transform: none;
}
}
.topTabsContentRight {
flex: 8;
img {
width: 800px;
height: 500px;
}
}

View File

@ -0,0 +1,22 @@
import { useState } from 'react';
import styles from './index.module.css';
import TopTabs from './TopTabs';
type Data = {
tabItems: {
icon?: string;
tabName: string;
contentTitle: string;
contentSubtitle: string;
contentText: string;
image: string;
}[]
}
export default function TopTabsSection({ data }: { data: Data }) {
return (
<section className={styles.topTabsSection} style={{ backgroundImage: `url(/images/TopTabsSection-background.png)` }}>
<TopTabs data={data} />
</section>
)
}

View File

@ -1,5 +1,5 @@
.footer { .footer {
background: #fff; background: #F6F6F6;
color: #333; color: #333;
} }

View File

@ -13,16 +13,35 @@
text-align: left; text-align: left;
font-style: normal; font-style: normal;
text-transform: none; text-transform: none;
transition: background 0.3s ease;
} }
.hoverMenu.header { .hoverMenu.header {
background: #fff; background: #fff;
box-shadow: 0 0 10px 0 rgba(255, 255, 255, 0.1); box-shadow: 0 0 10px 0 rgba(255, 255, 255, 0.1);
border-bottom: 1px solid #eee;
} }
.hoverMenu .navLink { .hoverMenu .navLink {
color: #222222; color: #222222;
} }
.hoverMenu {
.searchBtn {
color: #222222;
}
.langTrigger {
color: #222222;
}
svg,
svg path {
fill: #222222 !important;
}
}
.activeNav .navLink { .activeNav .navLink {
color: #14355C; color: #14355C;
} }
@ -34,6 +53,7 @@
height: 100%; height: 100%;
width: 100%; width: 100%;
} }
.headerInner::after { .headerInner::after {
position: absolute; position: absolute;
bottom: 0; bottom: 0;
@ -79,6 +99,7 @@
white-space: nowrap; white-space: nowrap;
cursor: pointer; cursor: pointer;
} }
.navLink:hover { .navLink:hover {
color: #14355C !important; color: #14355C !important;
} }
@ -122,7 +143,7 @@
left: 0; left: 0;
width: 100%; width: 100%;
height: 23.75rem; height: 23.75rem;
background: rgba(255, 255, 255, 0.9); background: rgba(255, 255, 255, 1);
box-shadow: 0 0 10px 0 rgba(0, 0, 0, 0.1); box-shadow: 0 0 10px 0 rgba(0, 0, 0, 0.1);
padding: 1.25rem; padding: 1.25rem;
z-index: 1000; z-index: 1000;

View File

@ -1,12 +1,14 @@
import { Link } from "react-router-dom"; import { Link, useLocation } from "react-router-dom";
import { Dropdown } from "antd"; import { Dropdown } from "antd";
import styles from "./Header.module.css"; import styles from "./Header.module.css";
import { useMemo, useState } from "react"; import { useEffect, useMemo, useState } from "react";
type NavChild = { path: string; label: string }; type NavChild = { path: string; label: string };
type NavItem = { path: string; label: string; children?: NavChild[] }; type NavItem = { path: string; label: string; children?: NavChild[] };
export default function Header() { export default function Header() {
const location = useLocation();
const navItems: NavItem[] = [ const navItems: NavItem[] = [
{ {
label: "关于银泰", label: "关于银泰",
@ -40,7 +42,7 @@ export default function Header() {
label: "新闻中心", label: "新闻中心",
path: "/news", path: "/news",
children: [ children: [
{ path: "/news/consult", label: "银泰咨询" }, { path: "/news/public", label: "集团发布" },
{ path: "/news/media", label: "媒体垂询" }, { path: "/news/media", label: "媒体垂询" },
], ],
}, },
@ -63,7 +65,7 @@ export default function Header() {
const [showDropPanel, setShowDropPanel] = useState(false); const [showDropPanel, setShowDropPanel] = useState(false);
const [hoverElLeft, setHoverElLeft] = useState(0); const [hoverElLeft, setHoverElLeft] = useState(0);
const handleNavEnter = (e: any, path: string) => { const handleNavEnter = (e: any, path: string) => {
console.log(e,e.target.offsetWidth) console.log(e, e.target.offsetWidth)
// left + 元素宽度的一半 // left + 元素宽度的一半
const left = e.target.offsetLeft; const left = e.target.offsetLeft;
setHoverElLeft(left); setHoverElLeft(left);
@ -74,8 +76,36 @@ export default function Header() {
const activePanelItem = useMemo(() => { const activePanelItem = useMemo(() => {
return navItems.find((item) => item.path === activeNav)?.children || []; return navItems.find((item) => item.path === activeNav)?.children || [];
}, [activeNav]); }, [activeNav]);
const [showWhiteMode, setShowWhiteMode] = useState(false);
useEffect(() => {
const path = location.pathname;
if (path.includes("/detail/")) {
setShowWhiteMode(true);
} else {
setShowWhiteMode(false);
}
}, [location.pathname]);
// 监听滚动
useEffect(() => {
const handleScroll = () => {
const scrollTop = window.scrollY;
if (scrollTop > 100) {
setShowWhiteMode(true);
} else {
setShowWhiteMode(false);
}
}
window.addEventListener("scroll", handleScroll);
return () => {
window.removeEventListener("scroll", handleScroll);
};
}, []);
return ( return (
<header className={`${styles.header} ${showDropPanel ? styles.hoverMenu : ""}`} <header className={`${styles.header} ${(showDropPanel || showWhiteMode) ? styles.hoverMenu : ""}`}
onMouseLeave={() => setShowDropPanel(false)} onMouseLeave={() => setShowDropPanel(false)}
> >
<div className={`header-row ${styles.headerInner}`}> <div className={`header-row ${styles.headerInner}`}>
@ -104,7 +134,7 @@ export default function Header() {
trigger={["click"]} trigger={["click"]}
> >
<button className={styles.langTrigger} type="button"> <button className={styles.langTrigger} type="button">
<span style={{fontSize: '18px'}}></span>
<svg xmlns="http://www.w3.org/2000/svg" fill="none" version="1.1" width="24" height="24" viewBox="0 0 24 24"><g transform="matrix(0,1,-1,0,24,-24)"><path d="M46.720364062499996,30.4020875C46.720364062499996,30.4020875,45.6597041625,31.462787499999997,45.6597041625,31.462787499999997C45.6597041625,31.462787499999997,39.8815300725,25.6845775,39.8815300725,25.6845775C39.4910054655,25.2940474,39.4910053615,24.6608877,39.8815300725,24.2703576C39.8815300725,24.2703576,45.6597041625,18.4921875,45.6597041625,18.4921875C45.6597041625,18.4921875,46.720364062499996,19.5528475,46.720364062499996,19.5528475C46.720364062499996,19.5528475,41.2957440625,24.9774675,41.2957440625,24.9774675C41.2957440625,24.9774675,46.720364062499996,30.4020875,46.720364062499996,30.4020875C46.720364062499996,30.4020875,46.720364062499996,30.4020875,46.720364062499996,30.4020875Z" fillRule="evenodd" fill="#FFFFFF" fillOpacity="1" transform="matrix(-1,0,0,-1,79.173828125,36.984375)" /></g></svg> <svg xmlns="http://www.w3.org/2000/svg" fill="none" version="1.1" width="24" height="24" viewBox="0 0 24 24"><g transform="matrix(0,1,-1,0,24,-24)"><path d="M46.720364062499996,30.4020875C46.720364062499996,30.4020875,45.6597041625,31.462787499999997,45.6597041625,31.462787499999997C45.6597041625,31.462787499999997,39.8815300725,25.6845775,39.8815300725,25.6845775C39.4910054655,25.2940474,39.4910053615,24.6608877,39.8815300725,24.2703576C39.8815300725,24.2703576,45.6597041625,18.4921875,45.6597041625,18.4921875C45.6597041625,18.4921875,46.720364062499996,19.5528475,46.720364062499996,19.5528475C46.720364062499996,19.5528475,41.2957440625,24.9774675,41.2957440625,24.9774675C41.2957440625,24.9774675,46.720364062499996,30.4020875,46.720364062499996,30.4020875C46.720364062499996,30.4020875,46.720364062499996,30.4020875,46.720364062499996,30.4020875Z" fillRule="evenodd" fill="#FFFFFF" fillOpacity="1" transform="matrix(-1,0,0,-1,79.173828125,36.984375)" /></g></svg>
</button> </button>
</Dropdown> </Dropdown>
@ -117,8 +147,9 @@ export default function Header() {
); );
} }
function DropPanel({ items, left }: { items: NavChild[]; left: number }) { function DropPanel({ items, left }: { items: NavChild[]; left: number }) {
return ( return (
<div id="drop-panel" className={styles.dropPanel} style={{paddingLeft: left}}> <div id="drop-panel" className={styles.dropPanel} style={{ paddingLeft: left, }}>
<div className={styles.dropPanelContent}> <div className={styles.dropPanelContent}>
{items.map((item) => ( {items.map((item) => (
<div key={item.path} className={styles.dropPanelItem}> <div key={item.path} className={styles.dropPanelItem}>

View File

@ -1,8 +1,14 @@
import Banner from "@/components/banner"; import Banner from "@/components/Banner";
import styles from "./Founder.module.css"; import styles from "./Founder.module.css";
import { useState } from "react"; import { useState } from "react";
import ParagraphSection from "@/components/layout/ParagraphSection";
export default function AboutFounder() { export default function AboutFounder() {
const [paragraphSectionData] = useState({
title: "沈国军",
content: "汉族,博士,高级经济师。中国人民政治协商会议第十一届、十三届全国委员会委员、中国人民政治协商会议第十三届全国委员会提案委员会委员、中国致公党第十四届、十五届、十六届中央委员会常委、第一届浙商(全球)总会执行会长、第一届甬商(全球)总会会长。\n\n 银泰集团(全称“中国银泰投资有限公司”)创始人兼董事长、银泰公益基金会创始人及荣誉理事长、桃花源生态保护基金会董事局执行主席。",
})
const intoductionList = [ const intoductionList = [
{ {
title: "商业领域", title: "商业领域",
@ -25,12 +31,7 @@ export default function AboutFounder() {
desc="卓越的变革践行者、产业推动者及社会公民" desc="卓越的变革践行者、产业推动者及社会公民"
showBreadcrumb={true} backgroundImage={'/images/bg-overview.png'}></Banner> showBreadcrumb={true} backgroundImage={'/images/bg-overview.png'}></Banner>
<section className={styles.section}> <ParagraphSection data={paragraphSectionData} >
<div className={styles.content}>
<span></span>
<p></p>
<p></p>
</div>
<div className={styles.images}> <div className={styles.images}>
{intoductionList.map((item, index) => ( {intoductionList.map((item, index) => (
<div className={styles.imageItem} key={item.title}> <div className={styles.imageItem} key={item.title}>
@ -45,7 +46,8 @@ export default function AboutFounder() {
</div> </div>
))} ))}
</div> </div>
</section> </ParagraphSection>
<section className={styles.sectionFounder}> <section className={styles.sectionFounder}>
<div className={styles.founderIntroduction}> <div className={styles.founderIntroduction}>
@ -55,7 +57,7 @@ export default function AboutFounder() {
<div className={styles.founderPhoto}> <div className={styles.founderPhoto}>
<img src="/images/bg-invest-group.png" alt="个人照" /> <img src="/images/bg-invest-group.png" alt="个人照" />
<div className={styles.founderPhotoContent}> <div className={styles.founderPhotoContent}>
<p style={{color: '#14355C'}}>· </p> <p style={{ color: '#14355C' }}>· </p>
<p></p> <p></p>
</div> </div>
</div> </div>

View File

@ -1,4 +1,4 @@
import Banner from "@/components/banner"; import Banner from "@/components/Banner";
import YearPicker from "@/components/YearPicker"; import YearPicker from "@/components/YearPicker";
import styles from "./History.module.css"; import styles from "./History.module.css";
import { useState, useRef, useLayoutEffect } from "react"; import { useState, useRef, useLayoutEffect } from "react";

View File

@ -1,6 +1,6 @@
import { Link } from "react-router-dom"; import { Link } from "react-router-dom";
import styles from "./About.module.css"; import styles from "./About.module.css";
import Banner from "@/components/banner"; import Banner from "@/components/Banner";
const FALLBACK_GRADIENT = "linear-gradient(135deg, #1a2a4a 0%, #2d4a7c 100%)"; const FALLBACK_GRADIENT = "linear-gradient(135deg, #1a2a4a 0%, #2d4a7c 100%)";
@ -17,7 +17,7 @@ const sectionData: SectionItem[] = [
title: "银泰商业集团", title: "银泰商业集团",
desc: "涵盖地标型高端商业综合体in77、景观地标型商业综合体inPARK区域型品质商业生活中心银泰城等品牌的大型商业集团是一家持续推动传统零售业创新与互联网转型融合的典范性企业。", desc: "涵盖地标型高端商业综合体in77、景观地标型商业综合体inPARK区域型品质商业生活中心银泰城等品牌的大型商业集团是一家持续推动传统零售业创新与互联网转型融合的典范性企业。",
bgImg: '/images/bg-commercial-group.png', bgImg: '/images/bg-commercial-group.png',
links: [{ label: 'in77', to: '/in77' }, { label: 'inPARK', to: '/inPARK' }, { label: '银泰城购物中心', to: '/shopping-center' },] links: [{ label: 'in77', to: '/business/commercial-group/in77' }, { label: 'inPARK', to: '/inPARK' }, { label: '银泰城购物中心', to: '/shopping-center' },]
}, },
{ {
title: "银泰基业集团", title: "银泰基业集团",
@ -52,6 +52,7 @@ export default function About() {
title="集团概览" title="集团概览"
desc="银泰集团全称“中国银泰投资有限公司”由沈国军先生于1997年创立立足实业发展与产业投资业务涵盖商业零售、商业地产运营与开发、股权投资等领域在境内外拥有多家控股、参股公司已发展成为一家主业突出、多元发展的现代企业集团。" desc="银泰集团全称“中国银泰投资有限公司”由沈国军先生于1997年创立立足实业发展与产业投资业务涵盖商业零售、商业地产运营与开发、股权投资等领域在境内外拥有多家控股、参股公司已发展成为一家主业突出、多元发展的现代企业集团。"
showBreadcrumb={true} showBreadcrumb={true}
breadcrumbItems={[{ label: '关于银泰', to: '/about' }, { label: '集团概览', to: '' }]}
backgroundImage={'/images/bg-overview.png'} /> backgroundImage={'/images/bg-overview.png'} />
{sectionData.map((item, index) => ( {sectionData.map((item, index) => (
@ -62,7 +63,6 @@ export default function About() {
backgroundImage: `url(${item.bgImg}), ${FALLBACK_GRADIENT}`, backgroundImage: `url(${item.bgImg}), ${FALLBACK_GRADIENT}`,
}} }}
> >
{/* <div className={styles.overlay} /> */}
<div <div
className={`${styles.content} ${index % 2 === 1 ? styles.contentRight : ""}`} className={`${styles.content} ${index % 2 === 1 ? styles.contentRight : ""}`}
> >

View File

@ -1,8 +1,93 @@
export default function BusinessBaseGroup() { import Banner from "@/components/Banner";
import { useState } from "react";
import SwiperCardSection from "@/components/layout/SwiperCardSection";
import RowAccordion from "@/components/layout/RowAccordion";
import HonorGrids from "@/components/layout/HonorGrids";
import ParagraphSection from "@/components/layout/ParagraphSection";
import BottomTabsSection from "@/components/layout/BottomTabsSection";
export default function BaseGroup() {
const [paragraphSectionData] = useState({
title: "银泰基业集团",
content: "管理有限公司是一家集品质物业服务、资产托管运营、智慧物联管理、科技平台创新运维为一体的专业化物业服务企业,致力于商办类物业运营管理、打造资产全周期生态服务。\n\n 凭借银泰集团多年城市商业地产运营经验不断深化创新,银泰智享积极拓展业务深度与广度,做强基础物业服务,深耕客户卓越服务体验,创造企业多元化价值。核心业务涵盖资产全托管服务、资产顾问服务、资产设施服务、物业品牌合作等,着力实现服务体系化、标准化、精细化、智慧化“四化合一”,打造国内一流的物业管理品牌。",
statsData: [
{ num: "32 个", label: "全国在管项目" },
{ num: "475 万平方", label: "总建筑面积" },
{ num: "3 亿人次", label: "客流每年超" },
{ num: "350 亿元", label: "销售额每年" },
{ num: "5000 +", label: "合作品牌" },
],
})
const swiperCardData = {
title: "四大区域",
cardItems: [
{ title: "服务业态1", desc: "服务业态1", image: "/images/bg-overview.png" },
{ title: "服务业态2", desc: "服务业态2", image: "/images/bg-overview.png" },
{ title: "服务业态3", desc: "服务业态3", image: "/images/bg-overview.png" },
{ title: "服务业态4", desc: "服务业态3", image: "/images/bg-overview.png" },
{ title: "服务业态5", desc: "服务业态3", image: "/images/bg-overview.png" },
],
}
const rowAccordionData = {
title: "标杆项目",
items: [
{ title: "北京", subtitle: "北京银泰中心", image: "/images/bg-overview.png", links:[
{ text: 'in01', path: ''},
{ text: '超甲级写字楼', path: ''},
{ text: '北京柏悦酒店', path: ''},
{ text: '柏悦府', path: ''},
{ text: '柏悦居', path: ''},
] },
{ title: "四川", subtitle: "成都银泰中心", image: "/images/bg-overview.png" },
{ title: "浙江", subtitle: "杭州湖滨银泰in77", image: "/images/bg-overview.png" },
{ title: "上海", subtitle: "上海中骏广场", image: "/images/bg-overview.png" },
],
}
const honorsData = {
title: "企业价值",
items: [
{ title: "荣誉资质1" },
{ title: "荣誉资质2" },
{ title: "荣誉资质3" },
{ title: "荣誉资质4" },
{ title: "荣誉资质5" },
{ title: "荣誉资质6" },
{ title: "荣誉资质7" },
{ title: "荣誉资质8" },
],
}
const bottomTabsData = {
title: "业务特色",
tabItems: [
{ tabName: "精细化运营", contentTitle: "精细化运营——运筹帷幄·精于心", contentText: "通过精细化管理赋能运营,稳步提升商业资产价值。关注租金的成长性和租户的良性表现,实现产品逐步升级,服务稳健提升,实现商业资产整体增值。", image: "/images/bg-overview.png" },
{ tabName: "数智化管理", contentTitle: "内容标题2", contentText: "内容文本2", image: "/images/bg-overview.png" },
{ tabName: "生态化发展", contentTitle: "内容标题2", contentText: "内容文本2", image: "/images/bg-overview.png" },
{ tabName: "品牌化升级", contentTitle: "内容标题2", contentText: "内容文本2", image: "/images/bg-overview.png" },
],
}
return ( return (
<div> <div>
<h1></h1> <Banner
<p></p> title="银泰基业集团"
desc="商业物业资产运营与管理先锋"
titleSize="medium"
showBreadcrumb={false}
backgroundImage={`/images/bg-overview.png`}
/>
<ParagraphSection data={paragraphSectionData} />
<SwiperCardSection data={swiperCardData} />
<RowAccordion data={rowAccordionData} placement="top" />
<HonorGrids data={honorsData} />
<BottomTabsSection data={bottomTabsData} />
</div> </div>
); );
} }

View File

@ -56,11 +56,12 @@
cursor: pointer; cursor: pointer;
font-weight: 500; font-weight: 500;
font-size: 24px; font-size: 24px;
color: #14355C; color: #222;
line-height: 34px; line-height: 34px;
} }
.twoColSectionTab.active { .twoColSectionTab.active {
border-bottom: 2px solid #14355C; border-bottom: 2px solid #14355C;
color: #14355C;
} }
.twoColSectionContent { .twoColSectionContent {
display: grid; display: grid;

View File

@ -1,20 +1,12 @@
import { useState } from "react"; import { useState } from "react";
import styles from "./CommercialGroup.module.css"; import styles from "./CommercialGroup.module.css";
import Banner from "@/components/banner"; import Banner from "@/components/Banner";
import { Link } from "react-router-dom"; import { Link } from "react-router-dom";
import StatsRow from "@/components/layout/StatsRow/StatsRow"; import ParagraphSection from "@/components/layout/ParagraphSection";
const PUBLIC_URL = process.env.PUBLIC_URL || ""; const PUBLIC_URL = process.env.PUBLIC_URL || "";
const FALLBACK_GRADIENT = "linear-gradient(135deg, #1a2a4a 0%, #2d4a7c 100%)"; const FALLBACK_GRADIENT = "linear-gradient(135deg, #1a2a4a 0%, #2d4a7c 100%)";
const statsData = [
{ num: "32 个", label: "全国在管项目" },
{ num: "475 万平方", label: "总建筑面积" },
{ num: "3 亿人次", label: "客流每年超" },
{ num: "350 亿元", label: "销售额每年" },
{ num: "5000 +", label: "合作品牌" },
];
function PlaceholderImage() { function PlaceholderImage() {
return <div className={styles.placeholder}></div>; return <div className={styles.placeholder}></div>;
@ -22,7 +14,18 @@ function PlaceholderImage() {
export default function BusinessCommercialGroup() { export default function BusinessCommercialGroup() {
const [in77ImgError, setIn77ImgError] = useState(false); const [in77ImgError, setIn77ImgError] = useState(false);
const [propertyImgError, setPropertyImgError] = useState(false);
const [paragraphSectionData] = useState({
title: "银泰商业集团",
content: "作为一家大型商业集团品牌涵盖地标型高端商业综合体in77、景观地标型商业综合体inPARK、区域型品质商业生活中心银泰城等是一家持续推动传统零售业创新与互联网转型融合的典范性企业。其中in77系列购物中心位于核心商业圈和国家示范步行街是时尚零售业和新消费领域的标杆inPARK系列购物中心致力于打造“街区+shopping mall + 微景观”的公园商业新形态,通过创新营销催化人气聚集,构建新年轻生活方式;银泰城购物中心融合购物、餐饮、休闲、娱乐、社交等多元业态于一体,充分满足一站式消费需求。",
statsData: [
{ num: "32 个", label: "全国在管项目" },
{ num: "475 万平方", label: "总建筑面积" },
{ num: "3 亿人次", label: "客流每年超" },
{ num: "350 亿元", label: "销售额每年" },
{ num: "5000 +", label: "合作品牌" },
],
})
const [tabItems, setTabItems] = useState([ const [tabItems, setTabItems] = useState([
{ label: 'in77', content: 'in77 内容', image: '/images/bg-overview.png', path: '/business/commercial-group/in77' }, { label: 'in77', content: 'in77 内容', image: '/images/bg-overview.png', path: '/business/commercial-group/in77' },
@ -55,19 +58,8 @@ export default function BusinessCommercialGroup() {
backgroundImage={`${PUBLIC_URL}/images/bg-commercial-group.png`} backgroundImage={`${PUBLIC_URL}/images/bg-commercial-group.png`}
/> />
{/* 2. Overview + Stats */} {/* 2. Overview */}
<section className={styles.overview}> <ParagraphSection data={paragraphSectionData} />
<div className={styles.overviewInner}>
<p className={styles.overviewDesc}>
<span className={styles.overviewTitle}></span>
in77inPARKin77系列购物中心位于核心商业圈和国家示范步行街inPARK系列购物中心致力于打造+shopping mall +
</p>
<p className={styles.overviewDesc}>
in77inPARKin77系列购物中心位于核心商业圈和国家示范步行街inPARK系列购物中心致力于打造+shopping mall +
</p>
<StatsRow statsData={statsData} />
</div>
</section>
{/* 3. in77 Section - Image Left, Text Right */} {/* 3. in77 Section - Image Left, Text Right */}
<section className={styles.twoColSection} <section className={styles.twoColSection}

View File

@ -1,4 +1,4 @@
import Banner from "@/components/banner"; import Banner from "@/components/Banner";
import styles from "./CommercialGroupDetail.module.css"; import styles from "./CommercialGroupDetail.module.css";
import { useState } from "react"; import { useState } from "react";
export default function BusinessCommercialGroupDetail() { export default function BusinessCommercialGroupDetail() {

View File

@ -0,0 +1,128 @@
.investGroup {
width: 100%;
height: 800px;
padding: 100px 260px;
background: rgba(0, 39, 83, 0.7);
.investGroupContent {
color: #FFFFFF;
height: 460px;
.investGroupContentItems {
display: flex;
height: 460px;
.investGroupContentItem:first-child {
padding-right: 100px;
}
.investGroupContentItem:last-child {
padding-left: 100px;
}
.investGroupContentItem {
flex: 1;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
gap: 40px;
&:last-child {
border-right: none;
}
border-right: 1px solid rgba(255, 255, 255, .5);
.investGroupContentItemTitle {
font-size: 40px;
}
.investGroupContentItemContent {
font-weight: 400;
font-size: 16px;
color: #FFFFFF;
line-height: 30px;
text-align: justify;
font-style: normal;
text-transform: none;
}
}
}
}
}
.equityInvestment {
width: 100%;
padding: 100px 260px;
background: rgba(255, 255, 255, 0.6);
.equityInvestmentItems {
/* 5列布局 */
display: grid;
grid-template-columns: repeat(5, 1fr);
gap: 20px 40px;
.equityInvestmentItem {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
gap: 20px;
.equityInvestmentItemLogo {
width: 264px;
height: 157px;
object-fit: cover;
}
}
}
}
.industryFoster {
width: 100%;
height: 100vh;
display: flex;
align-items: center;
position: relative;
.bgMask {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(20,53,92,0.1);
}
.industryFosterMask {
width: 546px;
min-height: 400px;
background: rgba(20, 53, 92, 0.5);
color: #fff;
padding: 60px 50px;
.industryFosterMaskTitle {
font-weight: 500;
font-size: 40px;
color: #FFFFFF;
line-height: 50px;
text-align: left;
font-style: normal;
text-transform: none;
margin-bottom: 30px;
}
.industryFosterMaskContent {
font-weight: 400;
font-size: 18px;
color: #FFFFFF;
line-height: 34px;
text-align: justify;
font-style: normal;
text-transform: none;
}
}
}

View File

@ -1,8 +1,119 @@
export default function BusinessInvestGroup() { import { useState } from "react";
import Banner from "@/components/Banner";
import ParagraphSection from "@/components/layout/ParagraphSection";
import styles from "./InvestGroup.module.css";
import SectionTitle from "@/components/layout/SectionTitle";
import Section from "@/components/layout/Section";
export default function InvestGroup() {
const [paragraphSectionData] = useState({
title: "银泰投资集团",
content: "银泰集团坚持价值投资理念,积极拓展产业投资,在互联网科技、大消费、智慧物流、新能源、生物制药、医养服务、金融服务等新兴产业积极布局,围绕产业链形成协同效应,做头部资产的发现者、稀缺资源的整合者、企业成长的赋能者,助力技术创新与产业变革,促进中国实体经济高质量发展。\n\n成立银柏投资、之江投资两大投资平台。投资规模超200亿累计管理规模超700亿元其中有15家公司已经成长为估值10亿美金以上的“独角兽”18家已完成上市。",
statsData: [
{ num: "32 个", label: "全国在管项目" },
{ num: "475 万平方", label: "总建筑面积" },
{ num: "3 亿人次", label: "客流每年超" },
{ num: "350 亿元", label: "销售额每年" },
{ num: "5000 +", label: "合作品牌" },
],
})
const investGroupContentData = {
title: "发起设立",
items: [
{
title: "菜鸟",
content: "银泰集团与阿里巴巴集团等各方共同组建的菜鸟智慧物流网络有限公司于2013年5月正式成立。菜鸟网络扎根在物流产业以科技创新为核心搭建了领先的全球化物流网络为消费者和商家提供普惠优质服务为实体经济降本增效保障民生流通稳就业促增收是一家客户价值驱动的全球化产业互联网公司。",
},
{
title: "网商银行",
content: "2015年6月网商银行正式开业它是由银泰集团、阿里巴巴集团等企业共同发起的中国第一家将核心系统架构在金融云上的银行是中国首批试点的民营银行之一。网商银行旨在成为网商必选的金融服务商、互联网银行的探索者和普惠金融的实践者为小微企业、大众消费者、农村经营者与农户、中小金融机构提供服务。",
},
]
}
// 股权投资
const equityInvestmentData = {
title: "股权投资",
items: [
{ logo: "/images/bg-overview.png", title: "字节跳动", },
{ logo: "/images/bg-overview.png", title: "字节跳动", },
{ logo: "/images/bg-overview.png", title: "字节跳动", },
{ logo: "/images/bg-overview.png", title: "字节跳动", },
{ logo: "/images/bg-overview.png", title: "字节跳动", },
{ logo: "/images/bg-overview.png", title: "字节跳动", },
{ logo: "/images/bg-overview.png", title: "字节跳动", },
{ logo: "/images/bg-overview.png", title: "字节跳动", },
{ logo: "/images/bg-overview.png", title: "字节跳动", },
{ logo: "/images/bg-overview.png", title: "字节跳动", },
{ logo: "/images/bg-overview.png", title: "字节跳动", },
{ logo: "/images/bg-overview.png", title: "字节跳动", },
{ logo: "/images/bg-overview.png", title: "字节跳动", },
{ logo: "/images/bg-overview.png", title: "字节跳动", },
{ logo: "/images/bg-overview.png", title: "字节跳动", },
]
}
// 产业孵化
const industryFosterData = {
title: "产业孵化",
content: "银泰集团创立和培育了银泰黄金股份有限公司000975.SZ。银泰黄金是以黄金为主的高质量矿山投资运营商致力于贵金属和有色金属矿采选及金属贸易拥有全国储量最大、单体银品位最高的银多金属矿和品质较高的黄金矿已发展成为国内贵金属行业具有领先优势及影响力的上市公司之一。",
backgroundImage: "/images/bg-overview.png",
}
return ( return (
<div> <div>
<h1></h1> <Banner
<p></p> title="银泰投资集团"
desc="探索价值投资,协同产业发展"
titleSize="medium"
showBreadcrumb={false}
backgroundImage={`/images/bg-overview.png`}
/>
<ParagraphSection data={paragraphSectionData} />
{/* 发起成立 */}
<section className={styles.investGroup}>
<SectionTitle title={investGroupContentData.title} color="#fff" />
<div className={styles.investGroupContent}>
<div className={styles.investGroupContentItems}>
{investGroupContentData.items.map((item, index) => (
<div className={styles.investGroupContentItem} key={index}>
<div className={styles.investGroupContentItemTitle}>{item.title}</div>
<div className={styles.investGroupContentItemContent}>{item.content}</div>
</div>
))}
</div>
</div>
</section>
{/* 股权投资 */}
<section className={styles.equityInvestment}>
<SectionTitle title={equityInvestmentData.title} />
<div className={styles.equityInvestmentItems}>
{equityInvestmentData.items.map((item, index) => (
<div className={styles.equityInvestmentItem} key={index}>
<img src={item.logo} alt={item.title} className={styles.equityInvestmentItemLogo} />
<div className={styles.equityInvestmentItemTitle}>{item.title}</div>
</div>
))}
</div>
</section>
{/* 产业孵化 */}
<Section background={industryFosterData.backgroundImage} maskBackground="rgba(20,53,92,0.1)"
className={styles.industryFoster}
>
<div className={styles.industryFosterMask}>
<div className={styles.industryFosterMaskTitle}>{industryFosterData.title}</div>
<div className={styles.industryFosterMaskContent}>{industryFosterData.content}</div>
</div>
</Section>
</div> </div>
); );
} }

View File

@ -1,8 +1,87 @@
export default function BusinessRealtyGroup() { import Banner from "@/components/Banner";
import { useState } from "react";
import SwiperCardSection from "@/components/layout/SwiperCardSection";
import RowAccordion from "@/components/layout/RowAccordion";
import HonorGrids from "@/components/layout/HonorGrids";
import ParagraphSection from "@/components/layout/ParagraphSection";
import BottomTabsSection from "@/components/layout/BottomTabsSection";
import TopTabsSection from "@/components/layout/TopTabsSection";
export default function RealtyGroup() {
const [paragraphSectionData] = useState({
title: "银泰置地集团",
content: "专注于大型综合性商业地产项目和小镇开发涵盖高端购物中心、酒店、公寓、超甲级写字楼等业态旗下囊括“银泰中心”“银泰城”“柏悦府”“柏悦居”等产品线。公司秉承绿色建筑理念和楼宇智慧运营管理成为中国高端商业地产的领军企业。目前银泰置地集团在全国拥有100余个建成及在建项目遍布北京、杭州、成都等七十多个城市总开发面积近二千万平方米。\n\n近年来银泰置地集团紧密结合国家产业政策控制开发规模探索“租售并举+轻资产运作”的商业模式,成为商业地产领域创新变革与健康良性发展的代表性企业。",
statsData: [
{ num: "32 个", label: "全国在管项目" },
{ num: "475 万平方", label: "总建筑面积" },
{ num: "3 亿人次", label: "客流每年超" },
{ num: "350 亿元", label: "销售额每年" },
{ num: "5000 +", label: "合作品牌" },
],
})
const topTabsData = {
tabItems: [
{ tabName: "银泰中心", contentTitle: "银泰中心1", contentSubtitle: "城市封面地标", contentText: "北京银泰中心是银泰置地集团在北京的核心项目,是集高端购物中心、酒店、公寓、超甲级写字楼等业态于一体的综合性商业地产项目。", image: "/images/bg-overview.png" },
{ tabName: "银泰城", contentTitle: "银泰中心2", contentSubtitle: "城市封面地标", contentText: "北京银泰中心是银泰置地集团在北京的核心项目,是集高端购物中心、酒店、公寓、超甲级写字楼等业态于一体的综合性商业地产项目。", image: "/images/bg-overview.png" },
{ tabName: "高级酒店与公寓", contentTitle: "银泰中心3", contentSubtitle: "城市封面地标", contentText: "北京银泰中心是银泰置地集团在北京的核心项目,是集高端购物中心、酒店、公寓、超甲级写字楼等业态于一体的综合性商业地产项目。", image: "/images/bg-overview.png" },
{ tabName: "文旅小镇", contentTitle: "银泰中心", contentSubtitle: "城市封面地标", contentText: "北京银泰中心是银泰置地集团在北京的核心项目,是集高端购物中心、酒店、公寓、超甲级写字楼等业态于一体的综合性商业地产项目。", image: "/images/bg-overview.png" },
],
}
const rowAccordionData = {
title: "标杆项目",
items: [
{ title: "杭州银泰中心", content: "位于杭州未来科技城地块与余杭区政府合作开发建设规划投资数十亿元建设总建筑面积约60万方的高端TOD城市综合体推动区域向“国际化消费中心”转型打造百亿级商圈。", image: "/images/bg-overview.png"},
{ title: "丽水银泰城", content: "位于杭州未来科技城地块与余杭区政府合作开发建设规划投资数十亿元建设总建筑面积约60万方的高端TOD城市综合体推动区域向“国际化消费中心”转型打造百亿级商圈。", image: "/images/bg-overview.png"},
{ title: "杭州银泰喜来登大酒店", content: "位于杭州未来科技城地块与余杭区政府合作开发建设规划投资数十亿元建设总建筑面积约60万方的高端TOD城市综合体推动区域向“国际化消费中心”转型打造百亿级商圈。", image: "/images/bg-overview.png"},
{ title: "杭州银泰仙女湖小镇", content: "位于杭州未来科技城地块与余杭区政府合作开发建设规划投资数十亿元建设总建筑面积约60万方的高端TOD城市综合体推动区域向“国际化消费中心”转型打造百亿级商圈。", image: "/images/bg-overview.png"},
],
}
const honorsData = {
title: "荣誉奖项",
items: [
{ title: "荣誉资质1" },
{ title: "荣誉资质2" },
{ title: "荣誉资质3" },
{ title: "荣誉资质4" },
{ title: "荣誉资质5" },
{ title: "荣誉资质6" },
{ title: "荣誉资质7" },
{ title: "荣誉资质8" },
],
}
const bottomTabsData = {
title: "业务特色",
tabItems: [
{ tabName: "精细化运营", contentTitle: "精细化运营——运筹帷幄·精于心", contentText: "通过精细化管理赋能运营,稳步提升商业资产价值。关注租金的成长性和租户的良性表现,实现产品逐步升级,服务稳健提升,实现商业资产整体增值。", image: "/images/bg-overview.png" },
{ tabName: "数智化管理", contentTitle: "内容标题2", contentText: "内容文本2", image: "/images/bg-overview.png" },
{ tabName: "生态化发展", contentTitle: "内容标题2", contentText: "内容文本2", image: "/images/bg-overview.png" },
{ tabName: "品牌化升级", contentTitle: "内容标题2", contentText: "内容文本2", image: "/images/bg-overview.png" },
],
}
return ( return (
<div> <div>
<h1></h1> <Banner
<p></p> title="银泰置地集团"
desc="商业地产的高品质代表"
titleSize="medium"
showBreadcrumb={true}
breadcrumbItems={[{ label: '集团业务', to: '/business' }, { label: '银泰置地集团', to: '/business/realty-group' }]}
backgroundImage={`/images/bg-overview.png`}
/>
<ParagraphSection data={paragraphSectionData} />
<TopTabsSection data={topTabsData} />
<RowAccordion data={rowAccordionData} />
<HonorGrids data={honorsData} />
<BottomTabsSection data={bottomTabsData} />
</div> </div>
); );
} }

View File

@ -0,0 +1,7 @@
.RuijingGroup {
}
.businessFeatureContent {
color: #fff;
}

View File

@ -0,0 +1,90 @@
import Banner from "@/components/Banner";
import { useState } from "react";
import SwiperCardSection from "@/components/layout/SwiperCardSection";
import HonorGrids from "@/components/layout/HonorGrids";
import ParagraphSection from "@/components/layout/ParagraphSection";
import Section from "@/components/layout/Section";
import styles from "./RuijingGroup.module.css";
import StatsRow from "@/components/layout/StatsRow/StatsRow";
export default function RuijingGroup() {
const [paragraphSectionData] = useState({
title: "瑞京资产",
content: "(全称“江西瑞京金融资产管理有限公司”) 成立于2018年1月公司是经江西省人民政府批准设立、中国银行保险监督管理委员会备案通过由银泰集团、赣州发展集团联合发起设立的江西省第二家、赣州市唯一一家地方资产管理公司AMC实缴注册资本金15亿元人民币。\n\n瑞京资产秉承服务实体经济的战略定位以不良资产的收购和处置为核心业务通过主动式资产管理纾困问题企业协助地方政府有效化解金融风险助力实体企业健康发展。",
statsData: [
{ num: "32 个", label: "全国在管项目" },
{ num: "475 万平方", label: "总建筑面积" },
{ num: "3 亿人次", label: "客流每年超" },
],
})
const swiperCardData = {
title: "业务架构",
cardItems: [
{ title: "不良债权收购", desc: "服务业态1", image: "/images/bg-overview.png" },
{ title: "债务重组", desc: "服务业态2", image: "/images/bg-overview.png" },
{ title: "投资管理", desc: "服务业态3", image: "/images/bg-overview.png" },
{ title: "金融服务", desc: "服务业态4", image: "/images/bg-overview.png" },
{ title: "个贷不良", desc: "服务业态5", image: "/images/bg-overview.png" },
{ title: "企业纾困", desc: "服务业态5", image: "/images/bg-overview.png" },
{ title: "问题企业流动性支持", desc: "服务业态5", image: "/images/bg-overview.png" },
],
}
const businessFeatureData = {
title: "业务特色",
subtitle: "发展个贷业务,支持青年重返信用体系",
content: "2024年瑞京资产成功竞得捷信264.64亿元资产包成为个人贷款批转业务史上规模最大的单次资产交易。此次交易标志着瑞京资产在个人贷款批转业务管理规模上突破300亿本金排名行业前三甲。深入挖掘资产背后“人”的价值支持全国特殊青年群体修复征信重返社会信用体系使更多青年赶上共同富裕的浪潮。",
statsData: [
{ num: '260 万+户', label: '减免债务惠及人群'},
{ num: '4 万+笔', label: '累计处置债务纠纷'},
]
}
const honorsData = {
title: "荣誉奖项",
items: [
{ title: "荣誉资质1" },
{ title: "荣誉资质2" },
{ title: "荣誉资质3" },
{ title: "荣誉资质4" },
{ title: "荣誉资质5" },
{ title: "荣誉资质6" },
{ title: "荣誉资质7" },
{ title: "荣誉资质8" },
],
}
return (
<div>
<Banner
title="瑞京资产"
desc="助力实体经济健康发展"
titleSize="medium"
showBreadcrumb={true}
breadcrumbItems={[{ label: '集团业务', to: '/business' }, { label: '瑞京资产', to: '' }]}
backgroundImage={`/images/bg-overview.png`}
/>
<ParagraphSection data={paragraphSectionData} />
<SwiperCardSection data={swiperCardData} />
<Section
title={businessFeatureData.title}
subtitle={businessFeatureData.subtitle}
titleColor="#fff"
background={`/images/bg-overview.png`}
maskBackground="rgba(2,17,48,0.5)"
>
<div className={styles.businessFeatureContent}>{businessFeatureData.content}</div>
<StatsRow data={businessFeatureData.statsData} color="#fff" />
</Section>
<HonorGrids data={honorsData} />
</div>
);
}

View File

@ -1,8 +0,0 @@
export default function BusinessRujingGroup() {
return (
<div>
<h1></h1>
<p></p>
</div>
);
}

View File

@ -1,8 +0,0 @@
export default function Business() {
return (
<div>
<h1></h1>
<p></p>
</div>
);
}

View File

@ -251,22 +251,6 @@
} }
/* News */ /* News */
.news {
padding: 5rem 3.75rem;
}
.newsInner {
margin: 0 auto;
}
.newsTitle {
font-size: 2.5rem;
font-weight: 700;
color: #222222;
text-align: center;
margin: 1.25rem 0 5rem;
}
.newsGrid { .newsGrid {
display: grid; display: grid;
grid-template-columns: 1fr 1fr; grid-template-columns: 1fr 1fr;
@ -280,9 +264,9 @@
.newsFeaturedImgWrap { .newsFeaturedImgWrap {
width: 59.375rem; width: 59.375rem;
max-width: 100%;
aspect-ratio: 950 / 560; aspect-ratio: 950 / 560;
background: linear-gradient(135deg, #e8e8e8 0%, #d0d0d0 100%); background: linear-gradient(135deg, #e8e8e8 0%, #d0d0d0 100%);
background: red;
overflow: hidden; overflow: hidden;
position: relative; position: relative;
} }

View File

@ -1,12 +1,51 @@
import { useState } from "react"; import { useState } from "react";
import styles from "./Home.module.css"; import styles from "./Home.module.css";
import Banner from "@/components/banner"; import Banner from "@/components/Banner";
import Section from "@/components/layout/Section";
import RowAccordion from "@/components/layout/RowAccordion";
const PUBLIC_URL = process.env.PUBLIC_URL || ""; const PUBLIC_URL = process.env.PUBLIC_URL || "";
const HERO_IMG = `${PUBLIC_URL}/images/bg-overview.png`; const HERO_IMG = `${PUBLIC_URL}/images/bg-overview.png`;
const FALLBACK_GRADIENT = "linear-gradient(135deg, #1a2a4a 0%, #2d4a7c 100%)"; const FALLBACK_GRADIENT = "linear-gradient(135deg, #1a2a4a 0%, #2d4a7c 100%)";
const newsData = [
export default function Home() {
const [commercialData] = useState({
items: [
{
title: "银泰商业集团",
content: "涵盖地标型高端商业综合体in77、景观地标型商业综合体inPARK区域型品质商业生活中心银泰城等品牌的大型商业集团是一家持续推动传统零售业创新与互联网转型融合的典范性企业。",
image: '/images/bg-commercial-group.png',
links: [{ text: 'in77', path: '/in77' }, { text: 'inPARK', path: '/inPARK' }, { text: '银泰城购物中心', path: '/shopping-center' },]
},
{
title: "银泰基业集团",
content: "银泰基业集团是银泰集团旗下核心业务板块,深耕商业地产与零售领域多年,致力于打造高品质商业空间,引领现代消费体验。集团旗下拥有银泰百货、银泰城等多个知名商业品牌,在全国多个核心城市布局,持续为消费者创造美好生活。",
image: '/images/bg-base-group.png',
links: [{ text: 'in77', path: '/in77' }, { text: 'inPARK', path: '/inPARK' }, { text: '银泰城购物中心', path: '/shopping-center' },]
},
{
title: "银泰置地集团",
content: "银泰置地集团是银泰集团旗下核心业务板块,深耕商业地产与零售领域多年,致力于打造高品质商业空间,引领现代消费体验。集团旗下拥有银泰百货、银泰城等多个知名商业品牌,在全国多个核心城市布局,持续为消费者创造美好生活。",
image: '/images/bg-realty-group.png',
links: [{ text: 'in77', path: '/in77' }, { text: 'inPARK', path: '/inPARK' }, { text: '银泰城购物中心', path: '/shopping-center' },]
},
{
title: "银泰投资集团",
content: "银泰投资集团是银泰集团旗下核心业务板块,深耕商业地产与零售领域多年,致力于打造高品质商业空间,引领现代消费体验。集团旗下拥有银泰百货、银泰城等多个知名商业品牌,在全国多个核心城市布局,持续为消费者创造美好生活。",
image: '/images/bg-invest-group.png',
links: [{ text: 'in77', path: '/in77' }, { text: 'inPARK', path: '/inPARK' }, { text: '银泰城购物中心', path: '/shopping-center' },]
},
{
title: "瑞京资产",
content: "瑞京集团是银泰集团旗下核心业务板块,深耕商业地产与零售领域多年,致力于打造高品质商业空间,引领现代消费体验。集团旗下拥有银泰百货、银泰城等多个知名商业品牌,在全国多个核心城市布局,持续为消费者创造美好生活。",
image: '/images/bg-ruijing-group.png',
links: [{ text: 'in77', path: '/in77' }, { text: 'inPARK', path: '/inPARK' }, { text: '银泰城购物中心', path: '/shopping-center' },]
},
]
})
const [newsData] = useState([
{ {
title: "银泰百货×敦煌研究院联名新品限量首发", title: "银泰百货×敦煌研究院联名新品限量首发",
snippet: "10月28日在杭州余杭区委城市工作会议暨城市新中心中轴线创新发展大会上银泰集团正式宣布银泰杭州新中心项目定名为“杭州银泰中银泰集团正式宣布银泰杭州新中心项目定名为“杭州银泰中银泰集团正式宣布银泰杭州新中心项目定名为“杭州银泰中", snippet: "10月28日在杭州余杭区委城市工作会议暨城市新中心中轴线创新发展大会上银泰集团正式宣布银泰杭州新中心项目定名为“杭州银泰中银泰集团正式宣布银泰杭州新中心项目定名为“杭州银泰中银泰集团正式宣布银泰杭州新中心项目定名为“杭州银泰中",
@ -25,81 +64,18 @@ const newsData = [
date: "2023-11-20", date: "2023-11-20",
path: "/news/3", path: "/news/3",
}, },
]; ]);
export default function Home() {
const [commercialList] = useState([
{
title: "银泰商业集团",
desc: "涵盖地标型高端商业综合体in77、景观地标型商业综合体inPARK区域型品质商业生活中心银泰城等品牌的大型商业集团是一家持续推动传统零售业创新与互联网转型融合的典范性企业。",
bgImg: '/images/bg-commercial-group.png',
links: [{ label: 'in77', to: '/in77' }, { label: 'inPARK', to: '/inPARK' }, { label: '银泰城购物中心', to: '/shopping-center' },]
},
{
title: "银泰基业集团",
desc: "银泰基业集团是银泰集团旗下核心业务板块,深耕商业地产与零售领域多年,致力于打造高品质商业空间,引领现代消费体验。集团旗下拥有银泰百货、银泰城等多个知名商业品牌,在全国多个核心城市布局,持续为消费者创造美好生活。",
bgImg: '/images/bg-base-group.png',
links: [{ label: 'in77', to: '/in77' }, { label: 'inPARK', to: '/inPARK' }, { label: '银泰城购物中心', to: '/shopping-center' },]
},
{
title: "银泰置地集团",
desc: "银泰置地集团是银泰集团旗下核心业务板块,深耕商业地产与零售领域多年,致力于打造高品质商业空间,引领现代消费体验。集团旗下拥有银泰百货、银泰城等多个知名商业品牌,在全国多个核心城市布局,持续为消费者创造美好生活。",
bgImg: '/images/bg-realty-group.png',
links: [{ label: 'in77', to: '/in77' }, { label: 'inPARK', to: '/inPARK' }, { label: '银泰城购物中心', to: '/shopping-center' },]
},
{
title: "银泰投资集团",
desc: "银泰投资集团是银泰集团旗下核心业务板块,深耕商业地产与零售领域多年,致力于打造高品质商业空间,引领现代消费体验。集团旗下拥有银泰百货、银泰城等多个知名商业品牌,在全国多个核心城市布局,持续为消费者创造美好生活。",
bgImg: '/images/bg-invest-group.png',
links: [{ label: 'in77', to: '/in77' }, { label: 'inPARK', to: '/inPARK' }, { label: '银泰城购物中心', to: '/shopping-center' },]
},
{
title: "瑞京集团",
desc: "瑞京集团是银泰集团旗下核心业务板块,深耕商业地产与零售领域多年,致力于打造高品质商业空间,引领现代消费体验。集团旗下拥有银泰百货、银泰城等多个知名商业品牌,在全国多个核心城市布局,持续为消费者创造美好生活。",
bgImg: '/images/bg-ruijing-group.png',
links: [{ label: 'in77', to: '/in77' }, { label: 'inPARK', to: '/inPARK' }, { label: '银泰城购物中心', to: '/shopping-center' },]
},
])
const [activeCommercialIndex, setActiveCommercialIndex] = useState(0);
return ( return (
<div> <div>
{/* Hero */} {/* Hero */}
<Banner title="银泰集团" desc="中国现代新商业典范" showBreadcrumb={false} backgroundImage={HERO_IMG}></Banner> <Banner title="银泰集团" desc="中国现代新商业典范" showBreadcrumb={false}
backgroundImage={['/images/bg-overview.png', '/images/bg-base-group.png']}></Banner>
{/* Commercial */} {/* Commercial */}
<section <RowAccordion data={commercialData} />
className={styles.commercial}
style={{
backgroundImage: `url(${commercialList[activeCommercialIndex].bgImg}), ${FALLBACK_GRADIENT}`,
}}
>
<div className={styles.commercialOverlay} />
<div className={styles.commercialContent}>
{commercialList.map((item, index) => (
<div key={item.title} className={styles.commercialItem}
style={{
flex: index === activeCommercialIndex ? 2.22 : 1,
}}
>
<h2 className={styles.commercialTitle} onMouseEnter={() => setActiveCommercialIndex(index)}>{item.title}</h2>
{index === activeCommercialIndex && (
<>
<p className={styles.commercialDesc}>{item.desc}</p>
<div className={styles.commercialLinks}>
{item.links.map((link) => (
<a key={link.label} href={link.to}>{link.label}</a>
))}
</div>
</>
)}
</div>
))}
</div>
</section>
{/* Cards */} {/* Cards */}
<section className={styles.cards}> <Section background="/images/bg-mask-card.png">
<div className={styles.cardsInner}> <div className={styles.cardsInner}>
<div className={`${styles.card} ${styles.cardSustainable}`}> <div className={`${styles.card} ${styles.cardSustainable}`}>
<div <div
@ -132,17 +108,15 @@ export default function Home() {
</div> </div>
</div> </div>
</div> </div>
</section> </Section>
{/* News */} {/* News */}
<section className={styles.news}> <Section title="新闻资讯" maskBackground="#F0F2F4">
<div className={styles.newsInner}>
<h2 className={styles.newsTitle}></h2>
<div className={styles.newsGrid}> <div className={styles.newsGrid}>
<div className={styles.newsFeatured}> <div className={styles.newsFeatured}>
<div className={styles.newsFeaturedImgWrap}> <div className={styles.newsFeaturedImgWrap}>
<img <img
src={`${PUBLIC_URL}/images/news-featured.png`} src={`/images/bg-overview.png`}
alt="新闻配图" alt="新闻配图"
className={styles.newsFeaturedImg} className={styles.newsFeaturedImg}
onError={(e) => { onError={(e) => {
@ -166,8 +140,7 @@ export default function Home() {
))} ))}
</div> </div>
</div> </div>
</div> </Section>
</section>
</div> </div>
); );
} }

View File

@ -0,0 +1,211 @@
.campusRow {
display: flex;
flex-direction: row;
justify-content: space-between;
.campusColLeft {
display: flex;
flex-direction: column;
gap: 30px;
.resetButton {
width: 340px;
height: 50px;
border-radius: 6px 6px 6px 6px;
border: 1px solid #14355C;
cursor: pointer;
font-weight: 400;
font-size: 16px;
color: #14355C;
line-height: 50px;
outline: none;
}
}
.campusColRight {
.jobList {
padding-bottom: 100px;
width: 960px;
min-height: 500px;
}
.jobItem {
width: 100%;
height: 200px;
border-radius: 0px 0px 0px 0px;
border-bottom: 1px solid #E5E5E5;
display: flex;
flex-direction: column;
gap: 15px;
padding: 30px 20px;
cursor: pointer;
transition: all 0.3s ease;
&:hover {
border-color: #14355C;
.jobItemTitle {
color: #14355C !important;
}
.jobItemTitleRight {
color: #14355C !important;
}
}
.jobItemTitleRow {
display: flex;
justify-content: space-between;
.jobItemTitle {
font-weight: 500;
font-size: 20px;
color: #222222;
line-height: 26px;
transition: all 0.3s ease;
}
.jobItemTitleRight {
font-weight: 400;
font-size: 16px;
color: #999999;
line-height: 22px;
transition: all 0.3s ease;
}
}
.jobItemLabels {
font-weight: 400;
font-size: 18px;
color: #333333;
line-height: 24px;
display: flex;
gap: 10px;
}
.jobItemContent {
font-weight: 400;
font-size: 16px;
color: #666666;
line-height: 30px;
/* 超过2行省略 */
display: -webkit-box;
-webkit-line-clamp: 2;
line-clamp: 2;
-webkit-box-orient: vertical;
overflow: hidden;
}
}
}
}
.searchInput {
width: 340px;
height: 50px;
border-radius: 6px 6px 6px 6px;
border: 1px solid #B6C0CB;
display: flex;
align-items: center;
justify-content: center;
padding: 14px;
overflow: hidden;
.searchIcon {
width: 24px;
height: 24px;
}
input {
border: none;
width: 100%;
height: 50px;
font-weight: 400;
font-size: 16px;
line-height: 22px;
&::placeholder {
font-weight: 400;
font-size: 16px;
color: #999999;
line-height: 22px;
}
&:focus {
outline: none;
}
}
}
.selectFormItem {
display: flex;
flex-direction: column;
}
.selectFormItemLabel {
font-size: 16px;
color: #666666;
display: block;
margin-bottom: 8px;
}
.selectFormItemBox {
width: 340px;
height: 50px;
border-radius: 6px;
border: 1px solid #B6C0CB;
padding: 0 14px;
display: flex;
align-items: center;
font-weight: 400;
font-size: 16px;
line-height: 22px;
background: #FFFFFF;
}
.selectFilterIcon {
margin-right: 5px;
color: #666666;
}
.selectFormItemSelect {
flex: 1;
min-width: 0;
}
.selectFormItemSelect:global(.ant-select) {
width: 100%;
height: 100%;
}
.selectFormItemSelect :global(.ant-select-selector) {
border: none !important;
background: transparent !important;
padding: 0 !important;
height: 100% !important;
min-height: auto !important;
box-shadow: none !important;
align-items: center;
}
.selectFormItemSelect :global(.ant-select-selection-placeholder),
.selectFormItemSelect :global(.ant-select-selection-item) {
font-weight: 400;
font-size: 16px;
line-height: 22px;
color: #222222;
}
.selectFormItemSelect :global(.ant-select-selection-placeholder) {
color: #999999;
}
.selectDownIcon {
margin-left: 5px;
color: #999999;
}

View File

@ -1,8 +1,174 @@
import { useCallback, useEffect, useState } from "react";
import styles from "./Campus.module.css";
import Banner from "@/components/Banner";
import Section from "@/components/layout/Section";
import { SearchOutlined, FilterOutlined, DownOutlined, RightOutlined } from "@ant-design/icons";
import { Empty, Select } from "antd";
import Pagination from "@/components/Pagination";
import { Link } from "react-router-dom";
import { debounce } from "@/utils";
type JobItem = {
id: number;
title: string;
content: string;
labels: string[];
}
export default function JoinCampus() { export default function JoinCampus() {
const [searchValue, setSearchValue] = useState('');
// 职业类别 业务领域 所属板块
const [jobType, setJobType] = useState('');
const [jobTypeOptions, setJobTypeOptions] = useState([
{ label: "全部", value: "" },
{ label: "职业类别1", value: "1" },
{ label: "职业类别2", value: "2" },
{ label: "职业类别3", value: "3" },
]);
const [businessArea, setBusinessArea] = useState('');
const [businessAreaOptions, setBusinessAreaOptions] = useState([]);
const [businessPlate, setBusinessPlate] = useState('');
const [businessPlateOptions, setBusinessPlateOptions] = useState([]);
const [page, setPage] = useState(1);
const [size] = useState(9);
const [total, setTotal] = useState(1000);
const [jobList, setJobList] = useState<JobItem[]>([]);
const refreshData = useCallback(debounce(() => {
console.log('refreshData2');
setJobList([
{ id: 1, title: '职位1', content: '工作职责1、为集团的各类投资项目提供法律支持包括组织外部律师进行尽职调查、审阅及起草交易文件、必要时参与法律谈判、提示法律风险等2、协助完善集团本部的规章制度和合规体系3、审阅集团各部门提交法务部审阅的日常业务法务部审阅的日常业务法务部审阅的日常业务', labels: ['标签1', '标签2'] },
{ id: 2, title: '职位2', content: '职位2内容', labels: ['标签1', '标签2'] },
{ id: 3, title: '职位3', content: '职位3内容', labels: ['标签1', '标签2'] },
])
}, 500), []);
useEffect(() => {
refreshData();
}, [searchValue, jobType, businessArea, businessPlate, page, size]);
const handleReset = useCallback(() => {
setSearchValue('');
setJobType('');
setBusinessArea('');
setBusinessPlate('');
setPage(1);
}, []);
return ( return (
<div> <div>
<h1></h1> <Banner
<p></p> title="招贤纳士"
titleSize="large"
showBreadcrumb={true}
breadcrumbItems={[{ label: '加入银泰', to: '/business' }, { label: '招贤纳士', to: '' }]}
backgroundImage={`/images/bg-overview.png`}
/>
<Section maskBackground="#FFFFFF">
<div className={styles.campusRow}>
<div className={styles.campusColLeft}>
<SearchInput value={searchValue} placeholder="搜索职位" onChange={setSearchValue} onEnter={refreshData} />
<SelectFormItem value={jobType} options={jobTypeOptions} label="职业类别" onChange={setJobType} />
<SelectFormItem value={businessArea} options={businessAreaOptions} label="业务领域" onChange={setBusinessArea} />
<SelectFormItem value={businessPlate} options={businessPlateOptions} label="所属板块" onChange={setBusinessPlate} />
<button className={styles.resetButton} onClick={handleReset}></button>
</div>
<div className={styles.campusColRight}>
<div className={styles.jobList}>
{/* 没有数据时显示 */}
{jobList.length === 0 && (
<div className={styles.noData}>
<Empty description="暂无数据" />
</div>
)}
{jobList.map(item => (
<Link to={`/join/campus/detail/${item.id}`}>
<div key={item.id} className={styles.jobItem}>
<div className={styles.jobItemTitleRow}>
<div className={styles.jobItemTitle}>{item.title}</div>
<div className={styles.jobItemTitleRight}> <RightOutlined /></div>
</div>
<div className={styles.jobItemLabels}>
{item.labels.map(label => (
<div key={label} className={styles.jobItemLabel}>&nbsp;&nbsp;&nbsp;{label}</div>
))}
</div>
<div className={styles.jobItemContent}>{item.content}</div>
</div></Link>
))}
</div>
<Pagination total={total} size={size} page={page} onChange={setPage} />
</div>
</div>
</Section>
</div>
);
}
type SearchInputProps = {
value: string;
placeholder: string;
onChange: (value: string) => void;
onEnter: () => void;
}
function SearchInput(
{ value, placeholder, onChange, onEnter }: SearchInputProps) {
return (
<div className={styles.searchInput}>
<label htmlFor="searchInput"><SearchOutlined className={styles.searchIcon} /></label>
<input
id="searchInput"
type="text"
placeholder={placeholder}
value={value}
onChange={e => onChange(e.target.value)}
onKeyDown={e => {
if (e.key === 'Enter') {
onEnter();
}
}}
/>
</div>
);
}
type SelectFormItemProps = {
value: string;
options: { label: string; value: string }[];
label: string;
onChange: (value: string) => void;
}
function SelectFormItem({ value, options, label, onChange }: SelectFormItemProps) {
return (
<div className={styles.selectFormItem}>
<label className={styles.selectFormItemLabel} htmlFor={`select-${label.replace(/\s/g, "-")}`}>{label}</label>
<div className={styles.selectFormItemBox}>
<Select
id={`select-${label.replace(/\s/g, "-")}`}
className={styles.selectFormItemSelect}
showSearch
placeholder="全部"
notFoundContent="无数据"
optionFilterProp="label"
filterOption={(input, opt) =>
(opt?.label ?? "").toString().toLowerCase().includes(input.toLowerCase())
}
options={options}
value={value}
onChange={v => onChange(v ?? "")}
prefix={<FilterOutlined className={styles.selectFilterIcon} />}
suffixIcon={<DownOutlined className={styles.selectDownIcon} />}
bordered={false}
/>
</div>
</div> </div>
); );
} }

View File

@ -0,0 +1,18 @@
import JobPage from "@/components/layout/JobPage";
export default function CampusDetail() {
const data = {
title: "项目营销总监",
jobType: "营销总监",
businessArea: "营销",
businessPlate: "营销",
recruitNumber: "2",
jobLocation: "杭州",
content: "国以才立政以才治业以才兴做好新形势下立法工作保障立法质量人才队伍是关键。自2020年起在银泰公益基金会的支持下浙江立法研究院、浙江大学立法研究院联合浙江大学光华法学院致力于助推立法学科建设经过一年多时间的不懈努力获批增设立法学二级学科并面向全国招收立法学专业硕士、博士研究生旨在积极响应新时代下国家对立法学理论研究和人才培养的需求践行依法护航经济社会发展的理念不断开展探索助推立法工作更好地为中国特色社会主义法治建设服务。",
}
return (
<div>
<JobPage data={data} />
</div>
)
}

View File

@ -0,0 +1,103 @@
.cultureItems {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 15px;
.cultureItem {
color: #fff;
/* width: 457px;
height: 560px; */
aspect-ratio: 457 / 560;
background-size: cover;
background-position: center;
background-repeat: no-repeat;
position: relative;
.cultureItemMaks {
position: absolute;
inset: 0;
background: rgba(0, 0, 0, 0.2);
transition: all 0.3s ease-in-out;
}
.cultureItemInner {
position: absolute;
inset: 0;
padding: 40px;
display: flex;
flex-direction: column;
justify-content: flex-end;
align-items: center;
.cultureItemTitle {
font-weight: 700;
font-size: 24px;
color: #FFFFFF;
line-height: 34px;
}
.cultureItemContent {
font-weight: 400;
font-size: 18px;
color: #FFFFFF;
line-height: 40px;
height: 0;
opacity: 0;
overflow: hidden;
transition: all 0.3s ease-in-out;
}
}
&:hover {
.cultureItemMaks {
background: rgba(20, 53, 92, 0.5);
}
.cultureItemContent {
height: 40px;
opacity: 1;
}
}
}
}
.valuesItems {
display: flex;
flex-direction: row;
justify-content: space-between;
margin: 0 140px;
.valuesItem {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
gap: 20px;
.valuesItemIcon {
width: 100px;
height: 100px;
background-size: cover;
background-position: center;
background-repeat: no-repeat;
margin-bottom: 15px;
}
.valuesItemTitle {
font-weight: 500;
font-size: 24px;
color: #222222;
line-height: 34px;
}
.valuesItemContent {
font-weight: 500;
font-size: 18px;
color: #222222;
line-height: 26px;
}
}
}

View File

@ -1,8 +1,65 @@
export default function JoinCulture() { import styles from "./Culture.module.css";
import Banner from "@/components/Banner";
import Section from "@/components/layout/Section";
export default function Culture() {
const cultureItems = {
title: '企业文化',
items: [
{ title: '使命', content: '做新商业典范,律正合作共享', backgroundImage: '/images/bg-overview.png' },
{ title: '愿景', content: '成为世界级商业地产集团', backgroundImage: '/images/bg-overview.png' },
{ title: '核心价值观', content: '诚信、合作、创新、共赢', backgroundImage: '/images/bg-overview.png' },
]
}
// 价值观
const valuesItems = {
title: '价值观',
items: [
{ title: '简单', content: '以心境简单 促问题解决', icon: '/images/bg-overview.png' },
{ title: '担当', content: '以心境简单 促问题解决', icon: '/images/bg-overview.png' },
{ title: '创新', content: '以心境简单 促问题解决', icon: '/images/bg-overview.png' },
]
}
return ( return (
<div> <div>
<h1></h1> <Banner
<p></p> title="企业文化"
titleSize="large"
showBreadcrumb={true}
breadcrumbItems={[{ label: '加入银泰', to: '/business' }, { label: '企业文化', to: '' }]}
backgroundImage={`/images/bg-overview.png`}
/>
<Section title={cultureItems.title} background="/images/bg-overview.png" maskBackground="#D8D8D8">
<div className={styles.cultureItems}>
{cultureItems.items.map((item, index) => (
<div key={index} className={styles.cultureItem} style={{ backgroundImage: `url(${item.backgroundImage})` }}>
<div className={styles.cultureItemMaks}></div>
<div className={styles.cultureItemInner}>
<div className={styles.cultureItemTitle}>{item.title}</div>
<div className={styles.cultureItemContent}>{item.content}</div>
</div>
</div>
))}
</div>
</Section>
<Section title={valuesItems.title} background="" maskBackground="rgba(216,216,216,0.6)">
<div className={styles.valuesItems}>
{valuesItems.items.map((item, index) => (
<div key={index} className={styles.valuesItem}>
<div className={styles.valuesItemIcon} style={{ backgroundImage: `url(${item.icon})` }}></div>
<div className={styles.valuesItemTitle}>{item.title}</div>
<div className={styles.valuesItemContent}>{item.content}</div>
</div>
))}
</div>
</Section>
</div> </div>
); );
} }

View File

@ -1,8 +0,0 @@
export default function Join() {
return (
<div>
<h1></h1>
<p></p>
</div>
);
}

View File

@ -1,8 +0,0 @@
export default function NewsConsult() {
return (
<div>
<h1></h1>
<p></p>
</div>
);
}

15
src/pages/News/Detail.tsx Normal file
View File

@ -0,0 +1,15 @@
import Article from "@/components/layout/Article";
export default function NewsDetail() {
const data = {
title: "汇聚立法智慧,培育立法人才",
createTime: "2026-03-03",
readTimes: "100",
content: "国以才立政以才治业以才兴做好新形势下立法工作保障立法质量人才队伍是关键。自2020年起在银泰公益基金会的支持下浙江立法研究院、浙江大学立法研究院联合浙江大学光华法学院致力于助推立法学科建设经过一年多时间的不懈努力获批增设立法学二级学科并面向全国招收立法学专业硕士、博士研究生旨在积极响应新时代下国家对立法学理论研究和人才培养的需求践行依法护航经济社会发展的理念不断开展探索助推立法工作更好地为中国特色社会主义法治建设服务。",
}
return (
<div>
<Article data={data} />
</div>
)
}

View File

@ -0,0 +1,39 @@
.mediaItems {
display: grid;
grid-template-columns: repeat(2, 1fr);
height: 500px;
.mediaItem {
height: 100%;
flex: 1;
display: flex;
flex-direction: column;
justify-content: center;
&:first-child {
border-right: 1px solid rgba(255,255,255,0.5);
padding-right: 60px;
}
&:last-child {
padding-left: 60px;
}
.mediaItemTitle {
font-weight: 500;
font-size: 40px;
color: #FFFFFF;
line-height: 50px;
text-align: center;
margin-bottom: 40px;
}
.mediaItemContent {
font-weight: 400;
font-size: 24px;
color: #FFFFFF;
line-height: 40px;
text-align: center;
white-space: pre-line;
}
}
}

View File

@ -1,8 +1,37 @@
export default function NewsMedia() { import styles from "./Media.module.css";
import Banner from "@/components/Banner";
import Section from "@/components/layout/Section";
export default function NewsPublic() {
const data = {
items: [
{ title: '新闻、采访拍摄', content: '如希望对银泰集团领导或具体项目进行采访、拍摄请拟写采访申请并附上采访提纲后提前10个工作日发送至 yintai.brand@china-yintai.com.cn' },
{ title: '联系我们', content: '综合类事项需求,请联系:(86-10) 8540 5700\n有采访类需求请联系(86-10) 8540 5757' },
]
}
return ( return (
<div> <div>
<h1></h1> <Banner
<p></p> title="媒体垂询"
titleSize="large"
showBreadcrumb={true}
breadcrumbItems={[{ label: '新闻中心', to: '/business' }, { label: '媒体垂询', to: '' }]}
backgroundImage={`/images/bg-overview.png`}
/>
<Section background="/images/bg-overview.png" maskBackground="rgba(1,11,72,0.8)">
<div className={styles.mediaItems}>
{data.items.map((item, index) => (
<div key={index} className={styles.mediaItem}>
<div className={styles.mediaItemTitle}>{item.title}</div>
<div className={styles.mediaItemContent}>{item.content}</div>
</div>
))}
</div>
</Section>
</div> </div>
); );
} }

View File

@ -0,0 +1,110 @@
.searchInputRow {
display: flex;
justify-content: flex-end;
.searchInput {
width: 340px;
height: 50px;
background: #FFFFFF;
border-radius: 6px 6px 6px 6px;
border: 1px solid #B6C0CB;
padding: 0 16px;
position: relative;
input {
width: 100%;
height: 100%;
border: none;
outline: none;
background: transparent;
font-weight: 500;
font-size: 18px;
color: #222222;
line-height: 26px;
}
.searchIcon {
position: absolute;
right: 16px;
top: 50%;
transform: translateY(-50%);
font-size: 16px;
color: #333;
}
}
}
.newList {
/* 3列 */
margin-top: 100px;
margin-bottom: 100px;
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 22px 30px;
.newItem {
/* height: 500px;
width: 452px; */
aspect-ratio: 452 / 500;
overflow: hidden;
display: flex;
flex-direction: column;
img {
width: 100%;
/* height: 300px; */
aspect-ratio: 452 / 300;
object-fit: cover;
cursor: pointer;
}
&:hover {
.newItemContent {
background: #14355C;
}
.newItemTitle,
.newItemCreateTime {
color: #fff !important;
}
}
.newItemContent {
width: 100%;
aspect-ratio: 452 / 200;
background: #fff;
padding: 20px 20px 40px;
display: flex;
flex-direction: column;
justify-content: space-between;
cursor: pointer;
transition: all 0.3s ease;
.newItemTitle {
font-weight: 500;
font-size: 20px;
color: #222222;
line-height: 30px;
text-align: justify;
font-style: normal;
text-transform: none;
transition: all 0.3s ease;
}
.newItemCreateTime {
font-weight: 400;
font-size: 16px;
color: #666666;
line-height: 22px;
text-align: justify;
font-style: normal;
text-transform: none;
transition: all 0.3s ease;
}
}
}
}

View File

@ -0,0 +1,79 @@
import { useCallback, useState } from "react";
import styles from "./NewsPublic.module.css";
import Banner from "@/components/Banner";
import Section from "@/components/layout/Section";
import { SearchOutlined } from "@ant-design/icons";
import Pagination from "@/components/Pagination";
import { Link } from "react-router-dom";
export default function NewsPublic() {
const [newList] = useState([
{
id: 1,
title: "新闻标题",
createTime: "2026-03-03",
image: "/images/bg-overview.png",
},
{
id: 1,
title: "新闻标题",
createTime: "2026-03-03",
image: "/images/bg-overview.png",
},
{
id: 1,
title: "新闻标题",
createTime: "2026-03-03",
image: "/images/bg-overview.png",
},
]);
const [searchValue, setSearchValue] = useState('');
const handleSearch = useCallback(() => {
console.log('search', searchValue);
}, [searchValue]);
const [page, setPage] = useState(1);
const [size] = useState(9);
const [total, setTotal] = useState(1000);
return (
<div>
<Banner
title="集团发布"
titleSize="large"
showBreadcrumb={true}
breadcrumbItems={[{ label: '新闻中心', to: '/business' }, { label: '集团发布', to: '' }]}
backgroundImage={`/images/bg-overview.png`}
/>
<Section maskBackground="rgba(216,216,216,0.4)">
<div className={styles.searchInputRow}>
<div className={styles.searchInput}>
<input value={searchValue} onChange={e => setSearchValue(e.target.value)} type="text" placeholder="搜索关键词" onKeyDown={e => {
if (e.key === 'Enter') {
handleSearch();
}
}} />
<SearchOutlined className={styles.searchIcon} onClick={handleSearch} />
</div>
</div>
<div className={styles.newList}>
{newList.map((item, index) => (
<Link key={index} to={`/news/detail/${item.id}`} className={styles.newItem}>
<img src={item.image} alt={item.title} />
<div className={styles.newItemContent}>
<div className={styles.newItemTitle}>{item.title}</div>
<div className={styles.newItemCreateTime}>{item.createTime}</div>
</div>
</Link>
))}
</div>
<Pagination total={total} size={size} page={page} onChange={setPage} />
</Section>
</div>
);
}

View File

@ -1,8 +0,0 @@
export default function News() {
return (
<div>
<h1></h1>
<p></p>
</div>
);
}

View File

@ -0,0 +1,42 @@
.auditReport {
display: grid;
grid-template-columns: 2fr 1fr;
gap: 200px;
.auditReportP {
font-size: 18px;
line-height: 34px;
color: #333333;
}
.auditReportQrCodeWrapper {
display: flex;
flex-direction: column;
justify-content: center;
}
.auditReportQrCode {
width: 189px;
height: 241px;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
.auditReportQrCodeTitle {
font-size: 24px;
margin-bottom: 20px;
}
.auditReportQrCodeImg {
width: 160px;
height: 160px;
}
.auditReportQrCodeText {
font-size: 14px;
color: #222;
margin-top: 5px;
}
}
}

View File

@ -0,0 +1,43 @@
import Banner from "@/components/Banner";
import Section from "@/components/layout/Section";
import styles from "./AuditReport.module.css";
export default function AuditReport() {
const data = {
content: `
<p style="font-weight: bold;font-size: 24px;">使</p>
<p>()使/使使</p>
<p>()使/使使</p>
`,
qrCode: '/images/bg-overview.png'
}
return (
<div>
<Banner
title="审计举报"
titleSize="large"
showBreadcrumb={true}
breadcrumbItems={[{ label: '审计举报', to: '' }]}
backgroundImage={`/images/bg-overview.png`}
/>
<Section background="" maskBackground="#fff">
<div className={styles.auditReport}>
<p className={styles.auditReportP} dangerouslySetInnerHTML={{ __html: data.content }}></p>
{
data.qrCode && (
<div className={styles.auditReportQrCodeWrapper}>
<div className={styles.auditReportQrCode}>
<span className={styles.auditReportQrCodeTitle}></span>
<img className={styles.auditReportQrCodeImg} src={data.qrCode} alt="" />
<span className={styles.auditReportQrCodeText}></span>
</div>
</div>
)
}
</div>
</Section>
</div>
);
}

View File

@ -0,0 +1,29 @@
import Banner from "@/components/Banner";
import Section from "@/components/layout/Section";
export default function PrivacyPolicy() {
const data = {
content: `
<p style="font-weight: bold;font-size: 24px;">使</p>
<p>()使/使使</p>
<p>()使/使使</p>
`
}
return (
<div>
<Banner
title="隐私保护"
titleSize="large"
showBreadcrumb={true}
breadcrumbItems={[{ label: '隐私保护', to: '' }]}
backgroundImage={`/images/bg-overview.png`}
/>
<Section background="" maskBackground="#fff">
<p style={{fontSize: '18px', lineHeight: '34px', color: '#333333'}} dangerouslySetInnerHTML={{ __html: data.content }}></p>
</Section>
</div>
);
}

View File

@ -0,0 +1,106 @@
.siteMap {
.siteMapTitle {
font-weight: 700;
font-size: 24px;
color: #14355C;
line-height: 34px;
}
.siteMapItems {
margin-top: 60px;
border-top: 1px solid #DDDDDD;
padding: 0 50px;
/* 主网格:标签列 + 5列子项列宽固定以实现跨行对齐 */
/* 第一列为180px */
display: grid;
grid-template-columns: 182px repeat(5, minmax(140px, 1fr));
.siteMapItem {
padding: 50px 0;
border-bottom: 1px solid #DDDDDD;
display: grid;
grid-template-columns: subgrid;
grid-column: 1 / -1;
.siteMapItemLabel {
padding-left: 50px;
font-weight: 700;
font-size: 18px;
color: #14355C;
position: relative;
&::after {
content: '';
display: block;
height: 30px;
width: 1px;
background: #DDDDDD;
position: absolute;
right: 0;
top: 0;
}
}
.siteMapItemChildren {
padding: 0 20px 0 60px;
display: grid;
grid-column: 2 / -1;
grid-template-columns: subgrid;
column-gap: 20px;
.siteMapItemChildLabel {
font-weight: bold;
font-size: 18px;
color: #222222;
line-height: 22px;
cursor: pointer;
&:hover {
color: #14355C;
}
}
.siteMapItemChildChildren {
font-weight: 400;
font-size: 18px;
color: #666666;
line-height: 22px;
display: flex;
flex-flow: column;
gap: 10px;
margin-top: 10px;
.siteMapItemChildChild {
cursor: pointer;
&:hover {
color: #14355C;
}
}
}
}
/* 每个子项占据对应列,实现表格对齐 */
.siteMapItemChild:nth-child(1) {
grid-column: 1;
}
.siteMapItemChild:nth-child(2) {
grid-column: 2;
}
.siteMapItemChild:nth-child(3) {
grid-column: 3;
}
.siteMapItemChild:nth-child(4) {
grid-column: 4;
}
.siteMapItemChild:nth-child(5) {
grid-column: 5;
}
}
}
}

View File

@ -0,0 +1,129 @@
import Banner from "@/components/Banner";
import Section from "@/components/layout/Section";
import styles from "./SiteMap.module.css";
import { Link } from "react-router-dom";
export default function SiteMap() {
const data = {
title: '网站地图',
// 菜单
items: [
{
label: "关于银泰",
path: "/about",
children: [
{ path: "/about", label: "集团概览" },
{ path: "/about/history", label: "发展历程" },
{ path: "/about/founder", label: "创始人介绍" },
],
},
{
label: "集团业务",
path: "/business",
children: [
{
path: "/business/commercial-group", label: "银泰商业集团",
children: [
{ path: "/business/commercial-group/in77", label: "in77" },
{ path: "/business/commercial-group/inPARK", label: "inPARK" },
{ path: "/business/commercial-group/银泰城购物中心", label: "银泰城购物中心" },
]
},
{ path: "/business/base-group", label: "银泰基业集团",
children: [
{ path: "/business/base-group#北京", label: "北京" },
{ path: "/business/base-group#上海", label: "上海" },
{ path: "/business/base-group#浙江", label: "浙江" },
{ path: "/business/base-group#四川", label: "四川" },
]
},
{ path: "/business/realty-group", label: "银泰置地集团",
children: [
{ path: "/business/realty-group#北京", label: "北京" },
{ path: "/business/realty-group#上海", label: "上海" },
{ path: "/business/realty-group#浙江", label: "浙江" },
{ path: "/business/realty-group#四川", label: "四川" },
]
},
{ path: "/business/invest-group", label: "银泰投资集团",
children: [
{ path: "/business/invest-group#发起设立", label: "发起设立" },
{ path: "/business/invest-group#股权投资", label: "股权投资" },
{ path: "/business/invest-group#产业孵化", label: "产业孵化" },
]
},
{ path: "/business/ruijing-group", label: "瑞京集团" },
],
},
{
label: "社会责任",
path: "/social",
children: [
{ path: "/social/sustainability", label: "可持续发展" },
{ path: "/social/foundation", label: "银泰公益基金会" },
],
},
{
label: "新闻中心",
path: "/news",
children: [
{ path: "/news/public", label: "集团发布" },
{ path: "/news/media", label: "媒体垂询" },
],
},
{
label: "其它",
path: "/others",
children: [
{ path: "/join/campus", label: "加入银泰" },
{ path: "/terms-of-use", label: "使用条款" },
{ path: "/privacy-policy", label: "隐私保护" },
],
},
]
}
return (
<div>
<Banner
title="网站地图"
titleSize="large"
showBreadcrumb={true}
breadcrumbItems={[{ label: '网站地图', to: '' }]}
backgroundImage={`/images/bg-overview.png`}
/>
<Section background="" maskBackground="#fff">
<div className={styles.siteMap}>
<div className={styles.siteMapTitle}></div>
<div className={styles.siteMapItems}>
{
data.items.map((item) => (
<div className={styles.siteMapItem} key={item.label}>
<div className={styles.siteMapItemLabel}>{item.label}</div>
<div className={styles.siteMapItemChildren}>
{
item.children.map((child) => (
<div className={styles.siteMapItemChild} key={child.label}>
<Link to={child.path} className={styles.siteMapItemChildLabel}>{child.label}</Link>
<div className={styles.siteMapItemChildChildren}>
{
child?.children && child?.children.map((childChild) => (
<Link to={childChild.path} className={styles.siteMapItemChildChild} key={childChild.label}>{childChild.label}</Link>
))
}
</div>
</div>
))
}
</div>
</div>
))
}
</div>
</div>
</Section>
</div>
);
}

View File

@ -0,0 +1,29 @@
import Banner from "@/components/Banner";
import Section from "@/components/layout/Section";
export default function TermsOfUse() {
const data = {
content: `
<p style="font-weight: bold;font-size: 24px;">使</p>
<p>()使/使使</p>
<p>()使/使使</p>
`
}
return (
<div>
<Banner
title="使用条款"
titleSize="large"
showBreadcrumb={true}
breadcrumbItems={[{ label: '使用条款', to: '' }]}
backgroundImage={`/images/bg-overview.png`}
/>
<Section background="" maskBackground="#fff">
<p style={{fontSize: '18px', lineHeight: '34px', color: '#333333'}} dangerouslySetInnerHTML={{ __html: data.content }}></p>
</Section>
</div>
);
}

View File

@ -1,5 +0,0 @@
.propertyService {
padding: 100px 260px;
background: rgba(255, 255, 255, 0.8);
}

View File

@ -1,18 +1,22 @@
import Banner from "@/components/banner"; import Banner from "@/components/Banner";
import styles from "./PropertyService.module.css";
import StatsRow from "@/components/layout/StatsRow/StatsRow";
import { useState } from "react"; import { useState } from "react";
import SectionTitle from "@/components/layout/SectionTitle";
import SwiperCardSection from "@/components/layout/SwiperCardSection"; import SwiperCardSection from "@/components/layout/SwiperCardSection";
import RowAccordion from "@/components/layout/RowAccordion";
import HonorGrids from "@/components/layout/HonorGrids";
import ParagraphSection from "@/components/layout/ParagraphSection";
export default function PropertyService() { export default function PropertyService() {
const [statsData] = useState([ const [paragraphSectionData] = useState({
title: "银泰智享物业",
content: "管理有限公司是一家集品质物业服务、资产托管运营、智慧物联管理、科技平台创新运维为一体的专业化物业服务企业,致力于商办类物业运营管理、打造资产全周期生态服务。\n\n 凭借银泰集团多年城市商业地产运营经验不断深化创新,银泰智享积极拓展业务深度与广度,做强基础物业服务,深耕客户卓越服务体验,创造企业多元化价值。核心业务涵盖资产全托管服务、资产顾问服务、资产设施服务、物业品牌合作等,着力实现服务体系化、标准化、精细化、智慧化“四化合一”,打造国内一流的物业管理品牌。",
statsData: [
{ num: "32 个", label: "全国在管项目" }, { num: "32 个", label: "全国在管项目" },
{ num: "475 万平方", label: "总建筑面积" }, { num: "475 万平方", label: "总建筑面积" },
{ num: "3 亿人次", label: "客流每年超" }, { num: "3 亿人次", label: "客流每年超" },
{ num: "350 亿元", label: "销售额每年" }, { num: "350 亿元", label: "销售额每年" },
{ num: "5000 +", label: "合作品牌" }, { num: "5000 +", label: "合作品牌" },
]) ],
})
const swiperCardData = { const swiperCardData = {
title: "服务业态", title: "服务业态",
@ -24,6 +28,30 @@ export default function PropertyService() {
{ title: "服务业态5", desc: "服务业态3", image: "/images/bg-overview.png" }, { title: "服务业态5", desc: "服务业态3", image: "/images/bg-overview.png" },
], ],
} }
const rowAccordionData = {
title: "标杆项目",
items: [
{ title: "北京银泰中心", image: "/images/bg-overview.png" },
{ title: "北京银泰吉祥大厦", image: "/images/bg-overview.png" },
{ title: "杭州城西银泰城", image: "/images/bg-overview.png" },
{ title: "杭州千岛湖银泰城", image: "/images/bg-overview.png" },
{ title: "桐庐银泰城", image: "/images/bg-overview.png" },
],
}
const honorsData = {
title: "企业价值",
items: [
{ title: "荣誉资质1" },
{ title: "荣誉资质2" },
{ title: "荣誉资质3" },
{ title: "荣誉资质4" },
{ title: "荣誉资质5" },
{ title: "荣誉资质6" },
{ title: "荣誉资质7" },
{ title: "荣誉资质8" },
],
}
return ( return (
<div> <div>
<Banner <Banner
@ -34,15 +62,13 @@ export default function PropertyService() {
backgroundImage={`/images/bg-overview.png`} backgroundImage={`/images/bg-overview.png`}
/> />
<section className={`${styles.propertyService} normal-p`}> <ParagraphSection data={paragraphSectionData} />
<div className={styles.propertyServiceContent}>
<p> </p>
<p>广</p>
</div>
<StatsRow statsData={statsData} />
</section>
<SwiperCardSection data={swiperCardData} /> <SwiperCardSection data={swiperCardData} />
<RowAccordion data={rowAccordionData} />
<HonorGrids data={honorsData} />
</div> </div>
); );
} }

View File

@ -0,0 +1,72 @@
/* 公益传播 */
.publicWelfareDataItems {
/* 2列 */
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 30px;
.publicWelfareDataItem {
position: relative;
overflow: hidden;
aspect-ratio: 685 / 460;
background-size: cover;
background-position: center;
background-repeat: no-repeat;
}
}
/* 信息公开 */
.informationPublicDataContent {
min-height: 500px;
display: flex;
flex-direction: column;
justify-content: space-between;
}
.informationPublicDataItems {
/* min-height: 400px; */
color: #fff;
font-weight: 400;
font-size: 20px;
line-height: 34px;
text-align: left;
font-style: normal;
text-transform: none;
padding: 0 90px 150px 90px;
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 20px;
li {
list-style: disc;
span {
cursor: pointer;
}
}
}
/* 公益伙伴 */
.partnerItems {
display: grid;
grid-template-columns: repeat(5, 1fr);
gap: 38px;
.partnerItem {
width: 250px;
height: 120px;
border-radius: 999px;
overflow: hidden;
box-shadow: 0 0 10px 0 rgba(0, 0, 0, 0.3);
display: flex;
align-items: center;
justify-content: center;
img {
width: 100%;
height: 100%;
object-fit: cover;
}
}
}

View File

@ -1,8 +1,170 @@
export default function SocialFoundation() { import Banner from "@/components/Banner";
import { useState } from "react";
import ParagraphSection from "@/components/layout/ParagraphSection";
import TopTabs from "@/components/layout/TopTabsSection/TopTabs";
import Section from "@/components/layout/Section";
import styles from "./Foundation.module.css";
import AnimateTopCard from "@/components/layout/AnimateTopCard";
import BottomTabs from "@/components/layout/BottomTabsSection/BottomTabs";
export default function Foundation() {
const [paragraphSectionData] = useState({
title: "银泰公益基金会",
content: "由银泰集团创始人兼董事长沈国军先生发起于2014年初在北京成立。银泰集团希望以此为平台以公益促进社会进步用创新公益模式立足生态环保、乡村振兴、应急救灾、公益教育等方向用实际行动体现银泰人对社会责任的坚守和担当。",
backgroundImage: "/images/Foundation-sectionbg-1.png",
})
const topTabsData = {
tabItems: [
{ tabName: "生态环保", contentTitle: "生态环保", contentSubtitle: "", contentText: "北京银泰中心是银泰置地集团在北京的核心项目,是集高端购物中心、酒店、公寓、超甲级写字楼等业态于一体的综合性商业地产项目。", image: "/images/bg-overview.png" },
{ tabName: "乡村振兴", contentTitle: "银泰中心", contentSubtitle: "", contentText: "北京银泰中心是银泰置地集团在北京的核心项目,是集高端购物中心、酒店、公寓、超甲级写字楼等业态于一体的综合性商业地产项目。", image: "/images/bg-overview.png" },
{ tabName: "应急救灾", contentTitle: "银泰中心", contentSubtitle: "", contentText: "北京银泰中心是银泰置地集团在北京的核心项目,是集高端购物中心、酒店、公寓、超甲级写字楼等业态于一体的综合性商业地产项目。", image: "/images/bg-overview.png" },
{ tabName: "公益教育", contentTitle: "银泰中心", contentSubtitle: "", contentText: "北京银泰中心是银泰置地集团在北京的核心项目,是集高端购物中心、酒店、公寓、超甲级写字楼等业态于一体的综合性商业地产项目。", image: "/images/bg-overview.png" },
],
}
const publicWelfareData = {
title: "公益传播",
items: [
{ title: "公益传播1", content: "北京银泰中心是银泰置地集团在北京的核心项目,是集高端购物中心、酒店、公寓、超甲级写字楼等业态于一体的综合性商业地产项目。", backgroundImage: "/images/bg-overview.png", link: '' },
{ title: "公益传播2", content: "北京银泰中心是银泰置地集团在北京的核心项目,是集高端购物中心、酒店、公寓、超甲级写字楼等业态于一体的综合性商业地产项目。", backgroundImage: "/images/bg-overview.png", link: '' },
{ title: "公益传播3", content: "北京银泰中心是银泰置地集团在北京的核心项目,是集高端购物中心、酒店、公寓、超甲级写字楼等业态于一体的综合性商业地产项目。", backgroundImage: "/images/bg-overview.png", link: '' },
{ title: "公益传播4", content: "北京银泰中心是银泰置地集团在北京的核心项目,是集高端购物中心、酒店、公寓、超甲级写字楼等业态于一体的综合性商业地产项目。", backgroundImage: "/images/bg-overview.png", link: '' },
],
}
const informationPublicData = {
title: "信息公开",
tabItems: [
{
tabName: '规章制度', fileItems: [
{ fileName: '规章制度1.pdf', link: '' },
{ fileName: '规章制度1.pdf', link: '' },
{ fileName: '规章制度1.pdf', link: '' },
{ fileName: '规章制度1.pdf', link: '' },
{ fileName: '规章制度1.pdf', link: '' },
{ fileName: '规章制度1.pdf', link: '' },
{ fileName: '规章制度1.pdf', link: '' },
{ fileName: '规章制度1.pdf', link: '' },
{ fileName: '规章制度1.pdf', link: '' },
{ fileName: '规章制度1.pdf', link: '' },
{ fileName: '规章制度1.pdf', link: '' },
{ fileName: '规章制度1.pdf', link: '' },
{ fileName: '规章制度1.pdf', link: '' },
{ fileName: '规章制度1.pdf', link: '' },
{ fileName: '规章制度1.pdf', link: '' },
]
},
{
tabName: '工作报告', fileItems: [
{ fileName: '规章制度1.pdf', link: '' },
{ fileName: '规章制度1.pdf', link: '' },
{ fileName: '规章制度1.pdf', link: '' },
{ fileName: '规章制度1.pdf', link: '' },
{ fileName: '规章制度1.pdf', link: '' },
]
},
{
tabName: '审计报告', fileItems: [
{ fileName: '规章制度1.pdf', link: '' },
{ fileName: '规章制度1.pdf', link: '' },
{ fileName: '规章制度1.pdf', link: '' },
{ fileName: '规章制度1.pdf', link: '' },
{ fileName: '规章制度1.pdf', link: '' },
]
},
{
tabName: '资质证书', fileItems: [
{ fileName: '规章制度1.pdf', link: '' },
{ fileName: '规章制度1.pdf', link: '' },
{ fileName: '规章制度1.pdf', link: '' },
{ fileName: '规章制度1.pdf', link: '' },
{ fileName: '规章制度1.pdf', link: '' },
]
},
{
tabName: '组织架构', fileItems: [
{ fileName: '规章制度1.pdf', link: '' },
{ fileName: '规章制度1.pdf', link: '' },
{ fileName: '规章制度1.pdf', link: '' },
{ fileName: '规章制度1.pdf', link: '' },
{ fileName: '规章制度1.pdf', link: '' },
]
},
],
backgroundImage: "/images/bg-overview.png",
}
const [activeIndex, setActiveIndex] = useState(0);
const partnerData = {
title: "公益伙伴",
items: [
{ logo: "/images/bg-overview.png" },
{ logo: "/images/bg-overview.png" },
{ logo: "/images/bg-overview.png" },
{ logo: "/images/bg-overview.png" },
{ logo: "/images/bg-overview.png" },
{ logo: "/images/bg-overview.png" },
],
}
return ( return (
<div> <div>
<h1></h1> <Banner
<p></p> title="平台思维,共享价值"
titleSize="medium"
showBreadcrumb={true}
breadcrumbItems={[{ label: '社会责任', to: '/business' }, { label: '银泰公益基金会', to: '' }]}
backgroundImage={`/images/bg-overview.png`}
/>
<ParagraphSection data={paragraphSectionData}>
<div style={{ marginTop: '100px' }}></div>
<TopTabs data={topTabsData} />
<div style={{ marginBottom: '50px' }}></div>
</ParagraphSection>
{/* 公益传播 */}
<Section title={publicWelfareData.title} background="" maskBackground="rgba(255,255,255,0.3)">
<div className={styles.publicWelfareDataItems}>
{publicWelfareData.items.map((item, index) => (
<div key={index} className={styles.publicWelfareDataItem} style={{ backgroundImage: `url(${item.backgroundImage})` }}>
<AnimateTopCard data={item} />
</div>
))}
</div>
<div style={{ marginBottom: '50px' }}></div>
</Section>
{/* 信息公开 */}
<Section title={informationPublicData.title} titleColor="#fff" background="/images/bg-overview.png" maskBackground="rgba(255,255,255,0.1)">
<div className={styles.informationPublicDataContent}>
<div className={styles.informationPublicDataItems}>
{
informationPublicData.tabItems[activeIndex].fileItems.map((item, index) => (
<div key={index} className={styles.informationPublicDataItem}>
<li><span>{item.fileName}</span></li>
</div>
))
}
</div>
<BottomTabs tabItems={informationPublicData.tabItems} activeIndex={activeIndex} setActiveIndex={setActiveIndex} />
</div>
</Section>
{/* 公益伙伴 */}
<Section title={partnerData.title} background="" maskBackground="#F7FBFF">
<div className={styles.partnerItems}>
{partnerData.items.map((item, index) => (
<div key={index} className={styles.partnerItem}>
<img src={item.logo} alt='logo' />
</div>
))}
</div>
</Section>
</div> </div>
); );
} }

View File

@ -20,36 +20,62 @@
background-repeat: no-repeat; background-repeat: no-repeat;
color: #fff; color: #fff;
position: relative; position: relative;
overflow: hidden;
.mask { .mask {
position: absolute; position: absolute;
width: 100%; width: 100%;
height: 100%; height: 100%;
background: rgba(0,0,0,0.1); background: rgba(0, 0, 0, 0.1);
} }
&:hover { &:hover {
.socialResponsibilityCaseDataItemContentInner { .socialResponsibilityCaseDataItemContentInner {
background: rgba(20,53,92,0.9); top: 0;
background: rgba(20, 53, 92, 0.9);
justify-content: flex-start; justify-content: flex-start;
transition-delay: 0s;
.socialResponsibilityCaseDataItemTitle { .socialResponsibilityCaseDataItemTitle {
text-align: left; left: 50px;
transform: translateX(0);
transition-delay: 0s;
} }
} }
.socialResponsibilityCaseDataItemContent { .socialResponsibilityCaseDataItemContent {
display: block; opacity: 1;
transition: opacity 0.3s ease 0.3s;
} }
} }
.socialResponsibilityCaseDataItemContentInner { .socialResponsibilityCaseDataItemContentInner {
padding: 50px; padding: 50px;
width: 100%; width: 100%;
height: 100%; height: 100%;
background: transparent; background: transparent;
transition: all 0.3s ease; transition: all 0.3s ease;
transition-delay: 0.2s;
position: absolute;
top: 75%;
.socialResponsibilityCaseDataItemMore {
display: inline-block;
margin-top: 60px;
width: 104px;
height: 38px;
border-radius: 0px 0px 0px 0px;
border: 1px solid #FFFFFF;
font-weight: 400;
font-size: 16px;
color: #FFFFFF;
line-height: 22px;
text-align: center;
display: flex; display: flex;
flex-direction: column; align-items: center;
justify-content: flex-end; justify-content: center;
}
} }
.socialResponsibilityCaseDataItemTitle { .socialResponsibilityCaseDataItemTitle {
@ -57,9 +83,11 @@
font-size: 24px; font-size: 24px;
color: #FFFFFF; color: #FFFFFF;
line-height: 34px; line-height: 34px;
text-align: center;
font-style: normal; font-style: normal;
text-transform: none; text-transform: none;
transition: all 0.3s ease;
transition-delay: 0.2s;
transform: translateX(50%);
} }
.socialResponsibilityCaseDataItemContent { .socialResponsibilityCaseDataItemContent {
@ -71,8 +99,12 @@
text-align: justify; text-align: justify;
font-style: normal; font-style: normal;
text-transform: none; text-transform: none;
display: none; opacity: 0;
transition: opacity 0.2s ease 0s;
} }
} }
/* 奇数行 [宽|窄]: 4n+1 宽, 4n+2 窄 */ /* 奇数行 [宽|窄]: 4n+1 宽, 4n+2 窄 */
@ -89,3 +121,56 @@
flex-basis: calc((100% - 30px) * 560 / 1370); flex-basis: calc((100% - 30px) * 560 / 1370);
aspect-ratio: 560 / 480; aspect-ratio: 560 / 480;
} }
.socialResponsibilityReportData {
/* 4列 */
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 33px;
.socialResponsibilityReportItem {
/* width: 325px; */
.socialResponsibilityReportItemCover {
/* width: 325px; */
/* height: 439px; */
aspect-ratio: 325 / 439;
box-shadow: 0px 0px 20px 0px rgba(0, 16, 32, 0.2);
background-size: cover;
background-position: center;
background-repeat: no-repeat;
}
.socialResponsibilityReportItemTitle {
font-weight: 500;
font-size: 18px;
color: #222222;
line-height: 26px;
text-align: center;
font-style: normal;
text-transform: none;
margin-top: 40px;
}
}
}
.socialResponsibilityReportItemMore {
width: 104px;
height: 38px;
line-height: 38px;
text-align: center;
border: 1px solid #333333;
font-size: 16px;
color: #333333;
cursor: pointer;
margin: 0 auto;
margin-top: 100px;
&:hover {
background: #14355C;
color: #fff;
}
}

View File

@ -1,8 +1,122 @@
export default function SocialSustainability() { import Banner from "@/components/Banner";
import { useState } from "react";
import ParagraphSection from "@/components/layout/ParagraphSection";
import ColumnXGrids from "@/components/layout/ColumnXGrids";
import Section from "@/components/layout/Section";
import styles from "./Sustainability.module.css";
import { Link } from "react-router-dom";
import AnimateTopCard from "@/components/layout/AnimateTopCard";
export default function Sustainability() {
const [paragraphSectionData] = useState({
title: "银泰集团",
content: "始终秉持“创造价值,服务社会”的使命,将社会责任融入企业发展的各个环节,形成了以合规治理、实业报国、经典品质、人才发展、绿色低碳、公益向善为核心的六大责任方向。银泰积极践行新发展理念,深度融入国家发展大局,持续投身乡村振兴、儿童关爱、社区共建等公益事业,以实际行动诠释企业担当,为实现人与自然、社会和谐共生的美好未来贡献力量",
})
const columnXGridsData = [
{
title: "合规治理",
content: "银泰集团夯实治理基础,持续提升数字化、智慧化管理水平。坚守合规经营,加强风险管理,以良好的企业治理作为公司健康、稳定、持续发展的基石。",
backgroundImage: "/images/bg-overview.png",
},
{
title: "实业报国",
content: "银泰集团坚定实业报国,积极投身国家重大战略和重点领域。通过优化产业布局,强化创新驱动,提升核心竞争力,为国家经济发展贡献力量。",
backgroundImage: "/images/bg-overview.png",
},
{
title: "经典品质",
content: "银泰集团夯实治理基础,持续提升数字化、智慧化管理水平。坚守合规经营,加强风险管理,以良好的企业治理作为公司健康、稳定、持续发展的基石。",
backgroundImage: "/images/bg-overview.png",
},
{
title: "人才发展",
content: "银泰集团夯实治理基础,持续提升数字化、智慧化管理水平。坚守合规经营,加强风险管理,以良好的企业治理作为公司健康、稳定、持续发展的基石。",
backgroundImage: "/images/bg-overview.png",
},
{
title: "绿色低碳",
content: "银泰集团夯实治理基础,持续提升数字化、智慧化管理水平。坚守合规经营,加强风险管理,以良好的企业治理作为公司健康、稳定、持续发展的基石。",
backgroundImage: "/images/bg-overview.png",
},
{
title: "公益向善",
content: "银泰集团夯实治理基础,持续提升数字化、智慧化管理水平。坚守合规经营,加强风险管理,以良好的企业治理作为公司健康、稳定、持续发展的基石。",
backgroundImage: "/images/bg-overview.png",
},
]
const socialResponsibilityCaseData = {
title: "社会责任案例集",
content: "银泰集团通过挖掘内部员工,外部消费者、品牌方、合作伙伴、受益人等不同利益相关方的案例故事,希望以一个个真实、鲜活的人物为线索,全方位展现银泰的责任担当,让大家感受到“爱@在一起”的温暖和力量。",
items: [
{title: "案例1向浙江大学教育基金会", content: "2019年银泰公益基金会向浙江大学教育基金会捐赠资金250万元专项支持浙江立法研究院的发展建设助力汇聚立法智慧、培育立法人才、引领智能立法、致力于建成全国性的立法研究高地和人才培养基地。", link: '', backgroundImage: "/images/bg-overview.png"},
{title: "案例2", content: "不管是从响应国家的绿色战略还是从企业自身长远发展的维度进行考量,提倡节能减排、绿色环保,都势在必行。", link: '', backgroundImage: "/images/bg-overview.png"},
{title: "案例3", content: "案例3内容", link: '', backgroundImage: "/images/bg-overview.png"},
{title: "案例4", content: "案例4内容", link: '', backgroundImage: "/images/bg-overview.png"},
]
}
const socialResponsibilityReportData = {
title: '社会责任报告',
items: [
{title: "2024年度报告.pdf", coverImage: "/images/bg-overview.png", link: ''},
{title: "2024年度报告.pdf", coverImage: "/images/bg-overview.png", link: ''},
{title: "2024年度报告.pdf", coverImage: "/images/bg-overview.png", link: ''},
{title: "2024年度报告.pdf", coverImage: "/images/bg-overview.png", link: ''},
{title: "2024年度报告.pdf", coverImage: "/images/bg-overview.png", link: ''},
{title: "2024年度报告.pdf", coverImage: "/images/bg-overview.png", link: ''},
{title: "2024年度报告.pdf", coverImage: "/images/bg-overview.png", link: ''},
{title: "2024年度报告.pdf", coverImage: "/images/bg-overview.png", link: ''},
]
}
const [sliceIndex, setSliceIndex] = useState(4)
return ( return (
<div> <div>
<h1></h1> <Banner
<p></p> title="可持续发展"
titleSize="medium"
showBreadcrumb={true}
breadcrumbItems={[{ label: '社会责任', to: '/business' }, { label: '可持续发展', to: '' }]}
backgroundImage={`/images/bg-overview.png`}
/>
<ParagraphSection data={paragraphSectionData} >
<ColumnXGrids items={columnXGridsData} />
</ParagraphSection>
{/* 社会责任案例集 */}
<Section title={socialResponsibilityCaseData.title} background="" maskBackground="rgba(255,255,255,0.3)">
<p className={styles.socialResponsibilityCaseDataContent}>
{socialResponsibilityCaseData.content}
</p>
<div className={styles.socialResponsibilityCaseDataItems}>
{socialResponsibilityCaseData.items.map((item,index) => (
<div key={index} className={styles.socialResponsibilityCaseDataItem} style={{ backgroundImage: `url(${item.backgroundImage})` }}>
<AnimateTopCard data={item} />
</div>
))}
</div>
</Section>
{/* 社会责任报告 */}
<Section title={socialResponsibilityReportData.title} background="" maskBackground="#F7FBFF">
<div className={styles.socialResponsibilityReportData}>
{socialResponsibilityReportData.items.slice(0, sliceIndex).map((item,index) => (
<div key={index} className={styles.socialResponsibilityReportItem}>
<div className={styles.socialResponsibilityReportItemCover} style={{ backgroundImage: `url(${item.coverImage})` }}></div>
<div className={styles.socialResponsibilityReportItemTitle}>{item.title}</div>
</div>
))}
</div>
<div className={styles.socialResponsibilityReportItemMore} onClick={() => setSliceIndex(sliceIndex < socialResponsibilityReportData.items.length ? sliceIndex + 4 : 4)}>
{sliceIndex < socialResponsibilityReportData.items.length ? "了解更多" : "收起"}
</div>
</Section>
</div> </div>
); );
} }

View File

@ -1,8 +0,0 @@
export default function Social() {
return (
<div>
<h1></h1>
<p></p>
</div>
);
}

8
src/utils/index.ts Normal file
View File

@ -0,0 +1,8 @@
// debounce
export const debounce = (func: (...args: any[]) => void, delay: number) => {
let timeout: NodeJS.Timeout;
return (...args: any[]) => {
clearTimeout(timeout);
timeout = setTimeout(() => func(...args), delay);
};
};