diff --git a/.claude/settings.local.json b/.claude/settings.local.json index 18c86aa..4496928 100644 --- a/.claude/settings.local.json +++ b/.claude/settings.local.json @@ -11,7 +11,14 @@ "mcp__Claude_Preview__preview_start", "Bash(pnpm dev *)", "Bash(rtk read *)", - "Bash(rtk grep *)" + "Bash(rtk grep *)", + "Bash(rtk git *)", + "Bash(gh repo *)", + "Bash(gh release *)", + "Bash(gh api *)", + "Bash(echo \"exit: $?\")", + "Bash(rtk npx *)", + "Bash(rtk tsc *)" ] } } diff --git a/docs/create-project.md b/docs/create-project.md index e518fa7..3fe83f1 100644 --- a/docs/create-project.md +++ b/docs/create-project.md @@ -12,7 +12,8 @@ | 2 | `src/utils/iconRegistry.ts` | 仅当使用新图标时 | | 3 | `src/data/categories.yaml` | 仅当新增分类时 | | 4 | `src/data/statuses.yaml` | 仅当新增状态时 | -| 5 | `public/screenshots/` | 仅当有截图时 | +| 5 | `public/logos/` | 仅当有项目 Logo 时 | +| 6 | `public/screenshots/` | 仅当有截图时 | **核心原则:** 只需创建一个 YAML 文件,项目就会自动出现在网站上。`loader.ts` 使用 `import.meta.glob('./projects/*.yaml')` 自动扫描该目录,无需手动注册。 @@ -101,6 +102,11 @@ tags: # 如果需要新图标,见"步骤二" icon: 'Terminal' +# 项目 Logo 图片(可选,支持 SVG/PNG/JPG) +# 图片放在 public/logos/ 目录下,路径相对于 public 目录 +# 若设置了 logo,卡片和详情页会优先展示 Logo 图片,否则回退到上面的 lucide 图标 +# logo: '/logos/my-new-app.png' + # GitHub 仓库地址(必须) repoUrl: 'https://github.com/shenjianZ/my-new-app' @@ -115,8 +121,6 @@ docsUrl: 'https://github.com/shenjianZ/my-new-app#readme' latestVersion: 'v1.0.0' releaseDate: '2026-05-22' license: 'MIT' -stars: 10 -forks: 2 language: 'TypeScript' lastUpdated: '2026-05-22' @@ -189,6 +193,39 @@ architecture: # screenshots: # - '/screenshots/my-new-app/main.png' # - '/screenshots/my-new-app/settings.png' + +# ========== 安装指南(可选) ========== +# 每个项目生产的安装包不同,按实际包格式填写即可 +# 会以紧凑的单行提示展示在"下载安装"区域内 +# 不填写则使用默认的通用安装说明 + +installGuide: + zh: + - platform: 'Windows' + icon: '🪟' + format: '.exe' + tip: 'SmartScreen 拦截?点击"更多信息" → "仍要运行"' + - platform: 'macOS' + icon: '🍎' + format: '.dmg' + tip: '提示已损坏?终端运行: xattr -dr com.apple.quarantine /Applications/MyApp.app' + - platform: 'Linux' + icon: '🐧' + format: '.AppImage' + tip: 'chmod +x MyApp-*.AppImage && ./MyApp-*.AppImage' + en: + - platform: 'Windows' + icon: '🪟' + format: '.exe' + tip: 'SmartScreen blocked? Click "More info" → "Run anyway"' + - platform: 'macOS' + icon: '🍎' + format: '.dmg' + tip: '"Damaged" error? Run: xattr -dr com.apple.quarantine /Applications/MyApp.app' + - platform: 'Linux' + icon: '🐧' + format: '.AppImage' + tip: 'chmod +x MyApp-*.AppImage && ./MyApp-*.AppImage' ``` --- diff --git a/public/logos/.gitkeep b/public/logos/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/public/logos/quantanote.png b/public/logos/quantanote.png new file mode 100644 index 0000000..cde80a5 Binary files /dev/null and b/public/logos/quantanote.png differ diff --git a/public/screenshots/quantanote/accoun-login.png b/public/screenshots/quantanote/accoun-login.png new file mode 100644 index 0000000..3bcad22 Binary files /dev/null and b/public/screenshots/quantanote/accoun-login.png differ diff --git a/public/screenshots/quantanote/account-profile.png b/public/screenshots/quantanote/account-profile.png new file mode 100644 index 0000000..98dc3ec Binary files /dev/null and b/public/screenshots/quantanote/account-profile.png differ diff --git a/public/screenshots/quantanote/account-register.png b/public/screenshots/quantanote/account-register.png new file mode 100644 index 0000000..1ae8843 Binary files /dev/null and b/public/screenshots/quantanote/account-register.png differ diff --git a/public/screenshots/quantanote/account.png b/public/screenshots/quantanote/account.png new file mode 100644 index 0000000..cf74ec2 Binary files /dev/null and b/public/screenshots/quantanote/account.png differ diff --git a/public/screenshots/quantanote/library.png b/public/screenshots/quantanote/library.png new file mode 100644 index 0000000..8a78977 Binary files /dev/null and b/public/screenshots/quantanote/library.png differ diff --git a/public/screenshots/quantanote/note-edit.png b/public/screenshots/quantanote/note-edit.png new file mode 100644 index 0000000..509b2df Binary files /dev/null and b/public/screenshots/quantanote/note-edit.png differ diff --git a/public/screenshots/quantanote/note-preview.png b/public/screenshots/quantanote/note-preview.png new file mode 100644 index 0000000..93f04fc Binary files /dev/null and b/public/screenshots/quantanote/note-preview.png differ diff --git a/public/screenshots/quantanote/note-version.png b/public/screenshots/quantanote/note-version.png new file mode 100644 index 0000000..419ed79 Binary files /dev/null and b/public/screenshots/quantanote/note-version.png differ diff --git a/public/screenshots/quantanote/search-cmd.png b/public/screenshots/quantanote/search-cmd.png new file mode 100644 index 0000000..1e92d00 Binary files /dev/null and b/public/screenshots/quantanote/search-cmd.png differ diff --git a/public/screenshots/quantanote/settings-about.png b/public/screenshots/quantanote/settings-about.png new file mode 100644 index 0000000..e27b25c Binary files /dev/null and b/public/screenshots/quantanote/settings-about.png differ diff --git a/public/screenshots/quantanote/settings-appearance.png b/public/screenshots/quantanote/settings-appearance.png new file mode 100644 index 0000000..6e955ec Binary files /dev/null and b/public/screenshots/quantanote/settings-appearance.png differ diff --git a/public/screenshots/quantanote/settings-data.png b/public/screenshots/quantanote/settings-data.png new file mode 100644 index 0000000..a221760 Binary files /dev/null and b/public/screenshots/quantanote/settings-data.png differ diff --git a/public/screenshots/quantanote/settings-font.png b/public/screenshots/quantanote/settings-font.png new file mode 100644 index 0000000..b8e8526 Binary files /dev/null and b/public/screenshots/quantanote/settings-font.png differ diff --git a/public/screenshots/quantanote/settings-sync.png b/public/screenshots/quantanote/settings-sync.png new file mode 100644 index 0000000..0b9ac5f Binary files /dev/null and b/public/screenshots/quantanote/settings-sync.png differ diff --git a/public/screenshots/quantanote/topbar-more.png b/public/screenshots/quantanote/topbar-more.png new file mode 100644 index 0000000..4fbe47c Binary files /dev/null and b/public/screenshots/quantanote/topbar-more.png differ diff --git a/public/screenshots/quantanote/workspace.png b/public/screenshots/quantanote/workspace.png new file mode 100644 index 0000000..29ebaa4 Binary files /dev/null and b/public/screenshots/quantanote/workspace.png differ diff --git a/src/components/FeaturedCard.tsx b/src/components/FeaturedCard.tsx index e40dc04..df84414 100644 --- a/src/components/FeaturedCard.tsx +++ b/src/components/FeaturedCard.tsx @@ -1,5 +1,4 @@ import { Link } from 'react-router-dom'; -import { Star } from 'lucide-react'; import { useI18n } from '../hooks/useI18n'; import { siteData } from '../data/siteData'; import { getIcon } from '../utils/iconRegistry'; @@ -20,7 +19,12 @@ export default function FeaturedCard({ project }: FeaturedCardProps) { className="project-card project-card-link" >
-
{IconComponent && }
+
+ {project.logo + ? {project.name} + : (IconComponent && ) + } +
{project.displayName[lang] || project.name} @@ -43,9 +47,6 @@ export default function FeaturedCard({ project }: FeaturedCardProps) {
- - {project.stars} - {project.latestVersion}
diff --git a/src/components/ProjectCard.tsx b/src/components/ProjectCard.tsx index 48f30ef..9f430b8 100644 --- a/src/components/ProjectCard.tsx +++ b/src/components/ProjectCard.tsx @@ -1,5 +1,5 @@ import { Link } from 'react-router-dom'; -import { ExternalLink, Download, BookOpen, Star } from 'lucide-react'; +import { ExternalLink, Download, BookOpen, Globe } from 'lucide-react'; import { useI18n } from '../hooks/useI18n'; import { siteData } from '../data/siteData'; import { getIcon } from '../utils/iconRegistry'; @@ -17,7 +17,12 @@ export default function ProjectCard({ project }: ProjectCardProps) { return (
-
{IconComponent && }
+
+ {project.logo + ? {project.name} + : (IconComponent && ) + } +
{project.displayName[lang] || project.name} @@ -44,12 +49,6 @@ export default function ProjectCard({ project }: ProjectCardProps) { ))}
-
- - {project.stars} - -
-
GitHub @@ -59,6 +58,16 @@ export default function ProjectCard({ project }: ProjectCardProps) { {t('common.download')} )} + {project.websiteUrl && ( + + {t('detail.website')} + + )} {project.docsUrl && ( (null); const scrollRef = useRef(null); const scrollTo = useCallback((i: number) => { @@ -18,6 +21,16 @@ export default function ScreenshotCarousel({ screenshots }: ScreenshotCarouselPr }); }, []); + const prev = useCallback(() => { + if (!screenshots) return; + scrollTo(active > 0 ? active - 1 : screenshots.length - 1); + }, [active, screenshots, scrollTo]); + + const next = useCallback(() => { + if (!screenshots) return; + scrollTo(active < screenshots.length - 1 ? active + 1 : 0); + }, [active, screenshots, scrollTo]); + useEffect(() => { const el = scrollRef.current; if (!el) return; @@ -36,30 +49,97 @@ export default function ScreenshotCarousel({ screenshots }: ScreenshotCarouselPr return () => observer.disconnect(); }, []); + // 同步 lightbox 切换到轮播 + useEffect(() => { + if (preview === null) return; + scrollTo(preview); + }, [preview, scrollTo]); + + useEffect(() => { + if (preview === null) return; + const onKey = (e: KeyboardEvent) => { + if (e.key === 'Escape') setPreview(null); + if (e.key === 'ArrowLeft') setPreview((p) => p !== null ? (p > 0 ? p - 1 : screenshots!.length - 1) : null); + if (e.key === 'ArrowRight') setPreview((p) => p !== null ? (p < screenshots!.length - 1 ? p + 1 : 0) : null); + }; + document.addEventListener('keydown', onKey); + document.body.style.overflow = 'hidden'; + return () => { + document.removeEventListener('keydown', onKey); + document.body.style.overflow = ''; + }; + }, [preview, screenshots]); + if (!screenshots || screenshots.length === 0) { return null; } return ( -
-
- {screenshots.map((src, i) => ( -
- {`Screenshot -
- ))} -
- {screenshots.length > 1 && ( -
- {screenshots.map((_, i) => ( - + )} +
+ {screenshots.map((src, i) => ( +
setPreview(i)}> + {`Screenshot +
))}
+ {screenshots.length > 1 && ( + + )} + {screenshots.length > 1 && ( +
+ {screenshots.map((_, i) => ( +
+ )} +
+ + {preview !== null && createPortal( +
setPreview(null)}> + + {screenshots.length > 1 && ( + + )} + {`Screenshot e.stopPropagation()} + /> + {screenshots.length > 1 && ( + + )} +
{preview + 1} / {screenshots.length}
+
, + document.body )} -
+ ); } diff --git a/src/components/StatsBar.tsx b/src/components/StatsBar.tsx index c00aac0..534fd25 100644 --- a/src/components/StatsBar.tsx +++ b/src/components/StatsBar.tsx @@ -5,13 +5,11 @@ export default function StatsBar() { const { t } = useI18n(); const projects = siteData.projects; - const totalStars = projects.reduce((sum, p) => sum + p.stars, 0); const uniqueTechStacks = new Set(projects.flatMap((p) => p.techStack)).size; const uniquePlatforms = new Set(projects.flatMap((p) => p.platforms)).size; const stats = [ { id: 'projects', value: projects.length, label: t('stats.projects') }, - { id: 'stars', value: totalStars, label: t('stats.stars') }, { id: 'techStack', value: uniqueTechStacks, label: t('stats.techStack') }, { id: 'platforms', value: uniquePlatforms, label: t('stats.platforms') }, ]; diff --git a/src/data/i18n/en.yaml b/src/data/i18n/en.yaml index f3ac4f8..8b6b6b9 100644 --- a/src/data/i18n/en.yaml +++ b/src/data/i18n/en.yaml @@ -8,7 +8,6 @@ hero.cta.github: 'Visit GitHub' hero.cta.download: 'Download Software' hero.cta.docs: 'View Docs' stats.projects: 'Open Source Projects' -stats.stars: 'GitHub Stars' stats.techStack: 'Tech Stacks' stats.platforms: 'Platforms' featured.title: 'Featured Projects' @@ -30,7 +29,6 @@ projects.filter.tech: 'Tech Stack' projects.filter.platform: 'Platform' projects.filter.status: 'Status' projects.sort.updated: 'Recently Updated' -projects.sort.stars: 'Most Stars' projects.sort.name: 'By Name' projects.noResults: 'No matching projects' projects.search: 'Search project name, description, or tags...' @@ -49,6 +47,7 @@ detail.platforms: 'Platforms' detail.status: 'Status' detail.lastUpdate: 'Last Updated' detail.repo: 'GitHub Repo' +detail.website: 'Website' detail.docs: 'Online Docs' detail.release: 'Download Release' detail.installGuide: 'Installation Guide' @@ -119,8 +118,6 @@ common.download: 'Download' common.docs: 'Docs' common.demo: 'Live Demo' common.back: 'Back' -common.stars: 'Stars' -common.forks: 'Forks' common.version: 'Version' common.platform: 'Platform' common.size: 'Size' diff --git a/src/data/i18n/zh.yaml b/src/data/i18n/zh.yaml index 6d0892a..5811828 100644 --- a/src/data/i18n/zh.yaml +++ b/src/data/i18n/zh.yaml @@ -8,7 +8,6 @@ hero.cta.github: '访问 GitHub' hero.cta.download: '下载软件' hero.cta.docs: '查看文档' stats.projects: '开源项目' -stats.stars: 'GitHub Stars' stats.techStack: '技术栈' stats.platforms: '支持平台' featured.title: '重点项目' @@ -30,7 +29,6 @@ projects.filter.tech: '技术栈' projects.filter.platform: '平台' projects.filter.status: '状态' projects.sort.updated: '最近更新' -projects.sort.stars: 'Star 最多' projects.sort.name: '名称排序' projects.noResults: '没有匹配的项目' projects.search: '搜索项目名称、描述或标签...' @@ -49,6 +47,7 @@ detail.platforms: '支持平台' detail.status: '开发状态' detail.lastUpdate: '最后更新' detail.repo: 'GitHub 仓库' +detail.website: '官网' detail.docs: '在线文档' detail.release: '下载 Release' detail.installGuide: '安装说明' @@ -119,8 +118,6 @@ common.download: '下载' common.docs: '文档' common.demo: '在线演示' common.back: '返回' -common.stars: 'Stars' -common.forks: 'Forks' common.version: '版本' common.platform: '平台' common.size: '大小' diff --git a/src/data/projects/billddesk.yaml b/src/data/projects/billddesk.yaml index bb37a65..4ed105f 100644 --- a/src/data/projects/billddesk.yaml +++ b/src/data/projects/billddesk.yaml @@ -44,13 +44,12 @@ tags: - 'WebRTC' - 'Self-hosted' icon: 'Monitor' +logo: '/logos/billddesk.png' repoUrl: 'https://github.com/shenjianZ/billddesk' docsUrl: 'https://github.com/shenjianZ/billddesk#readme' latestVersion: 'v0.8.0' releaseDate: '2026-02-14' license: 'Apache-2.0' -stars: 45 -forks: 9 language: 'TypeScript' lastUpdated: '2026-04-20' recommended: false diff --git a/src/data/projects/codex-manager.yaml b/src/data/projects/codex-manager.yaml index 4db5950..d2cab10 100644 --- a/src/data/projects/codex-manager.yaml +++ b/src/data/projects/codex-manager.yaml @@ -45,13 +45,12 @@ tags: - 'Account Management' - 'Desktop' icon: 'KeyRound' +logo: '/logos/codex-manager.png' repoUrl: 'https://github.com/shenjianZ/codex-manager' docsUrl: 'https://github.com/shenjianZ/codex-manager#readme' latestVersion: 'v0.1.0-beta' releaseDate: '2026-04-28' license: 'MIT' -stars: 34 -forks: 2 language: 'Rust' lastUpdated: '2026-05-05' recommended: false diff --git a/src/data/projects/devicedeck.yaml b/src/data/projects/devicedeck.yaml index 5b5164a..a1138cc 100644 --- a/src/data/projects/devicedeck.yaml +++ b/src/data/projects/devicedeck.yaml @@ -49,13 +49,12 @@ tags: - 'Scrcpy' - 'Debug' icon: 'Smartphone' +logo: '/logos/devicedeck.png' repoUrl: 'https://github.com/shenjianZ/devicedeck' docsUrl: 'https://github.com/shenjianZ/devicedeck#readme' latestVersion: 'v0.3.0' releaseDate: '2026-04-20' license: 'MIT' -stars: 72 -forks: 6 language: 'Rust' lastUpdated: '2026-05-12' recommended: true diff --git a/src/data/projects/news-classifier.yaml b/src/data/projects/news-classifier.yaml index 5297335..d2d6fa5 100644 --- a/src/data/projects/news-classifier.yaml +++ b/src/data/projects/news-classifier.yaml @@ -45,13 +45,12 @@ tags: - 'Classification' - 'API' icon: 'Brain' +logo: '/logos/news-classifier.png' repoUrl: 'https://github.com/shenjianZ/news-classifier' docsUrl: 'https://github.com/shenjianZ/news-classifier#readme' latestVersion: 'v0.1.0' releaseDate: '2025-12-01' license: 'MIT' -stars: 23 -forks: 3 language: 'Python' lastUpdated: '2026-03-15' recommended: false diff --git a/src/data/projects/quantanote.yaml b/src/data/projects/quantanote.yaml index 97eb817..058dd31 100644 --- a/src/data/projects/quantanote.yaml +++ b/src/data/projects/quantanote.yaml @@ -4,15 +4,15 @@ displayName: zh: 'QuantaNote' en: 'QuantaNote' slogan: - zh: '本地优先的跨平台桌面笔记与知识管理工具' - en: 'Local-first cross-platform desktop note & knowledge management tool' + zh: '本地优先的跨平台桌面笔记与知识管理工具 — Markdown 编辑、全文搜索、悬浮球快捷操作' + en: 'Local-first cross-platform desktop note & knowledge management — Markdown editing, full-text search, floating ball quick actions' description: - zh: 'QuantaNote 是一个基于 Tauri 2、Rust 和 React 构建的本地优先桌面笔记软件。面向需要离线使用、Markdown 编辑、资料归档、快速搜索和长期保存笔记的用户。相比传统云笔记,它更强调本地数据控制、轻量启动和跨平台桌面体验。' - en: 'QuantaNote is a local-first desktop note-taking app built with Tauri 2, Rust, and React. Designed for users who need offline Markdown editing, knowledge archiving, fast search, and long-term note storage. Emphasizes local data control, lightweight startup, and cross-platform desktop experience.' + zh: 'QuantaNote 是一个基于 Tauri 2、Rust 和 React 构建的本地优先桌面笔记软件。支持 Markdown 编辑(Vditor IR 模式)、FTS5 全文搜索(含中文子串)、标签管理、版本历史 Diff 对比、附件预览、导入导出、自动备份、悬浮球快捷操作等功能。所有数据存储在本地 SQLite,强调数据主权和轻量跨平台体验。支持云同步(开发中)。' + en: 'QuantaNote is a local-first desktop note app built with Tauri 2, Rust, and React. Features include Markdown editing (Vditor IR mode), FTS5 full-text search with Chinese substring support, tag management, version history with diff comparison, attachment preview, import/export, auto backup, and floating ball quick actions. All data is stored in local SQLite, emphasizing data ownership and lightweight cross-platform experience. Cloud sync is under development.' type: - 'desktop' - 'devtool' -status: 'active' +status: 'maintained' platforms: - 'windows' - 'macos' @@ -20,50 +20,63 @@ platforms: techStack: - 'Tauri 2' - 'Rust' - - 'React' + - 'React 19' - 'TypeScript' - - 'SQLite' - - 'TailwindCSS' + - 'SQLite (rusqlite 0.35)' + - 'TailwindCSS 4' + - 'Vditor' + - 'Zustand' + - 'i18next' features: zh: - - 'Markdown 编辑' - - '本地 SQLite 存储' - - '全文搜索' - - '标签管理' - - '附件预览' - - '版本历史' - - '导入导出' - - '自动备份' - - '主题切换' - - '系统托盘' + - 'Markdown 编辑器(Vditor IR 模式)' + - '全文搜索(FTS5 + trigram 双引擎,支持中文子串)' + - '标签管理(CRUD + 多对多关联)' + - '命令面板(Ctrl+K 全局快速搜索)' + - '版本历史与 Diff 对比' + - '附件管理(图片/音频/视频/PDF 预览)' + - '数据导入导出(JSON / ZIP 可选)' + - '定时自动备份' + - '深色/浅色主题 + 自定义强调色' + - '系统托盘 + 开机自启动' + - '悬浮球快捷操作(径向菜单)' + - '快速笔记独立窗口' + - '中英文国际化' - '云同步(开发中)' en: - - 'Markdown editing' - - 'Local SQLite storage' - - 'Full-text search' - - 'Tag management' - - 'Attachment preview' - - 'Version history' - - 'Import/export' - - 'Auto backup' - - 'Theme switching' - - 'System tray' + - 'Markdown editor (Vditor IR mode)' + - 'Full-text search (FTS5 + trigram, Chinese substring)' + - 'Tag management (CRUD + many-to-many)' + - 'Command palette (Ctrl+K global search)' + - 'Version history with diff comparison' + - 'Attachment management (image/audio/video/PDF preview)' + - 'Import/Export (JSON / ZIP selectable)' + - 'Scheduled auto backup' + - 'Dark/Light theme + custom accent colors' + - 'System tray + auto-start on boot' + - 'Floating ball quick actions (radial menu)' + - 'Quick note standalone window' + - 'i18n (Chinese / English)' - 'Cloud sync (WIP)' tags: - 'Markdown' - 'Notes' - 'Knowledge Management' - 'Desktop' + - 'Notebook' + - 'Local-first' + - 'Tauri' + - 'Vditor' icon: 'NotebookPen' -repoUrl: 'https://github.com/shenjianZ/quantanote' -docsUrl: 'https://github.com/shenjianZ/quantanote#readme' -latestVersion: 'v0.2.0' -releaseDate: '2026-04-15' +logo: '/logos/quantanote.png' +repoUrl: 'https://github.com/shenjianZ/QuantaNote' +websiteUrl: 'https://shenjianz.github.io/QuantaNote/' +docsUrl: 'https://quantanote-docs.shenjianl.cn/' +latestVersion: 'v0.2.3' +releaseDate: '2026-05-12' license: 'MIT' -stars: 128 -forks: 12 language: 'Rust' -lastUpdated: '2026-05-10' +lastUpdated: '2026-05-12' recommended: true featured: true order: 1 @@ -71,23 +84,23 @@ color: '#3B82F6' downloads: - platform: 'Windows' arch: 'x64' - url: 'https://github.com/shenjianZ/quantanote/releases/download/v0.2.0/QuantaNote_0.2.0_x64-setup.exe' - size: '22.6 MB' + url: 'https://file.shenjianl.cn/softwore/QuantaNote/v0.2.3/QuantaNote-v0.2.3-windows-x64.exe' + size: '9.6 MB' sha256: '' - platform: 'macOS' arch: 'Apple Silicon' - url: 'https://github.com/shenjianZ/quantanote/releases/download/v0.2.0/QuantaNote_0.2.0_aarch64.dmg' - size: '18.3 MB' + url: 'https://file.shenjianl.cn/softwore/QuantaNote/v0.2.3/QuantaNote-v0.2.3-macos-aarch64.dmg' + size: '14.3 MB' sha256: '' - platform: 'macOS' arch: 'Intel' - url: 'https://github.com/shenjianZ/quantanote/releases/download/v0.2.0/QuantaNote_0.2.0_x64.dmg' - size: '19.1 MB' + url: 'https://file.shenjianl.cn/softwore/QuantaNote/v0.2.3/QuantaNote-v0.2.3-macos-x64.dmg' + size: '14.7 MB' sha256: '' - platform: 'Linux' arch: 'x64' - url: 'https://github.com/shenjianZ/quantanote/releases/download/v0.2.0/QuantaNote_0.2.0_amd64.AppImage' - size: '20.2 MB' + url: 'https://file.shenjianl.cn/softwore/QuantaNote/v0.2.3/QuantaNote-v0.2.3-linux-x64.AppImage' + size: '86.1 MB' sha256: '' roadmap: done: @@ -96,44 +109,136 @@ roadmap: - '本地存储' - '标签系统' - '全文搜索' + - '版本历史与 Diff' + - '附件管理' + - '导入导出' + - '自动备份' + - '主题与自定义强调色' + - '系统托盘与开机自启' + - '账号管理' + - '悬浮球快捷操作' + - '快速笔记窗口' doing: - '云同步' - '多端同步' - - '账号管理' planned: - '插件系统' - - 'MCP 接入' - '移动端查看' - 'AI 辅助写作' changelog: - - version: 'v0.2.0' - date: '2026-04-15' + - version: 'v0.2.3' + date: '2026-05-12' changes: zh: - - '新增账号管理模块' - - '修复 Token 刷新竞态' - - '优化同步状态显示' - - '新增附件预览支持' + - '悬浮球功能:收起时球体、展开时径向菜单,支持快速笔记和搜索' + - '悬浮球设置项:透明度调节、窗口置顶、开关控制' + - '快速笔记独立窗口,支持 Markdown 编辑' + - '完整中英文国际化支持' en: - - 'Added account management' - - 'Fixed token refresh race condition' - - 'Improved sync status display' - - 'Added attachment preview' + - 'Floating ball: radial menu for quick notes and search' + - 'Floating ball settings: opacity, always-on-top, toggle' + - 'Quick note standalone window with Markdown editing' + - 'Full Chinese/English i18n support' + - version: 'v0.2.2' + date: '2026-05-11' + changes: + zh: + - '修复更新包公钥配置被占位符覆盖导致签名校验失败' + - '更新关于页的更新错误提示' + en: + - 'Fixed updater public key config overridden by placeholder' + - 'Improved update error messages on About page' + - version: 'v0.2.1' + date: '2026-05-11' + changes: + zh: + - '升级 rusqlite 0.31→0.35、thiserror 1→2' + - '同步状态管理改用 Result 替代 unwrap' + - '新增密码长度、标签颜色等输入验证' + - '修复前端 TopBar 非 Tauri 环境报错' + - '编辑器搜索高亮改用 DOM API' + en: + - 'Upgraded rusqlite 0.31→0.35, thiserror 1→2' + - 'Sync state management uses Result instead of unwrap' + - 'Added input validation for password length, tag colors' + - 'Fixed TopBar errors in non-Tauri environment' + - 'Editor search highlight uses DOM API' + - version: 'v0.2.0' + date: '2026-05-05' + changes: + zh: + - '新增账号管理(个人资料、修改密码、删除账号)' + - '云同步增强:Token 刷新竞态修复、同步状态指示器' + - 'Docker 多阶段构建 + docker-compose 部署' + - '文档站自动部署到 GitHub Pages' + en: + - 'Account management (profile, password change, account deletion)' + - 'Cloud sync: token refresh race fix, sync status indicator' + - 'Docker multi-stage build + docker-compose deployment' + - 'Docs auto-deploy to GitHub Pages' - version: 'v0.1.0' - date: '2026-02-20' + date: '2026-05-02' changes: zh: - '首个公开版本' - - '基础笔记 CRUD' - - 'Markdown 编辑器' - - '本地 SQLite 存储' - - '标签管理' + - 'Markdown 编辑器(Vditor IR 模式)' + - '全文搜索(FTS5 + trigram 双引擎)' + - '版本历史与 Diff 对比' + - '附件管理、导入导出、自动备份' + - '主题切换、系统托盘' en: - 'First public release' - - 'Basic note CRUD' - - 'Markdown editor' - - 'Local SQLite storage' - - 'Tag management' + - 'Markdown editor (Vditor IR mode)' + - 'Full-text search (FTS5 + trigram dual engine)' + - 'Version history with diff comparison' + - 'Attachments, import/export, auto backup' + - 'Theme switching, system tray' architecture: - zh: '前端 (React + TypeScript) → Tauri Commands → Rust 核心层 → SQLite 数据库 → 本地文件存储' - en: 'Frontend (React + TypeScript) → Tauri Commands → Rust Core → SQLite Database → Local File Storage' + zh: '前端 (React 19 + Zustand + TailwindCSS 4) → Tauri 2 Commands → Rust 核心层 (rusqlite 0.35) → SQLite (WAL + FTS5) → 本地文件存储' + en: 'Frontend (React 19 + Zustand + TailwindCSS 4) → Tauri 2 Commands → Rust Core (rusqlite 0.35) → SQLite (WAL + FTS5) → Local File Storage' + +screenshots: + - '/screenshots/quantanote/library.png' + - '/screenshots/quantanote/note-preview.png' + - '/screenshots/quantanote/note-edit.png' + - '/screenshots/quantanote/note-version.png' + - '/screenshots/quantanote/workspace.png' + - '/screenshots/quantanote/search-cmd.png' + - '/screenshots/quantanote/settings-appearance.png' + - '/screenshots/quantanote/settings-font.png' + - '/screenshots/quantanote/settings-data.png' + - '/screenshots/quantanote/settings-sync.png' + - '/screenshots/quantanote/settings-about.png' + - '/screenshots/quantanote/accoun-login.png' + - '/screenshots/quantanote/account-register.png' + - '/screenshots/quantanote/account-profile.png' + - '/screenshots/quantanote/account.png' + - '/screenshots/quantanote/topbar-more.png' + +installGuide: + zh: + - platform: 'Windows' + icon: '🪟' + format: '.exe' + tip: 'SmartScreen 拦截?点击"更多信息" → "仍要运行"' + - platform: 'macOS' + icon: '🍎' + format: '.dmg' + tip: '提示已损坏?终端运行: xattr -dr com.apple.quarantine /Applications/QuantaNote.app' + - platform: 'Linux' + icon: '🐧' + format: '.AppImage' + tip: 'chmod +x QuantaNote-*.AppImage && ./QuantaNote-*.AppImage' + en: + - platform: 'Windows' + icon: '🪟' + format: '.exe' + tip: 'SmartScreen blocked? Click "More info" → "Run anyway"' + - platform: 'macOS' + icon: '🍎' + format: '.dmg' + tip: '"Damaged" error? Run: xattr -dr com.apple.quarantine /Applications/QuantaNote.app' + - platform: 'Linux' + icon: '🐧' + format: '.AppImage' + tip: 'chmod +x QuantaNote-*.AppImage && ./QuantaNote-*.AppImage' diff --git a/src/data/projects/react-docs-ui.yaml b/src/data/projects/react-docs-ui.yaml index 288ad09..65d9ea0 100644 --- a/src/data/projects/react-docs-ui.yaml +++ b/src/data/projects/react-docs-ui.yaml @@ -47,14 +47,13 @@ tags: - 'NPM' - 'MDX' 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' npmUrl: 'https://www.npmjs.com/package/react-docs-ui' latestVersion: 'v0.5.2' releaseDate: '2026-05-10' license: 'MIT' -stars: 203 -forks: 24 language: 'TypeScript' lastUpdated: '2026-05-18' recommended: true diff --git a/src/data/projects/ssh-terminal.yaml b/src/data/projects/ssh-terminal.yaml index 4f0f4c1..523a61a 100644 --- a/src/data/projects/ssh-terminal.yaml +++ b/src/data/projects/ssh-terminal.yaml @@ -50,13 +50,12 @@ tags: - 'SFTP' - 'DevOps' icon: 'Terminal' +logo: '/logos/ssh-terminal.png' repoUrl: 'https://github.com/shenjianZ/ssh-terminal' docsUrl: 'https://github.com/shenjianZ/ssh-terminal#readme' latestVersion: 'v0.1.5' releaseDate: '2026-03-28' license: 'MIT' -stars: 89 -forks: 8 language: 'Rust' lastUpdated: '2026-05-08' recommended: true diff --git a/src/data/projects/streetmoment.yaml b/src/data/projects/streetmoment.yaml index b3daddc..3fe904e 100644 --- a/src/data/projects/streetmoment.yaml +++ b/src/data/projects/streetmoment.yaml @@ -46,13 +46,12 @@ tags: - 'Social' - 'Mobile' icon: 'MapPin' +logo: '/logos/streetmoment.png' repoUrl: 'https://github.com/shenjianZ/streetmoment' docsUrl: 'https://github.com/shenjianZ/streetmoment#readme' latestVersion: 'v1.0.0' releaseDate: '2026-05-01' license: 'MIT' -stars: 56 -forks: 5 language: 'TypeScript' lastUpdated: '2026-05-15' recommended: false diff --git a/src/hooks/useProjectFilters.ts b/src/hooks/useProjectFilters.ts index 8beec68..a015e7c 100644 --- a/src/hooks/useProjectFilters.ts +++ b/src/hooks/useProjectFilters.ts @@ -39,8 +39,7 @@ export function useProjectFilters() { if (platform) result = result.filter((p) => p.platforms.includes(platform)); if (status) result = result.filter((p) => p.status === status); - if (sort === 'stars') result.sort((a, b) => b.stars - a.stars); - else if (sort === 'name') result.sort((a, b) => a.name.localeCompare(b.name)); + if (sort === 'name') result.sort((a, b) => a.name.localeCompare(b.name)); else result.sort((a, b) => b.lastUpdated.localeCompare(a.lastUpdated)); return result; diff --git a/src/pages/ProjectDetailPage.tsx b/src/pages/ProjectDetailPage.tsx index 91fca08..b21a414 100644 --- a/src/pages/ProjectDetailPage.tsx +++ b/src/pages/ProjectDetailPage.tsx @@ -6,7 +6,7 @@ import RoadmapGrid from '../components/RoadmapGrid'; import ChangelogList from '../components/ChangelogList'; import ScreenshotCarousel from '../components/ScreenshotCarousel'; import { getIcon } from '../utils/iconRegistry'; -import { ExternalLink, Download, BookOpen } from 'lucide-react'; +import { ExternalLink, Download, BookOpen, Globe } from 'lucide-react'; export default function ProjectDetailPage() { const { id } = useParams(); @@ -44,7 +44,10 @@ export default function ProjectDetailPage() {
- {IconComponent ? : {p.icon}} + {p.logo + ? {p.name} + : (IconComponent ? : {p.icon}) + }

{p.displayName[lang] || p.name}

@@ -70,10 +73,12 @@ export default function ProjectDetailPage() {
- - - GitHub - + {p.websiteUrl && ( + + + {t('detail.website')} + + )} {hasDownloads && ( { e.preventDefault(); @@ -130,18 +135,21 @@ export default function ProjectDetailPage() {

{t('detail.downloads')}

+ {p.installGuide && ( +
+ {p.installGuide[lang].map((item) => ( +
+ {item.icon} + {item.format} + {item.tip} +
+ ))} +
+ )}
{t('downloads.trustNote')}
)} - {/* Roadmap */} - {p.roadmap && ( -
-

{t('detail.roadmap')}

- -
- )} - {/* Changelog */} {p.changelog && p.changelog.length > 0 && (
@@ -150,30 +158,13 @@ export default function ProjectDetailPage() {
)} - {/* Install guide */} -
-

{t('detail.installGuide')}

-
-
- Windows - {t('detail.install.windows')} -
-
- macOS - {t('detail.install.macos')} -
-
- Linux - {t('detail.install.linux')} -
- {p.platforms.includes('android') && ( -
- Android - {t('detail.install.android')} -
- )} + {/* Roadmap */} + {p.roadmap && ( +
+

{t('detail.roadmap')}

+
-
+ )}
{/* Sidebar */} @@ -191,14 +182,6 @@ export default function ProjectDetailPage() { {t('detail.license')} {p.license}
-
- {t('common.stars')} - {p.stars} -
-
- {t('common.forks')} - {p.forks} -
{t('detail.lastUpdate')} {p.lastUpdated} @@ -213,6 +196,12 @@ export default function ProjectDetailPage() { {t('detail.repo')} + {p.websiteUrl && ( + + + {t('detail.website')} + + )} {p.docsUrl && ( diff --git a/src/pages/ProjectsPage.tsx b/src/pages/ProjectsPage.tsx index 66f6901..f66cacb 100644 --- a/src/pages/ProjectsPage.tsx +++ b/src/pages/ProjectsPage.tsx @@ -45,7 +45,6 @@ export default function ProjectsPage() { ]; const sortOptions = [ { value: 'updated', label: t('projects.sort.updated') }, - { value: 'stars', label: t('projects.sort.stars') }, { value: 'name', label: t('projects.sort.name') }, ]; diff --git a/src/styles/components/cards.css b/src/styles/components/cards.css index 76c2aba..a1c8fa6 100644 --- a/src/styles/components/cards.css +++ b/src/styles/components/cards.css @@ -169,6 +169,13 @@ transform: scale(1.08); } +.project-logo { + width: 32px; + height: 32px; + object-fit: contain; + border-radius: 4px; +} + .project-card-info { flex: 1; min-width: 0; diff --git a/src/styles/components/detail.css b/src/styles/components/detail.css index 1dd5bbb..6b02dc1 100644 --- a/src/styles/components/detail.css +++ b/src/styles/components/detail.css @@ -70,6 +70,11 @@ background: linear-gradient(135deg, oklch(100% 0 0 / 10%) 0%, transparent 60%); } +.detail-icon .project-logo { + width: 48px; + height: 48px; +} + .detail-title { font-size: 36px; font-weight: 800; @@ -290,12 +295,13 @@ .screenshot-scroll { display: flex; + align-items: flex-start; gap: 12px; overflow-x: auto; + overflow-y: hidden; scroll-snap-type: x mandatory; -webkit-overflow-scrolling: touch; scrollbar-width: none; - padding-bottom: 4px; } .screenshot-scroll::-webkit-scrollbar { @@ -305,13 +311,176 @@ .screenshot-slide { flex: 0 0 85%; max-width: 400px; + aspect-ratio: 16 / 10; scroll-snap-align: center; + cursor: pointer; + overflow: hidden; } .screenshot-slide:first-child { margin-inline-start: 4px; } +.screenshot-image { + width: 100%; + height: 100%; + display: block; + object-fit: cover; + border-radius: var(--radius-md); + border: 1px solid var(--border); + transition: transform 0.2s, box-shadow 0.2s; +} + +.screenshot-slide:hover .screenshot-image { + transform: scale(1.02); + box-shadow: 0 4px 20px oklch(0% 0 0 / 30%); +} + +/* Desktop arrows — hidden on mobile */ +.screenshot-arrow { + display: none; + position: absolute; + top: 50%; + transform: translateY(-50%); + z-index: 2; + width: 32px; + height: 32px; + border-radius: 50%; + border: 1px solid var(--border); + background: oklch(15% 0.025 270 / 80%); + backdrop-filter: blur(8px); + color: var(--fg); + cursor: pointer; + align-items: center; + justify-content: center; + transition: all var(--transition); +} + +.screenshot-arrow:hover { + background: oklch(74% 0.2 45 / 20%); + border-color: oklch(74% 0.2 45 / 30%); + color: var(--accent); +} + +.screenshot-arrow-prev { + left: 4px; +} + +.screenshot-arrow-next { + right: 4px; +} + +@media (min-width: 768px) { + .screenshot-slide { + flex: 0 0 calc(33.333% - 8px); + cursor: pointer; + } + + .screenshot-arrow { + display: flex; + } +} + +/* Lightbox overlay */ +.screenshot-lightbox { + position: fixed; + inset: 0; + z-index: 9999; + background: oklch(0% 0 0 / 85%); + backdrop-filter: blur(12px); + display: flex; + align-items: center; + justify-content: center; + padding: 40px; + cursor: zoom-out; + animation: lightbox-in 0.2s ease; +} + +@keyframes lightbox-in { + from { opacity: 0; } + to { opacity: 1; } +} + +.screenshot-lightbox-img { + max-width: 90vw; + max-height: 85vh; + object-fit: contain; + border-radius: var(--radius-lg); + box-shadow: 0 8px 40px oklch(0% 0 0 / 50%); + cursor: default; + animation: lightbox-zoom 0.25s ease; +} + +@keyframes lightbox-zoom { + from { transform: scale(0.92); opacity: 0; } + to { transform: scale(1); opacity: 1; } +} + +.screenshot-lightbox-close { + position: absolute; + top: 16px; + right: 16px; + width: 40px; + height: 40px; + border-radius: 50%; + border: 1px solid oklch(100% 0 0 / 20%); + background: oklch(0% 0 0 / 50%); + color: oklch(100% 0 0 / 80%); + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; + transition: all 0.2s; + z-index: 10; +} + +.screenshot-lightbox-close:hover { + background: oklch(0% 0 0 / 70%); + color: oklch(100% 0 0 / 100%); +} + +.screenshot-lightbox-arrow { + position: absolute; + top: 50%; + transform: translateY(-50%); + width: 48px; + height: 48px; + border-radius: 50%; + border: 1px solid oklch(100% 0 0 / 20%); + background: oklch(0% 0 0 / 40%); + color: oklch(100% 0 0 / 80%); + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; + transition: all 0.2s; + z-index: 10; +} + +.screenshot-lightbox-arrow:hover { + background: oklch(0% 0 0 / 60%); + color: oklch(100% 0 0 / 100%); +} + +.screenshot-lightbox-prev { + left: 16px; +} + +.screenshot-lightbox-next { + right: 16px; +} + +.screenshot-lightbox-counter { + position: absolute; + bottom: 20px; + left: 50%; + transform: translateX(-50%); + color: oklch(100% 0 0 / 60%); + font-size: 14px; + font-weight: 500; + letter-spacing: 0.05em; +} + .screenshot-placeholder { aspect-ratio: 16/10; border-radius: var(--radius-lg); @@ -365,12 +534,6 @@ box-shadow: 0 0 8px oklch(74% 0.2 45 / 30%); } -@media (min-width: 768px) { - .screenshot-slide { - flex: 0 0 calc(33.333% - 8px); - } -} - /* ── Install guide ───────────────────────────────────── */ .install-list { display: flex; @@ -405,6 +568,57 @@ letter-spacing: 0.03em; } +/* ── Install guide inline (compact) ──────────────────── */ +.install-guide-inline { + display: flex; + flex-direction: column; + gap: 4px; + margin-top: 12px; + padding: 8px 10px; + border-radius: var(--radius-md); + border: 1px dashed oklch(74% 0.2 45 / 15%); + background: oklch(74% 0.2 45 / 3%); +} + +:root.light .install-guide-inline { + border-color: oklch(58% 0.22 45 / 15%); + background: oklch(58% 0.22 45 / 3%); +} + +.install-tip-row { + display: flex; + align-items: baseline; + gap: 8px; + font-size: 12px; + line-height: 1.6; + padding: 3px 4px; + border-radius: var(--radius-sm); +} + +.install-tip-icon { + flex-shrink: 0; + font-size: 13px; + width: 18px; + text-align: center; +} + +.install-tip-format { + flex-shrink: 0; + font-family: var(--font-mono); + font-size: 11px; + font-weight: 600; + color: var(--accent); + padding: 1px 6px; + border-radius: 4px; + background: oklch(74% 0.2 45 / 10%); +} + +.install-tip-text { + color: var(--muted); + min-width: 0; + word-break: break-all; +} + /* ── Project selector (for roadmap/changelog) ────────── */ .project-selector { display: flex; diff --git a/src/types/index.ts b/src/types/index.ts index a712bb4..a77e63c 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -56,6 +56,20 @@ export interface ChangelogEntry { changes: BilingualArray; } +export interface InstallGuideItem { + platform: string; + icon: string; + format: string; + tip: string; +} + +export type InstallGuide = InstallGuideItem[]; + +export interface BilingualInstallGuide { + zh: InstallGuide; + en: InstallGuide; +} + export interface Project { id: string; name: string; @@ -69,14 +83,14 @@ export interface Project { features: BilingualArray; tags: string[]; icon: string; + logo?: string; repoUrl: string; + websiteUrl?: string; docsUrl?: string; npmUrl?: string; latestVersion: string; releaseDate: string; license: string; - stars: number; - forks: number; language: string; lastUpdated: string; recommended: boolean; @@ -88,6 +102,7 @@ export interface Project { changelog?: ChangelogEntry[]; architecture?: BilingualText; screenshots?: string[]; + installGuide?: BilingualInstallGuide; } export interface AboutData {