# Miniapp Operation Report Sync Design ## Goal 解决“生产执行 · 工序报工”每次刷新都要等待十几秒的问题。页面刷新只负责查看小程序报工列表,ERP 同步改成显式按钮触发;同步范围由系统固定为“从上次同步成功时间起自动补齐”,不允许用户手工选择同步时间,避免漏同步。 ## Problem 当前前端进入页面或点击刷新时,请求 `/production/miniapp-operation-reports` 会带上 `sync_to_erp=true` 和 `limit=800`。后端接口默认也会执行同步逻辑,对每条小程序报工逐条匹配生产台账或旧工单、工序、员工、ERP 报工记录,并更新累计值。数据库在远程 MySQL 上,逐条查询和写入会被网络往返延迟放大,所以一次刷新可能需要十几秒。 ## Business Rules - `刷新列表` 只读取小程序报工数据,使用页面日期筛选范围,不能创建或更新 ERP 报工。 - `同步到 ERP` 不使用页面日期筛选范围。 - 同步范围固定为“上次同步成功时间之后,到本次同步开始时间止”。 - 如果没有上次同步成功时间,首次同步从现有小程序报工数据中最早的记录开始。 - 同步成功后更新上次同步成功时间。 - 同步失败时不更新上次同步成功时间,下次点击同步继续从旧时间补齐。 - 同步按钮在同步过程中显示加载状态并禁用,防止用户连续点击造成重复请求。 - 同一条小程序报工重复同步必须幂等,不能重复累计 ERP 报工数量。 - 页面日期筛选只影响“看哪些数据”,绝不影响“同步哪些数据”。 ## Backend Design 新增一个明确的同步接口: ```text POST /production/miniapp-operation-reports/sync ``` 该接口不接受用户传入的开始日期和结束日期。服务端读取系统配置中的上次同步成功时间,计算本次同步窗口: ```text sync_from = 上次同步成功时间,如果不存在则为空 sync_to = 当前服务端时间 ``` 查询范围使用小程序报工的更新时间或创建时间,保证历史日期的补报、修改、驳回也能被纳入同步。接口循环调用现有 `_sync_miniapp_item_to_erp()`,复用当前 ERP 报工幂等差额逻辑。同步全部成功后,更新上次同步成功时间为 `sync_to`。 同步状态存储复用 `sys_system_config`: ```text config_code: MINIAPP_OPERATION_REPORT_LAST_SYNCED_AT config_name: 小程序报工上次同步成功时间 config_value: 2026-06-11 10:30:00 ``` 为了降低重复请求风险,同步接口在更新配置前对该配置行加数据库锁。前端禁用按钮解决正常用户重复点击,后端锁解决异常并发请求。 ## Frontend Design 工序报工页面顶部保留日期筛选和刷新按钮,并新增同步区: - `刷新列表`:请求 `/production/miniapp-operation-reports?sync_to_erp=false`,只读加载当前日期范围内的小程序报工。 - `同步到 ERP`:请求 `POST /production/miniapp-operation-reports/sync`,按钮进入 `同步中...` 状态并禁用。 - 同步完成后自动调用 `刷新列表`。 - 页面显示上次同步成功时间。 - 成功提示展示本次同步范围和结果数量。 - 失败提示说明“同步失败,上次同步成功时间未更新,可稍后重试”。 ## Response Shape 同步接口返回: ```json { "sync_from": "2026-06-01 10:00:00", "sync_to": "2026-06-11 15:30:00", "last_synced_at": "2026-06-11 15:30:00", "total": 120, "synced": 115, "skipped": 5, "failed": 0 } ``` `skipped` 表示小程序报工无法匹配有效生产台账、旧工单、有效工序,或没有有效数量。`failed` 初版只在单条同步被捕获为可恢复失败时使用;如果发生数据库级错误,接口直接失败并不更新同步时间。 ## Error Handling - 同步过程中出现数据库异常时,事务回滚,不更新 `MINIAPP_OPERATION_REPORT_LAST_SYNCED_AT`。 - 如果没有需要同步的数据,接口返回 `total=0`,并仍可更新上次同步成功时间为本次 `sync_to`,表示系统已经确认这一段时间没有新变化。 - 如果小程序报工被驳回,沿用现有 `_sync_miniapp_item_to_erp()` 对已同步报工的解绑逻辑。 - 前端同步失败时解除按钮禁用,并展示错误提示。 ## Verification - 后端测试覆盖列表接口 `sync_to_erp=false` 时不写 ERP。 - 后端测试覆盖同步接口从上次同步成功时间自动补齐,且不接受前端筛选范围。 - 后端测试覆盖同步成功后更新上次同步成功时间,失败时不更新。 - 前端静态测试覆盖列表刷新传 `sync_to_erp=false`。 - 前端静态测试覆盖同步按钮调用独立同步接口、同步中禁用、同步完成后刷新列表。 - 运行后端相关测试、前端静态脚本和前端构建。