消费模块语音提示与读卡器状态布局设计
文档信息
| 字段 | 内容 |
| 所属项目 | ZhctTrayBindingMachine |
| 设计范围 | 消费模块就餐人员语音提示、读卡器异常提示位置 |
| 版本 | v1.0 |
| 状态 | 已确认,待生成实施计划 |
| 日期 | 2026-08-29 |
| 主要受众 | 就餐人员 |
1. 背景与结论
消费流程当前主要依赖页面文案提示,仅有“请放卡片进行支付”语音。就餐人员在看向餐盘、卡片或读卡区时,可能错过支付状态变化;但如果播报首次读卡成功、写卡成功等技术阶段,又会造成提示密集、术语难懂,并可能让用户误以为交易已经完成。
最终采用“用户动作 + 业务结果”语音策略:只在就餐人员需要执行动作、获知最终结果或规避重复扣款风险时播报。首次读卡成功、写卡成功等内部阶段不单独播报;任何已经尝试扣款但无法确认最终结果的异常,都不能简单播报“支付失败”。
读卡器异常文字只做水平镜像:从屏幕右侧移到左侧对应位置,上下位置、字号、颜色、外边距数值和显示条件均保持不变。
2. 目标与范围
2.1 目标
- 让就餐人员无需持续盯住屏幕,也能正确完成放卡、等待和取卡动作。
- 明确区分支付成功、未扣款失败和扣款结果不确定,避免重复刷卡。
- 避免播报读卡、写卡等内部技术阶段。
- 防止同一交易状态因轮询、页面刷新或回调重复而连续播报。
- 保持语音与页面业务文案的语义一致。
- 将读卡器异常提示移动到当前右侧位置的左侧镜像位置。
2.2 范围内
- 正金额订单的等待放卡、支付处理中和最终结果语音。
- 零金额订单的放卡核验和最终结果语音。
- 无待支付订单、读卡失败、交易结果待确认、读卡器不可用等异常语音。
- 语音开关、去重、优先级和播放生命周期。
- 读卡器异常提示的水平镜像布局。
- 语音策略单元测试、页面布局检查和真机验收规则。
2.3 范围外
- 不改变消费交易协议、扣款顺序和后台上报规则。
- 不向就餐人员播报首次读卡成功、写卡成功等技术阶段。
- 不新增联网 TTS;继续使用本地语音资源和现有语音开关。
- 不改变读卡器连接状态的判定逻辑和红字显示条件。
- 不调整读卡器异常文字的纵向位置、样式或内容。
3. 方案对比与选型
| 方案 | 说明 | 优点 | 问题 | 结论 |
| 全阶段播报 | 首次读卡、写卡及各处理阶段均播报 | 技术过程完整 | 频繁、术语化,容易把阶段成功误认为支付成功 | 不采用 |
| 用户动作 + 业务结果 | 只播报需要动作、最终结果和安全风险 | 清晰、节制,适合就餐人员 | 需要准确分类交易结果 | 采用 |
| 仅最终结果 | 只播报支付成功或异常 | 最安静 | 用户可能过早拿卡,不适合需持续放卡的读卡器 | 不采用 |
4. 语音提示清单
4.1 必须播报
| 业务场景 | 播报文案 | 播放时机 | 规则 |
| 正金额订单等待卡片 | 请将卡片放在读卡区。 | 订单有效并进入等待卡片状态 | 每个订单会话一次;使用“放卡”而非“刷卡”,避免用户立即移走卡片 |
| 正金额订单开始处理 | 正在支付,请勿移动卡片。 | 首次检测到本次卡片并进入支付处理 | 每次交易尝试一次 |
| 没有待支付订单 | 没有待支付订单,请取走餐盘。 | 服务端明确返回餐盘无待支付订单 | 每次餐盘查询结果一次 |
| 支付确定成功 | 支付成功,请取走卡片和餐盘。 | 扣款结果及消费后读卡校验均满足成功条件 | 只允许在确定成功后播报 |
| 首次读卡失败且未尝试扣款 | 读卡失败,请取走卡片后重新操作。 | 首次读卡未完成,并能确定尚未进入扣款 | 每次交易尝试一次 |
| 已尝试扣款但结果不确定 | 支付结果待确认,请勿重复刷卡,请联系工作人员。 | 已调用扣款/写卡,但后读卡、卡片一致性或结果确认不完整 | 安全最高优先级;禁止改成“支付失败” |
| 读卡器暂不可用 | 读卡器暂不可用,请联系工作人员。 | 业务正等待就餐人员放卡时,读卡器进入不可用状态 | 每次连续异常期间一次;空闲初始化和重连轮询不重复播报 |
| 零金额订单等待核验 | 请将卡片放在读卡区进行核验。 | 零金额订单进入读卡核验状态 | 每个订单会话一次;不得包含“支付”或“扣款” |
| 零金额订单核验成功 | 核验完成,请取走卡片和餐盘。 | 零金额订单完成有效读卡并上报 | 每个订单会话一次 |
| 零金额订单读卡失败 | 读卡失败,请取走卡片后重新操作。 | 零金额核验首次读卡失败 | 每次核验尝试一次 |
4.2 条件播报
| 业务场景 | 播报文案 | 启用条件 |
| 余额不足 | 余额不足,请更换卡片或选择其他支付方式。 | 只有底层交易结果能够明确区分“未发生扣款的余额不足”时才启用;无法明确分类时不得使用 |
| 需要先移走遗留卡片 | 请先取走读卡区卡片,再放入本次支付卡片。 | 当前流程确有“等待移走旧卡”独立状态,并能与本次放卡区分时启用 |
4.3 不单独播报
| 技术阶段 | 处理方式 | 原因 |
| 首次读卡成功 | 页面继续展示处理状态,不播报 | 用户无需执行新动作,且交易尚未完成 |
| 写卡/扣款成功 | 等待最终校验后播报支付成功 | 阶段成功不等于整笔交易完成 |
| 写卡/扣款失败 | 根据是否尝试扣款及能否确认结果,映射为未扣款失败或结果待确认 | “写卡失败”是技术术语,也可能掩盖已经扣款的风险 |
| 后台上报失败 | 对就餐人员仍按确定的扣款结果播报,后台自行补传 | 上报失败不能否定已经确认的支付结果 |
| 读卡器正常连接 | 保持静默 | 页面正常状态已足够,无需增加噪声 |
5. 交易结果语义
消费语音不能只使用“成功/失败”二分类,必须使用以下业务结果:
| 结果类型 | 判定边界 | 就餐人员语音 |
| 确定成功 | 扣款已成功,消费后读取结果与本次卡片和金额一致 | 支付成功,请取走卡片和餐盘。 |
| 确定未扣款 | 首次读卡失败或在扣款调用前终止 | 读卡失败,请取走卡片后重新操作。 |
| 结果不确定 | 已尝试扣款,但写卡结果、消费后读卡或卡片一致性无法完整确认 | 支付结果待确认,请勿重复刷卡,请联系工作人员。 |
| 支付成功但上报待补传 | 本地扣款和校验确定成功,仅服务端上报失败 | 支付成功,请取走卡片和餐盘。 |
“结果不确定”优先于一般失败提示。此状态必须同时在页面展示“请勿重复支付”类警示,并禁止自动重新发起同一笔扣款。
6. 播放策略
6.1 触发原则
- Activity 只上报“等待卡片、开始支付、支付成功、未扣款失败、结果不确定”等业务事件,不直接根据读卡/写卡回调拼接语音。
- 页面文案和语音共用同一业务语义映射,避免页面显示成功而语音提示失败。
- 语音开关关闭时不播放,但不得改变状态机和页面结果。
- 页面重绘、生命周期回调、硬件轮询和相同状态重复回调不得触发重复播报。
6.2 去重范围
- 等待放卡、开始支付和最终结果按“餐盘订单会话 + 交易尝试”去重。
- 无待支付订单按“餐盘查询会话”去重。
- 读卡器不可用按“连续异常区间”去重;恢复连接后再次断开可重新提示一次。
- 新订单、新交易尝试或新的连续硬件异常区间会建立新的去重范围。
6.3 优先级
- 支付结果待确认等防重复扣款安全提示。
- 确定失败和余额不足等终止结果。
- 支付成功或核验成功。
- 正在支付、等待放卡等动作提示。
- 读卡器不可用等硬件建议。
高优先级事件到达时可以停止尚未完成的低优先级提示;同级或低级重复事件不叠加播放。一个最终结果确定后,本次交易不再播放等待或处理中提示。
7. 组件职责设计
| 组件 | 责任 | 边界 |
ConsumptionVoiceEvent | 定义与就餐人员有关的业务语音事件 | 不包含原始读卡器错误码和 UI 文案 |
ConsumptionVoicePolicy | 将业务事件映射为语音类型、优先级和去重范围 | 纯 Java,不直接操作播放器或 Activity |
ConsumptionVoiceController | 执行语音开关、去重、优先级、停止和播放 | 不判断交易是否成功 |
ConsumptionActivity | 在状态机发生语义变化时发出业务事件 | 不直接用读卡/写卡技术阶段决定最终语音 |
| 交易结果分类器 | 输出确定成功、确定未扣款、结果不确定、上报待补传 | 不负责播放和页面布局 |
语音资源使用具名资源和枚举集中管理,禁止在 Activity 中散落资源 ID、优先级数字或提示文案。类和非显然的交易安全判断应增加责任及原因注释。
8. 本地语音资源
- 继续使用项目现有本地音频播放能力和语音开关,不依赖网络。
- 新增语音文件采用统一命名,例如
consumption_payment_success、consumption_payment_unknown,禁止用 audio1 等无语义名称。
- 录音文案以本设计为唯一业务基准;文件格式、采样率、声道和响度与现有可正常播放资源保持一致。
- 实施时先复核现有音频是否可复用;文案语义不完全一致时不得勉强复用。
- 语音应完整、自然、无静音长尾;真机播放不得截断下一条高优先级提示。
9. 读卡器异常提示左侧镜像
现有 consumption_reader_status 位于页面右侧。布局只做水平镜像:
| 属性 | 当前 | 调整后 |
| 水平对齐 | layout_alignParentEnd="true" | layout_alignParentStart="true" |
| 水平外边距 | layout_marginEnd="@dimen/common_title_bar_horizontal_margin" | layout_marginStart="@dimen/common_title_bar_horizontal_margin" |
| 纵向规则 | 位于现有状态视图下方 | 不变 |
| 顶部外边距 | 现有 consumption_ui_reader_margin_top | 不变 |
| 文字、字号、颜色 | 现状 | 不变 |
| 显示逻辑 | 仅错误状态显示红字,正常连接时隐藏 | 不变 |
此调整不新增绝对坐标或重复尺寸,继续复用现有 dimen,以保证不同分辨率下仍是相对屏幕边缘的镜像位置。
10. 状态映射
| 消费状态/事件 | 语音事件 | 备注 |
有效正金额订单进入 WAITING_CARD | 等待支付放卡 | 每订单会话一次 |
| 首次检测到卡片并开始首次读取/交易 | 支付处理中 | 每交易尝试一次 |
| 订单查询明确无待支付订单 | 无待支付订单 | 不进入刷卡流程 |
| 交易分类为确定成功 | 支付成功 | 最终提示 |
| 首次读取失败且未调用扣款 | 读卡失败 | 允许用户移卡后重新操作 |
| 扣款已尝试但交易无法确认 | 支付结果待确认 | 禁止自动重试 |
| 确定扣款成功、仅上报失败 | 支付成功 | 后台补传不打扰就餐人员 |
| 零金额订单进入读卡状态 | 等待核验放卡 | 不使用支付语义 |
| 零金额有效读取及上报完成 | 核验完成 | 最终提示 |
| 等待卡片期间读卡器不可用 | 读卡器不可用 | 连续异常一次 |
11. 验收标准
| AC | 场景 | 预期 |
AC-VOICE-001 | 正金额订单进入等待卡片 | 每个订单会话只播报一次“请将卡片放在读卡区” |
AC-VOICE-002 | 首次检测到卡片并开始支付 | 播报一次“正在支付,请勿移动卡片” |
AC-VOICE-003 | 页面重绘、前后台切换或相同回调重复 | 不重复播报相同语音 |
AC-VOICE-004 | 无待支付订单 | 播报“没有待支付订单,请取走餐盘”,不进入支付语音 |
AC-VOICE-005 | 交易确定成功 | 只在最终校验成功后播报支付成功 |
AC-VOICE-006 | 首次读卡失败且未扣款 | 播报读卡失败并允许重新操作 |
AC-VOICE-007 | 扣款已尝试但结果不完整 | 播报结果待确认及禁止重复刷卡,不播报支付失败 |
AC-VOICE-008 | 扣款成功但服务端上报失败 | 对就餐人员播报支付成功,后台补传 |
AC-VOICE-009 | 零金额订单 | 等待和完成语音均不包含支付、扣款含义 |
AC-VOICE-010 | 语音开关关闭 | 所有语音静默,页面和交易逻辑不变 |
AC-VOICE-011 | 等待放卡期间读卡器连续异常 | 只播报一次不可用提示;恢复后再次异常可再播一次 |
AC-VOICE-012 | 高优先级安全提示到达 | 停止低优先级提示且不发生重叠 |
AC-UI-001 | 读卡器异常文字显示 | 位于原右侧位置的左侧水平镜像位置 |
AC-UI-002 | 读卡器连接正常 | 状态文字仍隐藏,不因布局调整改变逻辑 |
12. 测试策略
12.1 自动化测试
ConsumptionVoicePolicyTest:覆盖所有业务结果到语音类型的映射。
ConsumptionVoiceControllerTest:覆盖语音开关、同状态去重、连续异常区间、高优先级抢占和最终状态封口。
- 交易结果分类测试:重点覆盖“首次读卡失败”“扣款后复读失败”“卡片不一致”“上报待补传”。
- 正金额与零金额测试:验证零金额流程不会映射到任何支付语音。
- 布局静态检查:验证使用
layout_alignParentStart 和 layout_marginStart,且不再使用对应 End 属性。
12.2 构建与静态检查
- 执行消费模块相关单元测试和完整
testDebugUnitTest。
- 执行
assembleDebug。
- 检查新增资源命名、未引用资源、文案硬编码和重复优先级数字。
- 检查语音和页面最终结果由同一业务分类驱动。
12.3 真机验收
- 验证环境噪声下的音量、语速和可理解性。
- 验证放卡后提示不会让用户提前取卡。
- 验证连续订单不会漏播或串播上一笔结果。
- 验证读卡器拔插、USB 权限失败和重连时只提示一次连续异常。
- 验证支付结果待确认时页面和语音都明确禁止重复刷卡。
- 验证读卡器异常文字在不同设备分辨率下保持左侧镜像位置。
13. 风险与控制
| 风险 | 影响 | 控制 |
| 将写卡失败直接映射为支付失败 | 已扣款用户可能再次刷卡 | 统一经过交易结果分类器,扣款尝试后无法确认一律提示结果待确认 |
| Activity 多处直接播放 | 重复、重叠或语义冲突 | 集中到语音策略和控制器 |
| 页面重绘触发语音 | 同一状态反复播报 | 使用订单会话和交易尝试级去重键 |
| 零金额复用支付语音 | 就餐人员误以为发生扣款 | 独立核验语义和音频资源 |
| 硬件断开轮询反复报警 | 现场噪声和焦虑 | 连续异常区间只播一次 |
| 新音频规格不一致 | 播放失败、音量跳变 | 与现有正常资源统一编码并真机验收 |
14. 设计结论
- 采用“用户动作 + 业务结果”语音方案。
- 必须把支付异常拆为“确定未扣款”和“结果不确定”,禁止笼统播报支付失败。
- 首次读卡成功、写卡成功和写卡失败不直接面向就餐人员播报。
- 正金额使用支付语义,零金额使用核验语义。
- 语音由集中策略映射并按会话去重,安全提示拥有最高优先级。
- 读卡器异常提示从右侧移动到左侧镜像位置,其他布局和显示逻辑不变。
- 本设计已由用户确认;完成设计文档复核后,再生成代码实施计划。