feat(edit): 编辑上报细节优化

This commit is contained in:
2026-10-06 18:30:05 +08:00
parent e20cd7547f
commit 79b310efe7
92 changed files with 2764 additions and 368 deletions
+18 -3
View File
@@ -22,6 +22,8 @@ Headers:`Idempotency-Key` 必填。
}
```
`purpose=product_image` 时必须传当前商品 UUID `product_id`,商品须属于当前工作空间;水印上传不传该字段。上传归属保存在上传意图中,完成上传沿用归属。
允许 `image/png`、`image/jpeg`、`image/webp`。`watermark_image` 最大 5 MiB、宽高 1–8192 px;`product_image` 最大 20 MiB、宽高 1–10000 px。服务端按用途校验大小/尺寸策略,生成随机 `object_key` 和 10 分钟有效的预签名上传地址。返回 `201 Created`:
```json
@@ -40,6 +42,8 @@ Headers:`Idempotency-Key` 必填。
前端必须以服务器返回的 method、URL 与 headers 上传,不能自行拼接对象路径;上传 URL 仅可写入该次目标对象。
对象存储的跨域规则必须允许实际 Web Origin 发起 `PUT`,并允许 `content-type` 请求头;使用 Fetch 读取签名图片时还需允许 `GET`/`HEAD`。预检 `OPTIONS` 由存储服务处理,不能通过设置 `no-cors` 绕过。七牛 S3 空间未配置 CORS 时预检返回 403 `CORS is not enabled for this bucket`,浏览器直传会抛出 `Failed to fetch`,尚未进入完成校验。开发空间当前规则 `atlas-local-web-upload` 允许 `http://localhost:8100`、`http://127.0.0.1:8100` 的 PUT/GET/HEAD 和 content-type,预检缓存 600 秒;部署其他域名或新建空间时需单独配置对应 Origin。
### 1.2 完成与校验上传
`POST /api/media/upload-intents/{upload_id}/complete`
@@ -79,13 +83,13 @@ Headers:`Idempotency-Key` 必填。
`purpose` 可为 `preview` 或 `download`。下载时传 `{ "purpose": "download" }`,服务端在签名 GET 请求中指定 `Content-Disposition: attachment`,文件名为 `atlas-image-{asset_id}` 加素材类型对应扩展名,浏览器打开该短时地址时保存文件。两种用途都返回 10 分钟有效的 `url` 与 `expires_at`。仅当前工作空间的素材可签发;前端在 URL 过期后重新请求,不能把 URL 写回业务表或长期缓存。
`GET /api/media-assets/product-uploads` 返回当前工作空间最近 100 个已经完成校验的 `product_image` 素材。每项包含 `MediaAsset` 字段及 10 分钟有效的 `preview_url`、`preview_url_expires_at`,供编辑页“上传图片”候选区展示;该地址不得写入草稿。
`GET /api/media-assets/product-uploads?product_id={product_id}` 必须指定当前商品,返回该商品最近 100 个已经完成校验的 `product_image` 素材。每项包含 `MediaAsset` 字段及 10 分钟有效的 `preview_url`、`preview_url_expires_at`,供编辑页“上传图片”候选区展示;该地址不得写入草稿。
### 1.4 网络商品图片导入
`POST /api/media-assets/product-imports`,需 `Idempotency-Key`,请求 `{ "url": "https://example.com/image.jpg" }`。只接受 HTTPS、无用户信息和自定义端口、路径以 `.jpg`、`.jpeg` 或 `.png` 结尾的链接。服务端在每次重定向时解析域名并把连接固定到已检查的公网 IPv4;最多跟随 3 次重定向,下载上限 5 MiB,校验文件内容、MIME 与最大边长 10,000 px。成功返回 `201`,`data` 为 `ProductImportedImage`:`MediaAsset` 字段、原始 `source_url`、10 分钟有效的 `preview_url` 和 `preview_url_expires_at`。重复 URL 更新当前候选素材;原有 SKU 选图不被自动替换。
`POST /api/media-assets/product-imports`,需 `Idempotency-Key`,请求 `{ "product_id": "当前商品 UUID", "url": "https://example.com/image.jpg" }`,商品须属于当前工作空间。只接受 HTTPS、无用户信息和自定义端口、路径以 `.jpg`、`.jpeg` 或 `.png` 结尾的链接。服务端在每次重定向时解析域名并把连接固定到已检查的公网 IPv4;最多跟随 3 次重定向,下载上限 5 MiB,校验文件内容、MIME 与最大边长 10,000 px。成功返回 `201`,`data` 为 `ProductImportedImage`:`MediaAsset` 字段、原始 `source_url`、10 分钟有效的 `preview_url` 和 `preview_url_expires_at`。同一商品重复 URL 更新当前候选素材;原有 SKU 选图不被自动替换。
`GET /api/media-assets/product-imports` 返回当前工作空间最近 100 条已导入的网络图片,响应项同上。图片已生成正式素材 ID 后才可进入 SKU 草稿;网络来源地址和预览地址均不得写入 `media_asset_ids`。
`GET /api/media-assets/product-imports?product_id={product_id}` 必须指定当前商品,返回该商品最近 100 条已导入的网络图片,响应项同上。图片已生成正式素材 ID 后才可进入 SKU 草稿;网络来源地址和预览地址均不得写入 `media_asset_ids`。
### 1.5 商品图片一键 3:4
@@ -233,3 +237,14 @@ Headers:`Idempotency-Key` 必填;请求体为 `{}`。将当前工作空间
单张和批量处理逐张创建任务。成功结果在图片弹窗中替换对应位置;来源候选图成功后加入已选区,失败图保持原样。弹窗可撤销本次水印替换;确认后才写入当前编辑表单,页面保存后持久化 SKU 选图。上架任务不会临时加水印。
`GET /api/products/{product_id}/image-derivatives` 返回当前工作空间内该商品最近 100 条成功的 3:4 与水印处理记录,按处理时间倒序;商品不存在返回 `404`。每条记录包含 `id`、`kind`(`aspect_ratio_3_4` / `watermark`)、`source_asset_id`、`created_at` 和带短时预览地址的 `output_asset`。编辑页选图弹窗的「图片处理记录」Tab 用它找回结果,选用后仍需确认选图并保存页面。未绑定商品的历史任务无法确定商品归属,不进入该列表;来源图与原素材不被覆盖。
商品图片候选库按商品隔离,同一商品的 SKU 可共用。上传/导入记录使用 `(workspace_id, product_id)` 外键约束商品归属;不同商品即使复用同一哈希素材,也必须各自上传或导入才能取得候选资格。历史无归属的记录不进入候选库,已有 SKU 选图仍可原样保存。
### 商品图片删除
`POST /api/products/{product_id}/image-deletions` 需 Idempotency-Key。请求严格为 `{ "asset_id": "素材 UUID" }` 或 `{ "collection_image_id": "采集图片 UUID" }`。仅可删除当前工作空间、当前商品的上传/网络导入/AI/处理结果/采集候选。未物化的采集图仅移除 Atlas 候选;已有正式素材同时清理对象存储。返回 202,data 为 ProductImageDeletion(id/status/asset_id/collection_image_id/error_code/operation)。GET 同路径列出未完成清理记录,GET 同路径加 `/{deletion_id}` 读取状态;POST `/{deletion_id}/retry` 需 Idempotency-Key,重试失败清理。
已保存 SKU、头像/水印、其他商品候选或活跃图片任务引用时返回 409 `MEDIA_ASSET_IN_USE`,须先解除引用。删除事务锁定素材、标记不可选并记录清理对象及 Outbox;Worker 幂等清理七牛实际对象,成功后标记 succeeded,失败后 failed 可重试。未成功清理不得显示已删除成功。素材审计关系保留,删除后摘要释放,后续相同图片重新上传使用新素材和新对象路径。所有新引用由数据库触发器拒绝已删除素材。
删除资源携带统一 operation,可通过 GET /api/operations/{operation_id} 查询;operation 与业务资源/Outbox 同事务创建,重试和终态同步更新。