Files
huajishe-tts/docs/texas/01-rename-not-refreshing.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

2.7 KiB
Raw Permalink Blame History

问题 1改名后牌桌 UI 不刷新

现象

点击“改名”后,房间列表 pill 上的名字更新了,但进入牌桌后,座位上的名字(HoldemBoard没有任何变化

根因(已定位)

存在两个相互独立的名字来源,改名只更新了其中一个:

  1. Lobby 名字LobbyRoomList.renameMe()lobby.updatePlayer(...) → boardgame.io /update 路由只改 metadata.players[playerID].name (见 boardgame.io/dist/cjs/server.js:2428metadata.players[playerID].name = newName;)。 房间列表pill读的就是这个所以刷新后变了。
  2. 游戏内名字:牌桌 HoldemBoard 显示的是 G.players[pid].name,由 sitDownMoveholdem.ts:363)在入座时写入一次,之后再也没更新过

因此房间列表刷新(来源 1 变了)但牌桌(来源 2 没变)出现不一致。

拟采用方案

让游戏内的名字成为单一权威来源,并把改名事件传导进游戏状态:

  1. engineholdem.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 }

  2. uiHoldemBoard.tsx:新增 effect——当 playerName prop 变化且该座位已入座时, 自动 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]);
    
  3. uiApp.tsx 已有链路)LobbyRoomList.renameMe 成功后调 onRename(newName) → 已写入 App.playerNameApp.tsx:225onRename)→ 作为 playerName prop 透传给 HoldemBoardApp.tsx:609)→ 触发上面的 effect → 改掉 G.players[me].name

这样改名在“房间列表”和“牌桌”两处都会刷新,且只依赖已有的 prop 链路,无需重构 Client 实例。

验证

  • 联机:改名 → 牌桌 holdem-seat-{pid}p.name 在下一帧变为新名。
  • 单测:直接调 renameMove 断言 G.players[me].name 更新。
  • 边界:空名 / 超过 20 字被截断;未入座不生效。