13 KiB
Studio 排版 API · 标准图文与 27 套固定构图
把本篇与图片生成文档一起交给 coding agent。agent 自行选择图片、配色、字体、构图与参数,通过 HTTP 保存渲染描述,得到可持续更新的原生 HTML/CSS 页面。数据库只保存模板关联、文字、素材引用和渲染参数,不保存截图或任意 HTML。
可选:查看模板示例 · 读取实时 API 契约 · 照片入皮影 · 街头小人
agent 的交付流程
- 按下文读取模板 API,选择 layoutId,并获取该模板实际的 T/I/D 元素 ID。
- 上传图片取得 assetId,把图片、文字和参数提交给创建 API。
- 从创建响应读取
design.id与design.url,把完整结果链接交给用户,例如http://8.211.154.134:18131/studio/template-layout?id=实际返回的UUID。 - 用户直接打开该链接看结果;修改内容继续调用 PATCH,同一 ID 与结果链接保持不变。
不要编造 ID,也不要把模板预览链接当作最终结果。API 保存成功并返回真实 UUID 才算完成。以下文档足以通过 HTTP 完成流程,无需使用编辑器。
两类排版,同一内容模型
- 标准排版:
standard-01,120×160 单位。沿用原 Studio 图文页的标题、正文、栏目结构,增加主题图片与分隔线。T01 主标题、T02 正文、T03 栏目、I01 图片、D01 分隔线。所有内容和位置可设置,也能增加原生元素。 - 固定排版:
ref-01至ref-27,保留各自画板、出血、圆形、斜切、竖题和字体构图。先读取模板,按实际 T/I/D ID 填入内容。不能假定各模板拥有相同元素。
两类都使用 /api/studio/designs 的真实 CRUD。创建额外指定 layoutId;更新从 URL 确定 ID,模板关联不能修改。更换模板应创建新记录,避免把旧元素 ID 错套到新模板。调用方无需打开 /studio 或操作编辑器。模板由 agent 经 API 选择,图片和文字由 API 保存,用户只打开结果链接。现有独立工具箱功能保持可用。
1. 由 agent 通过 API 发现模板
以下 curl 使用指定服务器。PROMPT_TOKEN 由用户通过现有登录方式提供,只保存在进程环境,不放 URL 或日志。也可使用已登录浏览器的同源 Cookie;浏览器写请求需要同源 Origin。未登录 API 返回 401。
BASE=http://8.211.154.134:18131
curl -fsS -H "Authorization: Bearer $PROMPT_TOKEN" "$BASE/studio/api/layouts"
curl -fsS -H "Authorization: Bearer $PROMPT_TOKEN" "$BASE/studio/api/layouts/standard-01"
curl -fsS -H "Authorization: Bearer $PROMPT_TOKEN" "$BASE/studio/api/layouts/ref-17"
目录返回 version, layouts, saveApi, catalogUrl, documentationUrl。每项包含 id,name,family,url,api,family 为 standard/fixed。模板返回尺寸、元素 ID/类型/role/box/direction/text、默认 parameters、workspaceSchema 与页面 URL。?agent_mode=True 返回纯文本文档,业务请求移除此参数。
2. 生成图片,上传一次,显示压缩衍生图
先让 coding agent 按生成图片文档产出文件;Studio 不暗中调用生成模型。图片可以来自用户素材或生成结果。上传走现有素材 API:
curl -fsS -H "Authorization: Bearer $PROMPT_TOKEN" \
-F kind=image -F assetOnly=true -F files=@hero.png "$BASE/api/upload"
返回 assets UUID 数组及对应 files 元数据。取 assets[0] 作为 assetId。上传不单独发帖;设计创建时才自动关联 Wiki post。不要把 Base64、任意远程 URL、HTML 或 SVG 塞入参数。
原素材保留在素材库,页面展示只请求压缩 WebP。以 assetId 引用素材,不必自行再上传缩略图:
curl -fsS -H "Authorization: Bearer $PROMPT_TOKEN" \
"$BASE/api/preview?source=%2Fapi%2Fmedia%2FASSET_UUID&width=960" -o hero-preview.webp
width 只允许 240/480/960/1280;小图预算 100KB,大图预算 220KB,复杂图片会降低尺寸/质量。原生页面按槽位显示宽度和像素密度选择 srcset 衍生图,保留 fit/cropX/cropY/zoom。目录使用原生文字与 CSS 色块,不加载参考原图;旧工具箱参考图也使用压缩预览。/api/media/{id} 是素材原件读取接口,不应用作展示图片的 src。
3. 创建:POST /api/studio/designs
创建和更新共用内容字段 name,parameters;schemaVersion 可省略,当前仅支持 1。创建额外传 layoutId,不传 revision 或 id。
curl -fsS -X POST "$BASE/api/studio/designs" \
-H "Authorization: Bearer $PROMPT_TOKEN" -H 'Content-Type: application/json' \
-d '{"schemaVersion":1,"layoutId":"standard-01","name":"观察日常","parameters":{"paper":"#edf0ef","texts":{"T01":{"value":"观察日常\n记录灵感","fontFamily":"serif","color":"#23424b"},"T02":{"value":"让每一页只讲一件事。","lineHeight":1.4}},"images":{"I01":{"color":"#73929a","fit":"cover","cropX":50,"cropY":45,"zoom":1}},"decorations":{"D01":{"color":"#73929a"}}}}'
有图片时在 I01 加 assetId:"上传返回的UUID"。固定排版只需改为所选 layoutId,并按 schema 选择元素 ID。例如 ref-01 支持 texts.T01、texts.T02 与 images.I01。
201 返回 {design}。design 包含:
| 字段 | 含义 |
|---|---|
| id / layoutId / family | 持久化 UUID、不可变模板 ID、standard 或 fixed |
| schemaVersion / revision | 参数契约版本(1)、记录修订号(从1递增) |
| name / parameters | 名称与规范化内容;省略的分组返回空对象 |
| url / renderUrl | 同一个原生 HTML/CSS 页面 URL |
| schemaUrl | 当前模板参数地址 |
| postId / postUrl | 自动创建并在后续更新中复用的 Wiki post |
| archived / archivedAt | 可恢复归档状态与时间 |
| createdAt / updatedAt | 创建与最后修改时间 |
| legacySvgUrl | 固定排版的旧 SVG 导出地址,标准排版为 null |
创建设计与 Wiki post 在同一数据库事务内完成,失败整体回滚。更新同一设计复用同一 post;手工编辑过的 Wiki 正文、标题、标签、封面不会被参数更新覆盖。
4. 读取与打开
ID=创建返回的UUID
curl -fsS -H "Authorization: Bearer $PROMPT_TOKEN" "$BASE/api/studio/designs/$ID"
curl -fsS -H "Authorization: Bearer $PROMPT_TOKEN" "$BASE/api/studio/designs?layoutId=standard-01&limit=20"
读取返回 {design},没有副作用。列表默认只列未归档记录;archived=true 只列归档记录;limit 为1–50,默认20;nextCursor 作为下一页 before。layoutId 可省略。
直接打开创建响应中的 design.url:/studio/template-layout?id={UUID}。这个 UUID 对应数据库里 API 保存的模板、图片与文字,服务端按记录渲染最终 HTML/CSS。链接中无需携带 layoutId,无需打开 /studio 选择模板,也没有编辑按钮、双击编辑或右键编辑。standard-01 与 ref-17 是模板 ID,不是保存记录的 UUID。
/studio/designs/{UUID} 与旧 /studio/layouts/{layoutId}?id={UUID} 兼容跳转到同一个结果页。缺失、非法、不存在或已归档的 ID 返回404,不会显示空模板或编辑器;旧链接模板与记录不匹配也返回404。归档设计仍能经 API 读取以恢复。
5. 更新:PATCH /api/studio/designs/{id}
先 GET,保留所有未改字段,再整体替换 parameters;不是深度合并。以下假设刚读到 revision=1:
curl -fsS -X PATCH "$BASE/api/studio/designs/$ID" \
-H "Authorization: Bearer $PROMPT_TOKEN" -H 'Content-Type: application/json' \
-d '{"name":"观察日常 · 修订","revision":1,"parameters":{"texts":{"T01":{"value":"新的标题"}},"images":{},"decorations":{}}}'
200 返回新 design,revision 增加。过期 revision 返回409,重新 GET 并合并后再提交;不要盲目重试。不接受 layoutId、id、url、postId 等返回字段;不能直接把整个 design 作为 body。另存副本使用 POST 创建新 UUID。
6. 删除与恢复
DELETE 采用可恢复归档,不物理删除参数、素材或 Wiki post。和更新一样必须提供最新 revision;自动同步关联 post 的归档状态。
curl -fsS -X DELETE "$BASE/api/studio/designs/$ID" \
-H "Authorization: Bearer $PROMPT_TOKEN" -H 'Content-Type: application/json' -d '{"revision":2}'
# 删除后读取新 revision,再恢复。此例删除后为3:
curl -fsS -X POST "$BASE/api/studio/designs/$ID" \
-H "Authorization: Bearer $PROMPT_TOKEN" -H 'Content-Type: application/json' -d '{"revision":3,"archived":false}'
两者200返回 {design},revision 递增。归档记录 PATCH 返回409,先恢复。重复写入仍需最新 revision;409不会修改数据。独立归档 Wiki post 只影响笔记发现状态,不等于删除设计。旧设计缺 Wiki 入口可调用 POST /api/studio/designs/{id}/post,body {},首次201、已有200;不改变 revision。
参数清单(两类共用)
parameters 顶层允许 texts/images/decorations/paper/layers/added;全部可省略,不能添加未知字段。最大请求64KB。颜色都为 #RRGGBB。坐标与字号使用模板单位,不是 CSS 像素。
| 分组 | 字段与约束 |
|---|---|
| texts.{文字ID} | value 必填,可空,最多500字/8行;color;scale 0.25–2;align start/middle/end;fontFamily sans/serif/mono;fontSize 0.1–1000;fontWeight 100–900;lineHeight 0.5–4;letterSpacing -20–100 |
| images.{图片ID} | assetId(已存在的图片 UUID);color;fit cover/contain;cropX/cropY 0–100(默认50);zoom 1–5(默认1) |
| decorations.{装饰ID} | color;hidden 布尔值 |
| paper | 纸张颜色 |
| layers.{元素ID} | x/y -10000–10000;width/height 0.1–10000;rotation -360–360;opacity 0–1;radius 0–5000;z -1000–1000;hidden/locked 布尔值 |
| added | 最多100项:id 为 user- 加1–60位字母/数字/连字符,唯一;kind text/image/decoration;role 最多80字;box 为 [x,y,width,height];direction 必须 horizontal;text 为文字或null;reading 必须 custom;装饰可带 shape rectangle/ellipse |
新增元素先在 added 声明,然后在 texts/images/decorations/layers 用该 ID 配置。locked 控制工作区交互,不禁止 agent 更新。数据是封闭结构,无脚本执行。未来扩展新增契约版本;v1 不接受未知字段/版本。现有省略 schemaVersion 的请求继续按v1处理,旧记录无需重建,布局 ID 和页面 UUID 保持不变。默认视觉可随模板美化变化;要求固定外观时显式设置配色、字体和图层参数。
错误:400 参数/版本/构件类型/图片 ID 不合法;401 未登录;404 模板或设计不存在;409 修订冲突或已归档;405 方法不支持;413 请求超限;500 服务失败。压缩预览失败可能返回503与 Retry-After。
现有工具箱与兼容导出
工具功能保留:ref-17 同一母版四张试版、ref-01/07/26 三种构图试版、最初图文页。旧封面工具文档已合并到本篇,旧文档 URL 保留为归档说明,避免重复顶级入口。
旧无状态 API:/studio/api/export/learning-skills-template 和 /studio/api/export/layout-selection 支持 GET/POST,不保存设计。前者参数 slide=0..3、heading(1–6字)、body(最多360字/3行)、color/accent、masthead(2项);后者 layoutId=ref-01/ref-07/ref-26、fields(对应T ID,1–120字/4行)、color/accent。GET 默认返回方案 JSON;GET format=svg 导出初始图;POST format=svg(默认)导出 SVG,format=json 返回参数,最大32KB。first-idea 仅支持 GET 方案/Markdown。
curl -fsS -X POST "$BASE/studio/api/export/learning-skills-template?format=svg" \
-H "Authorization: Bearer $PROMPT_TOKEN" -H 'Content-Type: application/json' \
-d '{"slide":1,"heading":"笔记复习","color":"#7a8b7e"}' -o cover.svg
curl -fsS -X POST "$BASE/studio/api/export/layout-selection?format=svg" \
-H "Authorization: Bearer $PROMPT_TOKEN" -H 'Content-Type: application/json' \
-d '{"layoutId":"ref-01","fields":{"T01":"STUDY"},"color":"#83918a"}' -o selection.svg
固定排版 /studio/api/layouts/ref-01 的 GET format=svg、POST 仍提供旧分层 SVG;POST format=json 只验证和返回规范化参数。旧 SVG 不反映 added、layers、扩展字体和裁切参数,不能用来证明原生效果。standard-01 不支持 SVG。原生页面应直接打开返回 URL,或用浏览器打印。代码可扩展渲染能力,但每次是否使用、选择哪些参数均由 coding agent 决定。
固定排版索引
{{LAYOUTS}}