# React 控制台与 OBS 前端 Vite 在 Docker build stage 编译本目录,最终静态文件由 Rust 同域托管。生产容器不包含 Node。 ## 路由 | 路由 | 权限 | 作用 | | --------------------------------------- | --------------- | ------------------------------------ | | `/control/` | 登录用户 | 直播源、组件、测试、设置和 OBS token | | `/control/invitations` | system admin | 创建/撤销绑定房间的邀请码 | | `/control/components/:id/song-requests` | 登录用户 | 点歌队列、统计与管理操作 | | `/control/login` | 匿名 | 用户名 + TOTP/恢复码登录 | | `/control/register` | 匿名受邀用户 | 邀请码注册与 TOTP enrollment | | `/control/setup` | 首次部署 | 创建唯一 system admin | | `/obs/:publicId` | component token | 透明 OBS 浏览器源 | `main.tsx` 在初始化控制台前先识别 OBS 路由,因此 OBS 不会注册 PWA 或请求账户 session。 ## 文件职责 | 文件 | 职责 | | ----------------------- | ---------------------------------------------------- | | `src/api.ts` | same-origin fetch、错误模型和兼容性 normalizer | | `src/auth.tsx` | passwordless login、TOTP QR 与恢复码 | | `src/control.tsx` | tenant component studio 和 system-admin 邀请码页面 | | `src/stream.ts` | 通用组件 WebSocket 鉴权、重连和 renderer 分流 | | `src/overlay.tsx` | 弹幕、礼物/表情和 OBS 自适应渲染 | | `src/songOverlay.tsx` | 点歌快照 reducer、revision 校验与往返滚动 | | `src/giftEffect.tsx` | 礼物流星、大航海全屏庆祝与视口自适应渲染 | | `src/giftThemes.ts` | 可扩展礼物特效主题注册表与 CSS 变量 | | `src/giftMenu.tsx` | 礼物菜单无限循环、触发定位与高亮 reducer | | `src/giftMenuThemes.ts` | 可扩展礼物菜单主题注册表 | | `src/pwa.tsx` | install prompt、离线状态、显式更新和敏感状态 blocker | | `src/i18n.tsx` | TOML 语言资源、浏览器回退和运行时切换 | | `src/types.ts` | sanitized API view model 与 overlay settings | | `pwa/control-sw.js` | `/control/` 静态壳层的缓存策略 | ## Secret 与状态 - TOTP Secret、恢复码、邀请码和新 OBS 地址只保存在当前 React state。 - API normalizer 不把未知对象直接传播到组件。 - API mutation 离线时立即失败,不进入 Background Sync。 - PWA 更新在 dirty form 或一次性 secret 可见时被阻止。 - OBS token 从 URL fragment 读取,只在 WebSocket 第一帧发送。 - OBS 收到坏 JSON、坏图片或未知事件时局部降级,不让浏览器源崩溃。 ## PWA manifest、start URL 与 Service Worker scope 均为 `/control/`。worker 使用 network-first HTML 和 cache-first build assets;`/api/*`、`/obs/*`、WebSocket 和用户数据永不缓存。每次 Vite build 把同一个 build ID 注入浏览器 bundle 与 worker,发现更新后等待用户确认激活。 ## 语言资源 `../../resources/i18n.toml` 是控制台、OBS 组件、API 错误和 PWA metadata 的唯一文案来源。Vite 在构建时解析并注入它,Rust 则嵌入同一文件来验证允许保存的 locale。增加文案键时必须为每个 locale 提供值;增加语言时同时增加完整 `[locales."".messages]` 段。业务命令如“点歌”是 Bilibili 输入协议,不属于 UI 翻译。 ## 字体资源 Noto Serif SC、ZCOOL XiaoWei 与 LXGW WenKai 由锁定的 Fontsource 依赖提供;漓雨手书则以固定版本的 WOFF2 文件保存在 `public/fonts/`。浏览器从 Rust 静态服务同域加载这些字体,不依赖 OBS 设备的系统字体。每套字体的 OFL-1.1 许可证均输出到 `/fonts/licenses/`。 ## 格式化与构建 ```bash npm run format npm run format:check npm run docs:check npm run build ``` `npm run format` 使用仓库根目录的 Prettier 配置,同时格式化 TypeScript、TSX、CSS、HTML、JSON、Markdown、Compose YAML 和项目文档。 组件协议与弹幕姬行为分别见: - [实时协议](../../docs/protocol.md) - [弹幕姬组件](../../docs/components/danmaku-overlay.md) - [点歌姬组件](../../docs/components/song-request.md) - [全屏礼物特效](../../docs/components/gift-effect.md) - [礼物菜单组件](../../docs/components/gift-menu.md)