1.ws优化bet.win订阅

This commit is contained in:
2026-05-26 18:44:42 +08:00
parent bb5ef82d49
commit e163090bc2
4 changed files with 207 additions and 52 deletions

View File

@@ -109,9 +109,12 @@
| `streak_win_reward` | JSON`rows[]` 每项含 `streak`110`odds_factor`(与 33 相乘为整段赔率)、`is_jackpot`(是否大奖)。派彩公式:`total_amount × odds_factor × 33`。默认第 10 档 `is_jackpot=true`。 |
| `deposit_tier` | 仍由「充值档位」独立菜单维护,**不出现在**「常规配置」列表。 |
开奖结算后更新 **`user.current_streak`**:本期有中奖注单则 `min(streak_at_bet+1, 10)`,否则 **连胜归 0**(无档位配置)。**中奖 WebSocket同一结算时刻**
- 向相关用户推送 **`bet.win`**(小奖/大奖统一;`data.is_jackpot` 标记是否大奖档;含 `total_win``balance_after``bets[]`)。
- 若存在大奖档命中,**再**向公共频道推送 **`jackpot.hit`**`hits[]` 每项含 `user_id`、**`nickname`**(昵称优先、空则 fallback 到 username`period_no``total_win``result_number`),供全站公告;移动端个人弹窗以 **`bet.win`** 为准。
开奖结算后更新 **`user.current_streak`**:本期有中奖注单则 `min(streak_at_bet+1, 10)`,否则 **连胜归 0**(无档位配置)。**中奖 WebSocket同一结算批次**(实现:`GameBetSettleService::publishSettlementWinsAfterCommit`
- 向相关用户推送 **`bet.win`**(小奖/大奖统一;**个人中奖弹窗只认此主题**)。载荷含 `total_win``balance_after``bets[]``is_win=true`,并合并 `current_streak` / `streak_level` / `odds_factor` / **`is_jackpot`**(是否**大奖档**,由 `streak_at_bet` 对应 `streak_win_reward.is_jackpot` 决定,非 `bet.accepted` 的下注时展示含义)。
- 若存在大奖档命中,**再**向公共频道推送 **`jackpot.hit`**`hits[]` 每项含 `user_id`、**`nickname`**、`period_no``total_win``result_number`),供全站跑马灯;**个人弹窗`bet.win` 为准**
- **去重**`user.streak` / `wallet.changed` / `jackpot.hit` 使用 `dfw:v1:settle:notify:{period_id}`**`bet.win` 独立** `dfw:v1:ws:betwin:{period_id}:{user_id}`,避免整期 dedup 吞掉中奖推送。
- **补偿**:库内已结算中奖但内存未聚合时,从 `bet_order` 重建并补发;运维可用 `php scripts/republish_bet_win.php`(见移动端草案 §7.1.4)。
- **大奖审核**`win_amount >= jackpot_max_amount` 时注单可先 `status=待审核`,仍推 `bet.win`;后台审核通过后再推一次 `bet.win``approveJackpot`)。
> **派彩期间 `period.tick` 静默规则**:开奖到派彩宽限期结束(`status=payouting`)期间**不再推送 `period.tick`**,避免覆盖中奖动画;本期进入 `finished`/`void` 时各推一帧边界帧每期号每状态去重Redis Key `dfw:v1:ws:tick:boundary:{period_no}:{status}`TTL 300s下一期 `betting` 时恢复每秒推送。详见《36字花-移动端接口设计草案》§7.1.3。
@@ -282,6 +285,21 @@
| 后台快照 `maintenance_ui` | `!game_live_runtime_enabled && !hasActiveRecord()` 时为 `true`:表示**当局已完全结束**(含派彩),此时后台页展示「维护中」并锁定操作区(仅顶部「游戏运行」开关可用);当局尚在 03 状态时为 `false`,倒计时与操作区保持可用直至收尾完成 |
| 作废本局(后台按钮) | 仅当本期为 **下注开放 / 已封盘**`game_record.status``0``1`):将所有 **待开奖** 注单(`bet_order.status = 1`)按 `total_amount` 退回余额并置 `bet_order.status = 3`,写钱包流水 `biz_type = bet_void`;本期 **`game_record.status = 5`**,写入 **`void_reason`**;并 **强制将 `game_live_runtime_enabled` 置为 `0`**。需管理员在后台再次打开「游戏运行」开关后,才恢复下注与后续期次创建 |
| 后台接口 | `POST /admin/game.Live/runtime`body`enabled` 0/1`POST /admin/game.Live/voidPeriod`body`record_id` 可选、`void_reason` 必填) |
| 实时快照 HTTP | `GET /admin/game.Live/snapshot`**只读** `buildSnapshot`,不执行 `recoverLiveRoundState`,避免接口超时;对局自愈/自动开奖由 **`gameLiveTicker`**(每秒 `publishSnapshot`)与 `drawResult` 链路负责 |
| WebSocket | `GET /admin/game.Live/wsConfig` 返回 `ws_url` 与推荐 `subscribe_topics`(含 `admin.live.snapshot``bet.win` 等);`admin.live.snapshot` 由 WS 进程每秒直推(有订阅者时) |
| WS 地址 | `WebSocketConfigHelper``.env``H5_WEBSOCKET_URL``127.0.0.1` 且请求 Host 非本机时自动改用 `ws(s)://{host}/ws/`;生产需 Nginx 将 `/ws/` 反代至 **3131** |
#### 8.2.2 WebSocket 主题与 `bet.win`(联调清单)
| 主题 | 触发 | 移动端 |
|------|------|--------|
| `bet.accepted` | 下注成功 | 扣款确认;`is_jackpot` 为下注时档位 |
| `bet.win` | 开奖结算后中奖 | **中奖弹窗**`is_jackpot` 为大奖档 |
| `jackpot.hit` | 本期有大奖档命中 | 全站公告(可选) |
| `wallet.changed` | 余额变动 | 含 `biz_type=payout` 派彩 |
| `user.streak` | 每期结算后 | 连胜更新 |
详见《36字花-移动端接口设计草案》§7.1.3、§7.1.4。
### 8.3 代理与结算(逻辑就绪后)