Files
opendance-web/DSH.md
T
zijunchiang 75498db1c0 feat(web): 部署方式由 Docker 改为 Linux 原生站点(nginx + systemd)
需求变更:Web 服务端不再使用 Docker,改为直接运行在 Linux 上的网站。

- 移除 deploy/docker-compose.yml、web-server/Dockerfile、
  web-server/admin/Dockerfile、web-server/.dockerignore
- 新增 deploy/install.sh:建服务用户与目录 → 装运行期依赖 → 迁移
  → 注册 systemd 服务 → 配置 nginx 站点 → 健康检查,一键完成
- 新增 deploy/systemd/opendance-api.service:ProtectSystem=strict 等
  安全加固,ReadWritePaths 限定为上传目录
- 新增 deploy/nginx/opendance.conf:同站点托管管理端静态资源 +
  反代 /api /health /static,client_max_body_size 512m,SPA 回退
- 新增 deploy/uninstall.sh:默认保留数据,--purge 才删除
- 新增配置项 HOST(AppConfig.bindHost):原生部署下 Node 只监听
  127.0.0.1,不直接对外暴露,实测外部 IP 不可达
- 同步更新 contracts/rest-api.yaml、DSH.md、project.yaml、README.txt、
  tasks/008、tasks/010 与发布打包脚本
2026-09-14 22:42:56 +08:00

5.7 KiB
Raw Blame History

DSH.md —— opendance-web(OpenDance Studio 项目一:Web 管理服务端)

0. 本文件的作用

本文件是 opendance-web 仓库内的 DSH 执行约束。顶层说明书见用户提供的 《DSH 开发文档:OpenDance Studio》,二者冲突时以顶层文档为准。

1. 项目定位

Web 管理服务端是另两端(Windows 客户端、Android 辅助 App)的唯一数据源与 契约权威。它管理歌曲、VRM 模型与动作来源,并输出冻结的 REST / WebSocket / 数据模型契约。

现有 MySQL 实例(外部,本项目不部署)
   │
   ▼
opendance-web  ←── 本仓库
   │  冻结 REST API + 数据模型 + WebSocket 关键点协议
   ├──▶ opendance-windows
   └──▶ opendance-android

2. 技术栈

组件 选型
后端 NestJS 11
ORM TypeORM 0.3
数据库 现有 MySQL 兼容实例(当前部署为 MariaDB 10.11.19),mysql2 驱动
管理前端 React 18 + Vite + TypeScript
3D 预览 three.js + @pixiv/three-vrm
多格式解析 BVH 内置纯 TS 解析器;FBX/glTF 走可选外部 Assimp
认证 本版本不含认证(内网部署);上线前须补 ≥ T-WEB-011

3. 单次会话加载范围

允许加载:

  1. 本文件 DSH.md
  2. project.yaml
  3. 当前 tasks/xxx.md
  4. 该任务文件中 load 列出的文件
  5. contracts/ 中被明确引用的锚点片段

禁止加载:

  • opendance-windows / opendance-android 的任何源码
  • 非当前任务的 tasks/*.md
  • 完整 contracts/ 目录(只引用锚点)
  • node_modules/、dist/、构建产物、二进制、模型文件、上传存储

4. 上下文预算

项 建议值
单任务文件数 ≤ 6
单任务代码行数 ≤ 1500
单任务 Token ≤ 12K
契约引用 只引用锚点,不加载全文

5. 目录结构

opendance-web/
├── project.yaml                 # 任务清单与状态
├── DSH.md                       # 本文件
├── tasks/                       # 单任务说明书(001~010)
├── contracts/                   # ★ 跨端契约(权威)
│   ├── VERSION                  # 契约版本(唯一来源)
│   ├── rest-api.yaml            # OpenAPI 3.0
│   ├── websocket-keypoints.md   # 239 字节关键点帧 + 控制消息
│   ├── data-models.md           # 资源字段与 VRM 优先规则
│   ├── skeleton-topology.md     # MediaPipe 33 点拓扑 + 关节角
│   ├── model-formats.md         # 支持格式、预处理产物、上传限制
│   ├── database.md              # 现有 MySQL 连接与迁移约定
│   └── open-source-credits.md   # 开源声明锚点(三端共用)
├── web-server/                  # NestJS 服务端
│   ├── src/                     # 源码(entities / modules / preprocess)
│   ├── admin/                   # React 管理端
│   ├── test/                    # 单元测试 + 端到端冒烟
│   └── scripts/                 # migrate.mjs / check-contracts.mjs / check-routes.mjs
├── deploy/                      # ★ Linux 原生站点部署(不含 MySQL)
│   ├── install.sh               # 一键部署(systemd + nginx)
│   ├── uninstall.sh
│   ├── .env.example
│   ├── systemd/opendance-api.service
│   └── nginx/opendance.conf
├── scripts/package-release.sh   # 发布产物打包
└── THIRD_PARTY.md

6. 硬性约束

  1. 不部署 MySQL。数据库为部署方提供的现有实例,连接信息只经环境变量注入。 也不使用 Docker:以 nginx 站点 + systemd 服务的形式直接跑在 Linux 上。
  2. DB_SYNCHRONIZE 生产必须为 false,所有表结构变更走 migration;每个 migration 必须可逆。
  3. 绝不把凭证写入仓库。.env 已在 .gitignore 中,只提交 .env.example。
  4. 来源五元组强制必填:source_type / source_name / source_url / license / author。任何资产入库缺一即 400。
  5. 契约先行:改接口先改 contracts/,再提升 contracts/VERSION,同步 web-server/src/config/contract-versions.ts,最后才改实现。 npm run contracts:check 在构建前拦截漂移。
  6. 不使用 SMPL 及其衍生拓扑(许可风险),统一 MediaPipe 33 点。
  7. 上传文件永不使用原始文件名作为路径,一律 sha256 去重后归档。

7. 每任务的执行步骤

# 1. 静态与单元校验
cd web-server
npm run contracts:check
npm run typecheck
npm run test

# 2. 构建
npm run build

# 3. 端到端冒烟(需数据库可连通)
npm run start:prod &
npm run test:smoke

# 4. 数据库迁移
npm run migration:run

# 5. 提交
git checkout -b task/T-WEB-0XX
git add . && git commit -m "feat(web): <scope>"
git push origin task/T-WEB-0XX
# Gitea 创建 PR → 合并到 dev

8. 环境变量

见 web-server/.env.example 与 deploy/.env.example。生产关键项:

DB_HOST DB_PORT DB_USER DB_PASS DB_NAME
DB_SYNCHRONIZE=false
STORAGE_DIR=/data/storage
UPLOAD_MAX_BYTES=536870912
ASSIMP_BIN=assimp           # 可选
CONTRACTS_DIR=/contracts    # 可选,读取实时契约版本

9. 上下文超标时的拆分策略

超标原因 拆分方式
单任务涉及多个端点 按端点拆
单文件过大 按类/函数拆,先生成接口再分实现
契约全文加载 改用锚点引用
需要参考其他项目 只读契约,不读源码
UI 与逻辑耦合 UI 任务只调用已定义接口
测试与实现同任务 测试单独任务,共享接口摘要