feat(t240): cache freight item images

This commit is contained in:
QiuSW
2026-07-29 15:12:05 +08:00
parent 5f17fc11aa
commit c7e152aaa1
28 changed files with 1728 additions and 30 deletions
+27
View File
@@ -205,6 +205,33 @@ T-203 成功返回 `201`。使用相同 `Idempotency-Key` 和相同图片内容
`null`,币种固定为 `TWD`。`product_thumb_ref` 来自商品 `productThumb`,存在时必须是
规范化正整数,不能使用货运单 ID、商品明细 ID 或完整 URL。
货运详情中的每个商品还返回:
```json
{
"image_status": "READY",
"image_error_code": null,
"image_url": "/api/v1/freight-items/{item_id}/image"
}
```
`image_status` 为 `NONE/PENDING/READY/MISSING/FAILED`。只有 `READY` 返回同源
`image_url`;其他状态返回 `null`,失败时 `image_error_code` 是不包含上游正文的稳定错误码。
元数据同步先提交,图片在剩余请求预算内 best-effort 缓存,因此图片失败不改变货运同步的
`SUCCEEDED` 终态。后续新同步会重试非 `READY` 图片,相同引用的 `READY` 图片不会重复下载。
### `GET /api/v1/freight-items/{item_id}/image`
Admin 会话鉴权的本地货运商品图片流。仅当商品仍在当前货运版本中、当前 `productThumb`
与已缓存引用一致且状态为 `READY` 时返回 `200 image/jpeg`;不存在、未完成、引用已变化或
无权访问统一返回 `404`。响应包含 `Content-Length`、ETag、
`X-Content-Type-Options: nosniff` 和 `Cache-Control: private, no-store`,不返回 ERP URL、
查询参数或服务端文件路径。
后端只使用配置的 `CMROUBAO_SHUNYUNBAO_URL` origin 和固定
`/api/p/file?id=<productThumb>` 请求图片,复用 ERP Cookie jar 并禁止重定向。下载内容经过
既有大小、尺寸、像素和解码校验,统一白底规范化为最长边不超过 2048 px 的 JPEG。
### Go ERP 会话(T-230、T-236)
`/erp`、`/erp/captcha`、`/erp/login` 和 `/api/v1/erp-session*` 不再暴露。创建货运同步
+4 -3
View File
@@ -202,6 +202,7 @@
| `docs/tasks/T-237.md` | DONE | 完整单号在 55 秒预算内同步导入并可靠收敛终态 |
| `docs/tasks/T-238.md` | DONE | 兼容顺运宝详情分钟精度时间 |
| `docs/tasks/T-239.md` | DONE | 冻结货运规格 SKU、TWD 原始单价和图片引用契约 |
| `docs/tasks/T-240.md` | DONE | 后端受控缓存并鉴权提供货运商品图片 |
| `docs/design/` | 已确认 | T-202 原型索引、4 个管理页和 7 个 Android 页面 |
| `deepseek总结.txt` | 已有 | 历史讨论摘要,不是正式需求权威 |
| `android-buyer/` | 已有 | Roubao `main` 固定 commit 的 Android 基线 |
@@ -213,11 +214,11 @@
## 任务摘要
- 已完成:T-001 至 T-004、T-101 至 T-104、T-201 至 T-219。
- 已完成:另含 T-220 至 T-239 ERP 契约、货运存储、采购需求生成、日期增量同步、Go
- 已完成:另含 T-220 至 T-240 ERP 契约、货运存储、采购需求生成、日期增量同步、Go
直连协议、OCR 会话预检、稳定预检错误、安全诊断日志、直连 `FreightSource`、旧 Connector
清理、受控本地凭证加载、同步单号导入、分钟时间兼容和货运商品元数据契约。
清理、受控本地凭证加载、同步单号导入、分钟时间兼容、货运商品元数据契约和本地图片缓存。
- 进行中:无。
- 下一步:实现商品 `productThumb` 图片的后端受控下载、本地保存和鉴权访问。
- 下一步:在货运列表和详情中展示本地缩略图、原始单价和清晰的图片状态。
## 当前可运行内容
+14 -9
View File
@@ -4,7 +4,7 @@ title: 缓存并鉴权提供顺运宝货运商品图片
phase: 2
deps:
- T-239
status: TODO
status: DONE
created: 2026-07-29
context_ref: 3bd9726
work_branch: null
@@ -57,14 +57,14 @@ write_paths:
## 验收要点
- [ ] 图片请求固定为配置 ERP origin 的 `/api/p/file?id=<productThumb>`,不接受任意 URL。
- [ ] 请求复用现有 ERP Cookie jar,禁止重定向;401/403、404、错误类型和无效图片稳定分类。
- [ ] 有效 JPEG/PNG/WebP 规范化保存为本地 JPEG,大小和像素限制不回归。
- [ ] 货运元数据先成功提交;单图失败不改变同步 `SUCCEEDED`,状态可审计并在后续同步重试。
- [ ] 相同 READY 引用不重复下载;引用变化替换关联并 best-effort 删除旧文件。
- [ ] Admin 图片接口只返回当前商品本地 READY 图片,未授权及其他状态不泄露存在性。
- [ ] 自动测试不访问真实 ERP,覆盖 Cookie、URL、重定向、状态、去重、替换和内容响应头。
- [ ] 标准 Go 测试、race、vet 和三个入口构建通过。
- [x] 图片请求固定为配置 ERP origin 的 `/api/p/file?id=<productThumb>`,不接受任意 URL。
- [x] 请求复用现有 ERP Cookie jar,禁止重定向;401/403、404、错误类型和无效图片稳定分类。
- [x] 有效 JPEG/PNG/WebP 规范化保存为本地 JPEG,大小和像素限制不回归。
- [x] 货运元数据先成功提交;单图失败不改变同步 `SUCCEEDED`,状态可审计并在后续同步重试。
- [x] 相同 READY 引用不重复下载;引用变化替换关联并 best-effort 删除旧文件。
- [x] Admin 图片接口只返回当前商品本地 READY 图片,未授权及其他状态不泄露存在性。
- [x] 自动测试不访问真实 ERP,覆盖 Cookie、URL、重定向、状态、去重、替换和内容响应头。
- [x] 标准 Go 测试、race、vet 和三个入口构建通过。
## 边界
@@ -77,3 +77,8 @@ write_paths:
- 2026-07-29:创建任务。采用货运商品专属图片元数据表并复用安全文件编码管线;先提交货运
元数据,再 best-effort 缓存图片,避免单个外部文件阻塞或回滚完整订单。
- 2026-07-29:增加 migration 16、固定 ERP 图片客户端、四 worker/最多 1000 项/15 秒
best-effort 缓存、图片状态仓储和 Admin 本地内容接口。相同 READY 引用跳过,失败引用在
新同步重试,引用替换后删除旧文件;同步成功不受单图失败影响。脱敏测试覆盖 Cookie、
固定 query、重定向、401/404/无效类型、JPEG 规范化、去重、替换、回滚保护、鉴权与响应头。
`go test ./...`、`go test -race ./...`、`go vet ./...` 及三个入口构建均通过;未访问真实 ERP。