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

115 lines
No EOL
4.8 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 设置页 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 和字段映射。为了不扩大产品行为回退范围,本轮不顺手收紧它,只做缓存与批量读取优化。