来源:
notes/documents/网页端改用_Note_ID_与「其他文档」模块实施记录.md网页端改用 Note ID 与「其他文档」模块实施记录
2026-09-22 一天之内把「网页版按路径认笔记」改成「按 Note ID 认笔记」,并把 notes/ 下不是正式笔记的那 47 篇
分出去单独做一个模块。相关 spec 在 .scratch/web-documents-split-and-note-id-api/(已 resolved)与
.scratch/web-note-identity-by-id/(Q1 被前者回答)。
一句话结果
网页端的「笔记」= notes/documents/ 的 115 篇,每篇按 note_id 取;其余 47 篇进脊上第四格「其他文档」,
按路径取、按目录分组、原样渲染、不搜索。「日程」的笔记线深链也改成 Note ID。线上 aef8363 已 READY。
改了什么
本地事实源(工作区根)
scripts/backfill_note_created_at.py(dry-run 默认):把 115 篇documents/笔记的文件创建时间 写进 front matter 的created_at(日期粒度)。逐条确认过:115 篇全部一致,重跑零变更。scripts/check_note_created_at.py:并排看 文件创建时间 /created_at/ git 首次提交 / 注册时间, 报告落config/note_created_at_report.json。回填后退出码 0(无mismatch/unreadable)。scripts/note_cli.py:新建笔记写created_at(取当天),重同步时沿用文件里已有的值,不被重置。 这一步不可省——create --apply --force会整份重写 front matter,不特意保留就会把创建时间冲掉。
产物(web/scripts/)
generate-notes.mjs产出两个集合:notes(documents/,带id与createdAt)与others。- 构建期两条硬断言:
documents/下有笔记缺note_id、或两个文件共用同一个note_id,直接构建失败。
接口
| 接口 | 服务谁 | 身份 |
|---|---|---|
GET /api/notes/entry?id= |
笔记 + 日程 | Note ID |
GET /api/notes / /api/notes/search |
笔记 | Note ID(只含 documents/) |
GET /api/others |
其他文档 | Note Path |
GET /api/notes/detail?path= |
其他文档(保留原读法) | Note Path |
GET /api/daily/* |
日程 | 笔记线新增 noteId,notePath 降为档号 |
同一接口不再接受两种身份:detail?path= 传 documents/ 路径返回 404 是设计,不是 bug。
前端
- 脊上第四格由占位「材料与来源」落成「其他文档」(ADR-0009 的格数没动)。
- 路由:
?n=装 Note ID、?o=装其他文档路径;旧书签?n=documents/xx.md由前端在已加载的索引里 解析成 id 后改写地址栏,实测可用。 - 页边档号区:笔记是「档号 / 创建 / 更新」,其他文档是「档号 / 分类 / 更新」。
验证
npm run build通过;npm test53/53;npm run lint与tsc -b干净。npm run preview:local+ Playwright:笔记 115 篇且只有「文档」一组;其他文档按 来源 25 / 书籍 11 / 专题 6 / 项目 4 / 知识库 1 分组;旧 path 链接 canonical 成 id; 日程笔记线深链落到?n=note_2972af60fe554c7b;无 console 错误。- 线上:页面引用的 JS 哈希与本地构建一致;
/api/notes/entry、/api/others都在(未登录返回 401, 而不是 404)。
踩到的坑(留给下一次)
- 文件创建时间只在开发机上可信。 构建容器是
git clone,所有文件的出生时间等于检出时刻;本机birthtime却是真的(某篇笔记 2026-06-10、BERT 全文 2026-06-06)。所以创建时间只能落进文件。 而且birthtime会随文件被重新生成而变化——实测有 2 篇就有这个痕迹(提交次日才落盘)。写进created_at之后才稳定。 git log --name-only会漏掉合并提交带来的文件。 2026-08-30 那次迁移是合并进来的,整棵树扫一遍 会看不见那 71 篇的首次提交;改成单路径查询(git log --diff-filter=A -1 -- <path>)才对得上。- React 的 hook 不能写在 early return 之后。 把
useEffect挪到if (!state) return下面就炸 「Rendered more hooks than during the previous render」(minified error #310),整页白屏。 note_cli.py create的 dry-run 与--apply生成的note_id不同,拿 dry-run 的 id 去查status必然 LookupError。真要 id 就执行--apply后从输出里读。git add -u不含新增文件。 有一次只提交了.scratch/的 spec,notes/documents/下的笔记文件 漏了,得补一个提交。- 本地 Playwright 的 chromium 版本与虚拟环境不一致时,需要显式指定
executable_path才能起浏览器。
遗留(不在这轮范围里)
- 那 47 篇「其他文档」不补
note_id、不进注册表、不进日历——这正是本次修掉的错位。 documents/里有 2 篇有note_id却没注册(06_dg板卡X5_BPU推理服务_开放词表检测YOLO-World接入.md、02_dg板卡X5_BPU推理服务_可视化HTML.md)。- 5 个迁移期手写 id 不是
note_<16hex>形态(含上面那个note_dg_bpu_html_viz)。 note_path_aliases里 71 条旧路径现在都不在盘上了:改过名的旧链接仍然打不开(别名在 SQLite 里, 构建期读不到)。notes表的path存了两种前缀形态(41 条带notes/、71 条裸相对路径),对比时要自己归一。