| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158 |
- <?php
- namespace App\Http\Controllers\Admin;
- /*
- * DashboardController — главная страница административной панели.
- * Собирает метрики: заявки, посетители, состояние системы, последние события.
- */
- use App\Http\Controllers\Controller;
- use App\Models\Car;
- use App\Models\Lead;
- use App\Models\Review;
- use App\Models\Service;
- use Illuminate\Support\Carbon;
- use Illuminate\Support\Facades\Cache;
- use Illuminate\Support\Facades\DB;
- use Illuminate\View\View;
- class DashboardController extends Controller
- {
- public function index(): View
- {
- $today = now()->toDateString();
- $yesterday = now()->subDay()->toDateString();
- // ── Заявки ────────────────────────────────────────────────────────
- $leadsToday = Lead::whereDate('created_at', $today)->count();
- $leadsYesterday = Lead::whereDate('created_at', $yesterday)->count();
- $leadsTotal = Lead::count();
- $leadsUnread = Lead::whereNull('read_at')->count();
- // График заявок за 14 дней
- $leadsChart = $this->chartData(
- Lead::class,
- 'created_at',
- 14,
- 'Заявки'
- );
- // Последние 6 заявок
- $recentLeads = Lead::latest()->limit(6)->get();
- // ── Посетители ────────────────────────────────────────────────────
- $visitRow = DB::table('page_visits')->where('date', $today)->first();
- $visitYesterday = DB::table('page_visits')->where('date', $yesterday)->first();
- $visitsToday = $visitRow?->views ?? 0;
- $uniqueToday = $visitRow?->unique_ips ?? 0;
- // График посетителей за 14 дней
- $visitsChart = $this->visitsChartData(14);
- // ── Контент ───────────────────────────────────────────────────────
- $carsTotal = Car::count();
- $servicesTotal = Service::count();
- $reviewsTotal = Review::count();
- // ── Скорость / система ────────────────────────────────────────────
- $systemInfo = $this->systemInfo();
- // ── Средняя скорость ответа (самозамер) ───────────────────────────
- $responseTime = $this->measureSelfResponseTime();
- return view('admin.dashboard', compact(
- 'leadsToday', 'leadsYesterday', 'leadsTotal', 'leadsUnread',
- 'leadsChart', 'recentLeads',
- 'visitsToday', 'uniqueToday', 'visitYesterday',
- 'visitsChart',
- 'carsTotal', 'servicesTotal', 'reviewsTotal',
- 'systemInfo', 'responseTime'
- ));
- }
- // ── Приватные хелперы ─────────────────────────────────────────────────
- private function chartData(string $model, string $column, int $days, string $label): array
- {
- $start = now()->subDays($days - 1)->startOfDay();
- $rows = DB::table((new $model)->getTable())
- ->selectRaw("DATE($column) as d, COUNT(*) as cnt")
- ->where($column, '>=', $start)
- ->groupBy('d')
- ->pluck('cnt', 'd');
- $labels = [];
- $data = [];
- for ($i = $days - 1; $i >= 0; $i--) {
- $date = now()->subDays($i)->toDateString();
- $labels[] = now()->subDays($i)->format('d.m');
- $data[] = (int) ($rows[$date] ?? 0);
- }
- return compact('labels', 'data', 'label');
- }
- private function visitsChartData(int $days): array
- {
- $start = now()->subDays($days - 1)->toDateString();
- $rows = DB::table('page_visits')
- ->where('date', '>=', $start)
- ->orderBy('date')
- ->pluck('views', 'date');
- $labels = [];
- $data = [];
- for ($i = $days - 1; $i >= 0; $i--) {
- $date = now()->subDays($i)->toDateString();
- $labels[] = now()->subDays($i)->format('d.m');
- $data[] = (int) ($rows[$date] ?? 0);
- }
- return ['labels' => $labels, 'data' => $data, 'label' => 'Просмотры'];
- }
- private function systemInfo(): array
- {
- $cacheDriver = config('cache.default', 'file');
- $opcache = function_exists('opcache_get_status') ? opcache_get_status(false) : null;
- return [
- 'php' => PHP_VERSION,
- 'laravel' => app()->version(),
- 'cache_driver' => $cacheDriver,
- 'opcache' => $opcache && ($opcache['opcache_enabled'] ?? false),
- 'opcache_hits' => $opcache ? ($opcache['opcache_statistics']['hits'] ?? 0) : 0,
- 'opcache_misses'=> $opcache ? ($opcache['opcache_statistics']['misses'] ?? 0) : 0,
- 'disk_free' => $this->humanBytes(disk_free_space(base_path())),
- 'disk_total' => $this->humanBytes(disk_total_space(base_path())),
- 'disk_pct' => round((1 - disk_free_space(base_path()) / disk_total_space(base_path())) * 100),
- 'memory_limit' => ini_get('memory_limit'),
- 'max_upload' => ini_get('upload_max_filesize'),
- ];
- }
- private function measureSelfResponseTime(): ?int
- {
- // Берём время старта текущего запроса как proxy метрики
- if (defined('LARAVEL_START')) {
- return (int) ((microtime(true) - LARAVEL_START) * 1000);
- }
- return null;
- }
- private function humanBytes(float $bytes): string
- {
- foreach (['Б', 'КБ', 'МБ', 'ГБ', 'ТБ'] as $unit) {
- if ($bytes < 1024) {
- return round($bytes, 1) . ' ' . $unit;
- }
- $bytes /= 1024;
- }
- return round($bytes, 1) . ' ПБ';
- }
- }
|