docs(memory): 第三批修复与三个新踩到的坑

- 2026-10-29.md:第三批 7 项改动与验证数据
- MEMORY.md:三条长期结论 ——
  「用户主动删除 = 真删」(模型全带 DeletedAt,默认 Delete 是软删)、
  「配额必须与内容同事务」(incrementQuotaTx 是唯一实现,且投票口径是票数不是个数)、
  「错误页不套模板」(f.NotFound 不经过组级中间件,注入 template.Data 会 panic)
- topics/quality.md:标注第三批范围

新踩到的三个坑:
1. gofmt 会把注释列表 `// 1) ...` 改写成 `//  1. ...`,被标为未格式化时先排除这个
2. Select(...) 漏列 = 字段静默为空(摘要永远是空串,只有一项测试红)
3. CDP 验证纯前端:chrome 必须作为独立后台进程启动,跟在别的命令后面 `&`
   会随 shell 退出被回收;headless=new 的空标签页 type 常是 other
This commit is contained in:
tamakyi
2026-10-29 17:18:47 +08:00
parent 5def41d0f8
commit 4fcaa197cf
3 changed files with 69 additions and 13 deletions
+15
View File
@@ -41,6 +41,9 @@
- 线上通道 = 七牛;裁决在 `censor/policy.go` + `moderation.Check`,新增调用点必须走 `moderation.Check`,不可用时 fail-closed。
- 严格度存 `users.moderation_strictness`;受处置用户强制 strict(`moderation.EffectiveStrictness`),查询失败回退用户设置。
- 同请求渲染只能用 `ctx.SetError`/`SetInternalError`,不能 `*Flash`。
- 写路径查功能开关用 `db.FeatureStateOfStrict`(失败即拒);`FeatureStateOf` 的
fail-open 只给读展示用 —— 它的默认值对提问/投票是「开启」,等于让一次配置读失败
绕过箱主的关闭与定量上限。
- 处置四级 L1–L4;到期靠 `expires_at` 无 cron;`restrict` 是替换语义;比较用 `RestrictionAtLeast`。
- L2 强制私密须在审核通过后、与写回答同一条 UPDATE(`AnswerByIDPrivate`)。
- `ListAPI` 不经 Pager 中间件,L4 与页面密码须自校验;分享卡拦截须在缓存查询之前。
@@ -54,11 +57,23 @@
- 默认值必须带引号;事务里每句 `tx.WithContext(ctx)`;链式对象带状态,统计/更新各自重建 query。
- 软删除+唯一索引 = 槽位永久占用;级联删除一律 `Unscoped()`。
- **「用户主动删除」= 真删**:模型全带 `dbutil.Model` 的 `DeletedAt`,默认 Delete 是软删 ——
提交记录里的 `voter_ip`/文本、提问里的 `FromIP` 会永久留在库里。删投票/删提问已改
`Unscoped` 并收进一个事务(`Votes.DeleteWithCascade`、`Questions.DeleteByID`)。
- **配额必须与内容同事务**:`incrementQuotaTx(tx,...)` 是唯一实现;别在 handler 里
再补一次 `IncrementQuota`(那是独立写入,失败只 Warn → `quota_count` 永久偏低)。
注意口径按功能不同:提问/私聊是「条数」,投票是「累计收到的票数」。
## 前端样式(topics/style.md)
- `static/css/base.css`(`?v=` 取 `conf.StaticVersion`,改完 +1)。令牌在 `:root` + `html[data-theme="dark"]`,新样式一律 `var(--tb-*)`。
- 移动端(≤640px)语言/主题按钮在固定底栏 `#tb-mobile-utils`;箱主页**有意**无语言切换。
- **错误页不套模板**:`f.NotFound` 不经过组级中间件(`template.Templater`/`Contexter`
连同 session、CSRF 都在 `f.Group` 里),在里面注入 `template.Data` 会 panic。
404/500 统一走 `internal/route/errorpage.go` 的内联 HTML + `i18n.T`,
语言从 `Accept-Language` 猜(`pickErrorPageLang`)。Recovery 也是自写的。
- **提问者找回自己的提问**:`templates/question/{success,list}.html` + `POST /api/v1/ask-status`。
记录只在本机 localStorage;接口必须同时给对 token 才返回信息,三种失败情形响应完全一致。
- UIkit 3.3.3:`.uk-flex::before/::after{display:none}`;主色是编译期常量,需在 base.css 末尾映射。
- 视觉自检:`TEST_PREVIEW=1 go test ./templates -run TestGenPreview`;截图用 `chrome --headless=old`。