ensurePlatformAdmin($request); $stats = Cache::remember( CacheKeys::platformDashboardStats(), now()->addMinutes(10), fn () => [ 'merchants' => Merchant::count(), 'admins' => Admin::count(), 'users' => User::count(), 'products' => Product::count(), 'orders' => Order::count(), // 收费中心(平台侧) 'plans' => Plan::count(), 'site_subscriptions' => SiteSubscription::count(), 'site_subscriptions_expired' => SiteSubscription::query() ->whereNotNull('ends_at') ->where('ends_at', '<', now()) ->count(), 'site_subscriptions_expiring_7d' => SiteSubscription::query() ->whereNotNull('ends_at') ->where('ends_at', '>=', now()) ->where('ends_at', '<', now()->addDays(7)) ->count(), 'platform_orders' => PlatformOrder::count(), 'platform_orders_unpaid_pending' => PlatformOrder::query() ->where('payment_status', 'unpaid') ->where('status', 'pending') ->count(), 'platform_orders_paid_pending' => PlatformOrder::query() ->where('payment_status', 'paid') ->where('status', 'pending') // 口径对齐“待生效”语义:排除明确的同步失败(失败单应该去同步失败治理) ->whereRaw("JSON_EXTRACT(meta, '$.subscription_activation_error.message') IS NULL") ->count(), // 可同步:沿用平台订单列表口径(paid+activated+未同步+无失败),且排除续费缺订阅脏数据 'platform_orders_syncable' => PlatformOrder::query() ->where('payment_status', 'paid') ->where('status', 'activated') ->whereRaw("JSON_EXTRACT(meta, '$.subscription_activation.subscription_id') IS NULL") ->whereRaw("JSON_EXTRACT(meta, '$.subscription_activation_error.message') IS NULL") ->where(function ($q) { $q->where('order_type', '!=', 'renewal') ->orWhereNotNull('site_subscription_id'); }) ->count(), // 同步失败:沿用平台订单列表口径(meta.subscription_activation_error.message 存在即失败) 'platform_orders_sync_failed' => PlatformOrder::query() ->whereRaw("JSON_EXTRACT(meta, '$.subscription_activation_error.message') IS NOT NULL") ->count(), 'platform_orders_renewal_missing_subscription' => PlatformOrder::query() ->where('order_type', 'renewal') ->whereNull('site_subscription_id') ->count(), // BMPA 失败:用于运营快速定位“批量标记支付并生效”失败的订单集合 'platform_orders_bmpa_failed' => PlatformOrder::query() ->whereRaw("JSON_EXTRACT(meta, '$.batch_mark_paid_and_activate_error.message') IS NOT NULL") ->count(), // 无回执(已支付但缺少回执证据):用于治理“已付但无回执”的风险订单 'platform_orders_paid_no_receipt' => PlatformOrder::query() ->where('payment_status', 'paid') ->whereRaw("JSON_EXTRACT(meta, '$.payment_summary.total_amount') IS NULL") ->whereRaw("JSON_EXTRACT(meta, '$.payment_receipts[0].amount') IS NULL") ->count(), // 站点治理 'active_merchants' => Merchant::query()->where('status', 'active')->count(), 'pending_orders' => Order::query()->where('status', 'pending')->count(), ] ); // 趋势卡(最小可用):近 7 天平台订单按天统计(订单数 + 已付金额) $trendDays = 7; $trendStart = now()->startOfDay()->subDays($trendDays - 1); $trendEnd = now()->endOfDay(); $trendRawRows = PlatformOrder::query() ->selectRaw("DATE(created_at) as d") ->selectRaw('COUNT(*) as cnt') ->selectRaw("SUM(CASE WHEN payment_status = 'paid' THEN paid_amount ELSE 0 END) as paid_sum") ->whereBetween('created_at', [$trendStart, $trendEnd]) ->groupBy('d') ->orderBy('d') ->get(); $trendByDate = []; foreach ($trendRawRows as $r) { $trendByDate[(string) $r->d] = [ 'date' => (string) $r->d, 'count' => (int) ($r->cnt ?? 0), 'paid_sum' => (float) ($r->paid_sum ?? 0), ]; } $platformOrderTrend7d = []; for ($i = 0; $i < $trendDays; $i++) { $day = $trendStart->copy()->addDays($i)->format('Y-m-d'); $platformOrderTrend7d[] = $trendByDate[$day] ?? [ 'date' => $day, 'count' => 0, 'paid_sum' => 0.0, ]; } $recentPlatformOrders = PlatformOrder::query() ->orderByDesc('id') ->limit(5) ->get(); // 占比卡(最小可用):按套餐统计平台订单数量 TopN $planOrderShare = PlatformOrder::query() ->selectRaw('plan_id, COUNT(*) as cnt') ->whereNotNull('plan_id') ->groupBy('plan_id') ->orderByDesc('cnt') ->limit(5) ->get() ->map(function ($row) { return [ 'plan_id' => (int) $row->plan_id, 'count' => (int) $row->cnt, ]; }) ->values() ->all(); $planIdToName = Plan::query()->pluck('name', 'id')->all(); // 排行卡(最小可用):近 7 天站点收入排行 Top5(按已付金额) $merchantRevenueRank7d = PlatformOrder::query() ->selectRaw('merchant_id, COUNT(*) as cnt') ->selectRaw("SUM(CASE WHEN payment_status = 'paid' THEN paid_amount ELSE 0 END) as paid_sum") ->whereBetween('created_at', [$trendStart, $trendEnd]) ->groupBy('merchant_id') ->orderByDesc('paid_sum') ->limit(5) ->get() ->map(function ($row) { return [ 'merchant_id' => (int) ($row->merchant_id ?? 0), 'count' => (int) ($row->cnt ?? 0), 'paid_sum' => (float) ($row->paid_sum ?? 0), ]; }) ->values() ->all(); $merchantIdToName = Merchant::query()->pluck('name', 'id')->all(); return view('admin.dashboard', [ 'adminName' => $admin->name, 'stats' => $stats, 'platformOrderTrend7d' => $platformOrderTrend7d, 'recentPlatformOrders' => $recentPlatformOrders, 'planOrderShare' => $planOrderShare, 'planIdToName' => $planIdToName, 'merchantRevenueRank7d' => $merchantRevenueRank7d, 'merchantIdToName' => $merchantIdToName, 'platformAdmin' => $admin, 'cacheMeta' => [ 'store' => config('cache.default'), 'ttl' => '10m', ], 'platformOverview' => [ 'system_role' => '总台管理', 'current_scope' => '总台运营方视角', 'merchant_mode' => '统一管理多个站点', 'channel_count' => 5, 'active_merchants' => $stats['active_merchants'], 'pending_orders' => $stats['pending_orders'], ], ]); } }