问题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>
2.7 KiB
2.7 KiB
问题 1:改名后牌桌 UI 不刷新
现象
点击“改名”后,房间列表 pill 上的名字更新了,但进入牌桌后,座位上的名字(HoldemBoard)没有任何变化。
根因(已定位)
存在两个相互独立的名字来源,改名只更新了其中一个:
- Lobby 名字:
LobbyRoomList.renameMe()→lobby.updatePlayer(...)→ boardgame.io/update路由只改metadata.players[playerID].name(见boardgame.io/dist/cjs/server.js:2428:metadata.players[playerID].name = newName;)。 房间列表(pill)读的就是这个,所以刷新后变了。 - 游戏内名字:牌桌
HoldemBoard显示的是G.players[pid].name,由sitDownMove(holdem.ts:363)在入座时写入一次,之后再也没更新过。
因此房间列表刷新(来源 1 变了)但牌桌(来源 2 没变)出现不一致。
拟采用方案
让游戏内的名字成为单一权威来源,并把改名事件传导进游戏状态:
-
engine(
holdem.ts):新增renameMove({ G, ctx, playerID }, newName?):export function renameMove({ G, ctx, playerID }, rawName?: string) { const me = playerID ?? ctx.currentPlayer; const p = G.players[me]; if (!p || !p.seated) return; const nm = (rawName ?? '').trim().slice(0, 20); if (!nm) return; p.name = nm; pushLog(G, `${nm} 改名`); }沿用现有
sitDownMove的信任模型(直接用playerID,局域网休闲场景可接受)。 在moves里注册rename: { move: renameMove, client: false }。 -
ui(
HoldemBoard.tsx):新增 effect——当playerNameprop 变化且该座位已入座时, 自动onMove('rename', [playerName]):const renamedRef = useRef<string | null>(null); useEffect(() => { if (playerName && renamedRef.current !== playerName && G.players[me]?.seated) { renamedRef.current = playerName; onMove('rename', [playerName]); } }, [playerName, G.players, me, onMove]); -
ui(
App.tsx已有链路):LobbyRoomList.renameMe成功后调onRename(newName)→ 已写入App.playerName(App.tsx:225的onRename)→ 作为playerNameprop 透传给HoldemBoard(App.tsx:609)→ 触发上面的 effect → 改掉G.players[me].name。
这样改名在“房间列表”和“牌桌”两处都会刷新,且只依赖已有的 prop 链路,无需重构 Client 实例。
验证
- 联机:改名 → 牌桌
holdem-seat-{pid}的p.name在下一帧变为新名。 - 单测:直接调
renameMove断言G.players[me].name更新。 - 边界:空名 / 超过 20 字被截断;未入座不生效。