From c2016a8ea59914e5314a84b53fa5c62676da4d23 Mon Sep 17 00:00:00 2001 From: cc Date: Thu, 25 Jun 2026 22:54:23 +0800 Subject: [PATCH] =?UTF-8?q?fix(blog-plan):=20=E4=BF=AE=E5=B0=B1=E5=9C=B0?= =?UTF-8?q?=E7=BC=96=E8=BE=91=E5=90=8E=E6=96=87=E7=AB=A0=E4=B8=8D=E5=88=B7?= =?UTF-8?q?=E6=96=B0=EF=BC=88articleNonce=20=E5=BC=BA=E5=88=B6=E9=87=8D?= =?UTF-8?q?=E6=8C=82=E8=BD=BD=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.8 --- docs/superpowers/plans/2026-06-25-blog-writing.md | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/docs/superpowers/plans/2026-06-25-blog-writing.md b/docs/superpowers/plans/2026-06-25-blog-writing.md index 75cadb5..0f589e6 100644 --- a/docs/superpowers/plans/2026-06-25-blog-writing.md +++ b/docs/superpowers/plans/2026-06-25-blog-writing.md @@ -1258,6 +1258,9 @@ export function BlogPage({ username, token, initialPostId, onSignOut }: BlogPage // 编辑器浮层:editing=true 时无视路由优先显示编辑器;editingPost=null 为新建。 const [editing, setEditing] = useState(false) const [editingPost, setEditingPost] = useState(null) + // 文章重挂载计数:保存编辑后 bump,作为 PostArticle 的 key 强制重拉 + // (否则 id 不变时其 useEffect 不会重新 fetch,显示旧内容)。 + const [articleNonce, setArticleNonce] = useState(0) const refresh = useCallback(() => { setLoading(true) @@ -1288,9 +1291,11 @@ export function BlogPage({ username, token, initialPostId, onSignOut }: BlogPage setEditing(true) } const onEditorSaved = () => { - // 编辑既有文章:hash 仍是 #post/,关掉编辑器即回到该文章(会重拉)。 + // 编辑既有文章:hash 仍是 #post/,关掉编辑器即回到该文章;bump + // articleNonce 让 PostArticle 重挂载、重拉到最新内容。 // 新建:hash 为空,关掉后回列表。两种都刷新列表数据。 setEditing(false) + setArticleNonce((n) => n + 1) refresh() } @@ -1309,6 +1314,7 @@ export function BlogPage({ username, token, initialPostId, onSignOut }: BlogPage } else if (initialPostId) { center = ( " - **Spec coverage**:存储/上限/接口/鉴权(Task 1-2);api 封装 + 派生(Task 3);Markdown(Task 4);编辑器(Task 5);阅读页(Task 6);列表改造 + `#post/` 路由 + 边界态(Task 7)。spec 各节均有对应任务。 - **路由真相源**:列表↔文章统一由 `App.tsx` 经 hash 决定(`initialPostId`),`BlogPage` 仅管编辑器浮层,避免双方争用 URL。编辑器不进 URL(不可分享,符合 spec)。 - **类型一致**:`Post`/`PostInput`/`PostError` 在 Task 3 定义,Task 5/6/7 一致引用;后端 `Post` camelCase 与前端字段对齐。 +- **就地编辑刷新**:`PostArticle` 的 fetch effect 依赖 `[token, id]`,id 不变时不会重拉;故编辑保存后 bump `articleNonce` 并用作 `key` 强制重挂载,保证文章页显示最新内容(Task 7)。 +- **Markdown code 边界**:以 `language-` 类名区分行内/块级,未指定语言的 ```围栏块``` 会被当作行内样式——个人博客可接受(写 ```lang 即可),不为此引 `node` 判定增复杂度。 - **已知取舍**:返回列表用 `window.location.hash = ''` 会留下一个光秃秃的 `#`(cosmetic),换页/刷新无副作用;如介意可在 `backToList` 改用 `history.pushState` + 手动置空 `initialPostId`,但那会让 BlogPage 也参与路由、复杂度上升,故不采用。 ```