128 lines
4.1 KiB
Markdown
128 lines
4.1 KiB
Markdown
# 图片资产生命周期
|
||
|
||
> 状态:已实施(2026-08-30)
|
||
> 适用范围:采集图、手动上传图、AI 套图、单张 AI 图生图,以及图片水印。
|
||
|
||
## 1. 核心模型
|
||
|
||
每个 `product_assets` 图片素材只维护两个逻辑版本:
|
||
|
||
```text
|
||
original:无水印原图,始终保留
|
||
current:页面预览、单图下载、ZIP 导出使用的当前版本
|
||
```
|
||
|
||
| 状态 | original | current | 七牛对象数 |
|
||
|---|---|---|---|
|
||
| 未加水印 | 同一个对象 | 指向 original | 1 |
|
||
| 已加水印 | 无水印对象 | 指向水印对象 | 2 |
|
||
|
||
系统**不保留历史水印版**。修改水印时,先上传新的水印版并切换 current,再删除旧水印版。
|
||
|
||
采集图、上传图、AI 图的区别只在 original 的来源:采集源站、用户上传文件、模型输出。后续水印、下载、删除均走同一套流程。
|
||
|
||
## 2. 数据字段
|
||
|
||
`product_assets` 继续保留 `stored_url` 兼容既有前端接口;其语义为 current URL。新增字段:
|
||
|
||
| 字段 | 含义 |
|
||
|---|---|
|
||
| `original_url` | 无水印原图公开 URL |
|
||
| `original_storage_key` | 无水印原图对象 Key |
|
||
| `current_storage_key` | 当前展示对象 Key |
|
||
| `watermark_enabled` | current 是否为水印版 |
|
||
| `watermark_config` | 当前水印配置快照 |
|
||
|
||
删除对象必须使用 `storage_key`,不应由 URL 反推;`storage_key_from_url()` 仅用于兼容旧数据迁移。
|
||
|
||
迁移:`a41e8c7f4b20_add_asset_image_lifecycle.py`。`start.command` 会在启动服务前执行 `alembic upgrade head`。
|
||
|
||
## 3. 对象路径
|
||
|
||
新图片统一使用:
|
||
|
||
```text
|
||
products/{product_id}/assets/{asset_id}/original.{ext}
|
||
products/{product_id}/assets/{asset_id}/watermark-{uuid}.{ext}
|
||
```
|
||
|
||
路径前缀不仅便于单图精准删除,也允许删除商品时按 `products/{product_id}/` 兜底清理所有对象,包括异常中断留下的孤儿文件。
|
||
|
||
## 4. 创建与水印流程
|
||
|
||
### 采集、上传、无水印 AI 图
|
||
|
||
```text
|
||
写入 original
|
||
→ current 指向 original
|
||
→ watermark_enabled = false
|
||
```
|
||
|
||
### 添加或修改水印
|
||
|
||
```text
|
||
读取 original
|
||
→ 合成新水印图
|
||
→ 上传新 current
|
||
→ 提交数据库切换 current
|
||
→ 删除旧 current(水印版)
|
||
```
|
||
|
||
因此不会叠加水印。AI 生图参考图也优先使用 `original_url`,避免把水印带进下一次生成。
|
||
|
||
### 移除水印
|
||
|
||
```text
|
||
current 切回 original
|
||
→ 提交数据库
|
||
→ 删除旧水印对象
|
||
```
|
||
|
||
## 5. 删除流程
|
||
|
||
### 删除单张素材
|
||
|
||
```text
|
||
删除 products/{product_id}/assets/{asset_id}/ 前缀
|
||
→ 删除旧格式路径中的 original/current 对象(兼容迁移前数据)
|
||
→ 删除 product_assets 记录
|
||
```
|
||
|
||
若对象存储删除失败,接口返回失败并保留数据库素材记录,避免出现“数据库已删、文件未删”的静默状态。
|
||
|
||
### 硬删除商品
|
||
|
||
```text
|
||
查询商品所有素材
|
||
→ 清理每个素材目录和旧格式对象
|
||
→ 清理 products/{product_id}/ 前缀(孤儿兜底)
|
||
→ 删除商品,数据库级联删除素材记录
|
||
```
|
||
|
||
归档商品只改变商品状态,不删除图片。
|
||
|
||
## 6. 服务职责
|
||
|
||
| 模块 | 职责 |
|
||
|---|---|
|
||
| `services/image_assets.py` | original/current 生命周期、加/移水印、迁入正式路径、单图/整商品回收 |
|
||
| `services/storage.py` | 本地/七牛上传、下载、按 Key 删除、按前缀删除、URL→Key 兼容解析 |
|
||
| `services/watermark.py` | 纯图片字节合成;不操作数据库或对象存储 |
|
||
| API 路由 | 参数校验、数据库提交、调用生命周期服务 |
|
||
|
||
## 7. 前端入口
|
||
|
||
试算页“采集图片”和“生成结果”均可打开水印设置:
|
||
|
||
- 为已选采集图添加水印;
|
||
- 为已选生成图添加水印;
|
||
- 移除已选采集图或生成图水印;
|
||
- 新的一键生图和单张 AI 生图按当前设置自动加水印。
|
||
|
||
预览、下载与 ZIP 导出始终使用 `stored_url`(current);AI 生成参考图使用 `original_url`。
|
||
|
||
## 8. 旧数据兼容
|
||
|
||
旧素材首次加/移水印时会迁入新的商品/素材路径,并补齐 original/current 字段。迁移前已经产生但数据库无记录的旧七牛对象无法可靠识别;后续可按运营需要增加七牛前缀扫描与人工确认清理工具。
|
||
|