panatgithub_AnkiHeadingSync/docs/2026-04-16PLAN2.md

4.6 KiB
Raw Blame History

模块 1从 Anki 读取 Note Type 字段并建立标题/正文映射

Summary

  • 目标是把当前“靠字段名猜测”的同步方式,升级成“先从 Anki 读取 note type 字段,再由用户确认映射,之后同步严格按映射执行”。
  • 本模块只解决“字段识别与映射配置”,不处理真正的卡片模板 HTML/CSS 编辑;这里把“读取卡片样式”明确落成“读取 note type 与字段结构”。
  • 范围覆盖两类卡:QA/BasicCloze
  • UI 方向固定为:从 Anki 拉取 note type 列表做下拉选择,再点击按钮读取当前 note type 的字段,系统先自动建议,再让用户确认。
  • 映射按“具体 note type”持久化保存为避免同一个模型名在 Basic/Cloze 语义冲突,持久化 key 使用 cardType:modelName

Implementation Changes

  • AnkiGateway / AnkiConnectGateway 增加 listNoteModels(): Promise<string[]>,用于设置页拉取全部 note type 名称;保留现有 getModelDetails(modelName) 负责读取字段名。
  • PluginSettings 增加持久化配置 noteFieldMappings,结构固定为:
    • key: ${cardType}:${modelName}
    • value: { cardType, modelName, loadedFieldNames, titleField?, bodyField?, mainField?, loadedAt }
  • 保留现有 qaNoteType / clozeNoteType 两个设置字段,但设置页改成 Anki 下拉选择,不再靠自由文本输入作为主交互。
  • 设置页拆成两个区块:QA/BasicCloze。每个区块都包含:
    • 当前 note type 下拉框
    • 从 Anki 读取字段 按钮
    • 字段读取结果展示
    • 自动建议后的映射下拉框
    • 保存后的状态提示
  • 自动建议规则固定:
    • Basic 标题字段优先匹配 Front / Title,否则取第一个字段。
    • Basic 正文字段优先匹配 Back / Body / Answer,否则取第二个不同字段。
    • Cloze 主字段优先匹配 Text / Body / Content,否则取第一个字段。
  • NoteFieldMappingService 改为“配置驱动”而不是“仅启发式驱动”:
    • Basic 必须存在 titleFieldbodyField,且二者不能相同。
    • Cloze 必须存在 mainField
    • 没有配置时禁止同步,不允许继续偷偷猜字段。
  • CardRenderingService 的语义输出改成面向“标题片段 + 正文片段”,不要再把 front/backtext/extra 当成固定领域语义。
  • Cloze 的最终拼接策略固定为:mainField = titleHtml + "<br><br>" + bodyHtml;辅助字段本模块不写入,保持空缺。
  • 同步执行前加入映射校验:
    • 选中的 note type 没有已确认映射时,直接报错并提示先去设置页读取字段。
    • 已保存映射里的字段名不再存在于 Anki 当前模型时,直接报错并提示重新读取字段。
  • 老数据迁移策略固定:
    • 旧用户升级后,保留 qaNoteType / clozeNoteType 原值。
    • noteFieldMappings 初始为空。
    • 第一次同步若未配置映射则阻止执行,并给出明确 notice。

Public Interfaces / Types

  • AnkiGateway.listNoteModels(): Promise<string[]>
  • NoteModelFieldMapping:
    • cardType: "basic" | "cloze"
    • modelName: string
    • loadedFieldNames: string[]
    • titleField?: string
    • bodyField?: string
    • mainField?: string
    • loadedAt: number
  • PluginSettings.noteFieldMappings: Record<string, NoteModelFieldMapping>

Test Plan

  • AnkiConnectGateway
    • 能拉取 note type 列表
    • 能读取模型字段
  • 设置持久化:
    • 旧 settings 无 noteFieldMappings 时能正常加载
    • 保存后重新加载仍能还原映射
  • NoteFieldMappingService
    • Basic 按已保存映射输出标题/正文
    • Cloze 按 title + <br><br> + body 输出到主字段
    • 缺映射时报错
    • 映射字段不存在时报错
    • Basic 两个字段选成同一字段时报错
  • 设置页交互:
    • 刷新 note type 列表
    • 读取字段后生成自动建议
    • 用户改选后正确保存
  • 同步用例:
    • 已配置映射时 add/update 正确写入真实 Anki 字段
    • 未配置映射时同步被阻止并提示
    • Anki 模型字段变更后旧映射失效并提示重新读取

Assumptions

  • 本模块只做字段结构读取与映射,不读取 Anki 卡片模板的 HTML/CSS也不做模板编辑器。
  • note type 列表只做运行时拉取,不持久化缓存到 data.json
  • 这一版不保留旧的“无映射时自动兜底同步”路径;安全优先。
  • Cloze 在本模块内采用“标题和正文都进入主字段,辅助字段留空”的规则;如果以后要恢复 Extra/Context,作为下一模块单独扩展。