DishRecognitionActivity 自动识别 / 自动支付需求整理
1. 背景
DishRecognitionActivity 当前已具备以下基础能力:
- 菜品自动识别预览与识别结果刷新
- 加菜抽屉与已加菜浮层
- 手动输入固定金额
- 手动点击“去支付”
页面上已增加两个按钮:
本文件用于整理这两个能力在 DishRecognitionActivity 内的完整业务规则,补齐边界场景,作为下一步开发实现依据。
2. 需求目标
实现一套可预测、可恢复、防误触发的自动化流程:
- 自动识别负责驱动识别循环
- 自动支付依赖识别结果稳定后自动拉起支付
- 任意会打断用户确认、支付、加载的弹框出现时,自动流程暂停
- 支付完成后页面回到统一初始状态,准备下一单
3. 状态定义
建议把状态拆成两层,避免后续逻辑混乱。
3.1 用户意图状态
userAutoRecognitionEnabled
userAutoPayEnabled
- 用户是否希望开启自动支付能力
- 初始值:
false
- 注意:这里的“开启”更准确地说是“允许系统进入自动支付”
3.2 运行态状态
isRecognitionPaused
isAutoPayPaused
isPaymentProcessing
stableRecognitionCount
lastRecognitionSnapshot
3.3 暂停原因集合
建议不要只用一个布尔值控制暂停,而是维护“暂停原因集合”,例如:
ADD_DISH_DRAWER
ADD_DISH_POPUP
PROGRESS_DIALOG
PAYMENT_FLOW
PAYMENT_RESULT_DIALOG
ACTIVITY_NOT_FOREGROUND
这样在多个弹框叠加时,不会出现“先来的弹框还没关闭,后来的弹框关闭后却误恢复自动流程”的问题。
4. 初始状态
进入 DishRecognitionActivity 后,初始状态统一定义为:
- 自动识别:默认打开
- 自动支付:默认关闭
- 稳定计数:
0
- 当前订单内容:
- 未进入支付流程
- 无暂停原因
说明:
- 这里的“自动识别默认打开”是指用户意图打开,且在没有暂停原因时应实际执行识别。
- “自动支付默认关闭”是指即使识别结果稳定,也不会自动发起支付,除非后续满足开启条件。
5. 核心业务规则
5.1 自动识别规则
- 页面初次进入后,自动识别默认开启。
- 当存在任一暂停原因时,自动识别暂停。
- 暂停解除后:
- 若
userAutoRecognitionEnabled = true,则恢复自动识别。
- 若用户手动关闭了自动识别,则不恢复。
- 自动识别关闭时:
- 不再发起新的识别请求
- 已返回的识别结果可以继续展示,但不更新
- 自动支付必须同时不可执行
5.2 自动支付规则
- 自动支付初始默认关闭。
- 自动支付依赖自动识别,自动识别关闭时,自动支付必须关闭。
- 当识别结果“连续 5 次不改变”时,自动支付进入打开状态。
- 当识别结果发生变化时,自动支付立即关闭。
- 当存在任一暂停原因时,自动支付暂停。
- 自动支付一旦真正发起支付请求,必须立即进入支付中状态,直到收到支付结果前不得再次触发。
- 当识别结果中存在任一未识别菜品时,自动支付不得进入开启状态。
- 底部支付按钮需与支付状态同步;自动支付不可用时按钮不可点击并显示灰色,可用时恢复当前可点击样式。
5.3 弹框/遮罩暂停规则
以下场景出现时,自动识别和自动支付都必须暂停:
- 加菜抽屉显示时
- 已加菜浮层显示时
- 其他菜品识别页面上的业务弹框显示时
showProgress() 弹框显示时
- 已进入支付流程时
- 支付结果弹框显示时
恢复规则:
- 对应弹框关闭后,不是直接无条件恢复,而是先判断是否仍存在其他暂停原因。
- 只有暂停原因集合为空时,才允许按用户意图恢复自动识别/自动支付。
5.4 支付完成后的复位规则
拿到支付结果后,无论成功还是失败,页面都回到初始状态:
- 自动识别恢复为默认打开
- 自动支付恢复为默认关闭
- 稳定计数清零
- 清空上一次识别稳定性快照
- 清空识别结果展示
- 清空加菜内容
- 清空固定金额
- 关闭所有与本单相关的弹框
- 退出支付中状态
说明:
- 这里的“拿到支付结果”建议定义为:收到支付成功/失败回调并完成结果展示后,页面准备进入下一单。
- 若产品希望用户先看完支付结果弹框,再重置页面,则应在“支付结果弹框自动消失/手动关闭”后执行复位;开发时需要统一选一个时机,避免 UI 抖动。
6. 识别稳定性判定规则
“连续 5 次不改变”需要明确什么叫“不改变”,建议定义如下:
识别结果快照一致,需同时满足:
- 菜品数量一致
- 每个菜品的
goodsCode 一致
- 每个菜品价格一致
- 每个菜品框位置信息一致,或在允许误差范围内一致
- 顺序一致;若 SDK 返回顺序不稳定,则开发时应先排序再比较
稳定计数规则:
- 第一次拿到有效识别结果时:
- 记录为
lastRecognitionSnapshot
stableRecognitionCount = 1
- 新结果与上一次快照相同:
stableRecognitionCount += 1
- 新结果与上一次快照不同:
- 更新
lastRecognitionSnapshot
stableRecognitionCount = 1
- 自动支付关闭
- 当
stableRecognitionCount >= 5 时:
建议补充:
- 空结果不参与“自动支付打开”判定。
- 连续 5 次空结果,不应打开自动支付。
- 识别结果中只要混入未识别菜品,即使其他已识别菜品已连续稳定 5 次,也不应打开自动支付。
7. 订单变更规则
除了“识别结果变化”,以下变化也应视为“当前订单发生变化”,需要关闭自动支付并重新计数:
- 用户新增加菜
- 用户删除已加菜
- 用户修改固定金额
- 用户点击重置
- 用户手动修改了识别结果对应的菜品
原因:
- 自动支付本质上对应“当前订单已稳定”
- 订单任何组成项变化,都意味着不能沿用上一轮的自动支付资格
因此建议定义统一事件:
触发后执行:
- 自动支付关闭
stableRecognitionCount = 0
- 清空或重建稳定性快照
8. 建议补充的边界场景
你给出的 4 条规则已经覆盖了主流程,但还没有完全覆盖以下场景,建议补充进需求。
8.1 用户手动点击开关
需要明确:
- 用户手动关闭自动识别时,自动支付是否强制关闭
- 用户手动打开自动支付时,是否允许立即打开
- 建议:不立即进入可支付状态,仍需满足“识别结果连续 5 次稳定”后才可真正触发支付
- 用户手动关闭自动支付时,后续即使继续稳定,也不再自动支付,直到用户再次允许
建议实现为:
8.2 弹框关闭后的恢复策略
需要明确:
- 加菜抽屉关闭后是否立即恢复自动识别
- 建议:恢复,但稳定计数清零,重新开始统计 5 次稳定
- 已加菜浮层关闭后是否恢复自动识别
showProgress() 关闭后是否恢复
原因:
- 弹框期间画面和订单都有可能变化
- 继续沿用之前计数容易误触发自动支付
8.3 支付进行中防重入
需要明确:
- 自动支付已触发后,不能再次触发支付
- 用户手动点击“去支付”时,如果已经处于支付中,应直接拦截
- 支付结果弹框未关闭前,不能发起新支付
8.4 空订单 / 空识别结果
需要明确:
- 当前订单金额为 0 时,自动支付不得触发
- 当前没有任何识别结果、没有加菜、没有固定金额时,自动支付不得触发
- 只有固定金额但无识别结果时,是否允许自动支付
- 建议:不允许自动支付,只允许手动支付
- 原因:自动支付的前提是“菜品识别结果稳定”
8.5 页面生命周期
需要明确:
onPause() / onStop() 时,自动识别和自动支付暂停
- 页面回到前台后:
- 自动识别按用户意图恢复
- 自动支付恢复为关闭,并重新开始稳定计数
建议不要跨前后台保留“已稳定 4 次”之类的中间态。
8.6 支付失败后的处理
需要明确:
这里有两种方案:
- 方案 A:失败也回到初始状态
- 与你当前第 4 条完全一致
- 优点:流程简单,适合纯自动收银场景
- 风险:失败订单丢失,用户需要重新摆盘或重新输入
- 方案 B:失败保留当前订单,但自动支付恢复关闭
如果按你目前描述,建议本期采用方案 A,并在文档中明确“支付成功和失败都清单复位”。
9. 推荐统一状态机
建议按以下状态流转实现:
INITIAL
RECOGNIZING
RECOGNITION_PAUSED
AUTO_PAY_READY
PAYING
PAYMENT_RESULT
RESETTING
10. 最终需求口径
以下内容可直接作为开发需求。
10.1 开关默认值
- 进入
DishRecognitionActivity 时:
10.2 暂停规则
- 当页面出现任意业务弹框、加菜抽屉、已加菜浮层、
showProgress() 弹框、支付流程弹框、支付结果弹框时:
10.3 自动支付开启规则
- 只有在自动识别开启且无暂停原因时,才允许进行稳定性统计。
- 当识别结果连续 5 次不改变时:
- 当识别结果发生变化时:
10.4 订单变更规则
以下任一情况都视为订单变更:
- 识别结果变化
- 加菜增加
- 加菜删除
- 固定金额变化
- 用户重置订单
订单变更后统一执行:
10.5 自动支付触发限制
自动支付只有在以下条件同时满足时才允许真正发起:
- 自动识别处于开启且非暂停状态
- 自动支付处于允许状态
- 识别结果已连续稳定 5 次
- 当前不在支付中
- 当前订单金额大于 0
- 当前订单中存在有效识别菜品
10.6 支付中的规则
- 自动支付一旦发起支付请求:
- 自动识别暂停
- 自动支付暂停
- 页面进入支付中状态
- 不允许重复发起支付
10.7 支付结果后的规则
- 收到支付成功或失败结果后:
- 展示支付结果弹框
- 弹框展示期间,自动识别和自动支付继续暂停
- 支付结果处理完成后:
- 页面整体恢复到初始状态
- 自动识别默认开启
- 自动支付默认关闭
- 清空本单所有中间数据
11. 开发实现建议
建议在代码里显式拆出以下方法,避免逻辑散落:
setUserAutoRecognitionEnabled(boolean enabled)
setUserAutoPayEnabled(boolean enabled)
pauseAutomation(PauseReason reason)
resumeAutomation(PauseReason reason)
onRecognitionSnapshotChanged(snapshot)
onOrderContentChanged()
tryEnterAutoPayReady()
tryTriggerAutoPayment()
resetToInitialStateAfterPayment()
建议额外增加日志埋点,便于联调:
- 自动识别开关变化
- 自动支付开关变化
- 暂停原因增加/移除
- 稳定计数变化
- 自动支付触发原因
- 自动支付被拦截原因
12. 结论
你原来的 4 条规则已经覆盖了主路径,但还缺少以下关键约束:
- 用户手动开关后的优先级
- 弹框关闭后的恢复策略
- 订单内容变化不仅包含识别结果变化,还包括加菜和固定金额变化
- 空结果/零金额时禁止自动支付
- 支付中的防重入
- 前后台切换后的重置策略
建议按本文件的完整口径执行,这样下一步编码时状态边界会清晰很多,也能避免自动支付误触发。