yanhui
cb7d06c20c
feat(wst): 数据源停更熔断——订单表停更时醒目标注,别把「没同步」当「没发货」
## 业务问题
10-28 18:00 轮页面核验出 546 单超时未发,业务核对「基本都发了,怎么会核验出未发」。
## 根因(不是判定写错,是数据源停更)
`jst_Orders` 当时**从 14:40 就停止同步了**(停了 4 小时),停更之后发出的单
`send_date` 一直是空,因此全被判成「未发货」:
| 来源表 | 超时单数 | 该表状态 |
|---|---|---|
| `jst_Orders` | 540 | 最后更新 14:40(停 4 小时) |
| `jst_qmcust_orderlist` | 6 | 17:30 正常 |
两个订单表**各自独立同步**,同一天完全可能一个正常一个停更。原来只拿候选行的
`MAX(updated_at)` 判快照滞后,会被「碰巧新」的行掩盖 —— 必须直接问源表。
## 改动
后端 `warehouseShipTimelinessService.js`:
- 新增 `loadSourceFreshness()`:分别直接查 `jst_Orders.MAX(updateTime)` 与
`jst_qmcust_orderlist.MAX(local_updated)`(限轮次窗口起 30 天,避免全表扫描),
两源并行;按 `CANGKU_WST_SOURCE_STALE_MINUTES`(默认 60 分钟)判停更
- 查询失败或取不到更新时间 → **不判停更**(宁可漏报,不谎报为停更)
- 明细行新增 `src` / `srcLabel` / `sourceStale`;`summary` 新增 `sourceStaleUnshipped`
- `freshness.stale` 改为「候选行滞后 **OR** 任一源停更」;`hint` 说清停更源、
停更时刻、以及各源各贡献多少单(不能只写「这张表」)
- 导出数据带 `dataSources`,Excel 脱离页面也有上下文
- 响应新增 `dataSources` 数组(每源 label / lastUpdate / lagMinutes / stale)
前端 `WarehouseShipTimeliness/index.jsx`:
- 红条 Alert:「N 单所在订单表已停止同步,这些单很可能已经发货」(error 级),
描述里逐源列出「最后同步 14:40:05(已 3.9 小时)」
- 超时统计卡下方小字:「其中 N 单数据未同步」(悬停有说明)
- 明细「内部单号」旁「未同步」红标签 + tooltip,一眼看出哪几行不可信
- 导出新增「数据源 / 数据源是否停更」两列(`是(该单可能已发)`)
## 验证
- 后端 `npm run check`:**494/496**,2 个失败是既有环境问题(负缓存 TTL 计时、
Windows 文件权限 0o600),改动前同样失败
- `warehouseShipTimeliness.test.js` **23/23** 通过(含新增「停更表超时单必须打标
并计入 sourceStaleUnshipped」用例)
- 本地真渲染(Playwright + 手签 token,localhost:5173):
- 真数据:13:00 前 `notStarted` 正常展示「—」,无 pageerror
- mock 停更数据:红条 / 逐源行 / 统计小字 / 3 行「未同步」标签全部渲染,无 pageerror
- 真实接口 10-28 13:00 轮:`dataSources` 正确识别 `jst_Orders` 停更(滞后 96 分钟)
而 qmcust 正常;`sourceStaleUnshipped=1146` 与明细逐行打标同源同口径
## 风险与回退
- 只新增字段与展示,**不改动分轮、起算点、候选池口径** —— 超时单量本身不变
- 阈值可用 `CANGKU_WST_SOURCE_STALE_MINUTES` 调;不配默认 60 分钟
- 低峰期(凌晨)可能出现「1 小时无新单」被判停更,但页面只在 13:00 / 18:00
核验时刻展示超时数据,这两个时点 1 小时不同步即属异常
- 回退:revert 本提交即可,无数据迁移、无新表、无新依赖
2026-10-29 08:25:41 +08:00
..
2026-09-12 11:51:44 +08:00
2026-10-22 12:06:48 +08:00
2026-10-29 08:25:41 +08:00
2026-09-24 14:02:24 +08:00
2026-09-12 11:51:44 +08:00
2026-09-12 11:51:44 +08:00
2026-09-12 11:51:44 +08:00
2026-09-17 11:54:03 +08:00
2026-10-22 12:06:48 +08:00
2026-09-12 11:51:44 +08:00
2026-09-23 11:35:47 +08:00