问题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>
29 lines
1.6 KiB
Markdown
29 lines
1.6 KiB
Markdown
# 问题 9:筹码滑块分段(每段 5,每 5 一段)
|
||
|
||
## 现象 / 需求
|
||
加注输入框旁的滑块(`HoldemBoard.tsx:210` 的 `<input type="range">`)目前是连续整数步进,
|
||
用户希望**分段**,每一段 = 5(即滑块只能停在 5 的倍数上,step=5)。
|
||
|
||
## 现状
|
||
```tsx
|
||
<input type="range" min={minRaiseTo} max={maxRaiseTo} value={raiseAmt}
|
||
onChange={(e) => setRaiseAmt(Number(e.target.value))} style={{ width: 120 }} />
|
||
```
|
||
- 没有 `step` → 默认 step=1,连续可调。
|
||
- 同时 `type="number"` 输入框允许任意值(含非 5 倍数)。
|
||
|
||
## 拟采用方案
|
||
1. **滑块加 `step={5}`**:`min/max` 都对齐到 5 的倍数。
|
||
- `minRaiseTo` 与 `maxRaiseTo` 在传给 range 前 `Math.round(x/5)*5`。
|
||
- 加注合法性校验(`raiseMove`)本就要求 `to > currentBet` 且为完整加注;
|
||
为保证“只能下 5 的倍数”,在 `raiseMove` 入口增加:`if (to % 5 !== 0) return;`(或四舍五入后校验)。
|
||
这样即使 number 输入框填了非 5 倍数也会被拒,UI 与引擎一致。
|
||
2. **number 输入框同步 step=5**:`<input type="number" step={5} ... />`,
|
||
并在 `onChange` 里 `Math.round(v/5)*5` 归一,避免输入非法值。
|
||
3. **小 bet 边界**:盲注/筹码本身是 5 的倍数(默认 10/20、1000),自然对齐;
|
||
若 setup 用了非 5 倍数,滑块仍按 5 段但 min/max 取整到最近的 5 倍数。
|
||
|
||
## 验证
|
||
- UI:拖动滑块,值始终为 5 的倍数;输入 23 → 归一为 25 或被拒。
|
||
- engine:单测 `raiseMove` 对 `to=23` 拒绝、对 `to=25`(>currentBet 且完整加注)通过。
|