Commit a55524f5 authored by 陈冲's avatar 陈冲

feat: 添加项目开发文档

parent 67801653
# FC Minigame 技术归档
归档日期:2026-06-26
适用范围:`frontend-h5``frontend-large``backend`、互动游戏资源与运行流程
文档目的:归档 Vue 前端项目、Rust 后端服务、Socket.IO 互动游戏的完整技术、业务、配置、运维信息,防止项目信息遗忘、资源丢失,为后期页面维护、功能迭代、问题排查、样式兼容优化提供技术依据。
## 1. 项目总览
本项目是一个多端互动小游戏系统,包含:
| 模块 | 目录 | 说明 |
| --- | --- | --- |
| H5 玩家端 | `frontend-h5` | 手机端游戏入口,负责玩家登录参数读取、入房、游玩、提交分数、展示个人结果 |
| 大屏/管理端 | `frontend-large` | 大屏展示与管理员控制端,负责登录、创建房间、开始游戏、排行榜展示、关闭房间 |
| 后端服务 | `backend` | Rust 服务,提供 HTTP 管理接口、Socket.IO 实时通信、房间状态、排行榜、数据库落库 |
| 素材资源 | `frontend-h5/src/assets/images``frontend-large/src/assets/images` | 各游戏背景、动画帧、音频、二维码、排行榜装饰图等 |
整体交互模型:
1. 管理端登录后建立 Socket.IO 管理员连接。
2. 管理员选择游戏并创建房间。
3. 玩家从 H5 链接携带身份参数进入对应游戏页,建立 Socket.IO 玩家连接并加入当前房间。
4. 管理端开始游戏,后端广播开始事件。
5. 玩家端本地运行游戏逻辑并持续/最终提交分数。
6. 后端维护内存房间状态和排行榜,结束后写入数据库。
7. 管理端与玩家端展示排行或结算结果。
## 2. 技术栈
### 2.1 前端公共技术
| 类型 | 技术 |
| --- | --- |
| 框架 | Vue 3 |
| 构建工具 | Vite |
| 语言 | TypeScript、Vue SFC |
| 路由 | vue-router,Hash 模式 |
| 实时通信 | socket.io-client |
| 二进制协议 | `@msgpack/msgpack` |
| 加密 | crypto-js |
| 调试 | H5 使用 vConsole,大屏端使用浏览器控制台 |
| 包管理 | 仓库同时存在 `package-lock.json``pnpm-lock.yaml`,现有脚本以 npm 命令为主 |
### 2.2 后端技术
| 类型 | 技术 |
| --- | --- |
| 语言 | Rust 2024 edition |
| HTTP 框架 | Salvo |
| 实时通信 | socketioxide |
| 异步运行时 | Tokio |
| 数据库 | sqlx,支持 PostgreSQL 与 MySQL |
| 序列化 | serde、serde_json、rmp-serde |
| 静态资源嵌入 | rust-embed,debug 模式挂载 `backend/src/web` |
| 跨域 | tower-http `CorsLayer::permissive()` |
## 3. 目录结构
```text
fc_minigame/
backend/
Cargo.toml
config.json
deploy/
game.sql
game_mysql.sql
src/
main.rs
router.rs
commons/
db/
protocols/
web/
frontend-h5/
package.json
vite.config.ts
src/
router/
commons/
composables/
pages/game1..game6/
assets/images/
frontend-large/
package.json
vite.config.ts
src/
router/
commons/
composables/
pages/game1..game6/
assets/images/
docs/
TECHNICAL_ARCHIVE.md
```
说明:
- `node_modules``backend/target` 是本地构建产物或依赖目录,不应作为业务维护入口。
- 两套前端代码结构高度相似,但面向角色不同:H5 是玩家端,大屏端是管理员/展示端。
- `backend/src/web` 是后端 debug 模式下可挂载的测试页面和第三方前端库,不是主业务前端。
## 4. 前端归档
### 4.1 H5 玩家端 `frontend-h5`
入口:
- `src/main.ts`:Vue 应用入口。
- `src/App.vue`:根组件。
- `src/router/index.ts`:路由配置。
路由:
| 路径 | 页面 | 说明 |
| --- | --- | --- |
| `/loading` | `pages/Loading.vue` | 加载页 |
| `/game1` | `pages/game1/Game.vue` | 游戏 1 |
| `/game2` | `pages/game2/Game.vue` | 游戏 2 |
| `/game3` | `pages/game3/Game3.vue` | 游戏 3 |
| `/game4` | `pages/game4/Game4.vue` | 游戏 4 |
| `/game5` | `pages/game5/Game5.vue` | 游戏 5 |
| `/game6` | `pages/game6/Game.vue` | 游戏 6 |
关键公共模块:
| 文件 | 作用 |
| --- | --- |
| `src/commons/ws.ts` | Socket.IO 初始化、MsgPack 编解码、消息发送与订阅 |
| `src/composables/useGameSocket.ts` | 玩家端房间协议封装:入房、开始、恢复、排名、提交分数 |
| `src/commons/utils.ts` | localStorage、URL 参数、Toast、Confirm、微信/用户参数读取、外部分数上报 |
| `src/commons/assets.ts` | 图片/音频资源 URL 生成,支持本地资源和 OSS/CDN 资源 |
| `src/commons/music.ts` | 音频播放相关工具 |
| `src/commons/debug.ts` | 调试相关工具 |
H5 用户参数:
玩家端通过 URL Query 读取:
| 参数 | 用途 |
| --- | --- |
| `token` | 原始授权 token,用于后续外部接口上报 |
| `nickname` | 玩家昵称 |
| `avatar` | 玩家头像 |
| `userno` | 玩家唯一标识,代码中会作为 Socket 鉴权 `userid` |
当处于 debug 模式时,H5 会生成模拟玩家信息,便于本地调试。
### 4.2 大屏/管理端 `frontend-large`
入口:
- `src/main.ts`:Vue 应用入口。
- `src/App.vue`:根组件。
- `src/router/index.ts`:路由配置。
路由:
| 路径 | 页面 | 权限 |
| --- | --- | --- |
| `/` | 重定向 | 有 token 到 `/main`,否则到 `/login` |
| `/login` | `pages/Login.vue` | 无需登录 |
| `/main` | `pages/Main.vue` | 需要管理员 token |
| `/game1``/game6` | 对应大屏游戏页 | 需要管理员 token |
关键公共模块:
| 文件 | 作用 |
| --- | --- |
| `src/composables/useAdminGameSocket.ts` | 管理端 Socket 协议封装:房间状态、建房、回退、开始、关房、排行榜 |
| `src/commons/ws.ts` | Socket.IO 初始化、MsgPack 编解码、连接复用与关闭 |
| `src/commons/utils.ts` | localStorage、登录态、通知、Toast、Confirm、运行模式工具 |
| `src/commons/assets.ts` | 素材 URL 统一生成 |
| `src/commons/player.ts` | 玩家展示相关逻辑 |
| `src/components/DesignStage.vue` | 大屏适配容器 |
管理员登录态字段存储在 localStorage:
| 字段 | 来源 | 说明 |
| --- | --- | --- |
| `token` | `/manager/login` | 管理员 token |
| `passphrase` | `/manager/login` | AES 加密短语,用于 Socket 鉴权 |
| `socket_path` | `/manager/login` | Socket.IO path |
| `client_ns` | `/manager/login` | Socket.IO namespace |
| `domain` | 前端逻辑写入 | 连接域名,开发时可为空或本地域名 |
### 4.3 前端资源策略
两套前端都使用 `src/commons/assets.ts` 生成资源 URL。
资源路径规则:
| 场景 | 行为 |
| --- | --- |
| 开发环境 | 默认读取 `/src/assets/images/...` |
| 生产环境且配置 `VITE_ASSET_BASE_URL` | 读取 OSS/CDN 资源 |
| 生产环境未配置 OSS/CDN | 读取构建产物中的 `/assets/images/...` |
| `VITE_ASSET_BUILD_LOCAL=true` | 强制把 `src/assets/images` 复制到 `dist/assets/images` |
相关环境变量:
| 变量 | 说明 |
| --- | --- |
| `VITE_ASSET_BASE_URL` | 生产静态资源基础路径 |
| `VITE_ASSET_DEV_LOCAL` | 开发环境是否优先本地资源,`false` 时可直接测试 OSS/CDN |
| `VITE_ASSET_BUILD_LOCAL` | 是否构建本地资源包 |
当前已见配置:
- H5 生产资源前缀:`https://xjfcoss.guocai365.org.cn/games/h5/assets/images/`
- 大屏生产资源前缀:`https://xjfcoss.guocai365.org.cn/games/pc/assets/images/`
注意:
- 修改素材文件后,如走 OSS/CDN,需要同步上传远程资源。
- 如走本地资源构建,需要使用 `build:local` 或设置 `VITE_ASSET_BUILD_LOCAL=true`
- 音频文件也放在 `assets/images` 下,资源工具同样适用。
## 5. 前端构建与运行
### 5.1 H5
```bash
cd frontend-h5
npm install
npm run dev
npm run build:oss
npm run build:local
npm run preview
```
脚本说明:
| 脚本 | 说明 |
| --- | --- |
| `dev` | 启动 Vite 开发服务 |
| `build:oss` | 类型检查后按 production 模式构建,优先使用 OSS/CDN 资源 |
| `build:local` | 类型检查后按 local-assets 模式构建,并打包本地素材 |
| `preview` | 预览生产构建 |
| `serve:local` | H5 特有,`vite preview --host 0.0.0.0` |
| `type-check` | `vue-tsc --build` |
H5 Vite 配置要点:
- 开发代理 `/socket.io``/manager``http://localhost:8082`
- 使用 `@vitejs/plugin-basic-ssl`,开发服务可支持 HTTPS。
- build 时 `base``/h5/`
- build 时注入 `__APP_DOMAIN__ = https://hddp.guocai365.org.cn`
- serve 时注入 `__DEBUG__ = true`
### 5.2 大屏/管理端
```bash
cd frontend-large
npm install
npm run dev
npm run build:oss
npm run build:local
npm run preview
```
大屏 Vite 配置要点:
- 开发代理 `/socket.io``/manager``http://localhost:8082`
- build 时当前 `base``/`
- build 时注入 `__APP_DOMAIN__ = https://hddp.guocai365.org.cn`
- 支持 OSS/CDN 或本地素材两种构建方式。
### 5.3 Node 版本要求
两个前端项目 `package.json` 中均要求:
```text
node ^20.19.0 || >=22.12.0
```
建议归档锁定:
- Node:20.19+ 或 22.12+
- npm:随 Node 安装版本即可
- TypeScript:项目依赖约束为 `~6.0.0`
## 6. 后端归档
### 6.1 后端入口
| 文件 | 作用 |
| --- | --- |
| `src/main.rs` | 初始化数据库、配置路由、启动 Salvo HTTP 服务 |
| `src/router.rs` | HTTP 路由、Socket.IO layer、404/405 处理 |
| `src/protocols/socket_io.rs` | 核心业务协议、房间状态机、管理员/玩家 Socket 消息处理 |
| `src/commons/config.rs` | `config.json` 配置加载 |
| `src/commons/utils.rs` | AES 加解密、时间工具、全局配置 |
| `src/db/mod.rs` | 数据库驱动选择与统一查询入口 |
| `src/db/pg.rs` | PostgreSQL 驱动 |
| `src/db/mysql.rs` | MySQL 驱动 |
| `src/db/models/*` | 房间、游戏成绩、日志、管理员模型 |
### 6.2 后端启动
```bash
cd backend
cargo run
```
发布构建:
```bash
cd backend
cargo build --release
```
Linux musl 目标构建备注:
```bash
cargo zigbuild --release --target x86_64-unknown-linux-musl
```
`Cargo.toml` 中二进制名:
```text
hddpServer
```
### 6.3 后端配置
后端启动时读取 `backend/config.json`。如果文件不存在,会生成默认配置并 panic,提示配置后再运行。
配置字段:
| 字段 | 说明 |
| --- | --- |
| `host` | 服务监听地址,例如 `0.0.0.0:8082` |
| `client_ns` | Socket.IO namespace,默认 `/ws` |
| `socket_path` | Socket.IO path,默认 `/socket.io` |
| `aes_passphrase` | 管理员 Socket 鉴权用 AES 短语, ***发生泄漏时请更改配置及管理员登录密码token等信息*** |
| `db.kind` | 数据库类型,支持 `postgresql``mysql` |
| `db.uri` | 数据库连接串 |
### 6.4 HTTP 接口
| 方法 | 路径 | 说明 |
| --- | --- | --- |
| POST | `/manager/login` | 管理员登录,返回 token、passphrase、socket_path、client_ns |
| POST | `/manager/getConn` | 获取 Socket 连接配置 |
| POST | `/manager/getTop10Rank` | 根据 `batch_no` 查询历史前十排行榜 |
| GET | `/socket.io` | Socket.IO path,由 socketioxide layer 接管 |
| GET | `/web/{path}` | debug 模式挂载 `backend/src/web` 静态测试页 |
统一响应形态:
```json
{
"state": 1,
"msg": "",
"data": {}
}
```
失败响应:
```json
{
"state": 0,
"msg": "错误信息",
"data": null
}
```
### 6.5 数据库
初始化 SQL:
- PostgreSQL:`backend/deploy/game.sql`
- MySQL:`backend/deploy/game_mysql.sql`
数据表:
| 表 | 说明 |
| --- | --- |
| `tb_room` | 游戏房间批次记录 |
| `tb_game` | 玩家游戏成绩记录 |
| `tb_log` | 后端错误日志 |
| `tb_manager` | 管理员账号与 token |
`tb_room` 关键字段:
| 字段 | 说明 |
| --- | --- |
| `batch_no` | 批次号,主键 |
| `item_num` | 游戏编号,1 到 6 |
| `player_count` | 房间人数 |
| `create_date` | 创建时间 |
`tb_game` 关键字段:
| 字段 | 说明 |
| --- | --- |
| `wechat_id` | 玩家原始身份 token 或微信标识 |
| `nickname` | 昵称 |
| `avatar` | 头像 |
| `game_rank` | 排名 |
| `item_num` | 游戏编号 |
| `score` | 分数 |
| `create_date` | 创建时间 |
| `batch_no` | 所属房间批次 |
默认管理员初始化 SQL:
```sql
INSERT INTO tb_manager(username, password/token字段, token)
VALUES ('admin', '123456', '88236aeb-8d3f-6d56-fdf5-3adca3961dfb');
```
注意:PostgreSQL 与 MySQL 对 `password` 字段转义方式不同,以各自 SQL 文件为准。
## 7. Socket.IO 互动协议
### 7.1 连接参数
Socket.IO 统一配置:
| 参数 | 值 |
| --- | --- |
| path | `/socket.io` |
| namespace | `/ws` |
| transports | `['websocket']` |
| upgrade | `false` |
| timeout | `10000` ms |
| payload 编码 | MsgPack |
前端发送消息:
```ts
socket.send(encode({ cmd, data }))
```
后端响应事件:
```json
{
"state": 1,
"msg": "",
"data": {}
}
```
所有后端业务响应都通过 MsgPack 编码后按事件名 emit。
### 7.2 管理员 Socket 鉴权
管理员连接 `auth`
| 字段 | 说明 |
| --- | --- |
| `userid` | 管理员 token |
| `validuser` | `CryptoJS.AES.encrypt(token, passphrase).toString()` |
后端校验:
1. 解密 `validuser`
2. 解密结果必须等于 `userid`
3. 使用 token 查询 `tb_manager`
4. 同一时间只允许一个管理员在线;新管理员登录会顶掉旧管理员。
### 7.3 玩家 Socket 鉴权
玩家连接 `auth`
| 字段 | 说明 |
| --- | --- |
| `userid` | 玩家唯一标识,H5 中来自 `userno` |
玩家不使用 `validuser` 字段。若没有管理员在线,后端允许连接记录但返回 `connect_result` 失败,提示房间未开启。
### 7.4 管理端命令
| cmd | data | 说明 | 主要响应事件 |
| --- | --- | --- | --- |
| `room_state` | `{}` | 获取当前房间状态 | `room_state_result` |
| `room_create` | 游戏序号数字,如 `1` | 创建游戏房间,进入 Loading 状态 | `room_create_result` |
| `room_back` | 游戏序号数字 | 回到指定游戏 Loading 状态 | `room_back_result` |
| `game_start` | 游戏 ID 字符串,如 `game1` | 开始当前游戏 | `game_start_result` |
| `room_rank` | `{}` | 获取当前排行榜 | `room_rank_result` |
| `room_close` | `{}` | 关闭房间,断开玩家连接 | `room_close_result` |
### 7.5 玩家端命令
| cmd | data | 说明 | 主要响应事件 |
| --- | --- | --- | --- |
| `room_join` | `{ nickname, token, avatar, gameId }` | 玩家加入房间 | `room_join_result``room_recover_result``room_rank_result` |
| `submit_score` | `{ score }` | 游戏中提交/刷新分数 | `submit_score_result` |
| `submit_score_save` | `{ item_num, wechat, nickname, avatar, rank, score }` | 结算后保存成绩到数据库 | `submit_score_save_result` |
### 7.6 后端主动事件
| event | 接收端 | 说明 |
| --- | --- | --- |
| `connect_result` | 玩家端 | 连接失败或无管理员时提示 |
| `login_result` | 管理端 | token 失效或管理员登录异常 |
| `new_admin_result` | 管理端 | 被其他管理员登录顶下线 |
| `room_join_result` | 管理端、玩家端 | 玩家入房或房间人数/列表变化 |
| `room_recover_result` | 玩家端 | 玩家断线重连后恢复游戏状态 |
| `game_start_result` | 管理端、玩家端 | 游戏开始 |
| `submit_score_result` | 玩家端 | 当前玩家分数/名次结果 |
| `submit_score_save_result` | 玩家端 | 成绩保存结果和最终排行榜 |
| `room_rank_result` | 管理端、玩家端 | 排行榜 |
| `room_close_result` | 管理端、玩家端 | 房间关闭 |
| `player_offline_result` | 管理端 | 玩家离线通知,当前代码中部分广播逻辑保留但未启用 |
## 8. 房间状态与游戏流程
### 8.1 房间状态
后端内存状态 `RoomStatus`
| 状态 | 数值 | 说明 |
| --- | --- | --- |
| `Closed` | 0 | 房间关闭 |
| `Loading` | 1 | 已创建房间,等待玩家加入 |
| `Running` | 2 | 游戏进行中 |
| `Submit` | 3 | 分数提交/结果等待阶段 |
| `Ended` | 4 | 游戏结束 |
### 8.2 时间控制
后端常量:
| 常量 | 值 | 说明 |
| --- | --- | --- |
| `ROOM_ENTRY_LIMIT` | 20 | 等待阶段最多展示前 20 个入房玩家 |
| `ROOM_SCORE_RANK_LIMIT` | 10 | 结算排行榜前 10 |
| `GAME_START_COUNTDOWN_SECS` | 3 | 开始倒计时 |
| `GAME_RESULT_WAIT_SECS` | 2 | 结果等待时间 |
| `GAME_RUNNING_SECS` | 60 | 游戏运行时间 |
| `ADMIN_ABSENT_DEACTIVATE_PLAYER_SECS` | 300 | 管理员离线后玩家连接失效等待 |
### 8.3 排行规则
后端规则:
- 分数越高排名越靠前。
- 分数相同时按玩家标识排序。
- 只取前 10 名作为最终榜单展示。
- 已进入历史前十的玩家,本轮不再进入可领奖前十展示。
- `submit_score_save` 落库时使用后端内存中的分数与排名为准,避免客户端篡改最终排名。
### 8.4 房间生命周期
```text
Closed
-> 管理员 room_create
Loading
-> 玩家 room_join
-> 管理员 game_start
Running
-> 玩家 submit_score
-> 后端 60 秒倒计时
Submit
-> 玩家 submit_score_save
-> 后端推送排行榜
Ended
-> 管理员 room_close 或重新创建房间
Closed
```
## 9. 游戏清单
代码中存在 6 个游戏,H5 和大屏均有对应页面。
| 编号 | ID | H5 页面 | 大屏页面 | 备注 |
| --- | --- | --- | --- | --- |
| 1 | `game1` | `frontend-h5/src/pages/game1/Game.vue` | `frontend-large/src/pages/game1/Game.vue` | 素材目录 `game1` |
| 2 | `game2` | `frontend-h5/src/pages/game2/Game.vue` | `frontend-large/src/pages/game2/Game.vue` | 素材目录 `game2` |
| 3 | `game3` | `frontend-h5/src/pages/game3/Game3.vue` | `frontend-large/src/pages/game3/Game3.vue` | 素材目录 `game3` |
| 4 | `game4` | `frontend-h5/src/pages/game4/Game4.vue` | `frontend-large/src/pages/game4/Game4.vue` | 素材目录 `game4` |
| 5 | `game5` | `frontend-h5/src/pages/game5/Game5.vue` | `frontend-large/src/pages/game5/Game5.vue` | 素材目录 `game5` |
| 6 | `game6` | `frontend-h5/src/pages/game6/Game.vue` | `frontend-large/src/pages/game6/Game.vue` | 素材目录 `game6` |
后端历史注释中的游戏中文名映射:
| ID | 名称 |
| --- | --- |
| `game1` | 击鼓齐福 |
| `game2` | 聚宝接福 |
| `game3` | 马上有福 |
| `game4` | 策马迎福 |
| `game5` | 圈彩纳福 |
| `game6` | 福运当头 |
外部分数上报中曾出现的游戏代码:
| 游戏 | code |
| --- | --- |
| 击鼓齐福 | `JGQF` |
| 聚宝接福 | `JBJF` |
| 马上有福 | `MSYF` |
| 策马迎福 | `CMYF` |
| 圈彩纳福 | `QCNF` |
| 福运当头 | `FYDT` |
H5 成绩保存成功后,若存在原始 token,会调用外部接口:
```text
POST https://api.guocai365.org.cn/api/offline_clearance/user/screen_game_score
Authorization: 玩家原始 token
Content-Type: application/json
```
请求体字段:
| 字段 | 说明 |
| --- | --- |
| `game_code` | 游戏代码 |
| `score` | 分数 |
| `batch_no` | 当前批次号 |
| `rank_no` | 排名 |
## 10. 部署与运维
### 10.1 推荐部署顺序
1. 准备数据库,执行对应 SQL。
2. 准备 `backend/config.json`,确认 `host``client_ns``socket_path``aes_passphrase`、数据库连接。
3. 构建并启动后端,确认 `http://host:port` 可访问。
4. 构建 H5 前端。
5. 构建大屏/管理端。
6. 上传或同步 `assets/images` 素材到 OSS/CDN,或使用本地资源构建。
7. 配置 Nginx/网关:
- H5 静态目录。
- 大屏静态目录。
- `/manager/*` 反向代理到后端。
- `/socket.io` 反向代理到后端并支持 WebSocket Upgrade。
8. 用管理端登录创建房间。
9. 用 H5 测试链接进入房间,验证入房、开始、提交分数、排行榜、落库。
### 10.2 Nginx 代理要点
必须保证:
- `/socket.io` 代理到后端 `host`
- 代理支持 WebSocket。
- `client_ns` 保持 `/ws`
- H5 构建 `base` 当前为 `/h5/`,部署路径应匹配。
- 大屏构建 `base` 当前为 `/`,如部署到子路径需要同步调整 Vite `base` 与路由资源路径。
WebSocket 代理关键头:
```nginx
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
```
### 10.3 上线检查清单
| 检查项 | 说明 |
| --- | --- |
| 后端端口 | `config.json.host` 与网关代理一致 |
| Socket path | 前端、后端、Nginx 均为 `/socket.io` |
| namespace | 前端、后端均为 `/ws` |
| AES 短语 | 后端 `aes_passphrase` 与登录返回一致 |
| 数据库 | `tb_manager` 有管理员账号,`tb_game` 可写入 |
| 素材 | OSS/CDN 路径或本地 `dist/assets/images` 可访问 |
| H5 URL 参数 | `token``nickname``avatar``userno` 完整 |
| 排行榜 | 管理端和玩家端均能收到 `room_rank_result` |
| 外部接口 | H5 可访问 `api.guocai365.org.cn` 成绩上报接口 |
## 11. 排障指南
### 11.1 管理端登录失败
检查:
- `/manager/login` 是否 200。
- `tb_manager` 是否存在对应账号。
- 后端 `config.json` 是否配置数据库。
- `aes_passphrase` 是否为空;为空时登录接口会失败。
- 浏览器 localStorage 中旧 token 是否需要清理。
### 11.2 Socket 连接失败
检查:
- 浏览器 Network 中 `/socket.io` 是否 101 或 WebSocket 连接成功。
- Vite 开发代理是否指向 `http://localhost:8082`
- 生产 Nginx 是否支持 WebSocket Upgrade。
- 前端 `socket_path` 与后端 `config.socket_path` 是否一致。
- 前端 `client_ns` 与后端 `config.client_ns` 是否一致。
### 11.3 玩家提示房间未开启
可能原因:
- 管理端未登录或管理员 Socket 已断开。
- 管理端未创建房间。
- H5 进入的 `gameId` 与当前房间 `current_game_id` 不一致。
- 管理员离线超过保护时间,后端已将玩家连接标记失效。
### 11.4 排行榜不更新
检查:
- 玩家是否成功发送 `submit_score`
- 后端房间状态是否为 `Running``Submit`
- 管理端是否订阅 `room_rank_result`
- 玩家是否已经进入历史前十,导致本轮不再进入可领奖榜单。
- 分数相同时排序会按玩家标识兜底,可能看起来顺序固定。
### 11.5 成绩未落库
检查:
- H5 是否发送 `submit_score_save`
- 后端数据库连接是否正常。
- `tb_game` 表结构是否已初始化。
- `submit_score_save` 必需字段是否完整:`item_num``wechat``nickname``avatar``rank``score`
- 后端会用内存中的 server_score/server_rank 覆盖客户端上报结果,排查时应看后端状态而不是只看前端 payload。
- 如插入失败,后端会尝试写 `tb_log`
### 11.6 素材加载失败
检查:
- 当前构建是 `build:oss` 还是 `build:local`
- `VITE_ASSET_BASE_URL` 是否指向正确目录。
- OSS/CDN 是否存在对应文件。
- 文件大小写是否一致,Windows 本地不敏感,Linux/OSS 通常敏感。
- H5 的 build base 是 `/h5/`,资源相对路径需匹配部署路径。
### 11.7 中文显示乱码
源码中部分历史中文注释或字符串显示为乱码,可能是历史编码保存问题。维护时建议:
- 不要批量自动转码整个仓库,避免引入大规模 diff。
- 只在需要改动的文件中逐段确认编码和运行表现。
- 用户可见文案优先通过浏览器实际页面确认,不只看源码显示。
## 12. 后续维护建议
### 12.1 新增游戏
需要同步修改:
1. H5 新增 `src/pages/gameN`
2. 大屏新增 `src/pages/gameN`
3. 两端路由新增 `/gameN`
4. 两端素材目录新增 `assets/images/gameN`
5. 后端允许 `item_num` 范围或 SQL check 约束扩展。
6. 后端游戏名映射扩展。
7. 外部分数上报 code 映射扩展。
8. 管理端主页面游戏入口扩展。
9. OSS/CDN 上传新增素材。
### 12.2 修改游戏时长
后端统一控制:
- `GAME_RUNNING_SECS`
- `GAME_START_COUNTDOWN_SECS`
- `GAME_RESULT_WAIT_SECS`
前端如果有本地倒计时、动画节奏或结算弹窗,也必须同步调整,否则会出现前后端状态不一致。
### 12.3 修改排行榜规则
重点文件:
- `backend/src/protocols/socket_io.rs`
- `frontend-h5/src/composables/useGameSocket.ts`
- `frontend-large/src/composables/useAdminGameSocket.ts`
需要确认:
- 前 10 名限制。
- 已上榜玩家是否可重复上榜。
- 同分排序规则。
- 玩家个人排名和大屏展示排名是否一致。
- `tb_game.game_rank` 落库规则是否同步。
### 12.4 修改部署路径
需要同步:
- H5 `vite.config.ts``base`
- 大屏 `vite.config.ts``base`
- Nginx 静态路径。
- OSS/CDN `VITE_ASSET_BASE_URL`
- H5 分享/入口链接。
- 大屏登录和管理入口。
## 13. 重要风险记录
| 风险 | 说明 | 建议 |
| --- | --- | --- |
| 配置含敏感信息 | `backend/config.json` 可能包含数据库账号和 AES 短语 | 生产配置单独托管,不公开 |
| 内存房间状态 | 房间状态在后端进程内存中,服务重启会丢失当前房间 | 活动前避免重启,必要时设计持久化 |
| 单管理员限制 | 后端只允许一个管理员在线 | 多人运维时约定唯一控制端 |
| 素材体积大 | 游戏动画帧、音频较多 | 上线前确认 CDN 缓存、首屏加载和移动端流量 |
| 锁文件并存 | npm 与 pnpm 锁文件同时存在 | 后续维护固定一种包管理器,避免依赖漂移 |
| 编码历史问题 | 部分中文注释/文案显示乱码 | 小范围修复,避免批量误伤 |
## 14. 归档结论
本项目核心是“管理端控制房间 + H5 玩家互动 + Rust 后端实时排行与落库”的活动型小游戏系统。后续维护最重要的边界是:
- 页面样式与游戏交互在两套 Vue 前端中维护。
- 房间状态、排行、管理员唯一在线、成绩落库在后端维护。
- 前后端实时协议统一使用 Socket.IO + MsgPack。
- 素材资源由 `assetUrl/cssAssetUrl` 统一管理,可走 OSS/CDN 或本地打包。
- 生产配置、数据库和 OSS/CDN 路径是运维交接重点,需单独安全保管。
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment