优化websocket连接
This commit is contained in:
@@ -52,6 +52,7 @@ class Live extends Backend
|
||||
$topics = [
|
||||
'admin.live.snapshot',
|
||||
'admin.live.opened',
|
||||
'jackpot.hit',
|
||||
'period.tick',
|
||||
'period.locked',
|
||||
'period.opened',
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -24,6 +24,7 @@ export default {
|
||||
ws_connect: '连接WS',
|
||||
ws_disconnect: '断开WS',
|
||||
ws_log_empty: '暂无 WebSocket 日志。',
|
||||
jackpot_hit_tip: '本期出现中大奖用户,请查看开奖信息。',
|
||||
candidate_title: '候选号码赔付预估',
|
||||
number: '号码',
|
||||
estimated_loss: '预估赔付',
|
||||
|
||||
@@ -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') {
|
||||
|
||||
Reference in New Issue
Block a user