mirror of
https://github.com/panatgithub/AnkiHeadingSync.git
synced 2026-07-22 06:51:43 +00:00
- 设置页在有缓存时立即显示缓存摘要,并在打开时只做一次轻量 note type freshness 检查 - 手动读取仍负责完整模板与字段刷新,不会在页面打开时读取所有字段 - Add tests and docs for cache summary, stale-cache warning, and failed background checks
131 lines
No EOL
5.7 KiB
Markdown
131 lines
No EOL
5.7 KiB
Markdown
# 设置页 Anki 模板缓存状态差距审计
|
||
|
||
本文基于当前仓库真实实现,审计“设置页模板缓存状态显示 + 后台轻量 freshness 检测”的落地差距。
|
||
|
||
## 1. 当前设置页已是 cache-first 下拉,但不是 cache-first 状态
|
||
|
||
- 入口在 [src/presentation/settings/PluginSettingTab.ts](src/presentation/settings/PluginSettingTab.ts)。
|
||
- `renderCardTypesCard()` 打开时会先执行 `hydrateVisibleCardTypeCaches()`。
|
||
- note type 下拉来自:
|
||
- `availableNoteModels`,若为空则退回 `settings.ankiNoteTypeCache`
|
||
- 字段下拉来自:
|
||
- `settings.ankiModelFieldCache` 水合出的 `loadedModelDetails`
|
||
- 再经 `getCurrentMappingForConfig()` 生成 draft mapping
|
||
|
||
这说明缓存实际上已经参与首屏渲染,当前问题不是“缓存没被用”,而是“状态文案没有反映缓存可用性”。
|
||
|
||
## 2. 当前首屏状态文本仍固定为 idle
|
||
|
||
- 当前类内状态是:
|
||
- `cardTypeStatus: UserFacingMessage = NOTE_TYPE_STATUS_IDLE`
|
||
- `NOTE_TYPE_STATUS_IDLE` 指向 `settings.mapping.status.idle`。
|
||
- `renderCardTypesCard()` 直接渲染 `renderUserFacingMessage(this.cardTypeStatus)`。
|
||
- `cardTypeStatus` 只会在以下情况变化:
|
||
- `saveCardTypeConfig()` 校验失败
|
||
- `loadAnkiCardTypeConfig()` 开始 / 成功 / 失败
|
||
|
||
结果:即使已有 `ankiNoteTypeCache` 和 `ankiModelFieldCache`,首次打开设置页仍显示“请先从 Anki 刷新”语义,而不是缓存摘要。
|
||
|
||
## 3. 当前设置页打开时不会做任何后台 freshness 检测
|
||
|
||
- `display()` -> `renderCard("card-types")` -> `renderCardTypesCard()` 的当前路径里没有自动调用:
|
||
- `listNoteModels()`
|
||
- `getModelFieldNamesByModelNames()`
|
||
- `getNoteModelDetails()`
|
||
- 唯一主动访问 Anki 的入口仍是点击“手动读取 Anki 里的模板配置”。
|
||
|
||
这与目标方案的差距是:当前没有“只跑一次 modelNames 的轻量后台检测”。
|
||
|
||
## 4. 当前完整刷新流程已经符合“手动触发全量字段读取”约束
|
||
|
||
- `loadAnkiCardTypeConfig()` 当前真实流程是:
|
||
- `listNoteModels()` 一次
|
||
- `getModelFieldNamesByModelNames()` 一次
|
||
- `updateSettings({ ankiNoteTypeCache, ankiModelFieldCache })`
|
||
- `hydrateVisibleCardTypeCaches()`
|
||
- `syncQaGroupMappingFromCache()`
|
||
- `renderCard("card-types")`
|
||
- 当前不会在设置页打开时读取所有字段。
|
||
|
||
这意味着本轮应保留该完整刷新流程,只新增轻量 `listNoteModels()` 检测,不改 full refresh 语义。
|
||
|
||
## 5. 当前 card 1 已具备局部刷新壳层,可直接复用
|
||
|
||
- `display()` 只在首次进入时 `containerEl.empty()` 和初始化 card shells。
|
||
- 后续都是 `renderCard(cardId)` 的局部刷新。
|
||
- `loadAnkiCardTypeConfig()`、`saveCardTypeConfig()`、`saveFieldMapping()` 等都只刷新 `card-types` 卡片。
|
||
|
||
这与目标方案一致:后台检测完成后只需 `renderCard("card-types")`,不需要整页重建。
|
||
|
||
## 6. 当前没有“一次性检测状态”或“override 状态”的分层模型
|
||
|
||
- 当前只有一个 `cardTypeStatus` 字段,同时承载:
|
||
- idle
|
||
- manual refresh loading
|
||
- manual refresh success
|
||
- manual refresh failure
|
||
- validation failure
|
||
- 没有单独的:
|
||
- cache freshness check 状态
|
||
- status override
|
||
- detected live note type list
|
||
- one-shot lifecycle promise
|
||
|
||
结果:如果直接把后台检测结果写回 `cardTypeStatus`,会和手动刷新成功/失败状态互相覆盖。
|
||
|
||
## 7. 当前没有防重入机制来保证“一次生命周期只检测一次”
|
||
|
||
- 现在 `renderCard("card-types")` 会在很多交互后被反复调用:
|
||
- display 初始渲染
|
||
- toggle/heading/note type 变更
|
||
- QA Group warning acceptance
|
||
- manual refresh 前后
|
||
- 但类内没有任何 `Promise` 或 `status` 标记来阻止重复启动 live 检测。
|
||
|
||
因此如果要加后台检测,必须把“是否已检测过/是否检测中”挂在 settings tab 实例上,而不是放在 render 逻辑里临时判断。
|
||
|
||
## 8. 当前测试已证明缓存渲染存在,但未覆盖状态与后台检测
|
||
|
||
- [src/presentation/settings/PluginSettingTab.test.ts](src/presentation/settings/PluginSettingTab.test.ts) 当前已经覆盖:
|
||
- `ankiNoteTypeCache` 渲染 note type 下拉
|
||
- `ankiModelFieldCache` 渲染字段下拉
|
||
- 手动完整刷新只触发 `listNoteModels()` + `getModelFieldNamesByModelNames()`
|
||
- `getNoteModelDetails()` 在设置页刷新路径中不应被调用
|
||
- 但未覆盖:
|
||
- 有缓存时首屏状态摘要
|
||
- 首屏后台 `listNoteModels()` 轻量检测
|
||
- 检测 changed / failed 分支
|
||
- 无缓存时不启动后台检测
|
||
- 手动 refresh 成功后清除 changed 提示
|
||
|
||
## 9. 当前 i18n 里缺少缓存状态分层文案
|
||
|
||
- 当前 card types 相关文案已有:
|
||
- `loadedSummary`
|
||
- `failedLoad`
|
||
- `failedSave`
|
||
- `loadAnki.loading`
|
||
- 但没有:
|
||
- `cacheEmpty`
|
||
- `cacheSummary`
|
||
- `cacheChanged`
|
||
- `cacheCheckFailed`
|
||
|
||
结果:即使实现了 cache-aware status,也没有现成 i18n key 可用。
|
||
|
||
## 10. 结论
|
||
|
||
当前仓库与目标方案的差距主要集中在状态模型,不在缓存渲染主链:
|
||
|
||
1. 缓存已经用于下拉和字段渲染,但状态文本仍是固定 idle。
|
||
2. 设置页打开时没有任何轻量 `modelNames` freshness check。
|
||
3. 当前缺少 cache status 与 manual refresh status 的分层模型。
|
||
4. 当前缺少防止重复后台检测的实例级状态。
|
||
5. 当前测试和 i18n 都还不知道这套缓存状态语义。
|
||
|
||
因此最安全的仓库兼容路径是:
|
||
|
||
1. 保留现有缓存渲染和 manual full refresh 流程。
|
||
2. 新增实例级的一次性 `listNoteModels()` 后台检测状态。
|
||
3. 用统一的 `getCardTypeStatusMessage()` 计算首屏状态与 override 状态。
|
||
4. 让后台检测只影响 card 1 的状态提示,不触碰 `data.json` 和字段缓存。 |