1.优化websocket中的jackpot.hit
2.优化/api/game/betMyOrders接口,新增中奖号码字段result_number
This commit is contained in:
@@ -96,6 +96,7 @@ class PlayRecord extends Backend
|
|||||||
'channel.name as channel__name',
|
'channel.name as channel__name',
|
||||||
'game_record.period_no as gameRecord__period_no',
|
'game_record.period_no as gameRecord__period_no',
|
||||||
'game_record.status as gameRecord__status',
|
'game_record.status as gameRecord__status',
|
||||||
|
'game_record.result_number as gameRecord__result_number',
|
||||||
])
|
])
|
||||||
->order($order)
|
->order($order)
|
||||||
->paginate($limit);
|
->paginate($limit);
|
||||||
@@ -120,6 +121,9 @@ class PlayRecord extends Backend
|
|||||||
'status' => isset($row['gameRecord__status']) && is_numeric((string) $row['gameRecord__status'])
|
'status' => isset($row['gameRecord__status']) && is_numeric((string) $row['gameRecord__status'])
|
||||||
? (int) $row['gameRecord__status']
|
? (int) $row['gameRecord__status']
|
||||||
: null,
|
: null,
|
||||||
|
'result_number' => isset($row['gameRecord__result_number']) && $row['gameRecord__result_number'] !== '' && $row['gameRecord__result_number'] !== null
|
||||||
|
? (string) $row['gameRecord__result_number']
|
||||||
|
: null,
|
||||||
];
|
];
|
||||||
unset(
|
unset(
|
||||||
$row['user__username'],
|
$row['user__username'],
|
||||||
@@ -127,6 +131,7 @@ class PlayRecord extends Backend
|
|||||||
$row['channel__name'],
|
$row['channel__name'],
|
||||||
$row['gameRecord__period_no'],
|
$row['gameRecord__period_no'],
|
||||||
$row['gameRecord__status'],
|
$row['gameRecord__status'],
|
||||||
|
$row['gameRecord__result_number'],
|
||||||
);
|
);
|
||||||
$list[$idx] = $row;
|
$list[$idx] = $row;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -401,8 +401,40 @@ class Game extends MobileBase
|
|||||||
'list_rows' => $pageSize,
|
'list_rows' => $pageSize,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
$periodIds = [];
|
||||||
|
foreach ($paginate->items() as $item) {
|
||||||
|
$periodIdValue = filter_var($item->period_id ?? null, FILTER_VALIDATE_INT);
|
||||||
|
if ($periodIdValue !== false && $periodIdValue > 0) {
|
||||||
|
$periodIds[] = $periodIdValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$periodIds = array_values(array_unique($periodIds));
|
||||||
|
$resultNumberByPeriodId = [];
|
||||||
|
if ($periodIds !== []) {
|
||||||
|
$periodRows = Db::name('game_record')
|
||||||
|
->whereIn('id', $periodIds)
|
||||||
|
->field(['id', 'result_number'])
|
||||||
|
->select()
|
||||||
|
->toArray();
|
||||||
|
foreach ($periodRows as $row) {
|
||||||
|
if (!is_array($row)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$pid = filter_var($row['id'] ?? null, FILTER_VALIDATE_INT);
|
||||||
|
if ($pid === false || $pid <= 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$rn = filter_var($row['result_number'] ?? null, FILTER_VALIDATE_INT);
|
||||||
|
$resultNumberByPeriodId[$pid] = ($rn === false ? null : $rn);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
$rows = [];
|
$rows = [];
|
||||||
foreach ($paginate->items() as $item) {
|
foreach ($paginate->items() as $item) {
|
||||||
|
$periodIdValue = filter_var($item->period_id ?? null, FILTER_VALIDATE_INT);
|
||||||
|
if ($periodIdValue === false) {
|
||||||
|
$periodIdValue = 0;
|
||||||
|
}
|
||||||
$rows[] = [
|
$rows[] = [
|
||||||
'order_no' => (string) $item->id,
|
'order_no' => (string) $item->id,
|
||||||
'period_no' => $item->period_no,
|
'period_no' => $item->period_no,
|
||||||
@@ -410,7 +442,7 @@ class Game extends MobileBase
|
|||||||
// 整笔压注金额(本笔总扣款)
|
// 整笔压注金额(本笔总扣款)
|
||||||
'bet_amount' => $item->total_amount,
|
'bet_amount' => $item->total_amount,
|
||||||
'total_amount' => $item->total_amount,
|
'total_amount' => $item->total_amount,
|
||||||
'result_number' => null,
|
'result_number' => $periodIdValue > 0 ? ($resultNumberByPeriodId[$periodIdValue] ?? null) : null,
|
||||||
'win_amount' => $item->win_amount,
|
'win_amount' => $item->win_amount,
|
||||||
'status' => (string) $item->status,
|
'status' => (string) $item->status,
|
||||||
'create_time' => $item->create_time,
|
'create_time' => $item->create_time,
|
||||||
|
|||||||
@@ -106,6 +106,61 @@ final class GameWebSocketSubscriptionRegistry
|
|||||||
return $finalTopics;
|
return $finalTopics;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 增量订阅:将 topics 合并到现有订阅集合(不会移除旧 topic)。
|
||||||
|
*
|
||||||
|
* 兼容部分客户端“多次 subscribe 但只携带增量 topic”的行为,避免后续误覆盖导致 bet.win/jackpot.hit 丢订阅。
|
||||||
|
*
|
||||||
|
* @param list<string> $topics
|
||||||
|
* @return list<string> 合并后的订阅列表(去重排序)
|
||||||
|
*/
|
||||||
|
public static function mergeSubscriptions(int $connectionId, array $topics): array
|
||||||
|
{
|
||||||
|
if ($connectionId <= 0 || !isset(self::$connectionMeta[$connectionId])) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
$clean = [];
|
||||||
|
foreach ($topics as $t) {
|
||||||
|
if (!is_string($t)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$v = trim($t);
|
||||||
|
if ($v === '' || strlen($v) > 64) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$clean[$v] = true;
|
||||||
|
}
|
||||||
|
if ($clean === []) {
|
||||||
|
return self::$connectionMeta[$connectionId]['topics'];
|
||||||
|
}
|
||||||
|
|
||||||
|
$existing = self::$connectionMeta[$connectionId]['topics'];
|
||||||
|
$mergedMap = [];
|
||||||
|
foreach ($existing as $t) {
|
||||||
|
$mergedMap[$t] = true;
|
||||||
|
}
|
||||||
|
foreach (array_keys($clean) as $t) {
|
||||||
|
$mergedMap[$t] = true;
|
||||||
|
}
|
||||||
|
$finalTopics = array_keys($mergedMap);
|
||||||
|
sort($finalTopics);
|
||||||
|
|
||||||
|
// 只需要把新增 topic 写入 topicIndex(旧 topic 已存在索引)
|
||||||
|
$existingMap = [];
|
||||||
|
foreach ($existing as $t) {
|
||||||
|
$existingMap[$t] = true;
|
||||||
|
}
|
||||||
|
foreach ($finalTopics as $topic) {
|
||||||
|
if (!isset($existingMap[$topic])) {
|
||||||
|
self::$topicIndex[$topic][$connectionId] = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self::$connectionMeta[$connectionId]['topics'] = $finalTopics;
|
||||||
|
|
||||||
|
return $finalTopics;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取订阅了指定 topic 的所有 connection_id。
|
* 获取订阅了指定 topic 的所有 connection_id。
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -170,10 +170,24 @@ class GameWebSocketServer
|
|||||||
if ($action === 'subscribe') {
|
if ($action === 'subscribe') {
|
||||||
$rawTopics = $decoded['topics'] ?? [];
|
$rawTopics = $decoded['topics'] ?? [];
|
||||||
$rawList = is_array($rawTopics) ? $rawTopics : [];
|
$rawList = is_array($rawTopics) ? $rawTopics : [];
|
||||||
$finalTopics = GameWebSocketSubscriptionRegistry::replaceSubscriptions($connection->id, $rawList);
|
$replace = false;
|
||||||
|
if (!empty($decoded['replace'])) {
|
||||||
|
$replace = true;
|
||||||
|
}
|
||||||
|
if (isset($decoded['mode']) && is_string($decoded['mode']) && trim($decoded['mode']) === 'replace') {
|
||||||
|
$replace = true;
|
||||||
|
}
|
||||||
|
$before = GameWebSocketSubscriptionRegistry::meta($connection->id);
|
||||||
|
$beforeTopics = is_array($before) ? ($before['topics'] ?? []) : [];
|
||||||
|
|
||||||
|
$finalTopics = $replace
|
||||||
|
? GameWebSocketSubscriptionRegistry::replaceSubscriptions($connection->id, $rawList)
|
||||||
|
: GameWebSocketSubscriptionRegistry::mergeSubscriptions($connection->id, $rawList);
|
||||||
Log::channel('ws')->info('subscribe', [
|
Log::channel('ws')->info('subscribe', [
|
||||||
'connection_id' => $connection->id,
|
'connection_id' => $connection->id,
|
||||||
'user_id' => GameWebSocketSubscriptionRegistry::userIdOf($connection->id),
|
'user_id' => GameWebSocketSubscriptionRegistry::userIdOf($connection->id),
|
||||||
|
'replace' => $replace,
|
||||||
|
'before_topics' => $beforeTopics,
|
||||||
'topics' => $finalTopics,
|
'topics' => $finalTopics,
|
||||||
'requested_count' => is_array($rawTopics) ? count($rawTopics) : 0,
|
'requested_count' => is_array($rawTopics) ? count($rawTopics) : 0,
|
||||||
]);
|
]);
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ export default {
|
|||||||
update_time: 'Updated',
|
update_time: 'Updated',
|
||||||
gameRecord_period_no: 'Round (relation)',
|
gameRecord_period_no: 'Round (relation)',
|
||||||
gameRecord_status: 'Round status',
|
gameRecord_status: 'Round status',
|
||||||
|
result_number: 'Result number',
|
||||||
'gameRecord_status 0': 'Open for betting',
|
'gameRecord_status 0': 'Open for betting',
|
||||||
'gameRecord_status 1': 'Closed',
|
'gameRecord_status 1': 'Closed',
|
||||||
'gameRecord_status 2': 'Settling tickets',
|
'gameRecord_status 2': 'Settling tickets',
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ export default {
|
|||||||
update_time: '更新时间',
|
update_time: '更新时间',
|
||||||
gameRecord_period_no: '对局期号',
|
gameRecord_period_no: '对局期号',
|
||||||
gameRecord_status: '期状态',
|
gameRecord_status: '期状态',
|
||||||
|
result_number: '中奖号码',
|
||||||
'gameRecord_status 0': '下注开放',
|
'gameRecord_status 0': '下注开放',
|
||||||
'gameRecord_status 1': '已封盘',
|
'gameRecord_status 1': '已封盘',
|
||||||
'gameRecord_status 2': '算票中',
|
'gameRecord_status 2': '算票中',
|
||||||
|
|||||||
@@ -147,6 +147,14 @@ const baTable = new baTableClass(
|
|||||||
'5': t('game.playRecord.gameRecord_status 5'),
|
'5': t('game.playRecord.gameRecord_status 5'),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
label: t('game.playRecord.result_number'),
|
||||||
|
prop: 'gameRecord.result_number',
|
||||||
|
align: 'center',
|
||||||
|
width: 110,
|
||||||
|
operator: 'eq',
|
||||||
|
showOverflowTooltip: true,
|
||||||
|
},
|
||||||
{ label: t('game.playRecord.user_id'), prop: 'user_id', align: 'center', show: false, width: 90, operator: 'RANGE' },
|
{ label: t('game.playRecord.user_id'), prop: 'user_id', align: 'center', show: false, width: 90, operator: 'RANGE' },
|
||||||
{
|
{
|
||||||
label: t('game.playRecord.user_username'),
|
label: t('game.playRecord.user_username'),
|
||||||
|
|||||||
Reference in New Issue
Block a user