文件删除前查引用:被文章/项目/站主头像用着就先挡住

- store.FileReferences(key) 反查谁在用这个文件:文章(封面 + content_md +
  content_html)、项目封面、settings.owner_avatar_key。匹配的键是 files.key 本身
  而不是完整 URL——本地 /uploads/{key}、R2 {publicBase}/{key}、缩略图
  /uploads/thumb/{key} 三种形态都以 key 结尾,换存储端后正文里的老链接照样查得到。
  草稿也算:现在没发布,删了将来发出来就是裂的。
- 按需 LIKE 现扫,不维护计数表:写入口有编辑器、外链转存、短文、项目、头像好几处,
  计数一旦漂移就再也信不过;删文件是低频操作,扫全表几十毫秒换一个永远正确的答案。
- 新端点 GET /api/admin/files/{id}/refs;DELETE 默认对在用文件返回 409(消息带引用数
  和前三个位置名),明确带 force=1 才真删。守卫放在动 blob 之前——存储端一删就没法回头。
- 后台删除弹层先把引用清单摊出来(文章《标题》(草稿)、站主头像),仍然要删才带 force。
  引用查询失败就按无引用走:真被引用时后端会 409,不会静默删掉在用文件。

顺手把另一个 agent 工具的本地草稿目录(.zcode/、.zcodeignore)加进 .gitignore。
This commit is contained in:
Sakurasan committed 2026-09-30 02:03:14 +08:00
1 parent f1e639e0ba
commit 1b3eb870da
8 files changed
+427 -4

No files matched your search

+10
View File
@@ -147,6 +147,16 @@ type FilePage struct {
Size int `json:"size"`
}
// FileRef 是「谁在用这个文件」的一处记录,供删除前的引用检查。
// Kind 取 post / project / avatar;avatar 没有可跳转的行,ID 为 0。
type FileRef struct {
Kind string `json:"kind"`
ID int64 `json:"id"`
Title string `json:"title"`
Slug string `json:"slug"`
Status string `json:"status"`
}
// CommentPage 是后台评论管理的分页容器(含文章标题与发表者)。
type CommentPage struct {
Items []Comment `json:"items"`