补充图片画布素材导出方案

新增画布素材 ZIP 导出技术方案

明确下载图标入口放在右上角标题栏

在 docs 总览补充图片画布素材导出文档入口
This commit is contained in:
2026-06-15 14:11:26 +08:00
parent b4746c24b5
commit 0bc7db5bf6
2 changed files with 160 additions and 0 deletions

View File

@@ -23,6 +23,8 @@
`/editor/agent` 浏览器内 AI Web 工程编辑器的静态 SPA 沙箱预览 MVP采用“平台编辑器壳 + api-server 控制面 + 独立 runner worker + 独立预览域”四层结构;技术方案、威胁模型和验收清单见 [【技术方案】浏览器内AIWeb工程沙箱预览方案-2026-06-13.md](./technical/【技术方案】浏览器内AIWeb工程沙箱预览方案-2026-06-13.md)、[【安全模型】AIWeb工程Runner与预览隔离威胁模型-2026-06-13.md](./technical/【安全模型】AIWeb工程Runner与预览隔离威胁模型-2026-06-13.md) 和 [【测试用例】AIWeb工程静态预览MVP验收清单-2026-06-13.md](./technical/【测试用例】AIWeb工程静态预览MVP验收清单-2026-06-13.md)。
`/editor/canvas` 图片画布编辑器的画布素材 ZIP 导出能力,入口放在右上角标题栏下载图标内,第一版采用前端 JSZip 打包画布中有效图层引用的上传图、生成图和修改结果,方案见 [【前端架构】图片画布素材导出方案-2026-06-15.md](./technical/【前端架构】图片画布素材导出方案-2026-06-15.md)。
本地通过 SSH alias 管理多台服务器、查看硬件 / systemd / HTTP 健康状态并执行受控服务启停的 egui 桌面工具见 [【开发运维】本地SSH服务器管理面板技术方案-2026-06-11.md](./technical/【开发运维】本地SSH服务器管理面板技术方案-2026-06-11.md)。
生产部署切换到 systemd + Nginx + SpacetimeDB 自托管的总方案见 [PRODUCTION_DEPLOYMENT_PLAN_2026-05-02.md](./technical/PRODUCTION_DEPLOYMENT_PLAN_2026-05-02.md),该文档也是当前生产 Jenkinsfile 的唯一入口。SpacetimeDB 表结构变更、自动迁移边界和保留旧数据的分阶段迁移流程见 [SPACETIMEDB_SCHEMA_CHANGE_CONSTRAINTS.md](./technical/SPACETIMEDB_SCHEMA_CHANGE_CONSTRAINTS.md)private 表迁移 JSON 导入导出、HTTP 413 分片导入和旧数据库迁移流水线经验见 [SPACETIMEDB_JSON_STRING_MIGRATION_PROCEDURE_2026-04-27.md](./technical/SPACETIMEDB_JSON_STRING_MIGRATION_PROCEDURE_2026-04-27.md) 与 [JENKINS_SPACETIMEDB_DATABASE_MIGRATION_PIPELINES_2026-04-29.md](./technical/JENKINS_SPACETIMEDB_DATABASE_MIGRATION_PIPELINES_2026-04-29.md);后台管理独立前端工程技术方案见 [ADMIN_WEB_CONSOLE_TECHNICAL_SOLUTION_2026-04-30.md](./technical/ADMIN_WEB_CONSOLE_TECHNICAL_SOLUTION_2026-04-30.md)。

View File

@@ -0,0 +1,158 @@
# 图片画布素材导出方案
日期2026-06-15
## 背景
`/editor/canvas` 已承载项目画布、账号级素材库、生成图片、图层、分组、隐藏、锁定、翻转、缩放和右键菜单等编辑能力。用户需要一次性下载当前画布中使用到的全部素材,用于本地归档、外部编辑或跨工具交接。
素材导出应作为画布级能力,而不是单个图层的“导出为”。单图导出仍保留在目标右键菜单;全部素材导出放在画布标题栏,入口稳定、可发现且不打断画布操作。
## 入口设计
- 在画布右上角标题栏内增加下载图标按钮。
- 图标使用 `lucide-react``Download`
- 按钮 `aria-label` 使用 `下载画布素材`
- 入口与返回项目页、项目名称同属标题栏,但视觉上靠右,不进入左下角画布工具组,也不进入底部 AI 工具栏。
- 标题栏空间不足时,下载图标保持固定尺寸,项目名称使用省略号收缩。
## 第一版范围
第一版实现“导出画布素材 ZIP”
- 导出当前画布中有效图层引用的图片。
- 包含上传图、生成图、修改生成结果。
- 默认包含隐藏图层。
- 跳过已被素材库删除且已判定无效的上传图层。
- 锁定、分组、翻转等状态不影响图片文件导出,但写入元数据。
- 空画布时按钮置灰,或点击后显示轻提示。
暂不实现:
- 画布整体截图 PNG。
- PSD / Figma / 工程包导出。
- 后端异步打包任务。
- 导入导出包恢复画布。
## ZIP 结构
导出文件名:
```text
项目名-画布素材-YYYYMMDD.zip
```
包内结构:
```text
项目名-画布素材/
├─ images/
│ ├─ 001-拼图素材.png
│ ├─ 002-生成图片.png
│ └─ 003-修改结果.png
├─ metadata.json
└─ manifest.txt
```
## 元数据结构
`metadata.json` 记录项目、导出时间、图层和图片文件映射:
```json
{
"projectId": "editor-project-default",
"projectTitle": "默认项目",
"exportedAt": "2026-06-15T00:00:00.000Z",
"layers": [
{
"layerId": "layer-generated-1",
"title": "生成图片 1",
"file": "images/002-生成图片.png",
"width": 1024,
"height": 1024,
"canvas": {
"x": 120,
"y": 80,
"width": 420,
"height": 420,
"zIndex": 12,
"hidden": false,
"locked": false,
"flipX": false,
"flipY": false,
"groupId": null
},
"sourceType": "generated",
"prompt": "一张明亮的拼图主视觉",
"actualPrompt": "一张明亮的拼图主视觉",
"model": "gpt-image-2",
"provider": "VectorEngine",
"taskId": "editor-real-task-1"
}
]
}
```
`manifest.txt` 用于人工快速查看:
```text
项目:默认项目
导出时间2026-06-15T00:00:00.000Z
素材数量3
图层数量5
```
## 去重规则
同一张图片被多个图层引用时,只导出一份图片,所有图层在 `metadata.json` 中指向同一个 `file`
图片去重 key 优先级:
```text
assetObjectId > objectKey > sourceAssetId > src
```
文件命名按图层 zIndex 从低到高排序,遇到重复名称追加序号。
## 前端实现
第一版优先使用客户端 ZIP
1. 从当前 `layers` 取目标图层。
2. 过滤无效图层,保留隐藏图层。
3. 按去重 key 合并图片源。
4. 对每个图片源读取 Blob
- `data:image/...` 直接转换为 Blob。
- 同源或可访问 URL 使用 `fetch` 拉取 Blob。
- 拉取失败时记录失败项,不中断整个导出。
5. 使用 `JSZip` 写入 `images/``metadata.json``manifest.txt`
6. `zip.generateAsync({ type: 'blob' })` 生成文件。
7. 用临时 `<a download>` 触发下载。
若当前仓库未安装 `jszip`,新增依赖时应只引入 `jszip`,不引入额外下载库。
## 错误处理
- 空画布:按钮置灰或显示短提示。
- 部分图片下载失败ZIP 仍生成,`metadata.json` 记录失败图片UI 显示“部分素材未能导出”。
- 全部图片失败:不下载 ZIP显示失败提示。
- 浏览器不支持 Blob 下载:显示失败提示。
## 测试计划
- 标题栏右上角显示 `下载画布素材` 图标入口。
- 空画布时入口不可执行或提示为空。
- 上传图和生成图都写入 ZIP。
- 多图层引用同一素材时,图片文件只写一份。
- 隐藏图层默认写入 `metadata.json`
- 图层的锁定、翻转、分组状态写入元数据。
- `data:image` 图片不经过网络请求即可导出。
- URL 图片 fetch 失败时不中断其他素材导出。
## 后续扩展
- 导出当前选中素材。
- 导出画布快照 PNG。
- 导出可恢复工程包。
- 导入工程包恢复画布。
- 后端异步打包大项目,前端只轮询下载结果。