Skip to content

Latest commit

 

History

History
175 lines (131 loc) · 18.3 KB

File metadata and controls

175 lines (131 loc) · 18.3 KB

v0.12.2:笔记页信息架构重构——三栏布局 + 收件箱动线 + 路由信息收敛

状态:代码已交付(2026-08-23) 依据:用户对话 2026-08-23(笔记页截图 4 点抱怨:碎片捕获无头绪 · 分组混乱交互不明 · 路由理由放置存疑 · 需要自主新建笔记)+ 市场调研(捕获收件箱模式 / Gmail 分类透明性 / 自动组织先例)+ 三项用户裁决(方案 A 三栏 · 二元论碎片 · 升笔记轻确认) 前置:v0.12.1(OCR 引擎回归修复)交付后开工 实施裁决(2026-08-23 用户最终确认):feedCapture 开关默认开启(快速记录收件箱转正,不再是预览);Phase 1 + Phase 2 全量实施

一句话

笔记页从"550px 一栏塞三职(筛选+列表+详情)"重构为三栏分工(组筛选 / 笔记列表 / 阅读编辑),给碎片补上向上的出路(升为笔记),把路由理由与组管理收敛进 ⓘ 弹层,新建笔记零对话框——四个抱怨分别对应:概念分家、职责分离、信息收敛、入口去摩擦。

范围

# 项目 类型 落点
1 三栏布局重构 P0 交互债 240px 组侧栏 + 320px 笔记列表(常驻)+ 阅读/编辑(现有 NoteReadingView);搜索/标签过滤时列表原位切换,不再换布局
2 收件箱动线(碎片→笔记) P0 产品缺口 碎片=原料(二元论裁决);快速记录→收件箱(恒常可见)→ 升笔记/升卡/删除;新增 promote_fragment_to_note(事务建笔记+删碎片)
3 路由信息收敛 P1 信息债 组行小字(系统自动归类/⚠待确认/已改判 + ⓘ);ⓘ 弹层=人话归因+明细折叠+改判+组管理(闪卡/结算/复习本组/周契约)
4 新建笔记零对话框 P2 摩擦 去 window.prompt;新建即编辑态;落未归组(全部笔记可见)
5 文档与治理 伴随 requirements-pool 回填 REQ 编号(实施时)· 本版本文档 · CHANGELOG(交付时)

设计背景

1. 市场调研要点(为何这样改)

调研结论 来源 对应变化
捕获面必须与检索面互相喂养;胜出模式 =「Capture everywhere, triage in ONE inbox」 捕获模式横评(Apple Notes/Notion/Obsidian/MindWiki) 快速记录→收件箱恒常首项,不再藏到 feed 开关后
自动分类:结果可见、原因不展示(Gmail 页签只给"归错了可改",从不解释信号) Gmail Categories 机制、Apple Photos 人物相册:聚类与确认界面分离 路由理由人话一行 + 信号明细默认折叠(REQ-198 "可见"重释:可见=结果+一句话,非算法原文)
组织范式:过滤器/容器/详情严格分离(Gmail 页签、Apple Notes 文件夹+列表+内容、Notion 视图≠容器) NoteLyn 组织系统分析 三栏拆分;组行单击=仅过滤
中文音视频转笔记:听悟/讯飞为"终点/转写工具"(组织缺失或靠用户自理),Ai好记=显式三级目录 通义听悟、讯飞听见、Ai好记实测 组=粗粒度容器(课程/主题/独立),不学三级目录(YAGNI)
新建:主流零对话框、第一行即标题(Apple Notes/Notion/Obsidian 快速捕获) 同上横评 去 prompt,新建即编辑

2. 三栏布局

┌──────────────┬───────────────────┬─────────────────────────────┐
│ 笔记组 (240px) │ 笔记列表 (320px)    │ 阅读 / 编辑(自适应)         │
├──────────────┼───────────────────┼─────────────────────────────┤
│ ⚡ 快速记录    │ 当前视图名 +搜索+排序│ 标题+来源徽标+操作行          │
│ 📥 收件箱 (3) │ 笔记卡片列表        │ Markdown 渲染(回链/任务勾选)│
│ 📁 全部笔记    │ (空态引导)        │ 辅助面板:版本时间线/AI补充    │
│ 📁 组…        │                   │                             │
│ ───────────  │                   │                             │
│ 🎴 复习 12    │                   │                             │
└──────────────┴───────────────────┴─────────────────────────────┘

原 NoteGroupPanel(545 行,职责三合一)按职责拆分:组筛选侧栏 + ⓘ 弹层 + 收件箱视图,各自单文件 ≤300 行(AGENTS.md §3.1)。

3. 碎片语义:二元论(用户裁决)

碎片 = 灵感/待处理原料,不是短笔记。短笔记可直接用「新建笔记」,碎片入口存在的意义是比新建更轻(零标题/零选组/零结构)。现状病根:v0.11.4 明确"碎片→笔记升级不做(身份诚实)"——捕获产物只有升卡/删除两条出口,无向上通道 → 永远躺在隐藏 feed 组里 →"无头绪"。

本版补上出口(对 v0.11.4 范围决策的修订):

捕获(快速记录/剪贴板)──► 📥 收件箱(fragment 列表)
                                 │
              ┌──────────────────┼──────────────────┐
              ▼                  ▼                  ▼
        ✍ 升为笔记           ⚙ 升为闪卡          🗑 删除
        (轻确认)           (现有多句卡生成)   (二次确认)
              │
              ▼
     进入笔记链路:编辑/AI精修/版本/归组/生成闪卡/搜索
  • 升笔记=轻确认(用户裁决):碎片卡内联展开标题(预填首句可改)+ 归组下拉(默认未归组)+ 确认 → promote_fragment_to_note 事务建笔记+删碎片 → 右侧自动打开新笔记(闭环可见)。
  • 收件箱只装碎片;未归组笔记(group_id IS NULL)显示在「全部笔记」——两种实体 UI 分家,各走各的动线(修正:草案中"收件箱=未归组笔记视图"作废,二元论下不成立)。
  • 收件箱恒常可见(固定侧栏首项 + 待处理计数),不再依赖 feedCapture 开关隐藏。
  • 空态引导:「一句灵感,三种归宿——升为笔记沉淀它,升为闪卡复习它,或删除它。」

4. 路由信息收敛(ⓘ 弹层)

组行下方一行小字(系统自动归类 · ⓘ / ⚠ 待确认 · ⓘ / 已改判 · ⓘ;⚠ 时淡橙描边保留),组行单击只做过滤(现状:单击=过滤+展开双动作——"不知道如何去交互"的直接原因)。

ⓘ 弹层四区:

  1. 人话归因:系统按内容特征归入:画面以术语表为主(60 条术语);信号明细(术语表成块/画面文字密度等原文)折叠在"查看明细",默认不展开;
  2. 改判:课程组/主题组/独立组 + 领域下拉 + 确认(修改即记忆,REQ-198 保留);
  3. 组管理:⚙ 生成闪卡 | 🧹 结算(含结算计划)| 🎴 复习本组 | 📥 移入/移出选中笔记;
  4. 周契约卡(REQ-200,组级承诺→组级详情)。

5. 新建笔记(去摩擦)

window.prompt 移除:点「✍ 新建」→ create_note(未命名笔记, "") → 立即进入编辑态聚焦首行(Apple Notes/Notion 式);落未归组(全部笔记可见);标题编辑器内可改。

6. 后端变更清单

变更 说明
promote_fragment_to_note(fragmentId, title, groupId?) 新命令;事务建 notes(source=manual, 正文=碎片文本+图)+ 删 fragment;标题必填(前端保证);groupId 可选
capture_fragment / list_group_fragments / delete_fragment / update_fragment_group 保留,语义不变;删除加二次确认(前端化)
feed 组地形 / fragments 表 保留不动(免迁移;对比 A-2 一元论:免 fragments→notes 迁移)
feedCapture 功能开关 语义改为「快速记录入口」开关;默认值建议改开(本重构即转正,不再是预览)——待实施前用户最终确认

7. 前端变更清单(组件级)

组件 动作
NoteGroupPanel.tsx 拆分为 GroupSidebar.tsx(筛选侧栏)+ RouteInfoPopover.tsx(ⓘ 弹层,≤300 行/文件)
FeedFragmentList.tsx 改造为收件箱碎片卡(升笔记内联表单 + 升卡 + 删)
NotesPage.tsx 三栏编排;groupFilter 只做过滤
NoteListView.tsx 常驻中部(去掉 flatMode 隐藏依赖)
WeekContractCard.tsx 迁入 RouteInfoPopover
handleCreate 去 prompt

关键决策与纪律

  1. 三元分离:筛选(侧栏)/ 列表(中部)/ 详情(右侧)各司一职;一个手势只触发一个动作——回应当前"组头单击=过滤+展开"的双动作歧义。
  2. 碎片是原料(二元论,用户裁决):碎片≠短笔记;补 v0.11.4"升级不做"的出口,范围修订在版本文档记录,不改 ADR。
  3. 结果可见、原因不展示(市场先例):路由理由人话一行 + ⓘ 明细折叠;REQ-198"可见可改"重释为"决策结果可感知、原因可按需、误判可一键纠正"。
  4. 收件箱只装碎片:未归组笔记不混入收件箱(两种实体、两条动线),延续"活沉淀"(note-design-philosophy)——笔记是过渡态,碎片是最粗的证据。
  5. YAGNI:不做拖拽归组(保留"移入选中笔记"按钮)、不做碎片批量处理(逐条,学习仪式感)、不做学习循环功能改动(只挪 UI 位置);三级目录/双链/图谱不做(产品边界,见注记哲学 §二)。
  6. 零后端破坏:Phase 1 纯前端先行;fragments/feed 语义零迁移,单一新命令,测试回归面小。

落地顺序

  • Phase 1(纯前端,零后端改动):三栏拆分 + 组行交互修正 + ⓘ 弹层(迁入路由理由/改判/组管理/周契约)+ 新建去 prompt + 收件箱视图常驻(碎片列表迁移)。
  • Phase 2(后端 + 开关):promote_fragment_to_note + 碎片卡升笔记/升卡接线 + feedCapture 开关语义调整(默认值已裁决:改开)。
  • 验收走查:种子数据过 捕获→升级→编辑→归组→闪卡 全链。

交付记录(2026-08-23)

M1 · 三栏布局重构(Phase 1)

  • NoteGroupPanel.tsx(545 行,三合一)按职责拆分并删除:
    • GroupSidebar.tsx(240px 组筛选侧栏)——行单击=仅过滤(删除"单击=过滤+展开"双动作);行小字=人话归因一行 + ⓘ;⚡ 快速记录、📥 收件箱(恒常首项+计数)、📁 全部笔记、🎴 复习徽标。
    • RouteInfoPopover.tsx(ⓘ 弹层,≤300 行)——四区:人话归因 + 信号明细默认折叠("查看明细"展开)/ 改判(修改即记忆)/ 组管理(生成闪卡·结算含计划·复习本组·移入移出选中笔记)/ 周契约卡(WeekContractCard 独立组件由弹层引用);fixed 锚定组行下方 + 透明背板/ESC 关闭。
  • NotesPage.tsx 三栏编排:view: notes | inbox 中部原位切换;groupFilter 只做过滤;搜索/标签过滤激活时 NoteListView 原位显示结果(不再 flatMode 换布局);focusNoteId 跨页直达简化为滚动定位(无展开依赖);noteTree.ts 树形合并纯函数与单测下线(v0.11.5 树模式被三栏取代)。
  • 行数豁免登记同步(docs/standards/line-limit-exemptions.md):NoteGroupPanel(545)与 NoteEditView(登记值过期,实测 ≤300)登记移除;NotesPage.tsx(328 行)正式登记(编排层内聚,拆分计划:快捷键/收件箱动线回调拆 hooks)。
  • 新建笔记:handleCreate 去 window.prompt —— create_note(未命名笔记,"") → 立即编辑态聚焦首行(NoteEditView autoFocus),落未归组(全部笔记可见),并自动切回笔记视图+全部过滤(新建即见闭环)。

M2 · 收件箱动线(Phase 2)

  • promote_fragment_to_note(fragment_id, title, group_id?) 新命令:单事务(读碎片→建 notes(source=manual, 正文=碎片文本)→图片搬运 fragments/→notes-images/{nid}/ 并写入 markdown 引用→删碎片);图片搬运失败降级纯文本笔记(碎片文本不丢);标题后端必填校验;require_feed_enabled 对称准入。
  • promote_fragment_to_card(fragment_id) 新命令:复用 card_from_fragment 多句卡规则;幂等(card_by_fragment 查重——已升级返回 0 不报错,可重复触发);未归组碎片明确报错引导先归组/升笔记(flashcards.group_id NOT NULL 契约);记 fragment_upgraded 指标(与组生成同口径)。
  • FeedFragmentList.tsx 改造为收件箱碎片卡(全量 active 碎片,不再依赖 feed 组展开):✍ 升为笔记(内联轻确认表单:标题预填首句可改 + 归组下拉默认未归组→确认后右侧自动打开新笔记)/ ⚙ 升为闪卡 / 🗑 删除(二次确认);空态引导"一句灵感,三种归宿"。
  • feedCapture 开关:默认值改开(feature_flags Default + 测试同步);语义改为「快速记录入口」(设置页文案更新);后端命令准入保留(减面不减安全)。

M3 · 验证

  • Rust:cargo test 新增 5 测(碎片升笔记 文本/图片搬运/图片缺失降级/碎片不存在 + flashcard 幂等判据)全绿;cargo clippy 零新增警告;cargo check 通过。
  • 前端:tsc --noEmit 零错误;vitest 67 通过(新增 10 测:routeReason 人话归因 5 + inbox 预填/预览 5 + jsdom 组件测试 收件箱状态机 4(捕获→升笔记→移除/升卡幂等/删除二次确认/空态)+ ⓘ 弹层 4(四区齐全/改判契约/生成闪卡/ESC);测试基建:jsdom + @testing-library/react + vitest include 扩展 .tsx,组件测试按文件 @vitest-environment jsdom 切换环境);npm run build 通过。
  • 待真机验收:种子数据过 捕获→升级→编辑→归组→闪卡 全链(验收标准 1-4 走查)。

与规划的主要差异(诚实记录)

  • ⓘ 弹层定位用视口 fixed 锚定(最初设计为侧栏内 absolute;fixed 简化背板关闭逻辑,视觉等价)。
  • noteTree.ts 被三栏取代后删除(含单测)——v0.11.5 树形合并是"展开组必看笔记"的过渡形态,三栏下组行只过滤、列表常驻,树无消费方(YAGNI);如后续需要"组内速览"再以独立视图恢复。
  • 收件箱碎片卡未逐个显示所属组名(Fragment 契约不含 name;补计需要额外 join——YAGNI,升笔记/升卡时组选择已可见)。

M4 · 新增代码七维审查与即修(2026-08-23 交付后审查)

  • HIGH:promote_fragment_to_note 原实现"伪事务"——with_conn 只给 &Connection 无法开事务,rusqlite 默认 autocommit 使建笔记/删碎片各自提交,④ 失败留"笔记已建/碎片未删"半态;改为直接锁 + conn.transaction()+commit()(与 versioned_save 既有模式一致)。
  • MED:ⓘ 弹层跨组 state 串组——组 A 改判/结算/明细选择(未确认)复用进组 B(key 缺失);修复 key={group.id} 重置表单态 + GroupSidebar 组件测试(切换组判类回到目标组 kind)。
  • MED:升笔记 onPromoted 只调 load("") 不同步清 keyword/tagFilter——防抖 effect 用旧搜索词重新覆盖列表(新笔记"被搜索态淹没");修复同步清空三过滤态。
  • LOW:捕获/弹层变更后双 load(显式 load + onChanged→refreshToken 再 load)→ 统一由 refreshToken 驱动;升卡成功 setErr 重复;升笔记标题输入补 maxLength=100(与后端 TITLE_MAX_CHARS 同口径);inbox.ts 截断改按码点切(防切半代理对残字);文档"視口"错字。
  • 观察项(登记不修):archived 碎片可升笔记(与 delete/update 旧命令行为一致);升卡成功静默(幂等语义,验收允许);编辑态+弹层同开时 ESC 双触发(边缘场景);db 层文件名沿用碎片名(同毫秒+4hex 后缀碰撞概率 1/65536,单笔记同目录冲突极低)。
  • 验证:cargo check/clippy 通过、promote 4 测全绿;tsc 零错误、vitest 83 通过(新增 GroupSidebar 2 测:组行单击仅过滤 + 弹层串组重置)、build 通过。

验收标准

  1. 侧栏组行单击=仅过滤(中部列表切换,无展开动作);⚠ 待确认组淡橙描边小字显示;ⓘ 弹层四区齐全,明细默认折叠。
  2. 快速记录捕获 → 收件箱计数 +1;升笔记(轻确认)→ 右侧自动打开新笔记、碎片从收件箱移除、新笔记在「全部笔记」可见;升卡幂等可重复触发;删除有二次确认;空态文案正确。
  3. 「✍ 新建」无 prompt,直接进入编辑态,落未归组;搜索/标签激活时中部列表原位切换为搜索结果(布局不变)。
  4. ⓘ 弹层内改判后组行小字变「已改判」且路由记忆生效(再次归组走新偏好);弹层内生成闪卡/结算/复习本组/周契约可用。
  5. 全量回归:cargo test(含新命令单测)/ cargo clippy / npx tsc --noEmit / npx vitest run / npm run build 全绿;前端组件测试覆盖收件箱状态机(捕获→升笔记→移除)与 ⓘ 弹层交互。

关联

  • note-design-philosophy.md(活沉淀:笔记=证据到知识过渡态)
  • requirements-pool:REQ-195198(组容器/路由可见可改·本版重释)、REQ-199201(内容分型/周契约/feed 消费闭环·本版补升级出口)
  • v0.11.md(v0.11.5 树形合并为本版三栏重构的前身)· v0.12.0.md · v0.12.1.md
  • 市场调研:捕获收件箱模式(MindWiki 横评)· 自动组织透明性(Gmail/Apple Photos)· 中文音视频笔记横评(听悟/讯飞/Ai好记)