- Introduce PolicyModal component for license and privacy policy display - Add Quick Start section to project detail pages - Update project descriptions, features, and URLs for several projects - Add new logos, screenshots, and favicon - Extend types and configuration for new features
@@ -18,7 +18,9 @@
|
||||
"Bash(gh api *)",
|
||||
"Bash(echo \"exit: $?\")",
|
||||
"Bash(rtk npx *)",
|
||||
"Bash(rtk tsc *)"
|
||||
"Bash(rtk tsc *)",
|
||||
"Bash(netstat -ano)",
|
||||
"mcp__chrome-devtools__*"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
<meta property="og:description" content="构建轻量、高效、开源的软件工具" />
|
||||
<meta property="og:type" content="website" />
|
||||
<meta name="color-scheme" content="dark light" />
|
||||
<link rel="icon" type="image/webp" href="/logos/app.webp" />
|
||||
<meta name="twitter:card" content="summary" />
|
||||
</head>
|
||||
<body>
|
||||
|
||||
|
After Width: | Height: | Size: 44 KiB |
|
After Width: | Height: | Size: 754 KiB |
|
After Width: | Height: | Size: 170 KiB |
|
After Width: | Height: | Size: 148 KiB |
|
After Width: | Height: | Size: 89 KiB |
|
After Width: | Height: | Size: 78 KiB |
|
After Width: | Height: | Size: 95 KiB |
|
After Width: | Height: | Size: 112 KiB |
|
After Width: | Height: | Size: 78 KiB |
|
After Width: | Height: | Size: 122 KiB |
|
After Width: | Height: | Size: 82 KiB |
|
After Width: | Height: | Size: 174 KiB |
|
After Width: | Height: | Size: 94 KiB |
|
After Width: | Height: | Size: 60 KiB |
|
After Width: | Height: | Size: 155 KiB |
@@ -1,9 +1,12 @@
|
||||
import { Link } from 'react-router-dom';
|
||||
import { useState } from 'react';
|
||||
import { useI18n } from '../hooks/useI18n';
|
||||
import { siteData } from '../data/siteData';
|
||||
import PolicyModal from './PolicyModal';
|
||||
|
||||
export default function Footer() {
|
||||
const { t, bi, lang } = useI18n();
|
||||
const [policyModal, setPolicyModal] = useState<'license' | 'privacy' | null>(null);
|
||||
|
||||
return (
|
||||
<footer className="footer">
|
||||
@@ -43,13 +46,13 @@ export default function Footer() {
|
||||
<div className="footer-bottom">
|
||||
<span>{t('footer.copyright')}</span>
|
||||
<span className="footer-policy-links">
|
||||
<Link to="/about" className="footer-policy-link">
|
||||
<button type="button" className="footer-policy-link" onClick={() => setPolicyModal('license')}>
|
||||
{t('footer.license')}
|
||||
</Link>
|
||||
</button>
|
||||
{' · '}
|
||||
<Link to="/about" className="footer-policy-link">
|
||||
<button type="button" className="footer-policy-link" onClick={() => setPolicyModal('privacy')}>
|
||||
{t('footer.privacy')}
|
||||
</Link>
|
||||
</button>
|
||||
</span>
|
||||
<span className="footer-legal">
|
||||
{siteData.brand.icp && (
|
||||
@@ -65,6 +68,9 @@ export default function Footer() {
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
{policyModal && (
|
||||
<PolicyModal type={policyModal} onClose={() => setPolicyModal(null)} />
|
||||
)}
|
||||
</footer>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,204 @@
|
||||
import { useEffect } from 'react';
|
||||
import { createPortal } from 'react-dom';
|
||||
import { X, Scale, ShieldCheck } from 'lucide-react';
|
||||
import { useI18n } from '../hooks/useI18n';
|
||||
|
||||
interface PolicyModalProps {
|
||||
type: 'license' | 'privacy';
|
||||
onClose: () => void;
|
||||
}
|
||||
|
||||
export default function PolicyModal({ type, onClose }: PolicyModalProps) {
|
||||
const { t, lang } = useI18n();
|
||||
|
||||
const title = type === 'license' ? t('footer.license') : t('footer.privacy');
|
||||
|
||||
useEffect(() => {
|
||||
const prev = document.body.style.overflow;
|
||||
document.body.style.overflow = 'hidden';
|
||||
const onKey = (e: KeyboardEvent) => { if (e.key === 'Escape') onClose(); };
|
||||
window.addEventListener('keydown', onKey);
|
||||
return () => {
|
||||
document.body.style.overflow = prev;
|
||||
window.removeEventListener('keydown', onKey);
|
||||
};
|
||||
}, [onClose]);
|
||||
|
||||
return createPortal(
|
||||
<div className="policy-overlay" onClick={onClose}>
|
||||
<div className="policy-modal" onClick={(e) => e.stopPropagation()}>
|
||||
<div className="policy-modal-header">
|
||||
<div className="policy-modal-header-left">
|
||||
{type === 'license' ? <Scale size={20} /> : <ShieldCheck size={20} />}
|
||||
<h3 className="policy-modal-title">{title}</h3>
|
||||
</div>
|
||||
<button className="policy-modal-close" onClick={onClose} aria-label="Close">
|
||||
<X size={20} />
|
||||
</button>
|
||||
</div>
|
||||
<div className="policy-modal-body">
|
||||
{type === 'license' ? <LicenseContent /> : <PrivacyContent lang={lang} />}
|
||||
</div>
|
||||
</div>
|
||||
</div>,
|
||||
document.body
|
||||
);
|
||||
}
|
||||
|
||||
function LicenseContent() {
|
||||
const { lang } = useI18n();
|
||||
return (
|
||||
<div className="policy-content">
|
||||
<div className="policy-badge">MIT License</div>
|
||||
|
||||
<section className="policy-section">
|
||||
<h4>Copyright © 2026 ZUJ OL</h4>
|
||||
<p className="policy-highlight">
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the “Software”),
|
||||
to deal in the Software without restriction, including without limitation the
|
||||
rights to <strong>use</strong>, <strong>copy</strong>, <strong>modify</strong>,{' '}
|
||||
<strong>merge</strong>, <strong>publish</strong>, <strong>distribute</strong>,{' '}
|
||||
<strong>sublicense</strong>, and/or <strong>sell</strong> copies of the Software.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section className="policy-section">
|
||||
<h4>Conditions</h4>
|
||||
<p>
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section className="policy-section">
|
||||
<h4>Disclaimer</h4>
|
||||
<p className="policy-muted">
|
||||
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
|
||||
OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<footer className="policy-footer">
|
||||
{lang === 'zh' ? '完整协议文本请访问 ' : 'Full text available at '}
|
||||
<a href="https://opensource.org/licenses/MIT" target="_blank" rel="noopener noreferrer">
|
||||
opensource.org/licenses/MIT
|
||||
</a>
|
||||
</footer>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function PrivacyContent({ lang }: { lang: string }) {
|
||||
if (lang === 'zh') {
|
||||
return (
|
||||
<div className="policy-content">
|
||||
<p className="policy-intro">
|
||||
本隐私政策适用于 ZUJ OL Apps 网站。我们尊重您的隐私,致力于保护您的个人信息。
|
||||
</p>
|
||||
|
||||
<section className="policy-section">
|
||||
<h4><span className="policy-num">1</span> 信息收集</h4>
|
||||
<p>
|
||||
本项目不使用 Cookie,不收集任何个人身份信息(PII)。我们可能使用
|
||||
Vercel Analytics 等隐私优先的分析工具收集匿名访问数据(如页面浏览量、浏览器类型),
|
||||
以帮助改进网站体验。
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section className="policy-section">
|
||||
<h4><span className="policy-num">2</span> 第三方链接</h4>
|
||||
<p>
|
||||
本网站包含指向 GitHub、npm 等外部第三方网站的链接。我们对这些网站的隐私政策不承担任何责任。
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section className="policy-section">
|
||||
<h4><span className="policy-num">3</span> 数据安全</h4>
|
||||
<p>
|
||||
我们采取合理的安全措施保护网站的运行安全,但无法保证互联网传输的绝对安全。
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section className="policy-section">
|
||||
<h4><span className="policy-num">4</span> 政策更新</h4>
|
||||
<p>
|
||||
我们可能会不时更新本隐私政策。任何变更将在本页面公布。
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section className="policy-section">
|
||||
<h4><span className="policy-num">5</span> 联系方式</h4>
|
||||
<p>
|
||||
如对本隐私政策有任何疑问,请通过{' '}
|
||||
<a href="https://github.com/shenjianZ" target="_blank" rel="noopener noreferrer">GitHub Issues</a>
|
||||
{' '}联系我们。
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<footer className="policy-footer">
|
||||
最后更新:2026 年 5 月
|
||||
</footer>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="policy-content">
|
||||
<p className="policy-intro">
|
||||
This privacy policy applies to the ZUJ OL Apps website. We respect your privacy
|
||||
and are committed to protecting your personal information.
|
||||
</p>
|
||||
|
||||
<section className="policy-section">
|
||||
<h4><span className="policy-num">1</span> Information Collection</h4>
|
||||
<p>
|
||||
This project does not use cookies and does not collect any personally identifiable
|
||||
information (PII). We may use privacy-first analytics tools such as Vercel Analytics
|
||||
to collect anonymous access data (e.g., page views, browser type) to help improve
|
||||
the website experience.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section className="policy-section">
|
||||
<h4><span className="policy-num">2</span> Third-Party Links</h4>
|
||||
<p>
|
||||
This website contains links to external third-party websites such as GitHub and npm.
|
||||
We are not responsible for the privacy policies of these websites.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section className="policy-section">
|
||||
<h4><span className="policy-num">3</span> Data Security</h4>
|
||||
<p>
|
||||
We take reasonable security measures to protect the operation of the website, but
|
||||
cannot guarantee absolute security of internet transmissions.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section className="policy-section">
|
||||
<h4><span className="policy-num">4</span> Policy Updates</h4>
|
||||
<p>
|
||||
We may update this privacy policy from time to time. Any changes will be posted
|
||||
on this page.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section className="policy-section">
|
||||
<h4><span className="policy-num">5</span> Contact</h4>
|
||||
<p>
|
||||
If you have any questions about this privacy policy, please contact us via{' '}
|
||||
<a href="https://github.com/shenjianZ" target="_blank" rel="noopener noreferrer">GitHub Issues</a>.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<footer className="policy-footer">
|
||||
Last updated: May 2026
|
||||
</footer>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
import { createContext, useContext, useState, useEffect, useCallback, type ReactNode } from 'react';
|
||||
import type { AppContextType } from '../types';
|
||||
import { siteData } from '../data/loader';
|
||||
|
||||
const AppContext = createContext<AppContextType | null>(null);
|
||||
|
||||
@@ -17,6 +18,11 @@ export function AppProvider({ children }: { children: ReactNode }) {
|
||||
localStorage.setItem('theme', theme);
|
||||
}, [theme]);
|
||||
|
||||
useEffect(() => {
|
||||
const { name, slogan } = siteData.brand;
|
||||
document.title = `${name[lang]} — ${slogan[lang]}`;
|
||||
}, [lang]);
|
||||
|
||||
const toggleTheme = useCallback(() => {
|
||||
setTheme((prev) => (prev === 'dark' ? 'light' : 'dark'));
|
||||
}, []);
|
||||
|
||||
@@ -4,7 +4,7 @@ name:
|
||||
slogan:
|
||||
zh: '构建轻量、高效、开源的软件工具'
|
||||
en: 'Building lightweight, efficient, open-source software tools'
|
||||
logo: '/logo.svg'
|
||||
logo: '/logos/app.webp'
|
||||
author: 'shenjianZ'
|
||||
github: 'https://github.com/shenjianZ'
|
||||
email: '15202078626@163.com'
|
||||
|
||||
@@ -33,6 +33,7 @@ projects.sort.name: 'By Name'
|
||||
projects.noResults: 'No matching projects'
|
||||
projects.search: 'Search project name, description, or tags...'
|
||||
detail.overview: 'Overview'
|
||||
detail.quickStart: 'Quick Start'
|
||||
detail.features: 'Features'
|
||||
detail.screenshots: 'Screenshots'
|
||||
detail.downloads: 'Downloads'
|
||||
|
||||
@@ -33,6 +33,7 @@ projects.sort.name: '名称排序'
|
||||
projects.noResults: '没有匹配的项目'
|
||||
projects.search: '搜索项目名称、描述或标签...'
|
||||
detail.overview: '概览'
|
||||
detail.quickStart: '快速开始'
|
||||
detail.features: '核心功能'
|
||||
detail.screenshots: '截图预览'
|
||||
detail.downloads: '下载安装'
|
||||
|
||||
@@ -45,6 +45,11 @@ features:
|
||||
- '操作日志查看与管理'
|
||||
- '环境检测(ADB / scrcpy)'
|
||||
- '字号自定义(12-16px)'
|
||||
- 'WiFi 文件传输实时事件推送(WebSocket)'
|
||||
- '分片上传与断点续传(SHA-256 校验)'
|
||||
- '传输历史记录追踪'
|
||||
- '批量下载'
|
||||
- '文件预览(扩展 MIME 识别)'
|
||||
en:
|
||||
- 'Android device scanning & management (USB / WiFi)'
|
||||
- 'Scrcpy mirroring with multiple preset configs'
|
||||
@@ -62,6 +67,11 @@ features:
|
||||
- 'Operation log viewer & management'
|
||||
- 'Environment check (ADB / scrcpy)'
|
||||
- 'Font size customization (12-16px)'
|
||||
- 'WiFi file transfer real-time event push (WebSocket)'
|
||||
- 'Chunked upload with resume (SHA-256 verification)'
|
||||
- 'Transfer history tracking'
|
||||
- 'Batch download'
|
||||
- 'File preview (extended MIME recognition)'
|
||||
tags:
|
||||
- 'Android'
|
||||
- 'ADB'
|
||||
@@ -76,11 +86,11 @@ logo: '/logos/devicedeck.png'
|
||||
repoUrl: 'https://github.com/shenjianZ/devicedeck'
|
||||
websiteUrl: 'https://shenjianz.github.io/DeviceDeck/'
|
||||
docsUrl: 'https://github.com/shenjianZ/devicedeck#readme'
|
||||
latestVersion: 'v0.1.1'
|
||||
releaseDate: '2026-05-18'
|
||||
latestVersion: 'v0.1.3'
|
||||
releaseDate: '2026-05-23'
|
||||
license: 'MIT'
|
||||
language: 'Rust'
|
||||
lastUpdated: '2026-05-18'
|
||||
lastUpdated: '2026-05-23'
|
||||
recommended: true
|
||||
featured: true
|
||||
order: 4
|
||||
@@ -88,23 +98,23 @@ color: '#8B5CF6'
|
||||
downloads:
|
||||
- platform: 'Windows'
|
||||
arch: 'x64'
|
||||
url: 'https://file.shenjianl.cn/softwore/DeviceDeck/v0.1.1/DeviceDeck-v0.1.1-windows-x64.exe'
|
||||
size: '17.5 MB'
|
||||
url: 'https://file.shenjianl.cn/softwore/DeviceDeck/v0.1.3/DeviceDeck-v0.1.3-windows-x64.exe'
|
||||
size: '18.31 MB'
|
||||
sha256: ''
|
||||
- platform: 'macOS'
|
||||
arch: 'Apple Silicon'
|
||||
url: 'https://file.shenjianl.cn/softwore/DeviceDeck/v0.1.1/DeviceDeck-v0.1.1-macos-aarch64.dmg'
|
||||
size: '35.8 MB'
|
||||
url: 'https://file.shenjianl.cn/softwore/DeviceDeck/v0.1.3/DeviceDeck-v0.1.3-macos-aarch64.dmg'
|
||||
size: '34.62 MB'
|
||||
sha256: ''
|
||||
- platform: 'macOS'
|
||||
arch: 'Intel'
|
||||
url: 'https://file.shenjianl.cn/softwore/DeviceDeck/v0.1.1/DeviceDeck-v0.1.1-macos-x64.dmg'
|
||||
size: '36.0 MB'
|
||||
url: 'https://file.shenjianl.cn/softwore/DeviceDeck/v0.1.3/DeviceDeck-v0.1.3-macos-x64.dmg'
|
||||
size: '34.9 MB'
|
||||
sha256: ''
|
||||
- platform: 'Linux'
|
||||
arch: 'x64'
|
||||
url: 'https://file.shenjianl.cn/softwore/DeviceDeck/v0.1.1/DeviceDeck-v0.1.1-linux-x64.AppImage'
|
||||
size: '98.8 MB'
|
||||
url: 'https://file.shenjianl.cn/softwore/DeviceDeck/v0.1.3/DeviceDeck-v0.1.3-linux-x64.AppImage'
|
||||
size: '99.9 MB'
|
||||
sha256: ''
|
||||
roadmap:
|
||||
done:
|
||||
@@ -123,6 +133,11 @@ roadmap:
|
||||
- 'WiFi 文件传输'
|
||||
- '环境检测'
|
||||
- '首次启动欢迎引导'
|
||||
- 'WiFi 文件传输实时事件推送'
|
||||
- '分片上传与断点续传'
|
||||
- '传输历史记录'
|
||||
- '批量下载'
|
||||
- '文件预览'
|
||||
doing:
|
||||
- '多设备同时投屏'
|
||||
- '脚本录制回放'
|
||||
@@ -130,6 +145,38 @@ roadmap:
|
||||
- 'iOS 设备支持'
|
||||
- '自动化测试集成'
|
||||
changelog:
|
||||
- version: 'v0.1.3'
|
||||
date: '2026-05-23'
|
||||
changes:
|
||||
zh:
|
||||
- '新增 WebSocket 实时文件事件通知'
|
||||
- '新增文件预览支持,扩展 MIME 类型识别'
|
||||
- '新增分片上传与断点续传(SHA-256 校验)'
|
||||
- '新增传输历史记录追踪'
|
||||
- '新增批量下载端点'
|
||||
- '新增文件筛选/排序下拉框自定义组件'
|
||||
- 'WiFi 传输模块大幅增强,引入 tokio broadcast channel 驱动事件广播'
|
||||
en:
|
||||
- 'Added WebSocket real-time file event notifications'
|
||||
- 'Added file preview with extended MIME type recognition'
|
||||
- 'Added chunked upload with resume (SHA-256 verification)'
|
||||
- 'Added transfer history tracking'
|
||||
- 'Added batch download endpoint'
|
||||
- 'Added custom file filter/sort dropdown component'
|
||||
- 'Major WiFi transfer module enhancement with tokio broadcast channel'
|
||||
- version: 'v0.1.2'
|
||||
date: '2026-05-22'
|
||||
changes:
|
||||
zh:
|
||||
- '新增项目官方网站(React 19 + Vite)'
|
||||
- '新增 WiFi 文件传输独立 Web 页面'
|
||||
- '新增 GitHub Actions 自动部署工作流'
|
||||
- '优化所有平台图标文件体积'
|
||||
en:
|
||||
- 'Added official project website (React 19 + Vite)'
|
||||
- 'Added standalone WiFi file transfer web page'
|
||||
- 'Added GitHub Actions auto-deploy workflow'
|
||||
- 'Optimized all platform icon file sizes'
|
||||
- version: 'v0.1.1'
|
||||
date: '2026-05-18'
|
||||
changes:
|
||||
|
||||
@@ -4,11 +4,11 @@ displayName:
|
||||
zh: 'React Docs UI'
|
||||
en: 'React Docs UI'
|
||||
slogan:
|
||||
zh: '基于 React 的文档组件库与站点生成器'
|
||||
en: 'React-based documentation component library & site generator'
|
||||
zh: '配置驱动的 React 文档站点组件库与脚手架'
|
||||
en: 'Configuration-driven React documentation site components & scaffolding'
|
||||
description:
|
||||
zh: 'react-docs-ui 是一套用于构建文档站点的 React 组件库,配合 create-react-docs-ui 脚手架可以快速搭建类似 Nextra / Docusaurus 风格的文档网站。支持 MDX、全文搜索、版本切换和主题定制。'
|
||||
en: 'react-docs-ui is a React component library for building documentation sites. Paired with create-react-docs-ui scaffolding, it quickly sets up Nextra/Docusaurus-style docs sites. Supports MDX, full-text search, version switching, and theme customization.'
|
||||
zh: 'react-docs-ui 是一套 React 文档站点 UI 组件库,配合 create-react-docs-ui 脚手架可快速搭建 Nextra / Docusaurus 风格的文档网站。基于 site.yaml 配置驱动,支持 MD/MDX、Shiki 代码高亮、全文搜索、版本切换、深浅主题、命令菜单、国际化、Mermaid 图表、KaTeX 数学公式、面包屑导航、RSS Feed、Sitemap 生成、PWA 支持、后端集成(认证、评论、书签、分析统计)、PDF/DOCX 导出等功能,并内置 CLI 工具链(搜索索引、llms.txt、changelog 索引生成)。'
|
||||
en: 'react-docs-ui is a React component library for building documentation sites. Paired with create-react-docs-ui scaffolding, it quickly sets up Nextra/Docusaurus-style docs. Configuration-driven via site.yaml, supporting MD/MDX, Shiki syntax highlighting, full-text search, version switching, light/dark themes, command menu, i18n, Mermaid diagrams, KaTeX math, breadcrumbs, RSS Feed, Sitemap generation, PWA, backend integration (auth, comments, bookmarks, analytics), PDF/DOCX export, and built-in CLI toolchain (search index, llms.txt, changelog index generation).'
|
||||
type:
|
||||
- 'library'
|
||||
- 'devtool'
|
||||
@@ -17,89 +17,83 @@ platforms:
|
||||
- 'web'
|
||||
- 'npm'
|
||||
techStack:
|
||||
- 'React'
|
||||
- 'React 19'
|
||||
- 'TypeScript'
|
||||
- 'MDX'
|
||||
- 'TailwindCSS'
|
||||
- 'Vite'
|
||||
- 'TailwindCSS 4'
|
||||
- 'shadcn/ui'
|
||||
- 'Radix UI'
|
||||
- 'MDX'
|
||||
- 'Shiki'
|
||||
- 'react-markdown'
|
||||
- 'Mermaid'
|
||||
- 'KaTeX'
|
||||
- 'FlexSearch'
|
||||
- 'next-themes'
|
||||
- 'cmdk'
|
||||
- 'lucide-react'
|
||||
- 'jsPDF'
|
||||
- 'Docx'
|
||||
features:
|
||||
zh:
|
||||
- 'MDX 支持'
|
||||
- '全文搜索'
|
||||
- '版本切换'
|
||||
- '主题定制'
|
||||
- '响应式布局'
|
||||
- 'API 文档生成'
|
||||
- '代码高亮'
|
||||
- '国际化'
|
||||
- '配置驱动(site.yaml),配套 create-react-docs-ui 一键脚手架快速搭建文档站点'
|
||||
- 'MD/MDX 渲染(GFM 扩展语法、Tabs、自定义图片组件)+ Shiki 代码高亮(100+ 主题)'
|
||||
- '全文搜索(FlexSearch 索引 + Cmd+K 命令菜单)'
|
||||
- '文档多版本控制与切换'
|
||||
- 'Mermaid 图表 + KaTeX 数学公式渲染'
|
||||
- 'SEO 与内容发现(元标签自动注入、RSS Feed、Sitemap、llms.txt 生成)'
|
||||
- '深色/浅色/跟随系统主题、国际化(多语言路由)、PWA 支持'
|
||||
- '导航体验:面包屑、目录导航(TOC)、上下文菜单、阅读进度条'
|
||||
- 'Changelog / Release Notes 页面模块与用户反馈'
|
||||
- '后端集成:用户认证(邮箱 + OAuth)、评论系统(线程回复)、书签、分析统计'
|
||||
- 'PDF / DOCX 文档导出'
|
||||
- '内置 CLI 工具链(搜索索引、changelog 索引、sitemap、feed 生成)'
|
||||
en:
|
||||
- 'MDX support'
|
||||
- 'Full-text search'
|
||||
- 'Version switching'
|
||||
- 'Theme customization'
|
||||
- 'Responsive layout'
|
||||
- 'API doc generation'
|
||||
- 'Code highlighting'
|
||||
- 'i18n'
|
||||
- 'Configuration-driven (site.yaml) with create-react-docs-ui one-command scaffolding'
|
||||
- 'MD/MDX rendering (GFM, Tabs, custom image components) + Shiki syntax highlighting (100+ themes)'
|
||||
- 'Full-text search (FlexSearch index + Cmd+K command menu)'
|
||||
- 'Multi-version documentation control & switching'
|
||||
- 'Mermaid diagrams + KaTeX math formula rendering'
|
||||
- 'SEO & content discovery (meta tag injection, RSS Feed, Sitemap, llms.txt generation)'
|
||||
- 'Dark/Light/Follow system theme, internationalization (multi-language routing), PWA support'
|
||||
- 'Navigation: breadcrumbs, Table of Contents (TOC), context menu, reading progress bar'
|
||||
- 'Changelog / Release Notes page module with user feedback'
|
||||
- 'Backend integration: auth (email + OAuth), threaded comments, bookmarks, analytics'
|
||||
- 'PDF / DOCX document export'
|
||||
- 'Built-in CLI toolchain (search index, changelog index, sitemap, feed generation)'
|
||||
tags:
|
||||
- 'Documentation'
|
||||
- 'React'
|
||||
- 'NPM'
|
||||
- 'MDX'
|
||||
- 'CLI'
|
||||
- 'Component Library'
|
||||
- 'Static Site'
|
||||
- 'TypeScript'
|
||||
- 'Vite'
|
||||
- 'TailwindCSS'
|
||||
icon: 'BookOpen'
|
||||
logo: '/logos/react-docs-ui.png'
|
||||
repoUrl: 'https://github.com/shenjianZ/react-docs-ui'
|
||||
docsUrl: 'https://github.com/shenjianZ/react-docs-ui#readme'
|
||||
websiteUrl: 'https://shenjianz.github.io/react-docs-ui'
|
||||
docsUrl: 'https://react-docs-ui.shenjianl.cn/'
|
||||
npmUrl: 'https://www.npmjs.com/package/react-docs-ui'
|
||||
latestVersion: 'v0.5.2'
|
||||
releaseDate: '2026-05-10'
|
||||
latestVersion: 'v0.9.2'
|
||||
releaseDate: '2025-08-10'
|
||||
license: 'MIT'
|
||||
language: 'TypeScript'
|
||||
lastUpdated: '2026-05-18'
|
||||
lastUpdated: '2026-05-05'
|
||||
recommended: true
|
||||
featured: true
|
||||
order: 5
|
||||
color: '#06B6D4'
|
||||
downloads: []
|
||||
roadmap:
|
||||
done:
|
||||
- '基础组件库'
|
||||
- 'MDX 渲染'
|
||||
- '侧边栏导航'
|
||||
- '搜索功能'
|
||||
- '主题系统'
|
||||
doing:
|
||||
- 'API 文档自动生成'
|
||||
- '版本切换'
|
||||
- '性能优化'
|
||||
planned:
|
||||
- '插件系统'
|
||||
- '评论集成'
|
||||
- '多语言路由'
|
||||
- 'CLI 工具'
|
||||
changelog:
|
||||
- version: 'v0.5.2'
|
||||
date: '2026-05-10'
|
||||
changes:
|
||||
zh:
|
||||
- '修复搜索索引构建错误'
|
||||
- '新增代码块复制按钮'
|
||||
- '优化移动端导航'
|
||||
en:
|
||||
- 'Fixed search index build error'
|
||||
- 'Added code copy button'
|
||||
- 'Improved mobile navigation'
|
||||
- version: 'v0.5.0'
|
||||
date: '2026-04-01'
|
||||
changes:
|
||||
zh:
|
||||
- '新增主题定制'
|
||||
- '支持 MDX 嵌入组件'
|
||||
- '新增面包屑导航'
|
||||
en:
|
||||
- 'Added theme customization'
|
||||
- 'MDX embedded components'
|
||||
- 'Breadcrumb navigation'
|
||||
architecture:
|
||||
zh: 'MDX 源文件 → Vite 构建 → React 组件渲染 → 静态文档站点'
|
||||
en: 'MDX Sources → Vite Build → React Component Rendering → Static Documentation Site'
|
||||
quickStart:
|
||||
zh:
|
||||
- 'pnpm create react-docs-ui@latest my-docs'
|
||||
- 'cd my-docs && pnpm install'
|
||||
- 'pnpm dev'
|
||||
en:
|
||||
- 'pnpm create react-docs-ui@latest my-docs'
|
||||
- 'cd my-docs && pnpm install'
|
||||
- 'pnpm dev'
|
||||
|
||||
@@ -84,7 +84,8 @@ tags:
|
||||
icon: 'Terminal'
|
||||
logo: '/logos/ssh-terminal.png'
|
||||
repoUrl: 'https://github.com/shenjianZ/ssh-terminal'
|
||||
docsUrl: 'https://github.com/shenjianZ/ssh-terminal#readme'
|
||||
websiteUrl: 'https://shenjianz.github.io/ssh-terminal'
|
||||
docsUrl: 'http://st-docs.shenjianl.cn'
|
||||
latestVersion: 'v1.2.1'
|
||||
releaseDate: '2026-03-04'
|
||||
license: 'MIT'
|
||||
@@ -167,7 +168,20 @@ architecture:
|
||||
zh: '前端 (React 19 + xterm.js + Zustand + shadcn/ui) → Tauri 2 Commands → Rust 服务层 (russh + r2d2_sqlite + aes-gcm) → SQLite / 远程服务器'
|
||||
en: 'Frontend (React 19 + xterm.js + Zustand + shadcn/ui) → Tauri 2 Commands → Rust Service Layer (russh + r2d2_sqlite + aes-gcm) → SQLite / Remote Server'
|
||||
|
||||
screenshots: []
|
||||
screenshots:
|
||||
- '/screenshots/ssh-terminal/terminal-main.png'
|
||||
- '/screenshots/ssh-terminal/session-manager.png'
|
||||
- '/screenshots/ssh-terminal/aichat-page.png'
|
||||
- '/screenshots/ssh-terminal/terminal-ai-short-page.png'
|
||||
- '/screenshots/ssh-terminal/terminal-nl-to-cmd.png'
|
||||
- '/screenshots/ssh-terminal/sftp-manager.png'
|
||||
- '/screenshots/ssh-terminal/recording-manager.png'
|
||||
- '/screenshots/ssh-terminal/setting-main.png'
|
||||
- '/screenshots/ssh-terminal/setting-terminal.png'
|
||||
- '/screenshots/ssh-terminal/setting-ai.png'
|
||||
- '/screenshots/ssh-terminal/setting-keybingdings.png'
|
||||
- '/screenshots/ssh-terminal/setting-reacording.png'
|
||||
- '/screenshots/ssh-terminal/setting-about.png'
|
||||
|
||||
installGuide:
|
||||
zh:
|
||||
|
||||
@@ -110,6 +110,21 @@ export default function ProjectDetailPage() {
|
||||
<p className="detail-prose">{bi(p.description)}</p>
|
||||
</div>
|
||||
|
||||
{/* Quick Start */}
|
||||
{p.quickStart && p.quickStart[lang] && p.quickStart[lang].length > 0 && (
|
||||
<div className="detail-section">
|
||||
<h2 className="detail-section-title">{t('detail.quickStart')}</h2>
|
||||
<div className="quickstart-commands">
|
||||
{p.quickStart[lang].map((cmd, i) => (
|
||||
<div key={i} className="quickstart-line">
|
||||
<span className="quickstart-prompt">$</span>
|
||||
<code className="quickstart-cmd">{cmd}</code>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Features */}
|
||||
<div className="detail-section">
|
||||
<h2 className="detail-section-title">{t('detail.features')}</h2>
|
||||
|
||||
@@ -114,6 +114,10 @@
|
||||
padding-bottom: 40px;
|
||||
}
|
||||
|
||||
.detail-body > * {
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.detail-sidebar {
|
||||
position: sticky;
|
||||
top: calc(var(--nav-height) + 32px);
|
||||
@@ -288,6 +292,12 @@
|
||||
background: oklch(58% 0.22 45 / 14%);
|
||||
}
|
||||
|
||||
@media (max-width: 767px) {
|
||||
.feature-tag {
|
||||
white-space: normal;
|
||||
}
|
||||
}
|
||||
|
||||
/* Screenshot carousel */
|
||||
.screenshot-carousel {
|
||||
position: relative;
|
||||
@@ -619,6 +629,48 @@
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
/* ── Quick start commands ─────────────────────────────── */
|
||||
.quickstart-commands {
|
||||
background: oklch(12% 0.02 270);
|
||||
border: 1px solid oklch(74% 0.2 45 / 12%);
|
||||
border-radius: var(--radius-lg);
|
||||
padding: 18px 20px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 6px;
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
||||
:root.light .quickstart-commands {
|
||||
background: oklch(97% 0.005 270);
|
||||
border-color: oklch(58% 0.22 45 / 12%);
|
||||
}
|
||||
|
||||
.quickstart-line {
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
gap: 10px;
|
||||
font-size: 13px;
|
||||
line-height: 1.7;
|
||||
}
|
||||
|
||||
.quickstart-prompt {
|
||||
color: var(--accent);
|
||||
font-weight: 700;
|
||||
flex-shrink: 0;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.quickstart-cmd {
|
||||
font-family: var(--font-mono);
|
||||
color: oklch(90% 0.01 270);
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
:root.light .quickstart-cmd {
|
||||
color: oklch(25% 0.02 270);
|
||||
}
|
||||
|
||||
/* ── Project selector (for roadmap/changelog) ────────── */
|
||||
.project-selector {
|
||||
display: flex;
|
||||
|
||||
@@ -105,4 +105,208 @@
|
||||
|
||||
.footer-policy-link {
|
||||
color: var(--muted);
|
||||
cursor: pointer;
|
||||
background: none;
|
||||
border: none;
|
||||
font: inherit;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.footer-policy-link:hover {
|
||||
color: var(--accent);
|
||||
}
|
||||
|
||||
/* ── Policy Modal ────────────────────────────────────── */
|
||||
.policy-overlay {
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
z-index: 9999;
|
||||
background: oklch(0% 0 0 / 70%);
|
||||
backdrop-filter: blur(8px);
|
||||
-webkit-backdrop-filter: blur(8px);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 24px;
|
||||
animation: policy-fade-in 0.2s ease;
|
||||
}
|
||||
|
||||
@keyframes policy-fade-in {
|
||||
from { opacity: 0; }
|
||||
to { opacity: 1; }
|
||||
}
|
||||
|
||||
.policy-modal {
|
||||
width: 100%;
|
||||
max-width: 600px;
|
||||
max-height: 80vh;
|
||||
background: var(--bg);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: var(--radius-lg);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
box-shadow: 0 16px 48px oklch(0% 0 0 / 40%);
|
||||
animation: policy-zoom-in 0.25s ease;
|
||||
}
|
||||
|
||||
@keyframes policy-zoom-in {
|
||||
from { transform: scale(0.95); opacity: 0; }
|
||||
to { transform: scale(1); opacity: 1; }
|
||||
}
|
||||
|
||||
.policy-modal-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 20px 24px;
|
||||
border-bottom: 1px solid var(--border);
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.policy-modal-header-left {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
color: var(--accent);
|
||||
}
|
||||
|
||||
.policy-modal-title {
|
||||
font-size: 18px;
|
||||
font-weight: 700;
|
||||
letter-spacing: -0.01em;
|
||||
}
|
||||
|
||||
.policy-modal-close {
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
border-radius: 50%;
|
||||
border: 1px solid var(--border);
|
||||
background: transparent;
|
||||
color: var(--muted);
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
transition: all var(--transition);
|
||||
}
|
||||
|
||||
.policy-modal-close:hover {
|
||||
color: var(--fg);
|
||||
background: oklch(74% 0.2 45 / 8%);
|
||||
border-color: oklch(74% 0.2 45 / 20%);
|
||||
}
|
||||
|
||||
.policy-modal-body {
|
||||
padding: 24px;
|
||||
overflow-y: auto;
|
||||
font-size: 14px;
|
||||
line-height: 1.8;
|
||||
color: var(--fg);
|
||||
}
|
||||
|
||||
.policy-modal-body p {
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.policy-modal-body p:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
/* Structured content layout */
|
||||
.policy-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 20px;
|
||||
}
|
||||
|
||||
.policy-badge {
|
||||
display: inline-flex;
|
||||
align-self: flex-start;
|
||||
padding: 4px 14px;
|
||||
border-radius: 99px;
|
||||
font-size: 13px;
|
||||
font-weight: 600;
|
||||
letter-spacing: 0.03em;
|
||||
background: oklch(74% 0.2 45 / 10%);
|
||||
color: var(--accent);
|
||||
border: 1px solid oklch(74% 0.2 45 / 15%);
|
||||
}
|
||||
|
||||
.policy-intro {
|
||||
font-size: 14px;
|
||||
line-height: 1.7;
|
||||
color: var(--muted);
|
||||
padding-bottom: 8px;
|
||||
border-bottom: 1px solid var(--border);
|
||||
}
|
||||
|
||||
.policy-section h4 {
|
||||
font-size: 15px;
|
||||
font-weight: 700;
|
||||
margin-bottom: 8px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.policy-num {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 22px;
|
||||
height: 22px;
|
||||
border-radius: 50%;
|
||||
background: oklch(74% 0.2 45 / 10%);
|
||||
color: var(--accent);
|
||||
font-size: 12px;
|
||||
font-weight: 700;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.policy-section p {
|
||||
font-size: 14px;
|
||||
line-height: 1.75;
|
||||
color: var(--fg);
|
||||
}
|
||||
|
||||
.policy-section a {
|
||||
color: var(--accent);
|
||||
text-decoration: underline;
|
||||
text-underline-offset: 2px;
|
||||
}
|
||||
|
||||
.policy-section a:hover {
|
||||
text-decoration-thickness: 2px;
|
||||
}
|
||||
|
||||
.policy-highlight {
|
||||
padding: 14px 16px;
|
||||
border-radius: var(--radius-md);
|
||||
background: oklch(74% 0.2 45 / 5%);
|
||||
border-left: 3px solid var(--accent);
|
||||
font-size: 13.5px;
|
||||
line-height: 1.75;
|
||||
}
|
||||
|
||||
.policy-highlight strong {
|
||||
color: var(--accent);
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.policy-muted {
|
||||
font-size: 12.5px;
|
||||
line-height: 1.7;
|
||||
color: var(--muted);
|
||||
}
|
||||
|
||||
.policy-footer {
|
||||
font-size: 12px;
|
||||
color: var(--muted);
|
||||
padding-top: 12px;
|
||||
border-top: 1px solid var(--border);
|
||||
}
|
||||
|
||||
.policy-footer a {
|
||||
color: var(--accent);
|
||||
}
|
||||
|
||||
@@ -102,6 +102,7 @@ export interface Project {
|
||||
changelog?: ChangelogEntry[];
|
||||
architecture?: BilingualText;
|
||||
screenshots?: string[];
|
||||
quickStart?: BilingualArray;
|
||||
installGuide?: BilingualInstallGuide;
|
||||
}
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@ export default defineConfig({
|
||||
assetsInlineLimit: 4096,
|
||||
},
|
||||
server: {
|
||||
host: true,
|
||||
warmup: {
|
||||
clientFiles: ['./src/data/loader.ts'],
|
||||
},
|
||||
|
||||