新建项目

This commit is contained in:
2026-07-29 10:50:33 +08:00
parent bfd3841cbd
commit 4f69b859a8
49 changed files with 5565 additions and 0 deletions

229
docs/TECHNICAL_DESIGN.md Normal file
View File

@@ -0,0 +1,229 @@
# 技术设计
## 1. 当前原型架构
当前版本采用微信小程序原生 JavaScript不依赖 npm 包和远程服务。
```text
页面层 pages/*
本地游戏服务 services/game-service.js
wx Storage房间、玩家、事件和结果
```
`game-service.js` 将页面与数据源隔离。接入真实后端时,页面调用接口可以尽量保持不变,只需将服务实现替换为网络请求和实时订阅。
## 2. 推荐生产架构
初期建议采用微信云开发,减少登录、部署和运维成本;验证规模后可迁移为自有服务。
```text
微信小程序
├─ HTTPS API创建、加入、抓捕、技能、结算
├─ WebSocket房间状态和事件推送
└─ 定位模块:低频位置上报与边界判断
应用服务
├─ 身份与权限
├─ 房间状态机
├─ 游戏规则引擎
├─ 位置模糊化
├─ 口令与防作弊
└─ 安全事件
数据层
├─ 持久数据库:用户、房间、结果
├─ Redis在线状态、口令、房间实时状态
└─ 短期位置存储:设置自动过期时间
```
## 3. 核心实体
### User
```js
{
id,
openId,
displayName,
avatarUrl,
safetySettings,
createdAt
}
```
### Room
```js
{
id,
code,
hostId,
name,
mode,
status,
settings: {
maxPlayers,
durationMinutes,
prepareMinutes,
clueIntervalMinutes,
seekerCount,
radiusMeters,
skillsEnabled
},
center,
phaseEndsAt,
version,
createdAt
}
```
### Player
```js
{
id,
roomId,
userId,
displayName,
role,
status,
ready,
caughtBy,
caughtAt,
joinedAt,
lastSeenAt
}
```
### GameEvent
```js
{
id,
roomId,
type,
actorId,
targetId,
visibility,
payload,
createdAt
}
```
### LocationPing
```js
{
roomId,
playerId,
latitude,
longitude,
accuracy,
capturedAt,
expiresAt
}
```
生产环境中 `LocationPing` 不应作为永久战绩保存。
## 4. API 草案
- `POST /rooms`:创建房间。
- `GET /rooms/:code`:读取可公开的房间摘要。
- `POST /rooms/:code/join`:加入房间。
- `POST /rooms/:id/ready`:切换准备状态。
- `POST /rooms/:id/start`:房主开始游戏。
- `POST /rooms/:id/location`:上报位置。
- `POST /rooms/:id/skills/:skill`:使用技能。
- `POST /rooms/:id/captures`:提交抓捕凭证。
- `POST /rooms/:id/pause`:暂停游戏。
- `POST /rooms/:id/assemble`:发起全员集合。
- `POST /rooms/:id/finish`:结束游戏。
- `GET /rooms/:id/result`:读取结算结果。
所有改变游戏状态的接口都应:
- 校验用户身份和房间成员关系。
- 校验当前房间状态和角色权限。
- 使用服务端时间。
- 支持幂等键,避免弱网重试造成重复事件。
- 更新房间版本号并广播事件。
## 5. 实时同步
WebSocket 消息建议仅发送必要状态变化:
```js
{
eventId,
roomId,
roomVersion,
type: "PLAYER_CAUGHT",
payload: {},
serverTime
}
```
客户端策略:
1. 进入候场或游戏页后建立连接。
2.`eventId` 去重。
3. 检测版本跳跃时重新拉取房间快照。
4. 退到后台后按微信能力选择保活或恢复时重连。
5. UI 倒计时基于 `phaseEndsAt - serverTimeOffset` 计算。
## 6. 位置和地理围栏
- 客户端获取坐标并附带定位精度和采集时间。
- 服务端校验坐标新鲜度、速度异常和精度阈值。
- 使用服务端保存的场地中心和半径判断越界。
- 向寻找者发送的线索由服务端完成网格化或随机偏移。
- 不将躲藏者原始坐标发送给其他普通玩家。
- 位置记录设置短期 TTL游戏结束后触发删除任务。
线索模糊化可采用:
- H3/Geohash 网格降级。
- 以真实点为中心生成受边界约束的随机圆。
- 仅返回目标与玩家的距离档位,如“很近、附近、较远”。
## 7. 抓捕防作弊
动态口令建议由服务端生成:
```text
token = HMAC(roomSecret, targetPlayerId + timeWindow + nonce)
```
- 口令窗口建议 30 秒。
- 提交时校验寻找者与目标的最近位置距离。
- 校验双方都在线、角色正确且目标尚未被抓。
- 使用事务写入抓捕结果,防止两个寻找者同时抓到同一目标。
- 口令只作为相遇证明之一,不能替代安全规则。
## 8. 安全设计
- 房主开始前必须完成场地和规则确认。
- 服务端保留暂停、集合和取消的高优先级事件通道。
- 客户端进入后台、定位失效、低电量或离线时产生状态提示。
- 精确位置访问纳入服务端审计,不允许普通运营后台随意查看。
- 公开组局上线前必须具备举报、封禁、内容安全和年龄策略。
## 9. 测试策略
- 单元测试:房间状态机、身份分配、倒计时、抓捕和结算。
- 属性测试:不同人数与寻找者数量下角色数量始终合法。
- 集成测试:多人并发加入、重复抓捕、断线重连和版本冲突。
- 真机测试:前后台切换、弱网、定位精度、耗电和不同微信版本。
- 户外测试:边界提醒时机、线索节奏、屏幕使用时间和安全流程。
## 10. 迁移顺序
1. 保留页面与服务接口,先把本地房间读写替换为云函数。
2. 接入微信登录并使每个玩家拥有稳定服务端 ID。
3. 引入实时房间事件和服务端倒计时。
4. 接入地图选区、定位上报和模糊线索。
5. 将抓捕、技能和结算全部迁到服务端裁决。
6. 增加日志、监控、隐私删除和运营安全能力。