| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192 |
- <?php
- namespace App\Services\AdminRealtime;
- use App\Constants\HttpStatus;
- use App\Http\Controllers\admin\Bet;
- use App\Http\Controllers\admin\JisuGameOrder;
- use App\Http\Controllers\admin\LhcOrder;
- use App\Http\Controllers\admin\Order;
- use App\Http\Controllers\admin\SportGameOrder;
- use App\Http\Controllers\admin\Wallet;
- use App\Http\Controllers\admin\Withdraw;
- use App\Services\ManualAuditService;
- use App\Services\OnlineUserService;
- use App\Services\PaymentOrderService;
- use App\Services\ThirdGameOrderService;
- use App\Services\ThirdPartyDepositService;
- use App\Services\UserService;
- use Illuminate\Http\JsonResponse;
- use Illuminate\Http\Request;
- use Illuminate\Support\Facades\DB;
- use Illuminate\Support\Facades\Facade;
- use RuntimeException;
- /**
- * 把事件表中的「表 + 主键」解析为对应后台列表接口的单行数据。
- *
- * 一律复用列表接口本身的查询(控制器内拼查询的直接以 id 参数调用控制器,
- * 其余调用列表所用的 service),保证推送的行与列表接口返回的行字段一致。
- */
- final class AdminRealtimeRows
- {
- /** 频道 => [列表接口, 菜单按钮权限 uri, 行主键字段] */
- public const CHANNELS = [
- 'admin.orders.sport' => ['/admin/order/list', 'admin/order/list', 'id'],
- 'admin.orders.lhc' => ['/admin/lhcOrder/list', 'admin/lhcOrder/list', 'id'],
- 'admin.orders.sport_game' => ['/admin/sportGameOrder/list', 'admin/sportGameOrder/list', 'id'],
- 'admin.orders.jisu_game' => ['/admin/jisuGameOrder/list', 'admin/jisuGameOrder/list', 'id'],
- 'admin.orders.third_game' => ['/admin/thirdGame/orders', 'admin/thirdGame/orders', 'id'],
- 'admin.orders.bet' => ['/admin/bet', 'admin/bet', 'id'],
- 'admin.orders.recharge' => ['/admin/wallet', 'admin/wallet', 'id'],
- 'admin.orders.payment' => ['/admin/paymentOrder', 'admin/paymentOrder', 'id'],
- 'admin.orders.third_party_deposit' => ['/admin/thirdPartyDeposit', 'admin/thirdPartyDeposit', 'id'],
- 'admin.orders.payment_withdraw' => ['/admin/withdraw/rmb', 'admin/withdraw/rmb', 'id'],
- 'admin.orders.withdraw' => ['/admin/withdraw', 'admin/withdraw', 'id'],
- 'admin.orders.manual_audit' => ['/admin/manualAudit', 'admin/manualAudit', 'id'],
- 'admin.users' => ['/admin/user', 'admin/user', 'id'],
- 'admin.users.online' => ['/admin/online/users', 'admin/online/users', 'member_id'],
- ];
- /** 表 => 默认频道(payment_orders 按 type 分流,见 paymentOrders) */
- private const RESOURCE_CHANNELS = [
- 'sport_order' => 'admin.orders.sport',
- 'lhc_order' => 'admin.orders.lhc',
- 'sport_game_order' => 'admin.orders.sport_game',
- 'jisu_game_order' => 'admin.orders.jisu_game',
- 'third_game_orders' => 'admin.orders.third_game',
- 'bets' => 'admin.orders.bet',
- 'recharges' => 'admin.orders.recharge',
- 'withdraws' => 'admin.orders.withdraw',
- 'manual_audits' => 'admin.orders.manual_audit',
- 'users' => 'admin.users',
- AdminRealtime::USER_ONLINE => 'admin.users.online',
- ];
- /**
- * @return list<array{channel:string,key:array,data:?array}> 解析不到(已删除或不在列表口径内)的行不返回,deleted / offline 只带 key
- */
- public static function resolve(string $resource, string $id, string $action): array
- {
- if ($resource === 'payment_orders') {
- return self::paymentOrders($id, $action);
- }
- $channel = self::RESOURCE_CHANNELS[$resource] ?? null;
- if ($channel === null) {
- return [];
- }
- if ($resource === AdminRealtime::USER_ONLINE) {
- return self::online($id, $action);
- }
- if ($action === 'deleted') {
- return [self::message($channel, ['id' => self::castId($id)], null)];
- }
- $rows = match ($resource) {
- 'sport_order' => self::viaController(Order::class, 'list', ['id' => $id]),
- 'lhc_order' => self::viaController(LhcOrder::class, 'list', ['id' => $id]),
- 'sport_game_order' => self::viaController(SportGameOrder::class, 'list', ['id' => $id]),
- 'jisu_game_order' => self::viaController(JisuGameOrder::class, 'list', ['id' => $id]),
- 'bets' => self::viaController(Bet::class, 'index', ['id' => $id]),
- 'recharges' => self::viaController(Wallet::class, 'index', ['id' => $id]),
- 'withdraws' => self::viaController(Withdraw::class, 'index', ['id' => $id]),
- 'third_game_orders' => app(ThirdGameOrderService::class)->paginate(['id' => $id])['list'] ?? [],
- 'manual_audits' => ManualAuditService::list(['id' => $id])['data'] ?? [],
- 'users' => UserService::paginate(['id' => $id])['data'] ?? [],
- };
- $row = self::pick($rows, 'id', $id);
- return $row === null ? [] : [self::message($channel, ['id' => self::castId($id)], $row)];
- }
- /** 代收(type=1)进「代收订单」与「三方充值」两张列表,代付(type=2/4)进「人民币提现」 */
- private static function paymentOrders(string $id, string $action): array
- {
- $key = ['id' => self::castId($id)];
- if ($action === 'deleted') {
- return array_map(static fn(string $channel): array => self::message($channel, $key, null),
- ['admin.orders.payment', 'admin.orders.third_party_deposit', 'admin.orders.payment_withdraw']);
- }
- $type = (int) DB::table('payment_orders')->where('id', $id)->value('type');
- $messages = [];
- if ($type === PaymentOrderService::TYPE_PAY) {
- $row = self::pick(PaymentOrderService::paginate(['type' => PaymentOrderService::TYPE_PAY, 'id' => $id])['data'] ?? [], 'id', $id);
- if ($row !== null) $messages[] = self::message('admin.orders.payment', $key, $row);
- $row = self::pick(ThirdPartyDepositService::list(['id' => $id])['data'] ?? [], 'id', $id);
- if ($row !== null) $messages[] = self::message('admin.orders.third_party_deposit', $key, $row);
- } elseif (in_array($type, [PaymentOrderService::TYPE_PAYOUT, PaymentOrderService::TYPE_SELF_PAYOUT], true)) {
- $row = self::pick(self::viaController(Withdraw::class, 'rmb', ['id' => $id, 'type' => $type]), 'id', $id);
- if ($row !== null) $messages[] = self::message('admin.orders.payment_withdraw', $key, $row);
- }
- return $messages;
- }
- private static function online(string $userId, string $action): array
- {
- $user = DB::table('users')->where('id', $userId)->first(['member_id', 'user_id']);
- if (!$user) {
- return [];
- }
- $key = ['member_id' => (string) ($user->member_id ?: $user->user_id)];
- if ($action === 'offline') {
- return [self::message('admin.users.online', $key, null)];
- }
- $row = OnlineUserService::list(['user_ids' => [(int) $userId], 'limit' => 1])['data'][0] ?? null;
- return $row === null ? [] : [self::message('admin.users.online', $key, self::normalize($row))];
- }
- /**
- * 以内部子请求调用后台列表控制器(与前端请求列表接口走同一段查询与格式化)。
- * 列表接口必须支持 id 筛选,pick() 再按 id 校验一次,防止筛选失效时推错行。
- */
- private static function viaController(string $class, string $method, array $query): array
- {
- $app = app();
- $original = $app->make('request');
- $request = Request::create('/', 'GET', $query + ['page' => 1, 'limit' => 20]);
- $request->user = $original->user ?? null;
- $app->instance('request', $request);
- Facade::clearResolvedInstance('request');
- try {
- $response = $app->call([$app->make($class), $method]);
- } finally {
- $app->instance('request', $original);
- Facade::clearResolvedInstance('request');
- }
- $body = $response instanceof JsonResponse ? $response->getData(true) : [];
- if ((int) ($body['code'] ?? -1) !== HttpStatus::OK) {
- throw new RuntimeException($class . '@' . $method . ' failed: ' . ($body['msg'] ?? 'non-json response'));
- }
- return $body['data']['data'] ?? [];
- }
- private static function pick($rows, string $field, string $id): ?array
- {
- foreach (self::normalize($rows) as $row) {
- if (is_array($row) && (string) ($row[$field] ?? '') === $id) {
- return $row;
- }
- }
- return null;
- }
- /** 与 HTTP 响应相同的序列化(模型的 appends / hidden / casts 均生效) */
- private static function normalize($value): array
- {
- return json_decode(json_encode($value), true) ?: [];
- }
- private static function message(string $channel, array $key, ?array $data): array
- {
- return ['channel' => $channel, 'key' => $key, 'data' => $data];
- }
- private static function castId(string $id)
- {
- return ctype_digit($id) ? (int) $id : $id;
- }
- }
|