diff --git a/public/images/bg-in.png b/public/images/bg-in.png new file mode 100644 index 0000000..f6d7f81 Binary files /dev/null and b/public/images/bg-in.png differ diff --git a/public/ttf/D-DIN-PRO-400-Regular.otf b/public/ttf/D-DIN-PRO-400-Regular.otf new file mode 100644 index 0000000..74dd61a Binary files /dev/null and b/public/ttf/D-DIN-PRO-400-Regular.otf differ diff --git a/public/ttf/SourceHanSansCN-Normal.otf b/public/ttf/SourceHanSansCN-Normal.otf new file mode 100644 index 0000000..091f56d Binary files /dev/null and b/public/ttf/SourceHanSansCN-Normal.otf differ diff --git a/src/App.css b/src/App.css index e164f52..6df83cf 100644 --- a/src/App.css +++ b/src/App.css @@ -66,13 +66,30 @@ ul, li { display: flex; } +/* 数字字体 */ +.font-num { + font-family: D-DIN-PRO, D-DIN-PRO; +} + .header-row { width: 100%; margin: 0 auto; - padding: 0 60px; + padding: 0 3.75rem; box-sizing: border-box; } +@media (max-width: 1024px) { + .header-row { + padding: 0 1.5rem; + } +} + +@media (max-width: 768px) { + .header-row { + padding: 0 1rem; + } +} + body { overflow-x: hidden; background: #f0f2f4; @@ -92,30 +109,17 @@ body { .container { flex: 1; - overflow: auto; + /* overflow: auto; */ } .layout-footer { flex-shrink: 0; } - - -/* html { - font-size: 16px; -} -@media screen and (max-width: 1920px) { - html { - font-size: 16px; - } -} -@media screen and (max-width: 1440px) { - html { - font-size: 14px; - } -} -@media screen and (max-width: 1024px) { - html { - font-size: 12px; - } -} */ \ No newline at end of file +.normal-p p { + font-weight: 400; + font-size: 18px; + color: #222222; + line-height: 34px; + margin-bottom: 20px; +} \ No newline at end of file diff --git a/src/Routes.tsx b/src/Routes.tsx index 57714fc..f4fb037 100644 --- a/src/Routes.tsx +++ b/src/Routes.tsx @@ -7,6 +7,7 @@ import AboutHistory from "@/pages/About/History"; import AboutFounder from "@/pages/About/Founder"; import Business from "@/pages/Business/index"; import BusinessCommercialGroup from "@/pages/Business/CommercialGroup"; +import BusinessCommercialGroupDetail from "@/pages/Business/CommercialGroupDetail"; import BusinessBaseGroup from "@/pages/Business/BaseGroup"; import BusinessRealtyGroup from "@/pages/Business/RealtyGroup"; import BusinessInvestGroup from "@/pages/Business/InvestGroup"; @@ -20,6 +21,7 @@ import NewsMedia from "@/pages/News/Media"; import Join from "@/pages/Join/index"; import JoinCulture from "@/pages/Join/Culture"; import JoinCampus from "@/pages/Join/Campus"; +import PropertyService from "@/pages/PropertyService/index"; const routes: RouteObject[] = [ { @@ -34,6 +36,7 @@ const routes: RouteObject[] = [ // 集团业务 { path: "business", element: }, { path: "business/commercial-group", element: }, + { path: "business/commercial-group/:detailType", element: }, { path: "business/base-group", element: }, { path: "business/realty-group", element: }, { path: "business/invest-group", element: }, @@ -50,6 +53,9 @@ const routes: RouteObject[] = [ { path: "join", element: }, { path: "join/culture", element: }, { path: "join/campus", element: }, + + // 物业服务 + { path: "property-service", element: }, ], }, { diff --git a/src/components/Banner.module.css b/src/components/Banner.module.css index 3fe7328..b7545a1 100644 --- a/src/components/Banner.module.css +++ b/src/components/Banner.module.css @@ -4,7 +4,7 @@ min-height: 100vh; background-size: cover; background-position: center; - padding-bottom: 50px; + padding-bottom: 3.125rem; display: flex; flex-direction: column; justify-content: flex-end; @@ -24,8 +24,7 @@ .heroContent { position: relative; z-index: 1; - padding: 0 24px; - /* padding-top: 400px; */ + padding: 0 1.5rem; padding-left: 13.5%; display: flex; flex-direction: column; @@ -33,31 +32,33 @@ } .heroTitle { - font-size: 60px; + font-size: 3.75rem; font-weight: 700; color: #fff; - /* margin: 0 0 50px; */ letter-spacing: 0.05em; } +.heroTitleMedium { + font-size: 2.5rem; +} + .heroSubtitle { - font-size: 40px; + font-size: 2.5rem; font-weight: 700; color: #fff; - /* margin: 0 0 16px; */ letter-spacing: 0.05em; } .heroDesc { - max-width: 900px; - font-size: 20px; + max-width: 56.25rem; + font-size: 1.25rem; color: rgba(255, 255, 255, 0.95); margin: 0; letter-spacing: 0.02em; } .heroLargeDesc { - font-size: 34px; + font-size: 2.125rem; color: rgba(255, 255, 255, 0.95); margin: 0; letter-spacing: 0.02em; @@ -66,10 +67,10 @@ .breadcrumb { display: flex; flex-direction: row; - gap: 5px; + gap: 0.3125rem; color: #fff; text-decoration: none; - font-size: 16px; - margin-top: 100px; + font-size: 1rem; + margin-top: 6.25rem; } diff --git a/src/components/YearPicker/YearPicker.module.css b/src/components/YearPicker/YearPicker.module.css index 1582b45..6d9036f 100644 --- a/src/components/YearPicker/YearPicker.module.css +++ b/src/components/YearPicker/YearPicker.module.css @@ -1,19 +1,19 @@ .wrapper { position: relative; display: inline-block; - min-width: 140px; + min-width: 8.75rem; } .trigger { display: flex; align-items: center; justify-content: space-between; - gap: 8px; - padding: 8px 11px; + gap: 0.5rem; + padding: 0.5rem 0.6875rem; background: #14355C; color: #fff; border: 1px solid rgba(255, 255, 255, 0.25); - border-radius: 6px; + border-radius: 0.375rem; cursor: pointer; user-select: none; } @@ -55,13 +55,13 @@ display: flex; align-items: center; justify-content: center; - width: 16px; - height: 16px; + width: 1rem; + height: 1rem; color: rgba(255, 255, 255, 0.85); - font-size: 14px; + font-size: 0.875rem; line-height: 1; cursor: pointer; - border-radius: 2px; + border-radius: 0.125rem; } .clear:hover { @@ -80,38 +80,38 @@ .panel { position: absolute; - top: calc(100% + 4px); + top: calc(100% + 0.25rem); left: 0; z-index: 1050; - min-width: 220px; - padding: 12px; + min-width: 13.75rem; + padding: 0.75rem; background: #14355C; border: 1px solid rgba(255, 255, 255, 0.25); - border-radius: 8px; - box-shadow: 0 6px 16px rgba(0, 0, 0, 0.3); + border-radius: 0.5rem; + box-shadow: 0 0.375rem 1rem rgba(0, 0, 0, 0.3); } .header { display: flex; align-items: center; justify-content: space-between; - margin-bottom: 12px; - padding: 0 4px; + margin-bottom: 0.75rem; + padding: 0 0.25rem; } .navBtn { display: flex; align-items: center; justify-content: center; - width: 28px; - height: 28px; + width: 1.75rem; + height: 1.75rem; padding: 0; background: transparent; color: #fff; border: none; - border-radius: 4px; + border-radius: 0.25rem; cursor: pointer; - font-size: 12px; + font-size: 0.75rem; } .navBtn:hover:not(:disabled) { @@ -125,26 +125,26 @@ .decadeLabel { color: #fff; - font-size: 14px; + font-size: 0.875rem; font-weight: 500; } .yearGrid { display: grid; grid-template-columns: repeat(3, 1fr); - gap: 4px; + gap: 0.25rem; } .yearCell { - min-width: 56px; - height: 32px; + min-width: 3.5rem; + height: 2rem; padding: 0; background: transparent; color: #fff; border: none; - border-radius: 4px; + border-radius: 0.25rem; cursor: pointer; - font-size: 14px; + font-size: 0.875rem; transition: background 0.2s; } diff --git a/src/components/banner.tsx b/src/components/banner.tsx index c4d8034..e57b862 100644 --- a/src/components/banner.tsx +++ b/src/components/banner.tsx @@ -2,15 +2,19 @@ import { Link } from "react-router-dom"; import styles from "./Banner.module.css"; const FALLBACK_GRADIENT = "linear-gradient(135deg, #1a2a4a 0%, #2d4a7c 100%)"; +type BreadcrumbItem = { label: string; to: string }; + type Props = { title: string; subtitle?: string; desc?: string; largedesc?: string; showBreadcrumb?: boolean; + breadcrumbItems?: BreadcrumbItem[]; + titleSize?: "large" | "medium"; backgroundImage: string; } -export default function Banner({ title, subtitle, desc, largedesc, showBreadcrumb, backgroundImage }: Props) { +export default function Banner({ title, subtitle, desc, largedesc, showBreadcrumb, breadcrumbItems, titleSize = "large", backgroundImage }: Props) { return (
-

{title}

+

{title}

{subtitle &&

{subtitle}

} {desc &&

{desc}

} {largedesc &&

{largedesc}

} - {showBreadcrumb && ( -
- 首页 - {'>'} - 关于银泰 -
- )} +
+ {showBreadcrumb && (breadcrumbItems ?? []).map((item, i) => ( + + {i > 0 && {' > '}} + {item.to ? {item.label} : {item.label}} + + ))} +
) diff --git a/src/components/layout/SectionTitle/index.module.css b/src/components/layout/SectionTitle/index.module.css new file mode 100644 index 0000000..20e1a49 --- /dev/null +++ b/src/components/layout/SectionTitle/index.module.css @@ -0,0 +1,8 @@ +.sectionTitle { + font-weight: 700; + font-size: 40px; + color: #222222; + line-height: 50px; + text-align: center; + margin-bottom: 100px; +} \ No newline at end of file diff --git a/src/components/layout/SectionTitle/index.tsx b/src/components/layout/SectionTitle/index.tsx new file mode 100644 index 0000000..6816d8c --- /dev/null +++ b/src/components/layout/SectionTitle/index.tsx @@ -0,0 +1,9 @@ +import styles from "./index.module.css"; + +export default function SectionTitle({ title }: { title: string }) { + return ( +
+ {title} +
+ ) +} \ No newline at end of file diff --git a/src/components/layout/StatsRow/StatsRow.module.css b/src/components/layout/StatsRow/StatsRow.module.css new file mode 100644 index 0000000..d30f5e4 --- /dev/null +++ b/src/components/layout/StatsRow/StatsRow.module.css @@ -0,0 +1,37 @@ +.statsRow { + margin-top: 9.375rem; + display: flex; + flex-wrap: wrap; + gap: 0; + align-items: flex-start; + justify-content: center; + flex-wrap: nowrap; +} + +.statItem { + width: 17rem; + display: flex; + flex-direction: column; + align-items: center; + gap: .625rem; +} + +.statItem:not(:last-child) { + border-right: 1px solid #222222; +} + +.statNum { + font-size: 2.5rem; + font-weight: 700; + color: #222; + line-height: 1.2; +} + +.statNumDesc { + font-size: 1.875rem; +} + +.statLabel { + font-size: 1rem; + color: #666; +} \ No newline at end of file diff --git a/src/components/layout/StatsRow/StatsRow.tsx b/src/components/layout/StatsRow/StatsRow.tsx new file mode 100644 index 0000000..22c0f55 --- /dev/null +++ b/src/components/layout/StatsRow/StatsRow.tsx @@ -0,0 +1,26 @@ +import styles from "./StatsRow.module.css"; + +type StatsData = { + num: string; + label: string; +} + +export default function StatsRow({ statsData }: { statsData: StatsData[] }) { + return ( +
+ {statsData.map((item, i) => ( +
+
+ + {item.num.split(' ')[0] + ' '} + + + {item.num.split(' ')[1]} + +
+ {item.label} +
+ ))} +
+ ); +} \ No newline at end of file diff --git a/src/components/layout/SwiperCardSection/index.module.css b/src/components/layout/SwiperCardSection/index.module.css new file mode 100644 index 0000000..0d4961d --- /dev/null +++ b/src/components/layout/SwiperCardSection/index.module.css @@ -0,0 +1,57 @@ +.swiperCardSection { + min-height: 100vh; + padding: 100px 260px; + background: #D8D8D8; +} + + +.swiperCardList { + display: flex; + flex-direction: row; + gap: 15px; + .swiperCardItem { + position: relative; + width: 100%; + aspect-ratio: 457 / 630; + img { + width: 100%; + aspect-ratio: 457 / 630; + object-fit: cover; + } + .swiperMask { + width: 100%; + aspect-ratio: 457 / 630; + position: absolute; + top: 0; + left: 0; + background: rgba(0, 0, 0, 0.2); + } + + .swiperContent { + color: #fff; + position: absolute; + top: 80%; + left: 0; + width: 100%; + height: 100%; + + .swiperTitle { + font-weight: 500; + font-size: 24px; + color: #FFFFFF; + line-height: 80px; + height: 80px; + margin: 0 30px; + text-align: center; + border-bottom: 1px solid rgba(255,255,255,0.3); + + span { + display: inline-block; + line-height: 80px; + height: 80px; + border-bottom: 3px solid #14355C; + } + } + } + } +} \ No newline at end of file diff --git a/src/components/layout/SwiperCardSection/index.tsx b/src/components/layout/SwiperCardSection/index.tsx new file mode 100644 index 0000000..bbe0b09 --- /dev/null +++ b/src/components/layout/SwiperCardSection/index.tsx @@ -0,0 +1,33 @@ +import SectionTitle from "../SectionTitle"; +import styles from "./index.module.css"; + +type Data = { + title: string; + cardItems: { + title: string; + desc: string; + image: string; + }[]; +} + +export default function SwiperCardSection({ data }: { data: Data }) { + return ( +
+ +
+ {data.cardItems.map((item) => ( +
+ {item.title} +
+
+
+ {item.title} +
+ {/*

{item.desc}

*/} +
+
+ ))} +
+
+ ) +} \ No newline at end of file diff --git a/src/index.css b/src/index.css index a30c8c8..fb7e8b9 100644 --- a/src/index.css +++ b/src/index.css @@ -1,3 +1,38 @@ +/* rem 基准:以 16px 为设计稿基准 */ +html { + font-size: 16px; +} + +@media screen and (max-width: 1920px) { + html { + font-size: 16px; + } +} + +@media screen and (max-width: 1440px) { + html { + font-size: 14px; + } +} + +@media screen and (max-width: 1024px) { + html { + font-size: 12px; + } +} + +@media screen and (max-width: 768px) { + html { + font-size: 12px; + } +} + +@media screen and (max-width: 480px) { + html { + font-size: 12px; + } +} + body { margin: 0; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', @@ -13,6 +48,10 @@ code { } @font-face { - font-family: 'Alimama ShuHeiTi'; - src: url('https://cdn.batiao8.com/static/ttf/%E9%98%BF%E9%87%8C%E5%A6%88%E5%A6%88%E6%95%B0%E9%BB%91%E4%BD%93.ttf'); + font-family: 'D-DIN-PRO'; + src: url('/public/ttf/D-DIN-PRO-400-Regular.otf'); +} +@font-face { + font-family: 'Source Han Sans'; + src: url('/public/ttf/SourceHanSansCN-Normal.otf'); } \ No newline at end of file diff --git a/src/layouts/Footer.module.css b/src/layouts/Footer.module.css index 2f59c4a..4ed245d 100644 --- a/src/layouts/Footer.module.css +++ b/src/layouts/Footer.module.css @@ -4,32 +4,32 @@ } .footerUpper { - padding: 60px; + padding: 3.75rem; } .footerGrid { display: grid; grid-template-columns: repeat(7, 1fr) auto; - gap: 24px; + gap: 1.5rem; align-items: start; } .footerColumn { display: flex; flex-direction: column; - gap: 12px; + gap: 0.75rem; } .footerTitle { - font-size: 14px; + font-size: 0.875rem; font-weight: 600; color: #333; - margin-bottom: 4px; + margin-bottom: 0.25rem; } .footerLink { - font-size: 13px; + font-size: 0.8125rem; color: #666; text-decoration: none; } @@ -42,25 +42,25 @@ display: flex; flex-direction: row; align-items: center; - gap: 16px; + gap: 1rem; position: absolute; - right: 60px; + right: 3.75rem; } .footerLogo { - font-size: 20px; + font-size: 1.25rem; font-weight: 600; color: #999; } .socialIcons { display: flex; - gap: 12px; + gap: 0.75rem; } .socialIcon { - width: 28px; - height: 28px; + width: 1.75rem; + height: 1.75rem; border-radius: 50%; background: #ddd; display: flex; @@ -68,13 +68,13 @@ justify-content: center; color: #666; text-decoration: none; - font-size: 12px; + font-size: 0.75rem; } .footerLower { background: #031229; color: #fff; - height: 60px; + height: 3.75rem; display: flex; align-items: center; justify-content: center; @@ -84,12 +84,12 @@ display: flex; align-items: center; justify-content: space-between; - font-size: 14px; + font-size: 0.875rem; } .footerLowerLinks { display: flex; - gap: 20px; + gap: 1.25rem; } .footerLowerLink { @@ -100,3 +100,44 @@ .footerLowerLink:hover { color: #fff; } + +@media (max-width: 1024px) { + .footerUpper { + padding: 2rem; + } + + .footerGrid { + grid-template-columns: repeat(4, 1fr); + gap: 1.25rem; + } + + .footerRight { + right: 2rem; + } +} + +@media (max-width: 768px) { + .footerUpper { + padding: 1.5rem; + } + + .footerGrid { + grid-template-columns: repeat(2, 1fr); + gap: 1rem; + } + + .footerRight { + position: static; + margin-top: 1rem; + } + + .footerLower { + height: auto; + padding: 1rem; + } + + .footerLowerInner { + flex-direction: column; + gap: 0.5rem; + } +} diff --git a/src/layouts/Header.module.css b/src/layouts/Header.module.css index bad39de..bb2ea9a 100644 --- a/src/layouts/Header.module.css +++ b/src/layouts/Header.module.css @@ -3,13 +3,13 @@ top: 0; left: 0; z-index: 1000; - height: 120px; + height: 7.5rem; width: 100%; font-family: Source Han Sans, Source Han Sans; font-weight: 700; - font-size: 18px; - line-height: 26px; + font-size: 1.125rem; + line-height: 1.625rem; text-align: left; font-style: normal; text-transform: none; @@ -37,10 +37,10 @@ .headerInner::after { position: absolute; bottom: 0; - left: 60px; + left: 3.75rem; content: ''; display: block; - width: calc(100% - 120px); + width: calc(100% - 7.5rem); box-sizing: border-box; height: 1px; background: #FFFFFF; @@ -56,7 +56,7 @@ .headerRight { display: flex; align-items: center; - gap: 30px; + gap: 1.875rem; } .nav { @@ -66,11 +66,11 @@ list-style: none; margin: 0; padding: 0; - margin-right: 30px; + margin-right: 1.875rem; } .navItem { - padding: 0 30px; + padding: 0 1.875rem; } .navLink { @@ -90,14 +90,14 @@ .actions { display: flex; align-items: center; - gap: 16px; - margin-left: 30px; + gap: 1rem; + margin-left: 1.875rem; } .langTrigger { display: flex; align-items: center; - gap: 4px; + gap: 0.25rem; color: #fff; background: transparent; border: none; @@ -109,7 +109,7 @@ background: transparent; border: none; cursor: pointer; - padding: 4px; + padding: 0.25rem; display: flex; align-items: center; justify-content: center; @@ -121,10 +121,10 @@ top: 100%; left: 0; width: 100%; - height: 380px; + height: 23.75rem; background: rgba(255, 255, 255, 0.9); box-shadow: 0 0 10px 0 rgba(0, 0, 0, 0.1); - padding: 20px; + padding: 1.25rem; z-index: 1000; } @@ -136,8 +136,71 @@ .dropPanelLink { font-weight: 400; - font-size: 18px; - line-height: 50px; + font-size: 1.125rem; + line-height: 3.125rem; color: #222222; text-decoration: none; +} + +@media (max-width: 1024px) { + .header { + height: 5.5rem; + } + + .headerInner::after { + left: 1.5rem; + width: calc(100% - 3rem); + } + + .navItem { + padding: 0 1rem; + } + + .headerRight { + gap: 1rem; + } + + .nav { + margin-right: 1rem; + } + + .actions { + margin-left: 1rem; + } +} + +@media (max-width: 768px) { + .header { + height: 4rem; + } + + .headerInner::after { + left: 1rem; + width: calc(100% - 2rem); + } + + .navItem { + padding: 0 0.5rem; + } + + .headerRight { + gap: 0.5rem; + } + + .nav { + margin-right: 0.5rem; + } + + .actions { + margin-left: 0.5rem; + } + + .dropPanel { + height: auto; + padding: 1rem; + } + + .dropPanelLink { + line-height: 2.5rem; + } } \ No newline at end of file diff --git a/src/layouts/Header.tsx b/src/layouts/Header.tsx index e68a276..ad3867a 100644 --- a/src/layouts/Header.tsx +++ b/src/layouts/Header.tsx @@ -80,7 +80,7 @@ export default function Header() { >
- logo + logo