从 Web 模拟到真机联调:离线抄表 APP 闭环落地实践

一、背景

很多移动端业务在早期都会先用 Web 页面或浏览器缓存模拟流程。这样做成本低、反馈快,适合验证接口契约和主流程。

但一旦进入真机 APP 场景,问题会明显变多:

  • 本地数据库是否可靠
  • 弱网和离线场景是否能继续作业
  • APP 状态和后端状态是否一致
  • 图片、蓝牙、文件、权限等能力是否可用
  • 重复点击、重复上传、重新安装后状态是否可控
  • 打包后的行为是否和调试基座一致

因此,从 Web 模拟到真机联调,核心不是把页面搬到手机上,而是把"任务下载、离线执行、数据上传、后台回写"这条链路做成稳定闭环。

二、目标链路

本次要落地的主链路可以抽象为:

text 复制代码
后台创建计划
-> 生成任务
-> 下发任务
-> APP 下载任务
-> 本地保存任务和表具
-> 现场抄表
-> 本地保存读数和附件
-> 上传附件
-> 上传抄表记录
-> 后台更新任务和业务数据

这个链路里有两个状态中心:

  • 后端数据库:保存计划、任务、记录、审核和最终业务状态
  • APP 本地库:保存离线任务、现场读数、附件路径和上传状态

移动端离线业务的难点,通常不在页面,而在这两个状态中心如何最终一致。

三、为什么 Web 模拟不能替代真机验证

Web 模拟适合验证接口,但覆盖不了真实 APP 的几个关键风险。

1. 本地存储不同

浏览器缓存和 APP 本地数据库不是一回事。

APP 需要处理:

  • 表结构初始化
  • 本地数据迁移
  • 重装后数据丢失
  • 本地查询和筛选
  • 本地统计字段更新

这些能力只有放到真机或接近真机的运行环境中才能可靠验证。

2. 文件和权限不同

拍照、图片路径、文件上传、蓝牙权限、定位权限等能力,在 Web 模拟里通常无法完整覆盖。

尤其是图片上传场景,常见问题不是接口参数,而是:

  • 本地临时路径和真实文件路径不同
  • 图片上传成功后需要替换为远端 URL
  • 上传记录时不能再使用本地路径
  • 用户取消拍照或重复拍照时状态要可控

3. 状态切换更复杂

APP 会经历前后台切换、页面返回、重新打开、断网重试等过程。

如果状态只存在页面内存里,很容易出现:

  • 页面显示已完成,本地库未更新
  • 本地已抄表,后端未上传
  • 图片已上传,记录上传失败
  • 记录上传成功,本地状态未标记

因此真机联调重点应放在状态落库和状态恢复,而不是只看页面是否跳转。

四、离线任务的本地模型

APP 下载任务后,不能只保存一份接口原始 JSON,而应拆成可查询、可统计、可恢复的本地模型。

一个常见拆分方式是:

text 复制代码
task   任务主表
point  抄表点或分组
meter  表具明细

其中任务主表负责保存任务级状态,抄表点负责保存分组统计,表具明细负责保存读数、附件和上传状态。

这样设计有几个好处:

  • 列表可以快速查询
  • 页面筛选不依赖后端
  • 断网后仍可查看和继续抄表
  • 统计进度有稳定来源
  • 上传成功后可以逐条标记状态

本地库不是简单缓存,而是现场作业区。

五、读数与附件上传的顺序

带附件的抄表上传,一般不要把本地图片路径直接传给业务记录接口。

更稳的流程是:

text 复制代码
保存读数和本地图片路径
-> 上传图片文件
-> 获得远端图片 URL
-> 回写本地记录的图片 URL
-> 上传抄表记录
-> 成功后标记记录已上传

这样后端业务记录里保存的是可访问的远端地址,而不是手机本地路径。

如果图片上传成功但记录上传失败,本地还保留远端 URL,下次重试时可以直接上传记录,避免重复上传文件或丢失附件。

六、重复上传的处理

移动端用户很可能多次点击上传,或者在网络不稳定时重复提交。

因此上传逻辑需要同时考虑两层防护:

  • APP 本地:只查询未上传记录进行上传
  • 后端:根据任务、表具、记录唯一标识做幂等处理

理想效果是:用户重复点击不会造成重复业务数据,也不会重复累加统计数量。

如果 APP 已经把某条记录标记为已上传,再次进入上传页面时,这条记录就不应该再进入待上传集合。

七、统计口径要统一

离线抄表常见统计包括:

  • 总数
  • 已抄数
  • 已上传数
  • 完成率
  • 上传率

这些字段必须区分清楚。

text 复制代码
已抄 = 本地已经产生有效读数
已上传 = 记录已经成功同步到后端
完成率 = 已抄 / 总数
上传率 = 已上传 / 总数

不要把"已抄"和"已上传"混成一个状态。现场人员完成抄表但暂时没有网络时,已抄数应该增加,已上传数不应该增加。

八、真机联调的务实策略

真机联调不建议一开始就测试所有边界,最好按风险分层推进。

推荐顺序是:

text 复制代码
登录和任务查询
-> 任务下载和本地入库
-> 本地列表和筛选
-> 手动录入读数
-> 无附件上传
-> 附件上传
-> 重复上传
-> 删除重装后的恢复策略

先跑通无附件的核心数据闭环,再专项处理图片、蓝牙、权限等能力。

这样做的好处是问题定位更清楚:如果基础读数都没有闭环,过早引入拍照、文件和权限,只会让排查范围变大。

九、调试包与正式包的差异

调试环境适合快速验证,但不能完全代表正式包。

常见差异包括:

  • 日志输出更多
  • 性能和包体积不同
  • 部分权限表现可能不同
  • 签名证书不同
  • 应用名称、包名、安装覆盖策略不同
  • 三方 SDK 或原生能力在正式包中表现更接近真实用户环境

因此调试基座验证通过后,至少还应使用正式 APK 做一次主流程确认。

十、复盘

从 Web 模拟迁移到真机 APP,真正要验证的是"离线闭环":

text 复制代码
任务可下载
本地可执行
状态可恢复
读数可上传
附件可关联
后端可回写
重复操作不破坏数据

这类场景的工程重点不是页面效果,而是状态设计、上传顺序、本地数据库和后端幂等。

只要这些基础能力稳定,后续扩展拍照、蓝牙批抄、AMR 自动回填、审核发布,都会有更可靠的承接基础。