优化websocket连接

This commit is contained in:
2026-04-24 15:25:15 +08:00
parent 2ce128e63a
commit 203e478b65
6 changed files with 47 additions and 2 deletions

View File

@@ -52,6 +52,7 @@ class Live extends Backend
$topics = [
'admin.live.snapshot',
'admin.live.opened',
'jackpot.hit',
'period.tick',
'period.locked',
'period.opened',

View File

@@ -385,14 +385,24 @@ final class GameLiveService
}
self::publishPublicPeriodOpened((string) $record['period_no'], $finalNumber, $now);
self::publishPublicPeriodPayout((string) $record['period_no'], $finalNumber, $payoutUntil);
$jackpotHits = is_array($settleOut['jackpot_hits'] ?? null) ? $settleOut['jackpot_hits'] : [];
GameWebSocketEventBus::publish('admin.live.opened', [
'period_id' => $rid,
'period_no' => (string) $record['period_no'],
'result_number' => $finalNumber,
'payout_until' => $payoutUntil,
'jackpot_hits' => is_array($settleOut['jackpot_hits'] ?? null) ? $settleOut['jackpot_hits'] : [],
'jackpot_hits' => $jackpotHits,
'server_time' => $now,
]);
if ($jackpotHits !== []) {
GameWebSocketEventBus::publish('jackpot.hit', [
'period_id' => $rid,
'period_no' => (string) $record['period_no'],
'result_number' => $finalNumber,
'hits' => $jackpotHits,
'server_time' => $now,
]);
}
self::publishSnapshot(null);
return [
@@ -618,7 +628,6 @@ final class GameLiveService
{
$snapshot = self::buildSnapshot($recordId);
self::publishPublicPeriodTick($snapshot);
GameWebSocketEventBus::publish('admin.live.snapshot', $snapshot);
}
/**

View File

@@ -697,6 +697,31 @@
- 订阅资金流:`{"action":"subscribe","topics":["bet.accepted","wallet.changed"]}`
- 订阅托管流:`{"action":"subscribe","topics":["auto.spin.progress","wallet.changed"]}`
#### 7.1.1 消息协议字段定义(联调口径)
- 客户端 -> 服务端:
- `action`:动作名(当前约定 `ping` / `subscribe`
- `topics`:仅 `subscribe` 时必填,表示要订阅的主题列表(数组)
- 服务端 -> 客户端:
- `event`:事件名(如 `period.tick``wallet.changed``jackpot.hit`
- `topic`:所属主题(通常与 `event` 一致;用于前端按主题路由)
- `data`:业务载荷(对象)
- `server_time`:服务端时间戳(秒,倒计时与对时基准)
#### 7.1.2 订阅行为说明
- **仅建立连接不会自动下发全部业务消息**;客户端需要发送 `subscribe` 明确订阅主题。
- 成功订阅后服务端返回:`{"event":"ws.subscribed","topics":[...]}`
- 若未订阅主题,通常只能收到握手首帧(`ws.connected`)和心跳回包(`pong`)。
#### 7.1.3 推送频率与触发规则(当前实现)
- `period.tick`**每秒一次**(用于倒计时、状态同步)。
- `admin.live.snapshot`**每秒一次**(后台实时对局页全量快照)。
- `period.opened` / `period.payout` / `admin.live.opened`:按开奖流程阶段触发(事件触发型,非固定频率)。
- `wallet.changed`:仅在余额发生变更时推送(如下注扣款、充值入账、派彩入账)。
- `jackpot.hit`**仅在本期存在中大奖命中用户时推送**;无命中不推送。
### 7.1A 后台连接方式(管理端联调)
- 后台菜单:仅保留一个菜单 `连接服务器websocket`,用于统一联调 WebSocket

View File

@@ -24,6 +24,7 @@ export default {
ws_connect: 'Connect WS',
ws_disconnect: 'Disconnect WS',
ws_log_empty: 'No WebSocket logs yet.',
jackpot_hit_tip: 'Jackpot winners detected in this round.',
candidate_title: 'Candidate payout estimates',
number: 'Number',
estimated_loss: 'Estimated payout',

View File

@@ -24,6 +24,7 @@ export default {
ws_connect: '连接WS',
ws_disconnect: '断开WS',
ws_log_empty: '暂无 WebSocket 日志。',
jackpot_hit_tip: '本期出现中大奖用户,请查看开奖信息。',
candidate_title: '候选号码赔付预估',
number: '号码',
estimated_loss: '预估赔付',

View File

@@ -305,6 +305,14 @@ function handleWsPayload(raw: unknown): void {
mergeLiveSnapshot(parsed.data as anyObj)
return
}
if (event === 'jackpot.hit' && parsed.data && typeof parsed.data === 'object') {
const jackpotData = parsed.data as anyObj
const hits = Array.isArray(jackpotData.hits) ? jackpotData.hits : []
if (hits.length > 0) {
ElMessage.success(t('game.live.jackpot_hit_tip'))
}
return
}
if (event === 'period.tick' && parsed.data && typeof parsed.data === 'object') {
const periodData = parsed.data as anyObj
if (typeof periodData.server_time === 'number') {