Skip to content

Repository files navigation

Beat C9ber League (BSC9) 官方网站

这是 BSC9 战队官网,前端使用 Vue 3 + Vite + Tailwind CSS。当前项目还包含两个 Node 辅助服务:

  • 公网机服务:托管构建后的前端、成员分数缓存、分数历史、队徽渲染请求队列。
  • 内网机服务:访问公网机领取队徽渲染任务,在本机调用 Blender 渲染,然后把 PNG 上传回公网机。

当前运行链路

  1. 用户在“队伍成员 - 成员排位”页面点击更新队徽。
  2. 浏览器请求公网机的 POST /api/clan-logo/request-render
  3. 公网机只记录一个 pending 状态,不会立即渲染。
  4. 内网机的 backend/server.js 每隔 PUBLIC_POLL_INTERVAL_MS 访问公网机 GET /api/internal/clan-logo/claim
  5. 如果有待渲染任务,公网机把任务状态改为 rendering,并返回前 9 名学校名称。
  6. 内网机复制对应学校图标,调用 Blender 渲染队徽,再上传到公网机 POST /api/internal/clan-logo/upload?requestId=...
  7. 公网机覆盖 public/pic/bsc9_clan_logo.webp,如果存在 dist/,也会同步覆盖 dist/pic/bsc9_clan_logo.webp
  8. 前端轮询 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-service

Vite 已配置 /api 代理到 http://localhost:5174,也可以用 VITE_PUBLIC_SERVICE_BASE 改为其他地址。

构建:

npm run build

公网机部署

公网机需要安装 Node.js,并开放网站访问端口。公网机不需要安装 Blender。

  1. 拉取项目

公网机器无需下载 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
  1. 安装依赖:
npm install
  1. 构建前端:
npm run build
  1. 设置环境变量:
$env:PUBLIC_SERVICE_HOST="0.0.0.0"
$env:PUBLIC_SERVICE_PORT="5174"
$env:CLAN_LOGO_SHARED_TOKEN="replace-with-a-long-random-secret"
  1. 启动公网服务:
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。它不需要被公网访问,只需要能主动访问公网机。

  1. 拉取同一份项目并安装依赖:
npm install
  1. 确认 Blender 路径和 .blend 文件存在:
backend/blender-projects/bsc9_logo/bsc9_logo.blend
  1. 设置环境变量。通常只需要把 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"
  1. 启动内网渲染服务:
npm run backend

启动后它会在 2 秒后先轮询一次,之后按 PUBLIC_POLL_INTERVAL_MS 周期轮询。默认值是 600000,即 10 分钟。想缩短等待时间可以改成例如 60000,即 1 分钟。

内网服务当前也会监听一个本地调试 HTTP 服务,默认 0.0.0.0:3109。生产链路不依赖公网访问这个端口;如果不需要调试,可以用防火墙限制该端口只允许本机或内网访问。

让服务始终运行

Windows:任务计划程序

公网机和内网机都可以用 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

Windows:NSSM

也可以用 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

公网机如果是 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-public

关键文件

  • frontend-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:队伍经历中的铺面制作页面

About

节奏光剑C9联合战队的首页

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages