feat(web): 端口分离 + VMD 动作支持;契约升至 0.2.0
需求 1:管理端端口与软件 API 端口分离 - 软件 API 端口 PORT(默认 3000)只提供 /api、/health、/static、/contracts, 不提供管理页面(未命中路径 404);管理端端口 ADMIN_PORT(默认 3001) 提供管理页面与全部接口;ADMIN_HOST 可单独限制管理端来源 - main.ts 同进程监听两个端口,用 req.socket.localPort 区分端口行为; ADMIN_PORT=PORT 为单端口兼容模式(只创建一个 server,无 EADDRINUSE) - 端口非法在生产环境中止启动;ADMIN_PORT=PORT 只 warn - 启动日志分别打印两个端口的访问地址 需求 2:动作数据支持 VMD(MikuMikuDance) - vmd-parser.ts:二进制解析(30 字节头 + Shift-JIS 模型名 + 111 字节/条骨骼 关键帧 + morph 段)、MMD 贝塞尔插值、GBK 模型名回退、固定 30fps - mmd-skeleton.ts:标准 MMD 骨架;静止比例从参考 PMX 骨骼段实测得到 (足首 1.43 / 膝 6.57 / 髋 11.50 / 首 16.21 / 頭 17.16,腿长 10.09) - mmd-pose.ts:FK + 两骨骼解析腿部 IK(膝盖朝正面,不可达收敛为伸直) + 左手系→右手系 Z 镜像(由真实数据对照实验确定:94.1% vs 5.9%) - retarget.ts:抽出 worldFramesToKeypointFrames(),BVH 与 VMD 共用重定向 - MotionFormat 增 vmd、扩展名映射增 .vmd;管理端上传支持 .vmd - scripts/inspect-vmd.mjs:上传前自查工具 契约:rest-api / data-models / model-formats → 0.2.0(另两库已同步逐字节一致) 验证:85 项单测通过(VMD 31 项);契约与 29 条路由一致;typecheck/build 通过; 真实样本经 HTTP 端到端:霜雪千年 2901 帧(IK 腿)、恋爱循环 4604 帧(FK 腿) 均 preprocessState=done、0 NaN、0 越界(测试数据已从数据库清理)。
This commit is contained in:
+39
-14
@@ -16,7 +16,8 @@
|
||||
# APP_DIR 安装目录(默认 /opt/opendance)
|
||||
# SERVICE_USER 运行服务的系统用户(默认 opendance)
|
||||
# STORAGE_DIR 上传文件目录(默认 /var/lib/opendance/storage)
|
||||
# PORT API 监听端口(默认 3000)
|
||||
# PORT 软件 API 监听端口(默认 3000)
|
||||
# ADMIN_PORT 管理端端口(默认 PORT + 1;设为与 PORT 相同即单端口模式)
|
||||
# ============================================================
|
||||
set -euo pipefail
|
||||
# 失败时打印出错行号,避免只看到半截输出
|
||||
@@ -29,6 +30,7 @@ APP_DIR="${APP_DIR:-/opt/opendance}"
|
||||
SERVICE_USER="${SERVICE_USER:-opendance}"
|
||||
STORAGE_DIR="${STORAGE_DIR:-/var/lib/opendance/storage}"
|
||||
API_PORT="${PORT:-3000}"
|
||||
ADMIN_PORT="${ADMIN_PORT:-$((API_PORT + 1))}"
|
||||
# 注意:健康检查与汇总输出用的地址不在这里写死——真实监听地址来自
|
||||
# deploy/.env 的 HOST,脚本在源入 .env 后计算 BIND_HOST / HEALTH_HOST / LAN_IP。
|
||||
|
||||
@@ -114,6 +116,9 @@ set -a
|
||||
. ./deploy/.env
|
||||
set +a
|
||||
API_PORT="${PORT:-3000}"
|
||||
# 管理端端口:默认 API 端口 + 1;等于 API 端口时是单端口兼容模式
|
||||
ADMIN_PORT="${ADMIN_PORT:-$((API_PORT + 1))}"
|
||||
ADMIN_BIND_HOST="${ADMIN_HOST:-${HOST:-0.0.0.0}}"
|
||||
|
||||
[ -n "${DB_HOST:-}" ] || die "deploy/.env 中 DB_HOST 未设置"
|
||||
[ -n "${DB_USER:-}" ] || die "deploy/.env 中 DB_USER 未设置"
|
||||
@@ -398,6 +403,21 @@ if [ "$READY" -ne 1 ]; then
|
||||
fi
|
||||
log "API 已就绪:$(http_get "http://${HEALTH_HOST}:${API_PORT}/health" | head -c 200)"
|
||||
|
||||
# 管理端端口单独确认(端口写错时,只有在装的时候点出来才有人看见)
|
||||
ADMIN_READY=""
|
||||
ADMIN_HOST_FOR_PROBE="${ADMIN_BIND_HOST}"
|
||||
case "$ADMIN_HOST_FOR_PROBE" in
|
||||
0.0.0.0|'*'|'') ADMIN_HOST_FOR_PROBE="127.0.0.1" ;;
|
||||
esac
|
||||
if [ "$ADMIN_PORT" = "$API_PORT" ]; then
|
||||
ADMIN_READY="same"
|
||||
elif http_ok "http://${ADMIN_HOST_FOR_PROBE}:${ADMIN_PORT}/health"; then
|
||||
ADMIN_READY="yes"
|
||||
else
|
||||
ADMIN_READY="no"
|
||||
warn "管理端端口 ${ADMIN_PORT} 未在本机就绪(API 端口=${API_PORT})"
|
||||
fi
|
||||
|
||||
# ---------- 5. 边界:确认"外部到底能不能访问" ----------
|
||||
# 绑定层写错(HOST=127.0.0.1)时,本机 curl 一切正常,但外部永远连不上,
|
||||
# 而安装日志里看不出任何异常——必须在安装时就点出来。
|
||||
@@ -425,10 +445,14 @@ cat <<EOF
|
||||
------------------------------------------------------------
|
||||
反向代理说明(本脚本不部署反代)
|
||||
------------------------------------------------------------
|
||||
本服务已同时提供 API 与管理端页面,反代只需将请求整体转发至:
|
||||
http://<本机地址>:${API_PORT}
|
||||
管理端口与软件 API 端口是分开的,按用途分别转发:
|
||||
|
||||
健康检查(可用于反代的存活探测):http://<本机地址>:${API_PORT}/health
|
||||
软件 API 端口(给 Windows/Godot 客户端与 Android App):http://<本机地址>:${API_PORT}
|
||||
提供 /api、/health、/static、/contracts;**不含管理页面**(未知路径返回 404)
|
||||
管理端端口(给浏览器):http://<本机地址>:${ADMIN_PORT}
|
||||
提供管理页面 + 上面全部接口;建议只在内网 / VPN 内暴露
|
||||
|
||||
健康检查(可用于反代的存活探测,两个端口都提供):/health
|
||||
上传上限需在代理层同步放开(本服务为 $(( ${UPLOAD_MAX_BYTES:-536870912} / 1024 / 1024 )) MiB)
|
||||
|
||||
配置样例与完整说明:
|
||||
@@ -437,7 +461,7 @@ cat <<EOF
|
||||
deploy/proxy/README.md IIS / nginx 反代说明文档
|
||||
|
||||
注意:若反代与后端不在同一台机器,需保持 HOST=0.0.0.0(当前值:${BIND_HOST})并用防火墙限制来源;
|
||||
若在同一台机器,建议把 HOST 改为 127.0.0.1。
|
||||
若在同一台机器,建议把 HOST 改为 127.0.0.1(管理端可用 ADMIN_HOST 单独限制,当前值:${ADMIN_BIND_HOST})。
|
||||
------------------------------------------------------------
|
||||
|
||||
EOF
|
||||
@@ -497,16 +521,17 @@ cat <<EOF
|
||||
|
||||
============================================================
|
||||
OpenDance Studio Web 服务端已部署(业务服务,无 Docker、不含反向代理)
|
||||
监听地址: ${LISTEN_DESC}
|
||||
管理端首页: http://${HOST_HINT}:${API_PORT}/ (由本服务直接提供)
|
||||
API 前缀: http://${HOST_HINT}:${API_PORT}/api
|
||||
软件 API: ${LISTEN_DESC}
|
||||
接口:/api、/health、/static、/contracts(客户端调用;不含管理页面)
|
||||
管理端: http://${HOST_HINT}:${ADMIN_PORT}/(浏览器访问管理界面)
|
||||
健康检查: http://${HOST_HINT}:${API_PORT}/health
|
||||
契约快照: http://${HOST_HINT}:${API_PORT}/contracts/
|
||||
数据库: 使用现有实例 ${DB_HOST}:${DB_PORT:-3306}/${DB_NAME}
|
||||
上传目录: ${STORAGE_DIR}
|
||||
程序目录: ${APP_DIR}
|
||||
进程管理: ${INIT_SYSTEM}
|
||||
HOST 配置: ${BIND_HOST}(部署配置文件 ${APP_DIR}/deploy/.env)
|
||||
端口配置: API ${API_PORT} / 管理端 ${ADMIN_PORT}(${APP_DIR}/deploy/.env)
|
||||
绑定配置: HOST=${BIND_HOST} ADMIN_HOST=${ADMIN_BIND_HOST}
|
||||
|
||||
常用命令:
|
||||
${CMD_HINT}
|
||||
@@ -534,9 +559,9 @@ EOF
|
||||
esac
|
||||
cat <<EOF
|
||||
|
||||
别忘了在防火墙放行 ${API_PORT}/tcp:
|
||||
firewall-cmd --permanent --add-port=${API_PORT}/tcp && firewall-cmd --reload
|
||||
# 或:ufw allow ${API_PORT}/tcp
|
||||
别忘了在防火墙放行端口(客户端用 ${API_PORT},浏览器管理界面用 ${ADMIN_PORT}):
|
||||
firewall-cmd --permanent --add-port=${API_PORT}/tcp --add-port=${ADMIN_PORT}/tcp && firewall-cmd --reload
|
||||
# 或:ufw allow ${API_PORT}/tcp && ufw allow ${ADMIN_PORT}/tcp
|
||||
|
||||
诊断脚本(只读):bash ${APP_DIR}/deploy/check-access.sh
|
||||
============================================================
|
||||
@@ -549,8 +574,8 @@ elif [ "$EXTERNAL_OK" = "no" ]; then
|
||||
============================================================
|
||||
绑定层没问题,外部却连不上,通常是防火墙或云安全组拦截:
|
||||
|
||||
1) 放行端口:firewall-cmd --permanent --add-port=${API_PORT}/tcp && firewall-cmd --reload
|
||||
或 ufw allow ${API_PORT}/tcp
|
||||
1) 放行端口:firewall-cmd --permanent --add-port=${API_PORT}/tcp --add-port=${ADMIN_PORT}/tcp && firewall-cmd --reload
|
||||
或 ufw allow ${API_PORT}/tcp && ufw allow ${ADMIN_PORT}/tcp
|
||||
2) 云服务器还要在控制台「安全组 / 网络 ACL」放行 ${API_PORT}/tcp
|
||||
3) 确认客户端与服务器网络互通
|
||||
|
||||
|
||||
Reference in New Issue
Block a user