Files
wordcloud/docs/CANVAS_EXPORT_PACKAGE.md
T

232 lines
6.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 画布模板导入导出包(`.wcd`)方案(规划)
> 状态:第一版已实现(画布导出 `.wcd`、首页导入 `.wcd`)。
> 目的:实现画布/设计的完整导入导出,要求包内不仅包含画布尺寸、背景、图层、元素摆放信息,还要把元素用到的素材一起带出去,使得包可以在另一台机器或另一个实例中导入复用。
## 1. 包格式
建议采用 Zip 包,文件后缀为 `.wcd`。没有必要自定义二进制格式。
预期目录结构:
```
example.wcd
├── manifest.json // 包元数据与 schema version
├── document.json // CanvasDocument:画布结构
├── preview.png // 可选封面图
├── fonts/ // 可选字体文件
│ └── ...
└── assets/
├── asset-001.svg
├── asset-002.png
└── asset-003.svg
```
## 2. manifest.json
```json
{
"format": "wordcloud-canvas",
"version": 1,
"name": "海报模板",
"description": "示例模板",
"createdAt": "2026-08-06T00:00:00Z",
"canvas": {
"width": 1600,
"height": 1000,
"background": "#ffffff"
},
"assets": [
{
"id": "asset-001",
"originalAssetId": "asset_xxx",
"name": "词云 A",
"type": "svg",
"mimeType": "image/svg+xml",
"sha256": "abc...",
"size": 1024
}
],
"fonts": []
}
```
字段说明:
- `format`:固定标识,防止其他 Zip 被误导入。
- `version`:包格式版本,后续升级时便于兼容。
- `assets[].id`:包内临时 ID,只在这个包内有效。
- `originalAssetId`:导出时的来源素材 ID,仅记录,不要求导入后保留。
- `sha256`:可选,导入时用于去重。
## 3. document.json
`document.json` 就是当前前端的 `CanvasDocument` 模型:
- `width`:画布宽度。
- `height`:画布高度。
- `background`:画布背景色。
- `layers`:图层列表。
- `layerFolders`:图层文件夹列表。
- `elements`:元素列表。
对 Sticker 元素有一个关键规则:**导出时把 `assetId` 替换成包内临时 ID**。
示例:
```json
{
"width": 1600,
"height": 1000,
"background": "#ffffff",
"layers": [
{ "id": "layer-1", "name": "词云", "visible": true, "locked": false }
],
"layerFolders": [],
"elements": [
{
"id": "element-1",
"type": "sticker",
"assetId": "asset-001",
"x": 100,
"y": 80,
"width": 800,
"height": 500,
"rotation": 0,
"opacity": 1
}
]
}
```
## 4. 导出流程
建议由后端提供导出接口,例如:
```text
GET /api/designs/{id}/export
```
或当前模板库扩展为:
```text
GET /api/design-templates/{id}/export
```
导出步骤:
1. 从数据库读取画布文档 `design_documents`
2. 序列化 `CanvasDocument`
3. 遍历 Sticker 元素,收集所有真实素材 ID。
4. 读取每个素材文件字节。
5. 为每个素材生成包内 ID,例如 `asset-001`
6. 用包内 ID 替换 `document.json` 中的 `assetId`
7. 把素材写入 `assets/` 目录。
8. 可选:生成 `preview.png` 作为导入时的缩略图。
9. 可选:如果模板使用了后端字体,把字体文件写入 `fonts/`
10. 生成 `manifest.json`
11. 打包为 `.wcd` 并返回。
## 5. 导入流程
建议后端提供导入接口,例如:
```text
POST /api/designs/import
multipart/form-data: file=.wcd
```
导入步骤:
1.`.wcd` 解压到临时目录。
2. 校验 `manifest.json`
- 是否是 `wordcloud-canvas` 格式。
- `version` 是否兼容。
- `document.json` 是否结构合法。
3. 读取 `document.json` 并通过现有 `normalizeDocument` 逻辑归一化。
4. 逐个处理 `assets/` 下素材:
- 计算 SHA-256。
- 如果素材表中已有相同 SHA-256,复用已有素材 ID。
- 否则调用素材导入逻辑写入 `assets` 表 + 文件系统。
5.`document.json` 中的包内 `assetId` 重新映射为真实素材 ID。
6. 保存为新的 `design_documents`
7. 可选:把 `preview.png` 作为模板封面。
8. 返回新设计/模板 ID。
## 6. 与现有模板系统的关系
当前模板保存是把 `CanvasDocument``reference_asset_ids` 写到目录 JSON 里:
- 在线模板:保持后端素材引用,适合当前实例内复用。
- `.wcd`:把素材一起打包,适合跨机器/离线/换实例导入导出。
两者最终统一到:
- `design_documents`:存画布文档。
- `assets`:存素材元数据。
- `design_templates`:存模板元数据并引用素材。
`.wcd` 只是外部交换容器。
## 7. 边界与设计决策
### 先不做自定义二进制格式
Zip + JSON 足够,方便调试、校验和后续扩展。
### 不把素材 base64 塞进 document.json
素材单独放文件,避免 JSON 膨胀;`document.json` 只保存引用 ID。
### 素材缺失处理
导出时如果某个素材文件缺失,可以选择:
- 导出失败并提示哪个素材缺失。
- 或在 `manifest` 中标记为 `missing`,导入时提示并跳过。
建议第一版采用“导出失败并提示”,保证导入包完整。
### 字体处理
第一版建议只保留 `fontFamily` 字符串,不打包字体。
后续如果确实需要跨机器还原,再把字体文件放进 `fonts/`,导入时注册到字体库。
### 去重
`assets.sha256` 是导入去重的关键字段:
- 包内相同素材只存一次。
- 多次导入相同素材时直接复用数据库中的现有素材。
## 8. 分阶段实施
### 阶段一:最小可用包(已完成)
- 定义 `.wcd`,包含 `manifest.json``document.json``assets/`
- 支持导出当前画布或模板。
- 支持解压导入,只处理贴纸素材和画布布局。
- 不处理字体,不生成 preview。
### 阶段二:导入体验完善
- 生成 `preview.png`
- 导入时检查素材缺失。
- 支持同一设计重复导入去重。
### 阶段三:与 PostgreSQL 打通
- `POST /api/designs/import` 最终写入 `design_documents`
- 素材导入自动写入 `assets` 表。
- 导出接口直接读取 `design_documents``assets`,不再依赖前端状态。
## 9. 相关文件参考
- `frontend/src/lib/svgExport.ts`:当前图层 ZIP 导出。
- `frontend/src/lib/templateLibrary.ts`:当前模板保存/读取。
- `frontend/src/lib/canvasDocument.ts``CanvasDocument` 模型与归一化。
- `frontend/src/types.ts``CanvasDocument``StickerAsset` 等类型。
- `backend/service/app.py`:当前 `/api/assets``/api/design-templates` 接口。
- `docs/DESIGN_DATA_STORAGE_PLAN.md`:存储层重构后文档落库设计。