Files
wordcloud/docs/API.md
T
broccoliandClaude Sonnet 5 1d17b5e20d Rework layout engine around exact-glyph collision, add tests and docs sync
Replace the old bbox/heuristic placement (scale search rounds, large-font
capping, stratified sampling, fill-retry ladders) with an area-model font
sizing pass feeding a C++ exact-glyph collision engine (centroid-biased
spiral + random probing, HD clearance refinement, density/hole
optimization). Simplify the frontend advanced-params panel and JobParams
type to match the surviving config surface, add a layout-constraints test
suite and a repeatable benchmark tool, and bring docs/*.md back in sync
with current code (plus new TESTING.md and DEPLOYMENT.md).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-26 18:32:25 +08:00

334 lines
6.7 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.
# 后端 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`
健康检查。
```json
{"ok": true}
```
### GET `/api/jobs`
返回内存中的任务状态列表,最新任务在前。
### POST `/api/jobs`
创建词云任务。
Form 字段:
| 字段 | 必填 | 说明 |
|------|------|------|
| `name_list` | 是 | `.xlsx` 名单文件 |
| `mask_image` | IMAGE 模式必填 | `.png` / `.jpg` / `.jpeg` 掩膜 |
| `font_file` | 否 | 临时上传字体(`.ttf` / `.ttc` / `.otf` |
| `font_id` | 否 | 使用已上传字体 |
| `params` | 否 | JSON 字符串,合并到任务配置 |
`params` 示例:
```json
{
"MODE": "IMAGE",
"DATA_COL_INDEX": 1,
"SEED": 42,
"N_REPETITIONS": 20,
"ENABLE_STROKE_WEIGHTS": false,
"FONT_COLOR": "#000000"
}
```
响应:
```json
{"job_id": "..." }
```
### GET `/api/jobs/{job_id}`
返回 `JobStatus`
```json
{
"job_id": "...",
"status": "queued|running|success|failed",
"stage": "...",
"progress_percent": 0,
"message": "...",
"created_at": "...",
"updated_at": "...",
"artifacts": {},
"error": ""
}
```
### GET `/api/jobs/{job_id}/detail`
返回状态和最近事件:
```json
{
"status": {},
"recent_events": []
}
```
### GET `/api/jobs/{job_id}/events`
SSE 事件流。事件数据模型:
```json
{
"type": "log|status",
"stage": "placing_words",
"progress_percent": 65,
"message": "...",
"timestamp": "..."
}
```
### GET `/api/jobs/{job_id}/result`
返回可下载产物 URL
```json
{
"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` 支持:
- `png`
- `svg`
- `svg_stroke`
- `db`
- `metrics`
### GET `/api/jobs/{job_id}/locations`
查询词语位置。
查询参数:
| 参数 | 说明 |
|------|------|
| `name` | 可选;为空返回全部,非空精确匹配 |
返回:
```json
{
"job_id": "...",
"query": "",
"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}/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` | 环间距 |
## 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`
列出素材。支持查询参数:
- `type`
- `job_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):
```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` |