update:before animate save
This commit is contained in:
parent
aa8358c91e
commit
1c1c68d597
|
|
@ -104,7 +104,7 @@ const zhCN = {
|
||||||
{
|
{
|
||||||
title: "银泰商业集团",
|
title: "银泰商业集团",
|
||||||
content: "涵盖地标型高端商业综合体in77、景观地标型商业综合体inPARK区域型品质商业生活中心银泰城等品牌的大型商业集团,是一家持续推动传统零售业创新与互联网转型融合的典范性企业。",
|
content: "涵盖地标型高端商业综合体in77、景观地标型商业综合体inPARK区域型品质商业生活中心银泰城等品牌的大型商业集团,是一家持续推动传统零售业创新与互联网转型融合的典范性企业。",
|
||||||
image: "/images/bg-commercial-group.png",
|
backgroundImage: "/images/bg-commercial-group.png",
|
||||||
links: [
|
links: [
|
||||||
{ text: "in77", path: "/in77" },
|
{ text: "in77", path: "/in77" },
|
||||||
{ text: "inPARK", path: "/inPARK" },
|
{ text: "inPARK", path: "/inPARK" },
|
||||||
|
|
@ -114,7 +114,7 @@ const zhCN = {
|
||||||
{
|
{
|
||||||
title: "银泰基业集团",
|
title: "银泰基业集团",
|
||||||
content: "银泰基业集团是银泰集团旗下核心业务板块,深耕商业地产与零售领域多年,致力于打造高品质商业空间,引领现代消费体验。集团旗下拥有银泰百货、银泰城等多个知名商业品牌,在全国多个核心城市布局,持续为消费者创造美好生活。",
|
content: "银泰基业集团是银泰集团旗下核心业务板块,深耕商业地产与零售领域多年,致力于打造高品质商业空间,引领现代消费体验。集团旗下拥有银泰百货、银泰城等多个知名商业品牌,在全国多个核心城市布局,持续为消费者创造美好生活。",
|
||||||
image: "/images/bg-base-group.png",
|
backgroundImage: "/images/bg-base-group.png",
|
||||||
links: [
|
links: [
|
||||||
{ text: "in77", path: "/in77" },
|
{ text: "in77", path: "/in77" },
|
||||||
{ text: "inPARK", path: "/inPARK" },
|
{ text: "inPARK", path: "/inPARK" },
|
||||||
|
|
@ -124,7 +124,7 @@ const zhCN = {
|
||||||
{
|
{
|
||||||
title: "银泰置地集团",
|
title: "银泰置地集团",
|
||||||
content: "银泰置地集团是银泰集团旗下核心业务板块,深耕商业地产与零售领域多年,致力于打造高品质商业空间,引领现代消费体验。集团旗下拥有银泰百货、银泰城等多个知名商业品牌,在全国多个核心城市布局,持续为消费者创造美好生活。",
|
content: "银泰置地集团是银泰集团旗下核心业务板块,深耕商业地产与零售领域多年,致力于打造高品质商业空间,引领现代消费体验。集团旗下拥有银泰百货、银泰城等多个知名商业品牌,在全国多个核心城市布局,持续为消费者创造美好生活。",
|
||||||
image: "/images/bg-realty-group.png",
|
backgroundImage: "/images/bg-realty-group.png",
|
||||||
links: [
|
links: [
|
||||||
{ text: "in77", path: "/in77" },
|
{ text: "in77", path: "/in77" },
|
||||||
{ text: "inPARK", path: "/inPARK" },
|
{ text: "inPARK", path: "/inPARK" },
|
||||||
|
|
@ -134,7 +134,7 @@ const zhCN = {
|
||||||
{
|
{
|
||||||
title: "银泰投资集团",
|
title: "银泰投资集团",
|
||||||
content: "银泰投资集团是银泰集团旗下核心业务板块,深耕商业地产与零售领域多年,致力于打造高品质商业空间,引领现代消费体验。集团旗下拥有银泰百货、银泰城等多个知名商业品牌,在全国多个核心城市布局,持续为消费者创造美好生活。",
|
content: "银泰投资集团是银泰集团旗下核心业务板块,深耕商业地产与零售领域多年,致力于打造高品质商业空间,引领现代消费体验。集团旗下拥有银泰百货、银泰城等多个知名商业品牌,在全国多个核心城市布局,持续为消费者创造美好生活。",
|
||||||
image: "/images/bg-invest-group.png",
|
backgroundImage: "/images/bg-invest-group.png",
|
||||||
links: [
|
links: [
|
||||||
{ text: "in77", path: "/in77" },
|
{ text: "in77", path: "/in77" },
|
||||||
{ text: "inPARK", path: "/inPARK" },
|
{ text: "inPARK", path: "/inPARK" },
|
||||||
|
|
@ -144,7 +144,7 @@ const zhCN = {
|
||||||
{
|
{
|
||||||
title: "瑞京资产",
|
title: "瑞京资产",
|
||||||
content: "瑞京集团是银泰集团旗下核心业务板块,深耕商业地产与零售领域多年,致力于打造高品质商业空间,引领现代消费体验。集团旗下拥有银泰百货、银泰城等多个知名商业品牌,在全国多个核心城市布局,持续为消费者创造美好生活。",
|
content: "瑞京集团是银泰集团旗下核心业务板块,深耕商业地产与零售领域多年,致力于打造高品质商业空间,引领现代消费体验。集团旗下拥有银泰百货、银泰城等多个知名商业品牌,在全国多个核心城市布局,持续为消费者创造美好生活。",
|
||||||
image: "/images/bg-ruijing-group.png",
|
backgroundImage: "/images/bg-ruijing-group.png",
|
||||||
links: [
|
links: [
|
||||||
{ text: "in77", path: "/in77" },
|
{ text: "in77", path: "/in77" },
|
||||||
{ text: "inPARK", path: "/inPARK" },
|
{ text: "inPARK", path: "/inPARK" },
|
||||||
|
|
@ -287,12 +287,12 @@ const zhCN = {
|
||||||
items: [
|
items: [
|
||||||
{
|
{
|
||||||
title: "商业领域",
|
title: "商业领域",
|
||||||
image: "/images/bg-invest-group.png",
|
backgroundImage: "/images/bg-invest-group.png",
|
||||||
content: "银泰集团在商业领域有着丰富的经验和深厚的实力,致力于打造高品质的商业空间,引领现代消费体验。",
|
content: "银泰集团在商业领域有着丰富的经验和深厚的实力,致力于打造高品质的商业空间,引领现代消费体验。",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "社会责任",
|
title: "社会责任",
|
||||||
image: "/images/bg-invest-group.png",
|
backgroundImage: "/images/bg-invest-group.png",
|
||||||
content: "银泰集团在社会责任方面有着丰富的经验和深厚的实力,致力于打造高品质的商业空间,引领现代消费体验。",
|
content: "银泰集团在社会责任方面有着丰富的经验和深厚的实力,致力于打造高品质的商业空间,引领现代消费体验。",
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|
@ -333,12 +333,23 @@ const zhCN = {
|
||||||
title: "荣誉奖项",
|
title: "荣誉奖项",
|
||||||
backgroundImage: '',
|
backgroundImage: '',
|
||||||
items: [
|
items: [
|
||||||
|
{ year: '2026年', children: ["2015年度“影响·2015中国公益100人”", "2015年度“中国社会十大推动者”"]},
|
||||||
|
{ year: '2025年', children: ["2015年度“影响·2015中国公益100人”", "2015年度“中国社会十大推动者”"]},
|
||||||
|
{ year: '2024年', children: ["2015年度“影响·2015中国公益100人”", "2015年度“中国社会十大推动者”"]},
|
||||||
|
{ year: '2023年', children: ["2015年度“影响·2015中国公益100人”", "2015年度“中国社会十大推动者”"]},
|
||||||
|
{ year: '2022年', children: ["2015年度“影响·2015中国公益100人”", "2015年度“中国社会十大推动者”"]},
|
||||||
|
{ year: '2021年', children: ["2015年度“影响·2015中国公益100人”", "2015年度“中国社会十大推动者”"]},
|
||||||
{ year: '2020年', children: ["2015年度“影响·2015中国公益100人”", "2015年度“中国社会十大推动者”"]},
|
{ year: '2020年', children: ["2015年度“影响·2015中国公益100人”", "2015年度“中国社会十大推动者”"]},
|
||||||
{ year: '2019年', children: ["2015年度“影响·2015中国公益100人”", "2015年度“中国社会十大推动者”"]},
|
{ year: '2019年', children: ["2015年度“影响·2015中国公益100人”", "2015年度“中国社会十大推动者”"]},
|
||||||
{ year: '2018年', children: ["2015年度“影响·2015中国公益100人”", "2015年度“中国社会十大推动者”"]},
|
{ year: '2018年', children: ["2015年度“影响·2015中国公益100人”", "2015年度“中国社会十大推动者”"]},
|
||||||
{ year: '2017年', children: ["2015年度“影响·2015中国公益100人”", "2015年度“中国社会十大推动者”"]},
|
{ year: '2017年', children: ["2015年度“影响·2015中国公益100人”", "2015年度“中国社会十大推动者”"]},
|
||||||
{ year: '2016年', children: ["2015年度“影响·2015中国公益100人”", "2015年度“中国社会十大推动者”"]},
|
{ year: '2016年', children: ["2015年度“影响·2015中国公益100人”", "2015年度“中国社会十大推动者”"]},
|
||||||
{ year: '2015年', children: ["2015年度“影响·2015中国公益100人”", "2015年度“中国社会十大推动者”"]},
|
{ year: '2015年', children: ["2015年度“影响·2015中国公益100人”", "2015年度“中国社会十大推动者”"]},
|
||||||
|
{ year: '2014年', children: ["2015年度“影响·2015中国公益100人”", "2015年度“中国社会十大推动者”"]},
|
||||||
|
{ year: '2013年', children: ["2015年度“影响·2015中国公益100人”", "2015年度“中国社会十大推动者”"]},
|
||||||
|
{ year: '2012年', children: ["2015年度“影响·2015中国公益100人”", "2015年度“中国社会十大推动者”"]},
|
||||||
|
{ year: '2011年', children: ["2015年度“影响·2015中国公益100人”", "2015年度“中国社会十大推动者”"]},
|
||||||
|
{ year: '2010年', children: ["2015年度“影响·2015中国公益100人”", "2015年度“中国社会十大推动者”"]},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
@ -359,17 +370,18 @@ const zhCN = {
|
||||||
},
|
},
|
||||||
section2Data: {
|
section2Data: {
|
||||||
tabItems: [
|
tabItems: [
|
||||||
{ label: "in77", content: "in77 内容", image: "/images/bg-overview.png", path: "/business/commercial-group/in77" },
|
{ tabName: "in77", content: "in77 内容", sideImage: "/images/bg-overview.png", path: "/business/commercial-group/in77" },
|
||||||
{ label: "inPARK", content: "inPARK 内容", image: "/images/bg-overview.png", path: "/business/commercial-group/inPARK" },
|
{ tabName: "inPARK", content: "inPARK 内容", sideImage: "/images/bg-overview.png", path: "/business/commercial-group/inPARK" },
|
||||||
{ label: "银泰城购物中心", content: "银泰城 内容", image: "/images/bg-overview.png", path: "/business/commercial-group/shopping-center" },
|
{ tabName: "银泰城购物中心", content: "银泰城 内容", sideImage: "/images/bg-overview.png", path: "/business/commercial-group/shopping-center" },
|
||||||
],
|
],
|
||||||
|
backgroundImage: '/images/bg-in.png'
|
||||||
},
|
},
|
||||||
section3Data: {
|
section3Data: {
|
||||||
tabItems: [
|
tabItems: [
|
||||||
{ label: "深耕运营", content: "全域营销 内容", image: "/images/bg-overview.png" },
|
{ tabName: "深耕运营", content: "全域营销 内容", backgroundImage: "/images/bg-overview.png" },
|
||||||
{ label: "行业领先", content: "数字化运营 内容", image: "/images/bg-overview.png" },
|
{ tabName: "行业领先", content: "数字化运营 内容", backgroundImage: "/images/bg-overview.png" },
|
||||||
{ label: "创新变革", content: "全球品牌合作 内容", image: "/images/bg-overview.png" },
|
{ tabName: "创新变革", content: "全球品牌合作 内容", backgroundImage: "/images/bg-overview.png" },
|
||||||
{ label: "数字生态", content: "全球品牌合作 内容", image: "/images/bg-overview.png" },
|
{ tabName: "数字生态", content: "全球品牌合作 内容", backgroundImage: "/images/bg-overview.png" },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
banner: {
|
banner: {
|
||||||
|
|
@ -381,13 +393,37 @@ const zhCN = {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
commercialGroupDetail: {
|
commercialGroupDetail: {
|
||||||
banner: {
|
items: [
|
||||||
title: "in77",
|
{
|
||||||
largeContent: "地标型高端商业综合体",
|
pathname: "in77",
|
||||||
titleSize: "large",
|
banner: {
|
||||||
showBreadcrumb: true,
|
title: "in77",
|
||||||
backgroundImage: "/images/bg-overview.png",
|
largeContent: "地标型高端商业综合体",
|
||||||
},
|
titleSize: "large",
|
||||||
|
showBreadcrumb: true,
|
||||||
|
backgroundImage: "/images/bg-overview.png",
|
||||||
|
},
|
||||||
|
section1Data: {
|
||||||
|
backgroundImage: "",
|
||||||
|
title: "in77",
|
||||||
|
content: "作为高端商业品牌,汲取了银泰集团优质的商业资源及运营管理能力,旗下项目均位于核心商业圈或国家示范步行街,成为时尚零售业和新消费领域的标杆。目前有北京银泰中心in01、杭州湖滨银泰in77、北京王府井银泰in88、合肥银泰in77及成都银泰中心in99等项目。每个项目都融入“唤醒真正的自我”的理念,同时亦不乏各自特色与个性。",
|
||||||
|
},
|
||||||
|
section2Data: {
|
||||||
|
backgroundImage: "/images/bg-in.png",
|
||||||
|
titleDirection: "column",
|
||||||
|
tabItems: [
|
||||||
|
{ tabName: "北京银泰中心in01", icon: '/images/bg-overview.png', contentTitle: "银泰中心1", contentSubtitle: "城市封面地标", contentText: "北京银泰中心是银泰置地集团在北京的核心项目,是集高端购物中心、酒店、公寓、超甲级写字楼等业态于一体的综合性商业地产项目。", sideImage: "/images/bg-overview.png" },
|
||||||
|
{ tabName: "杭州湖滨银泰in77", icon: '/images/bg-overview.png', contentTitle: "银泰中心2", contentSubtitle: "城市封面地标", contentText: "北京银泰中心是银泰置地集团在北京的核心项目,是集高端购物中心、酒店、公寓、超甲级写字楼等业态于一体的综合性商业地产项目。", sideImage: "/images/bg-overview.png" },
|
||||||
|
{ tabName: "北京王府井银泰in88", icon: '/images/bg-overview.png', contentTitle: "银泰中心3", contentSubtitle: "城市封面地标", contentText: "北京银泰中心是银泰置地集团在北京的核心项目,是集高端购物中心、酒店、公寓、超甲级写字楼等业态于一体的综合性商业地产项目。", sideImage: "/images/bg-overview.png" },
|
||||||
|
{ tabName: "成都银泰中心in99", icon: '/images/bg-overview.png', contentTitle: "银泰中心", contentSubtitle: "城市封面地标", contentText: "北京银泰中心是银泰置地集团在北京的核心项目,是集高端购物中心、酒店、公寓、超甲级写字楼等业态于一体的综合性商业地产项目。", sideImage: "/images/bg-overview.png" },
|
||||||
|
{ tabName: "成都银泰中心in99", icon: '/images/bg-overview.png', contentTitle: "银泰中心", contentSubtitle: "城市封面地标", contentText: "北京银泰中心是银泰置地集团在北京的核心项目,是集高端购物中心、酒店、公寓、超甲级写字楼等业态于一体的综合性商业地产项目。", sideImage: "/images/bg-overview.png" },
|
||||||
|
{ tabName: "成都银泰中心in99", icon: '/images/bg-overview.png', contentTitle: "银泰中心", contentSubtitle: "城市封面地标", contentText: "北京银泰中心是银泰置地集团在北京的核心项目,是集高端购物中心、酒店、公寓、超甲级写字楼等业态于一体的综合性商业地产项目。", sideImage: "/images/bg-overview.png" },
|
||||||
|
{ tabName: "成都银泰中心in99", icon: '/images/bg-overview.png', contentTitle: "银泰中心", contentSubtitle: "城市封面地标", contentText: "北京银泰中心是银泰置地集团在北京的核心项目,是集高端购物中心、酒店、公寓、超甲级写字楼等业态于一体的综合性商业地产项目。", sideImage: "/images/bg-overview.png" },
|
||||||
|
{ tabName: "成都银泰中心in99", icon: '/images/bg-overview.png', contentTitle: "银泰中心", contentSubtitle: "城市封面地标", contentText: "北京银泰中心是银泰置地集团在北京的核心项目,是集高端购物中心、酒店、公寓、超甲级写字楼等业态于一体的综合性商业地产项目。", sideImage: "/images/bg-overview.png" },
|
||||||
|
],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
},
|
},
|
||||||
baseGroup: {
|
baseGroup: {
|
||||||
section1Data: {
|
section1Data: {
|
||||||
|
|
@ -404,11 +440,11 @@ const zhCN = {
|
||||||
section2Data: {
|
section2Data: {
|
||||||
title: "四大区域",
|
title: "四大区域",
|
||||||
cardItems: [
|
cardItems: [
|
||||||
{ title: "服务业态1", content: "服务业态1", image: "/images/bg-overview.png" },
|
{ title: "服务业态1", content: "服务业态1", backgroundImage: "/images/bg-overview.png" },
|
||||||
{ title: "服务业态2", content: "服务业态2", image: "/images/bg-overview.png" },
|
{ title: "服务业态2", content: "服务业态2", backgroundImage: "/images/bg-overview.png" },
|
||||||
{ title: "服务业态3", content: "服务业态3", image: "/images/bg-overview.png" },
|
{ title: "服务业态3", content: "服务业态3", backgroundImage: "/images/bg-overview.png" },
|
||||||
{ title: "服务业态4", content: "服务业态3", image: "/images/bg-overview.png" },
|
{ title: "服务业态4", content: "服务业态3", backgroundImage: "/images/bg-overview.png" },
|
||||||
{ title: "服务业态5", content: "服务业态3", image: "/images/bg-overview.png" },
|
{ title: "服务业态5", content: "服务业态3", backgroundImage: "/images/bg-overview.png" },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
section3Data: {
|
section3Data: {
|
||||||
|
|
@ -417,7 +453,7 @@ const zhCN = {
|
||||||
{
|
{
|
||||||
title: "北京",
|
title: "北京",
|
||||||
subtitle: "北京银泰中心",
|
subtitle: "北京银泰中心",
|
||||||
image: "/images/bg-overview.png",
|
backgroundImage: "/images/bg-overview.png",
|
||||||
links: [
|
links: [
|
||||||
{ text: "in01", path: "" },
|
{ text: "in01", path: "" },
|
||||||
{ text: "超甲级写字楼", path: "" },
|
{ text: "超甲级写字楼", path: "" },
|
||||||
|
|
@ -426,9 +462,9 @@ const zhCN = {
|
||||||
{ text: "柏悦居", path: "" },
|
{ text: "柏悦居", path: "" },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{ title: "四川", subtitle: "成都银泰中心", image: "/images/bg-overview.png" },
|
{ title: "四川", subtitle: "成都银泰中心", backgroundImage: "/images/bg-overview.png" },
|
||||||
{ title: "浙江", subtitle: "杭州湖滨银泰in77", image: "/images/bg-overview.png" },
|
{ title: "浙江", subtitle: "杭州湖滨银泰in77", backgroundImage: "/images/bg-overview.png" },
|
||||||
{ title: "上海", subtitle: "上海中骏广场", image: "/images/bg-overview.png" },
|
{ title: "上海", subtitle: "上海中骏广场", backgroundImage: "/images/bg-overview.png" },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
section4Data: {
|
section4Data: {
|
||||||
|
|
@ -447,10 +483,10 @@ const zhCN = {
|
||||||
section5Data: {
|
section5Data: {
|
||||||
title: "业务特色",
|
title: "业务特色",
|
||||||
tabItems: [
|
tabItems: [
|
||||||
{ tabName: "精细化运营", contentTitle: "精细化运营——运筹帷幄·精于心", contentText: "通过精细化管理赋能运营,稳步提升商业资产价值。关注租金的成长性和租户的良性表现,实现产品逐步升级,服务稳健提升,实现商业资产整体增值。", image: "/images/bg-overview.png" },
|
{ tabName: "精细化运营", contentTitle: "精细化运营——运筹帷幄·精于心", contentText: "通过精细化管理赋能运营,稳步提升商业资产价值。关注租金的成长性和租户的良性表现,实现产品逐步升级,服务稳健提升,实现商业资产整体增值。", backgroundImage: "/images/bg-overview.png" },
|
||||||
{ tabName: "数智化管理", contentTitle: "内容标题2", contentText: "内容文本2", image: "/images/bg-overview.png" },
|
{ tabName: "数智化管理", contentTitle: "内容标题2", contentText: "内容文本2", backgroundImage: "/images/bg-overview.png" },
|
||||||
{ tabName: "生态化发展", contentTitle: "内容标题2", contentText: "内容文本2", image: "/images/bg-overview.png" },
|
{ tabName: "生态化发展", contentTitle: "内容标题2", contentText: "内容文本2", backgroundImage: "/images/bg-overview.png" },
|
||||||
{ tabName: "品牌化升级", contentTitle: "内容标题2", contentText: "内容文本2", image: "/images/bg-overview.png" },
|
{ tabName: "品牌化升级", contentTitle: "内容标题2", contentText: "内容文本2", backgroundImage: "/images/bg-overview.png" },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
banner: {
|
banner: {
|
||||||
|
|
@ -517,19 +553,19 @@ const zhCN = {
|
||||||
},
|
},
|
||||||
section2Data: {
|
section2Data: {
|
||||||
tabItems: [
|
tabItems: [
|
||||||
{ tabName: "银泰中心", contentTitle: "银泰中心1", contentSubtitle: "城市封面地标", contentText: "北京银泰中心是银泰置地集团在北京的核心项目,是集高端购物中心、酒店、公寓、超甲级写字楼等业态于一体的综合性商业地产项目。", image: "/images/bg-overview.png" },
|
{ tabName: "银泰中心", contentTitle: "银泰中心1", contentSubtitle: "城市封面地标", contentText: "北京银泰中心是银泰置地集团在北京的核心项目,是集高端购物中心、酒店、公寓、超甲级写字楼等业态于一体的综合性商业地产项目。", backgroundImage: "/images/bg-overview.png" },
|
||||||
{ tabName: "银泰城", contentTitle: "银泰中心2", contentSubtitle: "城市封面地标", contentText: "北京银泰中心是银泰置地集团在北京的核心项目,是集高端购物中心、酒店、公寓、超甲级写字楼等业态于一体的综合性商业地产项目。", image: "/images/bg-overview.png" },
|
{ tabName: "银泰城", contentTitle: "银泰中心2", contentSubtitle: "城市封面地标", contentText: "北京银泰中心是银泰置地集团在北京的核心项目,是集高端购物中心、酒店、公寓、超甲级写字楼等业态于一体的综合性商业地产项目。", backgroundImage: "/images/bg-overview.png" },
|
||||||
{ tabName: "高级酒店与公寓", contentTitle: "银泰中心3", contentSubtitle: "城市封面地标", contentText: "北京银泰中心是银泰置地集团在北京的核心项目,是集高端购物中心、酒店、公寓、超甲级写字楼等业态于一体的综合性商业地产项目。", image: "/images/bg-overview.png" },
|
{ tabName: "高级酒店与公寓", contentTitle: "银泰中心3", contentSubtitle: "城市封面地标", contentText: "北京银泰中心是银泰置地集团在北京的核心项目,是集高端购物中心、酒店、公寓、超甲级写字楼等业态于一体的综合性商业地产项目。", backgroundImage: "/images/bg-overview.png" },
|
||||||
{ tabName: "文旅小镇", contentTitle: "银泰中心", contentSubtitle: "城市封面地标", contentText: "北京银泰中心是银泰置地集团在北京的核心项目,是集高端购物中心、酒店、公寓、超甲级写字楼等业态于一体的综合性商业地产项目。", image: "/images/bg-overview.png" },
|
{ tabName: "文旅小镇", contentTitle: "银泰中心", contentSubtitle: "城市封面地标", contentText: "北京银泰中心是银泰置地集团在北京的核心项目,是集高端购物中心、酒店、公寓、超甲级写字楼等业态于一体的综合性商业地产项目。", backgroundImage: "/images/bg-overview.png" },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
section3Data: {
|
section3Data: {
|
||||||
title: "标杆项目",
|
title: "标杆项目",
|
||||||
items: [
|
items: [
|
||||||
{ title: "杭州银泰中心", content: '位于杭州未来科技城地块,与余杭区政府合作开发建设,规划投资数十亿元,建设总建筑面积约60万方的高端TOD城市综合体,推动区域向"国际化消费中心"转型,打造百亿级商圈。', image: "/images/bg-overview.png" },
|
{ title: "杭州银泰中心", content: '位于杭州未来科技城地块,与余杭区政府合作开发建设,规划投资数十亿元,建设总建筑面积约60万方的高端TOD城市综合体,推动区域向"国际化消费中心"转型,打造百亿级商圈。', backgroundImage: "/images/bg-overview.png" },
|
||||||
{ title: "丽水银泰城", content: '位于杭州未来科技城地块,与余杭区政府合作开发建设,规划投资数十亿元,建设总建筑面积约60万方的高端TOD城市综合体,推动区域向"国际化消费中心"转型,打造百亿级商圈。', image: "/images/bg-overview.png" },
|
{ title: "丽水银泰城", content: '位于杭州未来科技城地块,与余杭区政府合作开发建设,规划投资数十亿元,建设总建筑面积约60万方的高端TOD城市综合体,推动区域向"国际化消费中心"转型,打造百亿级商圈。', backgroundImage: "/images/bg-overview.png" },
|
||||||
{ title: "杭州银泰喜来登大酒店", content: '位于杭州未来科技城地块,与余杭区政府合作开发建设,规划投资数十亿元,建设总建筑面积约60万方的高端TOD城市综合体,推动区域向"国际化消费中心"转型,打造百亿级商圈。', image: "/images/bg-overview.png" },
|
{ title: "杭州银泰喜来登大酒店", content: '位于杭州未来科技城地块,与余杭区政府合作开发建设,规划投资数十亿元,建设总建筑面积约60万方的高端TOD城市综合体,推动区域向"国际化消费中心"转型,打造百亿级商圈。', backgroundImage: "/images/bg-overview.png" },
|
||||||
{ title: "杭州银泰仙女湖小镇", content: '位于杭州未来科技城地块,与余杭区政府合作开发建设,规划投资数十亿元,建设总建筑面积约60万方的高端TOD城市综合体,推动区域向"国际化消费中心"转型,打造百亿级商圈。', image: "/images/bg-overview.png" },
|
{ title: "杭州银泰仙女湖小镇", content: '位于杭州未来科技城地块,与余杭区政府合作开发建设,规划投资数十亿元,建设总建筑面积约60万方的高端TOD城市综合体,推动区域向"国际化消费中心"转型,打造百亿级商圈。', backgroundImage: "/images/bg-overview.png" },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
section4Data: {
|
section4Data: {
|
||||||
|
|
@ -548,10 +584,10 @@ const zhCN = {
|
||||||
section5Data: {
|
section5Data: {
|
||||||
title: "业务特色",
|
title: "业务特色",
|
||||||
tabItems: [
|
tabItems: [
|
||||||
{ tabName: "精细化运营", contentTitle: "精细化运营——运筹帷幄·精于心", contentText: "通过精细化管理赋能运营,稳步提升商业资产价值。关注租金的成长性和租户的良性表现,实现产品逐步升级,服务稳健提升,实现商业资产整体增值。", image: "/images/bg-overview.png" },
|
{ tabName: "精细化运营", contentTitle: "精细化运营——运筹帷幄·精于心", contentText: "通过精细化管理赋能运营,稳步提升商业资产价值。关注租金的成长性和租户的良性表现,实现产品逐步升级,服务稳健提升,实现商业资产整体增值。", backgroundImage: "/images/bg-overview.png" },
|
||||||
{ tabName: "数智化管理", contentTitle: "内容标题2", contentText: "内容文本2", image: "/images/bg-overview.png" },
|
{ tabName: "数智化管理", contentTitle: "内容标题2", contentText: "内容文本2", backgroundImage: "/images/bg-overview.png" },
|
||||||
{ tabName: "生态化发展", contentTitle: "内容标题2", contentText: "内容文本2", image: "/images/bg-overview.png" },
|
{ tabName: "生态化发展", contentTitle: "内容标题2", contentText: "内容文本2", backgroundImage: "/images/bg-overview.png" },
|
||||||
{ tabName: "品牌化升级", contentTitle: "内容标题2", contentText: "内容文本2", image: "/images/bg-overview.png" },
|
{ tabName: "品牌化升级", contentTitle: "内容标题2", contentText: "内容文本2", backgroundImage: "/images/bg-overview.png" },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
banner: {
|
banner: {
|
||||||
|
|
@ -575,13 +611,13 @@ const zhCN = {
|
||||||
section2Data: {
|
section2Data: {
|
||||||
title: "业务架构",
|
title: "业务架构",
|
||||||
cardItems: [
|
cardItems: [
|
||||||
{ title: "不良债权收购", content: "服务业态1", image: "/images/bg-overview.png" },
|
{ title: "不良债权收购", content: "服务业态1", backgroundImage: "/images/bg-overview.png" },
|
||||||
{ title: "债务重组", content: "服务业态2", image: "/images/bg-overview.png" },
|
{ title: "债务重组", content: "服务业态2", backgroundImage: "/images/bg-overview.png" },
|
||||||
{ title: "投资管理", content: "服务业态3", image: "/images/bg-overview.png" },
|
{ title: "投资管理", content: "服务业态3", backgroundImage: "/images/bg-overview.png" },
|
||||||
{ title: "金融服务", content: "服务业态4", image: "/images/bg-overview.png" },
|
{ title: "金融服务", content: "服务业态4", backgroundImage: "/images/bg-overview.png" },
|
||||||
{ title: "个贷不良", content: "服务业态5", image: "/images/bg-overview.png" },
|
{ title: "个贷不良", content: "服务业态5", backgroundImage: "/images/bg-overview.png" },
|
||||||
{ title: "企业纾困", content: "服务业态5", image: "/images/bg-overview.png" },
|
{ title: "企业纾困", content: "服务业态5", backgroundImage: "/images/bg-overview.png" },
|
||||||
{ title: "问题企业流动性支持", content: "服务业态5", image: "/images/bg-overview.png" },
|
{ title: "问题企业流动性支持", content: "服务业态5", backgroundImage: "/images/bg-overview.png" },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
section3Data: {
|
section3Data: {
|
||||||
|
|
@ -629,21 +665,21 @@ const zhCN = {
|
||||||
section2Data: {
|
section2Data: {
|
||||||
title: "服务业态",
|
title: "服务业态",
|
||||||
cardItems: [
|
cardItems: [
|
||||||
{ title: "服务业态1", content: "服务业态1", image: "/images/bg-overview.png" },
|
{ title: "服务业态1", content: "服务业态1", backgroundImage: "/images/bg-overview.png" },
|
||||||
{ title: "服务业态2", content: "服务业态2", image: "/images/bg-overview.png" },
|
{ title: "服务业态2", content: "服务业态2", backgroundImage: "/images/bg-overview.png" },
|
||||||
{ title: "服务业态3", content: "服务业态3", image: "/images/bg-overview.png" },
|
{ title: "服务业态3", content: "服务业态3", backgroundImage: "/images/bg-overview.png" },
|
||||||
{ title: "服务业态4", content: "服务业态3", image: "/images/bg-overview.png" },
|
{ title: "服务业态4", content: "服务业态3", backgroundImage: "/images/bg-overview.png" },
|
||||||
{ title: "服务业态5", content: "服务业态3", image: "/images/bg-overview.png" },
|
{ title: "服务业态5", content: "服务业态3", backgroundImage: "/images/bg-overview.png" },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
section3Data: {
|
section3Data: {
|
||||||
title: "标杆项目",
|
title: "标杆项目",
|
||||||
items: [
|
items: [
|
||||||
{ title: "北京银泰中心", image: "/images/bg-overview.png" },
|
{ title: "北京银泰中心", backgroundImage: "/images/bg-overview.png" },
|
||||||
{ title: "北京银泰吉祥大厦", image: "/images/bg-overview.png" },
|
{ title: "北京银泰吉祥大厦", backgroundImage: "/images/bg-overview.png" },
|
||||||
{ title: "杭州城西银泰城", image: "/images/bg-overview.png" },
|
{ title: "杭州城西银泰城", backgroundImage: "/images/bg-overview.png" },
|
||||||
{ title: "杭州千岛湖银泰城", image: "/images/bg-overview.png" },
|
{ title: "杭州千岛湖银泰城", backgroundImage: "/images/bg-overview.png" },
|
||||||
{ title: "桐庐银泰城", image: "/images/bg-overview.png" },
|
{ title: "桐庐银泰城", backgroundImage: "/images/bg-overview.png" },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
section4Data: {
|
section4Data: {
|
||||||
|
|
@ -748,16 +784,14 @@ const zhCN = {
|
||||||
title: "银泰公益基金会",
|
title: "银泰公益基金会",
|
||||||
content: "由银泰集团创始人兼董事长沈国军先生发起,于2014年初在北京成立。银泰集团希望以此为平台,以公益促进社会进步,用创新公益模式,立足生态环保、乡村振兴、应急救灾、公益教育等方向,用实际行动体现银泰人对社会责任的坚守和担当。",
|
content: "由银泰集团创始人兼董事长沈国军先生发起,于2014年初在北京成立。银泰集团希望以此为平台,以公益促进社会进步,用创新公益模式,立足生态环保、乡村振兴、应急救灾、公益教育等方向,用实际行动体现银泰人对社会责任的坚守和担当。",
|
||||||
backgroundImage: "/images/Foundation-sectionbg-1.png",
|
backgroundImage: "/images/Foundation-sectionbg-1.png",
|
||||||
},
|
|
||||||
section2Data: {
|
|
||||||
tabItems: [
|
tabItems: [
|
||||||
{ tabName: "生态环保", contentTitle: "生态环保", contentSubtitle: "", contentText: "北京银泰中心是银泰置地集团在北京的核心项目,是集高端购物中心、酒店、公寓、超甲级写字楼等业态于一体的综合性商业地产项目。", image: "/images/bg-overview.png" },
|
{ tabName: "生态环保", contentTitle: "生态环保", contentSubtitle: "", contentText: "北京银泰中心是银泰置地集团在北京的核心项目,是集高端购物中心、酒店、公寓、超甲级写字楼等业态于一体的综合性商业地产项目。", sideImage: "/images/bg-overview.png" },
|
||||||
{ tabName: "乡村振兴", contentTitle: "银泰中心", contentSubtitle: "", contentText: "北京银泰中心是银泰置地集团在北京的核心项目,是集高端购物中心、酒店、公寓、超甲级写字楼等业态于一体的综合性商业地产项目。", image: "/images/bg-overview.png" },
|
{ tabName: "乡村振兴", contentTitle: "银泰中心", contentSubtitle: "", contentText: "北京银泰中心是银泰置地集团在北京的核心项目,是集高端购物中心、酒店、公寓、超甲级写字楼等业态于一体的综合性商业地产项目。", sideImage: "/images/bg-overview.png" },
|
||||||
{ tabName: "应急救灾", contentTitle: "银泰中心", contentSubtitle: "", contentText: "北京银泰中心是银泰置地集团在北京的核心项目,是集高端购物中心、酒店、公寓、超甲级写字楼等业态于一体的综合性商业地产项目。", image: "/images/bg-overview.png" },
|
{ tabName: "应急救灾", contentTitle: "银泰中心", contentSubtitle: "", contentText: "北京银泰中心是银泰置地集团在北京的核心项目,是集高端购物中心、酒店、公寓、超甲级写字楼等业态于一体的综合性商业地产项目。", sideImage: "/images/bg-overview.png" },
|
||||||
{ tabName: "公益教育", contentTitle: "银泰中心", contentSubtitle: "", contentText: "北京银泰中心是银泰置地集团在北京的核心项目,是集高端购物中心、酒店、公寓、超甲级写字楼等业态于一体的综合性商业地产项目。", image: "/images/bg-overview.png" },
|
{ tabName: "公益教育", contentTitle: "银泰中心", contentSubtitle: "", contentText: "北京银泰中心是银泰置地集团在北京的核心项目,是集高端购物中心、酒店、公寓、超甲级写字楼等业态于一体的综合性商业地产项目。", sideImage: "/images/bg-overview.png" },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
section3Data: {
|
section2Data: {
|
||||||
title: "公益传播",
|
title: "公益传播",
|
||||||
items: Array(4).fill(null).map((_, i) => ({
|
items: Array(4).fill(null).map((_, i) => ({
|
||||||
title: `公益传播${i + 1}`,
|
title: `公益传播${i + 1}`,
|
||||||
|
|
@ -766,7 +800,7 @@ const zhCN = {
|
||||||
link: "",
|
link: "",
|
||||||
})),
|
})),
|
||||||
},
|
},
|
||||||
section4Data: {
|
section3Data: {
|
||||||
title: "信息公开",
|
title: "信息公开",
|
||||||
tabItems: [
|
tabItems: [
|
||||||
{ tabName: "规章制度", fileItems: Array(15).fill(null).map(() => ({ fileName: "规章制度1.pdf", link: "" })) },
|
{ tabName: "规章制度", fileItems: Array(15).fill(null).map(() => ({ fileName: "规章制度1.pdf", link: "" })) },
|
||||||
|
|
@ -777,7 +811,7 @@ const zhCN = {
|
||||||
],
|
],
|
||||||
backgroundImage: "/images/bg-overview.png",
|
backgroundImage: "/images/bg-overview.png",
|
||||||
},
|
},
|
||||||
section5Data: {
|
section4Data: {
|
||||||
title: "公益伙伴",
|
title: "公益伙伴",
|
||||||
items: Array(6).fill(null).map(() => ({ logo: "/images/bg-overview.png" })),
|
items: Array(6).fill(null).map(() => ({ logo: "/images/bg-overview.png" })),
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,87 @@
|
||||||
|
.scrollContainer {
|
||||||
|
width: 100%;
|
||||||
|
overflow-x: auto;
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content {
|
||||||
|
position: relative;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.svg {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bgPath {
|
||||||
|
stroke: #CACED9;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mainPath {
|
||||||
|
stroke: #CACED9;
|
||||||
|
stroke-linecap: round;
|
||||||
|
stroke-linejoin: round;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dotOuter {
|
||||||
|
fill: #14355c;
|
||||||
|
stroke: #2d4a7c;
|
||||||
|
stroke-width: 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dotInner {
|
||||||
|
fill: rgba(255, 255, 255, 0.9);
|
||||||
|
}
|
||||||
|
|
||||||
|
.labelsOverlay {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.labelBlock {
|
||||||
|
position: absolute;
|
||||||
|
pointer-events: auto;
|
||||||
|
min-width: 160px;
|
||||||
|
max-width: 550px;
|
||||||
|
min-height: 200px;
|
||||||
|
padding: 0 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.labelBlock.top {
|
||||||
|
margin-bottom: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.labelBlock.bottom {
|
||||||
|
margin-top: 4px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: flex-end;
|
||||||
|
}
|
||||||
|
|
||||||
|
.labelYear {
|
||||||
|
font-size: 1.125rem;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #14355c;
|
||||||
|
margin-bottom: 6px;
|
||||||
|
line-height: 1.3;
|
||||||
|
}
|
||||||
|
|
||||||
|
.labelList {
|
||||||
|
margin: 0;
|
||||||
|
font-size: 0.875rem;
|
||||||
|
line-height: 1.6;
|
||||||
|
color: #333;
|
||||||
|
list-style: disc;
|
||||||
|
}
|
||||||
|
|
||||||
|
.labelList li {
|
||||||
|
margin-bottom: 4px;
|
||||||
|
list-style: disc;
|
||||||
|
margin-left: 1.25em;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,215 @@
|
||||||
|
import styles from "./index.module.css";
|
||||||
|
|
||||||
|
const PEAK_TO_PEAK = 600;
|
||||||
|
const PEAK_TO_VALLEY = 125;
|
||||||
|
const AMPLITUDE = PEAK_TO_VALLEY / 2;
|
||||||
|
/** 正弦峰 x:sin(2πx/600)=1 → x=150+600n */
|
||||||
|
const PEAK_X_OFFSET = PEAK_TO_PEAK / 4;
|
||||||
|
/** 正弦谷 x:sin(2πx/600)=-1 → x=450+600n */
|
||||||
|
const VALLEY_X_OFFSET = (3 * PEAK_TO_PEAK) / 4;
|
||||||
|
const LINE_HEIGHT = 200;
|
||||||
|
/** 扩大 viewBox 以容纳上方垂直线,避免 rect 被裁剪 */
|
||||||
|
const VIEWBOX_PADDING = 170;
|
||||||
|
|
||||||
|
export type TimelineItem = {
|
||||||
|
year: string;
|
||||||
|
children: string[];
|
||||||
|
};
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
items: TimelineItem[];
|
||||||
|
height?: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
function generateSinePath(
|
||||||
|
width: number,
|
||||||
|
height: number,
|
||||||
|
amplitude: number
|
||||||
|
): string {
|
||||||
|
const centerY = height / 2;
|
||||||
|
const step = 4;
|
||||||
|
const parts: string[] = [];
|
||||||
|
|
||||||
|
for (let x = 0; x <= width; x += step) {
|
||||||
|
const y = centerY - amplitude * Math.sin((2 * Math.PI * x) / PEAK_TO_PEAK);
|
||||||
|
parts.push(`${x},${y}`);
|
||||||
|
}
|
||||||
|
return `M ${parts.join(" L ")}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 余弦曲线:正弦峰时余弦谷,相位差 π/2,即 cos(θ+π/2) = -sin(θ) */
|
||||||
|
function generateCosinePath(
|
||||||
|
width: number,
|
||||||
|
height: number,
|
||||||
|
amplitude: number
|
||||||
|
): string {
|
||||||
|
const centerY = height / 2;
|
||||||
|
const step = 4;
|
||||||
|
const parts: string[] = [];
|
||||||
|
|
||||||
|
for (let x = 0; x <= width; x += step) {
|
||||||
|
const y =
|
||||||
|
centerY -
|
||||||
|
amplitude * Math.cos((2 * Math.PI * x) / PEAK_TO_PEAK + Math.PI / 2);
|
||||||
|
parts.push(`${x},${y}`);
|
||||||
|
}
|
||||||
|
return `M ${parts.join(" L ")}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function computePeakValleyPoints(
|
||||||
|
items: TimelineItem[],
|
||||||
|
height: number
|
||||||
|
): Array<{
|
||||||
|
x: number;
|
||||||
|
y: number;
|
||||||
|
lineTopY: number;
|
||||||
|
side: "top" | "bottom";
|
||||||
|
item: TimelineItem;
|
||||||
|
}> {
|
||||||
|
if (items.length === 0) return [];
|
||||||
|
|
||||||
|
const centerY = height / 2;
|
||||||
|
|
||||||
|
return items.map((item, i) => {
|
||||||
|
const isPeak = i % 2 === 0;
|
||||||
|
const cycleIndex = Math.floor(i / 2);
|
||||||
|
const x = isPeak
|
||||||
|
? PEAK_X_OFFSET + cycleIndex * PEAK_TO_PEAK
|
||||||
|
: VALLEY_X_OFFSET + cycleIndex * PEAK_TO_PEAK;
|
||||||
|
const y =
|
||||||
|
centerY - AMPLITUDE * Math.sin((2 * Math.PI * x) / PEAK_TO_PEAK);
|
||||||
|
const lineTopY = isPeak ? y - LINE_HEIGHT : y;
|
||||||
|
return {
|
||||||
|
x,
|
||||||
|
y,
|
||||||
|
lineTopY,
|
||||||
|
side: isPeak ? "top" : "bottom",
|
||||||
|
item,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 根据 item 数量计算所需内容宽度 */
|
||||||
|
function computeContentWidth(items: TimelineItem[]): number {
|
||||||
|
if (items.length === 0) return 0;
|
||||||
|
const lastIndex = items.length - 1;
|
||||||
|
const isPeak = lastIndex % 2 === 0;
|
||||||
|
const cycleIndex = Math.floor(lastIndex / 2);
|
||||||
|
const lastX = isPeak
|
||||||
|
? PEAK_X_OFFSET + cycleIndex * PEAK_TO_PEAK
|
||||||
|
: VALLEY_X_OFFSET + cycleIndex * PEAK_TO_PEAK;
|
||||||
|
return lastX + 280;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function SineWaveTimeline({ items, height: propHeight = 400 }: Props) {
|
||||||
|
if (!items?.length) return null;
|
||||||
|
|
||||||
|
const height = propHeight ?? 400;
|
||||||
|
const contentWidth = computeContentWidth(items);
|
||||||
|
const points = computePeakValleyPoints(items, height);
|
||||||
|
const expandedHeight = height + 2 * VIEWBOX_PADDING;
|
||||||
|
const mainPathD = generateSinePath(contentWidth, height, AMPLITUDE);
|
||||||
|
const bgPathD = generateCosinePath(contentWidth, height, AMPLITUDE * 0.9);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={styles.scrollContainer}>
|
||||||
|
<div
|
||||||
|
className={styles.content}
|
||||||
|
style={{ width: contentWidth, height: `${expandedHeight}px` }}
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
className={styles.svg}
|
||||||
|
viewBox={`0 ${-VIEWBOX_PADDING} ${contentWidth} ${expandedHeight}`}
|
||||||
|
preserveAspectRatio="xMidYMid meet"
|
||||||
|
>
|
||||||
|
<defs>
|
||||||
|
<linearGradient
|
||||||
|
id="connectorLineGrad"
|
||||||
|
x1="0"
|
||||||
|
y1="0"
|
||||||
|
x2="0"
|
||||||
|
y2="1"
|
||||||
|
gradientUnits="objectBoundingBox"
|
||||||
|
>
|
||||||
|
<stop offset="0" stopColor="#14355C" />
|
||||||
|
<stop offset="0.9929" stopColor="rgba(20,53,92,0)" />
|
||||||
|
</linearGradient>
|
||||||
|
<linearGradient
|
||||||
|
id="connectorLineGradValley"
|
||||||
|
x1="0"
|
||||||
|
y1="0"
|
||||||
|
x2="0"
|
||||||
|
y2="1"
|
||||||
|
gradientUnits="objectBoundingBox"
|
||||||
|
>
|
||||||
|
<stop offset="0" stopColor="rgba(20,53,92,0)" />
|
||||||
|
<stop offset="0.9929" stopColor="#14355C" />
|
||||||
|
</linearGradient>
|
||||||
|
</defs>
|
||||||
|
{/* 背景余弦 - 正弦峰时余弦谷 */}
|
||||||
|
<path
|
||||||
|
d={bgPathD}
|
||||||
|
className={styles.bgPath}
|
||||||
|
fill="none"
|
||||||
|
strokeWidth="1"
|
||||||
|
/>
|
||||||
|
{/* 主正弦 */}
|
||||||
|
<path
|
||||||
|
d={mainPathD}
|
||||||
|
className={styles.mainPath}
|
||||||
|
fill="none"
|
||||||
|
strokeWidth="2"
|
||||||
|
/>
|
||||||
|
{/* 峰谷圆点与垂直线 */}
|
||||||
|
{points.map((point, i) => (
|
||||||
|
<g key={i}>
|
||||||
|
<rect
|
||||||
|
x={point.x - 1}
|
||||||
|
y={point.lineTopY}
|
||||||
|
width={2}
|
||||||
|
height={LINE_HEIGHT}
|
||||||
|
fill={
|
||||||
|
point.side === "top"
|
||||||
|
? "url(#connectorLineGrad)"
|
||||||
|
: "url(#connectorLineGradValley)"
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<circle
|
||||||
|
cx={point.x}
|
||||||
|
cy={point.y}
|
||||||
|
r="10"
|
||||||
|
className={styles.dotOuter}
|
||||||
|
/>
|
||||||
|
<circle
|
||||||
|
cx={point.x}
|
||||||
|
cy={point.y}
|
||||||
|
r="5"
|
||||||
|
className={styles.dotInner}
|
||||||
|
/>
|
||||||
|
</g>
|
||||||
|
))}
|
||||||
|
</svg>
|
||||||
|
{/* Item 文本块叠加层 */}
|
||||||
|
<div className={styles.labelsOverlay}>
|
||||||
|
{points.map((point, i) => (
|
||||||
|
<div
|
||||||
|
key={i}
|
||||||
|
className={`${styles.labelBlock} ${styles[point.side]}`}
|
||||||
|
style={{
|
||||||
|
left: `${((point.x + 14) / contentWidth) * 100}%`,
|
||||||
|
top: `${((point.lineTopY + VIEWBOX_PADDING) / expandedHeight) * 100}%`,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div className={styles.labelYear}>{point.item.year}</div>
|
||||||
|
<ul className={styles.labelList}>
|
||||||
|
{point.item.children?.map((child, j) => (
|
||||||
|
<li key={j}>{child}</li>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -29,7 +29,7 @@ export default function Banner({
|
||||||
desc,
|
desc,
|
||||||
content,
|
content,
|
||||||
largedesc,
|
largedesc,
|
||||||
showBreadcrumb,
|
showBreadcrumb = true,
|
||||||
titleSize = "large",
|
titleSize = "large",
|
||||||
backgroundImage,
|
backgroundImage,
|
||||||
}: Props) {
|
}: Props) {
|
||||||
|
|
|
||||||
|
|
@ -9,15 +9,18 @@ type Data = {
|
||||||
tabName: string;
|
tabName: string;
|
||||||
contentTitle: string;
|
contentTitle: string;
|
||||||
contentText: string;
|
contentText: string;
|
||||||
image: string;
|
/** 以 mockData 为准 */
|
||||||
|
backgroundImage?: string;
|
||||||
|
image?: string;
|
||||||
}[]
|
}[]
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function BottomTabsSection({ data }: { data: Data }) {
|
export default function BottomTabsSection({ data }: { data: Data }) {
|
||||||
const [activeIndex, setActiveIndex] = useState(0);
|
const [activeIndex, setActiveIndex] = useState(0);
|
||||||
|
const bgImg = data.tabItems[activeIndex]?.backgroundImage ?? data.tabItems[activeIndex]?.image ?? "";
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={styles.bottomTabsSection} style={{ backgroundImage: `url(${data.tabItems[activeIndex].image})` }}>
|
<div className={styles.bottomTabsSection} style={{ backgroundImage: bgImg ? `url(${bgImg})` : undefined }}>
|
||||||
<SectionTitle title={data.title} color="#fff" />
|
<SectionTitle title={data.title} color="#fff" />
|
||||||
<div className={styles.bottomTabsSectionContent}>
|
<div className={styles.bottomTabsSectionContent}>
|
||||||
<div className={styles.bottomTabsSectionContentContent}>
|
<div className={styles.bottomTabsSectionContentContent}>
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,9 @@ type Data = {
|
||||||
text: string;
|
text: string;
|
||||||
path: string;
|
path: string;
|
||||||
}[];
|
}[];
|
||||||
image: string;
|
/** 以 mockData 为准,优先使用 backgroundImage */
|
||||||
|
backgroundImage?: string;
|
||||||
|
image?: string;
|
||||||
}[];
|
}[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -34,7 +36,7 @@ export default function RowAccordion({ data, placement='bottom' }: Props) {
|
||||||
key={index}
|
key={index}
|
||||||
className={styles.rowAccordionBgLayer}
|
className={styles.rowAccordionBgLayer}
|
||||||
style={{
|
style={{
|
||||||
backgroundImage: `url(${item.image}), ${FALLBACK_GRADIENT}`,
|
backgroundImage: `url(${item.backgroundImage ?? item.image ?? ""}), ${FALLBACK_GRADIENT}`,
|
||||||
opacity: activeIndex === index ? 1 : 0,
|
opacity: activeIndex === index ? 1 : 0,
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,9 @@ type Data = {
|
||||||
title: string;
|
title: string;
|
||||||
desc?: string;
|
desc?: string;
|
||||||
content?: string;
|
content?: string;
|
||||||
image: string;
|
/** 以 mockData 为准,优先使用 backgroundImage */
|
||||||
|
backgroundImage?: string;
|
||||||
|
image?: string;
|
||||||
}[];
|
}[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -45,7 +47,7 @@ export default function SwiperCardSection({ data }: { data: Data }) {
|
||||||
{data.cardItems.map((item) => (
|
{data.cardItems.map((item) => (
|
||||||
<SwiperSlide key={item.title}>
|
<SwiperSlide key={item.title}>
|
||||||
<div className={styles.swiperCardItem}>
|
<div className={styles.swiperCardItem}>
|
||||||
<img src={item.image} alt={item.title} />
|
<img src={item.backgroundImage ?? item.image ?? ""} alt={item.title} />
|
||||||
<div className={styles.swiperMask}></div>
|
<div className={styles.swiperMask}></div>
|
||||||
<div className={styles.swiperContent}>
|
<div className={styles.swiperContent}>
|
||||||
<div className={styles.swiperTitle}>
|
<div className={styles.swiperTitle}>
|
||||||
|
|
|
||||||
|
|
@ -1,48 +1,149 @@
|
||||||
import { useState } from 'react';
|
import { useRef, useEffect, useState, useCallback } from 'react';
|
||||||
|
import { LeftOutlined, RightOutlined } from '@ant-design/icons';
|
||||||
import styles from './index.module.css';
|
import styles from './index.module.css';
|
||||||
|
|
||||||
type Data = {
|
type Data = {
|
||||||
tabItems: {
|
tabItems: {
|
||||||
icon?: string;
|
icon?: string;
|
||||||
tabName: string;
|
tabName?: string;
|
||||||
contentTitle: string;
|
contentTitle?: string;
|
||||||
contentSubtitle: string;
|
contentSubtitle?: string;
|
||||||
contentText: string;
|
contentText?: string;
|
||||||
image: string;
|
content?: string;
|
||||||
}[]
|
/** 以 mockData 为准,tabItems 可能使用 sideImage 或 backgroundImage */
|
||||||
|
sideImage?: string;
|
||||||
|
path?: string;
|
||||||
|
}[],
|
||||||
|
backgroundImage?: string;
|
||||||
|
titleDirection?: 'row' | 'column';
|
||||||
|
className?: string;
|
||||||
}
|
}
|
||||||
export default function TopTabs({ data }: { data: Data }) {
|
export default function TopTabs({ data, activeIndex, setActiveIndex, className }: { data: Data, activeIndex: number, setActiveIndex: (index: number) => void, className?: string }) {
|
||||||
const [activeIndex, setActiveIndex] = useState(0);
|
const containerRef = useRef<HTMLDivElement>(null);
|
||||||
|
const scrollRef = useRef<HTMLDivElement>(null);
|
||||||
|
|
||||||
|
const [indicatorStyle, setIndicatorStyle] = useState<{ left: number; width: number }>({ left: 0, width: 0 });
|
||||||
|
const [canScrollLeft, setCanScrollLeft] = useState(false);
|
||||||
|
const [canScrollRight, setCanScrollRight] = useState(false);
|
||||||
|
const [shouldCenter, setShouldCenter] = useState(true);
|
||||||
|
|
||||||
|
const updateIndicatorPosition = useCallback(() => {
|
||||||
|
const scrollEl = scrollRef.current;
|
||||||
|
const activeTab = activeIndex < data.tabItems.length
|
||||||
|
? (scrollEl?.children[activeIndex] as HTMLElement)
|
||||||
|
: null;
|
||||||
|
|
||||||
|
if (!scrollEl || !activeTab) return;
|
||||||
|
|
||||||
|
const container = containerRef.current;
|
||||||
|
if (!container) return;
|
||||||
|
|
||||||
|
const containerRect = container.getBoundingClientRect();
|
||||||
|
const scrollRect = scrollEl.getBoundingClientRect();
|
||||||
|
const tabRect = activeTab.getBoundingClientRect();
|
||||||
|
|
||||||
|
const scrollLeft = scrollEl.scrollLeft;
|
||||||
|
const tabOffsetLeft = activeTab.offsetLeft;
|
||||||
|
|
||||||
|
const left = scrollRect.left - containerRect.left + tabOffsetLeft - scrollLeft;
|
||||||
|
const width = tabRect.width;
|
||||||
|
|
||||||
|
setIndicatorStyle({ left, width });
|
||||||
|
}, [activeIndex, data.tabItems.length]);
|
||||||
|
|
||||||
|
const updateScrollState = useCallback(() => {
|
||||||
|
const scrollEl = scrollRef.current;
|
||||||
|
if (!scrollEl) return;
|
||||||
|
const { scrollLeft, clientWidth, scrollWidth } = scrollEl;
|
||||||
|
setCanScrollLeft(scrollLeft > 0);
|
||||||
|
setCanScrollRight(scrollLeft + clientWidth < scrollWidth - 1);
|
||||||
|
setShouldCenter(scrollWidth <= clientWidth);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const handleScrollLeft = () => {
|
||||||
|
scrollRef.current?.scrollBy({ left: -200, behavior: 'smooth' });
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleScrollRight = () => {
|
||||||
|
scrollRef.current?.scrollBy({ left: 200, behavior: 'smooth' });
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const scrollEl = scrollRef.current;
|
||||||
|
const handleScroll = () => {
|
||||||
|
updateIndicatorPosition();
|
||||||
|
updateScrollState();
|
||||||
|
};
|
||||||
|
|
||||||
|
const rafId = requestAnimationFrame(() => {
|
||||||
|
requestAnimationFrame(() => {
|
||||||
|
updateIndicatorPosition();
|
||||||
|
updateScrollState();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!scrollEl) return () => cancelAnimationFrame(rafId);
|
||||||
|
|
||||||
|
scrollEl.addEventListener('scroll', handleScroll);
|
||||||
|
|
||||||
|
const resizeObserver = new ResizeObserver(() => {
|
||||||
|
updateIndicatorPosition();
|
||||||
|
updateScrollState();
|
||||||
|
});
|
||||||
|
resizeObserver.observe(scrollEl);
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
cancelAnimationFrame(rafId);
|
||||||
|
scrollEl.removeEventListener('scroll', handleScroll);
|
||||||
|
resizeObserver.disconnect();
|
||||||
|
};
|
||||||
|
}, [activeIndex, data.tabItems.length, updateIndicatorPosition, updateScrollState]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div className={className}>
|
||||||
<div className={styles.topTabsTabs}>
|
<div ref={containerRef} className={styles.topTabsTabs}>
|
||||||
{data.tabItems.map((item, index) => (
|
{canScrollLeft && (
|
||||||
<div key={index} className={`${styles.topTabsTabItem} ${activeIndex === index ? styles.active : ''}`} onClick={() => setActiveIndex(index)}>
|
<button
|
||||||
<span>{item.tabName}</span>
|
type="button"
|
||||||
</div>
|
className={`${styles.topTabsNavBtn} ${styles.topTabsNavBtnLeft}`}
|
||||||
))}
|
onClick={handleScrollLeft}
|
||||||
</div>
|
aria-label="向左滚动"
|
||||||
<div className={styles.topTabsContent}>
|
>
|
||||||
<div className={styles.topTabsContentLeft}>
|
<LeftOutlined />
|
||||||
<div className={styles.topTabsContentLeftHead}>
|
</button>
|
||||||
{
|
)}
|
||||||
data.tabItems[activeIndex].icon && (
|
<div
|
||||||
<img src={data.tabItems[activeIndex].icon} alt="" style={{ width: '100px', height: '100px' }} />
|
ref={scrollRef}
|
||||||
)
|
className={`${styles.topTabsTabsScroll} ${shouldCenter ? styles.topTabsTabsScrollCenter : ''}`}
|
||||||
}
|
>
|
||||||
<div className={styles.topTabsContentLeftTitle}>
|
{data.tabItems.map((item, index) => (
|
||||||
<div className={styles.topTabsContentLeftTitleMain}>{data.tabItems[activeIndex].contentTitle}</div>
|
<div
|
||||||
<div className={styles.topTabsContentLeftTitleSub}>{data.tabItems[activeIndex].contentSubtitle}</div>
|
key={index}
|
||||||
|
className={`${styles.topTabsTabItem} ${activeIndex === index ? styles.active : ''}`}
|
||||||
|
onClick={() => setActiveIndex(index)}
|
||||||
|
>
|
||||||
|
<span>{item.tabName}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
))}
|
||||||
<p className={styles.topTabsContentLeftDesc}>
|
|
||||||
{data.tabItems[activeIndex].contentText}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<div className={styles.topTabsContentRight}>
|
|
||||||
<img src={data.tabItems[activeIndex].image} alt="" />
|
|
||||||
</div>
|
</div>
|
||||||
|
{canScrollRight && (
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className={`${styles.topTabsNavBtn} ${styles.topTabsNavBtnRight}`}
|
||||||
|
onClick={handleScrollRight}
|
||||||
|
aria-label="向右滚动"
|
||||||
|
>
|
||||||
|
<RightOutlined />
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
|
<div
|
||||||
|
className={styles.topTabsBottomLine}
|
||||||
|
style={{
|
||||||
|
left: indicatorStyle.left,
|
||||||
|
width: indicatorStyle.width,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -4,30 +4,90 @@
|
||||||
min-height: 100vh;
|
min-height: 100vh;
|
||||||
background-size: cover;
|
background-size: cover;
|
||||||
background-position: center;
|
background-position: center;
|
||||||
background-repeat: no-repeat;
|
background-repeat: repeat;
|
||||||
}
|
}
|
||||||
|
|
||||||
.topTabsTabs {
|
.topTabsTabs {
|
||||||
height: 60px;
|
position: relative;
|
||||||
display: flex;
|
/* height: 60px; */
|
||||||
flex-direction: row;
|
|
||||||
justify-content: center;
|
|
||||||
justify-content: space-between;
|
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
font-size: 24px;
|
font-size: 24px;
|
||||||
line-height: 34px;
|
line-height: 34px;
|
||||||
border-bottom: 1px solid #D5D8DC;
|
border-bottom: 1px solid #D5D8DC;
|
||||||
padding: 0 260px;
|
width: 100%;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.topTabsNavBtn {
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
transform: translateY(-50%);
|
||||||
|
z-index: 1;
|
||||||
|
width: 36px;
|
||||||
|
height: 36px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
border: none;
|
||||||
|
background: #fff;
|
||||||
|
color: #14355C;
|
||||||
|
cursor: pointer;
|
||||||
|
border-radius: 50%;
|
||||||
|
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.15);
|
||||||
|
transition: background 0.2s, color 0.2s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.topTabsNavBtn:hover {
|
||||||
|
background: #f0f2f5;
|
||||||
|
color: #14355C;
|
||||||
|
}
|
||||||
|
|
||||||
|
.topTabsNavBtnLeft {
|
||||||
|
left: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.topTabsNavBtnRight {
|
||||||
|
right: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.topTabsTabsScroll {
|
||||||
|
position: relative;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
flex-wrap: nowrap;
|
||||||
|
gap: 130px;
|
||||||
|
height: 100%;
|
||||||
|
overflow-x: auto;
|
||||||
|
-webkit-overflow-scrolling: touch;
|
||||||
|
/* 隐藏滚动条 */
|
||||||
|
scrollbar-width: none;
|
||||||
|
-ms-overflow-style: none;
|
||||||
|
&::-webkit-scrollbar {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.topTabsTabsScrollCenter {
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.topTabsBottomLine {
|
||||||
|
position: absolute;
|
||||||
|
bottom: 0;
|
||||||
|
height: 2px;
|
||||||
|
background: #000000;
|
||||||
|
transition: left 0.25s ease, width 0.25s ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
.topTabsTabItem {
|
.topTabsTabItem {
|
||||||
height: 60px;
|
height: 90px;
|
||||||
|
line-height: 90px;
|
||||||
|
flex-shrink: 0;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
color: #222222;
|
color: #222222;
|
||||||
}
|
}
|
||||||
|
|
||||||
.topTabsTabItem.active {
|
.topTabsTabItem.active {
|
||||||
border-bottom: 2px solid #000000;
|
|
||||||
color: #14355C;
|
color: #14355C;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -72,6 +132,12 @@
|
||||||
text-transform: none;
|
text-transform: none;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.columnCenter {
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: flex-start;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.topTabsContentLeftDesc {
|
.topTabsContentLeftDesc {
|
||||||
|
|
|
||||||
|
|
@ -5,18 +5,45 @@ import TopTabs from './TopTabs';
|
||||||
type Data = {
|
type Data = {
|
||||||
tabItems: {
|
tabItems: {
|
||||||
icon?: string;
|
icon?: string;
|
||||||
tabName: string;
|
tabName?: string;
|
||||||
contentTitle: string;
|
contentTitle?: string;
|
||||||
contentSubtitle: string;
|
contentSubtitle?: string;
|
||||||
contentText: string;
|
contentText?: string;
|
||||||
image: string;
|
content?: string;
|
||||||
|
/** 以 mockData 为准 */
|
||||||
|
sideImage?: string;
|
||||||
|
path?: string;
|
||||||
}[]
|
}[]
|
||||||
|
backgroundImage?: string;
|
||||||
|
titleDirection?: 'row' | 'column';
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function TopTabsSection({ data }: { data: Data }) {
|
export default function TopTabsSection({ data, className }: { data: Data, className?: string }) {
|
||||||
|
const [activeIndex, setActiveIndex] = useState(0);
|
||||||
return (
|
return (
|
||||||
<section className={styles.topTabsSection} style={{ backgroundImage: `url(/images/TopTabsSection-background.png)` }}>
|
<section className={`${styles.topTabsSection} ${className}`} style={{ backgroundImage: `url(${data.backgroundImage})` }}>
|
||||||
<TopTabs data={data} />
|
<TopTabs data={data} activeIndex={activeIndex} setActiveIndex={setActiveIndex} />
|
||||||
|
<div className={styles.topTabsContent}>
|
||||||
|
<div className={styles.topTabsContentLeft}>
|
||||||
|
<div className={styles.topTabsContentLeftHead}>
|
||||||
|
{
|
||||||
|
data.tabItems[activeIndex].icon && (
|
||||||
|
<img src={data.tabItems[activeIndex].icon} alt="" style={{ width: '100px', height: '100px' }} />
|
||||||
|
)
|
||||||
|
}
|
||||||
|
<div className={`${styles.topTabsContentLeftTitle} ${data.titleDirection === 'column' ? styles.columnCenter : ''}`}>
|
||||||
|
<div className={styles.topTabsContentLeftTitleMain}>{data.tabItems[activeIndex].contentTitle}</div>
|
||||||
|
<div className={styles.topTabsContentLeftTitleSub}>{data.tabItems[activeIndex].contentSubtitle}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<p className={styles.topTabsContentLeftDesc}>
|
||||||
|
{data.tabItems[activeIndex].contentText ?? data.tabItems[activeIndex].content}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div className={styles.topTabsContentRight}>
|
||||||
|
<img src={data.tabItems[activeIndex].sideImage} alt="side-image" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</section>
|
</section>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
@ -106,18 +106,18 @@ export default function Header() {
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{showDropPanel && activePanelItem.length > 0 && <DropPanel items={activePanelItem} left={hoverElLeft} />}
|
{showDropPanel && activePanelItem.length > 0 && <DropPanel items={activePanelItem} left={hoverElLeft} onLinkClick={() => setShowDropPanel(false)} />}
|
||||||
</header>
|
</header>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
function DropPanel({ items, left }: { items: NavChild[]; left: number }) {
|
function DropPanel({ items, left, onLinkClick }: { items: NavChild[]; left: number, onLinkClick: () => void }) {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div id="drop-panel" className={styles.dropPanel} style={{ paddingLeft: left, }}>
|
<div id="drop-panel" className={styles.dropPanel} style={{ paddingLeft: left, }}>
|
||||||
<div className={styles.dropPanelContent}>
|
<div className={styles.dropPanelContent}>
|
||||||
{items.map((item) => (
|
{items.map((item) => (
|
||||||
<div key={item.path} className={styles.dropPanelItem}>
|
<div key={item.path} className={styles.dropPanelItem}>
|
||||||
<Link to={item.path} className={styles.dropPanelLink}>
|
<Link to={item.path} className={styles.dropPanelLink} onClick={onLinkClick}>
|
||||||
{item.label}
|
{item.label}
|
||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -171,6 +171,24 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.section4Section {
|
||||||
|
padding-top: 100px;
|
||||||
|
|
||||||
|
.section4Title {
|
||||||
|
font-weight: 700;
|
||||||
|
font-size: 40px;
|
||||||
|
color: #222222;
|
||||||
|
line-height: 50px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
.timelineWrapper {
|
||||||
|
width: 100%;
|
||||||
|
overflow: auto;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@media (max-width: 768px) {
|
@media (max-width: 768px) {
|
||||||
.section {
|
.section {
|
||||||
padding: 2rem 1rem;
|
padding: 2rem 1rem;
|
||||||
|
|
@ -196,4 +214,7 @@
|
||||||
padding-top: 1rem;
|
padding-top: 1rem;
|
||||||
padding-right: 0;
|
padding-right: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.timelineWrapper {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -3,6 +3,7 @@ import styles from "./Founder.module.css";
|
||||||
import ParagraphSection from "@/components/layout/ParagraphSection";
|
import ParagraphSection from "@/components/layout/ParagraphSection";
|
||||||
import { useStore } from "@/store";
|
import { useStore } from "@/store";
|
||||||
import Section from "@/components/layout/Section";
|
import Section from "@/components/layout/Section";
|
||||||
|
import SineWaveTimeline from "@/components/SineWaveTimeline";
|
||||||
|
|
||||||
export default function AboutFounder() {
|
export default function AboutFounder() {
|
||||||
const appConfig = useStore((s) => s.appConfig);
|
const appConfig = useStore((s) => s.appConfig);
|
||||||
|
|
@ -31,7 +32,7 @@ export default function AboutFounder() {
|
||||||
<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.backgroundImage} alt={item.title} />
|
||||||
<div className={styles.imageMask} />
|
<div className={styles.imageMask} />
|
||||||
<div className={styles.imageOverlay}>
|
<div className={styles.imageOverlay}>
|
||||||
<div className={styles.imageOverlayTitle}>
|
<div className={styles.imageOverlayTitle}>
|
||||||
|
|
@ -68,24 +69,29 @@ export default function AboutFounder() {
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{/* 社会职务 */}
|
{/* 社会职务 */}
|
||||||
<Section title={section3Data?.title ?? ""} titleColor="#fff" background={section3Data?.backgroundImage ?? ""}>
|
{section3Data && (
|
||||||
<div className={styles.section3Content}>
|
<Section title={section3Data?.title} titleColor="#fff" background={section3Data?.backgroundImage}>
|
||||||
{Array.from({
|
<div className={styles.section3Content}>
|
||||||
length: Math.max(0, ...(section3Data?.columns?.map((c) => c.length) ?? [0])),
|
{Array.from({
|
||||||
}).flatMap((_, rowIndex) =>
|
length: Math.max(0, ...(section3Data?.columns?.map((c) => c.length) ?? [0])),
|
||||||
(section3Data?.columns ?? []).map((colItems, colIndex) => (
|
}).flatMap((_, rowIndex) =>
|
||||||
<div key={`${rowIndex}-${colIndex}`} className={styles.section3Item}>
|
(section3Data?.columns ?? []).map((colItems, colIndex) => (
|
||||||
{colItems[rowIndex] ? <li>{colItems[rowIndex].title}</li> : null}
|
<div key={`${rowIndex}-${colIndex}`} className={styles.section3Item}>
|
||||||
</div>
|
{colItems[rowIndex] ? <li>{colItems[rowIndex].title}</li> : null}
|
||||||
))
|
</div>
|
||||||
)}
|
))
|
||||||
</div>
|
)}
|
||||||
</Section>
|
</div>
|
||||||
|
</Section>
|
||||||
|
)}
|
||||||
|
|
||||||
{/* 荣誉奖项 */}
|
{section4Data && (
|
||||||
<Section title={section4Data?.title} background={section4Data?.backgroundImage ?? ""}>
|
<section className={styles.section4Section} style={{ backgroundImage: section4Data?.backgroundImage ? `url(${section4Data?.backgroundImage})` : undefined }}>
|
||||||
|
<div className={styles.section4Title}>{section4Data?.title}</div>
|
||||||
</Section>
|
<div className={styles.timelineWrapper}>
|
||||||
|
<SineWaveTimeline items={section4Data?.items ?? []} />
|
||||||
|
</div>
|
||||||
|
</section>)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -22,10 +22,10 @@ export default function BaseGroup() {
|
||||||
const swiperCardData = section2Data
|
const swiperCardData = section2Data
|
||||||
? {
|
? {
|
||||||
title: section2Data.title,
|
title: section2Data.title,
|
||||||
cardItems: section2Data.cardItems?.map((c: { title: string; content: string; image: string }) => ({
|
cardItems: section2Data.cardItems?.map((c: { title: string; content: string; backgroundImage?: string }) => ({
|
||||||
title: c.title,
|
title: c.title,
|
||||||
content: c.content,
|
content: c.content,
|
||||||
image: c.image,
|
backgroundImage: c.backgroundImage,
|
||||||
})) ?? [],
|
})) ?? [],
|
||||||
}
|
}
|
||||||
: null;
|
: null;
|
||||||
|
|
|
||||||
|
|
@ -35,8 +35,8 @@
|
||||||
background-size: cover;
|
background-size: cover;
|
||||||
background-position: center;
|
background-position: center;
|
||||||
background-repeat: no-repeat;
|
background-repeat: no-repeat;
|
||||||
|
padding: 100px 0 !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.twoColSection.reverse {
|
.twoColSection.reverse {
|
||||||
flex-direction: row-reverse;
|
flex-direction: row-reverse;
|
||||||
}
|
}
|
||||||
|
|
@ -45,11 +45,7 @@
|
||||||
height: 4.125rem;
|
height: 4.125rem;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
justify-content: center;
|
|
||||||
gap: 8.125rem;
|
|
||||||
border-bottom: 1px solid #D5D8DC;
|
|
||||||
margin: 0 16.25rem;
|
margin: 0 16.25rem;
|
||||||
margin-bottom: 3.75rem;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.twoColSectionTab {
|
.twoColSectionTab {
|
||||||
|
|
@ -66,6 +62,7 @@
|
||||||
.twoColSectionContent {
|
.twoColSectionContent {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: 1fr 1fr;
|
grid-template-columns: 1fr 1fr;
|
||||||
|
margin-top: 60px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.twoColImage {
|
.twoColImage {
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,11 @@
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
|
import { Link } from "react-router-dom";
|
||||||
|
import { useStore } from "@/store";
|
||||||
import styles from "./CommercialGroup.module.css";
|
import styles from "./CommercialGroup.module.css";
|
||||||
import Banner from "@/components/Banner";
|
import Banner from "@/components/Banner";
|
||||||
import { Link } from "react-router-dom";
|
|
||||||
import ParagraphSection from "@/components/layout/ParagraphSection";
|
import ParagraphSection from "@/components/layout/ParagraphSection";
|
||||||
import { useStore } from "@/store";
|
import Section from "@/components/layout/Section";
|
||||||
|
import TopTabs from "@/components/layout/TopTabsSection/TopTabs";
|
||||||
|
|
||||||
const FALLBACK_GRADIENT = "linear-gradient(135deg, #1a2a4a 0%, #2d4a7c 100%)";
|
const FALLBACK_GRADIENT = "linear-gradient(135deg, #1a2a4a 0%, #2d4a7c 100%)";
|
||||||
|
|
||||||
|
|
@ -23,8 +25,8 @@ export default function BusinessCommercialGroup() {
|
||||||
|
|
||||||
const banner = data.banner;
|
const banner = data.banner;
|
||||||
const section1Data = data.section1Data;
|
const section1Data = data.section1Data;
|
||||||
const tabItems = data.section2Data?.tabItems ?? [];
|
const section2Data = data.section2Data;
|
||||||
const featuresTabItems = data.section3Data?.tabItems ?? [];
|
const section3Data = data.section3Data;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
|
|
@ -38,28 +40,18 @@ export default function BusinessCommercialGroup() {
|
||||||
|
|
||||||
{section1Data && <ParagraphSection data={section1Data} />}
|
{section1Data && <ParagraphSection data={section1Data} />}
|
||||||
|
|
||||||
<section
|
<Section
|
||||||
|
background={section2Data.backgroundImage }
|
||||||
className={styles.twoColSection}
|
className={styles.twoColSection}
|
||||||
style={{ backgroundImage: "url(/images/bg-in.png)" }}
|
|
||||||
>
|
>
|
||||||
<div className={styles.twoColSectionTabs}>
|
<TopTabs className={styles.twoColSectionTabs} data={section2Data} activeIndex={activeTabIndex} setActiveIndex={setActiveTabIndex} />
|
||||||
{tabItems.map((item: { label: string }, i: number) => (
|
|
||||||
<div
|
|
||||||
key={i}
|
|
||||||
className={`${styles.twoColSectionTab} ${activeTabIndex === i ? styles.active : ""}`}
|
|
||||||
onClick={() => setActiveTabIndex(i)}
|
|
||||||
>
|
|
||||||
<span>{item.label}</span>
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
<div className={styles.twoColSectionContent}>
|
<div className={styles.twoColSectionContent}>
|
||||||
<div className={styles.twoColImage}>
|
<div className={styles.twoColImage}>
|
||||||
{in77ImgError ? (
|
{in77ImgError ? (
|
||||||
<PlaceholderImage />
|
<PlaceholderImage />
|
||||||
) : (
|
) : (
|
||||||
<img
|
<img
|
||||||
src={tabItems[activeTabIndex]?.image}
|
src={section2Data.tabItems[activeTabIndex]?.sideImage as string}
|
||||||
alt=""
|
alt=""
|
||||||
onError={() => setIn77ImgError(true)}
|
onError={() => setIn77ImgError(true)}
|
||||||
style={{ width: "100%", height: "800px" }}
|
style={{ width: "100%", height: "800px" }}
|
||||||
|
|
@ -67,16 +59,16 @@ export default function BusinessCommercialGroup() {
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div className={styles.twoColText}>
|
<div className={styles.twoColText}>
|
||||||
<p className={styles.twoColDesc}>{tabItems[activeTabIndex]?.content}</p>
|
<p className={styles.twoColDesc}>{section2Data.tabItems[activeTabIndex]?.content}</p>
|
||||||
<Link
|
<Link
|
||||||
to={tabItems[activeTabIndex]?.path ?? "#"}
|
to={section2Data.tabItems[activeTabIndex]?.path ?? "#"}
|
||||||
className={styles.btnPrimary}
|
className={styles.btnPrimary}
|
||||||
>
|
>
|
||||||
查看详情
|
查看详情
|
||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</Section>
|
||||||
|
|
||||||
<section
|
<section
|
||||||
className={styles.featuresHero}
|
className={styles.featuresHero}
|
||||||
|
|
@ -85,16 +77,16 @@ export default function BusinessCommercialGroup() {
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div className={styles.featuresHeroContent}>
|
<div className={styles.featuresHeroContent}>
|
||||||
<div>{featuresTabItems[activeFeaturesTabIndex]?.content}</div>
|
<div>{section3Data.tabItems[activeFeaturesTabIndex]?.content}</div>
|
||||||
</div>
|
</div>
|
||||||
<div className={styles.featuresHeroTabs}>
|
<div className={styles.featuresHeroTabs}>
|
||||||
{featuresTabItems.map((item: { label: string }, i: number) => (
|
{section3Data.tabItems.map((item: { tabName: string }, i: number) => (
|
||||||
<div
|
<div
|
||||||
key={i}
|
key={i}
|
||||||
className={`${styles.featuresHeroTab} ${activeFeaturesTabIndex === i ? styles.active : ""}`}
|
className={`${styles.featuresHeroTab} ${activeFeaturesTabIndex === i ? styles.active : ""}`}
|
||||||
onClick={() => setActiveFeaturesTabIndex(i)}
|
onClick={() => setActiveFeaturesTabIndex(i)}
|
||||||
>
|
>
|
||||||
<span>{item.label}</span>
|
<span>{item.tabName}</span>
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,15 @@
|
||||||
import Banner, { type BannerConfig } from "@/components/Banner";
|
import Banner, { type BannerConfig } from "@/components/Banner";
|
||||||
import { useStore } from "@/store";
|
import { useStore } from "@/store";
|
||||||
import styles from "./CommercialGroupDetail.module.css";
|
import styles from "./CommercialGroupDetail.module.css";
|
||||||
|
import ParagraphSection from "@/components/layout/ParagraphSection";
|
||||||
|
import { useParams } from "react-router-dom";
|
||||||
|
import TopTabsSection from "@/components/layout/TopTabsSection";
|
||||||
export default function BusinessCommercialGroupDetail() {
|
export default function BusinessCommercialGroupDetail() {
|
||||||
const appConfig = useStore((s) => s.appConfig);
|
const appConfig = useStore((s) => s.appConfig);
|
||||||
const data = appConfig?.business?.commercialGroupDetail;
|
const allData = appConfig?.business?.commercialGroupDetail;
|
||||||
|
const params = useParams()
|
||||||
|
const detailType = params.detailType as string
|
||||||
|
const data = allData?.items.find((item: any) => item.pathname === detailType)
|
||||||
const banner = data?.banner;
|
const banner = data?.banner;
|
||||||
|
|
||||||
if (!data) return null;
|
if (!data) return null;
|
||||||
|
|
@ -19,11 +24,9 @@ export default function BusinessCommercialGroupDetail() {
|
||||||
backgroundImage={banner?.backgroundImage ?? "/images/bg-commercial-group.png"}
|
backgroundImage={banner?.backgroundImage ?? "/images/bg-commercial-group.png"}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<section className={styles.twoColSection}>
|
<ParagraphSection data={data.section1Data}></ParagraphSection>
|
||||||
<p>
|
|
||||||
in77 作为高端商业品牌,汲取了银泰集团优质的商业资源及运营管理能力,旗下项目均位于核心商业圈或国家示范步行街,成为时尚零售业和新消费领域的标杆。
|
<TopTabsSection data={data.section2Data as any} />
|
||||||
</p>
|
|
||||||
</section>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -25,10 +25,10 @@ export default function RealtyGroup() {
|
||||||
const rowAccordionData = section3Data
|
const rowAccordionData = section3Data
|
||||||
? {
|
? {
|
||||||
title: section3Data.title,
|
title: section3Data.title,
|
||||||
items: section3Data.items?.map((i: { title: string; content?: string; image: string }) => ({
|
items: section3Data.items?.map((i: { title: string; content?: string; backgroundImage?: string }) => ({
|
||||||
title: i.title,
|
title: i.title,
|
||||||
content: i.content,
|
content: i.content,
|
||||||
image: i.image,
|
backgroundImage: i.backgroundImage,
|
||||||
})) ?? [],
|
})) ?? [],
|
||||||
}
|
}
|
||||||
: null;
|
: null;
|
||||||
|
|
|
||||||
|
|
@ -22,10 +22,10 @@ export default function RuijingGroup() {
|
||||||
const swiperCardData = section2Data
|
const swiperCardData = section2Data
|
||||||
? {
|
? {
|
||||||
title: section2Data.title,
|
title: section2Data.title,
|
||||||
cardItems: section2Data.cardItems?.map((c: { title: string; content: string; image: string }) => ({
|
cardItems: section2Data.cardItems?.map((c: { title: string; content: string; backgroundImage?: string }) => ({
|
||||||
title: c.title,
|
title: c.title,
|
||||||
content: c.content,
|
content: c.content,
|
||||||
image: c.image,
|
backgroundImage: c.backgroundImage,
|
||||||
})) ?? [],
|
})) ?? [],
|
||||||
}
|
}
|
||||||
: null;
|
: null;
|
||||||
|
|
|
||||||
|
|
@ -20,10 +20,10 @@ export default function PropertyService() {
|
||||||
const swiperCardData = section2Data
|
const swiperCardData = section2Data
|
||||||
? {
|
? {
|
||||||
title: section2Data.title,
|
title: section2Data.title,
|
||||||
cardItems: section2Data.cardItems?.map((c: { title: string; content: string; image: string }) => ({
|
cardItems: section2Data.cardItems?.map((c: { title: string; content: string; backgroundImage?: string }) => ({
|
||||||
title: c.title,
|
title: c.title,
|
||||||
content: c.content,
|
content: c.content,
|
||||||
image: c.image,
|
backgroundImage: c.backgroundImage,
|
||||||
})) ?? [],
|
})) ?? [],
|
||||||
}
|
}
|
||||||
: null;
|
: null;
|
||||||
|
|
@ -31,9 +31,9 @@ export default function PropertyService() {
|
||||||
const rowAccordionData = section3Data
|
const rowAccordionData = section3Data
|
||||||
? {
|
? {
|
||||||
title: section3Data.title,
|
title: section3Data.title,
|
||||||
items: section3Data.items?.map((i: { title: string; image: string }) => ({
|
items: section3Data.items?.map((i: { title: string; backgroundImage?: string }) => ({
|
||||||
title: i.title,
|
title: i.title,
|
||||||
image: i.image,
|
backgroundImage: i.backgroundImage,
|
||||||
})) ?? [],
|
})) ?? [],
|
||||||
}
|
}
|
||||||
: null;
|
: null;
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,7 @@
|
||||||
|
.topTabsSection {
|
||||||
|
padding: 0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
/* 公益传播 */
|
/* 公益传播 */
|
||||||
.publicWelfareDataItems {
|
.publicWelfareDataItems {
|
||||||
/* 2列 */
|
/* 2列 */
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,12 @@
|
||||||
import Banner, { type BannerConfig } 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 Section from "@/components/layout/Section";
|
import Section from "@/components/layout/Section";
|
||||||
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 { useStore } from "@/store";
|
||||||
import styles from "./Foundation.module.css";
|
import styles from "./Foundation.module.css";
|
||||||
|
import TopTabsSection from "@/components/layout/TopTabsSection";
|
||||||
|
|
||||||
export default function Foundation() {
|
export default function Foundation() {
|
||||||
const appConfig = useStore((s) => s.appConfig);
|
const appConfig = useStore((s) => s.appConfig);
|
||||||
|
|
@ -20,9 +20,6 @@ export default function Foundation() {
|
||||||
const section2Data = data.section2Data;
|
const section2Data = data.section2Data;
|
||||||
const section3Data = data.section3Data;
|
const section3Data = data.section3Data;
|
||||||
const section4Data = data.section4Data;
|
const section4Data = data.section4Data;
|
||||||
const section5Data = data.section5Data;
|
|
||||||
|
|
||||||
const topTabsData = section2Data ? { tabItems: section2Data.tabItems ?? [] } : null;
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
|
|
@ -37,19 +34,17 @@ export default function Foundation() {
|
||||||
{section1Data && (
|
{section1Data && (
|
||||||
<ParagraphSection data={section1Data}>
|
<ParagraphSection data={section1Data}>
|
||||||
<div style={{ marginTop: "100px" }} />
|
<div style={{ marginTop: "100px" }} />
|
||||||
{topTabsData && <TopTabs data={topTabsData} />}
|
{section1Data.tabItems && <TopTabsSection data={{ tabItems: section1Data.tabItems }} className={styles.topTabsSection} />}
|
||||||
<div style={{ marginBottom: "50px" }} />
|
|
||||||
</ParagraphSection>
|
</ParagraphSection>
|
||||||
)}
|
)}
|
||||||
|
{section2Data && (
|
||||||
{section3Data && (
|
|
||||||
<Section
|
<Section
|
||||||
title={section3Data.title}
|
title={section2Data.title}
|
||||||
background=""
|
background=""
|
||||||
maskBackground="rgba(255,255,255,0.3)"
|
maskBackground="rgba(255,255,255,0.3)"
|
||||||
>
|
>
|
||||||
<div className={styles.publicWelfareDataItems}>
|
<div className={styles.publicWelfareDataItems}>
|
||||||
{section3Data.items?.map((item, index) => (
|
{section2Data.items?.map((item, index) => (
|
||||||
<div
|
<div
|
||||||
key={index}
|
key={index}
|
||||||
className={styles.publicWelfareDataItem}
|
className={styles.publicWelfareDataItem}
|
||||||
|
|
@ -67,12 +62,12 @@ export default function Foundation() {
|
||||||
<Section
|
<Section
|
||||||
title={section4Data.title}
|
title={section4Data.title}
|
||||||
titleColor="#fff"
|
titleColor="#fff"
|
||||||
background={section4Data.backgroundImage ?? "/images/bg-overview.png"}
|
background={section3Data.backgroundImage ?? "/images/bg-overview.png"}
|
||||||
maskBackground="rgba(255,255,255,0.1)"
|
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) => (
|
{section3Data.tabItems?.[activeIndex]?.fileItems?.map((item, index) => (
|
||||||
<div key={index} className={styles.informationPublicDataItem}>
|
<div key={index} className={styles.informationPublicDataItem}>
|
||||||
<li>
|
<li>
|
||||||
<span>{item.fileName}</span>
|
<span>{item.fileName}</span>
|
||||||
|
|
@ -81,7 +76,7 @@ export default function Foundation() {
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
<BottomTabs
|
<BottomTabs
|
||||||
tabItems={section4Data.tabItems ?? []}
|
tabItems={section3Data.tabItems ?? []}
|
||||||
activeIndex={activeIndex}
|
activeIndex={activeIndex}
|
||||||
setActiveIndex={setActiveIndex}
|
setActiveIndex={setActiveIndex}
|
||||||
/>
|
/>
|
||||||
|
|
@ -89,10 +84,10 @@ export default function Foundation() {
|
||||||
</Section>
|
</Section>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{section5Data && (
|
{section4Data && (
|
||||||
<Section title={section5Data.title} background="" maskBackground="#F7FBFF">
|
<Section title={section4Data.title} background="" maskBackground="#F7FBFF">
|
||||||
<div className={styles.partnerItems}>
|
<div className={styles.partnerItems}>
|
||||||
{section5Data.items?.map((item, index) => (
|
{section4Data.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>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue