From 12b55df82f60f3a0f52cfe5c2019103f528f242d Mon Sep 17 00:00:00 2001 From: joey Date: Mon, 12 Jan 2026 11:09:24 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E4=BF=AE=E5=A4=8D=E5=B7=B2=E7=9F=A5bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/App.jsx | 489 +++++++++++++++++++++++------------------- src/data/osn/en.md | 13 ++ src/data/osn/ms.md | 13 ++ src/data/osn/zh-CN.md | 11 + src/data/osn/zh-TW.md | 13 ++ 5 files changed, 320 insertions(+), 219 deletions(-) create mode 100644 src/data/osn/en.md create mode 100644 src/data/osn/ms.md create mode 100644 src/data/osn/zh-CN.md create mode 100644 src/data/osn/zh-TW.md diff --git a/src/App.jsx b/src/App.jsx index 16c7390..0cfe1a4 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -1,216 +1,258 @@ -import React, { useState, useEffect } from 'react'; -import { Globe, ChevronDown } from 'lucide-react'; +import React, {useState, useEffect} from 'react'; +import {Globe, ChevronDown} from 'lucide-react'; import ReactMarkdown from 'react-markdown'; const LegalDocuments = () => { - const [currentDoc, setCurrentDoc] = useState('terms'); - const [language, setLanguage] = useState('zh-CN'); - const [showLangMenu, setShowLangMenu] = useState(false); - const [hideHeader, setHideHeader] = useState(true); - const [content, setContent] = useState(''); - const [loading, setLoading] = useState(true); + const [currentDoc, setCurrentDoc] = useState('terms'); + const [language, setLanguage] = useState('zh-CN'); + const [showLangMenu, setShowLangMenu] = useState(false); + const [hideHeader, setHideHeader] = useState(true); + const [content, setContent] = useState(''); + const [loading, setLoading] = useState(true); + const [initialized, setInitialized] = useState(false); // 添加初始化标志 - // 动态导入 Markdown 文件 - useEffect(() => { - const loadMarkdown = async () => { - setLoading(true); - try { - const docPath = currentDoc === 'terms' ? 'terms' : 'privacy'; - const response = await import(`./data/${docPath}/${language}.md?raw`); - setContent(response.default); - } catch (error) { - console.error('Error loading markdown:', error); - setContent('内容加载失败,请稍后重试。'); - } finally { - setLoading(false); - } - }; + // 解析URL并设置初始状态(优先执行) + useEffect(() => { + const searchParams = new URLSearchParams(window.location.search); + const docType = searchParams.get('content'); + const lang = searchParams.get('language'); - loadMarkdown(); - }, [currentDoc, language]); + if (docType === null && lang === null) { + setHideHeader(false); + return; + } - // 解析URL并设置初始状态 - // 解析 URL query 并设置初始状态 - useEffect(() => { - const searchParams = new URLSearchParams(window.location.search); - const docType = searchParams.get('content') ; - const lang = searchParams.get('language') ; - - - console.log(lang); - if (docType === null && lang === null) { - setHideHeader(false); - return; - } - - // 映射文档类型 - const docMap = { - 'user-agreement': 'terms', - 'terms': 'terms', - 'privacy-policy': 'privacy', - 'privacy': 'privacy' - }; - - // 映射语言类型 - const langMap = { - 'zh': 'zh-CN', - 'zh-FT': 'zh-TW', - 'en': 'en', - 'ms': 'ms', - } - - if (docMap[docType.toLowerCase()]) { - setCurrentDoc(docMap[docType.toLowerCase()]); - } - - if (langMap[lang]) { - setLanguage(langMap[lang]); - } - - if (docMap[docType.toLowerCase()] && langMap[lang]) { - setHideHeader(true); - } else { - setHideHeader(false); - } - }, []); - - const languages = { - 'zh-CN': '简体中文', - 'zh-TW': '繁體中文', - 'en': 'English', - 'ms': 'Bahasa Melayu' + // 映射文档类型 + const docMap = { + 'user-agreement': 'terms', + 'terms': 'terms', + 'privacy-policy': 'privacy', + 'osn': 'osn', }; - const navItems = { - 'zh-CN': { terms: '用户协议', privacy: '隐私政策' }, - 'zh-TW': { terms: '用戶協議', privacy: '隱私政策' }, - 'en': { terms: 'Terms', privacy: 'Privacy' }, - 'ms': { terms: 'Terma', privacy: 'Privasi' } + // 映射语言类型 + const langMap = { + 'zh': 'zh-CN', + 'zh-FT': 'zh-TW', + 'en': 'en', + 'ms': 'ms', }; - const lastUpdated = { - 'zh-CN': '最后更新时间', - 'zh-TW': '最後更新時間', - 'en': 'Last Updated', - 'ms': 'Kemaskini Terakhir' + if (docType && docMap[docType.toLowerCase()]) { + setCurrentDoc(docMap[docType.toLowerCase()]); + } + + if (lang && langMap[lang]) { + setLanguage(langMap[lang]); + } + + if ( + docType && + lang && + docMap[docType.toLowerCase()] && + langMap[lang] + ) { + setHideHeader(true); + } else { + setHideHeader(false); + } + + // 标记初始化完成 + setInitialized(true); + }, []); + + // 动态导入 Markdown 文件(只在初始化完成后执行) + useEffect(() => { + if (!initialized) return; // 等待 URL 解析完成 + + const loadMarkdown = async () => { + setLoading(true); + try { + const response = await import(`./data/${currentDoc}/${language}.md?raw`); + setContent(response.default); + } catch (error) { + console.error('Error loading markdown:', error); + setContent('内容加载失败,请稍后重试。'); + } finally { + setLoading(false); + } }; - const titles = { - terms: { - 'zh-CN': '用户协议', - 'zh-TW': '用戶協議', - 'en': 'Terms of Service', - 'ms': 'Perjanjian Pengguna' - }, - privacy: { - 'zh-CN': '隐私政策', - 'zh-TW': '隱私政策', - 'en': 'Privacy Policy', - 'ms': 'Dasar Privasi' - } - }; + loadMarkdown(); + }, [currentDoc, language, initialized]); - return ( -
- {/* Header - 根据 hideHeader 状态决定是否显示 */} - {!hideHeader && ( -
-
-
- {/* Logo */} -
-
- S -
- + const languages = { + 'zh-CN': '简体中文', + 'zh-TW': '繁體中文', + 'en': 'English', + 'ms': 'Bahasa Melayu', + }; + + const navItems = { + 'zh-CN': { + terms: '用户协议', + privacy: '隐私政策', + osn: '开源组件说明', + }, + 'zh-TW': { + terms: '用戶協議', + privacy: '隱私政策', + osn: '開源組件說明', + }, + 'en': { + terms: 'Terms', + privacy: 'Privacy', + osn: 'Open Source Notices', + }, + 'ms': { + terms: 'Terma', + privacy: 'Privasi', + osn: 'Notis Sumber Terbuka', + }, + }; + + const lastUpdated = { + 'zh-CN': '最后更新时间', + 'zh-TW': '最後更新時間', + 'en': 'Last Updated', + 'ms': 'Kemaskini Terakhir', + }; + + const titles = { + terms: { + 'zh-CN': '用户协议', + 'zh-TW': '用戶協議', + 'en': 'Terms of Service', + 'ms': 'Perjanjian Pengguna', + }, + privacy: { + 'zh-CN': '隐私政策', + 'zh-TW': '隱私政策', + 'en': 'Privacy Policy', + 'ms': 'Dasar Privasi', + }, + osn: { + 'zh-CN': '第三方开源组件与资源声明', + 'zh-TW': '第三方開源組件與資源聲明', + 'en': 'Third-Party Open Source Components and Resources Notice', + 'ms': 'Notis Komponen dan Sumber Sumber Terbuka Pihak Ketiga', + }, + }; + + + return ( +
+ {/* Header - 根据 hideHeader 状态决定是否显示 */} + {!hideHeader && ( +
+
+
+ {/* Logo */} +
+
+ S +
+ Social App -
+
- {/* Navigation */} -
+ {showLangMenu && ( +
+ {Object.entries(languages).map(([code, name]) => ( + + ))}
-
- )} + )} +
+ +
+
+
+ )} - {/* Main Content */} -
-
- {/* Title */} -
-

- {titles[currentDoc][language]} -

-
- {lastUpdated[language]}: - -
-
+ {/* Main Content */} +
+
+ {/* Title */} +
+

+ {titles[currentDoc][language]} +

+
+ {lastUpdated[language]}: + +
+
- {/* Content */} - {loading ? ( -
-
-
- ) : ( -
+
+
+ ) : ( +
-

, - h1: ({node, ...props}) =>

, - h2: ({node, ...props}) =>

, - h3: ({node, ...props}) =>

, - ul: ({node, ...props}) =>
    , - ol: ({node, ...props}) =>
      , - }} - > - {content} - -

- )} -
+

, + h1: ({node, ...props}) =>

, + h2: ({node, ...props}) =>

, + h3: ({node, ...props}) =>

, + ul: ({node, ...props}) =>
    , + ol: ({node, ...props}) =>
      , + code: ({node, ...props}) =>
      ,
       
      -                {/* Footer */}
      -                
      -

      © 2024 Social App. All rights reserved.

      -
      -

+ // code: ({node, inline, ...props}) => + // inline ? ( + // + // ) : ( + //
+                  //     ),
+                }}
+              >
+                {content}
+              
+            
+ )} + - {/* Click outside to close language menu */} - {showLangMenu && ( -
setShowLangMenu(false)} - /> - )} -
- ); + {/* Footer */} +
+

© 2024 Social App. All rights reserved.

+
+ + + {/* Click outside to close language menu */} + {showLangMenu && ( +
setShowLangMenu(false)} + /> + )} +
+ ); }; export default LegalDocuments; \ No newline at end of file diff --git a/src/data/osn/en.md b/src/data/osn/en.md new file mode 100644 index 0000000..d9de45c --- /dev/null +++ b/src/data/osn/en.md @@ -0,0 +1,13 @@ +**License**: Apache License 2.0 + +> **Attribution Requirement**: The animated emoji resources used in this project are from the Google Noto Emoji Animation project, + +> protected under the Apache License 2.0. When using these resources, please retain the following attribution information: +: +> +> ``` +> Animated emoji provided by Google Noto Emoji Animation +> +> https://googlefonts.github.io/noto-emoji-animation/ +> +> Licensed under Apache License 2.0 diff --git a/src/data/osn/ms.md b/src/data/osn/ms.md new file mode 100644 index 0000000..def5f5a --- /dev/null +++ b/src/data/osn/ms.md @@ -0,0 +1,13 @@ +**Lesen**: Apache License 2.0 + +> **Keperluan Pencatatan Nama**: Sumber emoji animasi yang digunakan dalam projek ini berasal dari projek Google Noto Emoji Animation +, +> dilindungi di bawah Lesen Apache License 2.0. Apabila menggunakan sumber ini, sila simpan maklumat pencatatan nama berikut: + +> +> ``` +> Animated emoji provided by Google Noto Emoji Animation +> +> https://googlefonts.github.io/noto-emoji-animation/ +> +> Licensed under Apache License 2.0 diff --git a/src/data/osn/zh-CN.md b/src/data/osn/zh-CN.md new file mode 100644 index 0000000..23e76f1 --- /dev/null +++ b/src/data/osn/zh-CN.md @@ -0,0 +1,11 @@ +**许可证**: Apache License 2.0 + +> **署名要求**: 本项目使用的动画表情资源来自 Google Noto Emoji Animation 项目, +> 受 Apache License 2.0 许可证保护。使用时需保留以下署名信息: +> +> ``` +> Animated emoji provided by Google Noto Emoji Animation +> +> https://googlefonts.github.io/noto-emoji-animation/ +> +> Licensed under Apache License 2.0 diff --git a/src/data/osn/zh-TW.md b/src/data/osn/zh-TW.md new file mode 100644 index 0000000..8af1fc7 --- /dev/null +++ b/src/data/osn/zh-TW.md @@ -0,0 +1,13 @@ +**授權條款**: Apache License 2.0 + +> **署名要求**: 本專案使用的動畫表情資源來自 Google Noto Emoji Animation 專案 +, +> 受 Apache License 2.0 授權條款保護。使用時需保留以下署名資訊: +: +> +> ``` +> Animated emoji provided by Google Noto Emoji Animation +> +> https://googlefonts.github.io/noto-emoji-animation/ +> +> Licensed under Apache License 2.0