39 Commits

Author SHA1 Message Date
xfy
8971fbe1a2 feat(write): 支持封面图上传(拖拽/点击/粘贴)
将编辑页封面图从纯 URL 输入框升级为完整的上传控件:
- 16:9 拖拽区,支持拖拽文件、点击选择、剪贴板粘贴三种上传入口
- 完整交互状态:空态/上传中(骨架占位)/预览/错误提示
- 保留外链 URL 输入(内联折叠),覆盖图床/CDN 场景
- 上传复用现有 POST /api/upload,服务端零改动

tiptap_bridge 提取 upload_image_file 通用上传函数,
make_upload_upload 改为薄包装,消除 fetch 逻辑重复。

Cargo.toml 补 web-sys feature(ClipboardEvent/DataTransfer/FileList/
HtmlInputElement),供粘贴/拖拽读取文件。
2026-06-24 15:09:47 +08:00
xfy
975e331dd5 fix(write): split tags on fullwidth punctuation
The tag splitter matched ASCII ',' and ';' twice instead of the
fullwidth ',' (U+FF0C) / ';' (U+FF1B) the comment intended, so tags
separated by fullwidth punctuation (common under Chinese IMEs)
collapsed into a single tag.

Also resolves the compiler warnings surfaced in the same build:
- tiptap_bridge: drop unused Readable/Writable imports and
  EditorInstance/TiptapEditorModule re-exports
- tiptap_bridge: migrate deprecated RequestInit::method/body/
  credentials builders to set_method/set_body/set_credentials
- write: remove redundant `mut` on Dioxus signals that are only
  read/set, never reassigned
- image_viewer: gate the server-only `mut` reassignment so the WASM
  build (which strips the cfg block) doesn't warn
2026-06-23 14:44:18 +08:00
xfy
ef6a3f0da2 fix(home,editor): repair post card nested anchors and editor upload state
首页审查修复(home/post_card/image_viewer/search/home_skeleton):
- PostCard 消除嵌套 <a>:外层 Link 包裹改为绝对定位覆盖层链接,
  标题/摘要/封面降级为普通元素,标签用 z-10 叠在覆盖层之上并
  stop_propagation,整卡点击跳转文章详情。
- ImageViewer 新增 lightbox prop(默认 true),卡片封面传 false
  禁用灯箱以归一为单一跳转交互;文章详情页零改动。
- home.rs 越界页码守卫:分页仅在 total>0 渲染,避免 /page/9999
  出现孤立空分页;错误文案脱敏为"加载失败"。
- search.rs 错误文案脱敏为"搜索失败",与首页/标签页一致。
- HomeSkeleton 卡片 5→10,对齐 POSTS_PER_PAGE。

编辑器上传重构(write/tiptap_bridge):
- consume_upload_event 改用 upload_errors Vec 自身判重,移除
  seen_error_ids 副本状态;Signal 参数加 mut 修复 E0596 编译错误。
- make_upload_closure 构造阶段错误以 rejected Promise 返回而非
  panic,单张坏文件不再拖垮整个编辑器。
- write.rs 移除未用的 success signal,编辑保存后统一跳转 Posts,
  标签分隔符支持半角/全角逗号与分号,提取 META_*_CLASS 常量去重。
- Makefile dev 目标清理 static/ 目录。
2026-06-23 14:14:28 +08:00
xfy
a6d30ed5d9 refactor(write): address code review feedback
- remove duplicate `use dioxus::prelude::*` (keep #[allow] inline with comment)
- update write_editor doc comment: callback-driven init, EditorHandle::drop cleanup
  (no more polling/globals)
- restore empty-url check in make_upload_closure (match original JS `success && url`):
  empty url on success now rejects with clear message instead of inserting broken image
- update AGENTS.md tiptap section: write.rs uses tiptap_bridge, no eval/polling
2026-06-23 13:32:34 +08:00
xfy
a3896c24a5 refactor(write): replace all js_sys::eval with tiptap_bridge bindings
write.rs changes (Tasks 7-11):
- use_drop: EditorHandle::drop replaces eval destroy + global reset (#1)
- init use_effect: closure-driven bridge.create replaces eval initEditor
  script + 100ms ready polling (#2/#3/#4/#5)
- getMarkdown: read via EditorHandle instead of eval (#8)
- delete upload polling use_future: driven by onUploadEvent closure (#6/#7)
- removeUploadByUploadId: call via EditorHandle instead of eval (#9)

Bridge fixes during integration:
- UploadCountsJs: drop Copy derive (wasm_bindgen types can't be Copy)
- split module: shared types compile on both targets, wasm externs gated
- add WritableExt/Readable/Writable trait imports for .write()/.set()
- use FnMut closures (Signal write/set take &mut self)
- consume_upload_event takes &mut Signal params

Also: remove stale window.__tiptap_content in index.ts source-mode handler.
2026-06-23 11:25:06 +08:00
xfy
75adaa2e1f fix(write): use signal for seen_error_ids to satisfy FnMut constraint
dev server (wasm32 target) 暴露的编译错误:
use_future 的 FnMut 闭包要求可重复调用, 但 seen_error_ids 作为局部
HashSet 被 move 进 async 后无法多次消费 (E0507).

改为 use_signal(HashSet::new): signal 是 Copy, 可被 FnMut 多次 move
进 async, 用 .write()/.read() 访问.

教训: cargo check (默认 target) 不编译 #[cfg(target_arch="wasm32")]
代码, 这类改动必须用 dx check 验证. 之前 Task 13 用 cargo check 漏判了.

验证: dx check (wasm32, 通过) + cargo test (384 passed)
2026-06-22 15:55:10 +08:00
xfy
cee4f3f3ef fix(upload): address code review findings
final code review 后的修复:

1. blob 检查收紧(Important): md.contains("blob:") 误伤合法讨论 blob URL
   的代码块/正文,改为检测 markdown 图片语法 ](blob: 才算占位符泄漏
2. 重试错误原地更新(Minor): seen_error_ids 去重逻辑导致重试后再失败时
   顶部提示停留在旧错误文案;改为已存在 id 时原地更新 message
3. destroy 清理 coordinatorRef(Minor): destroy() 调 setUploadCoordinator(null),
   避免 NodeView 指向已销毁的 coordinator(防御性)
4. 删除 NodeView 未用的 editor 字段(Nit): 死代码清理

验证: cargo test (384 passed) / clippy (本次零警告) / dx check / tiptap build 全过
2026-06-22 15:49:23 +08:00
xfy
a10f79d47e feat(write): upload failure notices, save blocking, and server error passthrough
- 顶部上传失败提示:多条堆叠,×关闭同时删除编辑器内失败占位符(避免孤儿)
  for err in upload_errors().clone() 取 owned 值,onclick 捕获 owned id
- 保存拦截双重防护:
  · counts 检查(uploading/error > 0 阻止保存并提示张数)
  · markdown 兜底扫描 blob:/data-upload-state(轮询窗口期漏判防护)
- onImageUpload fetch 改造:非 2xx 时读取服务端 error 字段,
  透传中文错误(如"文件超过大小限制")而非 'Upload failed: 413'
2026-06-22 15:38:53 +08:00
xfy
d90dd60e89 feat(write): poll window.__tiptap_uploads for upload events and counts 2026-06-22 15:35:17 +08:00
xfy
cb14924de8 feat(write): add upload state signals for placeholder tracking 2026-06-22 15:33:43 +08:00
xfy
18500c9496 docs(pages-admin): 补充中文注释 2026-06-12 19:24:22 +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
835d71972c fix(admin): add missing dark mode background colors to skeleton components 2026-06-12 11:15:46 +08:00
xfy
75e0659cb2 fix(admin): 后台管理页改为 CSR 避免闪烁
- dashboard: use_resource → use_signal + wasm32-only 加载
- posts: use_server_future → use_signal + wasm32-only 加载 + 乐观删除
- write: use_resource → use_signal + wasm32-only 加载
- 移除 use_server_future/use_resource 导致的骨架屏闪烁
- 操作按钮使用乐观更新,不调用 restart()
2026-06-11 18:04:07 +08:00
xfy
373d4f09ed refactor: clean up write page formatting and remove separator line
- Reorder imports to group wasm32-gated items together
- Format struct pattern matches for readability
- Remove metadata/editor separator line for cleaner visual flow
2026-06-10 17:50:07 +08:00
xfy
d3c5653808 feat: redesign admin write page with fixed-height editor layout
- Redesign write page UI with cleaner, more immersive editing experience
- Use CSS variables for theme-aware styling (paper-theme colors)
- Make editor fill remaining viewport height with internal scrolling
- Move action bar below editor (left-aligned, non-floating)
- Fix layout: page no longer scrolls, only editor content scrolls
- Update write skeleton to match new layout
- Update admin layout to use h-dvh for write routes to prevent page scroll
- Fix Dioxus.toml dev resource loading to include style.css

Fixes from review:
- Add missing relative positioning for loading overlay
- Use consistent root_class in unauthenticated state
- Use h-dvh instead of h-screen for mobile viewport compatibility
- Ensure skeleton matches actual component layout classes
2026-06-10 17:41:31 +08:00
xfy
a3fa602df2 refactor(api): unify error handling with AppError enum
Replace scattered ServerFnError::new("...") inline calls and utils.rs
helper functions with a single AppError enum that provides:
- Automatic tracing::error logging for system errors
- Safe generic messages to frontend (no SQL/connection detail leaks)
- Typed error variants (Unauthorized, Forbidden, NotFound, etc.)
- 5 unit tests for message passthrough and detail hiding

Removes src/api/utils.rs entirely; all error creation now goes through
src/api/error.rs.
2026-06-10 13:16:06 +08:00
xfy
717266db1e fix: resolve conditional compilation and dead code warnings 2026-06-08 16:11:24 +08:00
xfy
f6db477a88 fix(write): reset tiptap editor state on unmount to prevent blank editor on re-navigation 2026-06-05 18:16:46 +08:00
xfy
72b932c21b fix(write): add allow lint for unused vars in write_editor 2026-06-05 17:58:05 +08:00
xfy
4805f915c7 fix(write): address review feedback - backfill race, load errors, nav delay 2026-06-05 17:51:46 +08:00
xfy
2ecdc09138 feat(write): support edit mode with data backfill 2026-06-05 17:45:54 +08:00
xfy
08bd69d64b feat(write): add onImageUpload callback to tiptap editor 2026-06-05 15:23:36 +08:00
xfy
dd7022ec75 fix: replace select element with overlay pattern to fix dropdown arrow alignment in write page 2026-06-05 11:09:02 +08:00
xfy
58cfcc31bf fix: improve label and button text contrast in write page light mode 2026-06-05 10:33:41 +08:00
xfy
5321b8cf97 refactor: reorganize admin write page layout with card-based sections 2026-06-05 09:58:26 +08:00
xfy
ce14c476b5 refactor: replace string-based navigation with typed Route and Link components 2026-06-04 14:55:18 +08:00
xfy
c6ced73bac fix(admin): resolve compilation errors in posts and write pages 2026-06-03 10:57:22 +08:00
xfy
09060e12c0 fix(admin): cap tiptap editor ready-polling at 100 attempts
Replace infinite loop with bounded for-loop (100 × 100ms = 10s max).
On timeout the skeleton overlay is dismissed so the user can still
interact with the form instead of being stuck forever.
2026-06-03 10:34:06 +08:00
xfy
e6c3cacf12 chore: format with cargo fix 2026-06-03 10:12:04 +08:00
xfy
5544ea0c18 feat(admin): add cover_image input field in write form 2026-06-02 18:22:22 +08:00
xfy
9c5b09a278 chore: code cleanup - formatting, EOF newlines, model helper, and UI tweaks 2026-06-02 17:33:28 +08:00
xfy
df339cb084 feat: add post creation form to write.rs
- Add summary, slug, tags, status fields to editor
- Integrate create_post API with validation
- Add loading and error states
- Keep Tiptap editor initialization intact
2026-06-02 17:33:28 +08:00
xfy
c924b1e643 修复编译器警告并改进代码质量 2026-06-02 17:33:28 +08:00
李林军
4093178fc3 添加tracing日志并重构服务器启动逻辑 2026-05-27 11:39:09 +08:00
xfy
9c834ba1df 添加骨架屏组件,优化 admin 路由切换和编辑器初始化体验
- AdminLayout 使用骨架屏替代简单"加载中"文字,保持布局结构一致避免闪烁
- WritePage 添加编辑器初始化骨架屏和就绪状态轮询
- 新增 admin_skeleton.rs 和 write_skeleton.rs 组件

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-27 09:25:26 +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
f6d60520eb 集成 Tiptap Markdown 编辑器到文章撰写页面
- 新增 libs/tiptap-editor/ 打包子项目(Tiptap Core + StarterKit + Markdown)
- 构建产物输出到 public/tiptap/
- 替换原有的 textarea + pulldown_cmark 预览为 WYSIWYG 编辑器
- Makefile 新增 build-editor target
- Dioxus.toml 引入 editor.js 和 editor.css

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-26 17:46:04 +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