Răsfoiți Sursa

Add 用户流量使用分析(半成品)

兔姬桑 4 ani în urmă
părinte
comite
83fb4aee13

+ 52 - 0
app/Http/Controllers/Admin/ReportController.php

@@ -4,6 +4,8 @@ namespace App\Http\Controllers\Admin;
 
 use App\Http\Controllers\Controller;
 use App\Models\Order;
+use App\Models\User;
+use Illuminate\Http\Request;
 
 class ReportController extends Controller
 {
@@ -54,4 +56,54 @@ class ReportController extends Controller
 
         return view('admin.report.accounting', compact('data'));
     }
+
+    public function userAnalysis(Request $request)
+    {
+        $uid = $request->input('uid');
+        $username = $request->input('username');
+        if ($uid) {
+            $user = User::find($uid);
+        } elseif ($username) {
+            $user = User::whereUsername($username)->first();
+        }
+
+        $data = null;
+        if (isset($user)) {
+            // 用户当前小时在各线路消耗流量
+            $data['currentHourlyFlow'] = $user->dataFlowLogs()
+                ->where('log_time', '>=', strtotime(date('Y-m-d H:00')))
+                ->groupBy('node_id')
+                ->selectRaw('node_id, sum(u + d) as total')
+                ->get()->toArray();
+
+            // 用户今天各小时在各线路消耗流量
+            $data['hours'] = range(0, 23);
+            $data['hourlyFlow'] = $user->hourlyDataFlows()->whereNotNull('node_id')
+                ->where('created_at', '>=', date('Y-m-d H:i:s', strtotime('-1 days')))
+                ->selectRaw('node_id, (DATE_FORMAT(user_hourly_data_flow.created_at, "%k")) as date, total')
+                ->get()->transform(function ($item, $key) {
+                    return [
+                        'node_id' => $item->node_id,
+                        'date'    => (int) $item->date,
+                        'total'   => round($item->total / GB, 2),
+                    ];
+                })->toArray();
+
+            // 用户本月每天在各线路消耗流量
+            $data['days'] = range(1, date('j'));
+            $data['dailyFlow'] = $user->dailyDataFlows()->whereNotNull('node_id')
+                ->whereMonth('created_at', date('n'))
+                ->where('total', '>', 6000000)
+                ->selectRaw('node_id, (DATE_FORMAT(user_daily_data_flow.created_at, "%e")) as date, total')
+                ->get()->transform(function ($item, $key) {
+                    return [
+                        'node_id' => $item->node_id,
+                        'date'    => (int) $item->date,
+                        'total'   => round($item->total / GB, 2),
+                    ];
+                })->toArray();
+        }
+
+        return view('admin.report.userDataAnalysis', compact('data'));
+    }
 }

+ 9 - 2
resources/views/admin/layouts.blade.php

@@ -333,7 +333,7 @@
                         </ul>
                     </li>
                 @endcanany
-                @canany(['admin.report.accounting'])
+                @canany(['admin.report.accounting', 'admin.report.userAnalysis'])
                     <li class="site-menu-item has-sub {{request()->routeIs('admin.report.*') ? 'active open' : ''}}">
                         <a href="javascript:void(0)">
                             <i class="site-menu-icon wb-stats-bars" aria-hidden="true"></i>
@@ -347,6 +347,13 @@
                                     </a>
                                 </li>
                             @endcan
+                            @can('admin.report.userAnalysis')
+                                <li class="site-menu-item {{request()->routeIs('admin.report.userAnalysis') ? 'active open' : ''}}">
+                                    <a href="{{route('admin.report.userAnalysis')}}">
+                                        <span class="site-menu-title">用户分析</span>
+                                    </a>
+                                </li>
+                            @endcan
                         </ul>
                     </li>
                 @endcanany
@@ -504,4 +511,4 @@
     <![endif]-->
     <script src="/assets/custom/sweetalert2/sweetalert2.all.min.js"></script>
     @yield('javascript')
-@endsection
+@endsection

+ 126 - 0
resources/views/admin/report/userDataAnalysis.blade.php

@@ -0,0 +1,126 @@
+@extends('admin.layouts')
+@section('content')
+    <div class="page-content container-fluid">
+        <div class="card card-shadow">
+            <div class="card-block p-30">
+                <form class="form-row">
+                    <div class="form-group col-xxl-1 col-lg-1 col-md-1 col-sm-4">
+                        <input type="number" class="form-control" name="uid" value="{{Request::query('uid')}}" placeholder="ID"/>
+                    </div>
+                    <div class="form-group col-xxl-2 col-lg-3 col-md-3 col-sm-4">
+                        <input type="text" class="form-control" name="username" value="{{Request::query('username')}}" placeholder="用户账号"/>
+                    </div>
+                    <div class="form-group col-xxl-1 col-lg-3 col-md-3 col-4 btn-group">
+                        <button type="submit" class="btn btn-primary">搜 索</button>
+                        <a href="{{route('admin.report.userAnalysis')}}" class="btn btn-danger">{{trans('common.reset')}}</a>
+                    </div>
+                </form>
+            </div>
+        </div>
+        @isset($data)
+            <div class="card card-shadow">
+                <div class="card-block p-30">
+                    <div class="row pb-20">
+                        <div class="col-md-8 col-sm-6">
+                            <div class="blue-grey-700 font-size-26 font-weight-500">每时流量</div>
+                        </div>
+                    </div>
+                    <canvas id="hourlyBar"></canvas>
+                    <canvas id="hourlyDoughnut"></canvas>
+                </div>
+            </div>
+            <div class="card card-shadow">
+                <div class="card-block p-30">
+                    <div class="row pb-20">
+                        <div class="col-md-8 col-sm-6">
+                            <div class="blue-grey-700 font-size-26 font-weight-500">每天流量</div>
+                        </div>
+                    </div>
+                    <canvas id="dailyBar"></canvas>
+                    <canvas id="dailyDoughnut"></canvas>
+                </div>
+            </div>
+        @endisset
+    </div>
+@endsection
+@section('javascript')
+    @isset($data)
+        <script src="/assets/global/vendor/chart-js/chart.min.js"></script>
+        <script type="text/javascript">
+            function label_callbacks(tail) {
+                return {
+                    mode: 'index',
+                    intersect: false,
+                    callbacks: {
+                        title: function(context) {
+                            return context[0].label + tail;
+                        },
+                        label: function(context) {
+                            let label = context.dataset.label || '';
+
+                            if (label) {
+                                label += ': ';
+                            }
+                            if (context.parsed.y !== null) {
+                                label += new Intl.NumberFormat('ch-CN', {style: 'currency', currency: 'CNY'}).format(context.parsed.y);
+                            }
+                            return label;
+                        },
+                    },
+                };
+            }
+
+            const common_options = {
+                stack:'node_id',
+                parsing: {
+                    xAxisKey: 'date',
+                    yAxisKey: 'total',
+                },
+                responsive: true,
+                plugins: {
+                    legend: {
+                        labels: {
+                            padding: 20,
+                            usePointStyle: true,
+                            pointStyle: 'circle',
+                            font: {size: 14},
+                        },
+                    },
+                    tooltip: label_callbacks(' 日'),
+                },
+            };
+
+            function area_a(label, data) {
+                return {
+                    label: label,
+                    backgroundColor: 'rgba(184, 215, 255)',
+                    borderColor: 'rgba(184, 215, 255)',
+                    data: data,
+                    fill: {
+                        target: 'origin',
+                        above: 'rgba(184, 215, 255, 0.5)',
+                    },
+                    tension: 0.4,
+                };
+            }
+
+            new Chart(document.getElementById('hourlyBar'), {
+                type: 'bar',
+                data: {
+                    labels: @json($data['hours']),
+                    datasets: [area_a(' 本 日 ',@json($data['hourlyFlow']))],
+                },
+                options: common_options,
+            });
+
+            new Chart(document.getElementById('dailyBar'), {
+                type: 'bar',
+                data: {
+                    labels: @json($data['days']),
+                    datasets: [area_a(' 本 月 ',@json($data['dailyFlow']))],
+                },
+                options: common_options,
+            });
+        </script>
+    @endisset
+@endsection

+ 3 - 0
routes/admin.php

@@ -68,9 +68,12 @@ Route::prefix('admin')->name('admin.')->group(function () {
         });
 
         Route::get('order', 'LogsController@orderList')->name('order'); // 订单列表
+
         Route::prefix('report')->name('report.')->group(function () {
             Route::get('accounting', 'ReportController@accounting')->name('accounting'); // 流水账簿
+            Route::get('user/analysis', 'ReportController@userAnalysis')->name('userAnalysis'); // 用户流量分析
         });
+
         Route::prefix('log')->name('log.')->group(function () {
             Route::get('traffic', 'LogsController@trafficLog')->name('traffic'); // 流量日志
             Route::get('userCredit', 'LogsController@userCreditLogList')->name('credit'); // 余额变动记录