From a0ffbf9f0af6ddbccfbbf646aa2ef09be798a249 Mon Sep 17 00:00:00 2001 From: Blucas <15555602203@163.com> Date: Tue, 4 Mar 2025 23:08:11 +0800 Subject: [PATCH] feat: add cn mirror link --- src/App.tsx | 2 + src/assets/image/run-right.svg | 1 + src/assets/locales/index.ts | 10 ++--- src/components/CNUserModal/index.tsx | 62 ++++++++++++++++++++++++++++ src/pages/Layouts/Logo/index.less | 15 +------ src/pages/Layouts/Logo/index.tsx | 8 +++- src/pages/Layouts/NavMenu/index.tsx | 29 ++++++++++++- src/pages/Layouts/index.less | 7 +++- src/pages/Layouts/index.tsx | 8 ++-- 9 files changed, 114 insertions(+), 28 deletions(-) create mode 100644 src/assets/image/run-right.svg create mode 100644 src/components/CNUserModal/index.tsx diff --git a/src/App.tsx b/src/App.tsx index e1723aa9..ad482266 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -10,6 +10,7 @@ import { langType, useLanguage } from './utils/useLanguage'; import { ErrorBoundary } from './components/ErrorBoundary'; import type { Locale } from 'antd/es/locale'; import dayjs from 'dayjs'; +import { CNUserModal } from './components/CNUserModal'; const localeConfig: Record = { zh, @@ -39,6 +40,7 @@ export const App = () => { }, }} > + diff --git a/src/assets/image/run-right.svg b/src/assets/image/run-right.svg new file mode 100644 index 00000000..9275c7ba --- /dev/null +++ b/src/assets/image/run-right.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/locales/index.ts b/src/assets/locales/index.ts index 66b31309..66b68012 100644 --- a/src/assets/locales/index.ts +++ b/src/assets/locales/index.ts @@ -1,7 +1,3 @@ -// import zh from './zh.json'; -// import en from './en.json'; -// import ja from './ja.json'; -// import ko from './ko.json'; import { initReactI18next } from 'react-i18next'; import i18next, { InitOptions } from 'i18next'; import languageDetector from 'i18next-browser-languagedetector'; @@ -28,21 +24,21 @@ i18next .use(languageDetector) .init({ resources, - fallbackLng: 'zh', + fallbackLng: 'en', interpolation: { escapeValue: false, }, }); export const getTranslation = (key: string) => { - const lang = i18next.resolvedLanguage || 'zh'; + const lang = i18next.resolvedLanguage || 'en'; const res = i18next.getResource(lang, 'translation', key); return res || key; }; export const isCN = () => { const lang = i18next.resolvedLanguage; - return ['zh-CN', 'zh-HK', 'zh-TW', 'zh'].some((l) => { + return ['zh', 'zh-CN', 'zh-Hans-CN'].some((l) => { return lang === l; }); }; diff --git a/src/components/CNUserModal/index.tsx b/src/components/CNUserModal/index.tsx new file mode 100644 index 00000000..19d562c4 --- /dev/null +++ b/src/components/CNUserModal/index.tsx @@ -0,0 +1,62 @@ +import { isClient } from '@/utils/constants'; +import { Button, Modal } from 'antd'; +import dayjs from 'dayjs'; +import { useState } from 'react'; +import RunSvg from '@/assets/image/run-right.svg?react'; +import Icon from '@ant-design/icons'; +import { isCN } from '@/assets/locales'; + +const CACHE_NAME = 'page-spy-do-not-open-mirror-modal'; +export const OFFICIAL_SITE = /^(w{3}.)?pagespy\.org$/; +export const CN_MIRROR_SITE = 'https://pagespy.huolala.cn'; + +export const CNUserModal = () => { + const [open, setOpen] = useState(() => { + const { host } = location; + if (isClient || !OFFICIAL_SITE.test(host) || !isCN()) return false; + + const beforeOpenTime = localStorage[CACHE_NAME]; + if (beforeOpenTime) { + const before = dayjs(beforeOpenTime); + const now = dayjs(); + const diffDays = now.diff(before, 'day'); + if (diffDays < 7) { + return false; + } + } + + return true; + }); + + return ( + { + localStorage.setItem(CACHE_NAME, new Date().toString()); + setOpen(false); + }} + > + 7 天内不再显示 + , + , + ]} + > +

+ 国内用户推荐访问国内镜像站以获得最佳体验~ +

+
+ ); +}; diff --git a/src/pages/Layouts/Logo/index.less b/src/pages/Layouts/Logo/index.less index f44952ba..d38899ae 100644 --- a/src/pages/Layouts/Logo/index.less +++ b/src/pages/Layouts/Logo/index.less @@ -2,18 +2,13 @@ height: var(--header-height); display: flex; align-items: center; - gap: 20px; - > a { - height: 100%; - display: inline-flex; - place-items: center; - color: #000; + &.in-ospy { + gap: 20px; } .logo-icon { font-size: 48px; } .logo-name { - margin-left: 12px; margin-bottom: 0; } .page-spy-version { @@ -21,10 +16,4 @@ transform: translate(2px, -10px); font-size: 12px; } - .producthunt-brand { - height: 36px; - @media screen and (max-width: 420px) { - display: none; - } - } } diff --git a/src/pages/Layouts/Logo/index.tsx b/src/pages/Layouts/Logo/index.tsx index 8eb0c14f..c7df17db 100644 --- a/src/pages/Layouts/Logo/index.tsx +++ b/src/pages/Layouts/Logo/index.tsx @@ -8,6 +8,7 @@ import Icon from '@ant-design/icons'; import Title from 'antd/es/typography/Title'; import './index.less'; import { useWhere } from '@/utils/useWhere'; +import clsx from 'clsx'; export const Logo = () => { const where = useWhere(); @@ -29,7 +30,12 @@ export const Logo = () => { }, [where]); return ( - + {config.name} diff --git a/src/pages/Layouts/NavMenu/index.tsx b/src/pages/Layouts/NavMenu/index.tsx index 8aa9244e..f5de36ca 100644 --- a/src/pages/Layouts/NavMenu/index.tsx +++ b/src/pages/Layouts/NavMenu/index.tsx @@ -9,7 +9,8 @@ import I18nSvg from '@/assets/image/i18n.svg?react'; import BugSvg from '@/assets/image/bug.svg?react'; import OnlineSvg from '@/assets/image/online.svg?react'; import ReplaySvg from '@/assets/image/replay.svg?react'; -import i18n from '@/assets/locales'; +import RunSvg from '@/assets/image/run-right.svg?react'; +import i18n, { isCN } from '@/assets/locales'; import { useMemo, useRef, useState } from 'react'; import clsx from 'clsx'; import './index.less'; @@ -17,6 +18,7 @@ import { useDarkTheme } from '@/utils/useDarkTheme'; import { CSSTransition } from 'react-transition-group'; import { createPortal } from 'react-dom'; import { useWhere } from '@/utils/useWhere'; +import { CN_MIRROR_SITE } from '@/components/CNUserModal'; const ALL_LANGS: MenuProps['items'] = [ { @@ -138,6 +140,18 @@ export const NavMenuOnPc = () => { </ConfigProvider> </div> <Divider type="vertical" className="divider-bg" /> + {/* Mirror */} + {isDoc && isCN() && ( + <> + <a href={CN_MIRROR_SITE} target="_blank" className="menu-item doc"> + <Space align="center"> + <Icon component={RunSvg} style={{ fontSize: 16 }} /> + <span>国内镜像</span> + </Space> + </a> + <Divider type="vertical" className="divider-bg" /> + </> + )} <a href={import.meta.env.VITE_GITHUB_REPO} target="_blank" @@ -241,6 +255,19 @@ export const NavMenuOnMobile = () => { <span>{t('common.lang')}</span> </Space> </div> + {/* Mirror */} + {isDoc && isCN() && ( + <a + href={CN_MIRROR_SITE} + target="_blank" + className="menu-item doc" + > + <Space align="center"> + <Icon component={RunSvg} style={{ fontSize: 16 }} /> + <span>国内镜像</span> + </Space> + </a> + )} {/* GitHub */} <div className="menu-item"> <a href={import.meta.env.VITE_GITHUB_REPO} target="_blank"> diff --git a/src/pages/Layouts/index.less b/src/pages/Layouts/index.less index cde7e097..39c0276a 100644 --- a/src/pages/Layouts/index.less +++ b/src/pages/Layouts/index.less @@ -12,7 +12,7 @@ } .header { position: relative; - padding-inline: 48px; + padding-inline: 32px; height: var(--header-height); box-shadow: @light-box-shadow; background-color: var(--light-background); @@ -26,13 +26,16 @@ word-break: keep-all; } } + .third-brand { + line-height: 1; + } } } @media screen and (max-width: 768px) { .layouts { .header { - padding-inline: 24px; + padding-inline: 16px; } } } diff --git a/src/pages/Layouts/index.tsx b/src/pages/Layouts/index.tsx index 6ef7bc7a..4f5022b0 100644 --- a/src/pages/Layouts/index.tsx +++ b/src/pages/Layouts/index.tsx @@ -1,4 +1,4 @@ -import { Col, Layout, Row } from 'antd'; +import { Col, Flex, Layout, Row } from 'antd'; import { Outlet } from 'react-router-dom'; import './index.less'; import clsx from 'clsx'; @@ -23,7 +23,7 @@ export const Layouts = () => { className={clsx('header', isDark && 'is-dark')} > <Col> - <div className="logo"> + <Flex gap={20} align="center"> <Logo /> {isDoc && ( <a @@ -34,11 +34,11 @@ export const Layouts = () => { <img src="https://trendshift.io/api/badge/repositories/5407" alt="HuolalaTech/page-spy-web | Trendshift" - height="36" + style={{ height: 36 }} /> </a> )} - </div> + </Flex> </Col> <Col> <NavMenuOnPc />