Files
huajishe-tts/docs/texas/11-implementation-plan.md
e2hang 04d0af515c feat: 登录系统落地 + 踢人修正 + 单房间约束 + 权限收口
问题8 登录系统:
- node:sqlite 账号存储(scrypt 哈希 + HMAC 签名 token),preset admin 改为 e2hang/evan1115
- /api/auth/register|login|me,me 返回 room 供重联
- 网关拦截 create/join 需登录(401),列表保持开放

踢人逻辑修正(问题2 延伸):
- kickMove 真正释放座位(folded=false, name=null)而非锁死
- war/mill 去掉永久封禁语义

管理员越权:管理员 token 可删任意房间、踢任意房间内的人

单房间约束(用户新需求):
- 同一用户同时只能在一个房间,create/join 他房返回 409
- 踢人后若房间仅剩踢人者则自动解散并释放其记录(修复 2 人局踢光对手后被困 409)
- 陈旧房间记录兜底清理

UI 清理:移除"改名"按钮与"你的名字"输入框;删除房间按钮仅房主/管理员可见

docs: 新增 12-auth-kick-single-room.md 汇总本会话全部需求/根因/修复/边界测试

Co-Authored-By: Claude (CodeBuddy) <noreply@codebuddy.ai>
2026-08-25 14:13:59 +08:00

49 lines
5.1 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 11 - 实施计划(依次修改)
> 按用户要求“依次计入 docs/texas 用 md然后制定计划依次修改”。本文件为执行顺序与每步交付物。
> 所有改动以**不破坏现有单测/类型检查**为前提,每步附最小验证。
## 阶段 0基础设施server 房间管理 + 登录后端)
> 影响全局,先做。对应问题 2、问题 8 后端。
- [x] **2.1 房间内存在线表 + 心跳路由** (`packages/server/src/rooms.ts` 已实现:`presence` Map + `POST /api/rooms/:id/heartbeat` + 10min 自动关房 sweep)。
- [x] **2.2 删除房间路由** `POST /api/rooms/:id/delete`(仅房主),`db.wipe` + 清 presence。
- [x] **2.3 踢人路由** `POST /api/rooms/:id/kick`仅房主body `{target}`):清 metadata + 调游戏内 `kick` moveengine 层已单测验证 seated=false
- [x] **2.4 固化房主** engine `host()` 改读 `G.hostId`setup 写入 `'0'`)。
- [x] **8 后端** `/api/auth/register|login|me``packages/server/src/auth-db.ts` + `auth.ts`node:sqlite 持久化scrypt 哈希 + 随机盐HMAC-sha256 签名 token预设 admin 账号从 env/常量 seed`index.ts` 网关拦截"创建/加入房间"未带 token 的请求返回 401列表/查询接口保持开放。
## 阶段 1通用 UI 接房间管理 + 登录前端
- [x] **2.5 客户端** `LobbyRoomList`:房主显示“删除房间”“踢人”按钮;挂载后定时 `heartbeat`3min房间被删 → `onRoomGone` 清状态 + 提示。lobby-client 已加 `roomsInit/heartbeat/delete/kick`
- [x] **8 前端** `App.tsx``LoginBar`(登录/注册切换错误回显token 存 `localStorage``tts-like.token`/`tts-like.username`);进房时把 token 注入 `createMatch`/`joinMatch``Authorization` 头;登录名作默认 `playerName`(可手动改昵称,改后不再被登录名覆盖);未登录时列表区提示"创建/加入房间需先登录"。`lobby-client` 已加 `register/login/me` 方法。
- [x] **单房间约束(用户新需求)** `rooms.ts` 新增中间件mountApiPrefix 之前注册):拦截 `create`/`join`/`leave`,同一登录用户同时只能在一个房间——已在别房则 `create`/`join` 返回 **409**(中文提示先离开);`create`/`join` 成功登记 `userRoom`/`roomPlayers``leave`/`kick`/`delete` 成功清除对应记录。`/api/auth/me` 现返回 `room`,供客户端重联时权威确认所在房间;客户端 `config``localStorage` 持久化,刷新即自动重连原房间。`LobbyRoomList``errMsg` 把 409 文案友好展示。
## 阶段 2改名刷新问题 1
- [x] **1.1 engine** 新增 `renameMove`(沿用 `playerID` 信任模型),注册 `rename` move。
- [x] **1.2 ui** `HoldemBoard` 加 effect`playerName` 变化且已入座 → `onMove('rename', [playerName])`
- [x] 验证:改名后牌桌两处同步刷新(座位名 + 结果区)。
## 阶段 3游戏循环问题 3、4、5
- [x] **3.1 engine 通用** 各游戏加 `kick` move`seated`Holdem 加 `rebuy` / `leaveRoom` / `resetRoom`房主moves单测覆盖
- [x] **3.2 ui** Holdem筹码≤0 显示“补码/退出”;房主 `waiting` 显示“重置房间”War/Mill 加“再来一局”rematch move
- [x] **4.1 engine 修 `roundComplete`** `list.length===1` 分支加 `acted` 判定(单测回归)。
- [x] **4.2 engine 加固 `buildPots`** 空层结转 orphanCarry 并入下一层,避免退错人(归属权)。
- [x] **4.3 单测** `holdem.test.ts` 扩至 40 例(含 roundComplete、buildPots、kick/rebuy/leave/reset
- [x] **5.1 验证测试** 下注顺序单测证明preflop=UTG、postflop=SB、每次加注重置轮询结论原代码正确
## 阶段 4展示细节问题 6、9、10
- [x] **6.1 engine** `resolveHand` 摊牌亮所有未弃玩家牌(含 all-in 双方HoldemBoard 在 `G.myHand` 为 null已清时回落 `revealedHands[me]`,结算后保留自己牌可见。
- [x] **6.2 ui** 座位展示 revealedHands含自己结算区展示赢家。
- [x] **9.1 ui+engine** 滑块 `step=5`、number 归一 5 的倍数;`raiseMove` 拒绝非 5 倍数(全下除外,单测覆盖)。
- [x] **10.1 ui** 座位显示 `本手总下 {totalBetThisHand}`
## 依赖与风险
- 阶段 0 的“踢人改 G”依赖 `Master` dispatchboardgame.io `Server()` 未直接暴露 `master`
需确认能否经 `db` + 自建 `Master` 实例触发 move若不可行降级为“仅清 metadata + 游戏内 passive 检测
(该座位长时间无动作则自动 seated=false”。
- 问题 5 大概率为“无需改逻辑,仅文档澄清 + 加测试证据”;若测试暴露 `endTurn({next})``ActivePlayers.ALL` 下异常,则升级为逻辑修复。
## 不建议现在做(避免过度工程)
- 账号落盘持久化(先用内存,与现有 InMemory 房间一致)。→ **已改为 SQLite 落盘**node:sqlite 内置,无原生编译;房间 metadata 仍为 InMemory重启即清空账号跨重启保留
- 自动轮回的定时器自动开(用显式“再来一局”按钮,避免无人时误开)。
- OAuth / 第三方登录。