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

58 lines
2.7 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.
# 问题 1改名后牌桌 UI 不刷新
## 现象
点击“改名”后,**房间列表 pill 上的名字更新了**,但进入牌桌后,座位上的名字(`HoldemBoard`**没有任何变化**。
## 根因(已定位)
存在**两个相互独立的名字来源**,改名只更新了其中一个:
1. **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读的就是这个所以刷新后变了。
2. **游戏内名字**:牌桌 `HoldemBoard` 显示的是 `G.players[pid].name`,由
`sitDownMove``holdem.ts:363`)在入座时写入一次,**之后再也没更新过**。
因此房间列表刷新(来源 1 变了)但牌桌(来源 2 没变)出现不一致。
## 拟采用方案
让游戏内的名字成为**单一权威来源**,并把改名事件传导进游戏状态:
1. **engine`holdem.ts`**:新增 `renameMove({ G, ctx, playerID }, newName?)`
```ts
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. **ui`HoldemBoard.tsx`**:新增 effect——当 `playerName` prop 变化且该座位已入座时,
自动 `onMove('rename', [playerName])`
```ts
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. **ui`App.tsx` 已有链路)**`LobbyRoomList.renameMe` 成功后调 `onRename(newName)`
→ 已写入 `App.playerName``App.tsx:225` 的 `onRename`)→ 作为 `playerName` prop 透传给
`HoldemBoard``App.tsx:609`)→ 触发上面的 effect → 改掉 `G.players[me].name`。
这样改名在“房间列表”和“牌桌”两处都会刷新,且只依赖已有的 prop 链路,无需重构 Client 实例。
## 验证
- 联机:改名 → 牌桌 `holdem-seat-{pid}` 的 `p.name` 在下一帧变为新名。
- 单测:直接调 `renameMove` 断言 `G.players[me].name` 更新。
- 边界:空名 / 超过 20 字被截断;未入座不生效。