8.4 KiB
后端 API 说明
本文档按 backend/service/app.py 和 backend/service/schemas.py 当前代码整理。
基础约定
- 默认后端地址:
http://localhost:8000 - 请求体中上传文件使用
multipart/form-data params字段是 JSON 字符串,顶层必须是对象- 任务状态存在内存中(
JobManager),服务重启后状态会丢失;文件仍保留在service_workspace - CORS 已开启,允许所有来源
Jobs
GET /api/health
健康检查。
{"ok": true}
GET /api/jobs
返回任务状态列表,最新任务在前。除内存中登记的任务外,还会扫描 service_workspace 补充磁盘上已完成但未登记的任务(有 wordcloud_hd.db 即认为是成功可查找)。
POST /api/jobs
创建词云任务。
Form 字段:
| 字段 | 必填 | 说明 |
|---|---|---|
name_list |
是 | .xlsx 名单文件 |
mask_image |
IMAGE 模式必填 | .png / .jpg / .jpeg 掩膜 |
font_file |
否 | 临时上传字体(.ttf / .ttc / .otf) |
font_id |
否 | 使用已上传字体 |
params |
否 | JSON 字符串,合并到任务配置 |
params 示例:
{
"MODE": "IMAGE",
"DATA_COL_INDEX": 1,
"SEED": 42,
"N_REPETITIONS": 20,
"ENABLE_STROKE_WEIGHTS": false,
"FONT_COLOR": "#000000"
}
响应:
{"job_id": "..." }
GET /api/jobs/{job_id}
返回 JobStatus:
{
"job_id": "...",
"status": "queued|running|success|failed",
"stage": "...",
"progress_percent": 0,
"message": "...",
"created_at": "...",
"updated_at": "...",
"artifacts": {},
"error": ""
}
GET /api/jobs/{job_id}/detail
返回状态和最近事件:
{
"status": {},
"recent_events": []
}
GET /api/jobs/{job_id}/events
SSE 事件流。事件数据模型:
{
"type": "log|status",
"stage": "placing_words",
"progress_percent": 65,
"message": "...",
"timestamp": "..."
}
GET /api/jobs/{job_id}/result
返回可下载产物 URL:
{
"job_id": "...",
"status": "success",
"image_url": "/api/jobs/{job_id}/files/png",
"svg_url": "/api/jobs/{job_id}/files/svg",
"svg_stroke_url": "/api/jobs/{job_id}/files/svg_stroke",
"db_url": "/api/jobs/{job_id}/files/db",
"metrics_url": "/api/jobs/{job_id}/files/metrics"
}
GET /api/jobs/{job_id}/files/{kind}
下载产物。kind 支持:
pngsvgsvg_strokedbmetrics
GET /api/jobs/{job_id}/locations
查询词语位置(单任务内查找)。
查询参数:
| 参数 | 说明 |
|---|---|
name |
可选;为空返回全部,非空时按 mode 匹配 |
mode |
可选;exact(默认,精确匹配)/ contains(子串包含,转义通配符后 LIKE %name%) |
返回:
{
"job_id": "...",
"query": "",
"mode": "exact",
"total": 1,
"canvas_width": 8000,
"canvas_height": 4000,
"matches": [
{
"id": 1,
"name": "张三",
"x": 100,
"y": 200,
"font_size": 64,
"color": "#000000",
"orientation": "horizontal",
"box_x": 100,
"box_y": 200,
"box_width": 120,
"box_height": 50
}
]
}
GET /api/jobs/{job_id}/find
单任务内查找名字的受保护接口,供独立查找页使用(与 /locations 响应结构相同)。
- 需要鉴权:
Authorization: Bearer <token>,token 由POST /api/login获取 - 查询参数与
/locations一致:name、mode(exact/contains) - 无 token 或 token 错误返回
403
POST /api/login
管理口令登录,返回查找页 / 订单页共用的鉴权 token。
请求体(JSON):
{"password": "管理口令"}
- 口令错误返回
401 - 成功返回:
{"token": "..."};后续请求带Authorization: Bearer <token> - 默认口令
zhihui2024,生产可用环境变量ORDERS_ADMIN_PASSWORD覆盖(见backend/service/app.py)
GET /api/jobs/{job_id}/occupancy_mask
返回 PNG,显示每个已放置词语的 bounding box。
GET /api/jobs/{job_id}/custom.svg
按已生成 DB 重新导出 SVG。
查询参数:
| 参数 | 默认 | 说明 |
|---|---|---|
fill |
fill |
fill / dot / line / ring |
stroke |
0 |
是否描边 |
spacing |
10 |
点阵间距 |
radius |
2 |
点阵半径 |
color |
#000000 |
输出颜色 |
line_spacing |
6 |
线填充间距 |
line_width |
1 |
线宽 |
line_angle |
0 |
线角度 |
ring_radius |
3 |
环半径 |
ring_width |
1 |
环线宽 |
ring_spacing |
8 |
环间距 |
POST /api/exports/ai
将应用生成的 SVG 转换为 Illustrator 5 兼容的 .ai 文件。该接口仅转发到 Compose 内部的 ai-converter 服务,不暴露转换容器端口。
请求体:
{
"svg": "<svg ...>...</svg>",
"filename": "wordcloud.ai"
}
- 最大 SVG 大小:25 MB。
- 当前支持路径、
rect、circle、ellipse、line、纯色填充/描边和仿射变换。 - 普通 SVG
text会先使用内置中文字体转换为轮廓路径,以保证中文在 AI 中可见;文本将不再是可编辑文字。 - 不支持图片、SVG 图案/裁剪/透明效果时会返回
422,不会产生可能失真的 AI 文件。
Templates
GET /api/templates
返回后端硬编码模板列表:
poster_1x2(竖版手机海报,1080×2160)poster_4x5(社交媒体图,1080×1350)poster_1x1(方形封面,1080×1080)poster_3x4(竖版广告,1080×1440)poster_16x9(横版电商,1920×1080)
Assets
POST /api/assets
上传素材。Form 字段:
| 字段 | 必填 | 说明 |
|---|---|---|
file |
是 | 素材文件 |
name |
否 | 名称 |
type |
否 | 默认 upload |
POST /api/assets/from-job/{job_id}
从任务产物导入素材。Form 字段:
| 字段 | 默认 | 说明 |
|---|---|---|
kind |
png |
产物类型 |
name |
空 | 素材名称 |
type |
wordcloud |
素材类型 |
GET /api/assets
列出素材。支持查询参数:
typejob_id
GET /api/assets/{asset_id}
获取素材元数据。
GET /api/assets/{asset_id}/download
下载素材文件。
DELETE /api/assets/{asset_id}
删除素材。
Projects
POST /api/projects
创建工程。Form 字段:
| 字段 | 必填 | 说明 |
|---|---|---|
name |
是 | 工程名 |
template_id |
是 | 模板 ID |
background_color |
是 | #RRGGBB |
stickers |
否 | JSON 数组字符串 |
GET /api/projects
返回工程摘要列表。
GET /api/projects/{project_id}
返回工程完整数据。
PATCH /api/projects/{project_id}
按传入 Form 字段部分更新工程。
DELETE /api/projects/{project_id}
删除工程。
Fonts
GET /api/fonts
返回字体列表,包含默认字体项(__default__)。
POST /api/fonts
上传字体。Form 字段:
| 字段 | 必填 | 说明 |
|---|---|---|
file |
是 | 字体文件(.ttf / .ttc / .otf) |
name |
否 | 字体名 |
DELETE /api/fonts/{font_id}
删除已上传字体。默认字体不能删除。
Line Spacing Analysis
POST /api/jobs/{job_id}/analyze-line-spacing
分析 SVG 词云路径的线距,返回 LineSpacingAnalysisSummary。
请求体(JSON):
{
"percentile": 3,
"elementWidth": 100.0,
"elementHeight": 100.0,
"sampleStep": 2.0
}
响应字段:
| 字段 | 说明 |
|---|---|
percentile |
线距百分位 |
spacingPx |
采样线距(像素) |
spacingMm |
采样线距(毫米) |
minSpacingPx |
最小线距(像素) |
minSpacingMm |
最小线距(毫米) |
curveCount |
曲线数量 |
segmentCount |
线段数量 |
sourceWidth / sourceHeight |
SVG 原始尺寸 |
elementWidth / elementHeight |
目标元素尺寸 |
常见错误
| 场景 | 状态码 | detail |
|---|---|---|
params 不是合法 JSON |
400 | params must be valid JSON |
params 不是对象 |
400 | params must be JSON object |
name_list 非 .xlsx |
400 | name_list must be xlsx |
| IMAGE 模式缺少掩膜 | 400 | mask_image is required when MODE=IMAGE |
| 掩膜文件不存在 | 400 | mask_image must be png/jpg/jpeg |
| job 不存在 | 404 | job not found |
| 产物未就绪 | 404 | artifact not ready |
| 文件类型未知 | 404 | unknown artifact kind |