This commit is contained in:
zhangjianjun 2026-03-05 16:06:45 +08:00
parent 699e0c3a9a
commit 8502fdc6c3
31 changed files with 1533 additions and 1778 deletions

View File

@ -4,7 +4,7 @@ import "./App.css"
import routes from "@/Routes"; import routes from "@/Routes";
import { useCallback, useEffect, useState } from "react"; import { useCallback, useEffect, useState } from "react";
import appApi from "@/api/app"; import appApi from "@/api/app";
import { useStore } from "@/store"; import { useStore, type I18nData } from "@/store";
function AppRoutes() { function AppRoutes() {
return useRoutes(routes); return useRoutes(routes);
@ -12,9 +12,12 @@ function AppRoutes() {
function App() { function App() {
const [init, setInit] = useState(false); const [init, setInit] = useState(false);
const locale = useStore((s) => s.locale);
const appConfig = useStore((s) => s.appConfig);
const initState = useCallback((data: any) => { const initState = useCallback((data: Record<string, unknown>) => {
const { favicon, shortName } = data?.company?.config || {}; const company = data?.company as { config?: { favicon?: string; shortName?: string } } | undefined;
const { favicon, shortName } = company?.config || {};
if (favicon) { if (favicon) {
// 替换网页图标 // 替换网页图标
const favor: any = document.querySelector("link[rel*='icon']") || document.createElement('link'); const favor: any = document.querySelector("link[rel*='icon']") || document.createElement('link');
@ -29,24 +32,27 @@ function App() {
const getAppConfig = useCallback(async () => { const getAppConfig = useCallback(async () => {
try { try {
let res = await appApi.getAppConfig(); const res = await appApi.getAppConfig();
console.log('-------res', res) const data = res.data as I18nData;
let data = res.data;
useStore.getState().setAppConfig(data); useStore.getState().setAppConfig(data);
initState(data) const locale = useStore.getState().locale;
const config = data[locale] ?? data.zhCN;
initState(config);
} catch (error) { } catch (error) {
console.log(error) console.log(error);
} }
setInit(true); setInit(true);
}, []) }, [])
useEffect(() => { useEffect(() => {
if (init) { if (init) return;
return;
}
getAppConfig(); getAppConfig();
}, []) }, []);
useEffect(() => {
const shortName = (appConfig as { company?: { config?: { shortName?: string } } })?.company?.config?.shortName;
if (shortName) document.title = shortName;
}, [locale, appConfig]);
return ( return (
<> <>

View File

@ -1,18 +1,32 @@
/** /**
* *
* Header Footer path/label * mockData: {
* zhCN: {...},
* en: {...}
* }
*/ */
export type NavChild = { path: string; label: string }; export type NavChild = { path: string; label: string };
export type NavItem = { path: string; label: string; children?: NavChild[] }; export type NavItem = { path: string; label: string; children?: NavChild[]; index?: boolean };
export type LocaleKey = "zhCN" | "en";
const mockData = { const zhCN = {
// === 1. 全局/布局(优先) ===
companyName: "银泰", companyName: "银泰",
logo: "/images/logo.png", logo: "/images/logo.png",
company: {
config: {
favicon: "/favicon.ico",
shortName: "银泰",
},
},
header: { header: {
navItems: [ navItems: [
{
label: "首页",
path: "/",
index: true,
},
{ {
label: "关于银泰", label: "关于银泰",
path: "/about", path: "/about",
@ -59,7 +73,7 @@ const mockData = {
}, },
] as NavItem[], ] as NavItem[],
langMenuItems: [ langMenuItems: [
{ key: "zh", label: "中文" }, { key: "zhCN", label: "中文" },
{ key: "en", label: "English" }, { key: "en", label: "English" },
], ],
}, },
@ -157,6 +171,26 @@ const mockData = {
backgroundImage: "/images/welfare-check.png", backgroundImage: "/images/welfare-check.png",
}, },
], ],
newsData: [
{
title: "银泰百货×敦煌研究院联名新品限量首发",
snippet: "10月28日在杭州余杭区委城市工作会议暨城市新中心中轴线创新发展大会上银泰集团正式宣布银泰杭州新中心项目定名为「杭州银泰中心」",
date: "2024-01-15",
path: "/news/1",
},
{
title: "银泰中国区总裁陈晓:我们是长期主义者",
snippet: "10月28日在杭州余杭区委城市工作会议暨城市新中心中轴线创新发展大会上银泰集团正式宣布银泰杭州新中心项目定名为「杭州银泰中心」",
date: "2024-01-10",
path: "/news/2",
},
{
title: "中国青年发展基金会 | 银泰公益基金会合作签约",
snippet: "10月28日在杭州余杭区委城市工作会议暨城市新中心中轴线创新发展大会上银泰集团正式宣布银泰杭州新中心项目定名为「杭州银泰中心」",
date: "2023-11-20",
path: "/news/3",
},
],
}, },
about: { about: {
@ -318,7 +352,7 @@ const mockData = {
commercialGroupDetail: { commercialGroupDetail: {
banner: { banner: {
title: "in77", title: "in77",
largedesc: "地标型高端商业综合体", largeContent: "地标型高端商业综合体",
titleSize: "large", titleSize: "large",
showBreadcrumb: true, showBreadcrumb: true,
backgroundImage: "/images/bg-overview.png", backgroundImage: "/images/bg-overview.png",
@ -888,5 +922,85 @@ const mockData = {
}, },
}; };
const en: typeof zhCN = {
...zhCN,
companyName: "Yintai",
company: { config: { favicon: "/favicon.ico", shortName: "Yintai" } },
header: {
...zhCN.header,
navItems: [
{ label: "Home", path: "/", index: true },
{
label: "About Yintai",
path: "/about",
children: [
{ path: "/about/overview", label: "Overview" },
{ path: "/about/history", label: "History" },
{ path: "/about/founder", label: "Founder" },
],
},
{
label: "Business",
path: "/business",
children: [
{ path: "/business/commercial-group", label: "Yintai Commercial" },
{ path: "/business/base-group", label: "Yintai Base" },
{ path: "/business/realty-group", label: "Yintai Realty" },
{ path: "/business/invest-group", label: "Yintai Investment" },
{ path: "/business/ruijing-group", label: "Ruijing Group" },
],
},
{
label: "Social Responsibility",
path: "/social",
children: [
{ path: "/social/sustainability", label: "Sustainability" },
{ path: "/social/foundation", label: "Yintai Foundation" },
],
},
{
label: "News",
path: "/news",
children: [
{ path: "/news/public", label: "Press" },
{ path: "/news/media", label: "Media" },
],
},
{
label: "Join Yintai",
path: "/join",
children: [
{ path: "/join/culture", label: "Culture" },
{ path: "/join/campus", label: "Careers" },
],
},
] as NavItem[],
langMenuItems: [
{ key: "zhCN", label: "中文" },
{ key: "en", label: "English" },
],
},
footer: {
...zhCN.footer,
lowerLinks: [
{ path: "/contact-us", label: "Contact" },
{ path: "/site-map", label: "Site Map" },
{ path: "/terms-of-use", label: "Terms of Use" },
{ path: "/privacy-policy", label: "Privacy Policy" },
{ path: "/audit-report", label: "Audit Report" },
],
copyright: "Copyright ©2001-{year} | China Yintai Investment Co., Ltd.",
},
home: {
...zhCN.home,
banner: {
...zhCN.home.banner,
title: "Yintai Group",
content: "A Model of Modern Commerce in China",
},
},
};
export type LocaleConfig = typeof zhCN;
const mockData = { zhCN, en };
export default mockData; export default mockData;

View File

@ -4,20 +4,30 @@ import { Autoplay, EffectFade } from "swiper/modules";
import "swiper/css"; import "swiper/css";
import "swiper/css/effect-fade"; import "swiper/css/effect-fade";
import styles from "./Banner.module.css"; import styles from "./Banner.module.css";
import { useEffect } from "react"; import { useMemo } from "react";
import { useStore } from "@/store";
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 };
export type BannerConfig = {
title?: string;
content?: string;
subtitle?: string;
largeContent?: string;
titleSize?: "large" | "medium" | string;
showBreadcrumb?: boolean;
backgroundImage?: string | string[];
};
type Props = { type Props = {
title: string; title: string;
subtitle?: string; subtitle?: string;
desc?: string; desc?: string;
content?: string;
largedesc?: string; largedesc?: string;
showBreadcrumb?: boolean; showBreadcrumb?: boolean;
breadcrumbItems?: BreadcrumbItem[]; //废弃掉后改用pathname查找菜单名显示 titleSize?: "large" | "medium" | string;
titleSize?: "large" | "medium";
backgroundImage: string | string[]; backgroundImage: string | string[];
}; };
@ -25,21 +35,57 @@ export default function Banner({
title, title,
subtitle, subtitle,
desc, desc,
content,
largedesc, largedesc,
showBreadcrumb, showBreadcrumb,
breadcrumbItems,
titleSize = "large", titleSize = "large",
backgroundImage, backgroundImage,
}: Props) { }: Props) {
const appConfig = useStore((s) => s.appConfig);
const header = appConfig?.header;
const navItems = header?.navItems ?? [];
const location = useLocation(); const location = useLocation();
const images = Array.isArray(backgroundImage) ? backgroundImage : [backgroundImage]; const images = Array.isArray(backgroundImage) ? backgroundImage : [backgroundImage];
const isCarousel = images.length > 1; const isCarousel = images.length > 1;
const descText = desc ?? content;
const breadcrumbItems = useMemo(() => {
const segments = location.pathname.split("/").filter((s) => s !== "");
if (segments.length === 0) {
return [{ label: "首页", to: "/" }];
}
const paths: string[] = [];
for (let i = 0; i < segments.length; i++) {
paths.push((paths[i - 1] ?? "") + "/" + segments[i]);
}
const getLabelByPath = (path: string): string => {
if (path === "/") return navItems.find((n) => n.index)?.label ?? "首页";
const top = navItems.find((n) => n.path === path);
if (top) return top.label;
for (const item of navItems) {
const child = item.children?.find((c) => c.path === path);
if (child) return child.label;
}
const last = path.split("/").pop() ?? path;
return last;
};
const items = paths.map((path) => ({
label: getLabelByPath(path),
to: path,
}));
items.unshift({
label: navItems.find((n) => n.index)?.label ?? "首页",
to: "/",
});
return items;
}, [location.pathname, navItems]);
const heroContent = ( const heroContent = (
<div className={styles.heroContent} style={{ gap: "30px" }}> <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>} {descText && <p className={styles.heroDesc}>{descText}</p>}
{largedesc && <p className={styles.heroLargeDesc}>{largedesc}</p>} {largedesc && <p className={styles.heroLargeDesc}>{largedesc}</p>}
<div className={styles.breadcrumb}> <div className={styles.breadcrumb}>
{showBreadcrumb && {showBreadcrumb &&
@ -52,14 +98,6 @@ export default function Banner({
</div> </div>
</div> </div>
); );
// pathname
useEffect(() => {
const pathname = location.pathname;
console.log('pathname', pathname)
console.log('location', location)
},[location.pathname])
return ( return (
<section <section
className={styles.hero} className={styles.hero}

View File

@ -9,7 +9,8 @@ type Data = {
title: string; title: string;
cardItems: { cardItems: {
title: string; title: string;
desc: string; desc?: string;
content?: string;
image: string; image: string;
}[]; }[];
} }
@ -50,7 +51,7 @@ export default function SwiperCardSection({ data }: { data: Data }) {
<div className={styles.swiperTitle}> <div className={styles.swiperTitle}>
<span>{item.title}</span> <span>{item.title}</span>
</div> </div>
<p className={styles.swiperDesc}>{item.desc}</p> <p className={styles.swiperDesc}>{item.content ?? item.desc}</p>
</div> </div>
</div> </div>
</SwiperSlide> </SwiperSlide>

View File

@ -1,58 +1,27 @@
import { Link } from "react-router-dom"; import { Link } from "react-router-dom";
import styles from "./Footer.module.css"; import styles from "./Footer.module.css";
import { useStore } from "@/store";
const footerColumns = [
{
title: "关于银泰",
children: [
{ path: "/about", label: "公司简介" },
{ path: "/about/history", label: "发展历程" },
{ path: "/about/culture", label: "企业文化" },
],
},
{
title: "集团业务",
children: [
{ path: "/about", label: "银泰商业集团" },
{ path: "/business/base-group", label: "银泰基业集团" },
{ path: "/business/realty-group", label: "银泰置地集团" },
{ path: "/business/invest-group", label: "银泰投资集团" },
{ path: "/business/ruijing-group", label: "瑞京集团" },
],
},
{
title: "社会责任",
children: [
{ path: "/social", label: "可持续发展" },
{ path: "/social/sustainable", label: "银泰公益基金会" },
],
},
{
title: "新闻中心",
children: [
{ path: "/news", label: "银泰咨询" },
{ path: "/news/media", label: "媒体垂询" },
],
},
{
title: "加入我们",
children: [
{ path: "/join", label: "企业文化" },
{ path: "/join/campus", label: "招贤纳士" },
],
},
];
export default function Footer() { export default function Footer() {
const appConfig = useStore((s) => s.appConfig);
const footer = appConfig?.footer;
const header = appConfig?.header;
const footerColumns = header?.navItems?.filter((item) => !item.index) ?? [];
const lowerLinks = footer?.lowerLinks ?? [];
const socialIcons = footer?.socialIcons ?? [];
const copyright = footer?.copyright ?? "版权声明©2001-{year} | 中国银泰投资有限公司";
const icpNumber = footer?.icpNumber ?? "京ICP备05026114号-1";
return ( return (
<footer className={`layout-footer ${styles.footer}`}> <footer className={`layout-footer ${styles.footer}`}>
<div className={styles.footerUpper}> <div className={styles.footerUpper}>
<div> <div>
<div className={styles.footerGrid}> <div className={styles.footerGrid}>
{footerColumns.map((col) => ( {footerColumns.map((col) => (
<div key={col.title} className={styles.footerColumn}> <div key={col.path} className={styles.footerColumn}>
<div className={styles.footerTitle}>{col.title}</div> <div className={styles.footerTitle}>{col.label}</div>
{col.children.map((link) => ( {col.children?.map((link) => (
<Link <Link
key={link.path} key={link.path}
to={link.path} to={link.path}
@ -64,49 +33,54 @@ export default function Footer() {
</div> </div>
))} ))}
<div className={styles.footerRight}> <div className={styles.footerRight}>
<img src="/images/icon-weixin.png" alt="weixin" style={{ width: "26px", height: "26px" }} /> {socialIcons.map((icon) => (
<img src="/images/icon-weibo.png" alt="weibo" style={{ width: "26px", height: "26px" }} /> <img
<img src="/images/logo.png" alt="logo" style={{ width: "92px", height: "56px", background: '#000' }} /> key={icon.alt}
src={icon.src}
alt={icon.alt}
style={{ width: "26px", height: "26px" }}
/>
))}
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<FooterLower /> <FooterLower
lowerLinks={lowerLinks}
copyright={copyright.replace("{year}", String(new Date().getFullYear()))}
icpNumber={icpNumber}
/>
</footer> </footer>
); );
} }
function FooterLower({
function FooterLower() { lowerLinks,
const footerLowerLinks = [ copyright,
{ path: "/contact-us", label: "联系我们" }, icpNumber,
{ path: "/site-map", label: "网站地图" }, }: {
{ path: "/terms-of-use", label: "使用条款" }, lowerLinks: { path: string; label: string }[];
{ path: "/privacy-policy", label: "隐私保护" }, copyright: string;
{ path: "/audit-report", label: "审计举报" }, icpNumber: string;
] }) {
return ( return (
<div className={styles.footerLower}> <div className={styles.footerLower}>
<div className={`header-row ${styles.footerLowerInner}`}> <div className={`header-row ${styles.footerLowerInner}`}>
<div style={{ display: 'flex', flexDirection: 'row', gap: '50px' }}> <div style={{ display: "flex", flexDirection: "row", gap: "50px" }}>
<span>©2001-{new Date().getFullYear()} | </span> <span>{copyright}</span>
<span>ICP备05026114号-1</span> <span>{icpNumber}</span>
</div> </div>
<div className={styles.footerLowerLinks}> <div className={styles.footerLowerLinks}>
{footerLowerLinks.map((link, index) => ( {lowerLinks.map((link, index) => (
<> < >
<Link key={link.path} to={link.path} className={styles.footerLowerLink}> <Link to={link.path} className={styles.footerLowerLink}>
{link.label} {link.label}
</Link> </Link>
{ {index !== lowerLinks.length - 1 && <span>·</span>}
index !== footerLowerLinks.length - 1 && (
<span>·</span>
)
}
</> </>
))} ))}
</div> </div>
</div> </div>
</div> </div>
) );
} }

View File

@ -2,70 +2,27 @@ 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 { useEffect, useMemo, useState } from "react"; import { useEffect, useMemo, useState } from "react";
import { useStore } from "@/store";
import type { NavChild } from "@/api/mockData";
import type { LocaleKey } from "@/store";
type NavChild = { path: string; label: string }; const DEFAULT_NAV_ITEMS: { path: string; label: string; children?: NavChild[] }[] = [];
type NavItem = { path: string; label: string; children?: NavChild[] }; const DEFAULT_LANG_ITEMS = [{ key: "zh", label: "中文" }, { key: "en", label: "English" }];
export default function Header() { export default function Header() {
const location = useLocation(); const location = useLocation();
const appConfig = useStore((s) => s.appConfig);
const locale = useStore((s) => s.locale);
const setLocale = useStore((s) => s.setLocale);
const navItems: NavItem[] = [ const navItems = appConfig?.header?.navItems?.filter((item) => !item.index) ?? DEFAULT_NAV_ITEMS;
{ const langMenuItems = appConfig?.header?.langMenuItems ?? DEFAULT_LANG_ITEMS;
label: "关于银泰", const logo = appConfig?.logo ?? "/images/logo.png";
path: "/about",
children: [
{ path: "/about/overview", label: "集团概览" },
{ path: "/about/history", label: "发展历程" },
{ path: "/about/founder", label: "创始人介绍" },
],
},
{
label: "集团业务",
path: "/business",
children: [
{ path: "/business/commercial-group", label: "银泰商业集团" },
{ path: "/business/base-group", label: "银泰基业集团" },
{ path: "/business/realty-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: "/join",
children: [
{ path: "/join/culture", label: "企业文化" },
{ path: "/join/campus", label: "招贤纳士" },
],
},
];
const langMenuItems = [
{ key: "zh", label: "中文" },
{ key: "en", label: "English" },
];
const [activeNav, setActiveNav] = useState(""); const [activeNav, setActiveNav] = useState("");
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)
// left + 元素宽度的一半 // left + 元素宽度的一半
const left = e.target.offsetLeft; const left = e.target.offsetLeft;
setHoverElLeft(left); setHoverElLeft(left);
@ -110,7 +67,7 @@ export default function Header() {
> >
<div className={`header-row ${styles.headerInner}`}> <div className={`header-row ${styles.headerInner}`}>
<Link to="/" className={styles.logo}> <Link to="/" className={styles.logo}>
<img src="/images/logo.png" alt="logo" style={{ width: "5.75rem", height: "3.4375rem" }} /> <img src={logo} alt="logo" style={{ width: "5.75rem", height: "3.4375rem" }} />
</Link> </Link>
<div className={styles.headerRight}> <div className={styles.headerRight}>
<nav> <nav>
@ -129,12 +86,19 @@ export default function Header() {
<svg xmlns="http://www.w3.org/2000/svg" fill="none" version="1.1" width="26" height="26" viewBox="0 0 26 26"><g><path d="M16.739973374999998,17.76985499081421C15.429279375,18.85114099081421,13.749150275,19.50064899081421,11.917317875,19.50064899081421C7.729150975,19.50064899081421,4.333984375,16.105480990814208,4.333984375,11.91731549081421C4.333984375,7.729148590814209,7.729150975,4.333981990814209,11.917317875,4.333981990814209C16.105485375,4.333981990814209,19.500651375,7.729148590814209,19.500651375,11.91731549081421C19.500651375,13.80559489081421,18.810497375,15.532677990814209,17.668674375000002,16.86007799081421L21.741985375,20.93338899081421C21.953518375,21.144921990814208,21.953518375,21.48788599081421,21.741983375,21.69941999081421L21.588777375,21.852625990814207C21.377243375,22.06416099081421,21.034278375,22.06416099081421,20.822744375,21.852625990814207L16.739973374999998,17.76985499081421ZM18.199479375,11.916142890814209C18.199479375,15.38633899081421,15.386343375,18.199475990814207,11.916145775,18.199475990814207C8.445947675,18.199475990814207,5.632812475,15.38633899081421,5.632812475,11.916142890814209C5.632812475,8.44594479081421,8.445947675,5.632810090814209,11.916145775,5.632810090814209C15.386343375,5.632810090814209,18.199479375,8.44594479081421,18.199479375,11.916142890814209Z" fillRule="evenodd" fill="#FFFFFF" fillOpacity="1" /></g></svg> <svg xmlns="http://www.w3.org/2000/svg" fill="none" version="1.1" width="26" height="26" viewBox="0 0 26 26"><g><path d="M16.739973374999998,17.76985499081421C15.429279375,18.85114099081421,13.749150275,19.50064899081421,11.917317875,19.50064899081421C7.729150975,19.50064899081421,4.333984375,16.105480990814208,4.333984375,11.91731549081421C4.333984375,7.729148590814209,7.729150975,4.333981990814209,11.917317875,4.333981990814209C16.105485375,4.333981990814209,19.500651375,7.729148590814209,19.500651375,11.91731549081421C19.500651375,13.80559489081421,18.810497375,15.532677990814209,17.668674375000002,16.86007799081421L21.741985375,20.93338899081421C21.953518375,21.144921990814208,21.953518375,21.48788599081421,21.741983375,21.69941999081421L21.588777375,21.852625990814207C21.377243375,22.06416099081421,21.034278375,22.06416099081421,20.822744375,21.852625990814207L16.739973374999998,17.76985499081421ZM18.199479375,11.916142890814209C18.199479375,15.38633899081421,15.386343375,18.199475990814207,11.916145775,18.199475990814207C8.445947675,18.199475990814207,5.632812475,15.38633899081421,5.632812475,11.916142890814209C5.632812475,8.44594479081421,8.445947675,5.632810090814209,11.916145775,5.632810090814209C15.386343375,5.632810090814209,18.199479375,8.44594479081421,18.199479375,11.916142890814209Z" fillRule="evenodd" fill="#FFFFFF" fillOpacity="1" /></g></svg>
</Link> </Link>
<Dropdown <Dropdown
menu={{ items: langMenuItems }} menu={{
items: langMenuItems.map((item) => ({
...item,
onClick: () => setLocale(item.key as LocaleKey),
})),
}}
placement="bottomRight" placement="bottomRight"
trigger={["click"]} trigger={["click"]}
> >
<button className={styles.langTrigger} type="button"> <button className={styles.langTrigger} type="button">
<span style={{fontSize: '18px'}}></span> <span style={{ fontSize: "18px" }}>
{langMenuItems.find((i) => i.key === locale)?.label ?? "中文"}
</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>

View File

@ -1,8 +1,15 @@
import { Outlet } from "react-router-dom"; import { Outlet, useLocation } from "react-router-dom";
import { useEffect } from "react";
import Header from "./Header"; import Header from "./Header";
import Footer from "./Footer"; import Footer from "./Footer";
export default function MainLayout() { export default function MainLayout() {
const { pathname } = useLocation();
useEffect(() => {
window.scrollTo(0, 0);
}, [pathname]);
return ( return (
<div className="layout"> <div className="layout">
<Header /> <Header />

View File

@ -1,59 +1,56 @@
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 ParagraphSection from "@/components/layout/ParagraphSection"; import ParagraphSection from "@/components/layout/ParagraphSection";
import Section from "@/components/layout/Section"; import { useStore } from "@/store";
export default function AboutFounder() { export default function AboutFounder() {
const [section1Data] = useState({ const appConfig = useStore((s) => s.appConfig);
title: "沈国军", const founder = appConfig?.about?.founder;
content: "汉族,博士,高级经济师。中国人民政治协商会议第十一届、十三届全国委员会委员、中国人民政治协商会议第十三届全国委员会提案委员会委员、中国致公党第十四届、十五届、十六届中央委员会常委、第一届浙商(全球)总会执行会长、第一届甬商(全球)总会会长。\n\n 银泰集团(全称“中国银泰投资有限公司”)创始人兼董事长、银泰公益基金会创始人及荣誉理事长、桃花源生态保护基金会董事局执行主席。",
items: [
{
title: "商业领域",
image: "/images/bg-invest-group.png",
desc: "银泰集团在商业领域有着丰富的经验和深厚的实力,致力于打造高品质的商业空间,引领现代消费体验。",
},
{
title: "社会责任",
image: "/images/bg-invest-group.png",
desc: "银泰集团在社会责任方面有着丰富的经验和深厚的实力,致力于打造高品质的商业空间,引领现代消费体验。",
},
]
})
const [section2Data] = useState({ const banner = founder?.banner;
title: "企业家精神", const section1Data = founder?.section1Data;
subtitle: "一个优秀的企业家,要传承、弘扬传统优秀的商道,继续开创新的商业文明。创新与变革、勤奋与进取、分享与合作、诚信与责任是沈国军所倡导的企业家精神。", const section2Data = founder?.section2Data;
backgroundImage: '',
sideImage: "/images/bg-invest-group.png",
content: "银泰集团在社会责任方面有着丰富的经验和深厚的实力,致力于打造高品质的商业空间,引领现代消费体验。",
})
if (!founder) return null;
return ( return (
<div> <div>
<Banner title="创始人介绍" subtitle="银泰集团创始人、董事长——沈国军" <Banner
desc="卓越的变革践行者、产业推动者及社会公民" title={banner?.title ?? ""}
showBreadcrumb={true} backgroundImage={'/images/bg-overview.png'}></Banner> subtitle={banner?.subtitle}
desc={banner?.content}
showBreadcrumb={banner?.showBreadcrumb ?? false}
backgroundImage={banner?.backgroundImage ?? "/images/bg-overview.png"}
/>
<ParagraphSection data={section1Data} > {section1Data && (
<ParagraphSection data={section1Data}>
<div className={styles.images}> <div className={styles.images}>
{section1Data.items.map((item, index) => ( {section1Data.items?.map((item, index) => (
<div className={styles.imageItem} key={item.title}> <div className={styles.imageItem} key={item.title}>
<img src={item.image} alt={item.title} /> <img src={item.image} alt={item.title} />
<div className={styles.imageMask}></div> <div className={styles.imageMask} />
<div className={styles.imageOverlay}> <div className={styles.imageOverlay}>
<div className={styles.imageOverlayTitle}> <div className={styles.imageOverlayTitle}>
<span>{item.title}</span> <span>{item.title}</span>
</div> </div>
<div className={styles.imageOverlayDesc}>{item.desc}</div> <div className={styles.imageOverlayDesc}>{item.content}</div>
</div> </div>
</div> </div>
))} ))}
</div> </div>
</ParagraphSection> </ParagraphSection>
)}
<section className={styles.sectionFounder} style={{ backgroundImage: `url(${section2Data.backgroundImage})` }}> {section2Data && (
<section
className={styles.sectionFounder}
style={{
backgroundImage: section2Data.backgroundImage
? `url(${section2Data.backgroundImage})`
: undefined,
}}
>
<div className={styles.founderIntroduction}> <div className={styles.founderIntroduction}>
<h2>{section2Data.title}</h2> <h2>{section2Data.title}</h2>
<p>{section2Data.subtitle}</p> <p>{section2Data.subtitle}</p>
@ -61,10 +58,11 @@ export default function AboutFounder() {
<div className={styles.founderPhoto}> <div className={styles.founderPhoto}>
<img src={section2Data.sideImage} alt="个人照" /> <img src={section2Data.sideImage} alt="个人照" />
<div className={styles.founderPhotoContent}> <div className={styles.founderPhotoContent}>
<p dangerouslySetInnerHTML={{ __html: section2Data.content }} ></p> <p dangerouslySetInnerHTML={{ __html: section2Data.content ?? "" }} />
</div> </div>
</div> </div>
</section> </section>
)}
</div> </div>
); );
} }

View File

@ -2,49 +2,46 @@ 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";
import { useStore } from "@/store";
type TimelineItem = { year: number; description: string }; type TimelineItem = { year: number; content: string };
const TIMELINE_DATA: TimelineItem[] = [
{ year: 2025, description: "银泰集团持续深化战略布局,推动高质量发展。" },
{ year: 2024, description: "银泰集团创新发展模式,拓展业务新领域。" },
{ year: 2023, description: "银泰集团核心业务稳健增长,品牌影响力持续提升。" },
{ year: 2022, description: "银泰集团深化数字化转型,提升运营效率。" },
{ year: 2018, description: "银泰集团推进战略转型升级,开启新篇章。" },
{ year: 2016, description: "银泰集团拓展多元化业务,夯实发展基础。" },
{ year: 2015, description: "银泰集团完善产业布局,增强核心竞争力。" },
{ year: 2014, description: "银泰集团加速全国化扩张,品牌影响力扩大。" },
{ year: 2013, description: "银泰集团稳健发展,主营业务持续向好。" },
{ year: 2010, description: "银泰集团抓住市场机遇,实现跨越式发展。" },
{ year: 2009, description: "银泰集团应对金融危机,保持稳健经营。" },
{ year: 2008, description: "银泰集团完善管理体系,提升运营水平。" },
{ year: 2007, description: "银泰集团上市,开启资本化发展新征程。" },
{ year: 1998, description: "银泰集团快速成长,确立行业领先地位。" },
{ year: 1997, description: "银泰集团成立,迈出创业第一步。" },
];
export default function AboutHistory() { export default function AboutHistory() {
const appConfig = useStore((s) => s.appConfig);
const history = appConfig?.about?.history;
const banner = history?.banner;
const section1Data = (history?.section1Data ?? []) as TimelineItem[];
const [year, setYear] = useState<number | null>(null); const [year, setYear] = useState<number | null>(null);
const handleYearChange = (year: number | null) => { const handleYearChange = (year: number | null) => {
setYear(year); setYear(year);
// 滚动到对应的年份
const yearEl = document.querySelector(`#year-${year}`); const yearEl = document.querySelector(`#year-${year}`);
if (yearEl) { if (yearEl) {
yearEl.scrollIntoView({ behavior: "smooth" }); yearEl.scrollIntoView({ behavior: "smooth" });
} }
}; };
if (!history) return null;
return ( return (
<div> <div>
<Banner title="发展历程" desc="银泰集团的发展历程" showBreadcrumb={true} backgroundImage={'/images/bg-overview.png'}></Banner> <Banner
title={banner?.title ?? ""}
desc={banner?.content}
showBreadcrumb={banner?.showBreadcrumb ?? false}
backgroundImage={banner?.backgroundImage ?? "/images/bg-overview.png"}
/>
<section className={styles.section}> <section className={styles.section}>
<div className={styles.headRow}> <div className={styles.headRow}>
<YearPicker placeholder="年份" value={year} onChange={handleYearChange} /> <YearPicker placeholder="年份" value={year} onChange={handleYearChange} />
</div> </div>
<HistoryTimeline data={TIMELINE_DATA} selectedYear={year} onYearChange={setYear} /> <HistoryTimeline
data={section1Data}
selectedYear={year}
onYearChange={setYear}
/>
</section> </section>
</div> </div>
); );
@ -93,7 +90,7 @@ function TimelineItemRow({
{!isRight && ( {!isRight && (
<div onMouseEnter={onMouseEnter}> <div onMouseEnter={onMouseEnter}>
<span className={styles.year}>{item.year}</span> <span className={styles.year}>{item.year}</span>
<p className={styles.desc}>{item.description}</p> <p className={styles.desc}>{item.content}</p>
</div> </div>
)} )}
</div> </div>
@ -105,7 +102,7 @@ function TimelineItemRow({
{isRight && ( {isRight && (
<div onMouseEnter={onMouseEnter}> <div onMouseEnter={onMouseEnter}>
<span className={styles.year}>{item.year}</span> <span className={styles.year}>{item.year}</span>
<p className={styles.desc}>{item.description}</p> <p className={styles.desc}>{item.content}</p>
</div> </div>
)} )}
</div> </div>

View File

@ -1,66 +1,34 @@
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";
import { useStore } from "@/store";
const FALLBACK_GRADIENT = "linear-gradient(135deg, #1a2a4a 0%, #2d4a7c 100%)"; const FALLBACK_GRADIENT = "linear-gradient(135deg, #1a2a4a 0%, #2d4a7c 100%)";
type SectionLink = { label: string; to: string };
type SectionItem = {
title: string;
desc: string;
bgImg: string;
links: SectionLink[];
};
const sectionData: SectionItem[] = [
{
title: "银泰商业集团",
desc: "涵盖地标型高端商业综合体in77、景观地标型商业综合体inPARK区域型品质商业生活中心银泰城等品牌的大型商业集团是一家持续推动传统零售业创新与互联网转型融合的典范性企业。",
bgImg: '/images/bg-commercial-group.png',
links: [{ label: 'in77', to: '/business/commercial-group/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' },]
}
];
export default function About() { export default function About() {
const appConfig = useStore((s) => s.appConfig);
const overview = appConfig?.about?.overview;
const banner = overview?.banner;
const section1Data = overview?.section1Data ?? [];
if (!overview) return null;
return ( return (
<div> <div>
<Banner <Banner
title="集团概览" title={banner?.title ?? ""}
desc="银泰集团全称“中国银泰投资有限公司”由沈国军先生于1997年创立立足实业发展与产业投资业务涵盖商业零售、商业地产运营与开发、股权投资等领域在境内外拥有多家控股、参股公司已发展成为一家主业突出、多元发展的现代企业集团。" desc={banner?.content}
showBreadcrumb={true} showBreadcrumb={banner?.showBreadcrumb ?? false}
breadcrumbItems={[{ label: '关于银泰', to: '/about' }, { label: '集团概览', to: '' }]} backgroundImage={banner?.backgroundImage ?? "/images/bg-overview.png"}
backgroundImage={'/images/bg-overview.png'} /> />
{sectionData.map((item, index) => ( {section1Data.map((item, index) => (
<section <section
key={index} key={index}
className={`${styles.section} ${index % 2 === 1 ? styles.sectionRight : ""}`} className={`${styles.section} ${index % 2 === 1 ? styles.sectionRight : ""}`}
style={{ style={{
backgroundImage: `url(${item.bgImg}), ${FALLBACK_GRADIENT}`, backgroundImage: `url(${item.backgroundImage}), ${FALLBACK_GRADIENT}`,
}} }}
> >
<div <div
@ -68,9 +36,9 @@ export default function About() {
> >
<div className={styles.textBox}> <div className={styles.textBox}>
<h2 className={styles.title}>{item.title}</h2> <h2 className={styles.title}>{item.title}</h2>
<p className={styles.desc}>{item.desc}</p> <p className={styles.desc}>{item.content}</p>
<div className={styles.links}> <div className={styles.links}>
{item.links.map((link, index) => ( {item.links?.map((link) => (
<span key={link.label}> <span key={link.label}>
<Link to={link.to}>{link.label}</Link> <Link to={link.to}>{link.label}</Link>
</span> </span>

View File

@ -1,93 +1,57 @@
import Banner from "@/components/Banner"; import Banner from "@/components/Banner";
import { useState } from "react";
import SwiperCardSection from "@/components/layout/SwiperCardSection"; import SwiperCardSection from "@/components/layout/SwiperCardSection";
import RowAccordion from "@/components/layout/RowAccordion"; import RowAccordion from "@/components/layout/RowAccordion";
import HonorGrids from "@/components/layout/HonorGrids"; import HonorGrids from "@/components/layout/HonorGrids";
import ParagraphSection from "@/components/layout/ParagraphSection"; import ParagraphSection from "@/components/layout/ParagraphSection";
import BottomTabsSection from "@/components/layout/BottomTabsSection"; import BottomTabsSection from "@/components/layout/BottomTabsSection";
import { useStore } from "@/store";
export default function BaseGroup() { export default function BaseGroup() {
const [paragraphSectionData] = useState({ const appConfig = useStore((s) => s.appConfig);
title: "银泰基业集团", const data = appConfig?.business?.baseGroup;
content: "管理有限公司是一家集品质物业服务、资产托管运营、智慧物联管理、科技平台创新运维为一体的专业化物业服务企业,致力于商办类物业运营管理、打造资产全周期生态服务。\n\n 凭借银泰集团多年城市商业地产运营经验不断深化创新,银泰智享积极拓展业务深度与广度,做强基础物业服务,深耕客户卓越服务体验,创造企业多元化价值。核心业务涵盖资产全托管服务、资产顾问服务、资产设施服务、物业品牌合作等,着力实现服务体系化、标准化、精细化、智慧化“四化合一”,打造国内一流的物业管理品牌。",
statsData: [
{ num: "32 个", label: "全国在管项目" },
{ num: "475 万平方", label: "总建筑面积" },
{ num: "3 亿人次", label: "客流每年超" },
{ num: "350 亿元", label: "销售额每年" },
{ num: "5000 +", label: "合作品牌" },
],
})
const swiperCardData = { if (!data) return null;
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 = { const banner = data.banner;
title: "标杆项目", const section1Data = data.section1Data;
items: [ const section2Data = data.section2Data;
{ title: "北京", subtitle: "北京银泰中心", image: "/images/bg-overview.png", links:[ const section3Data = data.section3Data;
{ text: 'in01', path: ''}, const section4Data = data.section4Data;
{ text: '超甲级写字楼', path: ''}, const section5Data = data.section5Data;
{ text: '北京柏悦酒店', path: ''},
{ text: '柏悦府', path: ''}, const swiperCardData = section2Data
{ text: '柏悦居', path: ''}, ? {
] }, title: section2Data.title,
{ title: "四川", subtitle: "成都银泰中心", image: "/images/bg-overview.png" }, cardItems: section2Data.cardItems?.map((c: { title: string; content: string; image: string }) => ({
{ title: "浙江", subtitle: "杭州湖滨银泰in77", image: "/images/bg-overview.png" }, title: c.title,
{ title: "上海", subtitle: "上海中骏广场", image: "/images/bg-overview.png" }, content: c.content,
], image: c.image,
})) ?? [],
} }
const honorsData = { : null;
title: "企业价值",
items: [ const rowAccordionData = section3Data
{ title: "荣誉资质1" }, ? {
{ title: "荣誉资质2" }, title: section3Data.title,
{ title: "荣誉资质3" }, items: section3Data.items ?? [],
{ 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" },
],
} }
: null;
return ( return (
<div> <div>
<Banner <Banner
title="银泰基业集团" title={banner?.title ?? ""}
desc="商业物业资产运营与管理先锋" desc={banner?.content}
titleSize="medium" titleSize={banner?.titleSize as "medium" | "large" | undefined ?? "medium"}
showBreadcrumb={false} showBreadcrumb={banner?.showBreadcrumb ?? false}
backgroundImage={`/images/bg-overview.png`} backgroundImage={banner?.backgroundImage ?? "/images/bg-overview.png"}
/> />
<ParagraphSection data={paragraphSectionData} /> {section1Data && <ParagraphSection data={section1Data} />}
{swiperCardData && <SwiperCardSection data={swiperCardData} />}
<SwiperCardSection data={swiperCardData} /> {rowAccordionData && <RowAccordion data={rowAccordionData} placement="top" />}
{section4Data && <HonorGrids data={section4Data} />}
<RowAccordion data={rowAccordionData} placement="top" /> {section5Data && <BottomTabsSection data={section5Data} />}
<HonorGrids data={honorsData} />
<BottomTabsSection data={bottomTabsData} />
</div> </div>
); );
} }

View File

@ -3,71 +3,52 @@ 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 ParagraphSection from "@/components/layout/ParagraphSection"; import ParagraphSection from "@/components/layout/ParagraphSection";
import { useStore } from "@/store";
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%)";
function PlaceholderImage() { function PlaceholderImage() {
return <div className={styles.placeholder}></div>; return <div className={styles.placeholder}></div>;
} }
export default function BusinessCommercialGroup() { export default function BusinessCommercialGroup() {
const appConfig = useStore((s) => s.appConfig);
const data = appConfig?.business?.commercialGroup;
const [in77ImgError, setIn77ImgError] = useState(false); const [in77ImgError, setIn77ImgError] = 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([
{ label: 'in77', content: 'in77 内容', image: '/images/bg-overview.png', path: '/business/commercial-group/in77' },
{ label: 'inPARK', content: 'inPARK 内容', image: '/images/bg-overview.png', path: '/business/commercial-group/inPARK' },
{ label: '银泰城购物中心', content: '银泰城 内容', image: '/images/bg-overview.png', path: '/business/commercial-group/shopping-center' },
])
const [activeTabIndex, setActiveTabIndex] = useState(0); const [activeTabIndex, setActiveTabIndex] = useState(0);
const [featuresTabItems, setFeaturesTabItems] = useState([
{ label: '深耕运营', content: '全域营销 内容', image: '/images/bg-overview.png',},
{ label: '行业领先', content: '数字化运营 内容', image: '/images/bg-overview.png', },
{ label: '创新变革', content: '全球品牌合作 内容', image: '/images/bg-overview.png', },
{ label: '数字生态', content: '全球品牌合作 内容', image: '/images/bg-overview.png', },
])
const [activeFeaturesTabIndex, setActiveFeaturesTabIndex] = useState(0); const [activeFeaturesTabIndex, setActiveFeaturesTabIndex] = useState(0);
if (!data) return null;
const banner = data.banner;
const section1Data = data.section1Data;
const tabItems = data.section2Data?.tabItems ?? [];
const featuresTabItems = data.section3Data?.tabItems ?? [];
return ( return (
<div> <div>
{/* 1. Hero Banner */}
<Banner <Banner
title="银泰商业集团" title={banner?.title ?? ""}
desc="传统零售业的推动者和典范" desc={banner?.content}
titleSize="medium" titleSize={banner?.titleSize as "medium" | "large" | undefined ?? "medium"}
showBreadcrumb={true} showBreadcrumb={banner?.showBreadcrumb ?? false}
breadcrumbItems={[ backgroundImage={banner?.backgroundImage ?? "/images/bg-commercial-group.png"}
{ label: "首页", to: "/" },
{ label: "集团业务", to: "/business" },
{ label: "银泰商业集团", to: "" },
]}
backgroundImage={`${PUBLIC_URL}/images/bg-commercial-group.png`}
/> />
{/* 2. Overview */} {section1Data && <ParagraphSection data={section1Data} />}
<ParagraphSection data={paragraphSectionData} />
{/* 3. in77 Section - Image Left, Text Right */} <section
<section className={styles.twoColSection} className={styles.twoColSection}
style={{ backgroundImage: 'url(/images/bg-in.png)' }} style={{ backgroundImage: "url(/images/bg-in.png)" }}
> >
<div className={styles.twoColSectionTabs}> <div className={styles.twoColSectionTabs}>
{tabItems.map((item, i) => ( {tabItems.map((item: { label: string }, i: number) => (
<div key={i} className={`${styles.twoColSectionTab} ${activeTabIndex === i ? styles.active : ''}`} onClick={() => setActiveTabIndex(i)}> <div
key={i}
className={`${styles.twoColSectionTab} ${activeTabIndex === i ? styles.active : ""}`}
onClick={() => setActiveTabIndex(i)}
>
<span>{item.label}</span> <span>{item.label}</span>
</div> </div>
))} ))}
@ -78,48 +59,56 @@ export default function BusinessCommercialGroup() {
<PlaceholderImage /> <PlaceholderImage />
) : ( ) : (
<img <img
src={tabItems[activeTabIndex].image} src={tabItems[activeTabIndex]?.image}
alt="in77 杭州湖滨银泰" alt="in77 杭州湖滨银泰"
onError={() => setIn77ImgError(true)} onError={() => setIn77ImgError(true)}
style={{ width: '100%', height: '800px' }} style={{ width: "100%", height: "800px" }}
/> />
)} )}
</div> </div>
<div className={styles.twoColText}> <div className={styles.twoColText}>
<p className={styles.twoColDesc}>{tabItems[activeTabIndex].content}</p> <p className={styles.twoColDesc}>{tabItems[activeTabIndex]?.content}</p>
<a href={tabItems[activeTabIndex].path} className={styles.btnPrimary}> <Link
to={tabItems[activeTabIndex]?.path ?? "#"}
className={styles.btnPrimary}
>
</a> </Link>
</div> </div>
</div> </div>
</section> </section>
{/* 4. Features Section - Hero + 3 Blocks */} <section
<section className={styles.featuresHero} style={{ backgroundImage: `url(/images/bg-overview.png), ${FALLBACK_GRADIENT}` }}> className={styles.featuresHero}
style={{
backgroundImage: `url(/images/bg-overview.png), ${FALLBACK_GRADIENT}`,
}}
>
<div className={styles.featuresHeroContent}> <div className={styles.featuresHeroContent}>
<div>{featuresTabItems[activeFeaturesTabIndex].content}</div> <div>{featuresTabItems[activeFeaturesTabIndex]?.content}</div>
</div> </div>
<div className={styles.featuresHeroTabs}> <div className={styles.featuresHeroTabs}>
{featuresTabItems.map((item, i) => ( {featuresTabItems.map((item: { label: string }, i: number) => (
<div key={i} className={`${styles.featuresHeroTab} ${activeFeaturesTabIndex === i ? styles.active : ''}`} onClick={() => setActiveFeaturesTabIndex(i)}> <div
key={i}
className={`${styles.featuresHeroTab} ${activeFeaturesTabIndex === i ? styles.active : ""}`}
onClick={() => setActiveFeaturesTabIndex(i)}
>
<span>{item.label}</span> <span>{item.label}</span>
</div> </div>
))} ))}
</div> </div>
</section> </section>
<section
{/* 5. Property Services - Text Left, Image Right */} className={`${styles.twoColSection} ${styles.propertyServices}`}
<section className={`${styles.twoColSection} ${styles.propertyServices}`} style={{
style={{ backgroundImage: `url(/images/bg-overview.png), ${FALLBACK_GRADIENT}` }} backgroundImage: `url(/images/bg-overview.png), ${FALLBACK_GRADIENT}`,
}}
> >
<div className={styles.propertyServicesContent}> <div className={styles.propertyServicesContent}>
<div className={styles.propertyServicesTitle}> <div className={styles.propertyServicesTitle}></div>
<p className={styles.propertyServicesSubtitle}></p>
</div>
<p className={styles.propertyServicesSubtitle}>
</p>
<Link to="/property-service" className={styles.propertyServicesBtn}> <Link to="/property-service" className={styles.propertyServicesBtn}>
</Link> </Link>

View File

@ -1,62 +1,28 @@
import Banner from "@/components/Banner"; import Banner, { type BannerConfig } from "@/components/Banner";
import { useStore } from "@/store";
import styles from "./CommercialGroupDetail.module.css"; import styles from "./CommercialGroupDetail.module.css";
import { useState } from "react";
export default function BusinessCommercialGroupDetail() { export default function BusinessCommercialGroupDetail() {
const [tabItems, setTabItems] = useState([ const appConfig = useStore((s) => s.appConfig);
{ label: "北京银泰中心in01", icon: "", title: '北京银泰中心', subtitle: '精致优雅的典范', sideImg: '/images/bg-overview.png' }, const data = appConfig?.business?.commercialGroupDetail;
{ label: "杭州湖滨银泰in77", icon: "", title: '杭州湖滨银泰', subtitle: '潮流时尚的聚集地', sideImg: '/images/bg-overview.png' }, const banner = data?.banner;
{ label: "北京王府井银泰in88", icon: "", title: '北京王府井银泰', subtitle: '时尚购物的理想选择', sideImg: '/images/bg-overview.png' },
{ label: "成都银泰中心in99", icon: "", title: '成都银泰中心', subtitle: '现代都市的活力中心', sideImg: '/images/bg-overview.png' }, if (!data) return null;
{ label: "合肥银泰中心in77", icon: "", title: '合肥银泰中心', subtitle: '城市商业的璀璨明珠', sideImg: '/images/bg-overview.png' },
]);
const [activeTab, setActiveTab] = useState(0);
return ( return (
<div> <div>
<Banner <Banner
title="in77" title={banner?.title ?? ""}
largedesc="地标型高端商业综合体" largedesc={(banner as BannerConfig)?.largeContent}
titleSize="large" titleSize={(banner as BannerConfig)?.titleSize ?? "large"}
showBreadcrumb={true} showBreadcrumb={banner?.showBreadcrumb ?? false}
breadcrumbItems={[ backgroundImage={banner?.backgroundImage ?? "/images/bg-commercial-group.png"}
{ label: "首页", to: "/" },
{ label: "集团业务", to: "/business" },
{ label: "银泰商业集团", to: "/business/commercial-group" },
{ label: "in77", to: "" },
]}
backgroundImage={`/images/bg-commercial-group.png`}
/> />
<section className={styles.twoColSection}> <section className={styles.twoColSection}>
<p>in77 in01in77in88in77及成都银泰中心in99等项目</p> <p>
<p>2024in77线 </p> in77
</section>
<section className={styles.threeColSection}>
<div className={styles.threeColTabs}>
{tabItems.map((item, index) => (
<div key={index} className={`${styles.threeColTabItem} ${activeTab === index ? styles.active : ''}`} onClick={() => setActiveTab(index)}>
<span>{item.label}</span>
</div>
))}
</div>
<div className={styles.threeColContent}>
<div className={styles.threeColContentLeft}>
<div className={styles.threeColContentLeftHead}>
<img src="" alt="" style={{width: '100px', height: '100px'}} />
<div className={styles.threeColContentLeftTitle}>
<div className={styles.threeColContentLeftTitleMain}>{tabItems[activeTab].title}</div>
<div className={styles.threeColContentLeftTitleSub}>{tabItems[activeTab].subtitle}</div>
</div>
</div>
<p className={styles.threeColContentLeftDesc}>
CBD核心的北京银泰中心in01in01倡导美Chrome HearsalexanderwangRICHARD MILLE Burtonin式服务概念
</p> </p>
</div>
<div className={styles.threeColContentRight}>
<img src={tabItems[activeTab].sideImg} alt=""/>
</div>
</div>
</section> </section>
</div> </div>
); );

View File

@ -1,86 +1,40 @@
import { useState } from "react";
import Banner from "@/components/Banner"; import Banner from "@/components/Banner";
import ParagraphSection from "@/components/layout/ParagraphSection"; import ParagraphSection from "@/components/layout/ParagraphSection";
import styles from "./InvestGroup.module.css";
import SectionTitle from "@/components/layout/SectionTitle"; import SectionTitle from "@/components/layout/SectionTitle";
import Section from "@/components/layout/Section"; import Section from "@/components/layout/Section";
import { useStore } from "@/store";
import styles from "./InvestGroup.module.css";
export default function InvestGroup() { export default function InvestGroup() {
const [paragraphSectionData] = useState({ const appConfig = useStore((s) => s.appConfig);
title: "银泰投资集团", const data = appConfig?.business?.investGroup;
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 = { if (!data) return null;
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",
}
const banner = data.banner;
const section1Data = data.section1Data;
const section2Data = data.section2Data;
const section3Data = data.section3Data;
const section4Data = data.section4Data;
return ( return (
<div> <div>
<Banner <Banner
title="银泰投资集团" title={banner?.title ?? ""}
desc="探索价值投资,协同产业发展" desc={banner?.content}
titleSize="medium" titleSize={banner?.titleSize as "medium" | "large" | undefined ?? "medium"}
showBreadcrumb={false} showBreadcrumb={banner?.showBreadcrumb ?? false}
backgroundImage={`/images/bg-overview.png`} backgroundImage={banner?.backgroundImage ?? "/images/bg-overview.png"}
/> />
<ParagraphSection data={paragraphSectionData} /> {section1Data && <ParagraphSection data={section1Data} />}
{/* 发起成立 */} {section2Data && (
<section className={styles.investGroup}> <section className={styles.investGroup}>
<SectionTitle title={investGroupContentData.title} color="#fff" /> <SectionTitle title={section2Data.title} color="#fff" />
<div className={styles.investGroupContent}> <div className={styles.investGroupContent}>
<div className={styles.investGroupContentItems}> <div className={styles.investGroupContentItems}>
{investGroupContentData.items.map((item, index) => ( {section2Data.items?.map((item: { title: string; content: string }, index: number) => (
<div className={styles.investGroupContentItem} key={index}> <div className={styles.investGroupContentItem} key={index}>
<div className={styles.investGroupContentItemTitle}>{item.title}</div> <div className={styles.investGroupContentItemTitle}>{item.title}</div>
<div className={styles.investGroupContentItemContent}>{item.content}</div> <div className={styles.investGroupContentItemContent}>{item.content}</div>
@ -89,31 +43,38 @@ export default function InvestGroup() {
</div> </div>
</div> </div>
</section> </section>
)}
{/* 股权投资 */} {section3Data && (
<section className={styles.equityInvestment}> <section className={styles.equityInvestment}>
<SectionTitle title={equityInvestmentData.title} /> <SectionTitle title={section3Data.title} />
<div className={styles.equityInvestmentItems}> <div className={styles.equityInvestmentItems}>
{equityInvestmentData.items.map((item, index) => ( {section3Data.items?.map((item: { logo: string; title: string }, index: number) => (
<div className={styles.equityInvestmentItem} key={index}> <div className={styles.equityInvestmentItem} key={index}>
<img src={item.logo} alt={item.title} className={styles.equityInvestmentItemLogo} /> <img
src={item.logo}
alt={item.title}
className={styles.equityInvestmentItemLogo}
/>
<div className={styles.equityInvestmentItemTitle}>{item.title}</div> <div className={styles.equityInvestmentItemTitle}>{item.title}</div>
</div> </div>
))} ))}
</div> </div>
</section> </section>
)}
{/* 产业孵化 */} {section4Data && (
<Section background={industryFosterData.backgroundImage} maskBackground="rgba(20,53,92,0.1)" <Section
background={section4Data.backgroundImage}
maskBackground="rgba(20,53,92,0.1)"
className={styles.industryFoster} className={styles.industryFoster}
> >
<div className={styles.industryFosterMask}> <div className={styles.industryFosterMask}>
<div className={styles.industryFosterMaskTitle}>{industryFosterData.title}</div> <div className={styles.industryFosterMaskTitle}>{section4Data.title}</div>
<div className={styles.industryFosterMaskContent}>{industryFosterData.content}</div> <div className={styles.industryFosterMaskContent}>{section4Data.content}</div>
</div> </div>
</Section> </Section>
)}
</div> </div>
); );
} }

View File

@ -1,87 +1,53 @@
import Banner from "@/components/Banner"; import Banner from "@/components/Banner";
import { useState } from "react";
import SwiperCardSection from "@/components/layout/SwiperCardSection"; import SwiperCardSection from "@/components/layout/SwiperCardSection";
import RowAccordion from "@/components/layout/RowAccordion"; import RowAccordion from "@/components/layout/RowAccordion";
import HonorGrids from "@/components/layout/HonorGrids"; import HonorGrids from "@/components/layout/HonorGrids";
import ParagraphSection from "@/components/layout/ParagraphSection"; import ParagraphSection from "@/components/layout/ParagraphSection";
import BottomTabsSection from "@/components/layout/BottomTabsSection"; import BottomTabsSection from "@/components/layout/BottomTabsSection";
import TopTabsSection from "@/components/layout/TopTabsSection"; import TopTabsSection from "@/components/layout/TopTabsSection";
import { useStore } from "@/store";
export default function RealtyGroup() { export default function RealtyGroup() {
const [paragraphSectionData] = useState({ const appConfig = useStore((s) => s.appConfig);
title: "银泰置地集团", const data = appConfig?.business?.realtyGroup;
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" },
],
}
if (!data) return null;
const rowAccordionData = { const banner = data.banner;
title: "标杆项目", const section1Data = data.section1Data;
items: [ const section2Data = data.section2Data;
{ title: "杭州银泰中心", content: "位于杭州未来科技城地块与余杭区政府合作开发建设规划投资数十亿元建设总建筑面积约60万方的高端TOD城市综合体推动区域向“国际化消费中心”转型打造百亿级商圈。", image: "/images/bg-overview.png"}, const section3Data = data.section3Data;
{ title: "丽水银泰城", content: "位于杭州未来科技城地块与余杭区政府合作开发建设规划投资数十亿元建设总建筑面积约60万方的高端TOD城市综合体推动区域向“国际化消费中心”转型打造百亿级商圈。", image: "/images/bg-overview.png"}, const section4Data = data.section4Data;
{ title: "杭州银泰喜来登大酒店", content: "位于杭州未来科技城地块与余杭区政府合作开发建设规划投资数十亿元建设总建筑面积约60万方的高端TOD城市综合体推动区域向“国际化消费中心”转型打造百亿级商圈。", image: "/images/bg-overview.png"}, const section5Data = data.section5Data;
{ title: "杭州银泰仙女湖小镇", content: "位于杭州未来科技城地块与余杭区政府合作开发建设规划投资数十亿元建设总建筑面积约60万方的高端TOD城市综合体推动区域向“国际化消费中心”转型打造百亿级商圈。", image: "/images/bg-overview.png"},
], const topTabsData = section2Data ? { tabItems: section2Data.tabItems ?? [] } : null;
}
const honorsData = { const rowAccordionData = section3Data
title: "荣誉奖项", ? {
items: [ title: section3Data.title,
{ title: "荣誉资质1" }, items: section3Data.items?.map((i: { title: string; content?: string; image: string }) => ({
{ title: "荣誉资质2" }, title: i.title,
{ title: "荣誉资质3" }, content: i.content,
{ title: "荣誉资质4" }, image: i.image,
{ 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" },
],
} }
: null;
return ( return (
<div> <div>
<Banner <Banner
title="银泰置地集团" title={banner?.title ?? ""}
desc="商业地产的高品质代表" desc={banner?.content}
titleSize="medium" titleSize={banner?.titleSize as "medium" | "large" | undefined ?? "medium"}
showBreadcrumb={true} showBreadcrumb={banner?.showBreadcrumb ?? false}
breadcrumbItems={[{ label: '集团业务', to: '/business' }, { label: '银泰置地集团', to: '/business/realty-group' }]} backgroundImage={banner?.backgroundImage ?? "/images/bg-overview.png"}
backgroundImage={`/images/bg-overview.png`}
/> />
<ParagraphSection data={paragraphSectionData} /> {section1Data && <ParagraphSection data={section1Data} />}
{topTabsData && <TopTabsSection data={topTabsData} />}
<TopTabsSection data={topTabsData} /> {rowAccordionData && <RowAccordion data={rowAccordionData} />}
{section4Data && <HonorGrids data={section4Data} />}
<RowAccordion data={rowAccordionData} /> {section5Data && <BottomTabsSection data={section5Data} />}
<HonorGrids data={honorsData} />
<BottomTabsSection data={bottomTabsData} />
</div> </div>
); );
} }

View File

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

View File

@ -1,100 +1,39 @@
import { useState } from "react"; import { useStore } from "@/store";
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 Section from "@/components/layout/Section";
import RowAccordion from "@/components/layout/RowAccordion"; import RowAccordion from "@/components/layout/RowAccordion";
import { Link } from "react-router-dom";
export default function Home() { export default function Home() {
const [bannerData] = useState({ const appConfig = useStore((s) => s.appConfig);
title: "银泰集团", const home = appConfig?.home;
desc: "中国现代新商业典范",
backgroundImage: ['/images/bg-overview.png', '/images/bg-base-group.png'],
})
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 banner = home?.banner;
const [cardsData] = useState([ const section1Data = home?.section1Data;
{ const section2Data = home?.section2Data ?? [];
title: "可持续发展", const newsData = home?.newsData ?? [];
content: "银泰集团积极践行绿色发展理念,将可持续发展融入企业战略与日常运营,致力于构建人与自然和谐共生的美好未来。",
backgroundImage: '/images/sustainable-cranes.png', if (!home) return null;
},
{
title: "银泰公益基金会",
content: "银泰集团积极践行绿色发展理念,将可持续发展融入企业战略与日常运营,致力于构建人与自然和谐共生的美好未来。",
backgroundImage: '/images/welfare-check.png',
},
])
const [newsData] = useState([
{
title: "银泰百货×敦煌研究院联名新品限量首发",
snippet: "10月28日在杭州余杭区委城市工作会议暨城市新中心中轴线创新发展大会上银泰集团正式宣布银泰杭州新中心项目定名为“杭州银泰中银泰集团正式宣布银泰杭州新中心项目定名为“杭州银泰中银泰集团正式宣布银泰杭州新中心项目定名为“杭州银泰中",
date: "2024-01-15",
path: "/news/1",
},
{
title: "银泰中国区总裁陈晓:我们是长期主义者",
snippet: "10月28日在杭州余杭区委城市工作会议暨城市新中心中轴线创新发展大会上银泰集团正式宣布银泰杭州新中心项目定名为“杭州银泰中银泰集团正式宣布银泰杭州新中心项目定名为“杭州银泰中银泰集团正式宣布银泰杭州新中心项目定名为“杭州银泰中",
date: "2024-01-10",
path: "/news/2",
},
{
title: "中国青年发展基金会 | 银泰公益基金会合作签约",
snippet: "10月28日在杭州余杭区委城市工作会议暨城市新中心中轴线创新发展大会上银泰集团正式宣布银泰杭州新中心项目定名为“杭州银泰中银泰集团正式宣布银泰杭州新中心项目定名为“杭州银泰中银泰集团正式宣布银泰杭州新中心项目定名为“杭州银泰中",
date: "2023-11-20",
path: "/news/3",
},
]);
return ( return (
<div> <div>
{/* Hero */} {/* Hero */}
<Banner title={bannerData.title} desc={bannerData.desc} showBreadcrumb={false} <Banner
backgroundImage={bannerData.backgroundImage}></Banner> title={banner?.title ?? ""}
desc={banner?.content}
showBreadcrumb={banner?.showBreadcrumb ?? false}
backgroundImage={banner?.backgroundImage ?? "/images/bg-overview.png"}
/>
{/* Commercial */} {/* Commercial */}
<RowAccordion data={commercialData} /> {section1Data && <RowAccordion data={section1Data} />}
{/* 首页名片 */} {/* 首页名片 */}
<Section background="/images/bg-mask-card.png"> <Section background="/images/bg-mask-card.png">
<div className={styles.cardsInner}> <div className={styles.cardsInner}>
{ {section2Data.map((item, i) => (
cardsData.map((item) => ( <div key={i} className={`${styles.card} ${styles.cardSustainable}`}>
<div className={`${styles.card} ${styles.cardSustainable}`}>
<div <div
className={styles.cardBg} className={styles.cardBg}
style={{ style={{
@ -104,13 +43,10 @@ export default function Home() {
<div className={styles.cardOverlay} /> <div className={styles.cardOverlay} />
<div className={styles.cardContent}> <div className={styles.cardContent}>
<h3 className={styles.cardTitle}>{item.title}</h3> <h3 className={styles.cardTitle}>{item.title}</h3>
<p className={styles.cardDesc}> <p className={styles.cardDesc}>{item.content}</p>
{item.content}
</p>
</div> </div>
</div> </div>
)) ))}
}
</div> </div>
</Section> </Section>
@ -120,7 +56,7 @@ export default function Home() {
<div className={styles.newsFeatured}> <div className={styles.newsFeatured}>
<div className={styles.newsFeaturedImgWrap}> <div className={styles.newsFeaturedImgWrap}>
<img <img
src={`/images/bg-overview.png`} src="/images/bg-overview.png"
alt="新闻配图" alt="新闻配图"
className={styles.newsFeaturedImg} className={styles.newsFeaturedImg}
onError={(e) => { onError={(e) => {
@ -136,7 +72,7 @@ export default function Home() {
{newsData.map((item) => ( {newsData.map((item) => (
<article key={item.path} className={styles.newsItem}> <article key={item.path} className={styles.newsItem}>
<h3 className={styles.newsItemTitle}> <h3 className={styles.newsItemTitle}>
<a href={item.path}>{item.title}</a> <Link to={item.path}>{item.title}</Link>
</h3> </h3>
<p className={styles.newsItemSnippet}>{item.snippet}</p> <p className={styles.newsItemSnippet}>{item.snippet}</p>
<span className={styles.newsItemDate}>{item.date}</span> <span className={styles.newsItemDate}>{item.date}</span>

View File

@ -1,7 +1,8 @@
import { useCallback, useEffect, useState } from "react"; import { useCallback, useEffect, useState } from "react";
import styles from "./Campus.module.css"; import styles from "./Campus.module.css";
import Banner from "@/components/Banner"; import Banner, { type BannerConfig } from "@/components/Banner";
import Section from "@/components/layout/Section"; import Section from "@/components/layout/Section";
import { useStore } from "@/store";
import { SearchOutlined, FilterOutlined, DownOutlined, RightOutlined } from "@ant-design/icons"; import { SearchOutlined, FilterOutlined, DownOutlined, RightOutlined } from "@ant-design/icons";
import { Empty, Select } from "antd"; import { Empty, Select } from "antd";
import Pagination from "@/components/Pagination"; import Pagination from "@/components/Pagination";
@ -16,6 +17,10 @@ type JobItem = {
} }
export default function JoinCampus() { export default function JoinCampus() {
const appConfig = useStore((s) => s.appConfig);
const data = appConfig?.join?.campus;
const banner = data?.banner;
const [searchValue, setSearchValue] = useState(''); const [searchValue, setSearchValue] = useState('');
// 职业类别 业务领域 所属板块 // 职业类别 业务领域 所属板块
@ -62,11 +67,11 @@ export default function JoinCampus() {
return ( return (
<div> <div>
<Banner <Banner
title="招贤纳士" title={banner?.title ?? "招贤纳士"}
titleSize="large" content={(banner as BannerConfig)?.content}
showBreadcrumb={true} titleSize={(banner as BannerConfig)?.titleSize ?? "large"}
breadcrumbItems={[{ label: '加入银泰', to: '/business' }, { label: '招贤纳士', to: '' }]} showBreadcrumb={banner?.showBreadcrumb ?? false}
backgroundImage={`/images/bg-overview.png`} backgroundImage={banner?.backgroundImage ?? "/images/bg-overview.png"}
/> />
<Section maskBackground="#FFFFFF"> <Section maskBackground="#FFFFFF">

View File

@ -1,43 +1,42 @@
import styles from "./Culture.module.css"; import styles from "./Culture.module.css";
import Banner from "@/components/Banner"; import Banner, { type BannerConfig } from "@/components/Banner";
import Section from "@/components/layout/Section"; import Section from "@/components/layout/Section";
import { useStore } from "@/store";
export default function Culture() { export default function Culture() {
const appConfig = useStore((s) => s.appConfig);
const data = appConfig?.join?.culture;
const cultureItems = { if (!data) return null;
title: '企业文化',
items: [
{ title: '使命', content: '做新商业典范,律正合作共享', backgroundImage: '/images/bg-overview.png' },
{ title: '愿景', content: '成为世界级商业地产集团', backgroundImage: '/images/bg-overview.png' },
{ title: '核心价值观', content: '诚信、合作、创新、共赢', backgroundImage: '/images/bg-overview.png' },
]
}
// 价值观 const banner = data.banner;
const valuesItems = { const section1Data = data.section1Data;
title: '价值观', const section2Data = data.section2Data;
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>
<Banner <Banner
title="企业文化" title={banner?.title ?? ""}
titleSize="large" content={(banner as BannerConfig)?.content}
showBreadcrumb={true} titleSize={(banner as BannerConfig)?.titleSize ?? "large"}
breadcrumbItems={[{ label: '加入银泰', to: '/business' }, { label: '企业文化', to: '' }]} showBreadcrumb={banner?.showBreadcrumb ?? false}
backgroundImage={`/images/bg-overview.png`} backgroundImage={banner?.backgroundImage ?? "/images/bg-overview.png"}
/> />
<Section title={cultureItems.title} background="/images/bg-overview.png" maskBackground="#D8D8D8"> {section1Data && (
<Section
title={section1Data.title}
background="/images/bg-overview.png"
maskBackground="#D8D8D8"
>
<div className={styles.cultureItems}> <div className={styles.cultureItems}>
{cultureItems.items.map((item, index) => ( {section1Data.items?.map((item, index) => (
<div key={index} className={styles.cultureItem} style={{ backgroundImage: `url(${item.backgroundImage})` }}> <div
<div className={styles.cultureItemMaks}></div> key={index}
className={styles.cultureItem}
style={{ backgroundImage: `url(${item.backgroundImage})` }}
>
<div className={styles.cultureItemMaks} />
<div className={styles.cultureItemInner}> <div className={styles.cultureItemInner}>
<div className={styles.cultureItemTitle}>{item.title}</div> <div className={styles.cultureItemTitle}>{item.title}</div>
<div className={styles.cultureItemContent}>{item.content}</div> <div className={styles.cultureItemContent}>{item.content}</div>
@ -46,20 +45,28 @@ export default function Culture() {
))} ))}
</div> </div>
</Section> </Section>
)}
<Section title={valuesItems.title} background="" maskBackground="rgba(216,216,216,0.6)"> {section2Data && (
<Section
title={section2Data.title}
background=""
maskBackground="rgba(216,216,216,0.6)"
>
<div className={styles.valuesItems}> <div className={styles.valuesItems}>
{valuesItems.items.map((item, index) => ( {section2Data.items?.map((item, index) => (
<div key={index} className={styles.valuesItem}> <div key={index} className={styles.valuesItem}>
<div className={styles.valuesItemIcon} style={{ backgroundImage: `url(${item.icon})` }}></div> <div
className={styles.valuesItemIcon}
style={{ backgroundImage: `url(${item.icon})` }}
/>
<div className={styles.valuesItemTitle}>{item.title}</div> <div className={styles.valuesItemTitle}>{item.title}</div>
<div className={styles.valuesItemContent}>{item.content}</div> <div className={styles.valuesItemContent}>{item.content}</div>
</div> </div>
))} ))}
</div> </div>
</Section> </Section>
)}
</div> </div>
); );
} }

View File

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

View File

@ -1,28 +1,31 @@
import styles from "./Media.module.css"; import styles from "./Media.module.css";
import Banner from "@/components/Banner"; import Banner, { type BannerConfig } from "@/components/Banner";
import Section from "@/components/layout/Section"; import Section from "@/components/layout/Section";
import { useStore } from "@/store";
export default function NewsPublic() { export default function Media() {
const appConfig = useStore((s) => s.appConfig);
const data = appConfig?.news?.media;
if (!data) return null;
const banner = data.banner;
const section1Data = data.section1Data;
const items = section1Data?.items ?? [];
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>
<Banner <Banner
title="媒体垂询" title={banner?.title ?? ""}
titleSize="large" content={(banner as BannerConfig)?.content}
showBreadcrumb={true} titleSize={(banner as BannerConfig)?.titleSize ?? "large"}
breadcrumbItems={[{ label: '新闻中心', to: '/business' }, { label: '媒体垂询', to: '' }]} showBreadcrumb={banner?.showBreadcrumb ?? false}
backgroundImage={`/images/bg-overview.png`} backgroundImage={banner?.backgroundImage ?? "/images/bg-overview.png"}
/> />
<Section background="/images/bg-overview.png" maskBackground="rgba(1,11,72,0.8)"> <Section background="/images/bg-overview.png" maskBackground="rgba(1,11,72,0.8)">
<div className={styles.mediaItems}> <div className={styles.mediaItems}>
{data.items.map((item, index) => ( {items.map((item, index) => (
<div key={index} className={styles.mediaItem}> <div key={index} className={styles.mediaItem}>
<div className={styles.mediaItemTitle}>{item.title}</div> <div className={styles.mediaItemTitle}>{item.title}</div>
<div className={styles.mediaItemContent}>{item.content}</div> <div className={styles.mediaItemContent}>{item.content}</div>
@ -33,5 +36,3 @@ export default function NewsPublic() {
</div> </div>
); );
} }

View File

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

View File

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

View File

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

View File

@ -1,91 +1,108 @@
import Banner from "@/components/Banner"; import Banner, { type BannerConfig } from "@/components/Banner";
import Section from "@/components/layout/Section"; import Section from "@/components/layout/Section";
import styles from "./Search.module.css"; import styles from "./Search.module.css";
import { useCallback, useState } from "react"; import { useCallback, useState } from "react";
import { dateFormat } from "@/utils"; import { dateFormat } from "@/utils";
import { useStore } from "@/store";
type SearchData = { type SearchData = {
id: number; id: number;
title: string; title: string;
content: string; content: string;
createTime: string; createTime: string;
} };
export default function Search() { export default function Search() {
const appConfig = useStore((s) => s.appConfig);
const data = appConfig?.others?.search;
const banner = data?.banner;
const [searched, setSearched] = useState(false); const [searched, setSearched] = useState(false);
const [searchKeyword, setSearchKeyword] = useState(''); const [searchKeyword, setSearchKeyword] = useState("");
const [total, setTotal] = useState(0); const [total, setTotal] = useState(0);
const [searchData, setSearchData] = useState<SearchData[]>([]); const [searchData, setSearchData] = useState<SearchData[]>([]);
const handleSearch = useCallback(() => { const handleSearch = useCallback(() => {
setSearched(true); setSearched(true);
setSearchData([ setSearchData([
{ {
id: 1, id: 1,
title: '中共中央举行新闻发布会解读党的十九届五中全会精神_党建动态', title: "中共中央举行新闻发布会解读党的十九届五中全会精神_党建动态",
content: '中国共产党第十九届中央委员会第五次全体会议于2020年10月26日至29日在北京举行。全会审议通过了《中共中央关于制定国民经济和社会发展第十四个五年规划和二三五年远景目标的建议》。', content:
createTime: '2025-11-25' "中国共产党第十九届中央委员会第五次全体会议于2020年10月26日至29日在北京举行。全会审议通过了《中共中央关于制定国民经济和社会发展第十四个五年规划和二三五年远景目标的建议》。",
createTime: "2025-11-25",
}, },
{ {
id: 2, id: 2,
title: '中共中央举行新闻发布会解读党的十九届五中全会精神_党建动态', title: "中共中央举行新闻发布会解读党的十九届五中全会精神_党建动态",
content: '中国共产党第十九届中央委员会第五次全体会议于2020年10月26日至29日在北京举行。全会审议通过了《中共中央关于制定国民经济和社会发展第十四个五年规划和二三五年远景目标的建议》。', content:
createTime: '2025-11-25' "中国共产党第十九届中央委员会第五次全体会议于2020年10月26日至29日在北京举行。全会审议通过了《中共中央关于制定国民经济和社会发展第十四个五年规划和二三五年远景目标的建议》。",
createTime: "2025-11-25",
}, },
]) ]);
}, [searchKeyword]); }, [searchKeyword]);
return ( return (
<div> <div>
<Banner <Banner
title="搜索结果" title={banner?.title ?? "搜索结果"}
titleSize="large" content={(banner as BannerConfig)?.content}
showBreadcrumb={true} titleSize={(banner as BannerConfig)?.titleSize ?? "large"}
breadcrumbItems={[{ label: '搜索结果', to: '' }]} showBreadcrumb={banner?.showBreadcrumb ?? false}
backgroundImage={`/images/search-banner.png`} backgroundImage={banner?.backgroundImage ?? "/images/search-banner.png"}
/> />
<section className={styles.searchRow}> <section className={styles.searchRow}>
<div className={styles.searchRowInner}> <div className={styles.searchRowInner}>
<span className={styles.searchRowTitle}></span> <span className={styles.searchRowTitle}></span>
<div className={styles.searchInputWrapper}> <div className={styles.searchInputWrapper}>
<input type="text" placeholder="请输入" className={styles.searchInput} <input
type="text"
placeholder="请输入"
className={styles.searchInput}
value={searchKeyword} value={searchKeyword}
onChange={(e) => setSearchKeyword(e.target.value)} onChange={(e) => setSearchKeyword(e.target.value)}
onKeyDown={(e) => { onKeyDown={(e) => {
if (e.key === 'Enter') { if (e.key === "Enter") handleSearch();
handleSearch();
}
}} }}
/> />
{ {searched && (
searched && ( <div className={styles.searchKeyword}>
<div className={styles.searchKeyword}>
<span className={styles.searchKeywordKeyword}>{searchKeyword}&nbsp;</span> <span className={styles.searchKeywordKeyword}>
{searchKeyword}&nbsp;
</span>
<span>{total}</span> <span>{total}</span>
</div> </div>
) )}
}
</div> </div>
<button type="button" className={styles.searchBtn} onClick={handleSearch}></button> <button
type="button"
className={styles.searchBtn}
onClick={handleSearch}
>
</button>
</div> </div>
</section> </section>
<Section background="" maskBackground="#fff"> <Section background="" maskBackground="#fff">
<div className={styles.searchItemList}> <div className={styles.searchItemList}>
{ {searchData.map((item) => (
searchData.map((item => ( <div key={item.id} className={styles.searchItem}>
<div className={styles.searchItem}>
<div className={styles.searchItemTitleRow}> <div className={styles.searchItemTitleRow}>
<span className={styles.searchItemTitle}>{item.title}</span> <span className={styles.searchItemTitle}>{item.title}</span>
<span className={styles.searchItemCreateTime}>{dateFormat(item.createTime, 'yyyy年MM月dd日')}</span> <span className={styles.searchItemCreateTime}>
{dateFormat(item.createTime, "yyyy年MM月dd日")}
</span>
</div> </div>
<div className={styles.searchItemContent}>{item.content}</div> <div className={styles.searchItemContent}>{item.content}</div>
</div> </div>
))) ))}
}
</div> </div>
</Section> </Section>
</div> </div>
); );
} }

View File

@ -1,129 +1,69 @@
import Banner from "@/components/Banner"; import Banner, { type BannerConfig } from "@/components/Banner";
import Section from "@/components/layout/Section"; import Section from "@/components/layout/Section";
import styles from "./SiteMap.module.css"; import styles from "./SiteMap.module.css";
import { Link } from "react-router-dom"; import { Link } from "react-router-dom";
import { useStore } from "@/store";
export default function SiteMap() { export default function SiteMap() {
const data = { const appConfig = useStore((s) => s.appConfig);
title: '网站地图', const data = appConfig?.others?.siteMap;
// 菜单
items: [ if (!data) return null;
{
label: "关于银泰", const banner = data.banner;
path: "/about", const section1Data = data.section1Data;
children: [ const items = section1Data?.items ?? [];
{ path: "/about", label: "集团概览" }, const title = section1Data?.title ?? "网站地图";
{ 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 ( return (
<div> <div>
<Banner <Banner
title="网站地图" title={banner?.title ?? ""}
titleSize="large" content={(banner as BannerConfig)?.content}
showBreadcrumb={true} titleSize={(banner as BannerConfig)?.titleSize ?? "large"}
breadcrumbItems={[{ label: '网站地图', to: '' }]} showBreadcrumb={banner?.showBreadcrumb ?? false}
backgroundImage={`/images/bg-overview.png`} backgroundImage={banner?.backgroundImage ?? "/images/bg-overview.png"}
/> />
<Section background="" maskBackground="#fff"> <Section background="" maskBackground="#fff">
<div className={styles.siteMap}> <div className={styles.siteMap}>
<div className={styles.siteMapTitle}></div> <div className={styles.siteMapTitle}>{title}</div>
<div className={styles.siteMapItems}> <div className={styles.siteMapItems}>
{ {items.map((item) => (
data.items.map((item) => (
<div className={styles.siteMapItem} key={item.label}> <div className={styles.siteMapItem} key={item.label}>
<div className={styles.siteMapItemLabel}>{item.label}</div> <div className={styles.siteMapItemLabel}>{item.label}</div>
<div className={styles.siteMapItemChildren}> <div className={styles.siteMapItemChildren}>
{ {item.children?.map((child: { path: string; label: string; children?: { path: string; label: string }[] }) => (
item.children.map((child) => ( <div
<div className={styles.siteMapItemChild} key={child.label}> className={styles.siteMapItemChild}
<Link to={child.path} className={styles.siteMapItemChildLabel}>{child.label}</Link> key={child.label}
>
<Link
to={child.path}
className={styles.siteMapItemChildLabel}
>
{child.label}
</Link>
<div className={styles.siteMapItemChildChildren}> <div className={styles.siteMapItemChildChildren}>
{ {child.children?.map((childChild) => (
child?.children && child?.children.map((childChild) => ( <Link
<Link to={childChild.path} className={styles.siteMapItemChildChild} key={childChild.label}>{childChild.label}</Link> to={childChild.path}
)) className={styles.siteMapItemChildChild}
} key={childChild.label}
>
{childChild.label}
</Link>
))}
</div> </div>
</div> </div>
)) ))}
}
</div> </div>
</div> </div>
)) ))}
}
</div> </div>
</div> </div>
</Section> </Section>
</div> </div>
); );
} }

View File

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

View File

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

View File

@ -1,170 +1,105 @@
import Banner from "@/components/Banner"; import Banner, { type BannerConfig } from "@/components/Banner";
import { useState } from "react"; import { useState } from "react";
import ParagraphSection from "@/components/layout/ParagraphSection"; import ParagraphSection from "@/components/layout/ParagraphSection";
import TopTabs from "@/components/layout/TopTabsSection/TopTabs"; import TopTabs from "@/components/layout/TopTabsSection/TopTabs";
import Section from "@/components/layout/Section"; import Section from "@/components/layout/Section";
import styles from "./Foundation.module.css";
import AnimateTopCard from "@/components/layout/AnimateTopCard"; import AnimateTopCard from "@/components/layout/AnimateTopCard";
import BottomTabs from "@/components/layout/BottomTabsSection/BottomTabs"; import BottomTabs from "@/components/layout/BottomTabsSection/BottomTabs";
import { useStore } from "@/store";
import styles from "./Foundation.module.css";
export default function Foundation() { export default function Foundation() {
const [paragraphSectionData] = useState({ const appConfig = useStore((s) => s.appConfig);
title: "银泰公益基金会", const data = appConfig?.social?.foundation;
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 [activeIndex, setActiveIndex] = useState(0);
const partnerData = { if (!data) return null;
title: "公益伙伴",
items: [ const banner = data.banner;
{ logo: "/images/bg-overview.png" }, const section1Data = data.section1Data;
{ logo: "/images/bg-overview.png" }, const section2Data = data.section2Data;
{ logo: "/images/bg-overview.png" }, const section3Data = data.section3Data;
{ logo: "/images/bg-overview.png" }, const section4Data = data.section4Data;
{ logo: "/images/bg-overview.png" }, const section5Data = data.section5Data;
{ logo: "/images/bg-overview.png" },
], const topTabsData = section2Data ? { tabItems: section2Data.tabItems ?? [] } : null;
}
return ( return (
<div> <div>
<Banner <Banner
title="平台思维,共享价值" title={banner?.title ?? ""}
titleSize="medium" content={(banner as BannerConfig)?.content}
showBreadcrumb={true} titleSize={(banner as BannerConfig)?.titleSize ?? "medium"}
breadcrumbItems={[{ label: '社会责任', to: '/business' }, { label: '银泰公益基金会', to: '' }]} showBreadcrumb={banner?.showBreadcrumb ?? false}
backgroundImage={`/images/bg-overview.png`} backgroundImage={banner?.backgroundImage ?? "/images/bg-overview.png"}
/> />
<ParagraphSection data={paragraphSectionData}> {section1Data && (
<div style={{ marginTop: '100px' }}></div> <ParagraphSection data={section1Data}>
<TopTabs data={topTabsData} /> <div style={{ marginTop: "100px" }} />
<div style={{ marginBottom: '50px' }}></div> {topTabsData && <TopTabs data={topTabsData} />}
<div style={{ marginBottom: "50px" }} />
</ParagraphSection> </ParagraphSection>
)}
{/* 公益传播 */} {section3Data && (
<Section title={publicWelfareData.title} background="" maskBackground="rgba(255,255,255,0.3)"> <Section
title={section3Data.title}
background=""
maskBackground="rgba(255,255,255,0.3)"
>
<div className={styles.publicWelfareDataItems}> <div className={styles.publicWelfareDataItems}>
{publicWelfareData.items.map((item, index) => ( {section3Data.items?.map((item, index) => (
<div key={index} className={styles.publicWelfareDataItem} style={{ backgroundImage: `url(${item.backgroundImage})` }}> <div
key={index}
className={styles.publicWelfareDataItem}
style={{ backgroundImage: `url(${item.backgroundImage})` }}
>
<AnimateTopCard data={item} /> <AnimateTopCard data={item} />
</div> </div>
))} ))}
</div> </div>
<div style={{ marginBottom: '50px' }}></div> <div style={{ marginBottom: "50px" }} />
</Section> </Section>
)}
{/* 信息公开 */} {section4Data && (
<Section title={informationPublicData.title} titleColor="#fff" background="/images/bg-overview.png" maskBackground="rgba(255,255,255,0.1)"> <Section
title={section4Data.title}
titleColor="#fff"
background={section4Data.backgroundImage ?? "/images/bg-overview.png"}
maskBackground="rgba(255,255,255,0.1)"
>
<div className={styles.informationPublicDataContent}> <div className={styles.informationPublicDataContent}>
<div className={styles.informationPublicDataItems}> <div className={styles.informationPublicDataItems}>
{ {section4Data.tabItems?.[activeIndex]?.fileItems?.map((item, index) => (
informationPublicData.tabItems[activeIndex].fileItems.map((item, index) => (
<div key={index} className={styles.informationPublicDataItem}> <div key={index} className={styles.informationPublicDataItem}>
<li><span>{item.fileName}</span></li> <li>
<span>{item.fileName}</span>
</li>
</div> </div>
)) ))}
}
</div> </div>
<BottomTabs tabItems={informationPublicData.tabItems} activeIndex={activeIndex} setActiveIndex={setActiveIndex} /> <BottomTabs
tabItems={section4Data.tabItems ?? []}
activeIndex={activeIndex}
setActiveIndex={setActiveIndex}
/>
</div> </div>
</Section> </Section>
)}
{/* 公益伙伴 */} {section5Data && (
<Section title={partnerData.title} background="" maskBackground="#F7FBFF"> <Section title={section5Data.title} background="" maskBackground="#F7FBFF">
<div className={styles.partnerItems}> <div className={styles.partnerItems}>
{partnerData.items.map((item, index) => ( {section5Data.items?.map((item, index) => (
<div key={index} className={styles.partnerItem}> <div key={index} className={styles.partnerItem}>
<img src={item.logo} alt='logo' /> <img src={item.logo} alt="logo" />
</div> </div>
))} ))}
</div> </div>
</Section> </Section>
)}
</div> </div>
); );
} }

View File

@ -1,122 +1,102 @@
import Banner from "@/components/Banner"; import Banner, { type BannerConfig } from "@/components/Banner";
import { useState } from "react"; import { useState } from "react";
import ParagraphSection from "@/components/layout/ParagraphSection"; import ParagraphSection from "@/components/layout/ParagraphSection";
import ColumnXGrids from "@/components/layout/ColumnXGrids"; import ColumnXGrids from "@/components/layout/ColumnXGrids";
import Section from "@/components/layout/Section"; import Section from "@/components/layout/Section";
import styles from "./Sustainability.module.css";
import { Link } from "react-router-dom";
import AnimateTopCard from "@/components/layout/AnimateTopCard"; import AnimateTopCard from "@/components/layout/AnimateTopCard";
import { useStore } from "@/store";
import styles from "./Sustainability.module.css";
export default function Sustainability() { export default function Sustainability() {
const [paragraphSectionData] = useState({ const appConfig = useStore((s) => s.appConfig);
title: "银泰集团", const data = appConfig?.social?.sustainability;
content: "始终秉持“创造价值,服务社会”的使命,将社会责任融入企业发展的各个环节,形成了以合规治理、实业报国、经典品质、人才发展、绿色低碳、公益向善为核心的六大责任方向。银泰积极践行新发展理念,深度融入国家发展大局,持续投身乡村振兴、儿童关爱、社区共建等公益事业,以实际行动诠释企业担当,为实现人与自然、社会和谐共生的美好未来贡献力量", const [sliceIndex, setSliceIndex] = useState(4);
})
const columnXGridsData = [ if (!data) return null;
{
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 = { const banner = data.banner;
title: "社会责任案例集", const section1Data = data.section1Data;
content: "银泰集团通过挖掘内部员工,外部消费者、品牌方、合作伙伴、受益人等不同利益相关方的案例故事,希望以一个个真实、鲜活的人物为线索,全方位展现银泰的责任担当,让大家感受到“爱@在一起”的温暖和力量。", const section2Data = data.section2Data ?? [];
items: [ const section3Data = data.section3Data;
{title: "案例1向浙江大学教育基金会", content: "2019年银泰公益基金会向浙江大学教育基金会捐赠资金250万元专项支持浙江立法研究院的发展建设助力汇聚立法智慧、培育立法人才、引领智能立法、致力于建成全国性的立法研究高地和人才培养基地。", link: '', backgroundImage: "/images/bg-overview.png"}, const section4Data = data.section4Data;
{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 = { const columnXGridsData = section2Data;
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>
<Banner <Banner
title="可持续发展" title={banner?.title ?? ""}
titleSize="medium" content={(banner as BannerConfig)?.content}
showBreadcrumb={true} titleSize={(banner as BannerConfig)?.titleSize ?? "medium"}
breadcrumbItems={[{ label: '社会责任', to: '/business' }, { label: '可持续发展', to: '' }]} showBreadcrumb={banner?.showBreadcrumb ?? false}
backgroundImage={`/images/bg-overview.png`} backgroundImage={banner?.backgroundImage ?? "/images/bg-overview.png"}
/> />
<ParagraphSection data={paragraphSectionData} > {section1Data && (
<ParagraphSection data={section1Data}>
<ColumnXGrids items={columnXGridsData} /> <ColumnXGrids items={columnXGridsData} />
</ParagraphSection> </ParagraphSection>
)}
{/* 社会责任案例集 */} {section3Data && (
<Section title={socialResponsibilityCaseData.title} background="" maskBackground="rgba(255,255,255,0.3)"> <Section
title={section3Data.title}
background=""
maskBackground="rgba(255,255,255,0.3)"
>
<p className={styles.socialResponsibilityCaseDataContent}> <p className={styles.socialResponsibilityCaseDataContent}>
{socialResponsibilityCaseData.content} {section3Data.content}
</p> </p>
<div className={styles.socialResponsibilityCaseDataItems}> <div className={styles.socialResponsibilityCaseDataItems}>
{socialResponsibilityCaseData.items.map((item,index) => ( {section3Data.items?.map((item, index) => (
<div key={index} className={styles.socialResponsibilityCaseDataItem} style={{ backgroundImage: `url(${item.backgroundImage})` }}> <div
key={index}
className={styles.socialResponsibilityCaseDataItem}
style={{ backgroundImage: `url(${item.backgroundImage})` }}
>
<AnimateTopCard data={item} /> <AnimateTopCard data={item} />
</div> </div>
))} ))}
</div> </div>
</Section> </Section>
)}
{/* 社会责任报告 */} {section4Data && (
<Section title={socialResponsibilityReportData.title} background="" maskBackground="#F7FBFF"> <Section
title={section4Data.title}
background=""
maskBackground="#F7FBFF"
>
<div className={styles.socialResponsibilityReportData}> <div className={styles.socialResponsibilityReportData}>
{socialResponsibilityReportData.items.slice(0, sliceIndex).map((item,index) => ( {section4Data.items?.slice(0, sliceIndex).map((item, index) => (
<div key={index} className={styles.socialResponsibilityReportItem}> <div
<div className={styles.socialResponsibilityReportItemCover} style={{ backgroundImage: `url(${item.coverImage})` }}></div> key={index}
<div className={styles.socialResponsibilityReportItemTitle}>{item.title}</div> className={styles.socialResponsibilityReportItem}
>
<div
className={styles.socialResponsibilityReportItemCover}
style={{ backgroundImage: `url(${item.coverImage})` }}
/>
<div className={styles.socialResponsibilityReportItemTitle}>
{item.title}
</div>
</div> </div>
))} ))}
</div> </div>
<div className={styles.socialResponsibilityReportItemMore} onClick={() => setSliceIndex(sliceIndex < socialResponsibilityReportData.items.length ? sliceIndex + 4 : 4)}> <div
{sliceIndex < socialResponsibilityReportData.items.length ? "了解更多" : "收起"} className={styles.socialResponsibilityReportItemMore}
onClick={() =>
setSliceIndex(
sliceIndex < (section4Data.items?.length ?? 0)
? sliceIndex + 4
: 4
)
}
>
{sliceIndex < (section4Data.items?.length ?? 0) ? "了解更多" : "收起"}
</div> </div>
</Section> </Section>
)}
</div> </div>
); );
} }

View File

@ -1,31 +1,61 @@
import { create } from "zustand"; import { create } from "zustand";
import { persist } from "zustand/middleware"; import { persist } from "zustand/middleware";
interface AppConfig { import type mockData from "@/api/mockData";
company?: {
config?: { export type AppConfig = typeof mockData extends { zhCN: infer Z } ? Z : never;
favicon?: string; export type I18nData = { zhCN: AppConfig; en: AppConfig };
shortName?: string; export type LocaleKey = "zhCN" | "en";
};
};
[key: string]: unknown;
}
interface StoreState { interface StoreState {
locale: LocaleKey;
i18nData: I18nData | null;
appConfig: AppConfig | null; appConfig: AppConfig | null;
token: string | null; token: string | null;
setAppConfig: (config: AppConfig | null) => void; setLocale: (locale: LocaleKey) => void;
setAppConfig: (data: I18nData) => void;
setToken: (token: string | null) => void; setToken: (token: string | null) => void;
} }
export const useStore = create<StoreState>()( export const useStore = create<StoreState>()(
persist( persist(
(set) => ({ (set) => ({
locale: "zhCN",
i18nData: null,
appConfig: null, appConfig: null,
token: null, token: null,
setAppConfig: (config) => set({ appConfig: config }), setLocale: (locale) =>
set((state) => ({
locale,
appConfig: state.i18nData?.[locale] ?? null,
})),
setAppConfig: (data) =>
set((state) => ({
i18nData: data,
appConfig: data[state.locale] ?? null,
})),
setToken: (token) => set({ token }), setToken: (token) => set({ token }),
}), }),
{ name: "yintai-store" } {
name: "yintai-store",
version: 1,
migrate: (persisted: unknown) => {
const p = persisted as Record<string, unknown>;
if (p?.i18nData || !p?.appConfig) return p;
const legacy = p.appConfig as AppConfig;
return {
...p,
locale: (p.locale as LocaleKey) ?? "zhCN",
i18nData: { zhCN: legacy, en: legacy },
appConfig: legacy,
};
},
partialize: (s) => ({
locale: s.locale,
i18nData: s.i18nData,
token: s.token,
appConfig: s.i18nData?.[s.locale] ?? s.appConfig,
}),
}
) )
); );