优化websocket连接
This commit is contained in:
@@ -52,6 +52,7 @@ class Live extends Backend
|
|||||||
$topics = [
|
$topics = [
|
||||||
'admin.live.snapshot',
|
'admin.live.snapshot',
|
||||||
'admin.live.opened',
|
'admin.live.opened',
|
||||||
|
'jackpot.hit',
|
||||||
'period.tick',
|
'period.tick',
|
||||||
'period.locked',
|
'period.locked',
|
||||||
'period.opened',
|
'period.opened',
|
||||||
|
|||||||
@@ -385,14 +385,24 @@ final class GameLiveService
|
|||||||
}
|
}
|
||||||
self::publishPublicPeriodOpened((string) $record['period_no'], $finalNumber, $now);
|
self::publishPublicPeriodOpened((string) $record['period_no'], $finalNumber, $now);
|
||||||
self::publishPublicPeriodPayout((string) $record['period_no'], $finalNumber, $payoutUntil);
|
self::publishPublicPeriodPayout((string) $record['period_no'], $finalNumber, $payoutUntil);
|
||||||
|
$jackpotHits = is_array($settleOut['jackpot_hits'] ?? null) ? $settleOut['jackpot_hits'] : [];
|
||||||
GameWebSocketEventBus::publish('admin.live.opened', [
|
GameWebSocketEventBus::publish('admin.live.opened', [
|
||||||
'period_id' => $rid,
|
'period_id' => $rid,
|
||||||
'period_no' => (string) $record['period_no'],
|
'period_no' => (string) $record['period_no'],
|
||||||
'result_number' => $finalNumber,
|
'result_number' => $finalNumber,
|
||||||
'payout_until' => $payoutUntil,
|
'payout_until' => $payoutUntil,
|
||||||
'jackpot_hits' => is_array($settleOut['jackpot_hits'] ?? null) ? $settleOut['jackpot_hits'] : [],
|
'jackpot_hits' => $jackpotHits,
|
||||||
'server_time' => $now,
|
'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);
|
self::publishSnapshot(null);
|
||||||
|
|
||||||
return [
|
return [
|
||||||
@@ -618,7 +628,6 @@ final class GameLiveService
|
|||||||
{
|
{
|
||||||
$snapshot = self::buildSnapshot($recordId);
|
$snapshot = self::buildSnapshot($recordId);
|
||||||
self::publishPublicPeriodTick($snapshot);
|
self::publishPublicPeriodTick($snapshot);
|
||||||
GameWebSocketEventBus::publish('admin.live.snapshot', $snapshot);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -697,6 +697,31 @@
|
|||||||
- 订阅资金流:`{"action":"subscribe","topics":["bet.accepted","wallet.changed"]}`
|
- 订阅资金流:`{"action":"subscribe","topics":["bet.accepted","wallet.changed"]}`
|
||||||
- 订阅托管流:`{"action":"subscribe","topics":["auto.spin.progress","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 后台连接方式(管理端联调)
|
### 7.1A 后台连接方式(管理端联调)
|
||||||
|
|
||||||
- 后台菜单:仅保留一个菜单 `连接服务器websocket`,用于统一联调 WebSocket
|
- 后台菜单:仅保留一个菜单 `连接服务器websocket`,用于统一联调 WebSocket
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ export default {
|
|||||||
ws_connect: 'Connect WS',
|
ws_connect: 'Connect WS',
|
||||||
ws_disconnect: 'Disconnect WS',
|
ws_disconnect: 'Disconnect WS',
|
||||||
ws_log_empty: 'No WebSocket logs yet.',
|
ws_log_empty: 'No WebSocket logs yet.',
|
||||||
|
jackpot_hit_tip: 'Jackpot winners detected in this round.',
|
||||||
candidate_title: 'Candidate payout estimates',
|
candidate_title: 'Candidate payout estimates',
|
||||||
number: 'Number',
|
number: 'Number',
|
||||||
estimated_loss: 'Estimated payout',
|
estimated_loss: 'Estimated payout',
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ export default {
|
|||||||
ws_connect: '连接WS',
|
ws_connect: '连接WS',
|
||||||
ws_disconnect: '断开WS',
|
ws_disconnect: '断开WS',
|
||||||
ws_log_empty: '暂无 WebSocket 日志。',
|
ws_log_empty: '暂无 WebSocket 日志。',
|
||||||
|
jackpot_hit_tip: '本期出现中大奖用户,请查看开奖信息。',
|
||||||
candidate_title: '候选号码赔付预估',
|
candidate_title: '候选号码赔付预估',
|
||||||
number: '号码',
|
number: '号码',
|
||||||
estimated_loss: '预估赔付',
|
estimated_loss: '预估赔付',
|
||||||
|
|||||||
@@ -305,6 +305,14 @@ function handleWsPayload(raw: unknown): void {
|
|||||||
mergeLiveSnapshot(parsed.data as anyObj)
|
mergeLiveSnapshot(parsed.data as anyObj)
|
||||||
return
|
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') {
|
if (event === 'period.tick' && parsed.data && typeof parsed.data === 'object') {
|
||||||
const periodData = parsed.data as anyObj
|
const periodData = parsed.data as anyObj
|
||||||
if (typeof periodData.server_time === 'number') {
|
if (typeof periodData.server_time === 'number') {
|
||||||
|
|||||||
Reference in New Issue
Block a user