app.tsx 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. import React, { useEffect, useState } from "react";
  2. import { Dropdown } from "antd";
  3. import type { MenuProps } from "antd";
  4. import { DownOutlined } from "@ant-design/icons";
  5. import { history } from "@umijs/max";
  6. import logoPng from "@/assets/image/logo.ico";
  7. import logoKailin from "@/assets/image/logo_i.png";
  8. import { products } from "./utils/utils";
  9. const scrollToHash = (hash: string) => {
  10. if (typeof window === "undefined") return;
  11. const id = hash.replace(/^#/, "");
  12. requestAnimationFrame(() => {
  13. const el = document.getElementById(id);
  14. el?.scrollIntoView({ behavior: "smooth", block: "start" });
  15. });
  16. };
  17. const AppRoot: React.FC<React.PropsWithChildren> = (props) => {
  18. const [pathname, setPathname] = useState(() => history.location.pathname);
  19. useEffect(() => {
  20. const toAbsoluteUrl = (url: string) => {
  21. if (/^https?:\/\//.test(url)) return url;
  22. const origin = window.location.origin.replace(/\/+$/, "");
  23. const p = url.startsWith("/") ? url : `/${url}`;
  24. return `${origin}${p}`;
  25. };
  26. const ensureMetaProperty = (property: string) => {
  27. let meta = document.querySelector(
  28. `meta[property="${property}"]`,
  29. ) as HTMLMetaElement | null;
  30. if (!meta) {
  31. meta = document.createElement("meta");
  32. meta.setAttribute("property", property);
  33. document.head.appendChild(meta);
  34. }
  35. return meta;
  36. };
  37. ensureMetaProperty("og:type").content = "website";
  38. ensureMetaProperty("og:url").content = window.location.href;
  39. ensureMetaProperty("og:image").content = toAbsoluteUrl(logoPng);
  40. let faviconLink = document.querySelector(
  41. 'link[rel~="icon"]',
  42. ) as HTMLLinkElement | null;
  43. if (!faviconLink) {
  44. faviconLink = document.createElement("link");
  45. faviconLink.rel = "icon";
  46. document.head.appendChild(faviconLink);
  47. }
  48. faviconLink.type = "image/png";
  49. faviconLink.href = logoPng;
  50. let appleTouchIconLink = document.querySelector(
  51. 'link[rel="apple-touch-icon"]',
  52. ) as HTMLLinkElement | null;
  53. if (!appleTouchIconLink) {
  54. appleTouchIconLink = document.createElement("link");
  55. appleTouchIconLink.rel = "apple-touch-icon";
  56. document.head.appendChild(appleTouchIconLink);
  57. }
  58. appleTouchIconLink.href = logoPng;
  59. }, []);
  60. useEffect(() => {
  61. const unlisten = history.listen(({ location }) => {
  62. setPathname(location.pathname);
  63. });
  64. return unlisten;
  65. }, []);
  66. useEffect(() => {
  67. const { hash } = window.location;
  68. if (hash && hash.length > 1) {
  69. scrollToHash(hash);
  70. }
  71. }, [pathname]);
  72. const hideHeader = pathname === "/privacy" || pathname === "/agreement";
  73. const headerHeight = hideHeader ? 0 : 72;
  74. const productMenuItems: MenuProps["items"] = products.map((product) => ({
  75. key: product.name,
  76. label: (
  77. <a href={product.url} target="_blank" rel="noreferrer">
  78. {product.name}
  79. </a>
  80. ),
  81. }));
  82. const header = hideHeader ? null : (
  83. <header className="siteHeader">
  84. <div className="siteHeaderInner">
  85. <a
  86. className="siteHeaderBrand"
  87. onClick={() => history.push("/home")}
  88. >
  89. <img className="siteHeaderLogo" src={logoKailin} alt="开邻智数" />
  90. {/* <span className="siteHeaderWordmark">
  91. <span className="siteHeaderName">开邻智数</span>
  92. <span className="siteHeaderEn">Kirin Intelligent Data</span>
  93. </span> */}
  94. </a>
  95. <nav className="siteHeaderNav" aria-label="主导航">
  96. <button
  97. type="button"
  98. className={
  99. pathname === "/home"
  100. ? "siteHeaderNavLink siteHeaderNavLinkActive"
  101. : "siteHeaderNavLink"
  102. }
  103. onClick={() => history.push("/home")}
  104. >
  105. 首页
  106. </button>
  107. <Dropdown menu={{ items: productMenuItems }} placement="bottom">
  108. <button type="button" className="siteHeaderNavLink siteHeaderNavDropdown">
  109. 产品中心
  110. <DownOutlined className="siteHeaderNavCaret" />
  111. </button>
  112. </Dropdown>
  113. <button
  114. type="button"
  115. className={
  116. pathname === "/solution"
  117. ? "siteHeaderNavLink siteHeaderNavLinkActive"
  118. : "siteHeaderNavLink"
  119. }
  120. onClick={() => history.push("/solution")}
  121. >
  122. 联系我们
  123. </button>
  124. <button
  125. type="button"
  126. className="siteHeaderCta"
  127. onClick={() => history.push("/solution")}
  128. >
  129. 获取方案
  130. </button>
  131. </nav>
  132. </div>
  133. </header>
  134. );
  135. return (
  136. <>
  137. {header}
  138. <div style={{ paddingTop: headerHeight }}>{props.children}</div>
  139. </>
  140. );
  141. };
  142. export function rootContainer(container: React.ReactNode) {
  143. return <AppRoot>{container}</AppRoot>;
  144. }