A02 未放餐盘报警认领补录设计
范围仅限 A02「未放餐盘取餐」正式报警:现场人员可选择刷管理卡解除,或放餐盘认领并复用现有本地取餐记录与后台上传链路。
1. 目标
- 刷管理卡解除:只解除报警,不补录取餐记录。
- 放餐盘认领并补录:识别餐盘绑定人员,以认领前最后一次有效的实时逃单重量复用现有本地取餐记录和后台上传链路。
报警发生后,未点击任一按钮前,不响应放盘、普通餐盘码或解除卡;这些操作不能解除报警,也不能进入正常打餐流程。
2. 范围与非目标
本次范围
- 仅改造 A02 报警页和 A02 报警期内的扫码处理。
- 记录报警时间、时长、报警重量、解除方式及认领/刷卡信息。
- 复用
PickMealRecord、本地 DAO、调度器和上传 Worker。 - 在日报警分类日志及既有对应日志中保留记录。
非目标
- 不改 A01、A03 的规则或页面。
- 不新增服务端补录接口、订单事件 ID 或远程管理员页面。
- 不改变现有上传接口、补传策略和服务端计价口径。
- 不做进程被杀后的 A02 操作态恢复,沿用现有中断审计。
3. 业务流程
4. 关键规则
4.1 报警基准与实时逃单重量
当前 A02 检测器以“稳定重量相对无餐盘基线的减重达到阈值”触发报警。触发瞬间保存 baselineWeight、triggerCurrentWeight 和 triggerPickWeight = baselineWeight - triggerCurrentWeight 作为证据。报警触发后基准重量保持不变,但在报警解除前,currentWeight 与 alarmPickWeight = max(0, baselineWeight - currentWeight) 必须实时更新。仅在取餐前页、无餐盘码、秤体稳定时采纳当前重量;餐盘码出现后保留出现前最后一次有效实时值供认领使用。
报警页必须持续展示:本单逃单重量:{alarmPickWeight}g。未选择、等待管理卡和等待餐盘认领时均随有效实时重量更新;餐盘已识别后展示认领前最后一次有效值。
4.2 重量恢复自动解除
当 A02 尚未解除且秤体稳定、仍在取餐前页、无餐盘码,并且 currentWeight >= baselineWeight 时,自动解除报警。该条件表示重量已完全恢复到报警前基准,不使用报警阈值或容差代替。写入 WEIGHT_RECOVERED 和 RESOLVE|method=WEIGHT_RECOVERED,记录基准、触发重量、恢复重量、0g 逃单重量和时长;不创建取餐记录、不调度上传。
4.3 按钮门控
| 模式 | 可响应输入 | 行为 |
|---|---|---|
NONE | 无 | 忽略任何餐盘码、解除卡和放盘动作 |
WAIT_MANAGER_CARD | 有效管理卡 | 记录卡值并解除报警 |
WAIT_TRAY_CLAIM | 有效普通餐盘码 | 查询人员并执行补录 |
两个按钮互斥;进入任一模式后禁用另一个按钮,避免同一报警同时走两条解除链路。处于等待管理卡或等待餐盘码且尚未接收有效输入时,页面显示“返回重新选择”:它只取消本次等待态、停止 60 秒计时并回到 NONE,报警、声光、实时逃单重量和累计时长保持不变,日报警分类日志写入 ACTION_CANCEL。餐盘码已接收、查人或上传正在进行时,以及 LOCAL_SAVE_FAILED 状态下不显示该入口。默认页的“刷管理卡解除”和“放餐盘认领并补录”必须左右等宽地显示在同一行,中间保留 12dp 间距;按钮文字在各自按钮内水平居中,允许最多两行显示,不能因横向排布被截断。进入任一等待态后,继续沿用两个禁用按钮的同一横向位置。
4.4 操作超时
选择任一解除方式后,等待对应输入 60 秒:点击“刷管理卡解除”后等待有效管理卡 60 秒;点击“放餐盘认领并补录”后等待有效餐盘码 60 秒。超时不解除报警、不停止声光报警、不清除报警重量;仅回到 NONE 状态和“请选择解除方式”页面。报警持续时间从触发时起连续累计。日报警分类日志写入 ACTION_TIMEOUT;现场也可在尚未接收有效输入时通过“返回重新选择”提前回到选择页,记录 ACTION_CANCEL。
4.5 放盘认领
- 认领餐盘码不得走普通
scanCodeResult(0, ...)或handleScanResult(...),避免切换正常打餐页、重置基准重量或触发正常取餐逻辑。 - 只在 A02 处于
WAIT_TRAY_CLAIM时复用现有餐盘查人接口;回调时再次确认报警仍未解除且模式未变化。 - 成功读到六位餐盘码即展示餐盘码和“正在查询人员”;服务端
code=0但staff为空时,展示“餐盘未绑定人员,无法认领”,不得显示为未识别。 - 同一餐盘持续放置时只发起一次查询;餐盘码清空后重新放置、换盘或重新选择认领方式才允许再次查询,避免硬件约 100ms 回调重复请求。
- 查到有效人员后,用同一份认领上下文保存取餐记录:首次失败后自动重试 2 次,共 3 次;不得重复查人或产生多条候选记录。
- 三次保存均失败时进入
LOCAL_SAVE_FAILED:停止响应后续餐盘码,隐藏或禁用放盘认领入口,显示“取餐记录保存失败,无法进行放盘补录,请工作人员刷管理卡解除报警。”,仅管理卡可按LOCAL_SAVE_FAILED_ADMIN_OVERRIDE解除;不进入上传队列。 - 保存成功后保持 A02 报警并立即上传。网络超时、断网或可重试服务端异常立即重试 3 次;三次网络失败时保留记录进入既有定时队列,以
TRAY_CLAIM_DEFERRED_NETWORK离线解除,并提示累计营养可能暂未同步。 - 仅当同步或后续 Worker 对同一
alarmId、pickRecordId返回code=0且本地删除成功时,才以TRAY_CLAIM_UPLOAD_SUCCESS解除。成功时若该餐盘仍在当前打餐页,重新查询人员累计;餐盘已离开则下次放盘读取最新累计。 code=1仍按旧策略删除候选记录,但不解除报警;页面提示先绑定餐盘后移开并重新放置,再次认领。- 非网络类服务端失败和本地删除失败保持报警并显示原因。
4.6 刷管理卡解除
仅在 WAIT_MANAGER_CARD 模式接受现有管理卡范围,写入实际扫描卡值、解除时间和持续时长;不创建取餐记录,不上传取餐明细。
5. 本地记录与上传复用
从当前 HomeActivity.uploadPickInfo(int) 抽出可复用私有方法:
savePickMealRecord(String pickerUuid, String trayCode, String pickTime,
String dishUuid, int pickWeight, String source, String alarmId)
正常取餐调用时使用 source=NORMAL;A02 认领使用 source=ANTI_ESCAPE_A02 和报警流水号。为让后台上传结果回写日报警分类日志,pick_record 增加可选 source 与 alarm_id 两列。数据库升级必须采用保留历史数据的 ALTER TABLE 迁移,不能删除旧表重建。
UploadPickMealRecordWorker 保持原上传接口和删除策略,仅对 ANTI_ESCAPE_A02 来源追加日报警分类日志,并通过现有 EventBus 回传 alarmId、pickRecordId 与结果。只有 code=0 且本地删除成功的结果能正常解除匹配的 A02;网络类失败三次后则以已持久化记录进入定时队列作为离线兜底。延迟上传成功后,如果认领餐盘仍是当前餐盘,必须重新查询并刷新人员累计;正常取餐不接收该回传。
6. 日志要求
| 事件 | 必填字段 |
|---|---|
TRIGGER | type=A02、alarmId、triggerAt、baselineWeight、triggerCurrentWeight、triggerPickWeight |
WEIGHT_RECOVERED | alarmId、baselineWeight、triggerPickWeight、recoveredCurrentWeight、recoveredPickWeight=0、durationMs |
ACTION_SELECT | alarmId、action=MANAGER_CARD/TRAY_CLAIM |
ACTION_CANCEL | alarmId、action=MANAGER_CARD/TRAY_CLAIM、cancelAt |
ACTION_TIMEOUT | alarmId、action、waitDurationMs=60000、timeoutAt |
RESOLVE(刷卡) | alarmId、method=MANAGER_CARD、cardCode、durationMs、resolvedAt |
CLAIM | alarmId、trayCode、staffUuid、staffName、pickWeight、pickRecordId |
LOCAL_SAVE_ATTEMPT | alarmId、attempt=1/2/3、trayCode、staffUuid、pickWeight、result |
LOCAL_SAVE_FAILED | alarmId、attempts=3、lastError、trayCode、staffUuid、pickWeight |
UPLOAD_SUCCESS | alarmId、pickRecordId、serverCode=0、message |
UPLOAD_DEFERRED_NETWORK | alarmId、pickRecordId、attempts=3、lastNetworkError |
NEED_TRAY_BIND | alarmId、pickRecordId、serverCode=1、trayCode |
RESOLVE(放盘) | alarmId、method=TRAY_CLAIM_UPLOAD_SUCCESS/TRAY_CLAIM_DEFERRED_NETWORK、durationMs、resolvedAt |
RESOLVE(保存异常) | alarmId、method=LOCAL_SAVE_FAILED_ADMIN_OVERRIDE、cardCode、lastError、durationMs |
UPLOAD_RETRY/FAIL | alarmId、pickRecordId、serverCode、message |
ANTI_ESCAPE|event=TRIGGER|type=A02|alarmId=A02-...|baselineWeight=1000|triggerPickWeight=186|triggerAt=... ANTI_ESCAPE|event=WEIGHT_RECOVERED|type=A02|alarmId=A02-...|recoveredCurrentWeight=1000|recoveredPickWeight=0 ANTI_ESCAPE|event=ACTION_SELECT|type=A02|alarmId=A02-...|action=TRAY_CLAIM ANTI_ESCAPE|event=ACTION_TIMEOUT|type=A02|alarmId=A02-...|action=TRAY_CLAIM|waitDurationMs=60000|timeoutAt=... ANTI_ESCAPE|event=CLAIM|type=A02|alarmId=A02-...|trayCode=123456|staffUuid=...|staffName=张三|pickRecordId=42|pickWeight=186 ANTI_ESCAPE|event=UPLOAD_SUCCESS|type=A02|alarmId=A02-...|pickRecordId=42|serverCode=0 ANTI_ESCAPE|event=RESOLVE|type=A02|alarmId=A02-...|resolveMethod=TRAY_CLAIM_UPLOAD_SUCCESS
普通本地日志记录按钮选择、查人、落库和异常原因;取餐记录日志沿用明细并增加来源/报警流水号;上传日志沿用 Worker 日志,A02 来源同时追加日报警分类日志。
7. 代码改动范围
| 文件/模块 | 改动 |
|---|---|
antiescape/NoTrayPickDetector | 返回或暴露触发时基准重量、当前重量和减重值 |
antiescape/AntiEscapeAlarm | 增加 A02 报警流水号、固定基准重量、触发重量证据和实时逃单重量 |
activity/HomeActivity | 增加 A02 实时重量更新、重量恢复自动解除、按钮门控、认领扫码分支和日志记录 |
widget/AntiEscapeAlarmDialogFragment | A02 增加实时逃单重量、两种解除按钮、等待与认领结果状态展示;A01/A03 不变 |
PickMealRecord、DAO、DB Helper | 增加 source、alarm_id 并做非破坏性迁移 |
UploadPickMealRecordWorker | A02 同步结果追加日报警分类日志,并回传成功、需绑盘或重试结果 |
| 资源与单元测试 | 新增实时重量、自动恢复、按钮、等待、失败文案,并覆盖门控、重量恢复、解除与上传日志分支 |
8. 验收口径
- A02 报警页持续展示“本单逃单重量:xxg”;在无餐盘、稳定状态下按固定基准重量减当前重量实时变化。
- 当前稳定重量恢复至报警前基准重量或更高时,A02 自动解除,记录
WEIGHT_RECOVERED,且不生成取餐记录或上传。 - 未点击任何按钮时,放餐盘、普通餐盘码和管理卡均不解除报警、不进入正常打餐页。
- A02 默认页的两种解除按钮左右等宽、同一行显示,间距为
12dp;按钮文案完整可读,最多在按钮内换两行。 - 刷管理卡仅解除报警,日志包含卡值、报警时长和最终实时逃单重量,不产生取餐记录。
- 选择任一方式后等待 60 秒,超时仅返回选择页;尚未接收有效输入时可“返回重新选择”,报警仍锁定且日报警日志分别出现
ACTION_TIMEOUT或ACTION_CANCEL。 - 本地保存共三次;三次失败时只显示管理卡解除、停止响应放盘并写
LOCAL_SAVE_FAILED。 - 本地保存成功后,网络类上传失败三次可进入定时队列离线放行,显示累计暂未同步提示;非网络失败保持报警。
- 延迟上传成功时当前餐盘仍在打餐页则主动刷新累计,否则下次放盘读取最新累计。
code=1时删除候选记录但不解除报警,页面提示先绑定餐盘后重新认领;绑定后移开并重新放盘可生成新记录。- A01、A03、正常取餐、既有解除码范围和补传策略回归通过。
9. 实施前提
- 管理卡有效范围沿用
888880至888899。 - A02 开关开启时才进入本功能;关闭时维持原普通提示链路。
- 放盘认领以服务端返回
code=0且本地记录删除成功作为常规解除条件;仅网络类失败三次且本地记录已进入定时队列时可离线兜底解除。 - 现有服务端取餐上传接口兼容同一餐盘、菜品和取餐时间的补录记录。