这是 BSC9 战队官网,前端使用 Vue 3 + Vite + Tailwind CSS。当前项目还包含两个 Node 辅助服务:
- 公网机服务:托管构建后的前端、成员分数缓存、分数历史、队徽渲染请求队列。
- 内网机服务:访问公网机领取队徽渲染任务,在本机调用 Blender 渲染,然后把 PNG 上传回公网机。
- 用户在“队伍成员 - 成员排位”页面点击更新队徽。
- 浏览器请求公网机的
POST /api/clan-logo/request-render。 - 公网机只记录一个
pending状态,不会立即渲染。 - 内网机的
backend/server.js每隔PUBLIC_POLL_INTERVAL_MS访问公网机GET /api/internal/clan-logo/claim。 - 如果有待渲染任务,公网机把任务状态改为
rendering,并返回前 9 名学校名称。 - 内网机复制对应学校图标,调用 Blender 渲染队徽,再上传到公网机
POST /api/internal/clan-logo/upload?requestId=...。 - 公网机覆盖
public/pic/bsc9_clan_logo.webp,如果存在dist/,也会同步覆盖dist/pic/bsc9_clan_logo.webp。 - 前端轮询
GET /api/clan-logo/status,发现completed后刷新队徽 URL 版本。
因此,如果内网机轮询间隔是默认 10 分钟,用户点击后最长可能等接近 10 分钟才开始渲染。被内网机领取后,成员排位页会进入 3 分钟渲染倒计时。
注意:首页不会主动全局轮询公网状态;它订阅同一浏览器页面内的队徽更新事件。用户在成员排位页触发并完成渲染后,首页和成员排位页中的队徽会在当前页面会话内刷新。新访问页面会直接读取公网机上已经更新的 /pic/bsc9_clan_logo.webp。
安装依赖:
npm install启动 Vite 开发服务:
npm run dev如果需要在开发时访问公网辅助服务 API,另开一个终端启动:
npm run frontend-serviceVite 已配置 /api 代理到 http://localhost:5174,也可以用 VITE_PUBLIC_SERVICE_BASE 改为其他地址。
构建:
npm run build公网机需要安装 Node.js,并开放网站访问端口。公网机不需要安装 Blender。
- 拉取项目
公网机器无需下载 blender 部分内容:
cd ~
git clone --depth=1 --filter=blob:none --sparse git@github.com:CookedMelon/BSC9-website.git BSC9-website-new
cd BSC9-website-new
git sparse-checkout set \
src \
public \
index.html \
package.json \
package-lock.json \
vite.config.js \
tailwind.config.js \
postcss.config.js \
frontend-service.js \
public-member-score-service.js \
README.md- 安装依赖:
npm install- 构建前端:
npm run build- 设置环境变量:
$env:PUBLIC_SERVICE_HOST="0.0.0.0"
$env:PUBLIC_SERVICE_PORT="5174"
$env:CLAN_LOGO_SHARED_TOKEN="replace-with-a-long-random-secret"- 启动公网服务:
npm run frontend-service公网服务同时负责:
- 静态站点:优先服务
dist/,没有构建时回退到public/ - 队徽请求队列:
/api/clan-logo/request-render、/api/clan-logo/status - 内网渲染端上传接口:
/api/internal/clan-logo/claim、/api/internal/clan-logo/upload - 成员数据刷新:
/api/members/refresh、/api/members/cache - 分数折线图历史:
/api/school-score-history
建议用反向代理把公网域名转发到 127.0.0.1:5174。如果前端和 API 不在同一个域名,需要在构建前设置 VITE_PUBLIC_SERVICE_BASE 为公网服务地址。
内网机需要安装 Node.js 和 Blender。它不需要被公网访问,只需要能主动访问公网机。
- 拉取同一份项目并安装依赖:
npm install- 确认 Blender 路径和
.blend文件存在:
backend/blender-projects/bsc9_logo/bsc9_logo.blend
- 设置环境变量。通常只需要把
PUBLIC_SERVICE_BASE改成公网机地址,并保证 token 与公网机一致:
$env:PUBLIC_SERVICE_BASE="https://your-public-domain.example.com"
$env:CLAN_LOGO_SHARED_TOKEN="replace-with-the-same-long-random-secret"
$env:PUBLIC_POLL_INTERVAL_MS="600000"
$env:CLAN_LOGO_RENDER_IMAGE_SIZE="1024"
$env:CLAN_LOGO_DISPLAY_IMAGE_SIZE="512"
$env:BLENDER_EXE="D:\Programs\Steam\steamapps\common\Blender\blender.exe"- 启动内网渲染服务:
npm run backend启动后它会在 2 秒后先轮询一次,之后按 PUBLIC_POLL_INTERVAL_MS 周期轮询。默认值是 600000,即 10 分钟。想缩短等待时间可以改成例如 60000,即 1 分钟。
内网服务当前也会监听一个本地调试 HTTP 服务,默认 0.0.0.0:3109。生产链路不依赖公网访问这个端口;如果不需要调试,可以用防火墙限制该端口只允许本机或内网访问。
公网机和内网机都可以用 Windows 任务计划程序常驻。
公网机示例:
$project = "D:\Workspace\BSC9-website"
$node = "D:\Programs\nodejs\node.exe"
$action = New-ScheduledTaskAction `
-Execute $node `
-Argument "frontend-service.js" `
-WorkingDirectory $project
$trigger = New-ScheduledTaskTrigger -AtStartup
$settings = New-ScheduledTaskSettingsSet -RestartCount 999 -RestartInterval (New-TimeSpan -Minutes 1)
Register-ScheduledTask -TaskName "BSC9 Public Service" -Action $action -Trigger $trigger -Settings $settings -RunLevel Highest任务计划程序不适合直接写很多临时 $env:。建议在系统环境变量里设置:
PUBLIC_SERVICE_HOST=0.0.0.0
PUBLIC_SERVICE_PORT=5174
CLAN_LOGO_SHARED_TOKEN=replace-with-a-long-random-secret
内网机示例:
$project = "D:\Workspace\BSC9-website"
$node = "D:\Programs\nodejs\node.exe"
$action = New-ScheduledTaskAction `
-Execute $node `
-Argument "backend/server.js" `
-WorkingDirectory $project
$trigger = New-ScheduledTaskTrigger -AtStartup
$settings = New-ScheduledTaskSettingsSet -RestartCount 999 -RestartInterval (New-TimeSpan -Minutes 1)
Register-ScheduledTask -TaskName "BSC9 Blender Renderer" -Action $action -Trigger $trigger -Settings $settings -RunLevel Highest内网机建议设置系统环境变量:
PUBLIC_SERVICE_BASE=https://your-public-domain.example.com
CLAN_LOGO_SHARED_TOKEN=replace-with-the-same-long-random-secret
PUBLIC_POLL_INTERVAL_MS=600000
CLAN_LOGO_RENDER_IMAGE_SIZE=1024
CLAN_LOGO_DISPLAY_IMAGE_SIZE=512
BLENDER_EXE=D:\Programs\Steam\steamapps\common\Blender\blender.exe
也可以用 NSSM 安装为 Windows Service,更方便查看和重启:
nssm install BSC9BlenderRenderer "D:\Programs\nodejs\node.exe" "backend/server.js"
nssm set BSC9BlenderRenderer AppDirectory "D:\Workspace\BSC9-website"
nssm set BSC9BlenderRenderer AppEnvironmentExtra "PUBLIC_SERVICE_BASE=https://your-public-domain.example.com" "CLAN_LOGO_SHARED_TOKEN=replace-with-the-same-secret" "PUBLIC_POLL_INTERVAL_MS=600000" "CLAN_LOGO_RENDER_IMAGE_SIZE=1024" "CLAN_LOGO_DISPLAY_IMAGE_SIZE=512" "BLENDER_EXE=D:\Programs\Steam\steamapps\common\Blender\blender.exe"
nssm start BSC9BlenderRenderer公网机同理,把入口换成 frontend-service.js。
公网机如果是 Linux,可以使用 systemd:
[Unit]
Description=BSC9 Public Frontend Service
After=network.target
[Service]
WorkingDirectory=/opt/BSC9-website
ExecStart=/usr/bin/node frontend-service.js
Restart=always
RestartSec=5
Environment=PUBLIC_SERVICE_HOST=0.0.0.0
Environment=PUBLIC_SERVICE_PORT=5174
Environment=CLAN_LOGO_SHARED_TOKEN=replace-with-a-long-random-secret
[Install]
WantedBy=multi-user.target保存为 /etc/systemd/system/bsc9-public.service 后执行:
sudo systemctl daemon-reload
sudo systemctl enable --now bsc9-publicfrontend-service.js:公网机服务入口public-member-score-service.js:成员缓存和学校分数历史刷新backend/server.js:内网 Blender 轮询和渲染服务backend/render-blender.js:单次 Blender 渲染命令src/utils/clanLogoApi.js:前端队徽请求和状态查询src/components/MemberRanking.vue:队徽生成按钮、成员排位和分数折线图src/components/MapMaking.vue:队伍经历中的铺面制作页面