panatgithub_AnkiHeadingSync/docs/settings-anki-template-cache-decisions.md

4.8 KiB
Raw Permalink Blame History

设置页 Anki 模板缓存实现决策

本文锁定本轮“设置页 Anki 模板加载性能优化”的仓库兼容实现方案。

1. 设置模型新增字段缓存

  • 保留现有 ankiNoteTypeCache: string[]
  • 新增:
    • ankiModelFieldCache: Record<string, { fieldNames: string[]; loadedAt: number }>
  • 该缓存只用于设置页 UI 加速。
  • 同步路径继续通过 live getModelDetails() 做实时校验。

2. 字段缓存 normalize 规则

  • ankiNoteTypeCache
    • 继续 trim
    • 过滤空字符串
    • 去重
    • 按稳定字典序保存
  • ankiModelFieldCache
    • 只接受对象
    • key 只保留 trim 后非空的模型名
    • fieldNames 只保留字符串项
    • 对每个模型内的字段名trim、过滤空项、去重保留原出现顺序
    • loadedAt 非有限数字时回退为 0
    • 最终按模型名字典序稳定输出

3. validate 规则

  • ankiModelFieldCache 做结构校验:
    • 顶层必须是对象
    • 每个模型缓存值必须是对象
    • fieldNames 必须是数组
    • 数组项必须全是字符串
    • loadedAt 必须是有限数字
  • normalize 负责“纠偏和过滤”validate 负责拒绝直接传入的非法结构。

4. gateway 接口设计

  • AnkiGroupGateway 中新增:
    • getModelFieldNamesByModelNames(modelNames: string[]): Promise<Record<string, string[]>>
  • AnkiConnectGateway 内部使用一次 multi 请求发送多个 modelFieldNames action。
  • 单个 action 若返回 { error }:跳过该模型。
  • 顶层 multi 若失败:抛错。
  • 本轮不重构通用 invokeMulti();新增一个专门解析该响应的方法,降低行为风险。

5. 设置页卡片 1 的数据来源

  • 页面打开时:
    • note type 下拉来自 ankiNoteTypeCache
    • field 下拉来自 ankiModelFieldCache[selectedModel].fieldNames
  • 若字段缓存存在,则在设置页内即时水合为 loadedModelDetails / draft mapping 可消费的形态。
  • 若某个已选模板没有字段缓存:
    • 不阻塞渲染
    • 直接显示“请先读取字段”占位

6. 手动刷新按钮的精确流程

  • 点击按钮后:
    • listNoteModels() 一次
    • getModelFieldNamesByModelNames(modelNames) 一次
    • 将两份缓存合并成一次 updateSettings()
  • 保存成功后:
    • 刷新当前设置页实例内的 availableNoteModels
    • 用字段缓存为 3 个可见卡片类型生成或刷新 draft mapping
    • 状态显示:
      • x = 模板数量
      • y = basic / qa-group / cloze 中,所选模板已有字段缓存的数量
  • 不再在按钮流程里默认调用 getNoteModelDetails()
  • 不再在按钮流程里默认调用 modelTemplates()

7. 切换 note type 后的行为

  • 切换模板仍立即保存 cardTypeConfigs[configId].noteType
  • 保存后卡片 1 会局部重渲染。
  • 若新模板在 ankiModelFieldCache 中已有字段缓存:
    • 字段下拉立即显示缓存字段
    • draft mapping 若尚不存在,则用 NoteFieldMappingService.suggest() 现算一份 UI draft
  • 不因为只是切换下拉而立刻访问 AnkiConnect。

8. QA Group 行与可见卡片范围

  • 继续维持当前设置页只展示三行:
    • basic
    • qa-group
    • cloze
  • 不把 semantic-qa 加回设置页,避免超出本轮范围。
  • qa-group 当前仓库已经允许普通 note type / 字段映射编辑;本轮不扩大为产品改动,只沿用仓库现状。

9. Cloze 边界

  • 设置页只需要字段名缓存和字段建议。
  • Cloze 完整兼容性校验继续留在同步链路:
    • getModelDetails()
    • isCloze 判定
  • 本轮不把 Cloze 严格校验搬到设置页刷新按钮里。

10. 卡片 1 局部刷新策略

  • 按钮加载状态只存在于 card 1。
  • 刷新操作前后只调用 renderCard("card-types")
  • 不调用整页 display()
  • 缓存保存尽量合并成一次 updateSettings(),避免按钮流程内多次写 settings。

11. 测试决策

  • 配置层:补 ankiModelFieldCache 默认值、normalize、validate 覆盖。
  • gateway为新批量字段接口单独补 multi 请求与解析测试。
  • 设置页:新增缓存优先渲染、刷新按钮调用次数、状态文案、切换模板后即时字段缓存生效等断言。

12. 与原计划的受控偏离

  • 原计划写到“semantic-qa 继续不显示在设置页”,当前仓库确实只显示三行,因此保持不变。
  • 原计划提到“当前 3 个可见卡片类型”,但仓库里的三行是 basic / qa-group / cloze,不是 basic / cloze / semantic-qa;本轮按仓库真实 UI 执行。
  • 原计划说 QA Group 行是托管模型,但当前仓库已经允许 QA Group 行编辑 note type 和字段映射。为了不扩大产品行为回退范围,本轮不顺手收紧它,只做缓存与批量读取优化。