# 工作流模板

个人工作流模板是后端里的一份 **graphJson**（`nodes` + `edges`），不是前端私有状态。网页能套、CLI 也能套，走同一组接口。

## 最短路径

```text
给图 → upload 拿 URL
     → projects create 新建画布
     → workflow apply <模板名>     （GET templates?scope=mine → 必要时 GET template/graph → POST nodes/batch）
     → 产品白底图节点：url / remoteUrl / thumbnail / previewUrl 换成上传图
     → node run 批量生成（轮播、详情、标题）
     → 产物按 data.productSlot 回填产品
```

```powershell
"{baseDir}/bin/drowup.exe" upload ./product.png --json
"{baseDir}/bin/drowup.exe" projects create 印尼套图 --json
"{baseDir}/bin/drowup.exe" workflow apply 印尼工作流 --json
```

## 为什么浏览器里是 app.drowup.com

网页 axios 的 `VITE_BASE_API=/api`，请求写成相对路径 `/api/assetCanvas/templates?scope=mine`。浏览器 Network 因此显示：

`https://app.drowup.com/api/assetCanvas/templates?scope=mine`

这是前端同源代理：Nginx 剥掉 `/api`，转到 Go。Go 路由是 `GET /assetCanvas/templates`。

CLI 应打：

`https://api.drowup.com/assetCanvas/templates?scope=mine`

**不要再加一层 `/api`。** 看不到「印尼工作流」时，先检查是不是漏了 `scope=mine`（默认公共列表没有个人模板的完整图）。

`scope`：`mine` / `personal` = 个人；`public` / `system` / 空 = 公共。

## 套模板 body

真接口：`POST /assetCanvas/nodes/batch`。

必填：`projectUuid`、`version`、`requestId`；建议带 `sessionId`、`thumbnail`。

节点和边用 **`nodes.upsert` + `connections.upsert`**。不要写成 `nodes.update` / `nodes.create` / `edges`。

`product/openInCanvas`、`product/generate` 是产品驱动（强制 `productId`），不是画布级套个人模板。

## 节点契约

模板图是 `{ schemaVersion, nodes, edges }`。套用时会换新 id，只清执行态（`status` / `taskId` / `progress` 等），保留媒体 URL。

| 字段 | 位置 | 含义 |
| --- | --- | --- |
| `data.productSlot` | 输出节点 | 产物回填产品的槽，如 `main`、`carousel[1]`、`detail[0]`、`field.title` |
| `data.inputBinding` | 输入节点 | 从产品读入，如 `sourceImage[0]`、`title`、`cover` |

种子 JSON 在仓库 `server/source/agent/canvas_templates/`。详情图谱：`GET /assetCanvas/template/graph?id=`。

## 编码

CLI 内部 HTTP 与 `--out` 都是 UTF-8。Windows PowerShell 的 `>` 重定向会写成 UTF-16；`Invoke-RestMethod` 发中文 JSON 也可能乱码。中文模板名请用 CLI，不要自己拼 PowerShell JSON。
