docs(contracts): 补齐 rest-api 里 CatalogBundle.scenes[] 与 Scene/SceneConfig 结构
`catalog/export` 自 v0.7.0 起就返回 `scenes[]`(catalog.service.ts 已实现, data-models.md §7 也已冻结),但 rest-api.yaml 的 CatalogBundle 漏了这个字段, 且 components 里没有 Scene / SceneConfig 定义 —— 属于"实现已发布、规格漏写"。 本次只补规格,不改线格式,因此六个契约版本号均不变(rest-api 仍为 0.5.0, 与文档 v1.6 §5.6「客户端契约升级到 rest-api 0.5.0」一致): - CatalogBundle 增加 scenes[](标注 0.5.0 起下发) - 新增 Scene(含 glbUrl/thumbnailUrl/config/stats/来源五元组/status) - 新增 SceneConfig(physics.gravity/wind/ground/colliders、environment、 spawnPoints<=16、camera)与复用的 Vec3 注入依赖:Windows 端 T-WIN-013 需要按这份结构生成 GDScript 类型, 规格缺失会导致两端对字段边界(如 0~1、±200)的理解不一致。 同时补 deploy/proxy/README.md 第九节:托管 Gitea 的 IIS 站点 附件上传上限(与一~五节的 Web 服务反代是两个不同站点)。 实测 30.5 MB / 40 MB 上传返回 HTTP 413,根因是 IIS 默认 maxAllowedContentLength = 30,000,000 字节;给出放宽到 256 MB 的 IIS / ARR / Gitea app.ini / nginx 四处配置与复验命令。 这解释了 Windows 端 v0.1.0 为何被拆成 zip.part0/1/2(交付缺陷)。
This commit is contained in:
@@ -940,4 +940,96 @@ components:
|
|||||||
songs: { type: array, items: { $ref: '#/components/schemas/Song' } }
|
songs: { type: array, items: { $ref: '#/components/schemas/Song' } }
|
||||||
motions: { type: array, items: { $ref: '#/components/schemas/Motion' } }
|
motions: { type: array, items: { $ref: '#/components/schemas/Motion' } }
|
||||||
models: { type: array, items: { $ref: '#/components/schemas/Model' } }
|
models: { type: array, items: { $ref: '#/components/schemas/Model' } }
|
||||||
|
scenes:
|
||||||
|
type: array
|
||||||
|
description: 已发布场景(rest-api 0.5.0 起随目录下发;结构见 data-models.md 7)
|
||||||
|
items: { $ref: '#/components/schemas/Scene' }
|
||||||
defaultModelId: { type: integer, format: int64, nullable: true }
|
defaultModelId: { type: integer, format: int64, nullable: true }
|
||||||
|
|
||||||
|
Scene:
|
||||||
|
allOf:
|
||||||
|
- $ref: '#/components/schemas/SourceFields'
|
||||||
|
- type: object
|
||||||
|
properties:
|
||||||
|
id: { type: integer, format: int64 }
|
||||||
|
name: { type: string }
|
||||||
|
glbUrl: { type: string, nullable: true, description: 场景 GLB 下载地址 }
|
||||||
|
thumbnailUrl: { type: string, nullable: true }
|
||||||
|
fileSize: { type: integer, nullable: true }
|
||||||
|
fileSha256: { type: string, nullable: true }
|
||||||
|
conversionNote:
|
||||||
|
type: string
|
||||||
|
nullable: true
|
||||||
|
description: 由 .zip/.pmx/.fbx 转换而来时的说明;直接上传 GLB 为 null
|
||||||
|
config:
|
||||||
|
allOf: [{ $ref: '#/components/schemas/SceneConfig' }]
|
||||||
|
nullable: true
|
||||||
|
description: 物理 / 环境 / 出生点 / 相机;服务端只存参数,仿真在客户端
|
||||||
|
stats:
|
||||||
|
type: object
|
||||||
|
nullable: true
|
||||||
|
description: 场景 GLB 分析(面数 / 网格 / 材质 / warnings)
|
||||||
|
status: { $ref: '#/components/schemas/PublishStatus' }
|
||||||
|
createdAt: { type: string, format: date-time }
|
||||||
|
updatedAt: { type: string, format: date-time }
|
||||||
|
|
||||||
|
SceneConfig:
|
||||||
|
type: object
|
||||||
|
description: >-
|
||||||
|
data-models.md 7.1 冻结结构。服务端入库时对每项做边界收敛
|
||||||
|
(越界夹紧、非法枚举回退默认值),客户端拿到的参数一定可解释。
|
||||||
|
properties:
|
||||||
|
physics:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
gravity:
|
||||||
|
type: object
|
||||||
|
description: 米/秒^2,各分量 ±200
|
||||||
|
properties:
|
||||||
|
x: { type: number }
|
||||||
|
y: { type: number }
|
||||||
|
z: { type: number }
|
||||||
|
wind:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
base: { $ref: '#/components/schemas/Vec3' }
|
||||||
|
gustAmplitude: { type: number, description: 0~100 }
|
||||||
|
gustFrequency: { type: number, description: Hz,0.01~5 }
|
||||||
|
gustDirection: { $ref: '#/components/schemas/Vec3' }
|
||||||
|
space: { type: string, enum: [world, local] }
|
||||||
|
ground:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
friction: { type: number, description: 0~1 }
|
||||||
|
restitution: { type: number, description: 0~1 }
|
||||||
|
slopeLimit: { type: number, description: 0~89 度 }
|
||||||
|
colliders: { type: string, enum: [auto, mesh, none] }
|
||||||
|
environment:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
ambientColor: { type: string, description: '#RRGGBB' }
|
||||||
|
ambientIntensity: { type: number, description: 0~4 }
|
||||||
|
fogDensity: { type: number, description: 0~1,0=关闭 }
|
||||||
|
spawnPoints:
|
||||||
|
type: array
|
||||||
|
maxItems: 16
|
||||||
|
items:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
x: { type: number }
|
||||||
|
y: { type: number }
|
||||||
|
z: { type: number }
|
||||||
|
yaw: { type: number, description: 朝向(度,绕 Y 轴) }
|
||||||
|
camera:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
mode: { type: string, enum: [follow, fixed, orbit] }
|
||||||
|
distance: { type: number, description: 0.5~50 }
|
||||||
|
height: { type: number, description: 0~20 }
|
||||||
|
|
||||||
|
Vec3:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
x: { type: number }
|
||||||
|
y: { type: number }
|
||||||
|
z: { type: number }
|
||||||
|
|||||||
@@ -204,6 +204,7 @@ curl -i http://<反代地址>/api/catalog/version
|
|||||||
| 客户端接口全 404 | 把客户端的转发规则指到了管理端口之外,或误把 `/api` 前缀重写掉;客户端应转发到软件 API 端口 |
|
| 客户端接口全 404 | 把客户端的转发规则指到了管理端口之外,或误把 `/api` 前缀重写掉;客户端应转发到软件 API 端口 |
|
||||||
| 管理页面 404 | 把浏览器的转发规则指到了**软件 API 端口**(该端口不提供管理页面,这是有意设计);改指 `ADMIN_PORT` |
|
| 管理页面 404 | 把浏览器的转发规则指到了**软件 API 端口**(该端口不提供管理页面,这是有意设计);改指 `ADMIN_PORT` |
|
||||||
| 两个端口都转发到同一条规则 | 若确实想合并两个端口,设置 `ADMIN_PORT=PORT` 走单端口模式,而不是让反代去猜 |
|
| 两个端口都转发到同一条规则 | 若确实想合并两个端口,设置 `ADMIN_PORT=PORT` 走单端口模式,而不是让反代去猜 |
|
||||||
|
| **Gitea 的 Release 附件上传 413** | 这是**另一台站点**(托管 Gitea 的 IIS),本服务的 `UPLOAD_MAX_BYTES` 管不到它;见第九节 |
|
||||||
|
|
||||||
## 八、还没有反代时:直连后端怎么访问
|
## 八、还没有反代时:直连后端怎么访问
|
||||||
|
|
||||||
@@ -226,3 +227,91 @@ bash deploy/check-access.sh /opt/opendance # 指定安装目录
|
|||||||
脚本会打印 `.env` 中的 `HOST`/`PORT`、实际监听地址(重点看是否只监听
|
脚本会打印 `.env` 中的 `HOST`/`PORT`、实际监听地址(重点看是否只监听
|
||||||
`127.0.0.1`)、回环与对外 IP 两次自测结果、80/443 上有没有反代、
|
`127.0.0.1`)、回环与对外 IP 两次自测结果、80/443 上有没有反代、
|
||||||
firewalld / ufw / iptables 的放行情况,并直接给出修复命令。
|
firewalld / ufw / iptables 的放行情况,并直接给出修复命令。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 九、Gitea 站点的附件上传上限(Windows 客户端整包必须放开)
|
||||||
|
|
||||||
|
> 本节与第一~五节是**两个不同的站点**:前者是本 Web 服务的反代,后者是托管
|
||||||
|
> **Gitea**(源码仓库 + Release 附件)的站点。Windows 客户端的发布整包走 Gitea,
|
||||||
|
> 因此**必须**单独放开 Gitea 站点的上限。
|
||||||
|
|
||||||
|
### 9.1 实测结论
|
||||||
|
|
||||||
|
| 上传体积 | 结果 |
|
||||||
|
|--|--|
|
||||||
|
| 14 MB | 通过(HTTP 201) |
|
||||||
|
| 30.5 MB | **失败 HTTP 413**(IIS「请求实体过大」页面) |
|
||||||
|
| 40 MB | **失败 HTTP 413** |
|
||||||
|
|
||||||
|
→ 默认上限就是 **IIS 的 `maxAllowedContentLength = 30,000,000` 字节(≈28.6 MiB)**。
|
||||||
|
Windows 客户端整包约 38 MB(`OpenDance.exe` ≈104 MB 未压缩 + `OpenDance.pck`),
|
||||||
|
早先因此被拆成 `zip.part0/1/2`(每卷 13 MiB)才传上去 —— 用户拿到的是
|
||||||
|
**无法直接解压的碎片**,必须自己拼接,属于交付缺陷。
|
||||||
|
|
||||||
|
### 9.2 正确做法:放开 Gitea 站点上限到 256 MB
|
||||||
|
|
||||||
|
1. **IIS**(托管 Gitea 的站点根目录 `web.config`):
|
||||||
|
|
||||||
|
```xml
|
||||||
|
<configuration>
|
||||||
|
<system.webServer>
|
||||||
|
<security>
|
||||||
|
<requestFiltering>
|
||||||
|
<!-- 256 MiB;默认 30,000,000 字节,Windows 整包会被 413 掉 -->
|
||||||
|
<requestLimits maxAllowedContentLength="268435456" />
|
||||||
|
</requestFiltering>
|
||||||
|
</security>
|
||||||
|
<serverRuntime uploadReadAheadSize="268435456" />
|
||||||
|
</system.webServer>
|
||||||
|
</configuration>
|
||||||
|
```
|
||||||
|
|
||||||
|
`uploadReadAheadSize` 必须一起改(SSL 场景下默认仅 48 KB,会中途失败)。
|
||||||
|
|
||||||
|
2. **ARR**(服务器级,不是站点级)在 `applicationHost.config` 中同步放宽请求体上限:
|
||||||
|
|
||||||
|
```xml
|
||||||
|
<system.webServer>
|
||||||
|
<proxy>
|
||||||
|
<forwarding />
|
||||||
|
</proxy>
|
||||||
|
</system.webServer>
|
||||||
|
<webProxy enabled="true" timeout="00:05:00" />
|
||||||
|
<serverRuntime uploadReadAheadSize="268435456" />
|
||||||
|
```
|
||||||
|
|
||||||
|
并在 IIS 管理器 → Application Request Routing Cache → Server Proxy Settings
|
||||||
|
中确认请求体上限(`maxRequestBytes`)≥ `268435456`。
|
||||||
|
|
||||||
|
3. **Gitea 自身** `app.ini`:
|
||||||
|
|
||||||
|
```ini
|
||||||
|
[attachment]
|
||||||
|
; 默认通常为 4~32 MB,必须一起放大,否则 IIS 放行了 Gitea 仍会拒绝
|
||||||
|
MAX_SIZE = 256
|
||||||
|
```
|
||||||
|
|
||||||
|
4. **若 Gitea 前面还有 nginx**(IIS 之外或之内):
|
||||||
|
|
||||||
|
```nginx
|
||||||
|
client_max_body_size 256m;
|
||||||
|
proxy_read_timeout 300s;
|
||||||
|
proxy_send_timeout 300s;
|
||||||
|
```
|
||||||
|
|
||||||
|
5. 改完执行 `iisreset /noforce`(或只重启站点),再按下节复验。
|
||||||
|
|
||||||
|
### 9.3 复验方法
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 造一个 40 MB 文件上传到 Gitea 的附件接口,预期 HTTP 201(不再是 413)
|
||||||
|
head -c 40000000 /dev/urandom > /tmp/probe.bin
|
||||||
|
curl -i -X POST \
|
||||||
|
-H "Authorization: token <token>" \
|
||||||
|
-F "file=@/tmp/probe.bin" \
|
||||||
|
"https://<Gitea 地址>/api/v1/repos/<owner>/<repo>/releases/<id>/assets?name=probe.bin"
|
||||||
|
```
|
||||||
|
|
||||||
|
在放开上限之前,**不要**用分卷绕过:Windows 端 `build/package-release.sh`
|
||||||
|
会拒绝生成 `.partN`,超限时直接告警并要求先放宽本节的配置。
|
||||||
|
|||||||
Reference in New Issue
Block a user