新学习商品即时名称与计价设计

目标与边界

同一设备学习一个菜品或餐具成功后,首次返回识别页即可显示服务端商品名称,并按该商品的服务端价格参与现有计价规则;不等待全量商品目录同步。菜品模式和餐具模式共用流程,模式决定服务端返回什么商品,不新增客户端商品类型判断。

本设计不改变 SDK 学习算法、商品价格来源、菜单限制或自动支付门槛;不把学习记录同步等同于商品目录同步。跨设备新增商品因缺少本机选中时的完整商品资料,走后台目录补全,不承诺立即计价。

现状与根因

NewDishLearningActivity 和识别页的矫正学习入口均通过 getDishList 收到完整 DishBean,随后转换为仅供页面展示的 DishLearningDish。学习图片上传和 SDK 学习成功后,没有把原始 DishBean 写入 DishCatalogRepository。识别页按 SDK 商品编码查本地目录;未命中时回退到 SDK 返回的名称,而设备上的 SDK 名称可能就是 UUID。学习记录同步/数据矫正只处理图片与 SDK 学习数据,不刷新本地商品目录。识别页重新进入时也不强制全量同步;按需目录同步有六小时间隔。

方案选择

  1. 推荐:单商品增量入库。保留选中商品的原始服务端 DishBean,学习成功后只更新这一个商品的 SQLite 与内存缓存。无需新的服务端接口,学习完成后即可离线识别名称和价格。
  2. 每次学习后全量同步目录:一致性直观,但数据量和网络耗时较大,不适合作为返回识别页的前置条件。
  3. 只维护临时 UUID→名称映射:展示快,但缺少可靠价格与持久性,不能满足立即计价。

数据与组件流程

  1. 两个学习入口在 getDishList 页数据中保留每个可选商品的完整 DishBean,以稳定商品编码关联页面选项;不能从格式化后的名称或价格文本反向构造商品。切换搜索、分类或页面时,所选商品快照必须仍与当前选项编码一致。
  2. 当至少一张图片上传、保存并得到 SDK 学习成功响应后,将该商品交给目录仓库执行 upsertServerDishAsync。新增接口负责校验商品编码及名称、在现有单线程 I/O 队列中写 SQLite,再更新内存缓存,最后在主线程回调。它只改一条记录,不修改“上次全量同步时间”。
  3. 学习页仅在单商品入库完成后报告“学习完成、可识别计价”;返回识别页时使用现有结果重绘及后续帧识别,新 UUID 立即命中本地目录。价格来自原始 DishBean,仍受现有菜单和大于零金额等支付规则约束。
  4. 单商品写入与全量替换须串行化。对学习成功前已发起、可能持有旧服务端快照的全量同步,最终替换时保留/重放新商品,避免覆盖;学习成功后新发起的全量同步以服务端目录为权威,用于价格变化、删除和跨设备纠偏。
  5. 对本机没有选中快照的未知 UUID(例如跨设备学习),同一编码在一轮补全中仅触发一次后台目录同步,不阻塞摄像头;失败后可在网络恢复或用户重试时再发起。同步完成后重绘当前结果。补全中的编码在等待或失败期间显示“商品资料同步中/未同步”,不直接显示 UUID,也不参与自动计价;不改变其他既有未知结果的业务规则。

失败处理

验证标准

  1. 新餐具与新菜品各学习一次,成功返回后的首个识别结果显示正确名称、价格;支付状态仍遵守既有金额与稳定性门槛。
  2. 连续学习不同商品、重复学习同一商品,不串名、不重复目录记录;应用重启后仍能解析。
  3. 断网返回、单条数据库写入失败、SDK 部分学习成功、学习与全量同步并发,均有可解释结果且不重复上传。
  4. 未知 UUID 只发起一次后台补全;补全成功后自动重绘,失败不展示原始 UUID 且不误计价。
  5. 比较学习成功到识别就绪的时长,确认该路径不等待全量商品目录请求;真机复测名称、金额及帧流畅度。

预计改动范围