87a1ded2d2ec91a2b911e349329bb8050f606598
用户重装后仍报同一错误,且日志显示「复制 web-server … 174 个文件」。
经复现:发布包内 web-server 有 180 个文件(含 src/storage 2 个、
dist/storage 4 个),但 install.sh 复制后只剩 174 个——storage 被剔除了。
根因:上一轮只修了 package-release.sh,install.sh 里**还有一份独立的
copy_tree() 排除规则**,其中 'storage' 同样未锚定。install.sh 的
COPY_EXCLUDES 与 tar 回退分支都把 'storage' 当作任意层级模式,
于是 src/storage 与 dist/storage 在复制进 /opt/opendance 时被剔除。
这是同一类错误在本项目的第三次(.gitignore → package-release.sh →
install.sh)。因此这次不再只改模式,而是把语义显式化并加硬校验:
- 排除规则拆成三类常量,语义明确:
TOP_DIRS 仅顶层:storage data tmp dist-release → 必须锚定
ANY_DIRS 任意层级:node_modules .git coverage .gradle
TOP_FILES 仅顶层文件:.env .env.local
- rsync 用前导 '/' 锚定;tar 对 TOP_* 只给 './x'(绝不给 '*/storage'),
对 ANY_* 才给 './x' + '*/x'
- 复制后硬校验关键产物(dist/main.js、dist/storage/storage.module.js、
dist/app.module.js、admin/index.html),缺失即 die 并指出是排除规则问题
实测:
- rsync 路径:180 文件,src/storage 与 dist/storage 均在,
运行时 storage 与 .env 未带入,.env.example 保留
- tar 回退路径(隔离 PATH 屏蔽 rsync 后真跑):同样 180 文件,存储目录完整
- git 检出布局:214 文件,嵌套 admin/node_modules 未带入,本地 .env 未带入
- 对照实验:把锚定改回未锚定 → 复制剩 174 文件 → 守卫立刻报
「缺少关键文件 dist/storage/storage.module.js」并终止,不再拖到启动才炸
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.
================================================================ OpenDance Studio —— Web 管理服务端 v0.1.0 使用说明 ================================================================ 本服务端是 OpenDance Studio 三端中的第一端,负责管理歌曲、VRM 模型与 动作来源,是 Windows 客户端与 Android 辅助 App 的唯一数据源与契约权威。 重要:本服务端 **不部署、不管理 MySQL**。数据库为部署方提供的现有实例, 连接信息通过 .env 注入。 ---------------------------------------------------------------- 一、部署到 Linux 服务器(原生站点,不使用 Docker) ---------------------------------------------------------------- 部署形态:一个 nginx 站点同时提供管理端页面与 API。 Node 进程由 systemd 托管,只监听 127.0.0.1,外部只能经 nginx 访问。 前置要求 - Linux 服务器,有 root 权限(不需要 sudo,直接以 root 执行即可) - Node.js 22 或更高版本 - nginx(未安装时脚本会跳过站点配置并给出提示) - 进程管理:systemd / OpenRC / SysVinit 均可;**三者都没有也能装** (自动降级为 nohup 后台进程 + PID 文件 + crontab @reboot 开机自启) - 一个可连通的现有 MySQL / MariaDB 实例,并已创建数据库与账号: CREATE DATABASE IF NOT EXISTS dpendance CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; CREATE USER IF NOT EXISTS 'dpendance'@'%' IDENTIFIED BY '<密码>'; GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, ALTER, INDEX, DROP, REFERENCES ON dpendance.* TO 'dpendance'@'%'; FLUSH PRIVILEGES; (本项目不会创建数据库本身,也不需要 GRANT OPTION / FILE / SUPER 等管理权限) 部署步骤 tar -xzf opendance-web-v0.1.0.tar.gz cd opendance-web-v0.1.0 cp deploy/.env.example deploy/.env vi deploy/.env # 填写 DB_HOST / DB_PORT / DB_USER / DB_PASS / DB_NAME sudo bash deploy/install.sh 脚本会依次: 校验环境与 .env → 创建服务用户与目录 → 安装运行期依赖 → 执行 TypeORM 迁移 → 注册并启动 systemd 服务 → 等待健康检查 → 配置 nginx 站点并重载 部署完成后(<host> 为服务器 IP) 管理端首页: http://<host>/ API 前缀: http://<host>/api 健康检查: http://<host>/health 契约快照: http://<host>/contracts/ 可覆盖的安装参数 APP_DIR=/opt/opendance 程序目录 SERVICE_USER=opendance 运行服务的系统用户 STORAGE_DIR=/var/lib/opendance/storage 上传文件目录 SERVER_NAME=example.com nginx server_name SKIP_NGINX=1 只装 API 服务,不配置 nginx 例:sudo SERVER_NAME=dance.example.com bash deploy/install.sh 升级 解压新版本后重新执行 sudo bash deploy/install.sh 即可(会覆盖程序文件, 保留 deploy/.env 与上传数据)。 卸载 sudo bash deploy/uninstall.sh # 停服务、禁用站点,保留数据 sudo bash deploy/uninstall.sh --purge # 一并删除程序目录与上传文件 数据库始终由部署方自行管理,卸载脚本不做任何改动。 常用命令(按安装时自动检测到的初始化系统而定) systemd: systemctl status opendance-api # 服务状态 journalctl -u opendance-api -f # 实时日志 systemctl restart opendance-api # 重启 OpenRC: rc-service opendance-api status / restart tail -f /var/log/opendance-api.log SysVinit: /etc/init.d/opendance-api status / restart 无 init 系统(降级模式): bash /opt/opendance/deploy/ctl.sh status | restart | logs nginx 配置校验: nginx -t && (systemctl reload nginx || rc-service nginx reload || nginx -s reload) ---------------------------------------------------------------- 二、本地开发 ---------------------------------------------------------------- 后端 cd web-server cp .env.example .env # 填写 DB_* npm install npm run migration:run # 首次需要 npm run start:dev # http://localhost:3000 管理前端 cd web-server/admin npm install npm run dev # http://localhost:5173(/api 与 /health 代理到 3000) ---------------------------------------------------------------- 三、验证 ---------------------------------------------------------------- cd web-server npm run contracts:check # 契约版本一致性 npm run typecheck # TypeScript 严格检查 npm run test # 31 项单元测试 npm run build # 生产构建 npm run start:prod & # 启动 npm run test:smoke # 57 项端到端冒烟(需要数据库可连通) cd ../admin && npm run build # 管理端构建 ---------------------------------------------------------------- 四、环境变量 ---------------------------------------------------------------- DB_HOST / DB_PORT / DB_USER / DB_PASS / DB_NAME 现有 MySQL 实例连接信息(必填) DB_SYNCHRONIZE 必须为 false。生产环境启动时若检测到 true 会直接中止启动。 所有表结构变更通过 TypeORM migration 执行。 DB_LOGGING 是否打印 SQL(默认 false) PORT API 监听端口(默认 3000) HOST API 监听地址(原生部署用 127.0.0.1,仅由 nginx 反代访问) STORAGE_DIR 上传文件存储目录(原生部署默认 /var/lib/opendance/storage) UPLOAD_MAX_BYTES 单文件上限,默认 536870912(512 MiB) ASSIMP_BIN 可选:Assimp 可执行文件,FBX/glTF 动作预处理需要 CONTRACTS_DIR 可选:契约目录,设置后 /health 反映实时契约版本 (原生部署默认指向 /opt/opendance/contracts) ---------------------------------------------------------------- 五、主要 API ---------------------------------------------------------------- GET /health 健康检查(含数据库连通性) GET /api/songs 曲目列表(分页 / 检索) POST /api/songs 新建曲目 GET /api/songs/:id 曲目详情 PATCH /api/songs/:id 更新曲目 DELETE /api/songs/:id 删除曲目(软删除) POST /api/songs/:id/audio 上传音频 GET /api/motions 动作列表 POST /api/motions 上传动作 + 来源信息 POST /api/motions/:id/preprocess BVH/FBX → MediaPipe33 关键点 GET /api/motions/:id/keypoints 下载关键点序列(NDJSON) GET /api/models 模型列表 POST /api/models 上传模型 + 来源信息(VRM 优先) POST /api/models/:id/primary 设为全局默认模型 GET /api/reviews 审核流水 / 待审列表 POST /api/reviews/:type/:id/approve 审核通过 POST /api/reviews/:type/:id/reject 审核驳回(必须填意见) GET /api/catalog/export 客户端一次性拉取已发布目录 GET /api/catalog/version 契约版本 + 目录指纹 完整契约(OpenAPI 3.0)见 contracts/rest-api.yaml。 上传文件通过 /static/<kind>/<yyyy>/<mm>/<sha256>.ext 访问, 相同内容只落盘一次(sha256 去重)。 ---------------------------------------------------------------- 六、目录结构 ---------------------------------------------------------------- project.yaml 任务清单与状态 DSH.md 本项目 DSH 执行约束 tasks/ 单任务说明书(T-WEB-001 ~ 010) contracts/ 跨端契约(权威,改接口先改这里) web-server/ NestJS 服务端源码 web-server/admin/ React 管理端 deploy/ Linux 原生站点部署(nginx + systemd,不含 MySQL) THIRD_PARTY.md 第三方开源项目声明 ---------------------------------------------------------------- 七、安全提示 ---------------------------------------------------------------- 1. .env 已被 .gitignore 忽略,禁止提交;仓库中只保留 .env.example。 2. 数据库账号使用最小权限,不授予 GRANT OPTION / FILE / SUPER。 3. 本版本未内置管理端登录认证,请部署在内网,或在 nginx 层加 Basic Auth / SSO。 4. 上传的模型与动作必须填写来源五元组并通过审核后才对客户端可见。 5. 未使用 SMPL 拓扑,统一 MediaPipe 33 点,规避非商用许可限制。 ---------------------------------------------------------------- 八、第三方开源声明 ---------------------------------------------------------------- 见 THIRD_PARTY.md,或访问站点 http://<host>/ 的「关于」页面。
Releases
17
Languages
TypeScript
80.3%
Shell
9.3%
JavaScript
7.4%
CSS
2.3%
Python
0.6%