补充图片画布素材导出方案
新增画布素材 ZIP 导出技术方案 明确下载图标入口放在右上角标题栏 在 docs 总览补充图片画布素材导出文档入口
This commit is contained in:
@@ -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)。
|
||||
|
||||
158
docs/technical/【前端架构】图片画布素材导出方案-2026-06-15.md
Normal file
158
docs/technical/【前端架构】图片画布素材导出方案-2026-06-15.md
Normal 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。
|
||||
- 导出可恢复工程包。
|
||||
- 导入工程包恢复画布。
|
||||
- 后端异步打包大项目,前端只轮询下载结果。
|
||||
Reference in New Issue
Block a user