37 Commits

Author SHA1 Message Date
xfy
886eeca915 style: 全项目 rsx! 格式规范化(cargo fmt)
Some checks failed
CI / check (push) Has been cancelled
CI / build (push) Has been cancelled
2026-07-15 17:49:03 +08:00
xfy
65a7b1226f style: 全项目格式规范化(cargo fmt)+ Docker daemon 断连容错
- 全项目 .rs 统一 cargo fmt 排版(换行/缩进/参数分行/导入排序)
- infra/docker: DOCKER_CLIENT 连接失败不 panic,降级返回 None
  (博客不依赖 Docker,panic=abort 下会导致整个进程崩溃)
- infra/mod: 去除多余空行
- database/mod: 模块声明按字母序重新排序
2026-07-15 17:22:06 +08:00
xfy
25299d266f refactor(admin): 合并 /admin/posts 与 /admin/posts/trash 为单路由 + tab 切换
将「全部文章」与「回收站」从两个独立路由(及各自的分页变体 PostsPage /
PostsTrashPage)合并为单一 /admin/posts 路由,用顶部 tab 在二者间切换。
tab 状态与翻页均改为客户端 signal 驱动(不走路由、不深链),与 system.rs 的
tab 模式一致:admin 内部页,刷新回到「全部文章」第 1 页。

路由瘦身:删除 PostsTrash / PostsTrashPage / PostsPage 三个变体,Router 不再
需要「静态段 trash 优先于 :page」的排序技巧。

主要改动:
- posts.rs: Posts 改为 tab 容器(PostsTab 枚举 + active_tab signal + key 化
  match 渲染),header 文案随 tab 切换;PostsPage 主体下沉为 AllPostsList,
  翻页改 current_page signal + use_paginated 回调式 Pagination。
- posts_trash.rs: PostsTrashPage → PostsTrashPanel(无参,signal 翻页),
  删除入口组件与 PostsTabs import(header/tab 由容器统一提供)。
- PostsTabs: 从路由驱动(use_route)改为 signal 驱动(on_change 回调)。
- 修复 tab 水平对齐 bug:两个 tab 统一 inline-flex items-center 同盒模型 +
  外层容器加 items-center,根除原先「全部文章」(inline 文本) 与「回收站」
  (inline-flex 带角标) 盒模型不一致导致的垂直错位。
- admin_layout.rs: is_posts_route 简化为只匹配 Route::Posts{}。
- RebuildCacheBar 改为完全自持 state(rebuilding + result),结果消息行随组件
  内联渲染,与父组件零耦合。
2026-07-15 10:21:50 +08:00
xfy
a4297355b5 refactor(router): downcast ServerFnError in ErrorLayout and improve fallback styling 2026-07-09 17:36:38 +08:00
xfy
37e8f51fac feat(router): wrap public routes in ErrorLayout with ErrorBoundary 2026-07-09 17:29:47 +08:00
xfy
d72495c002 refactor(admin): merge trash into /admin/posts as a URL-driven tab
回收站从独立路由 /admin/trash 合并为 /admin/posts 下的一个 tab,
消除「回收站」导航项,让文章管理(列表 + 回收站 + 自动清理配置)集中在
同一页面,符合「相关功能就近聚合」的组织原则。

路由(router.rs)
- 删除 Route::Trash / Route::TrashPage
- 新增 Route::PostsTrash (/posts/trash) 与 PostsTrashPage (/posts/trash/:page)
- 静态段声明在 :page 之前::page 为 i32 类型,天然排斥 'trash' 文本,
  路由匹配安全且遵循文件内 static-first 约定

导航(admin_layout.rs)
- 移除「回收站」导航项
- 「管理文章」高亮覆盖其下所有子路由(列表/分页/回收站 tab),
  顺带修掉原 PostsPage 分页不高亮的小 bug

页面(posts.rs / posts_trash.rs)
- 新增 PostsTabs:URL 驱动的 tab 栏(Link 切换路由,非本地 signal),
  回收站 tab 带 get_post_stats().trash 数量角标,>0 用主题强调色提醒
- trash.rs → posts_trash.rs:TrashPage 重命名为 PostsTrashPage,
  分页路由改指向 PostsTrash/PostsTrashPage,内容(列表/批量操作/
  清空回收站/AutoPurgeSettings)原样迁移;include_str 测试同步更新
- posts.rs 的 PostsPage 渲染 PostsTabs,列表逻辑不变

无后端契约变更:所有 server function(list/delete/restore/purge/
batch/empty_trash/get_trash_settings)签名不变,Pagination 组件
接收具体 Route 变体,给 trash tab 传 PostsTrash 即可,无需改组件。
2026-07-08 16:52:02 +08:00
xfy
bbd4553467 feat(admin): add dedicated code-runner sandbox page at /admin/runner
不改动 852 行的 write.rs 编辑器布局,改为独立 admin 页面(与 posts/system 同款):
- runner.rs: Runner 页面(语言切换 join 按钮 + overrides JSON 输入 + CodeRunner 沙箱)
  切换语言自动填充示例源码;overrides JSON 实时校验,畸形时提示并忽略
- mod.rs: 注册 runner 模块并导出 Runner
- router.rs: 新增 #[route("/runner")] Runner {} 嵌套在 /admin 下
- admin_layout.rs: 导航新增「试运行」入口
2026-07-03 18:41:05 +08:00
xfy
404f85b732 refactor(web): 用 document::Link 注入 favicon,移除手写 index.html
Dioxus 0.7 提供 document::Link 组件,可在 Rust 代码里声明 <link rel="icon">
注入 <head>,与已有的 document::Stylesheet / document::Title 同机制。

之前的方案手写 index.html(复制 dx CLI 默认 shell + 加 favicon 链接),
脆弱:嵌入了 toast 基础设施 JS/CSS,升级 dioxus-cli 后需手动同步。
改用 document::Link 后,favicon 由 SSR 运行时注入,无需维护静态模板。
2026-07-01 17:00:58 +08:00
xfy
81a4196e43 feat(admin): add /admin/system route shell with 5 tabs
新增系统管理入口页(数据库状态/服务器状态/SQL 控制台/导出/备份恢复),
顶部 tab 切换(用 use_signal 不深链)。路由注册 + 导航加「系统」项。
tab 内容待后续 task 填充。
2026-06-29 18:26:24 +08:00
xfy
cb73a9b979 chore: fix cargo clippy warnings (unused import and false positive unused_mut) 2026-06-29 10:14:27 +08:00
xfy
82a8c511fc fix(theme): remove dark class from AppRouter div 2026-06-26 18:24:00 +08:00
xfy
0398cc6c66 perf(render): 列表加显式 key + release 启用 panic=abort
依据 Dioxus 0.7 optimizing 指南做两项改进:

- 为数据驱动列表渲染补全显式 key(13 处,9 个文件):
  home/archives/tags/search 文章与标签列表、post_card/post_footer
  标签、header 桌面/移动导航、admin dashboard/posts/write 列表。
  使用各类型稳定唯一字段(post.id / tag / tag.name / item.label /
  err.id / year_group.year / month_group.month_en)作为 key,
  让 Dioxus diff 正确识别元素身份。骨架屏 for _ in 0..N 静态占位
  循环与已带 key 的评论树/admin 行不动。

- [profile.release] 加 panic = "abort":WASM 去掉 unwind 元数据减小
  体积;server 端错误处理走 Result+?(见 error.rs),不依赖 panic
  unwind,无副作用。

其余文件为本机格式化(单行折叠/多行展开),一并提交。

验证:dx check 通过、cargo test 405 passed。
2026-06-25 18:07:22 +08:00
xfy
4ba4fedb23 feat(ui): 新增 /admin/trash 回收站管理页面与导航 2026-06-16 12:38:41 +08:00
xfy
c5d1eb117c docs(auth-pages, router, main): 补充中文注释 2026-06-12 19:31:21 +08:00
xfy
294d60afab style: format rust code
Some checks failed
CI / build (push) Has been cancelled
CI / check (push) Has been cancelled
2026-06-12 17:14:31 +08:00
xfy
04737300e6 feat(comments): add complete comment system with guest commenting, moderation, and admin UI
Implements a fully self-built comment system for the blog:

Data layer:
- comments table with BIGSERIAL PK, parent_id self-reference (ON DELETE SET NULL),
  depth tracking (max 20), status workflow (pending/approved/spam/trash),
  content hashing for dedup, GDPR consent tracking, IP/UA storage with auto-purge
- 5 partial indexes optimized for read patterns
- updated_at auto-trigger

API (9 Dioxus server functions):
- Public: get_comments, get_comment_count, create_comment
- Admin: get_pending_comments, get_pending_count, get_all_comments,
  approve_comment (with ancestor auto-approval), spam_comment, trash_comment,
  batch_update_comment_status

Security:
- Function-level rate limiting (1/sec, burst 5) via FullstackContext IP extraction
- Input validation (name, email, URL scheme, content length, consent)
- Parent chain validation (must be approved, same post)
- Strict comment Markdown renderer (headings→strong, no img/id/data URIs, nofollow links)
- Honeypot anti-spam field
- 5-minute dedup window via SHA-256 content hash

Frontend:
- CommentSection with SuspenseBoundary isolation
- Flat-list rendering with depth-based CSS indentation (responsive)
- Gravatar via cravatar.cn (server-computed, email never exposed)
- Inline reply forms (one-at-a-time via Signal)
- Admin action buttons (approve/spam/delete) visible per-comment
- CommentForm with privacy consent, Markdown hint, loading states

Admin:
- /admin/comments page with status tabs, batch operations, pagination
- Pending count badge on admin dashboard

Infrastructure:
- Shared get_current_admin_user moved from posts/helpers to auth module
- COMMENT_LIMITER rate limiter tier
- Moka caches (60s TTL for comments, 10s for pending count)
- IP/UA purge background task (daily, 90-day retention)
2026-06-11 12:34:26 +08:00
xfy
265eb15887 feat(admin): add pagination to posts management page
- list_posts API now accepts page/per_page params with LIMIT/OFFSET
- Add /admin/posts/:page route with PostsPage component
- Pagination component with prev/next navigation (20 posts/page)
- Update dashboard to use new list_posts(1, 5) signature
2026-06-10 18:03:36 +08:00
xfy
2f433e8f11 feat: add 404 Not Found page
- Add NotFound component with elegant design
- Register catch-all route in router
- Add skeleton placeholder for NotFound route
- Remove unused design-taste-frontend skill
2026-06-10 15:43:05 +08:00
xfy
026a331dcd feat(router): add /admin/write/:id route for post editing 2026-06-05 17:34:26 +08:00
xfy
a282d1dd29 feat: enable wasm-split for route-based code splitting
Enable Dioxus 0.7 automatic WASM bundle splitting by route:

- Add wasm-split feature to dioxus and dioxus-router in Cargo.toml
- Add --wasm-split flag to dx build in Makefile
- Router definitions stay as plain #[route] — splitting is automatic

Dioxus 0.7.9 handles splitting automatically when the feature and
CLI flag are enabled. Per-route #[wasm_split] attributes are not
required (and not supported by this version's derive macro).
2026-06-04 17:32:00 +08:00
xfy
c44f37e9ec feat: enable wasm_split for non-core routes
Split low-frequency routes into separate WASM chunks:
- archives, tags, search, about
- admin/* (dashboard, write, posts)
- login, register

Core reading paths (home, post detail) remain in initial bundle.
2026-06-04 17:15:14 +08:00
xfy
8845577958 feat: wrap frontend routes in FrontendLayout via router #[layout] attribute
- All public-facing pages (Home, Archives, Tags, PostDetail, Search,
  About, HomePage) are now wrapped in #[layout(FrontendLayout)]
- Header and Footer stay mounted during page transitions, only the
  <Outlet> content swaps — eliminates full-page flash/flicker
- Login and Register routes moved outside FrontendLayout since they
  are standalone pages without navigation header
- Route order restructured: FrontendLayout block → admin nest → auth pages
- Note: #[end_layout]/#[end_nest] must have a variant after them in the
  enum, otherwise the Routable derive macro fails with 'expected identifier'
2026-06-03 18:35:36 +08:00
xfy
e48ea4f97f fix: add CSS stylesheets via document API for SSR
- Add document::Stylesheet for /style.css and /highlight.css in AppRouter
- This ensures CSS is included in SSR HTML for all pages (home, post detail, etc.)
- Also add public/index.html for production builds
- Remove stale ISRG cache files
2026-06-03 15:37:17 +08:00
xfy
f5413e00cc fix(auth): prevent password_hash from reaching the frontend
Introduce PublicUser struct without password_hash field. The
get_current_user server function now returns PublicUser via
CurrentUserResponse, so Argon2 hashes are never serialized to WASM.

Internal server-side functions (get_current_admin_user) continue
using the full User struct.
2026-06-03 10:32:15 +08:00
xfy
1950646bef feat: add shared components, new pages, and pagination 2026-06-02 17:33:28 +08:00
xfy
b6cabe489f feat: migrate frontend to database-driven posts
- Replace hardcoded POSTS with API-driven data in home, archives, tags
- Add post detail page /post/:slug with HTML rendering
- Add admin posts management page with list and soft delete
- Update dashboard with real stats from database
- Add admin navigation for posts management
- Fix PartialEq derives for Post, Tag, PostStats models
- Use use_resource and use_memo for data fetching with proper loading states
2026-06-02 17:33:28 +08:00
李林军
4093178fc3 添加tracing日志并重构服务器启动逻辑 2026-05-27 11:39:09 +08:00
xfy
61376f6ba9 修复 admin 路由切换闪烁,全局替换原生导航为客户端路由
- 新增全局 UserContext,将用户认证状态提升到 App 级别缓存
- 将 /admin 和 /admin/write 改为嵌套路由,AdminLayout 作为共享父布局
- AdminLayout 使用 Outlet 渲染子页面,避免路由切换时重复挂载
- 修复所有原生 <a> 标签导致的整页刷新问题:
  - Header 导航栏 Logo 和 NavItem
  - 首页文章卡片、分页按钮
  - 归档页文章条目
  - 标签页标签云、文章卡片、标签链接
  - 登录/注册页面链接
  - Dashboard 快捷操作按钮

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-27 00:18:15 +08:00
xfy
8b9c6aa83d 重构 admin 模块,新增共享组件和文章撰写页面
- 将 monolithic admin.rs 拆分为 admin/ 目录模块(dashboard、write)
- 新增 components 模块:Header、Footer、AdminLayout
- 新增 /admin/write 文章撰写页面,支持 Markdown 实时预览
- 添加 pulldown-cmark 依赖用于 Markdown 渲染
- .env 移出版本控制,新增 .env.example 模板
- Home、Archives、Tags、Login、Register 等页面适配新组件

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-26 16:13:18 +08:00
xfy
06302b14de 实现 PaperMod 风格标签页面:标签列表 + 标签详情
- 新增 /tags 页面:展示所有标签及文章数量,按字母排序
- 新增 /tags/:tag 动态路由:展示该标签下的文章列表
- Post/POSTS 改为 pub,供 tags 模块复用
- NavItem 高亮也匹配 TagDetailPage
- 修复 CSS 路径为绝对路径,解决子路由下样式失效

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-26 13:43:38 +08:00
xfy
7599bfbb13 实现 PaperMod 风格归档页面,支持按年份月份分组
- 新增 ArchivesPage 组件,三级结构:年份 → 月份 → 文章
- Header/NavItem/Footer 改为 pub 共享,NavItem 通过路由动态判断高亮
- 编译 Tailwind CSS 包含归档页面所需 utility classes

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-26 13:31:35 +08:00
xfy
61c1ec7282 修复暗色模式:class 变体、状态同步、FOUC 预防、系统偏好
- 配置 Tailwind v4 @custom-variant dark 使用 class 模式
- 用 use_context_provider 共享主题状态,修复 AppRouter/ThemeToggle 不同步
- 默认跟随系统偏好(matchMedia),无 localStorage 时自动检测
- 统一暗色标记为 .dark class,移除 data-theme 冗余
- ThemePreload 内联脚本在 DOM 解析前设置 class,消除首屏闪烁
- SVG 内联 + currentColor,图标颜色随主题切换
- Cargo.toml 补充 web-sys MediaQueryList/DomTokenList feature

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-26 11:31:06 +08:00
xfy
8b3aab21de 恢复首页路由,添加归档/标签/搜索/关于路由占位
- router.rs: / 恢复为 HomePage,新增 /archives /tags /search /about
- mod.rs: 导出 home 模块
- theme.rs: ThemeToggle 从浮动按钮改为内联样式
- home.rs: 创建空占位文件

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-26 10:31:52 +08:00
xfy
c2d5619855 移除首页,将根路径重定向到登录页,添加注册链接
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-26 10:22:05 +08:00
xfy
0b15cc7e1c 切换到本地 Tailwind CSS 构建并清理项目文件
- 移除 CDN Tailwind,改用本地构建的 style.css
- 添加 package.json、tailwind.config.js、input.css 构建配置
- 清理 prd.json、progress.txt 及误创建的文件
- 修复 login.rs 中未使用变量命名 (_token → token)
- 更新 .gitignore 排除 node_modules 和 package-lock.json

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-25 17:35:02 +08:00
xfy
c4dfd1f445 Fix additional clippy warnings and update progress
- Add #[allow(dead_code)] to temporarily unused functions
- Remove unused is_expired() and UserRole::as_str()
- Fix unused variable warnings (token, theme)
- Update progress.txt: mark all stories complete

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-25 17:02:14 +08:00
xfy
14b92c3a89 US-005: 后台页面与路由整合
- src/router.rs: Dioxus 路由定义 (/login, /register, /admin, /)
- src/main.rs: 整合所有模块 + server block 启动 dotenvy + session 清理任务
- src/tasks/session_cleanup.rs: 每小时清理过期 session
- 修复编译错误: chrono serde, tokio-postgres chrono, argon2 OsRng
- 移除 server_context 依赖,简化 get_current_user 查询
- Tailwind CSS CDN + darkMode class 配置

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-25 16:29:50 +08:00