Files
pad_scanner/docs/error-feedback-refactoring-plan.md
Misaka_Company 1417c8baf9 refactor: unify error feedback system with FeedbackService and StatusBar widget
- Create FeedbackService as centralized sound/vibration dispatcher
- Create reusable StatusBar widget with StatusDotColor enum (blue/orange/green/red/yellow/amber)
- Extend SoundService with beep/error/alert sound types and loop playback
- Remove top feedback banners from both registration and boxing pages
- Route all feedback through bottom status bar per PRD requirements
- Add sound and vibration feedback to boxing module (was completely missing)
- Handle network errors with yellow status, general errors with red
- Enhance duplicate dialog with alert loop sound that stops on close
- Add beep/error/alert sound file selectors in settings page

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-05-12 17:15:28 +08:00

10 KiB
Raw Blame History

错误反馈机制重构计划

版本v1.0 日期2026-05-12 状态:已完成


1. 背景与目标

1.1 当前问题

对照 PRD上架登记模块 v1.0 + 装箱编号模块 v1.3)的要求,当前 Flutter 应用在错误反馈方面存在以下差距:

# 问题 影响范围
1 装箱模块完全没有声音和振动反馈boxing_page.dart 未引入 SoundServiceVibration 装箱编号
2 反馈横幅位置错误 — 当前在页面顶部显示反馈横幅PRD 要求统一由底部状态栏承载所有反馈文案 上架登记、装箱编号
3 底部状态栏缺少黄色(网络异常)和红色(错误)状态 — 注册页状态栏圆点仅使用蓝/橙/绿三色,错误信息只出现在顶部横幅 上架登记
4 反馈信息重复显示 — 顶部横幅和底部状态栏同时显示类似内容,造成冗余 上架登记、装箱编号
5 声音类型不足SoundService 只有 success/failure 两种PRD 要求区分"扫描提示音"、"错误音"、"成功音"、"连续错误音" 全局
6 重复上架弹窗缺少声音差异化 — PRD 要求"连续错误音"+"连续振动",当前只是普通失败音 上架登记

LED 反馈暂时不实现,后续单独处理。

1.2 重构目标

  • 统一反馈入口:创建集中的 FeedbackService,管理声音/振动三通道反馈
  • 消除重复:移除顶部反馈横幅,所有反馈文案统一由底部状态栏显示
  • 补全缺失:为装箱模块补齐声音/振动反馈
  • 符合 PRD:状态栏圆点颜色、文案、持续时间与 PRD 表格一一对应

2. PRD 反馈要求汇总

2.1 上架登记模块PRD 第 7 节)

事件 屏幕(底部状态栏) 声音 振动
扫入有效总排号 总排号字段填入,绿色高亮 短促提示音 短震
扫入有效货位号 货位号字段填入,绿色高亮 短促提示音 短震
扫入无效码 红色提示 2 秒:"无效码:{值}" 错误音 短震
提交成功 绿色提示 1.5 秒 成功音 长震
提交失败 红色提示 2 秒 失败音 短震
重复上架错误 红色错误弹窗(需手动关闭) 连续错误音 连续震
网络异常 黄色提示:"网络异常,请检查网络连接" 失败音 短震

2.2 装箱编号模块PRD 第 9 节)

事件 屏幕(底部状态栏) 声音 振动
扫入有效总排号 显示排产号信息,绿色对勾 短促提示音 短震
扫入无效码 红色提示:"无效码,请重新扫描" 错误音 短震
提交成功 绿色提示 1.5 秒 成功音 长震
重复箱号 amber 提示 + 输入框 amber 边框 失败音 短震
网络异常 黄色提示:"网络异常,请检查网络连接" 失败音 短震
切换装箱模式 模式控件高亮切换 短促提示音

2.3 底部状态栏圆点颜色规范

状态 圆点颜色
空闲等待 蓝色
提交中 橙色
成功 绿色
错误(无效码/提交失败/重复) 红色
网络异常 黄色
警告(重复箱号) amber

3. 架构设计

3.1 新增 FeedbackService

创建 lib/services/feedback_service.dart,作为唯一的反馈调度中心

FeedbackService
├── trigger(FeedbackEvent event)    ← 统一入口
├── _playSound(SoundType type)      ← 声音通道
├── _vibrate(VibrationPattern p)    ← 振动通道
└── 底部状态栏状态由各 Page State 管理FeedbackService 不直接操控 Widget

FeedbackEvent 枚举:

enum FeedbackEvent {
  scanValid,        // 扫入有效码 → 短促提示音 + 短震
  scanInvalid,      // 扫入无效码 → 错误音 + 短震
  submitSuccess,    // 提交成功   → 成功音 + 长震
  submitFailure,    // 提交失败   → 失败音 + 短震
  duplicateError,   // 重复上架   → 连续错误音 + 连续震
  networkError,     // 网络异常   → 失败音 + 短震
  duplicateBoxNo,   // 重复箱号   → 失败音 + 短震
  modeSwitch,       // 模式切换   → 短促提示音
}

3.2 声音扩展

扩展 SoundService,增加声音类型:

声音类型 方法名 用途
短促提示音 playBeep() 有效扫码、模式切换
错误音 playError() 无效码
成功音 playSuccess() 提交成功(保留现有)
失败音 playFailure() 提交失败、网络异常(保留现有)
连续错误音 playAlertLoop() 重复上架弹窗(循环播放直到弹窗关闭)

实现策略

  • SoundService 中增加 beeperroralert 三个可配置路径
  • 设置页面增加对应的文件选择器
  • 若路径未配置则静默跳过(不阻塞业务)

3.3 底部状态栏组件化

抽取 lib/widgets/status_bar.dart 为独立 Widget

enum StatusDotColor { blue, orange, green, red, yellow, amber }

class StatusBar extends StatelessWidget {
  final StatusDotColor dotColor;
  final String text;
  // ...
}

所有页面统一使用此组件,消除重复代码。


4. 文件变更清单

4.1 新增文件

文件路径 说明
lib/services/feedback_service.dart 反馈调度中心,管理声音/振动
lib/widgets/status_bar.dart 底部状态栏可复用组件

4.2 修改文件

文件路径 变更内容
lib/services/sound_service.dart 增加 beep/error/alert 声音类型和配置
lib/pages/registration_page.dart ① 移除顶部反馈横幅 ② 状态栏增加红/黄颜色 ③ 引入 FeedbackService ④ 重复上架弹窗调用连续错误音
lib/pages/boxing_page.dart ① 移除顶部反馈横幅 ② 引入 FeedbackService ③ 增加声音/振动反馈 ④ 状态栏统一使用 StatusBar 组件
lib/pages/settings_page.dart 增加声音文件配置项beep/error/alert

4.3 不变文件

文件路径 原因
lib/services/api_service.dart API 层只负责数据传输,不涉及反馈
lib/services/code_parser.dart 解析逻辑不变
lib/services/scanner_service.dart 扫码硬件层不变
lib/pages/home_page.dart 不涉及作业反馈
lib/pages/boxing_detail_page.dart 只读展示页,无反馈交互

5. 实施步骤

步骤 1创建 FeedbackService(核心)

文件lib/services/feedback_service.dart

  • 定义 FeedbackEvent 枚举
  • 根据 event 映射声音类型、振动模式
  • 调用 SoundServiceVibration

预估改动~70 行新代码

步骤 2扩展 SoundService

文件lib/services/sound_service.dart

  • 新增 playBeep()playError()playAlertLoop()stopAlert() 方法
  • 新增 beep_patherror_pathalert_path 配置存取
  • 所有播放方法在路径未配置时静默返回

预估改动~40 行新增

步骤 3创建 StatusBar 组件

文件lib/widgets/status_bar.dart

  • 抽取底部状态栏为独立 Widget
  • 接收 dotColor(枚举)和 text 参数
  • 统一样式:圆点 + 文字,背景色使用 surfaceContainerHighest

预估改动~40 行新代码

步骤 4重构上架登记页

文件lib/pages/registration_page.dart

变更清单:

  1. 删除顶部反馈横幅相关代码(_snackbarMessage_snackbarColor_showFeedback() 方法中的横幅渲染)
  2. 引入 FeedbackService,在以下时机调用 trigger()
    • _onScan 无效码 → scanInvalid
    • _onScan 有效码 → scanValid
    • _submitOne 成功 → submitSuccess
    • _submitOne 失败 → submitFailure
    • _submitOne 重复 → duplicateError
    • catch 网络异常 → networkError
  3. 修改底部状态栏:
    • 状态栏圆点颜色增加红色和黄色
    • 错误文案在状态栏中显示(不再在横幅中)
    • 移除 _successMessage 单独字段,统一由状态栏管理
  4. 替换 内联状态栏 Widget 为 StatusBar 组件
  5. 修改 _showDuplicateDialog:打开时触发 duplicateError(连续音/震),关闭时停止

预估改动:净减 ~30 行(移除横幅 > 新增 trigger 调用)

步骤 5重构装箱编号页

文件lib/pages/boxing_page.dart

变更清单:

  1. 删除顶部反馈横幅相关代码
  2. 删除 内联底部状态栏代码,替换为 StatusBar 组件
  3. 引入 FeedbackService,在以下时机调用 trigger()
    • _onScan 无效码 → scanInvalid
    • _queryBoxInfo 成功 → scanValid
    • _submit 成功 → submitSuccess
    • _submit 失败 → submitFailure
    • _submit 重复箱号 → duplicateBoxNo
    • catch 网络异常 → networkError
    • _cycleModemodeSwitch
  4. 修改状态栏颜色逻辑,增加红色/黄色/amber

预估改动:净减 ~20 行

步骤 6设置页扩展文件lib/pages/settings_page.dart- 新增三个声音文件选择器提示音beep、错误音error、警报音alert- 保持与现有 success/failure 选择器一致的 UI 风格预估改动~60 行新增


6. 风险与约束

风险 缓解措施
LED 功能依赖设备硬件 LedService 全面包裹 try-catch不支持时静默降级
声音文件路径未配置 所有 play*() 方法在路径为空时静默返回
连续错误音循环播放 playAlertLoop() 使用循环计数或时长上限,stopAlert() 确保可停止
振动权限 Android 需要 VIBRATE 权限,检查 AndroidManifest.xml 是否已声明

7. 不在本次范围内

  • 后端 API 错误格式调整PRD 已定义,后端自行对齐)
  • 操作日志与操作人员记录
  • 离线缓存与联网同步
  • 新模块开发
  • LED 反馈(后续单独处理)