chore(contracts): 同步 0.5.0/0.7.0/0.4.0(场景管理路由与 Scene 模型)
This commit is contained in:
+3
-3
@@ -1,8 +1,8 @@
|
||||
# OpenDance Studio 契约版本
|
||||
# 规则:任何字段级变更必须提升对应条目版本,并回到 opendance-web 修改后再向另两端建迁移任务。
|
||||
rest-api: 0.4.0
|
||||
rest-api: 0.5.0
|
||||
websocket-keypoints: 0.1.0
|
||||
data-models: 0.6.0
|
||||
data-models: 0.7.0
|
||||
skeleton-topology: 0.2.0
|
||||
model-formats: 0.5.0
|
||||
database: 0.3.0
|
||||
database: 0.4.0
|
||||
|
||||
@@ -83,7 +83,7 @@ rejected 已驳回
|
||||
| `durationMs` | number\|null | | |
|
||||
| `keypointFormat` | string\|null | 读 | 预处理后固定为 `mediapipe33@0.1.0` |
|
||||
| `keypointUrl` | string\|null | 读 | 预处理产物(NDJSON 或.npz 的 JSON 封装) |
|
||||
| `thumbnailUrl` | string\|null | 读 | 骨架缩略图(`/preprocess` 时生成,动作管理列表展示;未生成时为 null)(v0.6.0) |
|
||||
| `thumbnailUrl` | string\|null | 读 | 骨架缩略图(`/preprocess` 时生成,动作管理列表展示;未生成时为 null)(v0.7.0) |
|
||||
| `keypointFrames` | number\|null | 读 | 关键点帧数 |
|
||||
| `preprocessState` | enum | 读 | `none` / `running` / `done` / `failed` |
|
||||
| `preprocessError` | string\|null | 读 | |
|
||||
@@ -163,3 +163,48 @@ rejected 已驳回
|
||||
|
||||
- 仅包含 `status = 'published'` 的记录。
|
||||
- `defaultModelId` 由 4.1 的规则解析得出,客户端无需自行实现优先级。
|
||||
|
||||
---
|
||||
|
||||
## 7. `Scene`(场景,GLB 为主)(v0.7.0)
|
||||
|
||||
场景与模型的区别:**以 GLB 为主**(不做 humanoid 重绑定、不转 VRM),
|
||||
并携带**物理参数**(服务端只存参数、不跑物理;仿真在客户端)。
|
||||
|
||||
| 字段 | 类型 | 必填 | 说明 |
|
||||
|--|--|--|--|
|
||||
| `id` | number | 读 | |
|
||||
| `name` | string | ✅ | 场景名称,<=200 |
|
||||
| `glbUrl` | string\|null | 读 | 场景 GLB 下载地址 |
|
||||
| `thumbnailUrl` | string\|null | 读 | 缩略图(服务端离线渲染) |
|
||||
| `fileSize` | number\|null | 读 | |
|
||||
| `fileSha256` | string\|null | 读 | |
|
||||
| `conversionNote` | string\|null | 读 | 由 `.zip`/`.pmx`/`.fbx` 转换而来时的说明 |
|
||||
| `config` | `SceneConfig` | ✅ | 物理 / 环境 / 出生点 / 相机,见 7.1 |
|
||||
| `stats` | object\|null | 读 | 场景 GLB 分析(面数 / 网格 / 材质 / warnings) |
|
||||
| `sourceType` `sourceName` `sourceUrl` `license` `author` | string | ✅ | 来源五元组 |
|
||||
| `status` | enum | 读 | 上传一律 `pending`,经审核后 `published` |
|
||||
|
||||
### 7.1 `SceneConfig`(冻结)
|
||||
|
||||
```yaml
|
||||
physics:
|
||||
gravity: { x: 0, y: -9.8, z: 0 } # 米/秒^2,各分量 ±200
|
||||
wind:
|
||||
base: { x: 0, y: 0, z: 0 } # 基础风向量(米/秒,±100)
|
||||
gustAmplitude: 0 # 阵风幅度 0~100
|
||||
gustFrequency: 0.2 # 阵风频率 Hz,0.01~5
|
||||
gustDirection: { x: 1, y: 0, z: 0 } # 阵风方向(±1)
|
||||
space: world | local # 风的作用坐标系
|
||||
ground: { friction: 0.6, restitution: 0, slopeLimit: 45 } # 0~1 / 0~1 / 0~89 度
|
||||
colliders: auto | mesh | none # auto=按 GLB 命名约定,mesh=三角网
|
||||
environment:
|
||||
ambientColor: "#8fb4ff" # #RRGGBB
|
||||
ambientIntensity: 1 # 0~4
|
||||
fogDensity: 0 # 0~1(0=关闭)
|
||||
spawnPoints: [{ x: 0, y: 0, z: 0, yaw: 0 }] # 最多 16 个
|
||||
camera: { mode: follow | fixed | orbit, distance: 4.5, height: 1.6 }
|
||||
```
|
||||
|
||||
服务端入库时对每项做**边界收敛**(越界夹紧、非法枚举回退默认值),
|
||||
保证客户端拿到的参数一定可解释;`catalog/export` 的 `scenes[]` 直接下发该结构。
|
||||
|
||||
+22
-1
@@ -36,7 +36,7 @@ DB_LOGGING=false
|
||||
- 每个 migration 必须可逆(提供 `down` 方法)
|
||||
- 迁移文件名格式:`<timestamp>-<kebab-name>.ts`
|
||||
|
||||
## 增量迁移(v0.2.0 / v0.3.0)
|
||||
## 增量迁移(v0.2.0 / v0.4.0)
|
||||
|
||||
| 迁移 | 变更 |
|
||||
|--|--|
|
||||
@@ -63,3 +63,24 @@ draft ──submit──▶ pending ──approve──▶ published
|
||||
|
||||
- `published` 才可被 Windows 客户端 / Android App 消费
|
||||
- `/api/catalog/export` 只导出 `published` 记录
|
||||
|
||||
---
|
||||
|
||||
## 场景表 `scenes`(v0.4.0 / T-WEB-015)
|
||||
|
||||
| 列 | 类型 | 说明 |
|
||||
|--|--|--|
|
||||
| `id` | bigint PK | |
|
||||
| `name` | varchar(200) | 场景名称 |
|
||||
| `glb_asset_id` | bigint NULL | 场景 GLB(以 GLB 为主,不转 VRM) |
|
||||
| `thumbnail_asset_id` | bigint NULL | 缩略图 |
|
||||
| `config` | **mediumtext** NULL | `SceneConfig` JSON(物理 / 环境 / 出生点 / 相机) |
|
||||
| `stats` | **mediumtext** NULL | 场景 GLB 分析结果(复用模型检查器) |
|
||||
| `file_size` / `file_sha256` / `conversion_note` | - | 与 models 同义 |
|
||||
| `source_type` `source_name` `source_url` `license` `author` | - | 来源五元组(必填) |
|
||||
| `status` | varchar(16) | 上传一律 `pending`,审核后 `published`/`rejected` |
|
||||
| `created_at` `updated_at` `deleted_at` | datetime | 软删除 |
|
||||
|
||||
* `config` / `stats` 用 **MEDIUMTEXT**(TEXT 的 64KB 上限在 `models.stats` 上踩过坑);
|
||||
* 迁移:`AddScenes1789650000000`(可逆,`down` 为 `DROP TABLE scenes`);
|
||||
* 状态机与审核复用既有约定(审核走 `/api/reviews/scene/:id/approve|reject`)。
|
||||
|
||||
+65
-1
@@ -1,7 +1,7 @@
|
||||
openapi: 3.0.3
|
||||
info:
|
||||
title: OpenDance Studio Web 管理服务端 API
|
||||
version: 0.4.0
|
||||
version: 0.5.0
|
||||
description: |
|
||||
OpenDance Studio 的唯一数据源与契约权威。
|
||||
契约版本见 contracts/VERSION。字段语义见 contracts/data-models.md。
|
||||
@@ -594,6 +594,70 @@ paths:
|
||||
contractVersion: { type: object, additionalProperties: { type: string } }
|
||||
revision: { type: string, description: 目录内容 sha256,变化即需重新拉取 }
|
||||
|
||||
/api/scenes:
|
||||
get:
|
||||
tags: [scenes]
|
||||
summary: 场景列表(v0.5.0)
|
||||
parameters:
|
||||
- $ref: '#/components/parameters/Page'
|
||||
- $ref: '#/components/parameters/PageSize'
|
||||
- name: q
|
||||
in: query
|
||||
schema: { type: string }
|
||||
description: 按 name/author 模糊匹配
|
||||
- name: status
|
||||
in: query
|
||||
schema: { type: string, enum: [draft, pending, published, rejected] }
|
||||
responses:
|
||||
'200':
|
||||
description: 分页结果 { items, total, page, pageSize }
|
||||
post:
|
||||
tags: [scenes]
|
||||
summary: 上传场景(multipart:file + name + 来源五元组 + 可选 config)
|
||||
description: |
|
||||
`file` 以 **.glb 为主**(直接导入,不重编码);`.gltf` 直接导入;
|
||||
`.zip` / `.pmx` / `.fbx` 由服务端转换为 GLB(场景不做 humanoid 重绑定、不转 VRM)。
|
||||
`config` 为 JSON 字符串(或平铺字段 gravity / wind / environment / spawnPoints / camera),
|
||||
含物理参数:重力向量、风向动态(基础风 + 阵风)、地面摩擦/弹性/坡度、碰撞体来源。
|
||||
服务端**只存参数、不跑物理**(仿真在客户端)。上传一律 status=pending。
|
||||
requestBody:
|
||||
content:
|
||||
multipart/form-data:
|
||||
schema:
|
||||
type: object
|
||||
required: [file, name, sourceType, sourceName, sourceUrl, license, author]
|
||||
properties:
|
||||
file: { type: string, format: binary }
|
||||
name: { type: string }
|
||||
config: { type: string, description: SceneConfig 的 JSON 字符串 }
|
||||
sourceType: { type: string }
|
||||
sourceName: { type: string }
|
||||
sourceUrl: { type: string }
|
||||
license: { type: string }
|
||||
author: { type: string }
|
||||
responses:
|
||||
'201':
|
||||
description: 已入库(pending)
|
||||
/api/scenes/{id}:
|
||||
parameters: [{ $ref: '#/components/parameters/Id' }]
|
||||
get:
|
||||
tags: [scenes]
|
||||
summary: 场景详情
|
||||
responses:
|
||||
'200': { description: Scene }
|
||||
'404': { description: 不存在 }
|
||||
patch:
|
||||
tags: [scenes]
|
||||
summary: 更新场景名称 / 物理参数(状态变更走 /api/reviews)
|
||||
responses:
|
||||
'200': { description: Scene }
|
||||
'400': { description: 参数非法或试图直接改状态 }
|
||||
delete:
|
||||
tags: [scenes]
|
||||
summary: 删除场景(软删除)
|
||||
responses:
|
||||
'204': { description: 已删除 }
|
||||
|
||||
components:
|
||||
parameters:
|
||||
Id:
|
||||
|
||||
Reference in New Issue
Block a user