Files
zijunchiang 12041f2e58 fix(upload,models): 上传落盘补齐兜底 + 不可用模型归因准确(v0.7.5)
两个真实缺陷,都由本轮的「跨端边界验收」暴露:

一、上传落盘:去重命中时删掉了唯一副本(T-WEB-017)
persistTempFile(动作 / 模型 / 场景上传走的通路)在 sha256 去重命中时直接
safeUnlink(tempPath) 并返回旧记录 —— 一旦记录指向的路径不存在(换过 STORAGE_DIR、
只恢复数据库、手工删过文件),上传仍返回 201,但后续动作预处理 500
(实测 ENOENT .../<sha>.vmd)、模型分析与缩略图静默失败。持久化通路 persistBuffer
早在上一轮就补了「文件缺失则按原路径补写」,这条通路漏了;现在同样处理:
先 existsSync(absolutePath(existing)),缺失则按记录里的原路径 rename(跨设备退化为
copyFile)补写,只有确认目标存在才删临时文件。
新增 test/storage-persist.spec.ts(5 项):首次上传 / 去重命中且文件在 /
去重命中但文件已丢失(补写而非删除)/ persistBuffer 回归 / 空文件拒绝。
反向验证:临时还原修复后第 3 条立刻失败,恢复后 5 项全过。

二、不可用模型的原因归因不准确(T-WEB-017)
unusableReason() 只要 stats 里有 humanoid 数字就归因于 humanoid,于是一个直接上传的
.glb(骨架完全合规、drivable=true、只是没有 VRM 容器)会被写成
「humanoid 不达标(19/22)」,把审核引向"重新绑定骨骼"而不是"以 VRM 交付"。
实测(跨端验收用真实 PMX→Assimp→GLB,886 KB):
  修复前 → humanoid 不达标(19/22),未产出 VRM
  修复后 → 未产出 VRM(格式为 GLB;humanoid 覆盖 19/22 已达标),需重新以 VRM 交付才能进入客户端目录
现在按 drivable 区分:不满足 16 根必需骨才归因 humanoid;达标但没 VRM 容器则明确说"已达标"。
新增 2 项单测(model-usability 5 → 7 项)。

三、跨端边界验收(Windows × Web)新增两类场景,双方都断言
  * 不可用模型:真实 PMX 用 Assimp 转 GLB 后入库(等价"转换只产出 GLB")→
    usable=false、原因准确、**不进入 catalog/export**、defaultModelId 不变;
    包内客户端的 bundle.models 里没有任何非 VRM 模型;
  * 场景 config 只给 {physics:{gravity:{y:-9.8}}} → 服务端补齐默认
    (碰撞体 auto、地面 0.6/45°、静风、相机 follow、环境光 1、出生点 1 条),
    客户端解析后逐项一致。

实测:npm run verify 全绿(契约 6 项 / 35 路由 / 版本 0.7.5 / 27 文件 309 项测试 /
build / 产物级实体注册核对 / 启动冒烟);跨端集成验收在**发布包起的服务端**上全部通过。
版本 0.7.4 → 0.7.5。
2026-09-18 03:03:50 +08:00

107 lines
4.0 KiB
YAML
Raw Permalink 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.
project: opendance-web-server
version: 0.7.5
repository: opendance-web
default_branch: main
contracts_version:
rest-api: 0.5.0
websocket-keypoints: 0.2.0
data-models: 0.7.0
skeleton-topology: 0.2.0
model-formats: 0.5.0
database: 0.4.0
# 契约变更流程(文档 7.2):
# 任何跨端契约变更必须先在本项目修改 contracts/ 并提升版本,
# 再在 opendance-windows / opendance-android 创建适配任务。
database:
# 使用现有实例,本项目不部署、不管理 MySQL
managed_by: external
engine: MySQL 兼容(含 MariaDB 10.5+)
name: opendance
charset: utf8mb4
migrations: TypeORM migration
synchronize: forbidden
tasks:
- id: T-WEB-001
file: tasks/001-scaffold.md
scope: NestJS 骨架 + 连接现有 MySQL
status: done
- id: T-WEB-002
file: tasks/002-db-migration.md
scope: TypeORM 迁移生成 opendance 表结构
status: done
- id: T-WEB-003
file: tasks/003-song-crud.md
scope: /api/songs CRUD
status: done
- id: T-WEB-004
file: tasks/004-motion-upload.md
scope: 动作数据上传(BVH / VMD / FBX / glTF / keypoints)+ 来源字段
status: done
- id: T-WEB-005
file: tasks/005-model-upload.md
scope: 模型上传(GLB/VRM 直接导入 + PMX/FBX 转换 + .zip 自动搜索)+ 自动分析/缩略图 + 上传即待审
status: done
- id: T-WEB-006
file: tasks/006-keypoint-preprocess.md
scope: BVH / VMD / FBX -> 关键点序列预处理
status: done
- id: T-WEB-007
file: tasks/007-upload-review.md
scope: 上传审核流程
status: done
- id: T-WEB-008
file: tasks/008-admin-ui-songs.md
scope: 歌曲管理界面
status: done
- id: T-WEB-009
file: tasks/009-admin-ui-models.md
scope: 模型管理界面 + 来源展示
status: done
- id: T-WEB-010
file: tasks/010-deploy.md
scope: 部署脚本(双端口:软件 API 3000 + 管理端 3001,不部署 MySQL)+ deploy/.env 初始化引导(init-env.sh,HOST 默认 0.0.0.0)
status: done
- id: T-WEB-011
file: tasks/011-version-display.md
scope: 管理端左下角展示当前版本号(唯一来源 package.json)
status: done
- id: T-WEB-012
file: tasks/012-vrm-first.md
scope: 模型主力格式全面转为 VRM(非 VRM 入库标记不可用,不进已发布目录)
status: done
- id: T-WEB-013
file: tasks/013-bone-rebinding.md
scope: 动作内部标准(33 点)+ 模型骨骼按名重绑定(含 MMD/中文名)
status: done
- id: T-WEB-014
file: tasks/014-motion-preview.md
scope: 动作管理预览(离线骨架缩略图 + 管理端 3D 回放)
status: done
- id: T-WEB-015
file: tasks/015-scene-management.md
scope: 场景管理(GLB + 重力/风/物理参数,服务端只存参数)
status: done
- id: T-WEB-016
file: tasks/016-websocket-contract-020.md
scope: 契约 websocket-keypoints 0.2.0(保活 / 设备去重 / 状态机,与 T-AND-011 对齐)
status: done
- id: T-WEB-017
file: tasks/017-model-unusable-reason.md
scope: 不可用模型的原因归因必须准确(按 drivable 判断)+ 跨端边界验收(不可用模型不进目录 / 场景 config 缺字段收敛)
status: done
deliverable:
artifact: opendance-web-v0.7.5.tar.gz
packaging: Linux 业务服务(系统服务托管,双端口:软件 API + 管理端,不含 MySQL、不含反向代理、不使用 Docker)
includes:
- web-server/ # NestJS 源码 + 构建产物(含 BVH / VMD 内置解析、ZIP 读取与模型压缩包转换)
- admin/ # React 管理端构建产物
- deploy/ # install.sh / init-env.sh / systemd / openrc / initd / ctl.sh / .env.example(PORT、ADMIN_PORT、HOST)
- deploy/proxy/ # 反向代理说明(nginx / IIS,仅供参考不部署)
- contracts/ # 当前版本契约快照(rest-api 0.5.0 / websocket-keypoints 0.2.0 / data-models 0.7.0 / database 0.4.0)
- THIRD_PARTY.md # 开源声明
- README.txt # 使用说明