|null */ public function build(AdminUser $admin, array $filters): ?array { if (! $this->canView($admin)) { return null; } $scope = AdminScopeContextResolver::fromValues( $admin, requestedSiteCode: isset($filters['site_code']) ? (string) $filters['site_code'] : null, requestedAgentNodeId: isset($filters['agent_node_id']) ? (int) $filters['agent_node_id'] : null, ); $period = (string) ($filters['period'] ?? 'last_7_days'); $metric = (string) ($filters['metric'] ?? 'overview'); $playCode = isset($filters['play_code']) && $filters['play_code'] !== '' ? (string) $filters['play_code'] : null; $range = $this->reportQuery->resolveDashboardPeriod( $period, isset($filters['date_from']) ? (string) $filters['date_from'] : null, isset($filters['date_to']) ? (string) $filters['date_to'] : null, ); $dateFrom = $range['date_from']; $dateTo = $range['date_to']; $trend = $this->reportQuery->dailyProfitSeriesFilled($dateFrom, $dateTo, scope: $scope); return [ 'period' => $period, 'metric' => $metric, 'play_code' => $playCode, 'date_from' => $dateFrom, 'date_to' => $dateTo, 'currency_code' => $this->reportQuery->resolvePeriodCurrencyCode($dateFrom, $dateTo, $scope), 'summary' => $this->reportQuery->periodFinanceTotals($dateFrom, $dateTo, $scope), 'daily_series' => $trend['series'], 'chart_meta' => [ 'chart_date_from' => $trend['chart_date_from'], 'chart_date_to' => $trend['chart_date_to'], 'truncated' => $trend['truncated'], 'span_days' => $trend['span_days'], ], 'play_breakdown' => $this->reportQuery->playDimensionBreakdownRows( $dateFrom, $dateTo, $playCode, scope: $scope, ), 'agent_breakdown' => $this->reportQuery->agentRankingRows( $dateFrom, $dateTo, $playCode, limit: 200, scope: $scope, ), ]; } /** 与 {@see AdminAuthorizationRegistry} 中 dashboard 类 API 资源的 `dashboard.view` 绑定一致。 */ private function canView(AdminUser $admin): bool { return $admin->hasPermissionCode('dashboard.view'); } }